Merge pull request #1070 from rockchip-linux/rk3399-fixes-logic

rockchip/rk3399: Support Turning off VD_LOGIC during suspend-to-ram
This commit is contained in:
danh-arm 2017-08-29 11:52:04 +01:00 committed by GitHub
commit 6328f76b0c
12 changed files with 550 additions and 32 deletions

View File

@ -90,6 +90,8 @@ struct gpio_info *plat_get_rockchip_gpio_poweroff(void);
struct gpio_info *plat_get_rockchip_suspend_gpio(uint32_t *count);
struct apio_info *plat_get_rockchip_suspend_apio(void);
void plat_rockchip_gpio_init(void);
void plat_rockchip_save_gpio(void);
void plat_rockchip_restore_gpio(void);
int rockchip_soc_cores_pwr_dm_on(unsigned long mpidr, uint64_t entrypoint);
int rockchip_soc_hlvl_pwr_dm_off(uint32_t lvl,

View File

@ -45,7 +45,7 @@ sys_wakeup:
ddr_resume:
ldr x2, =__bl31_sram_stack_end
mov sp, x2
bl dmc_restore
bl dmc_resume
#endif
bl sram_restore
sys_resume:

View File

@ -25,10 +25,10 @@ struct rk3399_ddr_pctl_regs {
struct rk3399_ddr_publ_regs {
/*
* PHY registers from 0 to 511.
* Only registers 0-90 of each 128 register range are used.
* PHY registers from 0 to 90 for slice1.
* These are used to restore slice1-4 on resume.
*/
uint32_t phy0[4][91];
uint32_t phy0[91];
/*
* PHY registers from 512 to 895.
* Only registers 0-37 of each 128 register range are used.

View File

@ -43,6 +43,9 @@
#define SYS_COUNTER_FREQ_IN_MHZ (SYS_COUNTER_FREQ_IN_TICKS / 1000000)
__pmusramdata uint32_t dpll_data[PLL_CON_COUNT];
__pmusramdata uint32_t cru_clksel_con6;
/*
* Copy @num registers from @src to @dst
*/
@ -528,7 +531,7 @@ static __pmusramfunc void pctl_cfg(uint32_t ch,
for (i = 0; i < 4; i++)
sram_regcpy(PHY_REG(ch, 128 * i),
(uintptr_t)&phy_regs->phy0[i][0], 91);
(uintptr_t)&phy_regs->phy0[0], 91);
for (i = 0; i < 3; i++)
sram_regcpy(PHY_REG(ch, 512 + 128 * i),
@ -636,24 +639,45 @@ static __pmusramfunc int pctl_start(uint32_t channel_mask,
return 0;
}
void dmc_save(void)
__pmusramfunc static void pmusram_restore_pll(int pll_id, uint32_t *src)
{
mmio_write_32((CRU_BASE + CRU_PLL_CON(pll_id, 3)), PLL_SLOW_MODE);
mmio_write_32(CRU_BASE + CRU_PLL_CON(pll_id, 0), src[0] | REG_SOC_WMSK);
mmio_write_32(CRU_BASE + CRU_PLL_CON(pll_id, 1), src[1] | REG_SOC_WMSK);
mmio_write_32(CRU_BASE + CRU_PLL_CON(pll_id, 2), src[2]);
mmio_write_32(CRU_BASE + CRU_PLL_CON(pll_id, 4), src[4] | REG_SOC_WMSK);
mmio_write_32(CRU_BASE + CRU_PLL_CON(pll_id, 5), src[5] | REG_SOC_WMSK);
mmio_write_32(CRU_BASE + CRU_PLL_CON(pll_id, 3), src[3] | REG_SOC_WMSK);
while ((mmio_read_32(CRU_BASE + CRU_PLL_CON(pll_id, 2)) &
(1 << 31)) == 0x0)
;
}
void dmc_suspend(void)
{
struct rk3399_sdram_params *sdram_params = &sdram_config;
struct rk3399_ddr_publ_regs *phy_regs;
uint32_t *params_ctl;
uint32_t *params_pi;
uint32_t refdiv, postdiv2, postdiv1, fbdiv;
uint32_t tmp, ch, byte, i;
uint32_t ch, byte, i;
phy_regs = &sdram_params->phy_regs;
params_ctl = sdram_params->pctl_regs.denali_ctl;
params_pi = sdram_params->pi_regs.denali_pi;
fbdiv = mmio_read_32(CRU_BASE + CRU_PLL_CON(DPLL_ID, 0)) & 0xfff;
tmp = mmio_read_32(CRU_BASE + CRU_PLL_CON(DPLL_ID, 1));
postdiv2 = POSTDIV2_DEC(tmp);
postdiv1 = POSTDIV1_DEC(tmp);
refdiv = REFDIV_DEC(tmp);
/* save dpll register and ddr clock register value to pmusram */
cru_clksel_con6 = mmio_read_32(CRU_BASE + CRU_CLKSEL_CON6);
for (i = 0; i < PLL_CON_COUNT; i++)
dpll_data[i] = mmio_read_32(CRU_BASE + CRU_PLL_CON(DPLL_ID, i));
fbdiv = dpll_data[0] & 0xfff;
postdiv2 = POSTDIV2_DEC(dpll_data[1]);
postdiv1 = POSTDIV1_DEC(dpll_data[1]);
refdiv = REFDIV_DEC(dpll_data[1]);
sdram_params->ddr_freq = ((fbdiv * 24) /
(refdiv * postdiv1 * postdiv2)) * MHz;
@ -674,9 +698,8 @@ void dmc_save(void)
/* mask DENALI_PI_00_DATA.START, only copy here, will trigger later*/
params_pi[0] &= ~(0x1 << 0);
for (i = 0; i < 4; i++)
dram_regcpy((uintptr_t)&phy_regs->phy0[i][0],
PHY_REG(0, 128 * i), 91);
dram_regcpy((uintptr_t)&phy_regs->phy0[0],
PHY_REG(0, 0), 91);
for (i = 0; i < 3; i++)
dram_regcpy((uintptr_t)&phy_regs->phy512[i][0],
@ -697,12 +720,22 @@ void dmc_save(void)
phy_regs->phy896[0] &= ~(0x3 << 8);
}
__pmusramfunc void dmc_restore(void)
__pmusramfunc void dmc_resume(void)
{
struct rk3399_sdram_params *sdram_params = &sdram_config;
uint32_t channel_mask = 0;
uint32_t channel;
sram_secure_timer_init();
/*
* we switch ddr clock to abpll when suspend,
* we set back to dpll here
*/
mmio_write_32(CRU_BASE + CRU_CLKSEL_CON6,
cru_clksel_con6 | REG_SOC_WMSK);
pmusram_restore_pll(DPLL_ID, dpll_data);
configure_sgrf();
retry:

View File

@ -19,7 +19,7 @@
#define PI_WDQ_LEVELING (1 << 4)
#define PI_FULL_TRAINING (0xff)
void dmc_save(void);
__pmusramfunc void dmc_restore(void);
void dmc_suspend(void);
__pmusramfunc void dmc_resume(void);
#endif /* __DRAM_H__ */

View File

@ -22,10 +22,29 @@ uint32_t gpio_port[] = {
GPIO4_BASE,
};
struct {
uint32_t swporta_dr;
uint32_t swporta_ddr;
uint32_t inten;
uint32_t intmask;
uint32_t inttype_level;
uint32_t int_polarity;
uint32_t debounce;
uint32_t ls_sync;
} store_gpio[3];
static uint32_t store_grf_gpio[(GRF_GPIO2D_HE - GRF_GPIO2A_IOMUX) / 4 + 1];
#define SWPORTA_DR 0x00
#define SWPORTA_DDR 0x04
#define EXT_PORTA 0x50
#define INTEN 0x30
#define INTMASK 0x34
#define INTTYPE_LEVEL 0x38
#define INT_POLARITY 0x3c
#define DEBOUNCE 0x48
#define LS_SYNC 0x60
#define EXT_PORTA 0x50
#define PMU_GPIO_PORT0 0
#define PMU_GPIO_PORT1 1
#define GPIO_PORT2 2
@ -290,6 +309,99 @@ static void set_value(int gpio, int value)
gpio_put_clock(gpio, clock_state);
}
void plat_rockchip_save_gpio(void)
{
int i;
uint32_t cru_gate_save;
cru_gate_save = mmio_read_32(CRU_BASE + CRU_CLKGATE_CON(31));
/*
* when shutdown logic, we need to save gpio2 ~ gpio4 register,
* we need to enable gpio2 ~ gpio4 clock here, since it may be gating,
* and we do not care gpio0 and gpio1 clock gate, since we never
* gating them
*/
mmio_write_32(CRU_BASE + CRU_CLKGATE_CON(31),
BITS_WITH_WMASK(0, 0x07, PCLK_GPIO2_GATE_SHIFT));
/*
* since gpio0, gpio1 are pmugpio, they will keep ther value
* when shutdown logic power rail, so only need to save gpio2 ~ gpio4
* register value
*/
for (i = 2; i < 5; i++) {
store_gpio[i - 2].swporta_dr =
mmio_read_32(gpio_port[i] + SWPORTA_DR);
store_gpio[i - 2].swporta_ddr =
mmio_read_32(gpio_port[i] + SWPORTA_DDR);
store_gpio[i - 2].inten =
mmio_read_32(gpio_port[i] + INTEN);
store_gpio[i - 2].intmask =
mmio_read_32(gpio_port[i] + INTMASK);
store_gpio[i - 2].inttype_level =
mmio_read_32(gpio_port[i] + INTTYPE_LEVEL);
store_gpio[i - 2].int_polarity =
mmio_read_32(gpio_port[i] + INT_POLARITY);
store_gpio[i - 2].debounce =
mmio_read_32(gpio_port[i] + DEBOUNCE);
store_gpio[i - 2].ls_sync =
mmio_read_32(gpio_port[i] + LS_SYNC);
}
mmio_write_32(CRU_BASE + CRU_CLKGATE_CON(31),
cru_gate_save | REG_SOC_WMSK);
/*
* gpio0, gpio1 in pmuiomux, they will keep ther value
* when shutdown logic power rail, so only need to save gpio2 ~ gpio4
* iomux register value
*/
for (i = 0; i < ARRAY_SIZE(store_grf_gpio); i++)
store_grf_gpio[i] =
mmio_read_32(GRF_BASE + GRF_GPIO2A_IOMUX + i * 4);
}
void plat_rockchip_restore_gpio(void)
{
int i;
uint32_t cru_gate_save;
for (i = 0; i < ARRAY_SIZE(store_grf_gpio); i++)
mmio_write_32(GRF_BASE + GRF_GPIO2A_IOMUX + i * 4,
REG_SOC_WMSK | store_grf_gpio[i]);
cru_gate_save = mmio_read_32(CRU_BASE + CRU_CLKGATE_CON(31));
/*
* when shutdown logic, we need to save gpio2 ~ gpio4 register,
* we need to enable gpio2 ~ gpio4 clock here, since it may be gating,
* and we do not care gpio0 and gpio1 clock gate, since we never
* gating them
*/
mmio_write_32(CRU_BASE + CRU_CLKGATE_CON(31),
BITS_WITH_WMASK(0, 0x07, PCLK_GPIO2_GATE_SHIFT));
for (i = 2; i < 5; i++) {
mmio_write_32(gpio_port[i] + SWPORTA_DR,
store_gpio[i - 2].swporta_dr);
mmio_write_32(gpio_port[i] + SWPORTA_DDR,
store_gpio[i - 2].swporta_ddr);
mmio_write_32(gpio_port[i] + INTEN, store_gpio[i - 2].inten);
mmio_write_32(gpio_port[i] + INTMASK,
store_gpio[i - 2].intmask);
mmio_write_32(gpio_port[i] + INTTYPE_LEVEL,
store_gpio[i - 2].inttype_level);
mmio_write_32(gpio_port[i] + INT_POLARITY,
store_gpio[i - 2].int_polarity);
mmio_write_32(gpio_port[i] + DEBOUNCE,
store_gpio[i - 2].debounce);
mmio_write_32(gpio_port[i] + LS_SYNC,
store_gpio[i - 2].ls_sync);
}
mmio_write_32(CRU_BASE + CRU_CLKGATE_CON(31),
cru_gate_save | REG_SOC_WMSK);
}
const gpio_ops_t rk3399_gpio_ops = {
.get_direction = get_direction,
.set_direction = set_direction,

View File

@ -32,6 +32,19 @@ DEFINE_BAKERY_LOCK(rockchip_pd_lock);
static uint32_t cpu_warm_boot_addr;
static char store_sram[SRAM_BIN_LIMIT + SRAM_TEXT_LIMIT + SRAM_DATA_LIMIT];
static uint32_t store_cru[CRU_SDIO0_CON1 / 4];
static uint32_t store_usbphy0[7];
static uint32_t store_usbphy1[7];
static uint32_t store_grf_io_vsel;
static uint32_t store_grf_soc_con0;
static uint32_t store_grf_soc_con1;
static uint32_t store_grf_soc_con2;
static uint32_t store_grf_soc_con3;
static uint32_t store_grf_soc_con4;
static uint32_t store_grf_soc_con7;
static uint32_t store_grf_ddrc_con[4];
static uint32_t store_wdt0[2];
static uint32_t store_wdt1[2];
/*
* There are two ways to powering on or off on core.
@ -323,6 +336,11 @@ static void pmu_power_domains_suspend(void)
pmu_set_power_domain(PD_RGA, pmu_pd_off);
pmu_set_power_domain(PD_VCODEC, pmu_pd_off);
pmu_set_power_domain(PD_VDU, pmu_pd_off);
pmu_set_power_domain(PD_USB3, pmu_pd_off);
pmu_set_power_domain(PD_EMMC, pmu_pd_off);
pmu_set_power_domain(PD_VIO, pmu_pd_off);
pmu_set_power_domain(PD_SD, pmu_pd_off);
pmu_set_power_domain(PD_PERIHP, pmu_pd_off);
clk_gate_con_restore();
}
@ -358,6 +376,16 @@ static void pmu_power_domains_resume(void)
pmu_set_power_domain(PD_TCPD0, pmu_pd_on);
if (!(pmu_powerdomain_state & BIT(PD_GPU)))
pmu_set_power_domain(PD_GPU, pmu_pd_on);
if (!(pmu_powerdomain_state & BIT(PD_USB3)))
pmu_set_power_domain(PD_USB3, pmu_pd_on);
if (!(pmu_powerdomain_state & BIT(PD_EMMC)))
pmu_set_power_domain(PD_EMMC, pmu_pd_on);
if (!(pmu_powerdomain_state & BIT(PD_VIO)))
pmu_set_power_domain(PD_VIO, pmu_pd_on);
if (!(pmu_powerdomain_state & BIT(PD_SD)))
pmu_set_power_domain(PD_SD, pmu_pd_on);
if (!(pmu_powerdomain_state & BIT(PD_PERIHP)))
pmu_set_power_domain(PD_PERIHP, pmu_pd_on);
qos_restore();
clk_gate_con_restore();
}
@ -815,6 +843,7 @@ static void sys_slp_config(void)
BIT_WITH_WMSK(PMU_CLR_GIC2_CORE_L_HW));
slp_mode_cfg = BIT(PMU_PWR_MODE_EN) |
BIT(PMU_INPUT_CLAMP_EN) |
BIT(PMU_POWER_OFF_REQ_CFG) |
BIT(PMU_CPU0_PD_EN) |
BIT(PMU_L2_FLUSH_EN) |
@ -828,7 +857,9 @@ static void sys_slp_config(void)
BIT(PMU_DDRC0_GATING_EN) |
BIT(PMU_DDRC1_GATING_EN) |
BIT(PMU_DDRIO0_RET_EN) |
BIT(PMU_DDRIO0_RET_DE_REQ) |
BIT(PMU_DDRIO1_RET_EN) |
BIT(PMU_DDRIO1_RET_DE_REQ) |
BIT(PMU_DDRIO_RET_HW_DE_REQ) |
BIT(PMU_CENTER_PD_EN) |
BIT(PMU_PERILP_PD_EN) |
@ -1076,15 +1107,229 @@ void sram_restore(void)
incbin_size);
}
struct uart_debug {
uint32_t uart_dll;
uint32_t uart_dlh;
uint32_t uart_ier;
uint32_t uart_fcr;
uint32_t uart_mcr;
uint32_t uart_lcr;
};
#define UART_DLL 0x00
#define UART_DLH 0x04
#define UART_IER 0x04
#define UART_FCR 0x08
#define UART_LCR 0x0c
#define UART_MCR 0x10
#define UARTSRR 0x88
#define UART_RESET BIT(0)
#define UARTFCR_FIFOEN BIT(0)
#define RCVR_FIFO_RESET BIT(1)
#define XMIT_FIFO_RESET BIT(2)
#define DIAGNOSTIC_MODE BIT(4)
#define UARTLCR_DLAB BIT(7)
static struct uart_debug uart_save;
void suspend_uart(void)
{
uart_save.uart_lcr = mmio_read_32(PLAT_RK_UART_BASE + UART_LCR);
uart_save.uart_ier = mmio_read_32(PLAT_RK_UART_BASE + UART_IER);
uart_save.uart_mcr = mmio_read_32(PLAT_RK_UART_BASE + UART_MCR);
mmio_write_32(PLAT_RK_UART_BASE + UART_LCR,
uart_save.uart_lcr | UARTLCR_DLAB);
uart_save.uart_dll = mmio_read_32(PLAT_RK_UART_BASE + UART_DLL);
uart_save.uart_dlh = mmio_read_32(PLAT_RK_UART_BASE + UART_DLH);
mmio_write_32(PLAT_RK_UART_BASE + UART_LCR, uart_save.uart_lcr);
}
void resume_uart(void)
{
uint32_t uart_lcr;
mmio_write_32(PLAT_RK_UART_BASE + UARTSRR,
XMIT_FIFO_RESET | RCVR_FIFO_RESET | UART_RESET);
uart_lcr = mmio_read_32(PLAT_RK_UART_BASE + UART_LCR);
mmio_write_32(PLAT_RK_UART_BASE + UART_MCR, DIAGNOSTIC_MODE);
mmio_write_32(PLAT_RK_UART_BASE + UART_LCR, uart_lcr | UARTLCR_DLAB);
mmio_write_32(PLAT_RK_UART_BASE + UART_DLL, uart_save.uart_dll);
mmio_write_32(PLAT_RK_UART_BASE + UART_DLH, uart_save.uart_dlh);
mmio_write_32(PLAT_RK_UART_BASE + UART_LCR, uart_save.uart_lcr);
mmio_write_32(PLAT_RK_UART_BASE + UART_IER, uart_save.uart_ier);
mmio_write_32(PLAT_RK_UART_BASE + UART_FCR, UARTFCR_FIFOEN);
mmio_write_32(PLAT_RK_UART_BASE + UART_MCR, uart_save.uart_mcr);
}
void save_usbphy(void)
{
store_usbphy0[0] = mmio_read_32(GRF_BASE + GRF_USBPHY0_CTRL0);
store_usbphy0[1] = mmio_read_32(GRF_BASE + GRF_USBPHY0_CTRL2);
store_usbphy0[2] = mmio_read_32(GRF_BASE + GRF_USBPHY0_CTRL3);
store_usbphy0[3] = mmio_read_32(GRF_BASE + GRF_USBPHY0_CTRL12);
store_usbphy0[4] = mmio_read_32(GRF_BASE + GRF_USBPHY0_CTRL13);
store_usbphy0[5] = mmio_read_32(GRF_BASE + GRF_USBPHY0_CTRL15);
store_usbphy0[6] = mmio_read_32(GRF_BASE + GRF_USBPHY0_CTRL16);
store_usbphy1[0] = mmio_read_32(GRF_BASE + GRF_USBPHY1_CTRL0);
store_usbphy1[1] = mmio_read_32(GRF_BASE + GRF_USBPHY1_CTRL2);
store_usbphy1[2] = mmio_read_32(GRF_BASE + GRF_USBPHY1_CTRL3);
store_usbphy1[3] = mmio_read_32(GRF_BASE + GRF_USBPHY1_CTRL12);
store_usbphy1[4] = mmio_read_32(GRF_BASE + GRF_USBPHY1_CTRL13);
store_usbphy1[5] = mmio_read_32(GRF_BASE + GRF_USBPHY1_CTRL15);
store_usbphy1[6] = mmio_read_32(GRF_BASE + GRF_USBPHY1_CTRL16);
}
void restore_usbphy(void)
{
mmio_write_32(GRF_BASE + GRF_USBPHY0_CTRL0,
REG_SOC_WMSK | store_usbphy0[0]);
mmio_write_32(GRF_BASE + GRF_USBPHY0_CTRL2,
REG_SOC_WMSK | store_usbphy0[1]);
mmio_write_32(GRF_BASE + GRF_USBPHY0_CTRL3,
REG_SOC_WMSK | store_usbphy0[2]);
mmio_write_32(GRF_BASE + GRF_USBPHY0_CTRL12,
REG_SOC_WMSK | store_usbphy0[3]);
mmio_write_32(GRF_BASE + GRF_USBPHY0_CTRL13,
REG_SOC_WMSK | store_usbphy0[4]);
mmio_write_32(GRF_BASE + GRF_USBPHY0_CTRL15,
REG_SOC_WMSK | store_usbphy0[5]);
mmio_write_32(GRF_BASE + GRF_USBPHY0_CTRL16,
REG_SOC_WMSK | store_usbphy0[6]);
mmio_write_32(GRF_BASE + GRF_USBPHY1_CTRL0,
REG_SOC_WMSK | store_usbphy1[0]);
mmio_write_32(GRF_BASE + GRF_USBPHY1_CTRL2,
REG_SOC_WMSK | store_usbphy1[1]);
mmio_write_32(GRF_BASE + GRF_USBPHY1_CTRL3,
REG_SOC_WMSK | store_usbphy1[2]);
mmio_write_32(GRF_BASE + GRF_USBPHY1_CTRL12,
REG_SOC_WMSK | store_usbphy1[3]);
mmio_write_32(GRF_BASE + GRF_USBPHY1_CTRL13,
REG_SOC_WMSK | store_usbphy1[4]);
mmio_write_32(GRF_BASE + GRF_USBPHY1_CTRL15,
REG_SOC_WMSK | store_usbphy1[5]);
mmio_write_32(GRF_BASE + GRF_USBPHY1_CTRL16,
REG_SOC_WMSK | store_usbphy1[6]);
}
void grf_register_save(void)
{
int i;
store_grf_soc_con0 = mmio_read_32(GRF_BASE + GRF_SOC_CON(0));
store_grf_soc_con1 = mmio_read_32(GRF_BASE + GRF_SOC_CON(1));
store_grf_soc_con2 = mmio_read_32(GRF_BASE + GRF_SOC_CON(2));
store_grf_soc_con3 = mmio_read_32(GRF_BASE + GRF_SOC_CON(3));
store_grf_soc_con4 = mmio_read_32(GRF_BASE + GRF_SOC_CON(4));
store_grf_soc_con7 = mmio_read_32(GRF_BASE + GRF_SOC_CON(7));
for (i = 0; i < 4; i++)
store_grf_ddrc_con[i] =
mmio_read_32(GRF_BASE + GRF_DDRC0_CON0 + i * 4);
store_grf_io_vsel = mmio_read_32(GRF_BASE + GRF_IO_VSEL);
}
void grf_register_restore(void)
{
int i;
mmio_write_32(GRF_BASE + GRF_SOC_CON(0),
REG_SOC_WMSK | store_grf_soc_con0);
mmio_write_32(GRF_BASE + GRF_SOC_CON(1),
REG_SOC_WMSK | store_grf_soc_con1);
mmio_write_32(GRF_BASE + GRF_SOC_CON(2),
REG_SOC_WMSK | store_grf_soc_con2);
mmio_write_32(GRF_BASE + GRF_SOC_CON(3),
REG_SOC_WMSK | store_grf_soc_con3);
mmio_write_32(GRF_BASE + GRF_SOC_CON(4),
REG_SOC_WMSK | store_grf_soc_con4);
mmio_write_32(GRF_BASE + GRF_SOC_CON(7),
REG_SOC_WMSK | store_grf_soc_con7);
for (i = 0; i < 4; i++)
mmio_write_32(GRF_BASE + GRF_DDRC0_CON0 + i * 4,
REG_SOC_WMSK | store_grf_ddrc_con[i]);
mmio_write_32(GRF_BASE + GRF_IO_VSEL, REG_SOC_WMSK | store_grf_io_vsel);
}
void cru_register_save(void)
{
int i;
for (i = 0; i <= CRU_SDIO0_CON1; i = i + 4)
store_cru[i / 4] = mmio_read_32(CRU_BASE + i);
}
void cru_register_restore(void)
{
int i;
for (i = 0; i <= CRU_SDIO0_CON1; i = i + 4) {
/*
* since DPLL, CRU_CLKSEL_CON6 have been restore in
* dmc_resume, ABPLL will resote later, so skip them
*/
if ((i == CRU_CLKSEL_CON6) ||
(i >= CRU_PLL_CON(ABPLL_ID, 0) &&
i <= CRU_PLL_CON(DPLL_ID, 5)))
continue;
if ((i == CRU_PLL_CON(ALPLL_ID, 2)) ||
(i == CRU_PLL_CON(CPLL_ID, 2)) ||
(i == CRU_PLL_CON(GPLL_ID, 2)) ||
(i == CRU_PLL_CON(NPLL_ID, 2)) ||
(i == CRU_PLL_CON(VPLL_ID, 2)))
mmio_write_32(CRU_BASE + i, store_cru[i / 4]);
/*
* CRU_GLB_CNT_TH and CRU_CLKSEL_CON97~CRU_CLKSEL_CON107
* not need do high 16bit mask
*/
else if ((i > 0x27c && i < 0x2b0) || (i == 0x508))
mmio_write_32(CRU_BASE + i, store_cru[i / 4]);
else
mmio_write_32(CRU_BASE + i,
REG_SOC_WMSK | store_cru[i / 4]);
}
}
void wdt_register_save(void)
{
int i;
for (i = 0; i < 2; i++) {
store_wdt0[i] = mmio_read_32(WDT0_BASE + i * 4);
store_wdt1[i] = mmio_read_32(WDT1_BASE + i * 4);
}
}
void wdt_register_restore(void)
{
int i;
for (i = 0; i < 2; i++) {
mmio_write_32(WDT0_BASE + i * 4, store_wdt0[i]);
mmio_write_32(WDT1_BASE + i * 4, store_wdt1[i]);
}
}
int rockchip_soc_sys_pwr_dm_suspend(void)
{
uint32_t wait_cnt = 0;
uint32_t status = 0;
ddr_prepare_for_sys_suspend();
dmc_save();
dmc_suspend();
pmu_scu_b_pwrdn();
/* need to save usbphy before shutdown PERIHP PD */
save_usbphy();
pmu_power_domains_suspend();
set_hw_idle(BIT(PMU_CLR_CENTER1) |
BIT(PMU_CLR_ALIVE) |
@ -1096,7 +1341,7 @@ int rockchip_soc_sys_pwr_dm_suspend(void)
BIT(PMU_CLR_PERILP) |
BIT(PMU_CLR_PERILPM0) |
BIT(PMU_CLR_GIC));
set_pmu_rsthold();
sys_slp_config();
m0_configure_suspend();
@ -1139,8 +1384,13 @@ int rockchip_soc_sys_pwr_dm_suspend(void)
suspend_apio();
suspend_gpio();
suspend_uart();
grf_register_save();
cru_register_save();
wdt_register_save();
sram_save();
plat_rockchip_save_gpio();
return 0;
}
@ -1149,6 +1399,11 @@ int rockchip_soc_sys_pwr_dm_resume(void)
uint32_t wait_cnt = 0;
uint32_t status = 0;
plat_rockchip_restore_gpio();
wdt_register_restore();
cru_register_restore();
grf_register_restore();
resume_uart();
resume_apio();
resume_gpio();
enable_nodvfs_plls();
@ -1158,6 +1413,8 @@ int rockchip_soc_sys_pwr_dm_resume(void)
enable_dvfs_plls();
secure_watchdog_enable();
secure_sgrf_init();
secure_sgrf_ddr_rgn_init();
/* restore clk_ddrc_bpll_src_en gate */
mmio_write_32(CRU_BASE + CRU_CLKGATE_CON(3),
@ -1211,10 +1468,8 @@ int rockchip_soc_sys_pwr_dm_resume(void)
pmu_scu_b_pwrup();
pmu_power_domains_resume();
restore_dpll();
sram_func_set_ddrctl_pll(DPLL_ID);
restore_abpll();
restore_pmu_rsthold();
clr_hw_idle(BIT(PMU_CLR_CENTER1) |
BIT(PMU_CLR_ALIVE) |
BIT(PMU_CLR_MSCH0) |
@ -1229,6 +1484,8 @@ int rockchip_soc_sys_pwr_dm_resume(void)
plat_rockchip_gic_cpuif_enable();
m0_stop();
restore_usbphy();
ddr_prepare_for_sys_resume();
return 0;

View File

@ -101,6 +101,19 @@ void secure_watchdog_enable(void)
WMSK_BIT(PCLK_WDT_CM0_GATE_SHIFT));
}
__pmusramfunc void sram_secure_timer_init(void)
{
mmio_write_32(STIMER1_CHN_BASE(5) + TIMER_END_COUNT0, 0xffffffff);
mmio_write_32(STIMER1_CHN_BASE(5) + TIMER_END_COUNT1, 0xffffffff);
mmio_write_32(STIMER1_CHN_BASE(5) + TIMER_INIT_COUNT0, 0x0);
mmio_write_32(STIMER1_CHN_BASE(5) + TIMER_INIT_COUNT0, 0x0);
/* auto reload & enable the timer */
mmio_write_32(STIMER1_CHN_BASE(5) + TIMER_CONTROL_REG,
TIMER_EN | TIMER_FMODE);
}
void secure_timer_init(void)
{
mmio_write_32(STIMER1_CHN_BASE(5) + TIMER_END_COUNT0, 0xffffffff);

View File

@ -100,5 +100,6 @@ void secure_watchdog_enable(void);
void secure_timer_init(void);
void secure_sgrf_init(void);
void secure_sgrf_ddr_rgn_init(void);
__pmusramfunc void sram_secure_timer_init(void);
#endif /* __PLAT_ROCKCHIP_RK3399_DRIVER_SECURE_H__ */

View File

@ -171,11 +171,6 @@ void restore_abpll(void)
restore_pll(ABPLL_ID, slp_data.plls_con[ABPLL_ID]);
}
void restore_dpll(void)
{
restore_pll(DPLL_ID, slp_data.plls_con[DPLL_ID]);
}
void clk_gate_con_save(void)
{
uint32_t i = 0;
@ -229,6 +224,47 @@ static void _pll_resume(uint32_t pll_id)
set_pll_normal_mode(pll_id);
}
void set_pmu_rsthold(void)
{
uint32_t rstnhold_cofig0;
uint32_t rstnhold_cofig1;
slp_data.pmucru_rstnhold_con0 = mmio_read_32(PMUCRU_BASE +
PMUCRU_RSTNHOLD_CON0);
slp_data.pmucru_rstnhold_con1 = mmio_read_32(PMUCRU_BASE +
PMUCRU_RSTNHOLD_CON1);
rstnhold_cofig0 = BIT_WITH_WMSK(PRESETN_NOC_PMU_HOLD) |
BIT_WITH_WMSK(PRESETN_INTMEM_PMU_HOLD) |
BIT_WITH_WMSK(HRESETN_CM0S_PMU_HOLD) |
BIT_WITH_WMSK(HRESETN_CM0S_NOC_PMU_HOLD) |
BIT_WITH_WMSK(DRESETN_CM0S_PMU_HOLD) |
BIT_WITH_WMSK(POESETN_CM0S_PMU_HOLD) |
BIT_WITH_WMSK(PRESETN_TIMER_PMU_0_1_HOLD) |
BIT_WITH_WMSK(RESETN_TIMER_PMU_0_HOLD) |
BIT_WITH_WMSK(RESETN_TIMER_PMU_1_HOLD) |
BIT_WITH_WMSK(PRESETN_UART_M0_PMU_HOLD) |
BIT_WITH_WMSK(RESETN_UART_M0_PMU_HOLD) |
BIT_WITH_WMSK(PRESETN_WDT_PMU_HOLD);
rstnhold_cofig1 = BIT_WITH_WMSK(PRESETN_RKPWM_PMU_HOLD) |
BIT_WITH_WMSK(PRESETN_PMUGRF_HOLD) |
BIT_WITH_WMSK(PRESETN_SGRF_HOLD) |
BIT_WITH_WMSK(PRESETN_GPIO0_HOLD) |
BIT_WITH_WMSK(PRESETN_GPIO1_HOLD) |
BIT_WITH_WMSK(PRESETN_CRU_PMU_HOLD) |
BIT_WITH_WMSK(PRESETN_PVTM_PMU_HOLD);
mmio_write_32(PMUCRU_BASE + PMUCRU_RSTNHOLD_CON0, rstnhold_cofig0);
mmio_write_32(PMUCRU_BASE + PMUCRU_RSTNHOLD_CON1, rstnhold_cofig1);
}
void restore_pmu_rsthold(void)
{
mmio_write_32(PMUCRU_BASE + PMUCRU_RSTNHOLD_CON0,
slp_data.pmucru_rstnhold_con0 | REG_SOC_WMSK);
mmio_write_32(PMUCRU_BASE + PMUCRU_RSTNHOLD_CON1,
slp_data.pmucru_rstnhold_con1 | REG_SOC_WMSK);
}
/**
* enable_dvfs_plls - To resume the specific PLLs
*

View File

@ -56,6 +56,43 @@
#define PMUCRU_GATE_CON(n) (0x100 + (n) * 4)
#define CRU_GATE_CON(n) (0x300 + (n) * 4)
#define PMUCRU_RSTNHOLD_CON0 0x120
enum {
PRESETN_NOC_PMU_HOLD = 1,
PRESETN_INTMEM_PMU_HOLD,
HRESETN_CM0S_PMU_HOLD,
HRESETN_CM0S_NOC_PMU_HOLD,
DRESETN_CM0S_PMU_HOLD,
POESETN_CM0S_PMU_HOLD,
PRESETN_SPI3_HOLD,
RESETN_SPI3_HOLD,
PRESETN_TIMER_PMU_0_1_HOLD,
RESETN_TIMER_PMU_0_HOLD,
RESETN_TIMER_PMU_1_HOLD,
PRESETN_UART_M0_PMU_HOLD,
RESETN_UART_M0_PMU_HOLD,
PRESETN_WDT_PMU_HOLD
};
#define PMUCRU_RSTNHOLD_CON1 0x124
enum {
PRESETN_I2C0_HOLD,
PRESETN_I2C4_HOLD,
PRESETN_I2C8_HOLD,
PRESETN_MAILBOX_PMU_HOLD,
PRESETN_RKPWM_PMU_HOLD,
PRESETN_PMUGRF_HOLD,
PRESETN_SGRF_HOLD,
PRESETN_GPIO0_HOLD,
PRESETN_GPIO1_HOLD,
PRESETN_CRU_PMU_HOLD,
PRESETN_INTR_ARB_HOLD,
PRESETN_PVTM_PMU_HOLD,
RESETN_I2C0_HOLD,
RESETN_I2C4_HOLD,
RESETN_I2C8_HOLD
};
enum plls_id {
ALPLL_ID = 0,
ABPLL_ID,
@ -97,6 +134,8 @@ struct deepsleep_data_s {
uint32_t plls_con[END_PLL_ID][PLL_CON_COUNT];
uint32_t cru_gate_con[CRU_GATE_COUNT];
uint32_t pmucru_gate_con[PMUCRU_GATE_COUNT];
uint32_t pmucru_rstnhold_con0;
uint32_t pmucru_rstnhold_con1;
};
/**************************************************
@ -189,13 +228,35 @@ struct deepsleep_data_s {
#define PWM_ENABLE (1 << 0)
/* grf reg offset */
#define GRF_USBPHY0_CTRL0 0x4480
#define GRF_USBPHY0_CTRL2 0x4488
#define GRF_USBPHY0_CTRL3 0x448c
#define GRF_USBPHY0_CTRL12 0x44b0
#define GRF_USBPHY0_CTRL13 0x44b4
#define GRF_USBPHY0_CTRL15 0x44bc
#define GRF_USBPHY0_CTRL16 0x44c0
#define GRF_USBPHY1_CTRL0 0x4500
#define GRF_USBPHY1_CTRL2 0x4508
#define GRF_USBPHY1_CTRL3 0x450c
#define GRF_USBPHY1_CTRL12 0x4530
#define GRF_USBPHY1_CTRL13 0x4534
#define GRF_USBPHY1_CTRL15 0x453c
#define GRF_USBPHY1_CTRL16 0x4540
#define GRF_GPIO2A_IOMUX 0xe000
#define GRF_GPIO2D_HE 0xe18c
#define GRF_DDRC0_CON0 0xe380
#define GRF_DDRC0_CON1 0xe384
#define GRF_DDRC1_CON0 0xe388
#define GRF_DDRC1_CON1 0xe38c
#define GRF_SOC_CON_BASE 0xe200
#define GRF_SOC_CON(n) (GRF_SOC_CON_BASE + (n) * 4)
#define GRF_IO_VSEL 0xe640
#define CRU_CLKSEL_CON0 0x0100
#define CRU_CLKSEL_CON6 0x0118
#define CRU_SDIO0_CON1 0x058c
#define PMUCRU_CLKSEL_CON0 0x0080
#define PMUCRU_CLKGATE_CON2 0x0108
#define PMUCRU_SOFTRST_CON0 0x0110
@ -231,9 +292,9 @@ void enable_dvfs_plls(void);
void enable_nodvfs_plls(void);
void prepare_abpll_for_ddrctrl(void);
void restore_abpll(void);
void restore_dpll(void);
void clk_gate_con_save(void);
void clk_gate_con_disable(void);
void clk_gate_con_restore(void);
void set_pmu_rsthold(void);
void restore_pmu_rsthold(void);
#endif /* __SOC_H__ */

View File

@ -40,6 +40,9 @@
#define GPIO2_BASE (MMIO_BASE + 0x07780000)
#define GPIO3_BASE (MMIO_BASE + 0x07788000)
#define GPIO4_BASE (MMIO_BASE + 0x07790000)
#define WDT1_BASE (MMIO_BASE + 0x07840000)
#define WDT0_BASE (MMIO_BASE + 0x07848000)
#define TIMER_BASE (MMIO_BASE + 0x07850000)
#define STIME_BASE (MMIO_BASE + 0x07860000)
#define SRAM_BASE (MMIO_BASE + 0x078C0000)
#define SERVICE_NOC_0_BASE (MMIO_BASE + 0x07A50000)