diff options
author | Derek Basehore <dbasehore@chromium.org> | 2017-02-24 14:31:36 +0800 |
---|---|---|
committer | Xing Zheng <zhengxing@rock-chips.com> | 2017-02-24 20:07:44 +0800 |
commit | 4bd1d3faed7893e8e7d74f82b4b5de7443f434bd (patch) | |
tree | 3a7177de901d4f8b8eaf291a35bc70eadae4e5f5 /plat/rockchip/rk3399 | |
parent | 977001aa877f90dfbc8033f8b266b7488c442038 (diff) |
rockchip: rk3399: add support for ddrfreq suspend/resume
This patch sets the frequency configuration of the next DRAM DFS index
to the configuration of the current index. This does not perform a
frequency transition. It just configures registers so the training on
resume for both indices will be correct.
Signed-off-by: Derek Basehore <dbasehore@chromium.org>
Signed-off-by: Xing Zheng <zhengxing@rock-chips.com>
Diffstat (limited to 'plat/rockchip/rk3399')
-rw-r--r-- | plat/rockchip/rk3399/drivers/dram/dfs.c | 87 | ||||
-rw-r--r-- | plat/rockchip/rk3399/drivers/dram/dfs.h | 3 | ||||
-rw-r--r-- | plat/rockchip/rk3399/drivers/dram/suspend.c | 9 | ||||
-rw-r--r-- | plat/rockchip/rk3399/drivers/pmu/pmu.c | 4 |
4 files changed, 92 insertions, 11 deletions
diff --git a/plat/rockchip/rk3399/drivers/dram/dfs.c b/plat/rockchip/rk3399/drivers/dram/dfs.c index c093621d..1d7f0206 100644 --- a/plat/rockchip/rk3399/drivers/dram/dfs.c +++ b/plat/rockchip/rk3399/drivers/dram/dfs.c @@ -62,12 +62,20 @@ static const struct pll_div dpll_rates_table[] = { struct rk3399_dram_status { uint32_t current_index; uint32_t index_freq[2]; + uint32_t boot_freq; uint32_t low_power_stat; struct timing_related_config timing_config; struct drv_odt_lp_config drv_odt_lp_cfg; }; +struct rk3399_saved_status { + uint32_t freq; + uint32_t low_power_stat; + uint32_t odt; +}; + static struct rk3399_dram_status rk3399_dram_status; +static struct rk3399_saved_status rk3399_suspend_status; static uint32_t wrdqs_delay_val[2][2][4]; static struct rk3399_sdram_default_config ddr3_default_config = { @@ -226,6 +234,7 @@ static void sdram_timing_cfg_init(struct timing_related_config *ptiming_config, ptiming_config->dramds = drv_config->dram_side_drv; ptiming_config->dramodt = drv_config->dram_side_dq_odt; ptiming_config->caodt = drv_config->dram_side_ca_odt; + ptiming_config->odt = (mmio_read_32(PHY_REG(0, 5)) >> 16) & 0x1; } struct lat_adj_pair { @@ -1847,7 +1856,7 @@ static void dram_low_power_config(void) void dram_dfs_init(void) { - uint32_t trefi0, trefi1; + uint32_t trefi0, trefi1, boot_freq; /* get sdram config for os reg */ get_dram_drv_odt_val(sdram_config.dramtype, @@ -1867,8 +1876,15 @@ void dram_dfs_init(void) rk3399_dram_status.index_freq[0] /= 2; rk3399_dram_status.index_freq[1] /= 2; } - rk3399_dram_status.index_freq[(rk3399_dram_status.current_index + 1) - & 0x1] = 0; + boot_freq = + rk3399_dram_status.index_freq[rk3399_dram_status.current_index]; + boot_freq = dpll_rates_table[to_get_clk_index(boot_freq)].mhz; + rk3399_dram_status.boot_freq = boot_freq; + rk3399_dram_status.index_freq[rk3399_dram_status.current_index] = + boot_freq; + rk3399_dram_status.index_freq[(rk3399_dram_status.current_index + 1) & + 0x1] = 0; + rk3399_dram_status.low_power_stat = 0; /* * following register decide if NOC stall the access request * or return error when NOC being idled. when doing ddr frequency @@ -1883,6 +1899,10 @@ void dram_dfs_init(void) mmio_write_32(GRF_BASE + GRF_SOC_CON(3), 0xffffffff); mmio_write_32(GRF_BASE + GRF_SOC_CON(4), 0x70007000); + /* Disable multicast */ + mmio_clrbits_32(PHY_REG(0, 896), 1); + mmio_clrbits_32(PHY_REG(1, 896), 1); + dram_low_power_config(); } @@ -1974,7 +1994,7 @@ static uint32_t prepare_ddr_timing(uint32_t mhz) index = (rk3399_dram_status.current_index + 1) & 0x1; if (rk3399_dram_status.index_freq[index] == mhz) - goto out; + return index; /* * checking if having available gate traiing timing for @@ -1990,9 +2010,6 @@ static uint32_t prepare_ddr_timing(uint32_t mhz) &dram_timing, index); rk3399_dram_status.index_freq[index] = mhz; -out: - gen_rk3399_enable_training(rk3399_dram_status.timing_config.ch_cnt, - mhz); return index; } @@ -2024,6 +2041,8 @@ uint32_t ddr_set_rate(uint32_t hz) mhz = dpll_rates_table[index].mhz; ddr_index = prepare_ddr_timing(mhz); + gen_rk3399_enable_training(rk3399_dram_status.timing_config.ch_cnt, + mhz); if (ddr_index > 1) goto out; @@ -2051,3 +2070,57 @@ uint32_t ddr_round_rate(uint32_t hz) return dpll_rates_table[index].mhz * 1000 * 1000; } + +void ddr_prepare_for_sys_suspend(void) +{ + uint32_t mhz = + rk3399_dram_status.index_freq[rk3399_dram_status.current_index]; + + /* + * If we're not currently at the boot (assumed highest) frequency, we + * need to change frequencies to configure out current index. + */ + rk3399_suspend_status.freq = mhz; + exit_low_power(); + rk3399_suspend_status.low_power_stat = + rk3399_dram_status.low_power_stat; + rk3399_suspend_status.odt = rk3399_dram_status.timing_config.odt; + rk3399_dram_status.low_power_stat = 0; + rk3399_dram_status.timing_config.odt = 1; + if (mhz != rk3399_dram_status.boot_freq) + ddr_set_rate(rk3399_dram_status.boot_freq * 1000 * 1000); + + /* + * This will configure the other index to be the same frequency as the + * current one. We retrain both indices on resume, so both have to be + * setup for the same frequency. + */ + prepare_ddr_timing(rk3399_dram_status.boot_freq); +} + +void ddr_prepare_for_sys_resume(void) +{ + /* Disable multicast */ + mmio_clrbits_32(PHY_REG(0, 896), 1); + mmio_clrbits_32(PHY_REG(1, 896), 1); + + /* The suspend code changes the current index, so reset it now. */ + rk3399_dram_status.current_index = + (mmio_read_32(CTL_REG(0, 111)) >> 16) & 0x3; + rk3399_dram_status.low_power_stat = + rk3399_suspend_status.low_power_stat; + rk3399_dram_status.timing_config.odt = rk3399_suspend_status.odt; + + /* + * Set the saved frequency from suspend if it's different than the + * current frequency. + */ + if (rk3399_suspend_status.freq != + rk3399_dram_status.index_freq[rk3399_dram_status.current_index]) { + ddr_set_rate(rk3399_suspend_status.freq * 1000 * 1000); + return; + } + + gen_rk3399_set_odt(rk3399_dram_status.timing_config.odt); + resume_low_power(rk3399_dram_status.low_power_stat); +} diff --git a/plat/rockchip/rk3399/drivers/dram/dfs.h b/plat/rockchip/rk3399/drivers/dram/dfs.h index ab7276fa..3204ae74 100644 --- a/plat/rockchip/rk3399/drivers/dram/dfs.h +++ b/plat/rockchip/rk3399/drivers/dram/dfs.h @@ -66,4 +66,7 @@ uint32_t ddr_round_rate(uint32_t hz); uint32_t ddr_get_rate(void); uint32_t dram_set_odt_pd(uint32_t arg0, uint32_t arg1, uint32_t arg2); void dram_dfs_init(void); +void ddr_prepare_for_sys_suspend(void); +void ddr_prepare_for_sys_resume(void); + #endif diff --git a/plat/rockchip/rk3399/drivers/dram/suspend.c b/plat/rockchip/rk3399/drivers/dram/suspend.c index f408d676..02768fd6 100644 --- a/plat/rockchip/rk3399/drivers/dram/suspend.c +++ b/plat/rockchip/rk3399/drivers/dram/suspend.c @@ -571,14 +571,15 @@ static __sramfunc void pctl_cfg(uint32_t ch, sram_regcpy(PHY_REG(ch, 768), (uintptr_t)¶ms_phy[768], 38); } -static __sramfunc int dram_switch_to_phy_index1( +static __sramfunc int dram_switch_to_next_index( struct rk3399_sdram_params *sdram_params) { uint32_t ch, ch_count; + uint32_t fn = ((mmio_read_32(CTL_REG(0, 111)) >> 16) + 1) & 0x1; mmio_write_32(CIC_BASE + CIC_CTRL0, (((0x3 << 4) | (1 << 2) | 1) << 16) | - (1 << 4) | (1 << 2) | 1); + (fn << 4) | (1 << 2) | 1); while (!(mmio_read_32(CIC_BASE + CIC_STATUS0) & (1 << 2))) ; @@ -591,7 +592,7 @@ static __sramfunc int dram_switch_to_phy_index1( /* LPDDR4 f2 cann't do training, all training will fail */ for (ch = 0; ch < ch_count; ch++) { mmio_clrsetbits_32(PHY_REG(ch, 896), (0x3 << 8) | 1, - 1 << 8); + fn << 8); /* data_training failed */ if (data_training(ch, sdram_params, PI_FULL_TRAINING)) @@ -754,5 +755,5 @@ retry: dram_all_config(sdram_params); /* Switch to index 1 and prepare for DDR frequency switch. */ - dram_switch_to_phy_index1(sdram_params); + dram_switch_to_next_index(sdram_params); } diff --git a/plat/rockchip/rk3399/drivers/pmu/pmu.c b/plat/rockchip/rk3399/drivers/pmu/pmu.c index 6aeabfe5..b8afd387 100644 --- a/plat/rockchip/rk3399/drivers/pmu/pmu.c +++ b/plat/rockchip/rk3399/drivers/pmu/pmu.c @@ -33,6 +33,7 @@ #include <bakery_lock.h> #include <debug.h> #include <delay_timer.h> +#include <dfs.h> #include <errno.h> #include <gpio.h> #include <mmio.h> @@ -1076,6 +1077,7 @@ static int sys_pwr_domain_suspend(void) uint32_t wait_cnt = 0; uint32_t status = 0; + ddr_prepare_for_sys_suspend(); dmc_save(); pmu_scu_b_pwrdn(); @@ -1219,6 +1221,8 @@ static int sys_pwr_domain_resume(void) m0_stop(); + ddr_prepare_for_sys_resume(); + return 0; } |