blob: 993b80ad4833428358e6190bad0bd94dc8dc434a [file] [log] [blame]
Tony Xief6118cc2016-01-15 17:17:32 +08001/*
2 * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
3 *
dp-armfa3cf0b2017-05-03 09:38:09 +01004 * SPDX-License-Identifier: BSD-3-Clause
Tony Xief6118cc2016-01-15 17:17:32 +08005 */
6
7#include <arch_helpers.h>
Xing Zheng5e1e48f2017-02-24 14:47:51 +08008#include <assert.h>
Tony Xief6118cc2016-01-15 17:17:32 +08009#include <debug.h>
10#include <delay_timer.h>
Derek Basehoreff461d02016-10-20 20:46:43 -070011#include <dfs.h>
12#include <dram.h>
Xing Zheng93280b72016-10-26 21:25:26 +080013#include <m0_ctl.h>
Isla Mitchelle3631462017-07-14 10:46:32 +010014#include <mmio.h>
Tony Xief6118cc2016-01-15 17:17:32 +080015#include <plat_private.h>
Isla Mitchelle3631462017-07-14 10:46:32 +010016#include <platform_def.h>
Tony Xief6118cc2016-01-15 17:17:32 +080017#include <rk3399_def.h>
Xing Zheng22a98712017-02-24 14:56:41 +080018#include <secure.h>
Tony Xief6118cc2016-01-15 17:17:32 +080019#include <soc.h>
20
21/* Table of regions to map using the MMU. */
22const mmap_region_t plat_rk_mmap[] = {
Xing Zhengb4bcc1d2017-02-24 16:26:11 +080023 MAP_REGION_FLAT(DEV_RNG0_BASE, DEV_RNG0_SIZE,
Tony Xie42e113e2016-07-16 11:16:51 +080024 MT_DEVICE | MT_RW | MT_SECURE),
Caesar Wang5339d182016-10-27 01:13:34 +080025 MAP_REGION_FLAT(PMUSRAM_BASE, PMUSRAM_SIZE,
26 MT_MEMORY | MT_RW | MT_SECURE),
Tony Xie42e113e2016-07-16 11:16:51 +080027
Tony Xief6118cc2016-01-15 17:17:32 +080028 { 0 }
29};
30
31/* The RockChip power domain tree descriptor */
32const unsigned char rockchip_power_domain_tree_desc[] = {
33 /* No of root nodes */
34 PLATFORM_SYSTEM_COUNT,
35 /* No of children for the root node */
36 PLATFORM_CLUSTER_COUNT,
37 /* No of children for the first cluster node */
38 PLATFORM_CLUSTER0_CORE_COUNT,
39 /* No of children for the second cluster node */
40 PLATFORM_CLUSTER1_CORE_COUNT
41};
42
Xing Zheng22a98712017-02-24 14:56:41 +080043/* sleep data for pll suspend */
44static struct deepsleep_data_s slp_data;
Xing Zheng5e1e48f2017-02-24 14:47:51 +080045
Tony Xief6118cc2016-01-15 17:17:32 +080046static void set_pll_slow_mode(uint32_t pll_id)
47{
48 if (pll_id == PPLL_ID)
49 mmio_write_32(PMUCRU_BASE + PMUCRU_PPLL_CON(3), PLL_SLOW_MODE);
50 else
51 mmio_write_32((CRU_BASE +
52 CRU_PLL_CON(pll_id, 3)), PLL_SLOW_MODE);
53}
54
55static void set_pll_normal_mode(uint32_t pll_id)
56{
57 if (pll_id == PPLL_ID)
58 mmio_write_32(PMUCRU_BASE + PMUCRU_PPLL_CON(3), PLL_NOMAL_MODE);
59 else
60 mmio_write_32(CRU_BASE +
61 CRU_PLL_CON(pll_id, 3), PLL_NOMAL_MODE);
62}
63
64static void set_pll_bypass(uint32_t pll_id)
65{
66 if (pll_id == PPLL_ID)
67 mmio_write_32(PMUCRU_BASE +
68 PMUCRU_PPLL_CON(3), PLL_BYPASS_MODE);
69 else
70 mmio_write_32(CRU_BASE +
71 CRU_PLL_CON(pll_id, 3), PLL_BYPASS_MODE);
72}
73
74static void _pll_suspend(uint32_t pll_id)
75{
76 set_pll_slow_mode(pll_id);
77 set_pll_bypass(pll_id);
78}
79
Caesar Wang5339d182016-10-27 01:13:34 +080080/**
81 * disable_dvfs_plls - To suspend the specific PLLs
82 *
83 * When we close the center logic, the DPLL will be closed,
84 * so we need to keep the ABPLL and switch to it to supply
85 * clock for DDR during suspend, then we should not close
86 * the ABPLL and exclude ABPLL_ID.
87 */
Caesar Wanged6b9a52016-08-11 02:11:45 +080088void disable_dvfs_plls(void)
89{
90 _pll_suspend(CPLL_ID);
91 _pll_suspend(NPLL_ID);
92 _pll_suspend(VPLL_ID);
93 _pll_suspend(GPLL_ID);
Caesar Wanged6b9a52016-08-11 02:11:45 +080094 _pll_suspend(ALPLL_ID);
95}
96
Caesar Wang5339d182016-10-27 01:13:34 +080097/**
98 * disable_nodvfs_plls - To suspend the PPLL
99 */
Caesar Wanged6b9a52016-08-11 02:11:45 +0800100void disable_nodvfs_plls(void)
101{
102 _pll_suspend(PPLL_ID);
103}
104
Caesar Wang5339d182016-10-27 01:13:34 +0800105/**
106 * restore_pll - Copy PLL settings from memory to a PLL.
107 *
108 * This will copy PLL settings from an array in memory to the memory mapped
109 * registers for a PLL.
110 *
111 * Note that: above the PLL exclude PPLL.
112 *
113 * pll_id: One of the values from enum plls_id
114 * src: Pointer to the array of values to restore from
115 */
116static void restore_pll(int pll_id, uint32_t *src)
117{
118 /* Nice to have PLL off while configuring */
119 mmio_write_32((CRU_BASE + CRU_PLL_CON(pll_id, 3)), PLL_SLOW_MODE);
120
121 mmio_write_32(CRU_BASE + CRU_PLL_CON(pll_id, 0), src[0] | REG_SOC_WMSK);
122 mmio_write_32(CRU_BASE + CRU_PLL_CON(pll_id, 1), src[1] | REG_SOC_WMSK);
123 mmio_write_32(CRU_BASE + CRU_PLL_CON(pll_id, 2), src[2]);
124 mmio_write_32(CRU_BASE + CRU_PLL_CON(pll_id, 4), src[4] | REG_SOC_WMSK);
125 mmio_write_32(CRU_BASE + CRU_PLL_CON(pll_id, 5), src[5] | REG_SOC_WMSK);
126
127 /* Do PLL_CON3 since that will enable things */
128 mmio_write_32(CRU_BASE + CRU_PLL_CON(pll_id, 3), src[3] | REG_SOC_WMSK);
129
130 /* Wait for PLL lock done */
131 while ((mmio_read_32(CRU_BASE + CRU_PLL_CON(pll_id, 2)) &
132 0x80000000) == 0x0)
133 ;
134}
135
136/**
137 * save_pll - Copy PLL settings a PLL to memory
138 *
139 * This will copy PLL settings from the memory mapped registers for a PLL to
140 * an array in memory.
141 *
142 * Note that: above the PLL exclude PPLL.
143 *
144 * pll_id: One of the values from enum plls_id
145 * src: Pointer to the array of values to save to.
146 */
147static void save_pll(uint32_t *dst, int pll_id)
148{
149 int i;
150
151 for (i = 0; i < PLL_CON_COUNT; i++)
152 dst[i] = mmio_read_32(CRU_BASE + CRU_PLL_CON(pll_id, i));
153}
154
155/**
156 * prepare_abpll_for_ddrctrl - Copy DPLL settings to ABPLL
157 *
158 * This will copy DPLL settings from the memory mapped registers for a PLL to
159 * an array in memory.
160 */
161void prepare_abpll_for_ddrctrl(void)
162{
163 save_pll(slp_data.plls_con[ABPLL_ID], ABPLL_ID);
164 save_pll(slp_data.plls_con[DPLL_ID], DPLL_ID);
165
166 restore_pll(ABPLL_ID, slp_data.plls_con[DPLL_ID]);
167}
168
169void restore_abpll(void)
170{
171 restore_pll(ABPLL_ID, slp_data.plls_con[ABPLL_ID]);
172}
173
174void restore_dpll(void)
175{
176 restore_pll(DPLL_ID, slp_data.plls_con[DPLL_ID]);
177}
178
Tony Xie42e113e2016-07-16 11:16:51 +0800179void clk_gate_con_save(void)
180{
181 uint32_t i = 0;
182
183 for (i = 0; i < PMUCRU_GATE_COUNT; i++)
184 slp_data.pmucru_gate_con[i] =
185 mmio_read_32(PMUCRU_BASE + PMUCRU_GATE_CON(i));
186
187 for (i = 0; i < CRU_GATE_COUNT; i++)
188 slp_data.cru_gate_con[i] =
189 mmio_read_32(CRU_BASE + CRU_GATE_CON(i));
190}
191
192void clk_gate_con_disable(void)
193{
194 uint32_t i;
195
196 for (i = 0; i < PMUCRU_GATE_COUNT; i++)
197 mmio_write_32(PMUCRU_BASE + PMUCRU_GATE_CON(i), REG_SOC_WMSK);
198
199 for (i = 0; i < CRU_GATE_COUNT; i++)
200 mmio_write_32(CRU_BASE + CRU_GATE_CON(i), REG_SOC_WMSK);
201}
202
203void clk_gate_con_restore(void)
204{
205 uint32_t i;
206
207 for (i = 0; i < PMUCRU_GATE_COUNT; i++)
208 mmio_write_32(PMUCRU_BASE + PMUCRU_GATE_CON(i),
209 REG_SOC_WMSK | slp_data.pmucru_gate_con[i]);
210
211 for (i = 0; i < CRU_GATE_COUNT; i++)
212 mmio_write_32(CRU_BASE + CRU_GATE_CON(i),
213 REG_SOC_WMSK | slp_data.cru_gate_con[i]);
214}
215
Tony Xief6118cc2016-01-15 17:17:32 +0800216static void set_plls_nobypass(uint32_t pll_id)
217{
218 if (pll_id == PPLL_ID)
219 mmio_write_32(PMUCRU_BASE + PMUCRU_PPLL_CON(3),
220 PLL_NO_BYPASS_MODE);
221 else
222 mmio_write_32(CRU_BASE + CRU_PLL_CON(pll_id, 3),
223 PLL_NO_BYPASS_MODE);
224}
225
Caesar Wanged6b9a52016-08-11 02:11:45 +0800226static void _pll_resume(uint32_t pll_id)
227{
228 set_plls_nobypass(pll_id);
229 set_pll_normal_mode(pll_id);
230}
231
Caesar Wang5339d182016-10-27 01:13:34 +0800232/**
233 * enable_dvfs_plls - To resume the specific PLLs
234 *
235 * Please see the comment at the disable_dvfs_plls()
236 * we don't suspend the ABPLL, so don't need resume
237 * it too.
238 */
Caesar Wanged6b9a52016-08-11 02:11:45 +0800239void enable_dvfs_plls(void)
Tony Xief6118cc2016-01-15 17:17:32 +0800240{
Caesar Wanged6b9a52016-08-11 02:11:45 +0800241 _pll_resume(ALPLL_ID);
Caesar Wanged6b9a52016-08-11 02:11:45 +0800242 _pll_resume(GPLL_ID);
243 _pll_resume(VPLL_ID);
244 _pll_resume(NPLL_ID);
245 _pll_resume(CPLL_ID);
246}
Tony Xief6118cc2016-01-15 17:17:32 +0800247
Caesar Wang5339d182016-10-27 01:13:34 +0800248/**
249 * enable_nodvfs_plls - To resume the PPLL
250 */
Caesar Wanged6b9a52016-08-11 02:11:45 +0800251void enable_nodvfs_plls(void)
252{
253 _pll_resume(PPLL_ID);
Tony Xief6118cc2016-01-15 17:17:32 +0800254}
255
256void soc_global_soft_reset_init(void)
257{
258 mmio_write_32(PMUCRU_BASE + CRU_PMU_RSTHOLD_CON(1),
259 CRU_PMU_SGRF_RST_RLS);
Caesar Wang59e41b52016-04-10 14:11:07 +0800260
261 mmio_clrbits_32(CRU_BASE + CRU_GLB_RST_CON,
262 CRU_PMU_WDTRST_MSK | CRU_PMU_FIRST_SFTRST_MSK);
Tony Xief6118cc2016-01-15 17:17:32 +0800263}
264
Xing Zheng22a98712017-02-24 14:56:41 +0800265void __dead2 soc_global_soft_reset(void)
Tony Xief6118cc2016-01-15 17:17:32 +0800266{
Tony Xief6118cc2016-01-15 17:17:32 +0800267 set_pll_slow_mode(VPLL_ID);
268 set_pll_slow_mode(NPLL_ID);
269 set_pll_slow_mode(GPLL_ID);
270 set_pll_slow_mode(CPLL_ID);
271 set_pll_slow_mode(PPLL_ID);
272 set_pll_slow_mode(ABPLL_ID);
273 set_pll_slow_mode(ALPLL_ID);
Caesar Wang59e41b52016-04-10 14:11:07 +0800274
275 dsb();
276
Tony Xief6118cc2016-01-15 17:17:32 +0800277 mmio_write_32(CRU_BASE + CRU_GLB_SRST_FST, GLB_SRST_FST_CFG_VAL);
278
279 /*
280 * Maybe the HW needs some times to reset the system,
281 * so we do not hope the core to excute valid codes.
282 */
283 while (1)
Tony Xie42e113e2016-07-16 11:16:51 +0800284 ;
Tony Xief6118cc2016-01-15 17:17:32 +0800285}
286
287void plat_rockchip_soc_init(void)
288{
289 secure_timer_init();
Xing Zheng22a98712017-02-24 14:56:41 +0800290 secure_sgrf_init();
Xing Zheng5e1e48f2017-02-24 14:47:51 +0800291 secure_sgrf_ddr_rgn_init();
Tony Xief6118cc2016-01-15 17:17:32 +0800292 soc_global_soft_reset_init();
Caesar Wang038f6aa2016-05-25 19:21:43 +0800293 plat_rockchip_gpio_init();
Xing Zheng93280b72016-10-26 21:25:26 +0800294 m0_init();
Caesar Wanga8456902016-10-27 01:12:34 +0800295 dram_init();
Derek Basehoreff461d02016-10-20 20:46:43 -0700296 dram_dfs_init();
Tony Xief6118cc2016-01-15 17:17:32 +0800297}