229 lines
6.0 KiB
C
Executable File
229 lines
6.0 KiB
C
Executable File
#include "pmucal_system.h"
|
|
#include "pmucal_rae.h"
|
|
#ifdef CONFIG_FLEXPMU
|
|
#include "pmucal_powermode.h"
|
|
|
|
unsigned int pmucal_sys_powermode[NUM_SYS_POWERDOWN] = {0xffffffff, };
|
|
#endif
|
|
|
|
/**
|
|
* pmucal_system_enter - prepares to enter a system power mode.
|
|
* exposed to PWRCAL interface.
|
|
*
|
|
* @mode: index of system power mode described in pmucal_system.h.
|
|
*
|
|
* Returns 0 on success. Otherwise, negative error code.
|
|
*/
|
|
int pmucal_system_enter(int mode)
|
|
{
|
|
int ret;
|
|
|
|
if (mode != SYS_SICD)
|
|
dbg_snapshot_pmu(mode, __func__, DSS_FLAG_IN);
|
|
|
|
if (mode >= NUM_SYS_POWERDOWN) {
|
|
pr_err("%s %s: mode index(%d) is out of supported range (0~%d).\n",
|
|
PMUCAL_PREFIX, __func__, mode, NUM_SYS_POWERDOWN);
|
|
return -EINVAL;
|
|
}
|
|
|
|
if (!pmucal_lpm_list[mode].enter) {
|
|
pr_err("%s %s: there is no sequence element for entering mode(%d).\n",
|
|
PMUCAL_PREFIX, __func__, mode);
|
|
return -ENOENT;
|
|
}
|
|
#ifdef CONFIG_FLEXPMU
|
|
pmucal_powermode_hint(pmucal_sys_powermode[mode]);
|
|
#endif
|
|
|
|
pmucal_rae_save_seq(pmucal_lpm_list[mode].save, pmucal_lpm_list[mode].num_save);
|
|
|
|
ret = pmucal_rae_handle_seq(pmucal_lpm_list[mode].enter,
|
|
pmucal_lpm_list[mode].num_enter);
|
|
if (ret) {
|
|
pr_err("%s %s: error on handling enter sequence. (mode : %d)\n",
|
|
PMUCAL_PREFIX, __func__, mode);
|
|
return ret;
|
|
}
|
|
|
|
if (mode != SYS_SICD)
|
|
dbg_snapshot_pmu(mode, __func__, DSS_FLAG_OUT);
|
|
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* pmucal_system_exit - prepares to exit a system power mode.
|
|
* exposed to PWRCAL interface.
|
|
*
|
|
* @mode: index of system power mode described in pmucal_system.h.
|
|
*
|
|
* Returns 0 on success. Otherwise, negative error code.
|
|
*/
|
|
int pmucal_system_exit(int mode)
|
|
{
|
|
int ret;
|
|
|
|
if (mode != SYS_SICD)
|
|
dbg_snapshot_pmu(mode, __func__, DSS_FLAG_IN);
|
|
|
|
if (mode >= NUM_SYS_POWERDOWN) {
|
|
pr_err("%s %s: mode index(%d) is out of supported range (0~%d).\n",
|
|
PMUCAL_PREFIX, __func__, mode, NUM_SYS_POWERDOWN);
|
|
return -EINVAL;
|
|
}
|
|
|
|
if (!pmucal_lpm_list[mode].exit) {
|
|
pr_err("%s %s: there is no sequence element for exiting mode(%d).\n",
|
|
PMUCAL_PREFIX, __func__, mode);
|
|
return -ENOENT;
|
|
}
|
|
|
|
ret = pmucal_rae_handle_seq(pmucal_lpm_list[mode].exit,
|
|
pmucal_lpm_list[mode].num_exit);
|
|
if (ret) {
|
|
pr_err("%s %s: error on handling exit sequence. (mode : %d)\n",
|
|
PMUCAL_PREFIX, __func__, mode);
|
|
return ret;
|
|
}
|
|
|
|
ret = pmucal_rae_restore_seq(pmucal_lpm_list[mode].save,
|
|
pmucal_lpm_list[mode].num_save);
|
|
if (ret) {
|
|
pr_err("%s %s: error on handling restore sequence. (mode : %d)\n",
|
|
PMUCAL_PREFIX, __func__, mode);
|
|
return ret;
|
|
}
|
|
|
|
if (mode != SYS_SICD)
|
|
dbg_snapshot_pmu(mode, __func__, DSS_FLAG_OUT);
|
|
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* pmucal_system_earlywakeup - prepares to early-wakeup from a system power mode.
|
|
* exposed to PWRCAL interface.
|
|
*
|
|
* @mode: index of system power mode described in pmucal_system.h.
|
|
*
|
|
* Returns 0 on success. Otherwise, negative error code.
|
|
*/
|
|
int pmucal_system_earlywakeup(int mode)
|
|
{
|
|
int ret;
|
|
|
|
if (mode != SYS_SICD)
|
|
dbg_snapshot_pmu(mode, __func__, DSS_FLAG_IN);
|
|
|
|
if (mode >= NUM_SYS_POWERDOWN) {
|
|
pr_err("%s %s: mode index(%d) is out of supported range (0~%d).\n",
|
|
PMUCAL_PREFIX, __func__, mode, NUM_SYS_POWERDOWN);
|
|
return -EINVAL;
|
|
}
|
|
|
|
if (!pmucal_lpm_list[mode].early_wakeup) {
|
|
pr_err("%s %s: there is no sequence element for early_wkup mode(%d).\n",
|
|
PMUCAL_PREFIX, __func__, mode);
|
|
return -ENOENT;
|
|
}
|
|
|
|
ret = pmucal_rae_handle_seq(pmucal_lpm_list[mode].early_wakeup,
|
|
pmucal_lpm_list[mode].num_early_wakeup);
|
|
if (ret) {
|
|
pr_err("%s %s: error on handling elry_wkup sequence. (mode : %d)\n",
|
|
PMUCAL_PREFIX, __func__, mode);
|
|
return ret;
|
|
}
|
|
|
|
ret = pmucal_rae_restore_seq(pmucal_lpm_list[mode].save,
|
|
pmucal_lpm_list[mode].num_save);
|
|
if (ret) {
|
|
pr_err("%s %s: error on handling restore sequence. (mode : %d)\n",
|
|
PMUCAL_PREFIX, __func__, mode);
|
|
return ret;
|
|
}
|
|
#ifdef CONFIG_FLEXPMU
|
|
pmucal_powermode_hint_clear();
|
|
#endif
|
|
|
|
if (mode != SYS_SICD)
|
|
dbg_snapshot_pmu(mode, __func__, DSS_FLAG_OUT);
|
|
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* pmucal_system_init - Init function of PMUCAL SYSTEM common logic.
|
|
* exposed to PWRCAL interface.
|
|
*
|
|
* Returns 0 on success. Otherwise, negative error code.
|
|
*/
|
|
int __init pmucal_system_init(void)
|
|
{
|
|
int ret = 0, i;
|
|
|
|
if (!pmucal_lpm_init_size || !pmucal_lpm_list_size) {
|
|
pr_err("%s %s: there is no lpm init seq or lpm list. aborting init...\n",
|
|
PMUCAL_PREFIX, __func__);
|
|
return -ENOENT;
|
|
}
|
|
|
|
/* convert physical base address to virtual addr */
|
|
for (i = 0; i < NUM_SYS_POWERDOWN; i++) {
|
|
/* skip non-existing power mode */
|
|
if (!pmucal_lpm_list[i].num_enter && !pmucal_lpm_list[i].num_exit && !pmucal_lpm_list[i].num_early_wakeup)
|
|
continue;
|
|
|
|
ret = pmucal_rae_phy2virt(pmucal_lpm_list[i].enter,
|
|
pmucal_lpm_list[i].num_enter);
|
|
if (ret) {
|
|
pr_err("%s %s: error on PA2VA conversion. seq:enter, mode_id:%d. aborting init...\n",
|
|
PMUCAL_PREFIX, __func__, i);
|
|
goto out;
|
|
}
|
|
|
|
ret = pmucal_rae_phy2virt(pmucal_lpm_list[i].save,
|
|
pmucal_lpm_list[i].num_save);
|
|
if (ret) {
|
|
pr_err("%s %s: error on PA2VA conversion. seq:save, mode_id:%d. aborting init...\n",
|
|
PMUCAL_PREFIX, __func__, i);
|
|
goto out;
|
|
}
|
|
|
|
ret = pmucal_rae_phy2virt(pmucal_lpm_list[i].exit,
|
|
pmucal_lpm_list[i].num_exit);
|
|
if (ret) {
|
|
pr_err("%s %s: error on PA2VA conversion. seq:exit, mode_id:%d. aborting init...\n",
|
|
PMUCAL_PREFIX, __func__, i);
|
|
goto out;
|
|
}
|
|
|
|
ret = pmucal_rae_phy2virt(pmucal_lpm_list[i].early_wakeup,
|
|
pmucal_lpm_list[i].num_early_wakeup);
|
|
if (ret) {
|
|
pr_err("%s %s: error on PA2VA conversion. seq:erlywkup, mode_id:%d. aborting init...\n",
|
|
PMUCAL_PREFIX, __func__, i);
|
|
goto out;
|
|
}
|
|
}
|
|
|
|
ret = pmucal_rae_phy2virt(pmucal_lpm_init, pmucal_lpm_init_size);
|
|
if (ret) {
|
|
pr_err("%s %s: error on PA2VA conversion for lpm_init seq. aborting init...\n",
|
|
PMUCAL_PREFIX, __func__);
|
|
goto out;
|
|
}
|
|
|
|
/* do default settings for PMU */
|
|
ret = pmucal_rae_handle_seq(pmucal_lpm_init, pmucal_lpm_init_size);
|
|
if (ret) {
|
|
pr_err("%s %s: error on handling lpm_init sequence.\n",
|
|
PMUCAL_PREFIX, __func__);
|
|
goto out;
|
|
}
|
|
|
|
out:
|
|
return ret;
|
|
}
|