xref: /rk3399_ARM-atf/plat/rockchip/rk3399/drivers/soc/soc.c (revision a109ec92344fa443e39cc77c8b3de4527b8c1c4c)
16fba6e04STony Xie /*
26fba6e04STony Xie  * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
36fba6e04STony Xie  *
482cb2c1aSdp-arm  * SPDX-License-Identifier: BSD-3-Clause
56fba6e04STony Xie  */
66fba6e04STony Xie 
76fba6e04STony Xie #include <arch_helpers.h>
8941c7147SXing Zheng #include <assert.h>
96fba6e04STony Xie #include <debug.h>
106fba6e04STony Xie #include <delay_timer.h>
11f91b969cSDerek Basehore #include <dfs.h>
12f91b969cSDerek Basehore #include <dram.h>
13977001aaSXing Zheng #include <m0_ctl.h>
14ee1ebbd1SIsla Mitchell #include <mmio.h>
156fba6e04STony Xie #include <plat_private.h>
16ee1ebbd1SIsla Mitchell #include <platform_def.h>
176fba6e04STony Xie #include <rk3399_def.h>
18e3525114SXing Zheng #include <secure.h>
196fba6e04STony Xie #include <soc.h>
206fba6e04STony Xie 
216fba6e04STony Xie /* Table of regions to map using the MMU.  */
226fba6e04STony Xie const mmap_region_t plat_rk_mmap[] = {
231830f790SXing Zheng 	MAP_REGION_FLAT(DEV_RNG0_BASE, DEV_RNG0_SIZE,
249ec78bdfSTony Xie 			MT_DEVICE | MT_RW | MT_SECURE),
254c127e68SCaesar Wang 	MAP_REGION_FLAT(PMUSRAM_BASE, PMUSRAM_SIZE,
264c127e68SCaesar Wang 			MT_MEMORY | MT_RW | MT_SECURE),
279ec78bdfSTony Xie 
286fba6e04STony Xie 	{ 0 }
296fba6e04STony Xie };
306fba6e04STony Xie 
316fba6e04STony Xie /* The RockChip power domain tree descriptor */
326fba6e04STony Xie const unsigned char rockchip_power_domain_tree_desc[] = {
336fba6e04STony Xie 	/* No of root nodes */
346fba6e04STony Xie 	PLATFORM_SYSTEM_COUNT,
356fba6e04STony Xie 	/* No of children for the root node */
366fba6e04STony Xie 	PLATFORM_CLUSTER_COUNT,
376fba6e04STony Xie 	/* No of children for the first cluster node */
386fba6e04STony Xie 	PLATFORM_CLUSTER0_CORE_COUNT,
396fba6e04STony Xie 	/* No of children for the second cluster node */
406fba6e04STony Xie 	PLATFORM_CLUSTER1_CORE_COUNT
416fba6e04STony Xie };
426fba6e04STony Xie 
43e3525114SXing Zheng /* sleep data for pll suspend */
44e3525114SXing Zheng static struct deepsleep_data_s slp_data;
45941c7147SXing Zheng 
466fba6e04STony Xie static void set_pll_slow_mode(uint32_t pll_id)
476fba6e04STony Xie {
486fba6e04STony Xie 	if (pll_id == PPLL_ID)
496fba6e04STony Xie 		mmio_write_32(PMUCRU_BASE + PMUCRU_PPLL_CON(3), PLL_SLOW_MODE);
506fba6e04STony Xie 	else
516fba6e04STony Xie 		mmio_write_32((CRU_BASE +
526fba6e04STony Xie 			      CRU_PLL_CON(pll_id, 3)), PLL_SLOW_MODE);
536fba6e04STony Xie }
546fba6e04STony Xie 
556fba6e04STony Xie static void set_pll_normal_mode(uint32_t pll_id)
566fba6e04STony Xie {
576fba6e04STony Xie 	if (pll_id == PPLL_ID)
586fba6e04STony Xie 		mmio_write_32(PMUCRU_BASE + PMUCRU_PPLL_CON(3), PLL_NOMAL_MODE);
596fba6e04STony Xie 	else
606fba6e04STony Xie 		mmio_write_32(CRU_BASE +
616fba6e04STony Xie 			      CRU_PLL_CON(pll_id, 3), PLL_NOMAL_MODE);
626fba6e04STony Xie }
636fba6e04STony Xie 
646fba6e04STony Xie static void set_pll_bypass(uint32_t pll_id)
656fba6e04STony Xie {
666fba6e04STony Xie 	if (pll_id == PPLL_ID)
676fba6e04STony Xie 		mmio_write_32(PMUCRU_BASE +
686fba6e04STony Xie 			      PMUCRU_PPLL_CON(3), PLL_BYPASS_MODE);
696fba6e04STony Xie 	else
706fba6e04STony Xie 		mmio_write_32(CRU_BASE +
716fba6e04STony Xie 			      CRU_PLL_CON(pll_id, 3), PLL_BYPASS_MODE);
726fba6e04STony Xie }
736fba6e04STony Xie 
746fba6e04STony Xie static void _pll_suspend(uint32_t pll_id)
756fba6e04STony Xie {
766fba6e04STony Xie 	set_pll_slow_mode(pll_id);
776fba6e04STony Xie 	set_pll_bypass(pll_id);
786fba6e04STony Xie }
796fba6e04STony Xie 
804c127e68SCaesar Wang /**
814c127e68SCaesar Wang  * disable_dvfs_plls - To suspend the specific PLLs
824c127e68SCaesar Wang  *
834c127e68SCaesar Wang  * When we close the center logic, the DPLL will be closed,
844c127e68SCaesar Wang  * so we need to keep the ABPLL and switch to it to supply
854c127e68SCaesar Wang  * clock for DDR during suspend, then we should not close
864c127e68SCaesar Wang  * the ABPLL and exclude ABPLL_ID.
874c127e68SCaesar Wang  */
885d3b1067SCaesar Wang void disable_dvfs_plls(void)
895d3b1067SCaesar Wang {
905d3b1067SCaesar Wang 	_pll_suspend(CPLL_ID);
915d3b1067SCaesar Wang 	_pll_suspend(NPLL_ID);
925d3b1067SCaesar Wang 	_pll_suspend(VPLL_ID);
935d3b1067SCaesar Wang 	_pll_suspend(GPLL_ID);
945d3b1067SCaesar Wang 	_pll_suspend(ALPLL_ID);
955d3b1067SCaesar Wang }
965d3b1067SCaesar Wang 
974c127e68SCaesar Wang /**
984c127e68SCaesar Wang  * disable_nodvfs_plls - To suspend the PPLL
994c127e68SCaesar Wang  */
1005d3b1067SCaesar Wang void disable_nodvfs_plls(void)
1015d3b1067SCaesar Wang {
1025d3b1067SCaesar Wang 	_pll_suspend(PPLL_ID);
1035d3b1067SCaesar Wang }
1045d3b1067SCaesar Wang 
1054c127e68SCaesar Wang /**
1064c127e68SCaesar Wang  * restore_pll - Copy PLL settings from memory to a PLL.
1074c127e68SCaesar Wang  *
1084c127e68SCaesar Wang  * This will copy PLL settings from an array in memory to the memory mapped
1094c127e68SCaesar Wang  * registers for a PLL.
1104c127e68SCaesar Wang  *
1114c127e68SCaesar Wang  * Note that: above the PLL exclude PPLL.
1124c127e68SCaesar Wang  *
1134c127e68SCaesar Wang  * pll_id: One of the values from enum plls_id
1144c127e68SCaesar Wang  * src: Pointer to the array of values to restore from
1154c127e68SCaesar Wang  */
1164c127e68SCaesar Wang static void restore_pll(int pll_id, uint32_t *src)
1174c127e68SCaesar Wang {
1184c127e68SCaesar Wang 	/* Nice to have PLL off while configuring */
1194c127e68SCaesar Wang 	mmio_write_32((CRU_BASE + CRU_PLL_CON(pll_id, 3)), PLL_SLOW_MODE);
1204c127e68SCaesar Wang 
1214c127e68SCaesar Wang 	mmio_write_32(CRU_BASE + CRU_PLL_CON(pll_id, 0), src[0] | REG_SOC_WMSK);
1224c127e68SCaesar Wang 	mmio_write_32(CRU_BASE + CRU_PLL_CON(pll_id, 1), src[1] | REG_SOC_WMSK);
1234c127e68SCaesar Wang 	mmio_write_32(CRU_BASE + CRU_PLL_CON(pll_id, 2), src[2]);
1244c127e68SCaesar Wang 	mmio_write_32(CRU_BASE + CRU_PLL_CON(pll_id, 4), src[4] | REG_SOC_WMSK);
1254c127e68SCaesar Wang 	mmio_write_32(CRU_BASE + CRU_PLL_CON(pll_id, 5), src[5] | REG_SOC_WMSK);
1264c127e68SCaesar Wang 
1274c127e68SCaesar Wang 	/* Do PLL_CON3 since that will enable things */
1284c127e68SCaesar Wang 	mmio_write_32(CRU_BASE + CRU_PLL_CON(pll_id, 3), src[3] | REG_SOC_WMSK);
1294c127e68SCaesar Wang 
1304c127e68SCaesar Wang 	/* Wait for PLL lock done */
1314c127e68SCaesar Wang 	while ((mmio_read_32(CRU_BASE + CRU_PLL_CON(pll_id, 2)) &
1324c127e68SCaesar Wang 		0x80000000) == 0x0)
1334c127e68SCaesar Wang 		;
1344c127e68SCaesar Wang }
1354c127e68SCaesar Wang 
1364c127e68SCaesar Wang /**
1374c127e68SCaesar Wang  * save_pll - Copy PLL settings a PLL to memory
1384c127e68SCaesar Wang  *
1394c127e68SCaesar Wang  * This will copy PLL settings from the memory mapped registers for a PLL to
1404c127e68SCaesar Wang  * an array in memory.
1414c127e68SCaesar Wang  *
1424c127e68SCaesar Wang  * Note that: above the PLL exclude PPLL.
1434c127e68SCaesar Wang  *
1444c127e68SCaesar Wang  * pll_id: One of the values from enum plls_id
1454c127e68SCaesar Wang  * src: Pointer to the array of values to save to.
1464c127e68SCaesar Wang  */
1474c127e68SCaesar Wang static void save_pll(uint32_t *dst, int pll_id)
1484c127e68SCaesar Wang {
1494c127e68SCaesar Wang 	int i;
1504c127e68SCaesar Wang 
1514c127e68SCaesar Wang 	for (i = 0; i < PLL_CON_COUNT; i++)
1524c127e68SCaesar Wang 		dst[i] = mmio_read_32(CRU_BASE + CRU_PLL_CON(pll_id, i));
1534c127e68SCaesar Wang }
1544c127e68SCaesar Wang 
1554c127e68SCaesar Wang /**
1564c127e68SCaesar Wang  * prepare_abpll_for_ddrctrl - Copy DPLL settings to ABPLL
1574c127e68SCaesar Wang  *
1584c127e68SCaesar Wang  * This will copy DPLL settings from the memory mapped registers for a PLL to
1594c127e68SCaesar Wang  * an array in memory.
1604c127e68SCaesar Wang  */
1614c127e68SCaesar Wang void prepare_abpll_for_ddrctrl(void)
1624c127e68SCaesar Wang {
1634c127e68SCaesar Wang 	save_pll(slp_data.plls_con[ABPLL_ID], ABPLL_ID);
1644c127e68SCaesar Wang 	save_pll(slp_data.plls_con[DPLL_ID], DPLL_ID);
1654c127e68SCaesar Wang 
1664c127e68SCaesar Wang 	restore_pll(ABPLL_ID, slp_data.plls_con[DPLL_ID]);
1674c127e68SCaesar Wang }
1684c127e68SCaesar Wang 
1694c127e68SCaesar Wang void restore_abpll(void)
1704c127e68SCaesar Wang {
1714c127e68SCaesar Wang 	restore_pll(ABPLL_ID, slp_data.plls_con[ABPLL_ID]);
1724c127e68SCaesar Wang }
1734c127e68SCaesar Wang 
1749ec78bdfSTony Xie void clk_gate_con_save(void)
1759ec78bdfSTony Xie {
1769ec78bdfSTony Xie 	uint32_t i = 0;
1779ec78bdfSTony Xie 
1789ec78bdfSTony Xie 	for (i = 0; i < PMUCRU_GATE_COUNT; i++)
1799ec78bdfSTony Xie 		slp_data.pmucru_gate_con[i] =
1809ec78bdfSTony Xie 			mmio_read_32(PMUCRU_BASE + PMUCRU_GATE_CON(i));
1819ec78bdfSTony Xie 
1829ec78bdfSTony Xie 	for (i = 0; i < CRU_GATE_COUNT; i++)
1839ec78bdfSTony Xie 		slp_data.cru_gate_con[i] =
1849ec78bdfSTony Xie 			mmio_read_32(CRU_BASE + CRU_GATE_CON(i));
1859ec78bdfSTony Xie }
1869ec78bdfSTony Xie 
1879ec78bdfSTony Xie void clk_gate_con_disable(void)
1889ec78bdfSTony Xie {
1899ec78bdfSTony Xie 	uint32_t i;
1909ec78bdfSTony Xie 
1919ec78bdfSTony Xie 	for (i = 0; i < PMUCRU_GATE_COUNT; i++)
1929ec78bdfSTony Xie 		mmio_write_32(PMUCRU_BASE + PMUCRU_GATE_CON(i), REG_SOC_WMSK);
1939ec78bdfSTony Xie 
1949ec78bdfSTony Xie 	for (i = 0; i < CRU_GATE_COUNT; i++)
1959ec78bdfSTony Xie 		mmio_write_32(CRU_BASE + CRU_GATE_CON(i), REG_SOC_WMSK);
1969ec78bdfSTony Xie }
1979ec78bdfSTony Xie 
1989ec78bdfSTony Xie void clk_gate_con_restore(void)
1999ec78bdfSTony Xie {
2009ec78bdfSTony Xie 	uint32_t i;
2019ec78bdfSTony Xie 
2029ec78bdfSTony Xie 	for (i = 0; i < PMUCRU_GATE_COUNT; i++)
2039ec78bdfSTony Xie 		mmio_write_32(PMUCRU_BASE + PMUCRU_GATE_CON(i),
2049ec78bdfSTony Xie 			      REG_SOC_WMSK | slp_data.pmucru_gate_con[i]);
2059ec78bdfSTony Xie 
2069ec78bdfSTony Xie 	for (i = 0; i < CRU_GATE_COUNT; i++)
2079ec78bdfSTony Xie 		mmio_write_32(CRU_BASE + CRU_GATE_CON(i),
2089ec78bdfSTony Xie 			      REG_SOC_WMSK | slp_data.cru_gate_con[i]);
2099ec78bdfSTony Xie }
2109ec78bdfSTony Xie 
2116fba6e04STony Xie static void set_plls_nobypass(uint32_t pll_id)
2126fba6e04STony Xie {
2136fba6e04STony Xie 	if (pll_id == PPLL_ID)
2146fba6e04STony Xie 		mmio_write_32(PMUCRU_BASE + PMUCRU_PPLL_CON(3),
2156fba6e04STony Xie 			      PLL_NO_BYPASS_MODE);
2166fba6e04STony Xie 	else
2176fba6e04STony Xie 		mmio_write_32(CRU_BASE + CRU_PLL_CON(pll_id, 3),
2186fba6e04STony Xie 			      PLL_NO_BYPASS_MODE);
2196fba6e04STony Xie }
2206fba6e04STony Xie 
2215d3b1067SCaesar Wang static void _pll_resume(uint32_t pll_id)
2225d3b1067SCaesar Wang {
2235d3b1067SCaesar Wang 	set_plls_nobypass(pll_id);
2245d3b1067SCaesar Wang 	set_pll_normal_mode(pll_id);
2255d3b1067SCaesar Wang }
2265d3b1067SCaesar Wang 
227*a109ec92SLin Huang void set_pmu_rsthold(void)
228*a109ec92SLin Huang {
229*a109ec92SLin Huang 	uint32_t rstnhold_cofig0;
230*a109ec92SLin Huang 	uint32_t rstnhold_cofig1;
231*a109ec92SLin Huang 
232*a109ec92SLin Huang 	slp_data.pmucru_rstnhold_con0 = mmio_read_32(PMUCRU_BASE +
233*a109ec92SLin Huang 					    PMUCRU_RSTNHOLD_CON0);
234*a109ec92SLin Huang 	slp_data.pmucru_rstnhold_con1 = mmio_read_32(PMUCRU_BASE +
235*a109ec92SLin Huang 					    PMUCRU_RSTNHOLD_CON1);
236*a109ec92SLin Huang 	rstnhold_cofig0 = BIT_WITH_WMSK(PRESETN_NOC_PMU_HOLD) |
237*a109ec92SLin Huang 			  BIT_WITH_WMSK(PRESETN_INTMEM_PMU_HOLD) |
238*a109ec92SLin Huang 			  BIT_WITH_WMSK(HRESETN_CM0S_PMU_HOLD) |
239*a109ec92SLin Huang 			  BIT_WITH_WMSK(HRESETN_CM0S_NOC_PMU_HOLD) |
240*a109ec92SLin Huang 			  BIT_WITH_WMSK(DRESETN_CM0S_PMU_HOLD) |
241*a109ec92SLin Huang 			  BIT_WITH_WMSK(POESETN_CM0S_PMU_HOLD) |
242*a109ec92SLin Huang 			  BIT_WITH_WMSK(PRESETN_TIMER_PMU_0_1_HOLD) |
243*a109ec92SLin Huang 			  BIT_WITH_WMSK(RESETN_TIMER_PMU_0_HOLD) |
244*a109ec92SLin Huang 			  BIT_WITH_WMSK(RESETN_TIMER_PMU_1_HOLD) |
245*a109ec92SLin Huang 			  BIT_WITH_WMSK(PRESETN_UART_M0_PMU_HOLD) |
246*a109ec92SLin Huang 			  BIT_WITH_WMSK(RESETN_UART_M0_PMU_HOLD) |
247*a109ec92SLin Huang 			  BIT_WITH_WMSK(PRESETN_WDT_PMU_HOLD);
248*a109ec92SLin Huang 	rstnhold_cofig1 = BIT_WITH_WMSK(PRESETN_RKPWM_PMU_HOLD) |
249*a109ec92SLin Huang 			  BIT_WITH_WMSK(PRESETN_PMUGRF_HOLD) |
250*a109ec92SLin Huang 			  BIT_WITH_WMSK(PRESETN_SGRF_HOLD) |
251*a109ec92SLin Huang 			  BIT_WITH_WMSK(PRESETN_GPIO0_HOLD) |
252*a109ec92SLin Huang 			  BIT_WITH_WMSK(PRESETN_GPIO1_HOLD) |
253*a109ec92SLin Huang 			  BIT_WITH_WMSK(PRESETN_CRU_PMU_HOLD) |
254*a109ec92SLin Huang 			  BIT_WITH_WMSK(PRESETN_PVTM_PMU_HOLD);
255*a109ec92SLin Huang 
256*a109ec92SLin Huang 	mmio_write_32(PMUCRU_BASE + PMUCRU_RSTNHOLD_CON0, rstnhold_cofig0);
257*a109ec92SLin Huang 	mmio_write_32(PMUCRU_BASE + PMUCRU_RSTNHOLD_CON1, rstnhold_cofig1);
258*a109ec92SLin Huang }
259*a109ec92SLin Huang 
260*a109ec92SLin Huang void restore_pmu_rsthold(void)
261*a109ec92SLin Huang {
262*a109ec92SLin Huang 	mmio_write_32(PMUCRU_BASE + PMUCRU_RSTNHOLD_CON0,
263*a109ec92SLin Huang 		      slp_data.pmucru_rstnhold_con0 | REG_SOC_WMSK);
264*a109ec92SLin Huang 	mmio_write_32(PMUCRU_BASE + PMUCRU_RSTNHOLD_CON1,
265*a109ec92SLin Huang 		      slp_data.pmucru_rstnhold_con1 | REG_SOC_WMSK);
266*a109ec92SLin Huang }
267*a109ec92SLin Huang 
2684c127e68SCaesar Wang /**
2694c127e68SCaesar Wang  * enable_dvfs_plls - To resume the specific PLLs
2704c127e68SCaesar Wang  *
2714c127e68SCaesar Wang  * Please see the comment at the disable_dvfs_plls()
2724c127e68SCaesar Wang  * we don't suspend the ABPLL, so don't need resume
2734c127e68SCaesar Wang  * it too.
2744c127e68SCaesar Wang  */
2755d3b1067SCaesar Wang void enable_dvfs_plls(void)
2766fba6e04STony Xie {
2775d3b1067SCaesar Wang 	_pll_resume(ALPLL_ID);
2785d3b1067SCaesar Wang 	_pll_resume(GPLL_ID);
2795d3b1067SCaesar Wang 	_pll_resume(VPLL_ID);
2805d3b1067SCaesar Wang 	_pll_resume(NPLL_ID);
2815d3b1067SCaesar Wang 	_pll_resume(CPLL_ID);
2826fba6e04STony Xie }
2835d3b1067SCaesar Wang 
2844c127e68SCaesar Wang /**
2854c127e68SCaesar Wang  * enable_nodvfs_plls - To resume the PPLL
2864c127e68SCaesar Wang  */
2875d3b1067SCaesar Wang void enable_nodvfs_plls(void)
2885d3b1067SCaesar Wang {
2895d3b1067SCaesar Wang 	_pll_resume(PPLL_ID);
2906fba6e04STony Xie }
2916fba6e04STony Xie 
2926fba6e04STony Xie void soc_global_soft_reset_init(void)
2936fba6e04STony Xie {
2946fba6e04STony Xie 	mmio_write_32(PMUCRU_BASE + CRU_PMU_RSTHOLD_CON(1),
2956fba6e04STony Xie 		      CRU_PMU_SGRF_RST_RLS);
296f47a25ddSCaesar Wang 
297f47a25ddSCaesar Wang 	mmio_clrbits_32(CRU_BASE + CRU_GLB_RST_CON,
298f47a25ddSCaesar Wang 			CRU_PMU_WDTRST_MSK | CRU_PMU_FIRST_SFTRST_MSK);
2996fba6e04STony Xie }
3006fba6e04STony Xie 
3016fba6e04STony Xie void __dead2 soc_global_soft_reset(void)
3026fba6e04STony Xie {
3036fba6e04STony Xie 	set_pll_slow_mode(VPLL_ID);
3046fba6e04STony Xie 	set_pll_slow_mode(NPLL_ID);
3056fba6e04STony Xie 	set_pll_slow_mode(GPLL_ID);
3066fba6e04STony Xie 	set_pll_slow_mode(CPLL_ID);
3076fba6e04STony Xie 	set_pll_slow_mode(PPLL_ID);
3086fba6e04STony Xie 	set_pll_slow_mode(ABPLL_ID);
3096fba6e04STony Xie 	set_pll_slow_mode(ALPLL_ID);
310f47a25ddSCaesar Wang 
311f47a25ddSCaesar Wang 	dsb();
312f47a25ddSCaesar Wang 
3136fba6e04STony Xie 	mmio_write_32(CRU_BASE + CRU_GLB_SRST_FST, GLB_SRST_FST_CFG_VAL);
3146fba6e04STony Xie 
3156fba6e04STony Xie 	/*
3166fba6e04STony Xie 	 * Maybe the HW needs some times to reset the system,
3176fba6e04STony Xie 	 * so we do not hope the core to excute valid codes.
3186fba6e04STony Xie 	 */
3196fba6e04STony Xie 	while (1)
3206fba6e04STony Xie 		;
3216fba6e04STony Xie }
3226fba6e04STony Xie 
3236fba6e04STony Xie void plat_rockchip_soc_init(void)
3246fba6e04STony Xie {
3256fba6e04STony Xie 	secure_timer_init();
326e3525114SXing Zheng 	secure_sgrf_init();
327941c7147SXing Zheng 	secure_sgrf_ddr_rgn_init();
3286fba6e04STony Xie 	soc_global_soft_reset_init();
3299901dcf6SCaesar Wang 	plat_rockchip_gpio_init();
330977001aaSXing Zheng 	m0_init();
331613038bcSCaesar Wang 	dram_init();
332f91b969cSDerek Basehore 	dram_dfs_init();
3336fba6e04STony Xie }
334