xref: /rk3399_ARM-atf/plat/rockchip/rk3288/drivers/soc/soc.c (revision 4bd8c929b4bc6e1731c2892b38d4a8c43e8e89dc)
1780e3f24SHeiko Stuebner /*
2780e3f24SHeiko Stuebner  * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
3780e3f24SHeiko Stuebner  *
4780e3f24SHeiko Stuebner  * SPDX-License-Identifier: BSD-3-Clause
5780e3f24SHeiko Stuebner  */
6780e3f24SHeiko Stuebner 
7780e3f24SHeiko Stuebner #include <platform_def.h>
8780e3f24SHeiko Stuebner 
9780e3f24SHeiko Stuebner #include <arch_helpers.h>
10780e3f24SHeiko Stuebner #include <common/debug.h>
11780e3f24SHeiko Stuebner #include <lib/mmio.h>
12780e3f24SHeiko Stuebner 
13780e3f24SHeiko Stuebner #include <plat_private.h>
14780e3f24SHeiko Stuebner #include <rk3288_def.h>
15780e3f24SHeiko Stuebner #include <soc.h>
16780e3f24SHeiko Stuebner #include <secure.h>
17780e3f24SHeiko Stuebner 
18780e3f24SHeiko Stuebner /* sleep data for pll suspend */
19780e3f24SHeiko Stuebner static struct deepsleep_data_s slp_data;
20780e3f24SHeiko Stuebner 
21780e3f24SHeiko Stuebner /* Table of regions to map using the MMU. */
22780e3f24SHeiko Stuebner const mmap_region_t plat_rk_mmap[] = {
23780e3f24SHeiko Stuebner 	MAP_REGION_FLAT(GIC400_BASE, GIC400_SIZE,
24780e3f24SHeiko Stuebner 			MT_DEVICE | MT_RW | MT_SECURE),
25780e3f24SHeiko Stuebner 	MAP_REGION_FLAT(STIME_BASE, STIME_SIZE,
26780e3f24SHeiko Stuebner 			MT_DEVICE | MT_RW | MT_SECURE),
27780e3f24SHeiko Stuebner 	MAP_REGION_FLAT(SGRF_BASE, SGRF_SIZE,
28780e3f24SHeiko Stuebner 			MT_DEVICE | MT_RW | MT_SECURE),
29780e3f24SHeiko Stuebner 	MAP_REGION_FLAT(TZPC_BASE, TZPC_SIZE,
30780e3f24SHeiko Stuebner 			MT_DEVICE | MT_RW | MT_SECURE),
31780e3f24SHeiko Stuebner 	MAP_REGION_FLAT(PMUSRAM_BASE, PMUSRAM_SIZE,
32780e3f24SHeiko Stuebner 			MT_MEMORY | MT_RW | MT_SECURE),
33780e3f24SHeiko Stuebner 	MAP_REGION_FLAT(SRAM_BASE, SRAM_SIZE,
34780e3f24SHeiko Stuebner 			MT_DEVICE | MT_RW | MT_SECURE),
35780e3f24SHeiko Stuebner 	MAP_REGION_FLAT(PMU_BASE, PMU_SIZE,
36780e3f24SHeiko Stuebner 			MT_DEVICE | MT_RW | MT_SECURE),
370957b9b2SChristoph Müllner 	MAP_REGION_FLAT(UART0_BASE, UART0_SIZE,
380957b9b2SChristoph Müllner 			MT_DEVICE | MT_RW | MT_SECURE),
390957b9b2SChristoph Müllner 	MAP_REGION_FLAT(UART1_BASE, UART1_SIZE,
400957b9b2SChristoph Müllner 			MT_DEVICE | MT_RW | MT_SECURE),
410957b9b2SChristoph Müllner 	MAP_REGION_FLAT(UART2_BASE, UART2_SIZE,
420957b9b2SChristoph Müllner 			MT_DEVICE | MT_RW | MT_SECURE),
430957b9b2SChristoph Müllner 	MAP_REGION_FLAT(UART3_BASE, UART3_SIZE,
440957b9b2SChristoph Müllner 			MT_DEVICE | MT_RW | MT_SECURE),
450957b9b2SChristoph Müllner 	MAP_REGION_FLAT(UART4_BASE, UART4_SIZE,
46780e3f24SHeiko Stuebner 			MT_DEVICE | MT_RW | MT_SECURE),
47780e3f24SHeiko Stuebner 	MAP_REGION_FLAT(CRU_BASE, CRU_SIZE,
48780e3f24SHeiko Stuebner 			MT_DEVICE | MT_RW | MT_SECURE),
49780e3f24SHeiko Stuebner 	MAP_REGION_FLAT(GRF_BASE, GRF_SIZE,
50780e3f24SHeiko Stuebner 			MT_DEVICE | MT_RW | MT_SECURE),
51780e3f24SHeiko Stuebner 	MAP_REGION_FLAT(DDR_PCTL0_BASE, DDR_PCTL0_SIZE,
52780e3f24SHeiko Stuebner 			MT_DEVICE | MT_RW | MT_SECURE),
53780e3f24SHeiko Stuebner 	MAP_REGION_FLAT(DDR_PHY0_BASE, DDR_PHY0_SIZE,
54780e3f24SHeiko Stuebner 			MT_DEVICE | MT_RW | MT_SECURE),
55780e3f24SHeiko Stuebner 	MAP_REGION_FLAT(DDR_PCTL1_BASE, DDR_PCTL1_SIZE,
56780e3f24SHeiko Stuebner 			MT_DEVICE | MT_RW | MT_SECURE),
57780e3f24SHeiko Stuebner 	MAP_REGION_FLAT(DDR_PHY1_BASE, DDR_PHY1_SIZE,
58780e3f24SHeiko Stuebner 			MT_DEVICE | MT_RW | MT_SECURE),
59780e3f24SHeiko Stuebner 	MAP_REGION_FLAT(SERVICE_BUS_BASE, SERVICE_BUS_SIZE,
60780e3f24SHeiko Stuebner 			MT_DEVICE | MT_RW | MT_SECURE),
61780e3f24SHeiko Stuebner 	MAP_REGION_FLAT(CORE_AXI_BUS_BASE, CORE_AXI_BUS_SIZE,
62780e3f24SHeiko Stuebner 			MT_DEVICE | MT_RW | MT_SECURE),
63780e3f24SHeiko Stuebner 	{ 0 }
64780e3f24SHeiko Stuebner };
65780e3f24SHeiko Stuebner 
66780e3f24SHeiko Stuebner /* The RockChip power domain tree descriptor */
67780e3f24SHeiko Stuebner const unsigned char rockchip_power_domain_tree_desc[] = {
68780e3f24SHeiko Stuebner 	/* No of root nodes */
69780e3f24SHeiko Stuebner 	PLATFORM_SYSTEM_COUNT,
70780e3f24SHeiko Stuebner 	/* No of children for the root node */
71780e3f24SHeiko Stuebner 	PLATFORM_CLUSTER_COUNT,
72780e3f24SHeiko Stuebner 	/* No of children for the first cluster node */
73780e3f24SHeiko Stuebner 	PLATFORM_CLUSTER0_CORE_COUNT,
74780e3f24SHeiko Stuebner };
75780e3f24SHeiko Stuebner 
plat_rockchip_soc_init(void)76780e3f24SHeiko Stuebner void plat_rockchip_soc_init(void)
77780e3f24SHeiko Stuebner {
78780e3f24SHeiko Stuebner 	secure_timer_init();
79780e3f24SHeiko Stuebner 	secure_sgrf_init();
80780e3f24SHeiko Stuebner 	/*
81780e3f24SHeiko Stuebner 	 * We cannot enable ddr security at this point, as the kernel
82780e3f24SHeiko Stuebner 	 * seems to have an issue with it even living in the same 128MB
83780e3f24SHeiko Stuebner 	 * memory block. Only when moving the kernel to the second
84780e3f24SHeiko Stuebner 	 * 128MB block does it not conflict, but then we'd loose this
85780e3f24SHeiko Stuebner 	 * memory area for use. Late maybe enable
86780e3f24SHeiko Stuebner 	 * secure_sgrf_ddr_rgn_init();
87780e3f24SHeiko Stuebner 	 */
88780e3f24SHeiko Stuebner }
89780e3f24SHeiko Stuebner 
regs_update_bits(uintptr_t addr,uint32_t val,uint32_t mask,uint32_t shift)90780e3f24SHeiko Stuebner void regs_update_bits(uintptr_t addr, uint32_t val,
91780e3f24SHeiko Stuebner 		      uint32_t mask, uint32_t shift)
92780e3f24SHeiko Stuebner {
93780e3f24SHeiko Stuebner 	uint32_t tmp, orig;
94780e3f24SHeiko Stuebner 
95780e3f24SHeiko Stuebner 	orig = mmio_read_32(addr);
96780e3f24SHeiko Stuebner 
97780e3f24SHeiko Stuebner 	tmp = orig & ~(mask << shift);
98780e3f24SHeiko Stuebner 	tmp |= (val & mask) << shift;
99780e3f24SHeiko Stuebner 
100780e3f24SHeiko Stuebner 	if (tmp != orig)
101780e3f24SHeiko Stuebner 		mmio_write_32(addr, tmp);
102780e3f24SHeiko Stuebner 	dsb();
103780e3f24SHeiko Stuebner }
104780e3f24SHeiko Stuebner 
pll_save(uint32_t pll_id)105780e3f24SHeiko Stuebner static void pll_save(uint32_t pll_id)
106780e3f24SHeiko Stuebner {
107780e3f24SHeiko Stuebner 	uint32_t *pll = slp_data.pll_con[pll_id];
108780e3f24SHeiko Stuebner 
109780e3f24SHeiko Stuebner 	pll[0] = mmio_read_32(CRU_BASE + PLL_CONS((pll_id), 0));
110780e3f24SHeiko Stuebner 	pll[1] = mmio_read_32(CRU_BASE + PLL_CONS((pll_id), 1));
111780e3f24SHeiko Stuebner 	pll[2] = mmio_read_32(CRU_BASE + PLL_CONS((pll_id), 2));
112780e3f24SHeiko Stuebner 	pll[3] = mmio_read_32(CRU_BASE + PLL_CONS((pll_id), 3));
113780e3f24SHeiko Stuebner }
114780e3f24SHeiko Stuebner 
clk_plls_suspend(void)115780e3f24SHeiko Stuebner void clk_plls_suspend(void)
116780e3f24SHeiko Stuebner {
117780e3f24SHeiko Stuebner 	pll_save(NPLL_ID);
118780e3f24SHeiko Stuebner 	pll_save(CPLL_ID);
119780e3f24SHeiko Stuebner 	pll_save(GPLL_ID);
120780e3f24SHeiko Stuebner 	pll_save(APLL_ID);
121780e3f24SHeiko Stuebner 	slp_data.pll_mode = mmio_read_32(CRU_BASE + PLL_MODE_CON);
122780e3f24SHeiko Stuebner 
123780e3f24SHeiko Stuebner 	/*
124780e3f24SHeiko Stuebner 	 * Switch PLLs other than DPLL (for SDRAM) to slow mode to
125780e3f24SHeiko Stuebner 	 * avoid crashes on resume. The Mask ROM on the system will
126780e3f24SHeiko Stuebner 	 * put APLL, CPLL, and GPLL into slow mode at resume time
127780e3f24SHeiko Stuebner 	 * anyway (which is why we restore them), but we might not
128780e3f24SHeiko Stuebner 	 * even make it to the Mask ROM if this isn't done at suspend
129780e3f24SHeiko Stuebner 	 * time.
130780e3f24SHeiko Stuebner 	 *
131780e3f24SHeiko Stuebner 	 * NOTE: only APLL truly matters here, but we'll do them all.
132780e3f24SHeiko Stuebner 	 */
133780e3f24SHeiko Stuebner 	mmio_write_32(CRU_BASE + PLL_MODE_CON, 0xf3030000);
134780e3f24SHeiko Stuebner }
135780e3f24SHeiko Stuebner 
clk_plls_resume(void)136780e3f24SHeiko Stuebner void clk_plls_resume(void)
137780e3f24SHeiko Stuebner {
138780e3f24SHeiko Stuebner 	/* restore pll-modes */
139780e3f24SHeiko Stuebner 	mmio_write_32(CRU_BASE + PLL_MODE_CON,
140780e3f24SHeiko Stuebner 		      slp_data.pll_mode | REG_SOC_WMSK);
141780e3f24SHeiko Stuebner }
142780e3f24SHeiko Stuebner 
clk_gate_con_save(void)143780e3f24SHeiko Stuebner void clk_gate_con_save(void)
144780e3f24SHeiko Stuebner {
145780e3f24SHeiko Stuebner 	uint32_t i = 0;
146780e3f24SHeiko Stuebner 
147780e3f24SHeiko Stuebner 	for (i = 0; i < CRU_CLKGATES_CON_CNT; i++)
148780e3f24SHeiko Stuebner 		slp_data.cru_gate_con[i] =
149780e3f24SHeiko Stuebner 			mmio_read_32(CRU_BASE + CRU_CLKGATES_CON(i));
150780e3f24SHeiko Stuebner }
151780e3f24SHeiko Stuebner 
clk_gate_con_disable(void)152780e3f24SHeiko Stuebner void clk_gate_con_disable(void)
153780e3f24SHeiko Stuebner {
154780e3f24SHeiko Stuebner 	uint32_t i;
155780e3f24SHeiko Stuebner 
156780e3f24SHeiko Stuebner 	for (i = 0; i < CRU_CLKGATES_CON_CNT; i++)
157780e3f24SHeiko Stuebner 		mmio_write_32(CRU_BASE + CRU_CLKGATES_CON(i), REG_SOC_WMSK);
158780e3f24SHeiko Stuebner }
159780e3f24SHeiko Stuebner 
clk_gate_con_restore(void)160780e3f24SHeiko Stuebner void clk_gate_con_restore(void)
161780e3f24SHeiko Stuebner {
162780e3f24SHeiko Stuebner 	uint32_t i;
163780e3f24SHeiko Stuebner 
164780e3f24SHeiko Stuebner 	for (i = 0; i < CRU_CLKGATES_CON_CNT; i++)
165780e3f24SHeiko Stuebner 		mmio_write_32(CRU_BASE + CRU_CLKGATES_CON(i),
166780e3f24SHeiko Stuebner 			      REG_SOC_WMSK | slp_data.cru_gate_con[i]);
167780e3f24SHeiko Stuebner }
168780e3f24SHeiko Stuebner 
clk_sel_con_save(void)169780e3f24SHeiko Stuebner void clk_sel_con_save(void)
170780e3f24SHeiko Stuebner {
171780e3f24SHeiko Stuebner 	uint32_t i = 0;
172780e3f24SHeiko Stuebner 
173780e3f24SHeiko Stuebner 	for (i = 0; i < CRU_CLKSELS_CON_CNT; i++)
174780e3f24SHeiko Stuebner 		slp_data.cru_sel_con[i] =
175780e3f24SHeiko Stuebner 			mmio_read_32(CRU_BASE + CRU_CLKSELS_CON(i));
176780e3f24SHeiko Stuebner }
177780e3f24SHeiko Stuebner 
clk_sel_con_restore(void)178780e3f24SHeiko Stuebner void clk_sel_con_restore(void)
179780e3f24SHeiko Stuebner {
180780e3f24SHeiko Stuebner 	uint32_t i, val;
181780e3f24SHeiko Stuebner 
182780e3f24SHeiko Stuebner 	for (i = 0; i < CRU_CLKSELS_CON_CNT; i++) {
183780e3f24SHeiko Stuebner 		/* fractional dividers don't have write-masks */
184780e3f24SHeiko Stuebner 		if ((i >= 7 && i <= 9) ||
185780e3f24SHeiko Stuebner 		    (i >= 17 && i <= 20) ||
186780e3f24SHeiko Stuebner 		    (i == 23) || (i == 41))
187780e3f24SHeiko Stuebner 			val = slp_data.cru_sel_con[i];
188780e3f24SHeiko Stuebner 		else
189780e3f24SHeiko Stuebner 			val = slp_data.cru_sel_con[i] | REG_SOC_WMSK;
190780e3f24SHeiko Stuebner 
191780e3f24SHeiko Stuebner 		mmio_write_32(CRU_BASE + CRU_CLKSELS_CON(i), val);
192780e3f24SHeiko Stuebner 	}
193780e3f24SHeiko Stuebner }
194780e3f24SHeiko Stuebner 
rockchip_soc_soft_reset(void)195780e3f24SHeiko Stuebner void __dead2 rockchip_soc_soft_reset(void)
196780e3f24SHeiko Stuebner {
197780e3f24SHeiko Stuebner 	uint32_t temp_val;
198780e3f24SHeiko Stuebner 
199780e3f24SHeiko Stuebner 	/*
200780e3f24SHeiko Stuebner 	 * Switch PLLs other than DPLL (for SDRAM) to slow mode to
201780e3f24SHeiko Stuebner 	 * avoid crashes on resume. The Mask ROM on the system will
202780e3f24SHeiko Stuebner 	 * put APLL, CPLL, and GPLL into slow mode at resume time
203780e3f24SHeiko Stuebner 	 * anyway (which is why we restore them), but we might not
204780e3f24SHeiko Stuebner 	 * even make it to the Mask ROM if this isn't done at suspend
205780e3f24SHeiko Stuebner 	 * time.
206780e3f24SHeiko Stuebner 	 *
207780e3f24SHeiko Stuebner 	 * NOTE: only APLL truly matters here, but we'll do them all.
208780e3f24SHeiko Stuebner 	 */
209780e3f24SHeiko Stuebner 	mmio_write_32(CRU_BASE + PLL_MODE_CON, 0xf3030000);
210780e3f24SHeiko Stuebner 
211780e3f24SHeiko Stuebner 	temp_val = mmio_read_32(CRU_BASE + CRU_GLB_RST_CON);
212780e3f24SHeiko Stuebner 	temp_val &= ~PMU_RST_MASK;
213780e3f24SHeiko Stuebner 	temp_val |= PMU_RST_BY_SECOND_SFT;
214780e3f24SHeiko Stuebner 	mmio_write_32(CRU_BASE + CRU_GLB_RST_CON, temp_val);
215780e3f24SHeiko Stuebner 	mmio_write_32(CRU_BASE + CRU_GLB_SRST_SND, 0xeca8);
216780e3f24SHeiko Stuebner 
217780e3f24SHeiko Stuebner 	/*
218780e3f24SHeiko Stuebner 	 * Maybe the HW needs some times to reset the system,
219*1b491eeaSElyes Haouas 	 * so we do not hope the core to execute valid codes.
220780e3f24SHeiko Stuebner 	 */
221780e3f24SHeiko Stuebner 	while (1)
222780e3f24SHeiko Stuebner 		;
223780e3f24SHeiko Stuebner }
224