aboutsummaryrefslogtreecommitdiff
path: root/plat/rockchip/rk3399/drivers/dram/suspend.c
diff options
context:
space:
mode:
Diffstat (limited to 'plat/rockchip/rk3399/drivers/dram/suspend.c')
-rw-r--r--plat/rockchip/rk3399/drivers/dram/suspend.c63
1 files changed, 56 insertions, 7 deletions
diff --git a/plat/rockchip/rk3399/drivers/dram/suspend.c b/plat/rockchip/rk3399/drivers/dram/suspend.c
index 7f9fad10e2..caa784c790 100644
--- a/plat/rockchip/rk3399/drivers/dram/suspend.c
+++ b/plat/rockchip/rk3399/drivers/dram/suspend.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2016-2021, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -49,6 +49,7 @@
__pmusramdata uint32_t dpll_data[PLL_CON_COUNT];
__pmusramdata uint32_t cru_clksel_con6;
+__pmusramdata uint8_t pmu_enable_watchdog0;
/*
* Copy @num registers from @src to @dst
@@ -560,10 +561,16 @@ static __pmusramfunc int dram_switch_to_next_index(
ch_count = sdram_params->num_channels;
- /* LPDDR4 f2 cann't do training, all training will fail */
+ /* LPDDR4 f2 can't do training, all training will fail */
for (ch = 0; ch < ch_count; ch++) {
- mmio_clrsetbits_32(PHY_REG(ch, 896), (0x3 << 8) | 1,
- fn << 8);
+ /*
+ * Without this disabled for LPDDR4 we end up writing 0's
+ * in place of real data in an interesting pattern.
+ */
+ if (sdram_params->dramtype != LPDDR4) {
+ mmio_clrsetbits_32(PHY_REG(ch, 896), (0x3 << 8) | 1,
+ fn << 8);
+ }
/* data_training failed */
if (data_training(ch, sdram_params, PI_FULL_TRAINING))
@@ -748,13 +755,44 @@ void dmc_suspend(void)
phy_regs->phy896[0] &= ~(0x3 << 8);
}
+__pmusramfunc void phy_dll_bypass_set(uint32_t ch, uint32_t freq)
+{
+ if (freq <= (125 * 1000 * 1000)) {
+ /* Set master mode to SW for slices*/
+ mmio_setbits_32(PHY_REG(ch, 86), 3 << 10);
+ mmio_setbits_32(PHY_REG(ch, 214), 3 << 10);
+ mmio_setbits_32(PHY_REG(ch, 342), 3 << 10);
+ mmio_setbits_32(PHY_REG(ch, 470), 3 << 10);
+ /* Set master mode to SW for address slices*/
+ mmio_setbits_32(PHY_REG(ch, 547), 3 << 18);
+ mmio_setbits_32(PHY_REG(ch, 675), 3 << 18);
+ mmio_setbits_32(PHY_REG(ch, 803), 3 << 18);
+ } else {
+ /* Clear SW master mode for slices*/
+ mmio_clrbits_32(PHY_REG(ch, 86), 3 << 10);
+ mmio_clrbits_32(PHY_REG(ch, 214), 3 << 10);
+ mmio_clrbits_32(PHY_REG(ch, 342), 3 << 10);
+ mmio_clrbits_32(PHY_REG(ch, 470), 3 << 10);
+ /* Clear SW master mode for address slices*/
+ mmio_clrbits_32(PHY_REG(ch, 547), 3 << 18);
+ mmio_clrbits_32(PHY_REG(ch, 675), 3 << 18);
+ mmio_clrbits_32(PHY_REG(ch, 803), 3 << 18);
+ }
+}
+
__pmusramfunc void dmc_resume(void)
{
struct rk3399_sdram_params *sdram_params = &sdram_config;
uint32_t channel_mask = 0;
uint32_t channel;
- pmusram_enable_watchdog();
+ /*
+ * We can't turn off the watchdog, so if we have not turned it on before
+ * we should not turn it on here.
+ */
+ if ((pmu_enable_watchdog0 & 0x1) == 0x1) {
+ pmusram_enable_watchdog();
+ }
pmu_sgrf_rst_hld_release();
restore_pmu_rsthold();
sram_secure_timer_init();
@@ -772,6 +810,13 @@ __pmusramfunc void dmc_resume(void)
retry:
for (channel = 0; channel < sdram_params->num_channels; channel++) {
phy_pctrl_reset(channel);
+ /*
+ * Without this, LPDDR4 will write 0's in place of real data
+ * in a strange pattern.
+ */
+ if (sdram_params->dramtype == LPDDR4) {
+ phy_dll_bypass_set(channel, sdram_params->ddr_freq);
+ }
pctl_cfg(channel, sdram_params);
}
@@ -788,8 +833,12 @@ retry:
if (sdram_params->dramtype == LPDDR3)
sram_udelay(10);
- /* If traning fail, retry to do it again. */
- if (data_training(channel, sdram_params, PI_FULL_TRAINING))
+ /*
+ * Training here will always fail for LPDDR4, so skip it
+ * If traning fail, retry to do it again.
+ */
+ if (sdram_params->dramtype != LPDDR4 &&
+ data_training(channel, sdram_params, PI_FULL_TRAINING))
goto retry;
set_ddrconfig(sdram_params, channel,