mirror of
https://github.com/AetherDroid/android_kernel_samsung_on5xelte.git
synced 2025-10-30 15:48:52 +01:00
598 lines
22 KiB
C
598 lines
22 KiB
C
/*
|
|
* Copyright (c) 2015 Samsung Electronics Co., Ltd. All rights reserved.
|
|
* http://www.samsung.com
|
|
*
|
|
* Chip Abstraction Layer for System power down support
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License version 2 as
|
|
* published by the Free Software Foundation.
|
|
*/
|
|
|
|
#include "../pwrcal-env.h"
|
|
#include "../pwrcal.h"
|
|
#include "../pwrcal-pmu.h"
|
|
#include "../pwrcal-rae.h"
|
|
#include "S5E7570-cmusfr.h"
|
|
#include "S5E7570-pmusfr.h"
|
|
#include "S5E7570-cmu.h"
|
|
|
|
enum sys_powerdown {
|
|
SYS_SICD,
|
|
SYS_AFTR,
|
|
SYS_STOP,
|
|
SYS_LPD,
|
|
SYS_LPA,
|
|
SYS_DSTOP,
|
|
SYS_SLEEP,
|
|
NUM_SYS_POWERDOWN,
|
|
};
|
|
|
|
struct exynos_pmu_conf {
|
|
unsigned int *reg;
|
|
unsigned int val[NUM_SYS_POWERDOWN];
|
|
};
|
|
|
|
/* init_pmu_l2_option */
|
|
#define MANUAL_ACINACTM_VALUE (0x1 << 3)
|
|
#define MANUAL_ACINACTM_CONTROL (0x1 << 2)
|
|
#define MANUAL_AINACTS_VALUE (0x1 << 1)
|
|
#define MANUAL_AINACTS_CONTROL (0x1 << 0)
|
|
#define USE_AUTOMATIC_L2FLUSHREQ (0x1 << 17)
|
|
#define USE_STANDBYWFIL2 (0x1 << 16)
|
|
#define USE_RETENTION (0x1 << 4)
|
|
|
|
/* CPU option */
|
|
#define USE_SMPEN (0x1 << 28)
|
|
#define USE_STANDBYWFE (0x1 << 24)
|
|
#define USE_STANDBYWFI (0x1 << 16)
|
|
#define USE_IRQCPU_FOR_PWR (0x3 << 4)
|
|
#define USE_MEMPWRDOWN_FEEDBACK (0x1 << 3)
|
|
#define USE_MEMPWRDOWN_COUNTER (0x1 << 2)
|
|
#define USE_SC_FEEDBACK (0x1 << 1)
|
|
#define USE_SC_COUNTER (0x1 << 0)
|
|
#define DUR_WAIT_RESET (0xF << 20)
|
|
#define DUR_SCALL (0xF << 4)
|
|
#define DUR_SCALL_VALUE (0x1 << 4)
|
|
|
|
/* init_pmu_up_scheduler */
|
|
#define ENABLE_CPUCL0_CPU (0x1 << 0)
|
|
|
|
/* init_set_duration */
|
|
#define DUR_STABLE_MASK_AT_RESET 0xFFFFF
|
|
#define DUR_STABLE_MASK 0x3FF
|
|
#define TCXO_DUR_STABLE 0x140 /* 10ms in 32Khz */
|
|
#define EXTREG_SHARED_DUR_STABLE 0x140 /* 10ms in 32Khz */
|
|
#define EXTREG_SHARED_DUR_STABLE_AT_RESET 0x3F7A0 /* 10ms in 26Mhz */
|
|
|
|
/* init_pshold_setting_value*/
|
|
#define ENABLE_HW_TRIP (0x1 << 31)
|
|
#define PS_HOLD_OUTPUT_HIGH (0x3 << 8)
|
|
|
|
#define PAD_INITIATE_WAKEUP (0x1 << 28)
|
|
|
|
struct system_power_backup_reg {
|
|
void *reg;
|
|
unsigned int backup;
|
|
void *reg_stat;
|
|
unsigned int backup_stat;
|
|
void *pwr_stat_reg; /* if pwr_check true, this reg should be set */
|
|
unsigned int valid;
|
|
};
|
|
|
|
#define SYS_PWR_BACK_REG(_reg, _reg_stat, _pwr_stat_reg) \
|
|
{ \
|
|
.reg = _reg, \
|
|
.backup = 0, \
|
|
.reg_stat = _reg_stat, \
|
|
.backup_stat = 0, \
|
|
.pwr_stat_reg = _pwr_stat_reg, \
|
|
.valid = 0, \
|
|
}
|
|
|
|
static unsigned int *pmu_cpuoption_sfrlist[] = {
|
|
CPUCL0_CPU0_OPTION,
|
|
CPUCL0_CPU1_OPTION,
|
|
CPUCL0_CPU2_OPTION,
|
|
CPUCL0_CPU3_OPTION,
|
|
};
|
|
|
|
static void init_pmu_cpu_option(void)
|
|
{
|
|
int cpu;
|
|
unsigned int tmp;
|
|
|
|
/* use both sc_counter and sc_feedback */
|
|
/* enable to wait for low SMP-bit at sys power down */
|
|
for (cpu = 0; cpu < sizeof(pmu_cpuoption_sfrlist) / sizeof(pmu_cpuoption_sfrlist[0]); cpu++) {
|
|
tmp = pwrcal_readl(pmu_cpuoption_sfrlist[cpu]);
|
|
tmp |= USE_SC_FEEDBACK;
|
|
tmp |= USE_SMPEN;
|
|
tmp &= ~USE_SC_COUNTER;
|
|
tmp |= USE_STANDBYWFI;
|
|
tmp |= USE_MEMPWRDOWN_FEEDBACK;
|
|
tmp &= ~USE_STANDBYWFE;
|
|
pwrcal_writel(pmu_cpuoption_sfrlist[cpu], tmp);
|
|
}
|
|
}
|
|
|
|
static void set_pmu_enable_reset_lpi_timeout(void)
|
|
{
|
|
pwrcal_setbit(RESET_LPI_TIMEOUT, 0, 1);
|
|
}
|
|
|
|
static void init_pmu_apm_option(void)
|
|
{
|
|
pwrcal_setbit(CENTRAL_SEQ_APM_OPTION, 1, 1); /*USE STANDBYWFI*/
|
|
pwrcal_setbit(CORTEXM0_APM_OPTION, 16, 1); /*USE StandbyWFI*/
|
|
}
|
|
|
|
static void init_pmu_l2_option(void)
|
|
{
|
|
unsigned int tmp;
|
|
|
|
/* disable automatic L2 flush */
|
|
/* disable L2 retention */
|
|
|
|
tmp = pwrcal_readl(CPUCL0_L2_OPTION);
|
|
tmp &= ~(USE_AUTOMATIC_L2FLUSHREQ | USE_RETENTION);
|
|
tmp |= USE_STANDBYWFIL2;
|
|
pwrcal_writel(CPUCL0_L2_OPTION, tmp);
|
|
}
|
|
|
|
static void init_pmu_cpuseq_option(void)
|
|
{
|
|
}
|
|
|
|
static void init_pmu_up_scheduler(void)
|
|
{
|
|
unsigned int tmp;
|
|
|
|
/* limit in-rush current for CPUCL0/1 local power up */
|
|
tmp = pwrcal_readl(UP_SCHEDULER);
|
|
tmp |= ENABLE_CPUCL0_CPU;
|
|
pwrcal_writel(UP_SCHEDULER, tmp);
|
|
}
|
|
|
|
/* init_pmu_feedback */
|
|
static unsigned int *pmu_feedback_sfrlist[] = {
|
|
CPUCL0_NONCPU_OPTION,
|
|
TOP_PWR_OPTION,
|
|
TOP_PWR_MIF_OPTION,
|
|
DISPAUD_OPTION,
|
|
MFCMSCL_OPTION,
|
|
ISP_OPTION,
|
|
};
|
|
|
|
static void init_set_duration(void)
|
|
{
|
|
unsigned int tmp;
|
|
|
|
tmp = pwrcal_readl(TCXO_SHARED_DURATION3);
|
|
tmp &= ~DUR_STABLE_MASK;
|
|
tmp |= TCXO_DUR_STABLE;
|
|
pwrcal_writel(TCXO_SHARED_DURATION3, tmp);
|
|
|
|
tmp = pwrcal_readl(EXT_REGULATOR_SHARED_DURATION1);
|
|
tmp &= ~DUR_STABLE_MASK_AT_RESET;
|
|
tmp |= EXTREG_SHARED_DUR_STABLE_AT_RESET;
|
|
pwrcal_writel(EXT_REGULATOR_SHARED_DURATION1, tmp);
|
|
|
|
tmp = pwrcal_readl(EXT_REGULATOR_SHARED_DURATION3);
|
|
tmp &= ~DUR_STABLE_MASK;
|
|
tmp |= EXTREG_SHARED_DUR_STABLE;
|
|
pwrcal_writel(EXT_REGULATOR_SHARED_DURATION3, tmp);
|
|
}
|
|
|
|
static void init_pmu_feedback(void)
|
|
{
|
|
int i;
|
|
unsigned int tmp;
|
|
|
|
for (i = 0; i < sizeof(pmu_feedback_sfrlist) / sizeof(pmu_feedback_sfrlist[0]); i++) {
|
|
tmp = pwrcal_readl(pmu_feedback_sfrlist[i]);
|
|
tmp &= ~USE_SC_COUNTER;
|
|
tmp |= USE_SC_FEEDBACK;
|
|
pwrcal_writel(pmu_feedback_sfrlist[i], tmp);
|
|
}
|
|
}
|
|
static void init_ps_hold_setting(void)
|
|
{
|
|
unsigned int tmp;
|
|
|
|
tmp = pwrcal_readl(PS_HOLD_CONTROL);
|
|
tmp |= (ENABLE_HW_TRIP | PS_HOLD_OUTPUT_HIGH);
|
|
pwrcal_writel(PS_HOLD_CONTROL, tmp);
|
|
}
|
|
|
|
|
|
static void enable_armidleclockdown(void);
|
|
static void syspwr_init(void)
|
|
{
|
|
init_pmu_feedback();
|
|
init_pmu_l2_option();
|
|
init_pmu_cpu_option();
|
|
init_pmu_cpuseq_option();
|
|
init_pmu_up_scheduler();
|
|
init_ps_hold_setting();
|
|
init_set_duration();
|
|
init_pmu_apm_option();
|
|
set_pmu_enable_reset_lpi_timeout();
|
|
enable_armidleclockdown();
|
|
}
|
|
|
|
static struct exynos_pmu_conf exynos_syspwr_pmu_config[] = {
|
|
/* { .addr = address, .val = { SICD, AFTR, STOP, LPD, LPA, DSTOP, SLEEP } } */
|
|
{ CPUCL0_CPU0_SYS_PWR_REG, { 0xF, 0x0, 0xF, 0x0, 0x0, 0x0, 0x8} },
|
|
{ DIS_IRQ_CPUCL0_CPU0_LOCAL_SYS_PWR_REG, { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0} },
|
|
{ DIS_IRQ_CPUCL0_CPU0_CENTRAL_SYS_PWR_REG, { 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0} },
|
|
{ DIS_IRQ_CPUCL0_CPU0_CPUSEQUENCER_SYS_PWR_REG, { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0} },
|
|
{ CPUCL0_CPU1_SYS_PWR_REG, { 0xF, 0x0, 0xF, 0x0, 0x0, 0x0, 0x8} },
|
|
{ DIS_IRQ_CPUCL0_CPU1_LOCAL_SYS_PWR_REG, { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0} },
|
|
{ DIS_IRQ_CPUCL0_CPU1_CENTRAL_SYS_PWR_REG, { 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0} },
|
|
{ DIS_IRQ_CPUCL0_CPU1_CPUSEQUENCER_SYS_PWR_REG, { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0} },
|
|
{ CPUCL0_CPU2_SYS_PWR_REG, { 0xF, 0x0, 0xF, 0x0, 0x0, 0x0, 0x8} },
|
|
{ DIS_IRQ_CPUCL0_CPU2_LOCAL_SYS_PWR_REG, { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0} },
|
|
{ DIS_IRQ_CPUCL0_CPU2_CENTRAL_SYS_PWR_REG, { 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0} },
|
|
{ DIS_IRQ_CPUCL0_CPU2_CPUSEQUENCER_SYS_PWR_REG, { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0} },
|
|
{ CPUCL0_CPU3_SYS_PWR_REG, { 0xF, 0x0, 0xF, 0x0, 0x0, 0x0, 0x8} },
|
|
{ DIS_IRQ_CPUCL0_CPU3_LOCAL_SYS_PWR_REG, { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0} },
|
|
{ DIS_IRQ_CPUCL0_CPU3_CENTRAL_SYS_PWR_REG, { 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0} },
|
|
{ DIS_IRQ_CPUCL0_CPU3_CPUSEQUENCER_SYS_PWR_REG, { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0} },
|
|
{ CPUCL1_CPU0_SYS_PWR_REG, { 0xF, 0xF, 0xF, 0xF, 0xF, 0xF, 0xF} },
|
|
{ DIS_IRQ_CPUCL1_CPU0_LOCAL_SYS_PWR_REG, { 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1} },
|
|
{ DIS_IRQ_CPUCL1_CPU0_CENTRAL_SYS_PWR_REG, { 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1} },
|
|
{ DIS_IRQ_CPUCL1_CPU0_CPUSEQUENCER_SYS_PWR_REG, { 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1} },
|
|
{ CPUCL1_CPU1_SYS_PWR_REG, { 0xF, 0xF, 0xF, 0xF, 0xF, 0xF, 0xF} },
|
|
{ DIS_IRQ_CPUCL1_CPU1_LOCAL_SYS_PWR_REG, { 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1} },
|
|
{ DIS_IRQ_CPUCL1_CPU1_CENTRAL_SYS_PWR_REG, { 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1} },
|
|
{ DIS_IRQ_CPUCL1_CPU1_CPUSEQUENCER_SYS_PWR_REG, { 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1} },
|
|
{ CPUCL1_CPU2_SYS_PWR_REG, { 0xF, 0xF, 0xF, 0xF, 0xF, 0xF, 0xF} },
|
|
{ DIS_IRQ_CPUCL1_CPU2_LOCAL_SYS_PWR_REG, { 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1} },
|
|
{ DIS_IRQ_CPUCL1_CPU2_CENTRAL_SYS_PWR_REG, { 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1} },
|
|
{ DIS_IRQ_CPUCL1_CPU2_CPUSEQUENCER_SYS_PWR_REG, { 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1} },
|
|
{ CPUCL1_CPU3_SYS_PWR_REG, { 0xF, 0xF, 0xF, 0xF, 0xF, 0xF, 0xF} },
|
|
{ DIS_IRQ_CPUCL1_CPU3_LOCAL_SYS_PWR_REG, { 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1} },
|
|
{ DIS_IRQ_CPUCL1_CPU3_CENTRAL_SYS_PWR_REG, { 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1} },
|
|
{ DIS_IRQ_CPUCL1_CPU3_CPUSEQUENCER_SYS_PWR_REG, { 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1} },
|
|
{ CPUCL0_NONCPU_SYS_PWR_REG, { 0xF, 0x0, 0xF, 0x0, 0x0, 0x0, 0x8} },
|
|
{ CPUCL1_NONCPU_SYS_PWR_REG, { 0xF, 0xF, 0xF, 0xF, 0xF, 0xF, 0xF} },
|
|
{ CPUCL0_L2_SYS_PWR_REG, { 0x7, 0x0, 0x7, 0x0, 0x0, 0x0, 0x7} },
|
|
{ CPUCL1_L2_SYS_PWR_REG, { 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7} },
|
|
{ CLKSTOP_CMU_TOP_SYS_PWR_REG, { 0x1, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0} },
|
|
{ CLKRUN_CMU_TOP_SYS_PWR_REG, { 0x1, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0} },
|
|
{ RETENTION_CMU_TOP_SYS_PWR_REG, { 0x3, 0x3, 0x3, 0x0, 0x0, 0x0, 0x3} },
|
|
{ RESET_CMU_TOP_SYS_PWR_REG, { 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x0} },
|
|
{ RESET_CPUCLKSTOP_SYS_PWR_REG, { 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x0} },
|
|
{ CLKSTOP_CMU_MIF_SYS_PWR_REG, { 0x1, 0x1, 0x1, 0x1, 0x0, 0x0, 0x0} },
|
|
{ CLKRUN_CMU_MIF_SYS_PWR_REG, { 0x1, 0x1, 0x1, 0x1, 0x0, 0x0, 0x0} },
|
|
{ RETENTION_CMU_MIF_SYS_PWR_REG, { 0x3, 0x3, 0x3, 0x3, 0x0, 0x0, 0x3} },
|
|
{ RESET_CMU_MIF_SYS_PWR_REG, { 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x0} },
|
|
{ DDRPHY_CLKSTOP_SYS_PWR_REG, { 0x1, 0x1, 0x1, 0x1, 0x0, 0x0, 0x1} },
|
|
{ DDRPHY_ISO_SYS_PWR_REG, { 0x1, 0x1, 0x1, 0x1, 0x0, 0x0, 0x1} },
|
|
{ DDRPHY_DLL_CLK_SYS_PWR_REG, { 0x0, 0x1, 0x1, 0x1, 0x0, 0x0, 0x0} },
|
|
{ DISABLE_PLL_CMU_TOP_SYS_PWR_REG, { 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0} },
|
|
{ DISABLE_PLL_AUD_PLL_SYS_PWR_REG, { 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1} },
|
|
{ DISABLE_PLL_CMU_MIF_SYS_PWR_REG, { 0x0, 0x1, 0x0, 0x1, 0x0, 0x0, 0x0} },
|
|
{ DISABLE_PLL_APM_MIF_SYS_PWR_REG, { 0x1, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0} },
|
|
{ RESET_AHEAD_CP_SYS_PWR_REG, { 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3} },
|
|
{ RESET_AHEAD_GNSS_SYS_PWR_REG, { 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3} },
|
|
{ TOP_BUS_SYS_PWR_REG, { 0x7, 0x7, 0x7, 0x0, 0x0, 0x0, 0x0} },
|
|
{ TOP_RETENTION_SYS_PWR_REG, { 0x3, 0x3, 0x3, 0x0, 0x0, 0x0, 0x3} },
|
|
{ TOP_PWR_SYS_PWR_REG, { 0x3, 0x3, 0x3, 0x0, 0x0, 0x0, 0x3} },
|
|
{ TOP_BUS_MIF_SYS_PWR_REG, { 0x0, 0x7, 0x7, 0x7, 0x0, 0x0, 0x0} },
|
|
{ TOP_RETENTION_MIF_SYS_PWR_REG, { 0x3, 0x3, 0x3, 0x3, 0x0, 0x0, 0x3} },
|
|
{ TOP_PWR_MIF_SYS_PWR_REG, { 0x3, 0x3, 0x3, 0x3, 0x0, 0x0, 0x3} },
|
|
{ LOGIC_RESET_SYS_PWR_REG, { 0x3, 0x3, 0x3, 0x0, 0x0, 0x0, 0x0} },
|
|
{ OSCCLK_GATE_SYS_PWR_REG, { 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x1} },
|
|
{ SLEEP_RESET_SYS_PWR_REG, { 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x0} },
|
|
{ LOGIC_RESET_MIF_SYS_PWR_REG, { 0x3, 0x3, 0x3, 0x3, 0x0, 0x0, 0x0} },
|
|
{ OSCCLK_GATE_MIF_SYS_PWR_REG, { 0x1, 0x1, 0x0, 0x1, 0x0, 0x0, 0x1} },
|
|
{ SLEEP_RESET_MIF_SYS_PWR_REG, { 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x0} },
|
|
{ RESET_ASB_MIF_GNSS_SYS_PWR_REG, { 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3} },
|
|
{ MEMORY_TOP_SYS_PWR_REG, { 0x3, 0x3, 0x3, 0x0, 0x0, 0x0, 0x3} },
|
|
{ TCXO_GATE_GNSS_SYS_PWR_REG, { 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1} },
|
|
{ RESET_ASB_GNSS_SYS_PWR_REG, { 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3} },
|
|
{ CLEANY_BUS_CP_SYS_PWR_REG, { 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1} },
|
|
{ LOGIC_RESET_CP_SYS_PWR_REG, { 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3} },
|
|
{ TCXO_GATE_CP_SYS_PWR_REG, { 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1} },
|
|
{ RESET_ASB_CP_SYS_PWR_REG, { 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3} },
|
|
{ RESET_ASB_MIF_CP_SYS_PWR_REG, { 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3} },
|
|
{ MEMORY_MIF_ALIVEIRAM_SYS_PWR_REG, { 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3} },
|
|
{ MEMORY_MIF_TOP_SYS_PWR_REG, { 0x3, 0x3, 0x3, 0x3, 0x0, 0x0, 0x3} },
|
|
{ CLEANY_BUS_GNSS_SYS_PWR_REG, { 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1} },
|
|
{ LOGIC_RESET_GNSS_SYS_PWR_REG, { 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3} },
|
|
{ PAD_RETENTION_LPDDR3_SYS_PWR_REG, { 0x1, 0x1, 0x1, 0x1, 0x0, 0x0, 0x0} },
|
|
{ PAD_RETENTION_AUD_SYS_PWR_REG, { 0x1, 0x1, 0x1, 0x1, 0x0, 0x0, 0x0} },
|
|
{ PAD_RETENTION_PEDOMETER_TOP_SYS_PWR_REG, { 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1} },
|
|
{ PAD_RETENTION_MMC2_SYS_PWR_REG, { 0x1, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0} },
|
|
{ PAD_RETENTION_TOP_SYS_PWR_REG, { 0x1, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0} },
|
|
{ PAD_RETENTION_UART_SYS_PWR_REG, { 0x1, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0} },
|
|
{ PAD_RETENTION_MMC0_SYS_PWR_REG, { 0x1, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0} },
|
|
{ PAD_RETENTION_MMC1_SYS_PWR_REG, { 0x1, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0} },
|
|
{ PAD_RETENTION_SPI_SYS_PWR_REG, { 0x1, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0} },
|
|
{ PAD_RETENTION_MIF_SYS_PWR_REG, { 0x1, 0x1, 0x1, 0x1, 0x0, 0x0, 0x0} },
|
|
{ PAD_ISOLATION_SYS_PWR_REG, { 0x1, 0x1, 0x1, 0x0, 0x0, 0x0, 0x1} },
|
|
{ PAD_RETENTION_BOOTLDO_SYS_PWR_REG, { 0x1, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0} },
|
|
{ PAD_ISOLATION_MIF_SYS_PWR_REG, { 0x1, 0x1, 0x1, 0x1, 0x0, 0x0, 0x1} },
|
|
{ EXT_REGULATOR_MIF_SYS_PWR_REG, { 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x0} },
|
|
{ GPIO_MODE_SYS_PWR_REG, { 0x1, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0} },
|
|
{ GPIO_MODE_MIF_SYS_PWR_REG, { 0x1, 0x1, 0x1, 0x1, 0x0, 0x0, 0x0} },
|
|
{ GPIO_MODE_DISPAUD_SYS_PWR_REG, { 0x1, 0x1, 0x1, 0x1, 0x0, 0x0, 0x0} },
|
|
{ G3D_SYS_PWR_REG, { 0xF, 0xF, 0xF, 0x0, 0x0, 0x0, 0x0} },
|
|
{ DISPAUD_SYS_PWR_REG, { 0xF, 0xF, 0x0, 0xF, 0xF, 0x0, 0x0} },
|
|
{ ISP_SYS_PWR_REG, { 0xF, 0xF, 0xF, 0x0, 0x0, 0x0, 0x0} },
|
|
{ MFCMSCL_SYS_PWR_REG, { 0xF, 0xF, 0xF, 0x0, 0x0, 0x0, 0x0} },
|
|
{ CLKRUN_CMU_G3D_SYS_PWR_REG, { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0} },
|
|
{ CLKRUN_CMU_DISPAUD_SYS_PWR_REG, { 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0} },
|
|
{ CLKRUN_CMU_ISP_SYS_PWR_REG, { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0} },
|
|
{ CLKRUN_CMU_MFCMSCL_SYS_PWR_REG, { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0} },
|
|
{ CLKSTOP_CMU_G3D_SYS_PWR_REG, { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0} },
|
|
{ CLKSTOP_CMU_DISPAUD_SYS_PWR_REG, { 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0} },
|
|
{ CLKSTOP_CMU_ISP_SYS_PWR_REG, { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0} },
|
|
{ CLKSTOP_CMU_MFCMSCL_SYS_PWR_REG, { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0} },
|
|
{ DISABLE_PLL_CMU_G3D_SYS_PWR_REG, { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0} },
|
|
{ DISABLE_PLL_CMU_DISPAUD_SYS_PWR_REG, { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0} },
|
|
{ DISABLE_PLL_CMU_ISP_SYS_PWR_REG, { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0} },
|
|
{ DISABLE_PLL_CMU_MFCMSCL_SYS_PWR_REG, { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0} },
|
|
{ RESET_LOGIC_G3D_SYS_PWR_REG, { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0} },
|
|
{ RESET_LOGIC_DISPAUD_SYS_PWR_REG, { 0x0, 0x0, 0x3, 0x0, 0x0, 0x0, 0x0} },
|
|
{ RESET_LOGIC_ISP_SYS_PWR_REG, { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0} },
|
|
{ RESET_LOGIC_MFCMSCL_SYS_PWR_REG, { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0} },
|
|
{ MEMORY_G3D_SYS_PWR_REG, { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0} },
|
|
{ MEMORY_DISPAUD_SYS_PWR_REG, { 0x0, 0x0, 0x3, 0x0, 0x0, 0x0, 0x0} },
|
|
{ MEMORY_ISP_SYS_PWR_REG, { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0} },
|
|
{ MEMORY_MFCMSCL_SYS_PWR_REG, { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0} },
|
|
{ RESET_CMU_G3D_SYS_PWR_REG, { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0} },
|
|
{ RESET_CMU_DISPAUD_SYS_PWR_REG, { 0x0, 0x0, 0x3, 0x0, 0x0, 0x0, 0x0} },
|
|
{ RESET_CMU_ISP_SYS_PWR_REG, { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0} },
|
|
{ RESET_CMU_MFCMSCL_SYS_PWR_REG, { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0} },
|
|
|
|
{ RESET_AHEAD_WIFI_SYS_PWR_REG, { 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3} },
|
|
{ CLEANY_BUS_WIFI_SYS_PWR_REG, { 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1} },
|
|
{ LOGIC_RESET_WIFI_SYS_PWR_REG, { 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3} },
|
|
{ TCXO_GATE_WIFI_SYS_PWR_REG, { 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1} },
|
|
{ RESET_ASB_WIFI_SYS_PWR_REG, { 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3} },
|
|
{ RESET_ASB_MIF_WIFI_SYS_PWR_REG, { 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3} },
|
|
{ CORTEXM0_APM_SYS_PWR_REG, { 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1} },
|
|
{ CLKRUN_CMU_APM_SYS_PWR_REG, { 0x1, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0} },
|
|
{ TOP_BUS_APM_SYS_PWR_REG, { 0x7, 0x7, 0x7, 0x0, 0x0, 0x0, 0x0} },
|
|
{ CLKSTOP_CMU_APM_SYS_PWR_REG, { 0x1, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0} },
|
|
{ CLKSTOP_OPEN_CMU_APM_SYS_PWR_REG, { 0x1, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0} },
|
|
{ DISABLE_PLL_CMU_APM_SYS_PWR_REG, { 0x1, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0} },
|
|
{ TOP_RETENTION_APM_SYS_PWR_REG, { 0x3, 0x3, 0x3, 0x0, 0x0, 0x0, 0x0} },
|
|
{ OSCCLK_GATE_APM_SYS_PWR_REG, { 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0} },
|
|
{ MEMORY_APM_TOP_SYS_PWR_REG, { 0x3, 0x3, 0x3, 0x0, 0x0, 0x0, 0x0} },
|
|
{ LOGIC_RESET_APM_SYS_PWR_REG, { 0x3, 0x3, 0x3, 0x0, 0x0, 0x0, 0x0} },
|
|
{ SLEEP_RESET_APM_SYS_PWR_REG, { 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3} },
|
|
{ RETENTION_CMU_APM_SYS_PWR_REG, { 0x3, 0x3, 0x3, 0x0, 0x0, 0x0, 0x0} },
|
|
{ RESET_CMU_APM_SYS_PWR_REG, { 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3} },
|
|
{ TOP_PWR_APM_SYS_PWR_REG, { 0x3, 0x3, 0x3, 0x0, 0x0, 0x0, 0x0} },
|
|
{ TCXO_SYS_PWR_REG, { 0x1, 0x1, 0x0, 0x1, 0x1, 0x0, 0x0} },
|
|
{ PAD_RETENTION_PEDOMETER_APM_SYS_PWR_REG, { 0x1, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0} },
|
|
|
|
{ PAD_RETENTION_PEDOMETER_TOP_SYS_PWR_REG, { 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1} },
|
|
{ PAD_RETENTION_PEDOMETER_APM_SYS_PWR_REG, { 0x1, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0} },
|
|
|
|
{ 0, },
|
|
};
|
|
|
|
static struct exynos_pmu_conf exynos_syspwr_pmu_option[] = {
|
|
/* { .addr = address, .val = { SICD, AFTR, STOP, LPD, LPA, DSTOP, SLEEP } } */
|
|
{CENTRAL_SEQ_OPTION, {0x000F0000, 0x000F0000, 0x000F0000, 0x000F0000, 0x000F0000, 0x000F0000, 0x000F0000 } },
|
|
{CENTRAL_SEQ_OPTION1, {0x10000000, 0x10000000, 0x10000000, 0x10000000, 0x10000000, 0x10000000, 0x10000000 } },
|
|
{CENTRAL_SEQ_MIF_OPTION, {0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18 } },
|
|
{TOP_BUS_MIF_OPTION, {0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 } },
|
|
{0, },
|
|
};
|
|
|
|
static void set_pmu_sys_pwr_reg(enum sys_powerdown mode)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; exynos_syspwr_pmu_config[i].reg != 0; i++)
|
|
pwrcal_writel(exynos_syspwr_pmu_config[i].reg, exynos_syspwr_pmu_config[i].val[mode]);
|
|
|
|
for (i = 0; exynos_syspwr_pmu_option[i].reg != 0; i++)
|
|
pwrcal_writel(exynos_syspwr_pmu_option[i].reg, exynos_syspwr_pmu_option[i].val[mode]);
|
|
}
|
|
|
|
#define PWRCAL_CENTRALSEQ_PWR_CFG 0x10000
|
|
|
|
static void set_pmu_central_seq(int mode, bool enable)
|
|
{
|
|
unsigned int tmp;
|
|
|
|
/* central sequencer */
|
|
tmp = pwrcal_readl(CENTRAL_SEQ_CONFIGURATION);
|
|
if (enable)
|
|
tmp &= ~PWRCAL_CENTRALSEQ_PWR_CFG;
|
|
else
|
|
tmp |= PWRCAL_CENTRALSEQ_PWR_CFG;
|
|
pwrcal_writel(CENTRAL_SEQ_CONFIGURATION, tmp);
|
|
|
|
/* central sequencer MIF */
|
|
if (mode == SYS_SICD) {
|
|
tmp = pwrcal_readl(CENTRAL_SEQ_MIF_CONFIGURATION);
|
|
if (enable)
|
|
tmp &= ~PWRCAL_CENTRALSEQ_PWR_CFG;
|
|
else
|
|
tmp |= PWRCAL_CENTRALSEQ_PWR_CFG;
|
|
pwrcal_writel(CENTRAL_SEQ_MIF_CONFIGURATION, tmp);
|
|
}
|
|
}
|
|
|
|
static struct system_power_backup_reg backup_reg[] = {
|
|
};
|
|
|
|
static int syspwr_clkpwr_backup(unsigned int power_mode)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < sizeof(backup_reg) / sizeof(backup_reg[0]); i++) {
|
|
backup_reg[i].valid = 0;
|
|
if (backup_reg[i].pwr_stat_reg && pwrcal_getf(backup_reg[i].pwr_stat_reg, 0, 0xF) != 0xF)
|
|
continue;
|
|
|
|
if (backup_reg[i].reg) {
|
|
backup_reg[i].backup = pwrcal_readl(backup_reg[i].reg);
|
|
if (backup_reg[i].reg_stat)
|
|
backup_reg[i].backup_stat = pwrcal_readl(backup_reg[i].reg_stat);
|
|
backup_reg[i].valid = 1;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int syspwr_clkpwr_restore(unsigned int power_mode)
|
|
{
|
|
int i;
|
|
int timeout;
|
|
|
|
for (i = 0; i < sizeof(backup_reg) / sizeof(backup_reg[0]); i++) {
|
|
if (backup_reg[i].valid == 1) {
|
|
if (backup_reg[i].pwr_stat_reg && pwrcal_getf(backup_reg[i].pwr_stat_reg, 0, 0xF) != 0xF)
|
|
continue;
|
|
if (backup_reg[i].reg) {
|
|
pwrcal_writel(backup_reg[i].reg, backup_reg[i].backup);
|
|
|
|
if (backup_reg[i].reg_stat) {
|
|
for (timeout = 0; timeout < CLK_WAIT_CNT; timeout++) {
|
|
timeout = pwrcal_readl(backup_reg[i].reg_stat);
|
|
if (timeout == backup_reg[i].backup_stat)
|
|
break;
|
|
}
|
|
if (timeout == CLK_WAIT_CNT)
|
|
pr_warn("[%s] timeout wait for (0x%08X)\n",
|
|
__func__, backup_reg[i].backup_stat);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static void enable_armidleclockdown(void)
|
|
{
|
|
/*Use L2QACTIVE*/
|
|
pwrcal_setbit(PWR_CTRL3, 0, 1);
|
|
pwrcal_setbit(PWR_CTRL3, 1, 1);
|
|
}
|
|
|
|
inline void disable_armidleclockdown(void)
|
|
{
|
|
pwrcal_setbit(PWR_CTRL3, 0, 0);
|
|
}
|
|
|
|
static void syspwr_clock_config(int mode)
|
|
{
|
|
pwrcal_setbit(CLK_CON_MUX_CLKPHY_FSYS_USB20DRD_PHYCLOCK_USER, 12, 0);
|
|
pwrcal_setbit(CLK_CON_MUX_CLKPHY_FSYS_USB20DRD_PHYCLOCK_USER, 27, 1);
|
|
if (pwrcal_getf(ISP_STATUS, 0, 0xf) == 0xf) {
|
|
pwrcal_setbit(CLK_CON_MUX_CLKPHY_ISP_S_RXBYTECLKHS0_S4_USER, 12, 0);
|
|
pwrcal_setbit(CLK_CON_MUX_CLKPHY_ISP_S_RXBYTECLKHS0_S4_USER, 27, 1);
|
|
}
|
|
if ((pwrcal_getf(DISPAUD_STATUS, 0, 0xf) == 0xf) && (mode != SYS_LPD)) {
|
|
pwrcal_setbit(CLK_CON_MUX_CLKPHY_DISPAUD_MIPIPHY_TXBYTECLKHS_USER, 12, 0); /* MIPIDPHY */
|
|
pwrcal_setbit(CLK_CON_MUX_CLKPHY_DISPAUD_MIPIPHY_RXCLKESC0_USER, 12, 0); /* MIPIDPHY */
|
|
pwrcal_setbit(CLK_CON_MUX_CLKPHY_DISPAUD_MIPIPHY_TXBYTECLKHS_USER, 27, 1); /* MIPIDPHY */
|
|
pwrcal_setbit(CLK_CON_MUX_CLKPHY_DISPAUD_MIPIPHY_RXCLKESC0_USER, 27, 1); /* MIPIDPHY */
|
|
}
|
|
|
|
if (mode == SYS_LPD) {
|
|
/* PLL sharing is need to discuss, CP needs all PLL */
|
|
pwrcal_setbit(MIF_ROOTCLKEN, 0, 1);
|
|
pwrcal_setbit(CLK_ENABLE_CLKCMU_PERI_SPI_REARFROM, 0, 0);
|
|
pwrcal_setbit(CLK_ENABLE_CLKCMU_PERI_SPI_ESE, 0, 0);
|
|
pwrcal_setbit(CLK_ENABLE_CLKCMU_PERI_USI_0, 0, 0);
|
|
pwrcal_setbit(CLK_ENABLE_CLKCMU_PERI_USI_1, 0, 0);
|
|
}
|
|
/*LPI disable conditionally, when CP/GNSS/WIFI is disabled*/
|
|
}
|
|
|
|
static int syspwr_clkpwr_optimize(unsigned int power_mode)
|
|
{
|
|
disable_armidleclockdown();
|
|
|
|
return 0;
|
|
}
|
|
|
|
static void syspwr_set_additional_config(const enum sys_powerdown eMode)
|
|
{
|
|
/* USE_LEVEL_TRIGGER */
|
|
pwrcal_setf(WAKEUP_MASK, 30, 0x1, 0x1);
|
|
pwrcal_setf(WAKEUP_MASK_MIF, 30, 0x1, 0x1);
|
|
|
|
if (eMode == SYS_STOP) {
|
|
pwrcal_setf(DISPAUD_OPTION, 31, 0x1, 0x1);
|
|
pwrcal_setf(DISPAUD_OPTION, 21, 0x1, 0x1);
|
|
} else {
|
|
pwrcal_setf(DISPAUD_OPTION, 31, 0x1, 0x0);
|
|
pwrcal_setf(DISPAUD_OPTION, 21, 0x1, 0x0);
|
|
}
|
|
}
|
|
|
|
static void syspwr_prepare(int mode)
|
|
{
|
|
syspwr_clkpwr_backup(mode);
|
|
syspwr_clock_config(mode);
|
|
syspwr_clkpwr_optimize(mode);
|
|
|
|
set_pmu_sys_pwr_reg(mode);
|
|
syspwr_set_additional_config(mode);
|
|
set_pmu_central_seq(mode, true);
|
|
}
|
|
|
|
static void set_pmu_pad_retention_release(void)
|
|
{
|
|
pwrcal_writel(PAD_RETENTION_AUD_OPTION, PAD_INITIATE_WAKEUP);
|
|
pwrcal_writel(PAD_RETENTION_TOP_OPTION, PAD_INITIATE_WAKEUP);
|
|
pwrcal_writel(PAD_RETENTION_UART_OPTION, PAD_INITIATE_WAKEUP);
|
|
pwrcal_writel(PAD_RETENTION_MMC0_OPTION, PAD_INITIATE_WAKEUP);
|
|
pwrcal_writel(PAD_RETENTION_MMC2_OPTION, PAD_INITIATE_WAKEUP);
|
|
pwrcal_writel(PAD_RETENTION_SPI_OPTION, PAD_INITIATE_WAKEUP);
|
|
pwrcal_writel(PAD_RETENTION_BOOTLDO_OPTION, PAD_INITIATE_WAKEUP);
|
|
}
|
|
|
|
static void syspwr_post(int mode)
|
|
{
|
|
if (mode != SYS_SICD)
|
|
set_pmu_pad_retention_release();
|
|
|
|
switch (mode) {
|
|
case SYS_SICD:
|
|
case SYS_AFTR:
|
|
case SYS_DSTOP:
|
|
case SYS_STOP:
|
|
case SYS_LPD:
|
|
case SYS_LPA:
|
|
case SYS_SLEEP:
|
|
set_pmu_central_seq(mode, false);
|
|
break;
|
|
default:
|
|
return;
|
|
break;
|
|
}
|
|
|
|
enable_armidleclockdown();
|
|
|
|
syspwr_clkpwr_restore(mode);
|
|
}
|
|
|
|
static void syspwr_earlywakeup(int mode)
|
|
{
|
|
set_pmu_central_seq(mode, false);
|
|
|
|
enable_armidleclockdown();
|
|
|
|
syspwr_clkpwr_restore(mode);
|
|
}
|
|
|
|
struct cal_pm_ops cal_pm_ops = {
|
|
.pm_enter = syspwr_prepare,
|
|
.pm_exit = syspwr_post,
|
|
.pm_earlywakeup = syspwr_earlywakeup,
|
|
.pm_init = syspwr_init,
|
|
};
|