241 lines
5.9 KiB
C
Executable File
241 lines
5.9 KiB
C
Executable File
#include "pmucal_local.h"
|
|
#include "pmucal_rae.h"
|
|
|
|
#ifndef PWRCAL_TARGET_LINUX
|
|
struct pmucal_pd *pmucal_blkpwr_list[PMUCAL_NUM_PDS];
|
|
#endif
|
|
|
|
/**
|
|
* pmucal_local_enable - enables a power domain.
|
|
* exposed to PWRCAL interface.
|
|
*
|
|
* @pd_id: power domain index.
|
|
*
|
|
* Returns 0 on success. Otherwise, negative error code.
|
|
*/
|
|
int pmucal_local_enable(unsigned int pd_id)
|
|
{
|
|
int ret;
|
|
|
|
dbg_snapshot_pmu(pd_id, __func__, DSS_FLAG_IN);
|
|
|
|
if (pd_id >= pmucal_pd_list_size) {
|
|
pr_err("%s pd index(%d) is out of supported range (0~%d).\n",
|
|
PMUCAL_PREFIX, pd_id, pmucal_pd_list_size);
|
|
return -EINVAL;
|
|
}
|
|
|
|
if (!pmucal_pd_list[pd_id].on) {
|
|
pr_err("%s there is no sequence element for pd(%d) power-on.\n",
|
|
PMUCAL_PREFIX, pd_id);
|
|
return -ENOENT;
|
|
}
|
|
|
|
ret = pmucal_rae_handle_seq(pmucal_pd_list[pd_id].on,
|
|
pmucal_pd_list[pd_id].num_on);
|
|
if (ret) {
|
|
pr_err("%s %s: error on handling enable sequence. (pd_id : %d)\n",
|
|
PMUCAL_PREFIX, __func__, pd_id);
|
|
return ret;
|
|
}
|
|
|
|
if (pmucal_pd_list[pd_id].need_smc) {
|
|
ret = exynos_pd_tz_restore(pmucal_pd_list[pd_id].need_smc);
|
|
if (ret) {
|
|
pr_err("%s %s: DTZPC restore smc error. (pd_id : %d)\n",
|
|
PMUCAL_PREFIX, __func__, pd_id);
|
|
return ret;
|
|
}
|
|
}
|
|
|
|
ret = pmucal_rae_restore_seq(pmucal_pd_list[pd_id].save,
|
|
pmucal_pd_list[pd_id].num_save);
|
|
if (ret) {
|
|
pr_err("%s %s: error on handling restore sequence. (pd_id : %d)\n",
|
|
PMUCAL_PREFIX, __func__, pd_id);
|
|
return ret;
|
|
}
|
|
|
|
dbg_snapshot_pmu(pd_id, __func__, DSS_FLAG_OUT);
|
|
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* pmucal_local_disable - disables a power domain.
|
|
* exposed to PWRCAL interface.
|
|
*
|
|
* @pd_id: power domain index.
|
|
*
|
|
* Returns 0 on success. Otherwise, negative error code.
|
|
*/
|
|
int pmucal_local_disable(unsigned int pd_id)
|
|
{
|
|
int ret, i;
|
|
|
|
dbg_snapshot_pmu(pd_id, __func__, DSS_FLAG_IN);
|
|
|
|
if (pd_id >= pmucal_pd_list_size) {
|
|
pr_err("%s pd index(%d) is out of supported range (0~%d).\n",
|
|
PMUCAL_PREFIX, pd_id, pmucal_pd_list_size);
|
|
return -EINVAL;
|
|
}
|
|
|
|
if (!pmucal_pd_list[pd_id].off) {
|
|
pr_err("%s there is no sequence element for pd(%d) power-off.\n",
|
|
PMUCAL_PREFIX, pd_id);
|
|
return -ENOENT;
|
|
}
|
|
|
|
pmucal_rae_save_seq(pmucal_pd_list[pd_id].save,
|
|
pmucal_pd_list[pd_id].num_save);
|
|
|
|
if (pmucal_pd_list[pd_id].need_smc) {
|
|
ret = exynos_pd_tz_save(pmucal_pd_list[pd_id].need_smc);
|
|
if (ret) {
|
|
pr_err("%s %s: DTZPC save smc error. (pd_id : %d)\n",
|
|
PMUCAL_PREFIX, __func__, pd_id);
|
|
return ret;
|
|
}
|
|
}
|
|
|
|
ret = pmucal_rae_handle_seq(pmucal_pd_list[pd_id].off,
|
|
pmucal_pd_list[pd_id].num_off);
|
|
if (ret) {
|
|
pr_err("%s %s: error on handling disable sequence. (pd_id : %d)\n",
|
|
PMUCAL_PREFIX, __func__, pd_id);
|
|
|
|
for (i = 0; i < pmucal_pd_list[pd_id].num_save; i++) {
|
|
pr_err("%s[0x%x] = 0x%x\n", pmucal_pd_list[pd_id].save[i].sfr_name,
|
|
pmucal_pd_list[pd_id].save[i].offset,
|
|
pmucal_pd_list[pd_id].save[i].value);
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
dbg_snapshot_pmu(pd_id, __func__, DSS_FLAG_OUT);
|
|
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* pmucal_local_is_enabled - checks whether a power domain is enabled or not.
|
|
* exposed to PWRCAL interface.
|
|
*
|
|
* @pd_id: power domain index.
|
|
*
|
|
* Returns 1 when the pd is enabled, 0 when disabled.
|
|
* Otherwise, negative error code.
|
|
*/
|
|
int pmucal_local_is_enabled(unsigned int pd_id)
|
|
{
|
|
int i;
|
|
|
|
dbg_snapshot_pmu(pd_id, __func__, DSS_FLAG_IN);
|
|
|
|
if (pd_id >= pmucal_pd_list_size) {
|
|
pr_err("%s pd index(%d) is out of supported range (0~%d).\n",
|
|
PMUCAL_PREFIX, pd_id, pmucal_pd_list_size);
|
|
return -EINVAL;
|
|
}
|
|
|
|
if (!pmucal_pd_list[pd_id].status) {
|
|
pr_err("%s there is no sequence element for pd(%d) status.\n",
|
|
PMUCAL_PREFIX, pd_id);
|
|
return -ENOENT;
|
|
}
|
|
|
|
pmucal_rae_handle_seq(pmucal_pd_list[pd_id].status,
|
|
pmucal_pd_list[pd_id].num_status);
|
|
|
|
for (i = 0; i < pmucal_pd_list[pd_id].num_status; i++) {
|
|
if (pmucal_pd_list[pd_id].status[i].value !=
|
|
pmucal_pd_list[pd_id].status[i].mask)
|
|
break;
|
|
}
|
|
|
|
dbg_snapshot_pmu(pd_id, __func__, DSS_FLAG_OUT);
|
|
|
|
if (i == pmucal_pd_list[pd_id].num_status)
|
|
return 1;
|
|
else
|
|
return 0;
|
|
}
|
|
|
|
void pmucal_local_set_smc_id(unsigned int pd_id, unsigned int need_smc)
|
|
{
|
|
if (need_smc) {
|
|
if (pd_id >= pmucal_pd_list_size) {
|
|
pr_err("%s pd index(%d) is out of supported range (0~%d).\n",
|
|
PMUCAL_PREFIX, pd_id, pmucal_pd_list_size);
|
|
return;
|
|
}
|
|
|
|
pmucal_pd_list[pd_id].need_smc = need_smc;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* pmucal_local_init - Init function of PMUCAL LOCAL common logic.
|
|
* exposed to PWRCAL interface.
|
|
*
|
|
* Returns 0 on success. Otherwise, negative error code.
|
|
*/
|
|
int __init pmucal_local_init(void)
|
|
{
|
|
int ret = 0, i;
|
|
|
|
if (!pmucal_pd_list_size) {
|
|
pr_err("%s %s: there is no pd list. aborting init...\n",
|
|
PMUCAL_PREFIX, __func__);
|
|
return -ENOENT;
|
|
}
|
|
|
|
/* convert physical base address to virtual addr */
|
|
for (i = 0; i < pmucal_pd_list_size; i++) {
|
|
/* skip non-existing pd */
|
|
if (!pmucal_pd_list[i].num_on && !pmucal_pd_list[i].num_off && !pmucal_pd_list[i].num_status)
|
|
continue;
|
|
|
|
ret = pmucal_rae_phy2virt(pmucal_pd_list[i].on,
|
|
pmucal_pd_list[i].num_on);
|
|
if (ret) {
|
|
pr_err("%s %s: error on PA2VA conversion. seq:on, pd_id:%d. aborting init...\n",
|
|
PMUCAL_PREFIX, __func__, i);
|
|
goto out;
|
|
}
|
|
|
|
ret = pmucal_rae_phy2virt(pmucal_pd_list[i].save,
|
|
pmucal_pd_list[i].num_save);
|
|
if (ret) {
|
|
pr_err("%s %s: error on PA2VA conversion. seq:save, pd_id:%d. aborting init...\n",
|
|
PMUCAL_PREFIX, __func__, i);
|
|
goto out;
|
|
}
|
|
|
|
ret = pmucal_rae_phy2virt(pmucal_pd_list[i].off,
|
|
pmucal_pd_list[i].num_off);
|
|
if (ret) {
|
|
pr_err("%s %s: error on PA2VA conversion. seq:off, pd_id:%d. aborting init...\n",
|
|
PMUCAL_PREFIX, __func__, i);
|
|
goto out;
|
|
}
|
|
|
|
ret = pmucal_rae_phy2virt(pmucal_pd_list[i].status,
|
|
pmucal_pd_list[i].num_status);
|
|
if (ret) {
|
|
pr_err("%s %s: error on PA2VA conversion. seq:status, pd_id:%d. aborting init...\n",
|
|
PMUCAL_PREFIX, __func__, i);
|
|
goto out;
|
|
}
|
|
|
|
#ifndef PWRCAL_TARGET_LINUX
|
|
pmucal_blkpwr_list[i] = pmucal_pd_list + i;
|
|
#endif
|
|
}
|
|
|
|
out:
|
|
return ret;
|
|
}
|