From 977001aa877f90dfbc8033f8b266b7488c442038 Mon Sep 17 00:00:00 2001 From: Xing Zheng Date: Wed, 26 Oct 2016 21:25:26 +0800 Subject: [PATCH] rk3399: dram: use PMU M0 to do ddr frequency scaling We used dcf do ddr frequency scaling, but we just include a dcf binary, it hard to maintain later, we have M0 compile flow in ATF, and M0 can also work for ddr frequency scaling, so let's use it. Signed-off-by: Lin Huang Signed-off-by: Xing Zheng --- plat/rockchip/common/include/plat_private.h | 1 + plat/rockchip/common/pmusram/pmu_sram.c | 6 + .../rockchip/rk3399/drivers/dram/dcf_code.inc | 386 ------------------ plat/rockchip/rk3399/drivers/dram/dfs.c | 137 ++----- plat/rockchip/rk3399/drivers/dram/dfs.h | 1 - plat/rockchip/rk3399/drivers/m0/Makefile | 17 +- .../rk3399/drivers/m0/include/rk3399_mcu.h | 22 +- plat/rockchip/rk3399/drivers/m0/src/dram.c | 225 ++++++++++ plat/rockchip/rk3399/drivers/m0/src/main.c | 46 +-- .../m0/src/{rk3399m0.ld => rk3399m0.ld.S} | 4 + plat/rockchip/rk3399/drivers/m0/src/suspend.c | 54 +++ plat/rockchip/rk3399/drivers/pmu/m0_ctl.c | 98 +++++ .../drivers/pmu/{rk3399m0.h => m0_ctl.h} | 16 +- plat/rockchip/rk3399/drivers/pmu/pmu.c | 39 +- plat/rockchip/rk3399/drivers/soc/soc.c | 18 +- plat/rockchip/rk3399/drivers/soc/soc.h | 12 + .../rockchip/rk3399/include/shared/m0_param.h | 56 +++ plat/rockchip/rk3399/plat_sip_calls.c | 3 - plat/rockchip/rk3399/platform.mk | 2 + 19 files changed, 565 insertions(+), 578 deletions(-) delete mode 100644 plat/rockchip/rk3399/drivers/dram/dcf_code.inc create mode 100644 plat/rockchip/rk3399/drivers/m0/src/dram.c rename plat/rockchip/rk3399/drivers/m0/src/{rk3399m0.ld => rk3399m0.ld.S} (93%) create mode 100644 plat/rockchip/rk3399/drivers/m0/src/suspend.c create mode 100644 plat/rockchip/rk3399/drivers/pmu/m0_ctl.c rename plat/rockchip/rk3399/drivers/pmu/{rk3399m0.h => m0_ctl.h} (84%) create mode 100644 plat/rockchip/rk3399/include/shared/m0_param.h diff --git a/plat/rockchip/common/include/plat_private.h b/plat/rockchip/common/include/plat_private.h index b2234a650..9638aae3f 100644 --- a/plat/rockchip/common/include/plat_private.h +++ b/plat/rockchip/common/include/plat_private.h @@ -44,6 +44,7 @@ extern uint32_t __bl31_sram_text_start, __bl31_sram_text_end; extern uint32_t __bl31_sram_data_start, __bl31_sram_data_end; +extern uint32_t __sram_incbin_start, __sram_incbin_end; /****************************************************************************** * For rockchip socs pm ops diff --git a/plat/rockchip/common/pmusram/pmu_sram.c b/plat/rockchip/common/pmusram/pmu_sram.c index 120220ae2..82d55ba83 100644 --- a/plat/rockchip/common/pmusram/pmu_sram.c +++ b/plat/rockchip/common/pmusram/pmu_sram.c @@ -62,6 +62,12 @@ void rockchip_plat_sram_mmu_el3(void) mmap_add_region((unsigned long)&__bl31_sram_data_start, (unsigned long)&__bl31_sram_data_start, sram_size, MT_MEMORY | MT_RW | MT_SECURE); + + /* sram.incbin size */ + sram_size = (char *)&__sram_incbin_end - (char *)&__sram_incbin_start; + mmap_add_region((unsigned long)&__sram_incbin_start, + (unsigned long)&__sram_incbin_start, + sram_size, MT_NON_CACHEABLE | MT_RW | MT_SECURE); #else /* TODO: Support other SoCs, Just support RK3399 now */ return; diff --git a/plat/rockchip/rk3399/drivers/dram/dcf_code.inc b/plat/rockchip/rk3399/drivers/dram/dcf_code.inc deleted file mode 100644 index 957d1cf7a..000000000 --- a/plat/rockchip/rk3399/drivers/dram/dcf_code.inc +++ /dev/null @@ -1,386 +0,0 @@ - 0x0 , - 0x7f8c120c , - 0x0 , - 0x7f8c1210 , - 0x100000 , - 0x1f310019 , - 0x0 , - 0xb0000001 , - 0x58 , - 0xd0000000 , - 0x1300 , - 0x1f760329 , - 0x0 , - 0xb0000001 , - 0x40 , - 0xd0000000 , - 0xc , - 0x1f760371 , - 0x0 , - 0xb0000001 , - 0x28 , - 0xd0000000 , - 0x400000 , - 0x1f900009 , - 0x0 , - 0xb0000001 , - 0x10 , - 0xd0000000 , - 0x1 , - 0x7f8c120c , - 0x100000 , - 0x1f310019 , - 0x0 , - 0xb0000001 , - 0x58 , - 0xd0000000 , - 0x2c00 , - 0x1f760329 , - 0x0 , - 0xb0000001 , - 0x40 , - 0xd0000000 , - 0xc0 , - 0x1f760371 , - 0x0 , - 0xb0000001 , - 0x28 , - 0xd0000000 , - 0x400000 , - 0x1f8f0009 , - 0x0 , - 0xb0000001 , - 0x10 , - 0xd0000000 , - 0x1 , - 0x7f8c1210 , - 0x0 , - 0x7f8c1220 , - 0x0 , - 0x7f8c121c , - 0x0 , - 0xaf8c120d , - 0x108 , - 0xd0000000 , - 0x2000 , - 0x1f900009 , - 0x0 , - 0xa0000001 , - 0x30 , - 0xd0000000 , - 0x0 , - 0x7f8c1220 , - 0x0 , - 0x7f8c121c , - 0x0 , - 0x10000001 , - 0x0 , - 0xa0000001 , - 0xb0 , - 0xd0000000 , - 0x8000 , - 0x1f900009 , - 0x0 , - 0xa0000001 , - 0x30 , - 0xd0000000 , - 0x1 , - 0x7f8c1220 , - 0x0 , - 0x7f8c121c , - 0x0 , - 0x10000001 , - 0x0 , - 0xa0000001 , - 0x70 , - 0xd0000000 , - 0x4000 , - 0x1f900009 , - 0x0 , - 0xa0000001 , - 0x30 , - 0xd0000000 , - 0x0 , - 0x7f8c1220 , - 0x1 , - 0x7f8c121c , - 0x0 , - 0x10000001 , - 0x0 , - 0xa0000001 , - 0x30 , - 0xd0000000 , - 0x1000 , - 0x1f900009 , - 0x0 , - 0xa0000001 , - 0x18 , - 0xd0000000 , - 0x1 , - 0x7f8c1220 , - 0x0 , - 0x7f8c121c , - 0x0 , - 0x10000001 , - 0x0 , - 0xa0000001 , - 0x100 , - 0xd0000000 , - 0x0 , - 0xaf8c1211 , - 0xf0 , - 0xd0000000 , - 0x2000 , - 0x1f8f0009 , - 0x0 , - 0xa0000001 , - 0x30 , - 0xd0000000 , - 0x0 , - 0x7f8c1220 , - 0x0 , - 0x7f8c121c , - 0x0 , - 0x10000001 , - 0x0 , - 0xa0000001 , - 0xb0 , - 0xd0000000 , - 0x8000 , - 0x1f8f0009 , - 0x0 , - 0xa0000001 , - 0x30 , - 0xd0000000 , - 0x1 , - 0x7f8c1220 , - 0x0 , - 0x7f8c121c , - 0x0 , - 0x10000001 , - 0x0 , - 0xa0000001 , - 0x70 , - 0xd0000000 , - 0x4000 , - 0x1f8f0009 , - 0x0 , - 0xa0000001 , - 0x30 , - 0xd0000000 , - 0x0 , - 0x7f8c1220 , - 0x1 , - 0x7f8c121c , - 0x0 , - 0x10000001 , - 0x0 , - 0xa0000001 , - 0x30 , - 0xd0000000 , - 0x1000 , - 0x1f8f0009 , - 0x0 , - 0xa0000001 , - 0x18 , - 0xd0000000 , - 0x1 , - 0x7f8c1220 , - 0x0 , - 0x7f8c121c , - 0x0 , - 0xaf8c120d , - 0x40 , - 0xd0000000 , - 0x80008000 , - 0x7f900284 , - 0x1 , - 0x0 , - 0x8000 , - 0x1f90028d , - 0x0 , - 0x60000001 , - 0x0 , - 0x10000001 , - 0x0 , - 0xa0000001 , - 0x38 , - 0xd0000000 , - 0x0 , - 0xaf8c1211 , - 0x28 , - 0xd0000000 , - 0x80008000 , - 0x7f8f0284 , - 0x1 , - 0x0 , - 0x8000 , - 0x1f8f028d , - 0x0 , - 0x60000001 , - 0xffffffff , - 0x7f77e200 , - 0xffffffff , - 0x7f77e204 , - 0xffffffff , - 0x7f77e208 , - 0xffffffff , - 0x7f77e20c , - 0x70007000 , - 0x7f77e210 , - 0x3fffffff , - 0x7f750130 , - 0xc0000 , - 0x2f310061 , - 0x0 , - 0x7f310061 , - 0xc0000 , - 0x1f310065 , - 0xc0000 , - 0xb0000001 , - 0x10 , - 0xc0000000 , - 0x0 , - 0xaf8c121d , - 0x38 , - 0xd0000000 , - 0xff , - 0x1f7601c5 , - 0x0 , - 0x4f8c1215 , - 0xff00ff , - 0x7f7601c4 , - 0xff , - 0x1f7601c9 , - 0x0 , - 0x4f8c1219 , - 0xff00ff , - 0x7f7601c8 , - 0x0 , - 0xaf8c1221 , - 0x48 , - 0xd0000000 , - 0x0 , - 0xaf8c120d , - 0x18 , - 0xd0000000 , - 0x80000000 , - 0x2f90000d , - 0x0 , - 0x4f90000d , - 0x0 , - 0xaf8c1211 , - 0x18 , - 0xd0000000 , - 0x80000000 , - 0x2f8f000d , - 0x0 , - 0x4f8f000d , - 0x350005 , - 0x2f8c101d , - 0x0 , - 0x7f620001 , - 0x1 , - 0x0 , - 0x4 , - 0x1f620011 , - 0x0 , - 0x60000001 , - 0x3000000 , - 0x7f76004c , - 0x18 , - 0x0 , - 0x10001 , - 0x7f76004c , - 0x0 , - 0x2f8c1005 , - 0x0 , - 0x7f760041 , - 0x0 , - 0x2f8c1009 , - 0x0 , - 0x7f760045 , - 0x10000 , - 0x7f76004c , - 0x18 , - 0x0 , - 0x1 , - 0x0 , - 0x80000000 , - 0x1f760049 , - 0x0 , - 0x60000001 , - 0x3000100 , - 0x7f76004c , - 0x20002 , - 0x7f620000 , - 0x1 , - 0x0 , - 0x1 , - 0x1f620011 , - 0x0 , - 0x60000001 , - 0x0 , - 0xaf8c121d , - 0x28 , - 0xd0000000 , - 0xff0000 , - 0x2f8c1215 , - 0x0 , - 0x4f7601c5 , - 0xff0000 , - 0x2f8c1219 , - 0x0 , - 0x4f7601c9 , - 0x0 , - 0xaf8c1221 , - 0x48 , - 0xd0000000 , - 0x0 , - 0xaf8c120d , - 0x18 , - 0xd0000000 , - 0x7fffffff , - 0x1f90000d , - 0x0 , - 0x4f90000d , - 0x0 , - 0xaf8c1211 , - 0x18 , - 0xd0000000 , - 0x7fffffff , - 0x1f8f000d , - 0x0 , - 0x4f8f000d , - 0xfff3ffff , - 0x1f310061 , - 0x0 , - 0x7f310061 , - 0xc0000 , - 0x1f310065 , - 0x0 , - 0xb0000001 , - 0x10 , - 0xc0000000 , - 0x0 , - 0x7f750130 , - 0x1 , - 0x0 , - 0x1 , - 0x0 , - 0x1 , - 0x0 , - 0x1 , - 0x0 , - 0x1 , - 0x0 , - 0x1 , - 0x0 , - 0x1 , - 0x0 , - 0x1 , - 0x0 , - 0x1 , - 0x0 , - 0x0 , - 0xe0000000 , diff --git a/plat/rockchip/rk3399/drivers/dram/dfs.c b/plat/rockchip/rk3399/drivers/dram/dfs.c index bb381a26c..c093621d4 100644 --- a/plat/rockchip/rk3399/drivers/dram/dfs.c +++ b/plat/rockchip/rk3399/drivers/dram/dfs.c @@ -28,8 +28,10 @@ * POSSIBILITY OF SUCH DAMAGE. */ +#include #include #include +#include #include #include "dfs.h" #include "dram.h" @@ -43,20 +45,10 @@ #define ENPER_CS_TRAINING_FREQ (933) #define PHY_DLL_BYPASS_FREQ (260) -struct pll_div { - uint32_t mhz; - uint32_t refdiv; - uint32_t fbdiv; - uint32_t postdiv1; - uint32_t postdiv2; - uint32_t frac; - uint32_t freq; -}; - static const struct pll_div dpll_rates_table[] = { /* _mhz, _refdiv, _fbdiv, _postdiv1, _postdiv2 */ - {.mhz = 933, .refdiv = 3, .fbdiv = 350, .postdiv1 = 3, .postdiv2 = 1}, + {.mhz = 928, .refdiv = 1, .fbdiv = 116, .postdiv1 = 3, .postdiv2 = 1}, {.mhz = 800, .refdiv = 1, .fbdiv = 100, .postdiv1 = 3, .postdiv2 = 1}, {.mhz = 732, .refdiv = 1, .fbdiv = 61, .postdiv1 = 2, .postdiv2 = 1}, {.mhz = 666, .refdiv = 1, .fbdiv = 111, .postdiv1 = 4, .postdiv2 = 1}, @@ -100,24 +92,6 @@ static struct rk3399_sdram_default_config lpddr4_default_config = { .zqcsi = 0 }; -uint32_t dcf_code[] = { -#include "dcf_code.inc" -}; - -#define DCF_START_ADDR (SRAM_BASE + 0x1400) -#define DCF_PARAM_ADDR (SRAM_BASE + 0x1000) - -/* DCF_PAMET */ -#define PARAM_DRAM_FREQ (0) -#define PARAM_DPLL_CON0 (4) -#define PARAM_DPLL_CON1 (8) -#define PARAM_DPLL_CON2 (0xc) -#define PARAM_DPLL_CON3 (0x10) -#define PARAM_DPLL_CON4 (0x14) -#define PARAM_DPLL_CON5 (0x18) -/* equal to fn<<4 */ -#define PARAM_FREQ_SELECT (0x1c) - static uint32_t get_cs_die_capability(struct rk3399_sdram_params *sdram_config, uint8_t channel, uint8_t cs) { @@ -1749,22 +1723,6 @@ static int to_get_clk_index(unsigned int mhz) return i; } -uint32_t rkclk_prepare_pll_timing(unsigned int mhz) -{ - unsigned int refdiv, postdiv1, fbdiv, postdiv2; - int index; - - index = to_get_clk_index(mhz); - refdiv = dpll_rates_table[index].refdiv; - fbdiv = dpll_rates_table[index].fbdiv; - postdiv1 = dpll_rates_table[index].postdiv1; - postdiv2 = dpll_rates_table[index].postdiv2; - mmio_write_32(DCF_PARAM_ADDR + PARAM_DPLL_CON0, FBDIV(fbdiv)); - mmio_write_32(DCF_PARAM_ADDR + PARAM_DPLL_CON1, - POSTDIV2(postdiv2) | POSTDIV1(postdiv1) | REFDIV(refdiv)); - return (24 * fbdiv) / refdiv / postdiv1 / postdiv2; -} - uint32_t ddr_get_rate(void) { uint32_t refdiv, postdiv1, fbdiv, postdiv2; @@ -1856,51 +1814,6 @@ void resume_low_power(uint32_t low_power) } } -static void wait_dcf_done(void) -{ - while ((mmio_read_32(DCF_BASE + DCF_DCF_ISR) & (DCF_DONE)) == 0) - continue; -} - -void clr_dcf_irq(void) -{ - /* clear dcf irq status */ - mmio_write_32(DCF_BASE + DCF_DCF_ISR, DCF_TIMEOUT | DCF_ERR | DCF_DONE); -} - -static void enable_dcf(uint32_t dcf_addr) -{ - /* config DCF start addr */ - mmio_write_32(DCF_BASE + DCF_DCF_ADDR, dcf_addr); - /* wait dcf done */ - while (mmio_read_32(DCF_BASE + DCF_DCF_CTRL) & 1) - continue; - /* clear dcf irq status */ - mmio_write_32(DCF_BASE + DCF_DCF_ISR, DCF_TIMEOUT | DCF_ERR | DCF_DONE); - /* DCF start */ - mmio_setbits_32(DCF_BASE + DCF_DCF_CTRL, DCF_START); -} - -static void dcf_start(uint32_t freq, uint32_t index) -{ - mmio_write_32(CRU_BASE + CRU_SOFTRST_CON(10), - (0x1 << (1 + 16)) | (1 << 1)); - mmio_write_32(CRU_BASE + CRU_SOFTRST_CON(11), - (0x1 << (0 + 16)) | (1 << 0)); - mmio_write_32(DCF_PARAM_ADDR + PARAM_FREQ_SELECT, index << 4); - - mmio_write_32(DCF_PARAM_ADDR + PARAM_DRAM_FREQ, freq); - - rkclk_prepare_pll_timing(freq); - udelay(10); - mmio_write_32(CRU_BASE + CRU_SOFTRST_CON(10), - (0x1 << (1 + 16)) | (0 << 1)); - mmio_write_32(CRU_BASE + CRU_SOFTRST_CON(11), - (0x1 << (0 + 16)) | (0 << 0)); - udelay(10); - enable_dcf(DCF_START_ADDR); -} - static void dram_low_power_config(void) { uint32_t tmp, i; @@ -1956,6 +1869,20 @@ void dram_dfs_init(void) } rk3399_dram_status.index_freq[(rk3399_dram_status.current_index + 1) & 0x1] = 0; + /* + * following register decide if NOC stall the access request + * or return error when NOC being idled. when doing ddr frequency + * scaling in M0 or DCF, we need to make sure noc stall the access + * request, if return error cpu may data abort when ddr frequency + * changing. it don't need to set this register every times, + * so we init this register in function dram_dfs_init(). + */ + mmio_write_32(GRF_BASE + GRF_SOC_CON(0), 0xffffffff); + mmio_write_32(GRF_BASE + GRF_SOC_CON(1), 0xffffffff); + mmio_write_32(GRF_BASE + GRF_SOC_CON(2), 0xffffffff); + mmio_write_32(GRF_BASE + GRF_SOC_CON(3), 0xffffffff); + mmio_write_32(GRF_BASE + GRF_SOC_CON(4), 0x70007000); + dram_low_power_config(); } @@ -2015,6 +1942,21 @@ uint32_t dram_set_odt_pd(uint32_t arg0, uint32_t arg1, uint32_t arg2) return 0; } +static void m0_configure_ddr(struct pll_div pll_div, uint32_t ddr_index) +{ + /* set PARAM to M0_FUNC_DRAM */ + mmio_write_32(M0_PARAM_ADDR + PARAM_M0_FUNC, M0_FUNC_DRAM); + + mmio_write_32(M0_PARAM_ADDR + PARAM_DPLL_CON0, FBDIV(pll_div.fbdiv)); + mmio_write_32(M0_PARAM_ADDR + PARAM_DPLL_CON1, + POSTDIV2(pll_div.postdiv2) | POSTDIV1(pll_div.postdiv1) | + REFDIV(pll_div.refdiv)); + + mmio_write_32(M0_PARAM_ADDR + PARAM_DRAM_FREQ, pll_div.mhz); + + mmio_write_32(M0_PARAM_ADDR + PARAM_FREQ_SELECT, ddr_index << 4); +} + static uint32_t prepare_ddr_timing(uint32_t mhz) { uint32_t index; @@ -2071,7 +2013,7 @@ void print_dram_status_info(void) uint32_t ddr_set_rate(uint32_t hz) { - uint32_t low_power, index; + uint32_t low_power, index, ddr_index; uint32_t mhz = hz / (1000 * 1000); if (mhz == @@ -2081,16 +2023,19 @@ uint32_t ddr_set_rate(uint32_t hz) index = to_get_clk_index(mhz); mhz = dpll_rates_table[index].mhz; - index = prepare_ddr_timing(mhz); - if (index > 1) + ddr_index = prepare_ddr_timing(mhz); + if (ddr_index > 1) goto out; - dcf_start(mhz, index); - wait_dcf_done(); + m0_configure_ddr(dpll_rates_table[index], ddr_index); + m0_start(); + m0_wait_done(); + m0_stop(); + if (rk3399_dram_status.timing_config.odt == 0) gen_rk3399_set_odt(0); - rk3399_dram_status.current_index = index; + rk3399_dram_status.current_index = ddr_index; low_power = rk3399_dram_status.low_power_stat; resume_low_power(low_power); out: diff --git a/plat/rockchip/rk3399/drivers/dram/dfs.h b/plat/rockchip/rk3399/drivers/dram/dfs.h index 92aa483bd..ab7276fa6 100644 --- a/plat/rockchip/rk3399/drivers/dram/dfs.h +++ b/plat/rockchip/rk3399/drivers/dram/dfs.h @@ -64,7 +64,6 @@ struct drv_odt_lp_config { uint32_t ddr_set_rate(uint32_t hz); uint32_t ddr_round_rate(uint32_t hz); uint32_t ddr_get_rate(void); -void clr_dcf_irq(void); uint32_t dram_set_odt_pd(uint32_t arg0, uint32_t arg1, uint32_t arg2); void dram_dfs_init(void); #endif diff --git a/plat/rockchip/rk3399/drivers/m0/Makefile b/plat/rockchip/rk3399/drivers/m0/Makefile index c9454fe65..ec2b3d2d1 100644 --- a/plat/rockchip/rk3399/drivers/m0/Makefile +++ b/plat/rockchip/rk3399/drivers/m0/Makefile @@ -46,11 +46,14 @@ export Q .SUFFIXES: -INCLUDES += -Iinclude/ +INCLUDES += -Iinclude/ \ + -I../../include/shared/ # NOTE: Add C source files here C_SOURCES := src/startup.c \ - src/main.c + src/main.c \ + src/suspend.c \ + src/dram.c # Flags definition CFLAGS := -g @@ -83,10 +86,11 @@ endef SOURCES := $(C_SOURCES) OBJS := $(addprefix $(BUILD)/,$(call SOURCES_TO_OBJS,$(SOURCES))) -LINKERFILE := src/rk3399m0.ld +LINKERFILE := $(BUILD)/$(PLAT_M0).ld MAPFILE := $(BUILD)/$(PLAT_M0).map ELF := $(BUILD)/$(PLAT_M0).elf BIN := $(BUILD)/$(PLAT_M0).bin +LINKERFILE_SRC := src/$(PLAT_M0).ld.S # Function definition related compilation define MAKE_C @@ -118,8 +122,11 @@ define MAKE_OBJS $(and $(REMAIN),$(error Unexpected source files present: $(REMAIN))) endef -.PHONY: all -all: $(BIN) +.DEFAULT_GOAL := $(BIN) + +$(LINKERFILE): $(LINKERFILE_SRC) + $(CC) $(CFLAGS) $(INCLUDES) -P -E -D__LINKER__ -MMD -MF $@.d -MT $@ -o $@ $< +-include $(LINKERFILE).d $(ELF) : $(OBJS) $(LINKERFILE) @echo " LD $@" diff --git a/plat/rockchip/rk3399/drivers/m0/include/rk3399_mcu.h b/plat/rockchip/rk3399/drivers/m0/include/rk3399_mcu.h index d04c06ef0..7f4f34cb9 100644 --- a/plat/rockchip/rk3399/drivers/m0/include/rk3399_mcu.h +++ b/plat/rockchip/rk3399/drivers/m0/include/rk3399_mcu.h @@ -31,11 +31,29 @@ #ifndef __RK3399_MCU_H__ #define __RK3399_MCU_H__ +typedef unsigned int uint32_t; + #define mmio_read_32(c) ({unsigned int __v = \ (*(volatile unsigned int *)(c)); __v; }) #define mmio_write_32(c, v) ((*(volatile unsigned int *)(c)) = (v)) -#define MCU_BASE 0x40000000 -#define PMU_BASE (MCU_BASE + 0x07310000) +#define mmio_clrbits_32(addr, clear) \ + mmio_write_32(addr, (mmio_read_32(addr) & ~(clear))) +#define mmio_setbits_32(addr, set) \ + mmio_write_32(addr, (mmio_read_32(addr)) | (set)) +#define mmio_clrsetbits_32(addr, clear, set) \ + mmio_write_32(addr, (mmio_read_32(addr) & ~(clear)) | (set)) + +#define MCU_BASE 0x40000000 +#define PMU_BASE (MCU_BASE + 0x07310000) +#define CRU_BASE_ADDR 0x47760000 +#define GRF_BASE_ADDR 0x47770000 +#define PMU_CRU_BASE_ADDR 0x47750000 +#define VOP_LITE_BASE_ADDR 0x478F0000 +#define VOP_BIG_BASE_ADDR 0x47900000 +#define CIC_BASE_ADDR 0x47620000 + +void handle_suspend(void); +void handle_dram(void); #endif /* __RK3399_MCU_H__ */ diff --git a/plat/rockchip/rk3399/drivers/m0/src/dram.c b/plat/rockchip/rk3399/drivers/m0/src/dram.c new file mode 100644 index 000000000..79452c9aa --- /dev/null +++ b/plat/rockchip/rk3399/drivers/m0/src/dram.c @@ -0,0 +1,225 @@ +/* + * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of ARM nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include "rk3399_mcu.h" + +/* PMU */ +#define PMU_PWRDN_ST 0x18 +#define PMU_BUS_IDLE_REQ 0x60 +#define PMU_BUS_IDLE_ST 0x64 +#define PMU_NOC_AUTO_ENA 0xd8 + +/* PMU_BUS_IDLE_REQ */ +#define IDLE_REQ_MSCH1 (1 << 19) +#define IDLE_REQ_MSCH0 (1 << 18) + +/* #define PMU_BUS_IDLE_ST */ +#define IDLE_MSCH1 (1 << 19) +#define IDLE_MSCH0 (1 << 18) + +#define PD_VOP_PWR_STAT (1 << 20) + +/* CRU */ +#define CRU_DPLL_CON0 0x40 +#define CRU_DPLL_CON1 0x44 +#define CRU_DPLL_CON2 0x48 +#define CRU_DPLL_CON3 0x4c +#define CRU_DPLL_CON4 0x50 +#define CRU_DPLL_CON5 0x54 + +#define CRU_DPLL_CON2 0x48 +#define CRU_DPLL_CON3 0x4c +#define CRU_CLKGATE10_CON 0x328 +#define CRU_CLKGATE28_CON 0x370 + +/* CRU_CLKGATE10_CON */ +#define ACLK_VOP0_PRE_SRC_EN (1 << 8) +#define HCLK_VOP0_PRE_EN (1 << 9) +#define ACLK_VOP1_PRE_SRC_EN (1 << 10) +#define HCLK_VOP1_PRE_EN (1 << 11) +#define DCLK_VOP0_SRC_EN (1 << 12) +#define DCLK_VOP1_SRC_EN (1 << 13) + +/* CRU_CLKGATE28_CON */ +#define HCLK_VOP0_EN (1 << 2) +#define ACLK_VOP0_EN (1 << 3) +#define HCLK_VOP1_EN (1 << 6) +#define ACLK_VOP1_EN (1 << 7) + +/* CRU_PLL_CON3 */ +#define PLL_SLOW_MODE 0 +#define PLL_NORMAL_MODE 1 +#define PLL_MODE(n) ((0x3 << (8 + 16)) | ((n) << 8)) +#define PLL_POWER_DOWN(n) ((0x1 << (0 + 16)) | ((n) << 0)) + +/* PMU CRU */ +#define PMU_CRU_GATEDIS_CON0 0x130 + +/* VOP */ +#define VOP_SYS_CTRL 0x8 +#define VOP_SYS_CTRL1 0xc +#define VOP_INTR_CLEAR0 0x284 +#define VOP_INTR_RAW_STATUS0 0x28c + +/* VOP_SYS_CTRL */ +#define VOP_STANDBY_EN (1 << 22) + +/* VOP_INTR_CLEAR0 */ +#define INT_CLR_DMA_FINISH (1 << 15) +#define INT_CLR_LINE_FLAG1 (1 << 4) +#define INT_CLR_LINE_FLAG0 (1 << 3) + +/* VOP_INTR_RAW_STATUS0 */ +#define INT_RAW_STATUS_DMA_FINISH (1 << 15) +#define INT_RAW_STATUS_LINE_FLAG1 (1 << 4) +#define INT_RAW_STATUS_LINE_FLAG0 (1 << 3) + +/* CIC */ +#define CIC_CTRL0 0 +#define CIC_CTRL1 0x4 +#define CIC_STATUS0 0x10 + +struct ddr_freq_param { + uint32_t vop_big_en; + uint32_t vop_lit_en; + uint32_t dclk0_div; + uint32_t dclk1_div; +}; + +static struct ddr_freq_param rk3399_ddr_arg; + +static void get_vop_status(void) +{ + rk3399_ddr_arg.vop_big_en = 0; + rk3399_ddr_arg.vop_lit_en = 0; + + if ((mmio_read_32(PMU_BASE + PMU_PWRDN_ST) & PD_VOP_PWR_STAT) == 0) { + /* get vop0 status */ + if ((mmio_read_32(CRU_BASE_ADDR + CRU_CLKGATE10_CON) & + (DCLK_VOP0_SRC_EN | ACLK_VOP0_PRE_SRC_EN | + HCLK_VOP0_PRE_EN)) == 0) + if ((mmio_read_32(CRU_BASE_ADDR + CRU_CLKGATE28_CON) & + (HCLK_VOP0_EN | ACLK_VOP0_EN)) == 0) + if ((mmio_read_32(VOP_BIG_BASE_ADDR + + VOP_SYS_CTRL) & + VOP_STANDBY_EN) == 0) + rk3399_ddr_arg.vop_big_en = 1; + + /* get vop1 satus */ + if ((mmio_read_32(CRU_BASE_ADDR + CRU_CLKGATE10_CON) & + (DCLK_VOP1_SRC_EN | ACLK_VOP1_PRE_SRC_EN | + HCLK_VOP1_PRE_EN)) == 0) + if ((mmio_read_32(CRU_BASE_ADDR + CRU_CLKGATE28_CON) & + (HCLK_VOP1_EN | ACLK_VOP1_EN)) == 0) + if ((mmio_read_32(VOP_LITE_BASE_ADDR + + VOP_SYS_CTRL) & + VOP_STANDBY_EN) == 0) + rk3399_ddr_arg.vop_lit_en = 1; + } +} + +static void wait_vop_dma_finish(void) +{ + uint32_t vop_adr; + + get_vop_status(); + + if (rk3399_ddr_arg.vop_big_en) + vop_adr = VOP_BIG_BASE_ADDR; + else if (rk3399_ddr_arg.vop_lit_en) + vop_adr = VOP_LITE_BASE_ADDR; + else + return; + + /* clean dma finish irq and wait for it */ + mmio_write_32(vop_adr + VOP_INTR_CLEAR0, + INT_CLR_DMA_FINISH | (INT_CLR_DMA_FINISH << 16)); + + while ((mmio_read_32(vop_adr + VOP_INTR_RAW_STATUS0) & + INT_RAW_STATUS_DMA_FINISH) == 0) + ; +} + +static void idle_port(void) +{ + mmio_write_32(PMU_CRU_BASE_ADDR + PMU_CRU_GATEDIS_CON0, 0x3fffffff); + mmio_setbits_32(PMU_BASE + PMU_BUS_IDLE_REQ, + IDLE_REQ_MSCH0 | IDLE_REQ_MSCH1); + while ((mmio_read_32(PMU_BASE + PMU_BUS_IDLE_ST) & + (IDLE_MSCH1 | IDLE_MSCH0)) != (IDLE_MSCH1 | IDLE_MSCH0)) + continue; +} + +static void deidle_port(void) +{ + mmio_clrbits_32(PMU_BASE + PMU_BUS_IDLE_REQ, + IDLE_REQ_MSCH0 | IDLE_REQ_MSCH1); + while (mmio_read_32(PMU_BASE + PMU_BUS_IDLE_ST) & + (IDLE_MSCH1 | IDLE_MSCH0)) + continue; +} + +static void ddr_set_pll(void) +{ + mmio_write_32(CRU_BASE_ADDR + CRU_DPLL_CON3, PLL_MODE(PLL_SLOW_MODE)); + + mmio_write_32(CRU_BASE_ADDR + CRU_DPLL_CON3, PLL_POWER_DOWN(1)); + mmio_write_32(CRU_BASE_ADDR + CRU_DPLL_CON0, + mmio_read_32(PARAM_ADDR + PARAM_DPLL_CON0)); + mmio_write_32(CRU_BASE_ADDR + CRU_DPLL_CON1, + mmio_read_32(PARAM_ADDR + PARAM_DPLL_CON1)); + mmio_write_32(CRU_BASE_ADDR + CRU_DPLL_CON3, PLL_POWER_DOWN(0)); + + while ((mmio_read_32(CRU_BASE_ADDR + CRU_DPLL_CON2) & (1u << 31)) == 0) + continue; + + mmio_write_32(CRU_BASE_ADDR + CRU_DPLL_CON3, PLL_MODE(PLL_NORMAL_MODE)); +} + +void handle_dram(void) +{ + wait_vop_dma_finish(); + idle_port(); + + mmio_write_32(CIC_BASE_ADDR + CIC_CTRL0, + (((0x3 << 4) | (1 << 2) | 1) << 16) | + (1 << 2) | 1 | + mmio_read_32(PARAM_ADDR + PARAM_FREQ_SELECT)); + while ((mmio_read_32(CIC_BASE_ADDR + CIC_STATUS0) & (1 << 2)) == 0) + continue; + + ddr_set_pll(); + mmio_write_32(CIC_BASE_ADDR + CIC_CTRL0, 0x20002); + while ((mmio_read_32(CIC_BASE_ADDR + CIC_STATUS0) & (1 << 0)) == 0) + continue; + + deidle_port(); +} diff --git a/plat/rockchip/rk3399/drivers/m0/src/main.c b/plat/rockchip/rk3399/drivers/m0/src/main.c index d9cfd10b7..95659c4e5 100644 --- a/plat/rockchip/rk3399/drivers/m0/src/main.c +++ b/plat/rockchip/rk3399/drivers/m0/src/main.c @@ -28,44 +28,24 @@ * POSSIBILITY OF SUCH DAMAGE. */ +#include #include "rk3399_mcu.h" -#define PMU_PWRMODE_CON 0x20 -#define PMU_POWER_ST 0x78 - -#define M0_SCR 0xe000ed10 /* System Control Register (SCR) */ - -#define SCR_SLEEPDEEP_SHIFT (1 << 2) - -static void system_wakeup(void) +__attribute__((noreturn)) void main(void) { - unsigned int status_value; - unsigned int mode_con; - - while (1) { - status_value = mmio_read_32(PMU_BASE + PMU_POWER_ST); - if (status_value) { - mode_con = mmio_read_32(PMU_BASE + PMU_PWRMODE_CON); - mmio_write_32(PMU_BASE + PMU_PWRMODE_CON, - mode_con & (~0x01)); - return; - } + switch (mmio_read_32(PARAM_ADDR + PARAM_M0_FUNC)) { + case M0_FUNC_SUSPEND: + handle_suspend(); + break; + case M0_FUNC_DRAM: + handle_dram(); + break; + default: + break; } -} -int main(void) -{ - unsigned int reg_src; - - system_wakeup(); - - reg_src = mmio_read_32(M0_SCR); - - /* m0 enter deep sleep mode */ - mmio_write_32(M0_SCR, reg_src | SCR_SLEEPDEEP_SHIFT); + mmio_write_32(PARAM_ADDR + PARAM_M0_DONE, M0_DONE_FLAG); for (;;) - __asm volatile("wfi"); - - return 0; + __asm__ volatile ("wfi"); } diff --git a/plat/rockchip/rk3399/drivers/m0/src/rk3399m0.ld b/plat/rockchip/rk3399/drivers/m0/src/rk3399m0.ld.S similarity index 93% rename from plat/rockchip/rk3399/drivers/m0/src/rk3399m0.ld rename to plat/rockchip/rk3399/drivers/m0/src/rk3399m0.ld.S index 0b7b124d6..cb224f09c 100644 --- a/plat/rockchip/rk3399/drivers/m0/src/rk3399m0.ld +++ b/plat/rockchip/rk3399/drivers/m0/src/rk3399m0.ld.S @@ -28,12 +28,16 @@ * POSSIBILITY OF SUCH DAMAGE. */ +#include + OUTPUT_FORMAT("elf32-littlearm") SECTIONS { .m0_bin 0 : { KEEP(*(.isr_vector)) ASSERT(. == 0xc0, "ISR vector has the wrong size."); + ASSERT(. == PARAM_ADDR, "M0 params should go right behind ISR table."); + . += PARAM_M0_SIZE; *(.text*) *(.rodata*) *(.data*) diff --git a/plat/rockchip/rk3399/drivers/m0/src/suspend.c b/plat/rockchip/rk3399/drivers/m0/src/suspend.c new file mode 100644 index 000000000..e65594074 --- /dev/null +++ b/plat/rockchip/rk3399/drivers/m0/src/suspend.c @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of ARM nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include "rk3399_mcu.h" + +#define PMU_PWRMODE_CON 0x20 +#define PMU_POWER_ST 0x78 + +#define M0_SCR 0xe000ed10 /* System Control Register (SCR) */ + +#define SCR_SLEEPDEEP_SHIFT (1 << 2) + +void handle_suspend(void) +{ + unsigned int status_value; + + while (1) { + status_value = mmio_read_32(PMU_BASE + PMU_POWER_ST); + if (status_value) { + mmio_clrbits_32(PMU_BASE + PMU_PWRMODE_CON, 0x01); + return; + } + } + + /* m0 enter deep sleep mode */ + mmio_setbits_32(M0_SCR, SCR_SLEEPDEEP_SHIFT); +} diff --git a/plat/rockchip/rk3399/drivers/pmu/m0_ctl.c b/plat/rockchip/rk3399/drivers/pmu/m0_ctl.c new file mode 100644 index 000000000..4df0195b2 --- /dev/null +++ b/plat/rockchip/rk3399/drivers/pmu/m0_ctl.c @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of ARM nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +void m0_init(void) +{ + /* secure config for M0 */ + mmio_write_32(SGRF_BASE + SGRF_PMU_CON(0), WMSK_BIT(7)); + mmio_write_32(SGRF_BASE + SGRF_SOC_CON6, WMSK_BIT(12)); + + /* set the execute address for M0 */ + mmio_write_32(SGRF_BASE + SGRF_PMU_CON(3), + BITS_WITH_WMASK((M0_BINCODE_BASE >> 12) & 0xffff, + 0xffff, 0)); + mmio_write_32(SGRF_BASE + SGRF_PMU_CON(7), + BITS_WITH_WMASK((M0_BINCODE_BASE >> 28) & 0xf, + 0xf, 0)); + + /* gating disable for M0 */ + mmio_write_32(PMUCRU_BASE + PMUCRU_GATEDIS_CON0, BIT_WITH_WMSK(1)); + + /* + * To switch the parent to xin24M and div == 1, + * + * We need to close most of the PLLs and clocks except the OSC 24MHz + * durning suspend, and this should be enough to supplies the ddrfreq, + * For the simple handle, we just keep the fixed 24MHz to supply the + * suspend and ddrfreq directly. + */ + mmio_write_32(PMUCRU_BASE + PMUCRU_CLKSEL_CON0, + BIT_WITH_WMSK(15) | BITS_WITH_WMASK(0x0, 0x1f, 8)); +} + +void m0_start(void) +{ + /* clean the PARAM_M0_DONE flag, mean that M0 will start working */ + mmio_write_32(M0_PARAM_ADDR + PARAM_M0_DONE, 0); + + /* enable clocks for M0 */ + mmio_write_32(PMUCRU_BASE + PMUCRU_CLKGATE_CON2, + BITS_WITH_WMASK(0x0, 0x2f, 0)); + + /* start M0 */ + mmio_write_32(PMUCRU_BASE + PMUCRU_SOFTRST_CON0, + BITS_WITH_WMASK(0x0, 0x24, 0)); +} + +void m0_stop(void) +{ + /* stop M0 */ + mmio_write_32(PMUCRU_BASE + PMUCRU_SOFTRST_CON0, + BITS_WITH_WMASK(0x24, 0x24, 0)); + + /* disable clocks for M0 */ + mmio_write_32(PMUCRU_BASE + PMUCRU_CLKGATE_CON2, + BITS_WITH_WMASK(0x2f, 0x2f, 0)); +} + +void m0_wait_done(void) +{ + while (mmio_read_32(M0_PARAM_ADDR + PARAM_M0_DONE) != M0_DONE_FLAG) + dsb(); +} diff --git a/plat/rockchip/rk3399/drivers/pmu/rk3399m0.h b/plat/rockchip/rk3399/drivers/pmu/m0_ctl.h similarity index 84% rename from plat/rockchip/rk3399/drivers/pmu/rk3399m0.h rename to plat/rockchip/rk3399/drivers/pmu/m0_ctl.h index 78b350a2e..fcee9b0ce 100644 --- a/plat/rockchip/rk3399/drivers/pmu/rk3399m0.h +++ b/plat/rockchip/rk3399/drivers/pmu/m0_ctl.h @@ -28,13 +28,21 @@ * POSSIBILITY OF SUCH DAMAGE. */ -#ifndef __RK3399M0_H__ -#define __RK3399M0_H__ +#ifndef __M0_CTL_H__ +#define __M0_CTL_H__ + +#include + +#define M0_BINCODE_BASE ((uintptr_t)rk3399m0_bin) +#define M0_PARAM_ADDR (M0_BINCODE_BASE + PARAM_ADDR) /* pmu_fw.c */ extern char rk3399m0_bin[]; extern char rk3399m0_bin_end[]; -#define M0_BINCODE_BASE ((uintptr_t)rk3399m0_bin) +extern void m0_init(void); +extern void m0_start(void); +extern void m0_stop(void); +extern void m0_wait_done(void); -#endif /* __RK3399M0_H__ */ +#endif /* __M0_CTL_H__ */ diff --git a/plat/rockchip/rk3399/drivers/pmu/pmu.c b/plat/rockchip/rk3399/drivers/pmu/pmu.c index 05ca7fdd2..6aeabfe5b 100644 --- a/plat/rockchip/rk3399/drivers/pmu/pmu.c +++ b/plat/rockchip/rk3399/drivers/pmu/pmu.c @@ -36,6 +36,7 @@ #include #include #include +#include #include #include #include @@ -47,7 +48,6 @@ #include #include #include -#include #include DEFINE_BAKERY_LOCK(rockchip_pd_lock); @@ -1065,36 +1065,10 @@ static void resume_gpio(void) } } -static void m0_clock_init(void) +static void m0_configure_suspend(void) { - /* enable clocks for M0 */ - mmio_write_32(PMUCRU_BASE + PMUCRU_CLKGATE_CON2, - BITS_WITH_WMASK(0x0, 0x2f, 0)); - - /* switch the parent to xin24M and div == 1 */ - mmio_write_32(PMUCRU_BASE + PMUCRU_CLKSEL_CON0, - BIT_WITH_WMSK(15) | BITS_WITH_WMASK(0x0, 0x1f, 8)); - - /* start M0 */ - mmio_write_32(PMUCRU_BASE + PMUCRU_SOFTRST_CON0, - BITS_WITH_WMASK(0x0, 0x24, 0)); - - /* gating disable for M0 */ - mmio_write_32(PMUCRU_BASE + PMUCRU_GATEDIS_CON0, BIT_WITH_WMSK(1)); -} - -static void m0_reset(void) -{ - /* stop M0 */ - mmio_write_32(PMUCRU_BASE + PMUCRU_SOFTRST_CON0, - BITS_WITH_WMASK(0x24, 0x24, 0)); - - /* recover gating bit for M0 */ - mmio_write_32(PMUCRU_BASE + PMUCRU_GATEDIS_CON0, WMSK_BIT(1)); - - /* disable clocks for M0 */ - mmio_write_32(PMUCRU_BASE + PMUCRU_CLKGATE_CON2, - BITS_WITH_WMASK(0x2f, 0x2f, 0)); + /* set PARAM to M0_FUNC_SUSPEND */ + mmio_write_32(M0_PARAM_ADDR + PARAM_M0_FUNC, M0_FUNC_SUSPEND); } static int sys_pwr_domain_suspend(void) @@ -1117,7 +1091,8 @@ static int sys_pwr_domain_suspend(void) sys_slp_config(); - m0_clock_init(); + m0_configure_suspend(); + m0_start(); pmu_sgrf_rst_hld(); @@ -1242,7 +1217,7 @@ static int sys_pwr_domain_resume(void) plat_rockchip_gic_cpuif_enable(); - m0_reset(); + m0_stop(); return 0; } diff --git a/plat/rockchip/rk3399/drivers/soc/soc.c b/plat/rockchip/rk3399/drivers/soc/soc.c index d74a6cde9..7131b897f 100644 --- a/plat/rockchip/rk3399/drivers/soc/soc.c +++ b/plat/rockchip/rk3399/drivers/soc/soc.c @@ -34,10 +34,10 @@ #include #include #include +#include #include #include #include -#include #include /* Table of regions to map using the MMU. */ @@ -456,20 +456,6 @@ void __dead2 soc_global_soft_reset(void) ; } -static void soc_m0_init(void) -{ - /* secure config for pmu M0 */ - mmio_write_32(SGRF_BASE + SGRF_PMU_CON(0), WMSK_BIT(7)); - - /* set the execute address for M0 */ - mmio_write_32(SGRF_BASE + SGRF_PMU_CON(3), - BITS_WITH_WMASK((M0_BINCODE_BASE >> 12) & 0xffff, - 0xffff, 0)); - mmio_write_32(SGRF_BASE + SGRF_PMU_CON(7), - BITS_WITH_WMASK((M0_BINCODE_BASE >> 28) & 0xf, - 0xf, 0)); -} - void plat_rockchip_soc_init(void) { secure_timer_init(); @@ -477,7 +463,7 @@ void plat_rockchip_soc_init(void) sgrf_init(); soc_global_soft_reset_init(); plat_rockchip_gpio_init(); - soc_m0_init(); + m0_init(); dram_init(); dram_dfs_init(); } diff --git a/plat/rockchip/rk3399/drivers/soc/soc.h b/plat/rockchip/rk3399/drivers/soc/soc.h index 28590f2b8..371889468 100644 --- a/plat/rockchip/rk3399/drivers/soc/soc.h +++ b/plat/rockchip/rk3399/drivers/soc/soc.h @@ -108,6 +108,16 @@ enum glb_sft_reset { PMU_RST_NOT_BY_SFT = BIT(3), }; +struct pll_div { + uint32_t mhz; + uint32_t refdiv; + uint32_t fbdiv; + uint32_t postdiv1; + uint32_t postdiv2; + uint32_t frac; + uint32_t freq; +}; + struct deepsleep_data_s { uint32_t plls_con[END_PLL_ID][PLL_CON_COUNT]; uint32_t pmucru_clksel_con[PMUCRU_CLKSEL_CONUT]; @@ -312,6 +322,8 @@ struct deepsleep_data_s { #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 PMUCRU_CLKSEL_CON0 0x0080 #define PMUCRU_CLKGATE_CON2 0x0108 diff --git a/plat/rockchip/rk3399/include/shared/m0_param.h b/plat/rockchip/rk3399/include/shared/m0_param.h new file mode 100644 index 000000000..46755e1ed --- /dev/null +++ b/plat/rockchip/rk3399/include/shared/m0_param.h @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of ARM nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __M0_PARAM_H__ +#define __M0_PARAM_H__ + +#ifndef __LINKER__ +enum { + M0_FUNC_SUSPEND = 0, + M0_FUNC_DRAM = 1, +}; +#endif /* __LINKER__ */ + +#define PARAM_ADDR 0xc0 + +#define PARAM_M0_FUNC 0x00 +#define PARAM_DRAM_FREQ 0x04 +#define PARAM_DPLL_CON0 0x08 +#define PARAM_DPLL_CON1 0x0c +#define PARAM_DPLL_CON2 0x10 +#define PARAM_DPLL_CON3 0x14 +#define PARAM_DPLL_CON4 0x18 +#define PARAM_DPLL_CON5 0x1c +#define PARAM_FREQ_SELECT 0x20 +#define PARAM_M0_DONE 0x24 +#define PARAM_M0_SIZE 0x28 +#define M0_DONE_FLAG 0xf59ec39a + +#endif /*__M0_PARAM_H__*/ diff --git a/plat/rockchip/rk3399/plat_sip_calls.c b/plat/rockchip/rk3399/plat_sip_calls.c index ccd723095..7cf3957ed 100644 --- a/plat/rockchip/rk3399/plat_sip_calls.c +++ b/plat/rockchip/rk3399/plat_sip_calls.c @@ -56,9 +56,6 @@ uint32_t ddr_smc_handler(uint64_t arg0, uint64_t arg1, return ddr_round_rate((uint32_t)arg0); case DRAM_GET_RATE: return ddr_get_rate(); - case DRAM_CLR_IRQ: - clr_dcf_irq(); - break; case DRAM_SET_ODT_PD: dram_set_odt_pd(arg0, arg1, arg2); break; diff --git a/plat/rockchip/rk3399/platform.mk b/plat/rockchip/rk3399/platform.mk index ed61e484e..dd23d09f7 100644 --- a/plat/rockchip/rk3399/platform.mk +++ b/plat/rockchip/rk3399/platform.mk @@ -42,6 +42,7 @@ PLAT_INCLUDES := -I${RK_PLAT_COMMON}/ \ -I${RK_PLAT_SOC}/drivers/soc/ \ -I${RK_PLAT_SOC}/drivers/dram/ \ -I${RK_PLAT_SOC}/include/ \ + -I${RK_PLAT_SOC}/include/shared/ \ RK_GIC_SOURCES := drivers/arm/gic/common/gic_common.c \ drivers/arm/gic/v3/gicv3_main.c \ @@ -77,6 +78,7 @@ BL31_SOURCES += ${RK_GIC_SOURCES} \ ${RK_PLAT_SOC}/drivers/gpio/rk3399_gpio.c \ ${RK_PLAT_SOC}/drivers/pmu/pmu.c \ ${RK_PLAT_SOC}/drivers/pmu/pmu_fw.c \ + ${RK_PLAT_SOC}/drivers/pmu/m0_ctl.c \ ${RK_PLAT_SOC}/drivers/pwm/pwm.c \ ${RK_PLAT_SOC}/drivers/soc/soc.c \ ${RK_PLAT_SOC}/drivers/dram/dfs.c \