]>
Commit | Line | Data |
---|---|---|
83d290c5 | 1 | // SPDX-License-Identifier: GPL-2.0 |
5ff093ab SG |
2 | /* |
3 | * (C) Copyright 2015 Google, Inc | |
4 | * Copyright 2014 Rockchip Inc. | |
5 | * | |
5ff093ab SG |
6 | * Adapted from coreboot. |
7 | */ | |
8 | ||
9 | #include <common.h> | |
10 | #include <clk.h> | |
11 | #include <dm.h> | |
086ec0e2 | 12 | #include <dt-structs.h> |
5ff093ab SG |
13 | #include <errno.h> |
14 | #include <ram.h> | |
15 | #include <regmap.h> | |
16 | #include <syscon.h> | |
17 | #include <asm/io.h> | |
18 | #include <asm/arch/clock.h> | |
19 | #include <asm/arch/cru_rk3288.h> | |
20 | #include <asm/arch/ddr_rk3288.h> | |
21 | #include <asm/arch/grf_rk3288.h> | |
22 | #include <asm/arch/pmu_rk3288.h> | |
23 | #include <asm/arch/sdram.h> | |
7805cdf4 | 24 | #include <asm/arch/sdram_common.h> |
5ff093ab | 25 | #include <linux/err.h> |
dae594f2 | 26 | #include <power/regulator.h> |
453c5a92 | 27 | #include <power/rk8xx_pmic.h> |
5ff093ab | 28 | |
5ff093ab SG |
29 | struct chan_info { |
30 | struct rk3288_ddr_pctl *pctl; | |
31 | struct rk3288_ddr_publ *publ; | |
32 | struct rk3288_msch *msch; | |
33 | }; | |
34 | ||
35 | struct dram_info { | |
36 | struct chan_info chan[2]; | |
37 | struct ram_info info; | |
135aa950 | 38 | struct clk ddr_clk; |
5ff093ab SG |
39 | struct rk3288_cru *cru; |
40 | struct rk3288_grf *grf; | |
41 | struct rk3288_sgrf *sgrf; | |
42 | struct rk3288_pmu *pmu; | |
fb4baf5d SG |
43 | bool is_veyron; |
44 | }; | |
45 | ||
46 | struct rk3288_sdram_params { | |
086ec0e2 SG |
47 | #if CONFIG_IS_ENABLED(OF_PLATDATA) |
48 | struct dtd_rockchip_rk3288_dmc of_plat; | |
49 | #endif | |
fb4baf5d SG |
50 | struct rk3288_sdram_channel ch[2]; |
51 | struct rk3288_sdram_pctl_timing pctl_timing; | |
52 | struct rk3288_sdram_phy_timing phy_timing; | |
53 | struct rk3288_base_params base; | |
54 | int num_channels; | |
55 | struct regmap *map; | |
5ff093ab SG |
56 | }; |
57 | ||
8f3cbef5 HS |
58 | const int ddrconf_table[] = { |
59 | /* row col,bw */ | |
60 | 0, | |
61 | ((1 << DDRCONF_ROW_SHIFT) | 1 << DDRCONF_COL_SHIFT), | |
62 | ((2 << DDRCONF_ROW_SHIFT) | 1 << DDRCONF_COL_SHIFT), | |
63 | ((3 << DDRCONF_ROW_SHIFT) | 1 << DDRCONF_COL_SHIFT), | |
64 | ((4 << DDRCONF_ROW_SHIFT) | 1 << DDRCONF_COL_SHIFT), | |
65 | ((1 << DDRCONF_ROW_SHIFT) | 2 << DDRCONF_COL_SHIFT), | |
66 | ((2 << DDRCONF_ROW_SHIFT) | 2 << DDRCONF_COL_SHIFT), | |
67 | ((3 << DDRCONF_ROW_SHIFT) | 2 << DDRCONF_COL_SHIFT), | |
68 | ((1 << DDRCONF_ROW_SHIFT) | 0 << DDRCONF_COL_SHIFT), | |
69 | ((2 << DDRCONF_ROW_SHIFT) | 0 << DDRCONF_COL_SHIFT), | |
70 | ((3 << DDRCONF_ROW_SHIFT) | 0 << DDRCONF_COL_SHIFT), | |
71 | 0, | |
72 | 0, | |
73 | 0, | |
74 | 0, | |
75 | ((4 << 4) | 2), | |
76 | }; | |
77 | ||
7d6c78f5 KY |
78 | #define TEST_PATTEN 0x5aa5f00f |
79 | #define DQS_GATE_TRAINING_ERROR_RANK0 (1 << 4) | |
80 | #define DQS_GATE_TRAINING_ERROR_RANK1 (2 << 4) | |
81 | ||
5ff093ab SG |
82 | #ifdef CONFIG_SPL_BUILD |
83 | static void copy_to_reg(u32 *dest, const u32 *src, u32 n) | |
84 | { | |
85 | int i; | |
86 | ||
87 | for (i = 0; i < n / sizeof(u32); i++) { | |
88 | writel(*src, dest); | |
89 | src++; | |
90 | dest++; | |
91 | } | |
92 | } | |
93 | ||
94 | static void ddr_reset(struct rk3288_cru *cru, u32 ch, u32 ctl, u32 phy) | |
95 | { | |
96 | u32 phy_ctl_srstn_shift = 4 + 5 * ch; | |
97 | u32 ctl_psrstn_shift = 3 + 5 * ch; | |
98 | u32 ctl_srstn_shift = 2 + 5 * ch; | |
99 | u32 phy_psrstn_shift = 1 + 5 * ch; | |
100 | u32 phy_srstn_shift = 5 * ch; | |
101 | ||
102 | rk_clrsetreg(&cru->cru_softrst_con[10], | |
103 | 1 << phy_ctl_srstn_shift | 1 << ctl_psrstn_shift | | |
104 | 1 << ctl_srstn_shift | 1 << phy_psrstn_shift | | |
105 | 1 << phy_srstn_shift, | |
106 | phy << phy_ctl_srstn_shift | ctl << ctl_psrstn_shift | | |
107 | ctl << ctl_srstn_shift | phy << phy_psrstn_shift | | |
108 | phy << phy_srstn_shift); | |
109 | } | |
110 | ||
111 | static void ddr_phy_ctl_reset(struct rk3288_cru *cru, u32 ch, u32 n) | |
112 | { | |
113 | u32 phy_ctl_srstn_shift = 4 + 5 * ch; | |
114 | ||
115 | rk_clrsetreg(&cru->cru_softrst_con[10], | |
116 | 1 << phy_ctl_srstn_shift, n << phy_ctl_srstn_shift); | |
117 | } | |
118 | ||
119 | static void phy_pctrl_reset(struct rk3288_cru *cru, | |
120 | struct rk3288_ddr_publ *publ, | |
8f3cbef5 | 121 | int channel) |
5ff093ab SG |
122 | { |
123 | int i; | |
124 | ||
125 | ddr_reset(cru, channel, 1, 1); | |
126 | udelay(1); | |
127 | clrbits_le32(&publ->acdllcr, ACDLLCR_DLLSRST); | |
128 | for (i = 0; i < 4; i++) | |
129 | clrbits_le32(&publ->datx8[i].dxdllcr, DXDLLCR_DLLSRST); | |
130 | ||
131 | udelay(10); | |
132 | setbits_le32(&publ->acdllcr, ACDLLCR_DLLSRST); | |
133 | for (i = 0; i < 4; i++) | |
134 | setbits_le32(&publ->datx8[i].dxdllcr, DXDLLCR_DLLSRST); | |
135 | ||
136 | udelay(10); | |
137 | ddr_reset(cru, channel, 1, 0); | |
138 | udelay(10); | |
139 | ddr_reset(cru, channel, 0, 0); | |
140 | udelay(10); | |
141 | } | |
142 | ||
143 | static void phy_dll_bypass_set(struct rk3288_ddr_publ *publ, | |
144 | u32 freq) | |
145 | { | |
146 | int i; | |
8f3cbef5 | 147 | |
5ff093ab SG |
148 | if (freq <= 250000000) { |
149 | if (freq <= 150000000) | |
150 | clrbits_le32(&publ->dllgcr, SBIAS_BYPASS); | |
151 | else | |
152 | setbits_le32(&publ->dllgcr, SBIAS_BYPASS); | |
153 | setbits_le32(&publ->acdllcr, ACDLLCR_DLLDIS); | |
154 | for (i = 0; i < 4; i++) | |
155 | setbits_le32(&publ->datx8[i].dxdllcr, | |
156 | DXDLLCR_DLLDIS); | |
157 | ||
158 | setbits_le32(&publ->pir, PIR_DLLBYP); | |
159 | } else { | |
160 | clrbits_le32(&publ->dllgcr, SBIAS_BYPASS); | |
161 | clrbits_le32(&publ->acdllcr, ACDLLCR_DLLDIS); | |
162 | for (i = 0; i < 4; i++) { | |
163 | clrbits_le32(&publ->datx8[i].dxdllcr, | |
164 | DXDLLCR_DLLDIS); | |
165 | } | |
166 | ||
167 | clrbits_le32(&publ->pir, PIR_DLLBYP); | |
168 | } | |
169 | } | |
170 | ||
171 | static void dfi_cfg(struct rk3288_ddr_pctl *pctl, u32 dramtype) | |
172 | { | |
173 | writel(DFI_INIT_START, &pctl->dfistcfg0); | |
174 | writel(DFI_DRAM_CLK_SR_EN | DFI_DRAM_CLK_DPD_EN, | |
175 | &pctl->dfistcfg1); | |
176 | writel(DFI_PARITY_INTR_EN | DFI_PARITY_EN, &pctl->dfistcfg2); | |
177 | writel(7 << TLP_RESP_TIME_SHIFT | LP_SR_EN | LP_PD_EN, | |
178 | &pctl->dfilpcfg0); | |
179 | ||
180 | writel(2 << TCTRL_DELAY_TIME_SHIFT, &pctl->dfitctrldelay); | |
181 | writel(1 << TPHY_WRDATA_TIME_SHIFT, &pctl->dfitphywrdata); | |
182 | writel(0xf << TPHY_RDLAT_TIME_SHIFT, &pctl->dfitphyrdlat); | |
183 | writel(2 << TDRAM_CLK_DIS_TIME_SHIFT, &pctl->dfitdramclkdis); | |
184 | writel(2 << TDRAM_CLK_EN_TIME_SHIFT, &pctl->dfitdramclken); | |
185 | writel(1, &pctl->dfitphyupdtype0); | |
186 | ||
187 | /* cs0 and cs1 write odt enable */ | |
188 | writel((RANK0_ODT_WRITE_SEL | RANK1_ODT_WRITE_SEL), | |
189 | &pctl->dfiodtcfg); | |
190 | /* odt write length */ | |
191 | writel(7 << ODT_LEN_BL8_W_SHIFT, &pctl->dfiodtcfg1); | |
192 | /* phyupd and ctrlupd disabled */ | |
193 | writel(0, &pctl->dfiupdcfg); | |
194 | } | |
195 | ||
196 | static void ddr_set_enable(struct rk3288_grf *grf, uint channel, bool enable) | |
197 | { | |
198 | uint val = 0; | |
199 | ||
200 | if (enable) { | |
201 | val = 1 << (channel ? DDR1_16BIT_EN_SHIFT : | |
202 | DDR0_16BIT_EN_SHIFT); | |
203 | } | |
204 | rk_clrsetreg(&grf->soc_con0, | |
205 | 1 << (channel ? DDR1_16BIT_EN_SHIFT : DDR0_16BIT_EN_SHIFT), | |
206 | val); | |
207 | } | |
208 | ||
209 | static void ddr_set_ddr3_mode(struct rk3288_grf *grf, uint channel, | |
210 | bool ddr3_mode) | |
211 | { | |
212 | uint mask, val; | |
213 | ||
214 | mask = 1 << (channel ? MSCH1_MAINDDR3_SHIFT : MSCH0_MAINDDR3_SHIFT); | |
215 | val = ddr3_mode << (channel ? MSCH1_MAINDDR3_SHIFT : | |
216 | MSCH0_MAINDDR3_SHIFT); | |
217 | rk_clrsetreg(&grf->soc_con0, mask, val); | |
218 | } | |
219 | ||
220 | static void ddr_set_en_bst_odt(struct rk3288_grf *grf, uint channel, | |
221 | bool enable, bool enable_bst, bool enable_odt) | |
222 | { | |
223 | uint mask; | |
224 | bool disable_bst = !enable_bst; | |
225 | ||
226 | mask = channel ? | |
227 | (1 << LPDDR3_EN1_SHIFT | 1 << UPCTL1_BST_DIABLE_SHIFT | | |
228 | 1 << UPCTL1_LPDDR3_ODT_EN_SHIFT) : | |
229 | (1 << LPDDR3_EN0_SHIFT | 1 << UPCTL0_BST_DIABLE_SHIFT | | |
230 | 1 << UPCTL0_LPDDR3_ODT_EN_SHIFT); | |
231 | rk_clrsetreg(&grf->soc_con2, mask, | |
232 | enable << (channel ? LPDDR3_EN1_SHIFT : LPDDR3_EN0_SHIFT) | | |
233 | disable_bst << (channel ? UPCTL1_BST_DIABLE_SHIFT : | |
234 | UPCTL0_BST_DIABLE_SHIFT) | | |
235 | enable_odt << (channel ? UPCTL1_LPDDR3_ODT_EN_SHIFT : | |
236 | UPCTL0_LPDDR3_ODT_EN_SHIFT)); | |
237 | } | |
238 | ||
8f3cbef5 | 239 | static void pctl_cfg(int channel, struct rk3288_ddr_pctl *pctl, |
7d6c78f5 | 240 | struct rk3288_sdram_params *sdram_params, |
5ff093ab SG |
241 | struct rk3288_grf *grf) |
242 | { | |
243 | unsigned int burstlen; | |
244 | ||
245 | burstlen = (sdram_params->base.noc_timing >> 18) & 0x7; | |
246 | copy_to_reg(&pctl->togcnt1u, &sdram_params->pctl_timing.togcnt1u, | |
247 | sizeof(sdram_params->pctl_timing)); | |
248 | switch (sdram_params->base.dramtype) { | |
249 | case LPDDR3: | |
250 | writel(sdram_params->pctl_timing.tcl - 1, | |
251 | &pctl->dfitrddataen); | |
252 | writel(sdram_params->pctl_timing.tcwl, | |
253 | &pctl->dfitphywrlat); | |
254 | burstlen >>= 1; | |
255 | writel(LPDDR2_S4 | 0 << MDDR_LPDDR2_CLK_STOP_IDLE_SHIFT | | |
256 | LPDDR2_EN | burstlen << BURSTLENGTH_SHIFT | | |
257 | (6 - 4) << TFAW_SHIFT | PD_EXIT_FAST | | |
258 | 1 << PD_TYPE_SHIFT | 0 << PD_IDLE_SHIFT, | |
259 | &pctl->mcfg); | |
260 | ddr_set_ddr3_mode(grf, channel, false); | |
261 | ddr_set_enable(grf, channel, true); | |
262 | ddr_set_en_bst_odt(grf, channel, true, false, | |
263 | sdram_params->base.odt); | |
264 | break; | |
265 | case DDR3: | |
266 | if (sdram_params->phy_timing.mr[1] & DDR3_DLL_DISABLE) { | |
267 | writel(sdram_params->pctl_timing.tcl - 3, | |
268 | &pctl->dfitrddataen); | |
269 | } else { | |
270 | writel(sdram_params->pctl_timing.tcl - 2, | |
271 | &pctl->dfitrddataen); | |
272 | } | |
273 | writel(sdram_params->pctl_timing.tcwl - 1, | |
274 | &pctl->dfitphywrlat); | |
275 | writel(0 << MDDR_LPDDR2_CLK_STOP_IDLE_SHIFT | DDR3_EN | | |
276 | DDR2_DDR3_BL_8 | (6 - 4) << TFAW_SHIFT | PD_EXIT_SLOW | | |
277 | 1 << PD_TYPE_SHIFT | 0 << PD_IDLE_SHIFT, | |
278 | &pctl->mcfg); | |
279 | ddr_set_ddr3_mode(grf, channel, true); | |
280 | ddr_set_enable(grf, channel, true); | |
281 | ||
282 | ddr_set_en_bst_odt(grf, channel, false, true, false); | |
283 | break; | |
284 | } | |
285 | ||
286 | setbits_le32(&pctl->scfg, 1); | |
287 | } | |
288 | ||
8f3cbef5 | 289 | static void phy_cfg(const struct chan_info *chan, int channel, |
7d6c78f5 | 290 | struct rk3288_sdram_params *sdram_params) |
5ff093ab SG |
291 | { |
292 | struct rk3288_ddr_publ *publ = chan->publ; | |
293 | struct rk3288_msch *msch = chan->msch; | |
294 | uint ddr_freq_mhz = sdram_params->base.ddr_freq / 1000000; | |
295 | u32 dinit2, tmp; | |
296 | int i; | |
297 | ||
298 | dinit2 = DIV_ROUND_UP(ddr_freq_mhz * 200000, 1000); | |
299 | /* DDR PHY Timing */ | |
300 | copy_to_reg(&publ->dtpr[0], &sdram_params->phy_timing.dtpr0, | |
301 | sizeof(sdram_params->phy_timing)); | |
302 | writel(sdram_params->base.noc_timing, &msch->ddrtiming); | |
303 | writel(0x3f, &msch->readlatency); | |
304 | writel(sdram_params->base.noc_activate, &msch->activate); | |
305 | writel(2 << BUSWRTORD_SHIFT | 2 << BUSRDTOWR_SHIFT | | |
306 | 1 << BUSRDTORD_SHIFT, &msch->devtodev); | |
307 | writel(DIV_ROUND_UP(ddr_freq_mhz * 5120, 1000) << PRT_DLLLOCK_SHIFT | | |
308 | DIV_ROUND_UP(ddr_freq_mhz * 50, 1000) << PRT_DLLSRST_SHIFT | | |
309 | 8 << PRT_ITMSRST_SHIFT, &publ->ptr[0]); | |
310 | writel(DIV_ROUND_UP(ddr_freq_mhz * 500000, 1000) << PRT_DINIT0_SHIFT | | |
311 | DIV_ROUND_UP(ddr_freq_mhz * 400, 1000) << PRT_DINIT1_SHIFT, | |
312 | &publ->ptr[1]); | |
313 | writel(min(dinit2, 0x1ffffU) << PRT_DINIT2_SHIFT | | |
314 | DIV_ROUND_UP(ddr_freq_mhz * 1000, 1000) << PRT_DINIT3_SHIFT, | |
315 | &publ->ptr[2]); | |
316 | ||
317 | switch (sdram_params->base.dramtype) { | |
318 | case LPDDR3: | |
319 | clrsetbits_le32(&publ->pgcr, 0x1F, | |
320 | 0 << PGCR_DFTLMT_SHIFT | | |
321 | 0 << PGCR_DFTCMP_SHIFT | | |
322 | 1 << PGCR_DQSCFG_SHIFT | | |
323 | 0 << PGCR_ITMDMD_SHIFT); | |
324 | /* DDRMODE select LPDDR3 */ | |
325 | clrsetbits_le32(&publ->dcr, DDRMD_MASK << DDRMD_SHIFT, | |
326 | DDRMD_LPDDR2_LPDDR3 << DDRMD_SHIFT); | |
327 | clrsetbits_le32(&publ->dxccr, | |
328 | DQSNRES_MASK << DQSNRES_SHIFT | | |
329 | DQSRES_MASK << DQSRES_SHIFT, | |
330 | 4 << DQSRES_SHIFT | 0xc << DQSNRES_SHIFT); | |
331 | tmp = readl(&publ->dtpr[1]); | |
332 | tmp = ((tmp >> TDQSCKMAX_SHIFT) & TDQSCKMAX_MASK) - | |
333 | ((tmp >> TDQSCK_SHIFT) & TDQSCK_MASK); | |
334 | clrsetbits_le32(&publ->dsgcr, | |
335 | DQSGE_MASK << DQSGE_SHIFT | | |
336 | DQSGX_MASK << DQSGX_SHIFT, | |
337 | tmp << DQSGE_SHIFT | tmp << DQSGX_SHIFT); | |
338 | break; | |
339 | case DDR3: | |
340 | clrbits_le32(&publ->pgcr, 0x1f); | |
341 | clrsetbits_le32(&publ->dcr, DDRMD_MASK << DDRMD_SHIFT, | |
342 | DDRMD_DDR3 << DDRMD_SHIFT); | |
343 | break; | |
344 | } | |
345 | if (sdram_params->base.odt) { | |
346 | /*dynamic RTT enable */ | |
347 | for (i = 0; i < 4; i++) | |
348 | setbits_le32(&publ->datx8[i].dxgcr, DQSRTT | DQRTT); | |
349 | } else { | |
350 | /*dynamic RTT disable */ | |
351 | for (i = 0; i < 4; i++) | |
352 | clrbits_le32(&publ->datx8[i].dxgcr, DQSRTT | DQRTT); | |
353 | } | |
354 | } | |
355 | ||
356 | static void phy_init(struct rk3288_ddr_publ *publ) | |
357 | { | |
358 | setbits_le32(&publ->pir, PIR_INIT | PIR_DLLSRST | |
359 | | PIR_DLLLOCK | PIR_ZCAL | PIR_ITMSRST | PIR_CLRSR); | |
360 | udelay(1); | |
361 | while ((readl(&publ->pgsr) & | |
362 | (PGSR_IDONE | PGSR_DLDONE | PGSR_ZCDONE)) != | |
363 | (PGSR_IDONE | PGSR_DLDONE | PGSR_ZCDONE)) | |
364 | ; | |
365 | } | |
366 | ||
367 | static void send_command(struct rk3288_ddr_pctl *pctl, u32 rank, | |
368 | u32 cmd, u32 arg) | |
369 | { | |
370 | writel((START_CMD | (rank << 20) | arg | cmd), &pctl->mcmd); | |
371 | udelay(1); | |
372 | while (readl(&pctl->mcmd) & START_CMD) | |
373 | ; | |
374 | } | |
375 | ||
376 | static inline void send_command_op(struct rk3288_ddr_pctl *pctl, | |
377 | u32 rank, u32 cmd, u32 ma, u32 op) | |
378 | { | |
379 | send_command(pctl, rank, cmd, (ma & LPDDR2_MA_MASK) << LPDDR2_MA_SHIFT | | |
380 | (op & LPDDR2_OP_MASK) << LPDDR2_OP_SHIFT); | |
381 | } | |
382 | ||
383 | static void memory_init(struct rk3288_ddr_publ *publ, | |
384 | u32 dramtype) | |
385 | { | |
386 | setbits_le32(&publ->pir, | |
387 | (PIR_INIT | PIR_DRAMINIT | PIR_LOCKBYP | |
388 | | PIR_ZCALBYP | PIR_CLRSR | PIR_ICPC | |
389 | | (dramtype == DDR3 ? PIR_DRAMRST : 0))); | |
390 | udelay(1); | |
391 | while ((readl(&publ->pgsr) & (PGSR_IDONE | PGSR_DLDONE)) | |
392 | != (PGSR_IDONE | PGSR_DLDONE)) | |
393 | ; | |
394 | } | |
395 | ||
396 | static void move_to_config_state(struct rk3288_ddr_publ *publ, | |
397 | struct rk3288_ddr_pctl *pctl) | |
398 | { | |
399 | unsigned int state; | |
400 | ||
401 | while (1) { | |
402 | state = readl(&pctl->stat) & PCTL_STAT_MSK; | |
403 | ||
404 | switch (state) { | |
405 | case LOW_POWER: | |
406 | writel(WAKEUP_STATE, &pctl->sctl); | |
407 | while ((readl(&pctl->stat) & PCTL_STAT_MSK) | |
408 | != ACCESS) | |
409 | ; | |
410 | /* wait DLL lock */ | |
411 | while ((readl(&publ->pgsr) & PGSR_DLDONE) | |
412 | != PGSR_DLDONE) | |
413 | ; | |
8f3cbef5 HS |
414 | /* |
415 | * if at low power state,need wakeup first, | |
5ff093ab SG |
416 | * and then enter the config |
417 | * so here no break. | |
418 | */ | |
419 | case ACCESS: | |
420 | /* no break */ | |
421 | case INIT_MEM: | |
422 | writel(CFG_STATE, &pctl->sctl); | |
423 | while ((readl(&pctl->stat) & PCTL_STAT_MSK) != CONFIG) | |
424 | ; | |
425 | break; | |
426 | case CONFIG: | |
427 | return; | |
428 | default: | |
429 | break; | |
430 | } | |
431 | } | |
432 | } | |
433 | ||
8f3cbef5 | 434 | static void set_bandwidth_ratio(const struct chan_info *chan, int channel, |
5ff093ab SG |
435 | u32 n, struct rk3288_grf *grf) |
436 | { | |
437 | struct rk3288_ddr_pctl *pctl = chan->pctl; | |
438 | struct rk3288_ddr_publ *publ = chan->publ; | |
439 | struct rk3288_msch *msch = chan->msch; | |
440 | ||
441 | if (n == 1) { | |
442 | setbits_le32(&pctl->ppcfg, 1); | |
0906995b | 443 | rk_setreg(&grf->soc_con0, 1 << (8 + channel)); |
5ff093ab SG |
444 | setbits_le32(&msch->ddrtiming, 1 << 31); |
445 | /* Data Byte disable*/ | |
446 | clrbits_le32(&publ->datx8[2].dxgcr, 1); | |
447 | clrbits_le32(&publ->datx8[3].dxgcr, 1); | |
9368104d | 448 | /* disable DLL */ |
5ff093ab SG |
449 | setbits_le32(&publ->datx8[2].dxdllcr, DXDLLCR_DLLDIS); |
450 | setbits_le32(&publ->datx8[3].dxdllcr, DXDLLCR_DLLDIS); | |
451 | } else { | |
452 | clrbits_le32(&pctl->ppcfg, 1); | |
0906995b | 453 | rk_clrreg(&grf->soc_con0, 1 << (8 + channel)); |
5ff093ab SG |
454 | clrbits_le32(&msch->ddrtiming, 1 << 31); |
455 | /* Data Byte enable*/ | |
456 | setbits_le32(&publ->datx8[2].dxgcr, 1); | |
457 | setbits_le32(&publ->datx8[3].dxgcr, 1); | |
458 | ||
9368104d | 459 | /* enable DLL */ |
5ff093ab SG |
460 | clrbits_le32(&publ->datx8[2].dxdllcr, DXDLLCR_DLLDIS); |
461 | clrbits_le32(&publ->datx8[3].dxdllcr, DXDLLCR_DLLDIS); | |
462 | /* reset DLL */ | |
463 | clrbits_le32(&publ->datx8[2].dxdllcr, DXDLLCR_DLLSRST); | |
464 | clrbits_le32(&publ->datx8[3].dxdllcr, DXDLLCR_DLLSRST); | |
465 | udelay(10); | |
466 | setbits_le32(&publ->datx8[2].dxdllcr, DXDLLCR_DLLSRST); | |
467 | setbits_le32(&publ->datx8[3].dxdllcr, DXDLLCR_DLLSRST); | |
468 | } | |
469 | setbits_le32(&pctl->dfistcfg0, 1 << 2); | |
470 | } | |
471 | ||
8f3cbef5 | 472 | static int data_training(const struct chan_info *chan, int channel, |
7d6c78f5 | 473 | struct rk3288_sdram_params *sdram_params) |
5ff093ab SG |
474 | { |
475 | unsigned int j; | |
476 | int ret = 0; | |
477 | u32 rank; | |
478 | int i; | |
479 | u32 step[2] = { PIR_QSTRN, PIR_RVTRN }; | |
480 | struct rk3288_ddr_publ *publ = chan->publ; | |
481 | struct rk3288_ddr_pctl *pctl = chan->pctl; | |
482 | ||
483 | /* disable auto refresh */ | |
484 | writel(0, &pctl->trefi); | |
485 | ||
486 | if (sdram_params->base.dramtype != LPDDR3) | |
487 | setbits_le32(&publ->pgcr, 1 << PGCR_DQSCFG_SHIFT); | |
488 | rank = sdram_params->ch[channel].rank | 1; | |
489 | for (j = 0; j < ARRAY_SIZE(step); j++) { | |
490 | /* | |
491 | * trigger QSTRN and RVTRN | |
492 | * clear DTDONE status | |
493 | */ | |
494 | setbits_le32(&publ->pir, PIR_CLRSR); | |
495 | ||
496 | /* trigger DTT */ | |
497 | setbits_le32(&publ->pir, | |
498 | PIR_INIT | step[j] | PIR_LOCKBYP | PIR_ZCALBYP | | |
499 | PIR_CLRSR); | |
500 | udelay(1); | |
501 | /* wait echo byte DTDONE */ | |
502 | while ((readl(&publ->datx8[0].dxgsr[0]) & rank) | |
503 | != rank) | |
504 | ; | |
505 | while ((readl(&publ->datx8[1].dxgsr[0]) & rank) | |
506 | != rank) | |
507 | ; | |
508 | if (!(readl(&pctl->ppcfg) & 1)) { | |
509 | while ((readl(&publ->datx8[2].dxgsr[0]) | |
510 | & rank) != rank) | |
511 | ; | |
512 | while ((readl(&publ->datx8[3].dxgsr[0]) | |
513 | & rank) != rank) | |
514 | ; | |
515 | } | |
516 | if (readl(&publ->pgsr) & | |
517 | (PGSR_DTERR | PGSR_RVERR | PGSR_RVEIRR)) { | |
518 | ret = -1; | |
519 | break; | |
520 | } | |
521 | } | |
522 | /* send some auto refresh to complement the lost while DTT */ | |
523 | for (i = 0; i < (rank > 1 ? 8 : 4); i++) | |
524 | send_command(pctl, rank, REF_CMD, 0); | |
525 | ||
526 | if (sdram_params->base.dramtype != LPDDR3) | |
527 | clrbits_le32(&publ->pgcr, 1 << PGCR_DQSCFG_SHIFT); | |
528 | ||
529 | /* resume auto refresh */ | |
530 | writel(sdram_params->pctl_timing.trefi, &pctl->trefi); | |
531 | ||
532 | return ret; | |
533 | } | |
534 | ||
535 | static void move_to_access_state(const struct chan_info *chan) | |
536 | { | |
537 | struct rk3288_ddr_publ *publ = chan->publ; | |
538 | struct rk3288_ddr_pctl *pctl = chan->pctl; | |
539 | unsigned int state; | |
540 | ||
541 | while (1) { | |
542 | state = readl(&pctl->stat) & PCTL_STAT_MSK; | |
543 | ||
544 | switch (state) { | |
545 | case LOW_POWER: | |
546 | if (((readl(&pctl->stat) >> LP_TRIG_SHIFT) & | |
547 | LP_TRIG_MASK) == 1) | |
548 | return; | |
549 | ||
550 | writel(WAKEUP_STATE, &pctl->sctl); | |
551 | while ((readl(&pctl->stat) & PCTL_STAT_MSK) != ACCESS) | |
552 | ; | |
553 | /* wait DLL lock */ | |
554 | while ((readl(&publ->pgsr) & PGSR_DLDONE) | |
555 | != PGSR_DLDONE) | |
556 | ; | |
557 | break; | |
558 | case INIT_MEM: | |
559 | writel(CFG_STATE, &pctl->sctl); | |
560 | while ((readl(&pctl->stat) & PCTL_STAT_MSK) != CONFIG) | |
561 | ; | |
562 | case CONFIG: | |
563 | writel(GO_STATE, &pctl->sctl); | |
564 | while ((readl(&pctl->stat) & PCTL_STAT_MSK) == CONFIG) | |
565 | ; | |
566 | break; | |
567 | case ACCESS: | |
568 | return; | |
569 | default: | |
570 | break; | |
571 | } | |
572 | } | |
573 | } | |
574 | ||
575 | static void dram_cfg_rbc(const struct chan_info *chan, u32 chnum, | |
7d6c78f5 | 576 | struct rk3288_sdram_params *sdram_params) |
5ff093ab SG |
577 | { |
578 | struct rk3288_ddr_publ *publ = chan->publ; | |
579 | ||
580 | if (sdram_params->ch[chnum].bk == 3) | |
581 | clrsetbits_le32(&publ->dcr, PDQ_MASK << PDQ_SHIFT, | |
582 | 1 << PDQ_SHIFT); | |
583 | else | |
584 | clrbits_le32(&publ->dcr, PDQ_MASK << PDQ_SHIFT); | |
585 | ||
586 | writel(sdram_params->base.ddrconfig, &chan->msch->ddrconf); | |
587 | } | |
588 | ||
589 | static void dram_all_config(const struct dram_info *dram, | |
7d6c78f5 | 590 | struct rk3288_sdram_params *sdram_params) |
5ff093ab SG |
591 | { |
592 | unsigned int chan; | |
593 | u32 sys_reg = 0; | |
594 | ||
595 | sys_reg |= sdram_params->base.dramtype << SYS_REG_DDRTYPE_SHIFT; | |
596 | sys_reg |= (sdram_params->num_channels - 1) << SYS_REG_NUM_CH_SHIFT; | |
597 | for (chan = 0; chan < sdram_params->num_channels; chan++) { | |
598 | const struct rk3288_sdram_channel *info = | |
599 | &sdram_params->ch[chan]; | |
600 | ||
601 | sys_reg |= info->row_3_4 << SYS_REG_ROW_3_4_SHIFT(chan); | |
c482c60a | 602 | sys_reg |= 1 << SYS_REG_CHINFO_SHIFT(chan); |
5ff093ab SG |
603 | sys_reg |= (info->rank - 1) << SYS_REG_RANK_SHIFT(chan); |
604 | sys_reg |= (info->col - 9) << SYS_REG_COL_SHIFT(chan); | |
c482c60a | 605 | sys_reg |= info->bk == 3 ? 0 : 1 << SYS_REG_BK_SHIFT(chan); |
5ff093ab SG |
606 | sys_reg |= (info->cs0_row - 13) << SYS_REG_CS0_ROW_SHIFT(chan); |
607 | sys_reg |= (info->cs1_row - 13) << SYS_REG_CS1_ROW_SHIFT(chan); | |
c482c60a JK |
608 | sys_reg |= (2 >> info->bw) << SYS_REG_BW_SHIFT(chan); |
609 | sys_reg |= (2 >> info->dbw) << SYS_REG_DBW_SHIFT(chan); | |
5ff093ab SG |
610 | |
611 | dram_cfg_rbc(&dram->chan[chan], chan, sdram_params); | |
612 | } | |
613 | writel(sys_reg, &dram->pmu->sys_reg[2]); | |
0906995b | 614 | rk_clrsetreg(&dram->sgrf->soc_con2, 0x1f, sdram_params->base.stride); |
5ff093ab | 615 | } |
7d6c78f5 KY |
616 | |
617 | static int sdram_rank_bw_detect(struct dram_info *dram, int channel, | |
618 | struct rk3288_sdram_params *sdram_params) | |
619 | { | |
620 | int reg; | |
621 | int need_trainig = 0; | |
622 | const struct chan_info *chan = &dram->chan[channel]; | |
623 | struct rk3288_ddr_publ *publ = chan->publ; | |
624 | ||
8f3cbef5 | 625 | if (data_training(chan, channel, sdram_params) < 0) { |
7d6c78f5 KY |
626 | reg = readl(&publ->datx8[0].dxgsr[0]); |
627 | /* Check the result for rank 0 */ | |
628 | if ((channel == 0) && (reg & DQS_GATE_TRAINING_ERROR_RANK0)) { | |
629 | debug("data training fail!\n"); | |
8f3cbef5 | 630 | return -EIO; |
7d6c78f5 KY |
631 | } else if ((channel == 1) && |
632 | (reg & DQS_GATE_TRAINING_ERROR_RANK0)) { | |
633 | sdram_params->num_channels = 1; | |
634 | } | |
635 | ||
636 | /* Check the result for rank 1 */ | |
637 | if (reg & DQS_GATE_TRAINING_ERROR_RANK1) { | |
638 | sdram_params->ch[channel].rank = 1; | |
639 | clrsetbits_le32(&publ->pgcr, 0xF << 18, | |
640 | sdram_params->ch[channel].rank << 18); | |
641 | need_trainig = 1; | |
642 | } | |
643 | reg = readl(&publ->datx8[2].dxgsr[0]); | |
644 | if (reg & (1 << 4)) { | |
645 | sdram_params->ch[channel].bw = 1; | |
646 | set_bandwidth_ratio(chan, channel, | |
647 | sdram_params->ch[channel].bw, | |
648 | dram->grf); | |
649 | need_trainig = 1; | |
650 | } | |
651 | } | |
652 | /* Assume the Die bit width are the same with the chip bit width */ | |
653 | sdram_params->ch[channel].dbw = sdram_params->ch[channel].bw; | |
654 | ||
655 | if (need_trainig && | |
8f3cbef5 | 656 | (data_training(chan, channel, sdram_params) < 0)) { |
7d6c78f5 KY |
657 | if (sdram_params->base.dramtype == LPDDR3) { |
658 | ddr_phy_ctl_reset(dram->cru, channel, 1); | |
659 | udelay(10); | |
660 | ddr_phy_ctl_reset(dram->cru, channel, 0); | |
661 | udelay(10); | |
662 | } | |
663 | debug("2nd data training failed!"); | |
664 | return -EIO; | |
665 | } | |
666 | ||
667 | return 0; | |
668 | } | |
669 | ||
670 | static int sdram_col_row_detect(struct dram_info *dram, int channel, | |
671 | struct rk3288_sdram_params *sdram_params) | |
672 | { | |
673 | int row, col; | |
674 | unsigned int addr; | |
675 | const struct chan_info *chan = &dram->chan[channel]; | |
676 | struct rk3288_ddr_pctl *pctl = chan->pctl; | |
677 | struct rk3288_ddr_publ *publ = chan->publ; | |
678 | int ret = 0; | |
679 | ||
680 | /* Detect col */ | |
681 | for (col = 11; col >= 9; col--) { | |
682 | writel(0, CONFIG_SYS_SDRAM_BASE); | |
683 | addr = CONFIG_SYS_SDRAM_BASE + | |
684 | (1 << (col + sdram_params->ch[channel].bw - 1)); | |
685 | writel(TEST_PATTEN, addr); | |
686 | if ((readl(addr) == TEST_PATTEN) && | |
687 | (readl(CONFIG_SYS_SDRAM_BASE) == 0)) | |
688 | break; | |
689 | } | |
690 | if (col == 8) { | |
691 | printf("Col detect error\n"); | |
692 | ret = -EINVAL; | |
693 | goto out; | |
694 | } else { | |
695 | sdram_params->ch[channel].col = col; | |
696 | } | |
697 | ||
698 | move_to_config_state(publ, pctl); | |
699 | writel(4, &chan->msch->ddrconf); | |
700 | move_to_access_state(chan); | |
701 | /* Detect row*/ | |
702 | for (row = 16; row >= 12; row--) { | |
703 | writel(0, CONFIG_SYS_SDRAM_BASE); | |
704 | addr = CONFIG_SYS_SDRAM_BASE + (1 << (row + 15 - 1)); | |
705 | writel(TEST_PATTEN, addr); | |
706 | if ((readl(addr) == TEST_PATTEN) && | |
707 | (readl(CONFIG_SYS_SDRAM_BASE) == 0)) | |
708 | break; | |
709 | } | |
710 | if (row == 11) { | |
711 | printf("Row detect error\n"); | |
712 | ret = -EINVAL; | |
713 | } else { | |
714 | sdram_params->ch[channel].cs1_row = row; | |
715 | sdram_params->ch[channel].row_3_4 = 0; | |
716 | debug("chn %d col %d, row %d\n", channel, col, row); | |
717 | sdram_params->ch[channel].cs0_row = row; | |
718 | } | |
719 | ||
720 | out: | |
721 | return ret; | |
722 | } | |
723 | ||
724 | static int sdram_get_niu_config(struct rk3288_sdram_params *sdram_params) | |
725 | { | |
726 | int i, tmp, size, ret = 0; | |
727 | ||
728 | tmp = sdram_params->ch[0].col - 9; | |
729 | tmp -= (sdram_params->ch[0].bw == 2) ? 0 : 1; | |
730 | tmp |= ((sdram_params->ch[0].cs0_row - 12) << 4); | |
731 | size = sizeof(ddrconf_table)/sizeof(ddrconf_table[0]); | |
732 | for (i = 0; i < size; i++) | |
733 | if (tmp == ddrconf_table[i]) | |
734 | break; | |
735 | if (i >= size) { | |
736 | printf("niu config not found\n"); | |
737 | ret = -EINVAL; | |
738 | } else { | |
739 | sdram_params->base.ddrconfig = i; | |
740 | } | |
741 | ||
742 | return ret; | |
743 | } | |
744 | ||
745 | static int sdram_get_stride(struct rk3288_sdram_params *sdram_params) | |
746 | { | |
747 | int stride = -1; | |
748 | int ret = 0; | |
749 | long cap = sdram_params->num_channels * (1u << | |
750 | (sdram_params->ch[0].cs0_row + | |
751 | sdram_params->ch[0].col + | |
752 | (sdram_params->ch[0].rank - 1) + | |
753 | sdram_params->ch[0].bw + | |
754 | 3 - 20)); | |
755 | ||
756 | switch (cap) { | |
757 | case 512: | |
758 | stride = 0; | |
759 | break; | |
760 | case 1024: | |
761 | stride = 5; | |
762 | break; | |
763 | case 2048: | |
764 | stride = 9; | |
765 | break; | |
766 | case 4096: | |
767 | stride = 0xd; | |
768 | break; | |
769 | default: | |
770 | stride = -1; | |
771 | printf("could not find correct stride, cap error!\n"); | |
772 | ret = -EINVAL; | |
773 | break; | |
774 | } | |
775 | sdram_params->base.stride = stride; | |
776 | ||
777 | return ret; | |
778 | } | |
5ff093ab | 779 | |
135aa950 | 780 | static int sdram_init(struct dram_info *dram, |
7d6c78f5 | 781 | struct rk3288_sdram_params *sdram_params) |
5ff093ab SG |
782 | { |
783 | int channel; | |
784 | int zqcr; | |
785 | int ret; | |
786 | ||
787 | debug("%s start\n", __func__); | |
788 | if ((sdram_params->base.dramtype == DDR3 && | |
789 | sdram_params->base.ddr_freq > 800000000) || | |
790 | (sdram_params->base.dramtype == LPDDR3 && | |
791 | sdram_params->base.ddr_freq > 533000000)) { | |
792 | debug("SDRAM frequency is too high!"); | |
793 | return -E2BIG; | |
794 | } | |
795 | ||
135aa950 SW |
796 | debug("ddr clk dpll\n"); |
797 | ret = clk_set_rate(&dram->ddr_clk, sdram_params->base.ddr_freq); | |
5ff093ab SG |
798 | debug("ret=%d\n", ret); |
799 | if (ret) { | |
800 | debug("Could not set DDR clock\n"); | |
801 | return ret; | |
802 | } | |
803 | ||
804 | for (channel = 0; channel < 2; channel++) { | |
805 | const struct chan_info *chan = &dram->chan[channel]; | |
806 | struct rk3288_ddr_pctl *pctl = chan->pctl; | |
807 | struct rk3288_ddr_publ *publ = chan->publ; | |
808 | ||
7d6c78f5 KY |
809 | /* map all the 4GB space to the current channel */ |
810 | if (channel) | |
811 | rk_clrsetreg(&dram->sgrf->soc_con2, 0x1f, 0x17); | |
812 | else | |
813 | rk_clrsetreg(&dram->sgrf->soc_con2, 0x1f, 0x1a); | |
5ff093ab SG |
814 | phy_pctrl_reset(dram->cru, publ, channel); |
815 | phy_dll_bypass_set(publ, sdram_params->base.ddr_freq); | |
816 | ||
5ff093ab SG |
817 | dfi_cfg(pctl, sdram_params->base.dramtype); |
818 | ||
819 | pctl_cfg(channel, pctl, sdram_params, dram->grf); | |
820 | ||
821 | phy_cfg(chan, channel, sdram_params); | |
822 | ||
823 | phy_init(publ); | |
824 | ||
825 | writel(POWER_UP_START, &pctl->powctl); | |
826 | while (!(readl(&pctl->powstat) & POWER_UP_DONE)) | |
827 | ; | |
828 | ||
829 | memory_init(publ, sdram_params->base.dramtype); | |
830 | move_to_config_state(publ, pctl); | |
831 | ||
832 | if (sdram_params->base.dramtype == LPDDR3) { | |
833 | send_command(pctl, 3, DESELECT_CMD, 0); | |
834 | udelay(1); | |
835 | send_command(pctl, 3, PREA_CMD, 0); | |
836 | udelay(1); | |
837 | send_command_op(pctl, 3, MRS_CMD, 63, 0xfc); | |
838 | udelay(1); | |
839 | send_command_op(pctl, 3, MRS_CMD, 1, | |
840 | sdram_params->phy_timing.mr[1]); | |
841 | udelay(1); | |
842 | send_command_op(pctl, 3, MRS_CMD, 2, | |
843 | sdram_params->phy_timing.mr[2]); | |
844 | udelay(1); | |
845 | send_command_op(pctl, 3, MRS_CMD, 3, | |
846 | sdram_params->phy_timing.mr[3]); | |
847 | udelay(1); | |
848 | } | |
849 | ||
7d6c78f5 KY |
850 | /* Using 32bit bus width for detect */ |
851 | sdram_params->ch[channel].bw = 2; | |
5ff093ab SG |
852 | set_bandwidth_ratio(chan, channel, |
853 | sdram_params->ch[channel].bw, dram->grf); | |
854 | /* | |
7d6c78f5 | 855 | * set cs, using n=3 for detect |
5ff093ab SG |
856 | * CS0, n=1 |
857 | * CS1, n=2 | |
858 | * CS0 & CS1, n = 3 | |
859 | */ | |
7d6c78f5 | 860 | sdram_params->ch[channel].rank = 2, |
5ff093ab SG |
861 | clrsetbits_le32(&publ->pgcr, 0xF << 18, |
862 | (sdram_params->ch[channel].rank | 1) << 18); | |
7d6c78f5 | 863 | |
5ff093ab SG |
864 | /* DS=40ohm,ODT=155ohm */ |
865 | zqcr = 1 << ZDEN_SHIFT | 2 << PU_ONDIE_SHIFT | | |
866 | 2 << PD_ONDIE_SHIFT | 0x19 << PU_OUTPUT_SHIFT | | |
867 | 0x19 << PD_OUTPUT_SHIFT; | |
868 | writel(zqcr, &publ->zq1cr[0]); | |
869 | writel(zqcr, &publ->zq0cr[0]); | |
870 | ||
871 | if (sdram_params->base.dramtype == LPDDR3) { | |
872 | /* LPDDR2/LPDDR3 need to wait DAI complete, max 10us */ | |
873 | udelay(10); | |
874 | send_command_op(pctl, | |
875 | sdram_params->ch[channel].rank | 1, | |
876 | MRS_CMD, 11, | |
877 | sdram_params->base.odt ? 3 : 0); | |
878 | if (channel == 0) { | |
879 | writel(0, &pctl->mrrcfg0); | |
880 | send_command_op(pctl, 1, MRR_CMD, 8, 0); | |
881 | /* S8 */ | |
882 | if ((readl(&pctl->mrrstat0) & 0x3) != 3) { | |
883 | debug("failed!"); | |
884 | return -EREMOTEIO; | |
885 | } | |
886 | } | |
887 | } | |
888 | ||
7d6c78f5 KY |
889 | /* Detect the rank and bit-width with data-training */ |
890 | sdram_rank_bw_detect(dram, channel, sdram_params); | |
5ff093ab SG |
891 | |
892 | if (sdram_params->base.dramtype == LPDDR3) { | |
893 | u32 i; | |
894 | writel(0, &pctl->mrrcfg0); | |
895 | for (i = 0; i < 17; i++) | |
896 | send_command_op(pctl, 1, MRR_CMD, i, 0); | |
897 | } | |
7d6c78f5 | 898 | writel(15, &chan->msch->ddrconf); |
5ff093ab | 899 | move_to_access_state(chan); |
7d6c78f5 KY |
900 | /* DDR3 and LPDDR3 are always 8 bank, no need detect */ |
901 | sdram_params->ch[channel].bk = 3; | |
902 | /* Detect Col and Row number*/ | |
903 | ret = sdram_col_row_detect(dram, channel, sdram_params); | |
904 | if (ret) | |
905 | goto error; | |
5ff093ab | 906 | } |
7d6c78f5 KY |
907 | /* Find NIU DDR configuration */ |
908 | ret = sdram_get_niu_config(sdram_params); | |
909 | if (ret) | |
910 | goto error; | |
911 | /* Find stride setting */ | |
912 | ret = sdram_get_stride(sdram_params); | |
913 | if (ret) | |
914 | goto error; | |
915 | ||
5ff093ab SG |
916 | dram_all_config(dram, sdram_params); |
917 | debug("%s done\n", __func__); | |
918 | ||
919 | return 0; | |
7d6c78f5 KY |
920 | error: |
921 | printf("DRAM init failed!\n"); | |
922 | hang(); | |
5ff093ab | 923 | } |
5ff093ab | 924 | |
dae594f2 SG |
925 | # ifdef CONFIG_ROCKCHIP_FAST_SPL |
926 | static int veyron_init(struct dram_info *priv) | |
927 | { | |
928 | struct udevice *pmic; | |
929 | int ret; | |
930 | ||
3f603cbb | 931 | ret = uclass_first_device_err(UCLASS_PMIC, &pmic); |
dae594f2 SG |
932 | if (ret) |
933 | return ret; | |
934 | ||
935 | /* Slowly raise to max CPU voltage to prevent overshoot */ | |
453c5a92 | 936 | ret = rk8xx_spl_configure_buck(pmic, 1, 1200000); |
dae594f2 SG |
937 | if (ret) |
938 | return ret; | |
939 | udelay(175);/* Must wait for voltage to stabilize, 2mV/us */ | |
453c5a92 | 940 | ret = rk8xx_spl_configure_buck(pmic, 1, 1400000); |
dae594f2 SG |
941 | if (ret) |
942 | return ret; | |
943 | udelay(100);/* Must wait for voltage to stabilize, 2mV/us */ | |
944 | ||
b339b5db | 945 | rk3288_clk_configure_cpu(priv->cru, priv->grf); |
dae594f2 SG |
946 | |
947 | return 0; | |
948 | } | |
949 | # endif | |
950 | ||
5ff093ab SG |
951 | static int setup_sdram(struct udevice *dev) |
952 | { | |
953 | struct dram_info *priv = dev_get_priv(dev); | |
fb4baf5d SG |
954 | struct rk3288_sdram_params *params = dev_get_platdata(dev); |
955 | ||
956 | # ifdef CONFIG_ROCKCHIP_FAST_SPL | |
957 | if (priv->is_veyron) { | |
958 | int ret; | |
959 | ||
960 | ret = veyron_init(priv); | |
961 | if (ret) | |
962 | return ret; | |
963 | } | |
964 | # endif | |
965 | ||
966 | return sdram_init(priv, params); | |
967 | } | |
968 | ||
969 | static int rk3288_dmc_ofdata_to_platdata(struct udevice *dev) | |
970 | { | |
086ec0e2 | 971 | #if !CONFIG_IS_ENABLED(OF_PLATDATA) |
fb4baf5d | 972 | struct rk3288_sdram_params *params = dev_get_platdata(dev); |
7d6c78f5 KY |
973 | int ret; |
974 | ||
975 | /* Rk3288 supports dual-channel, set default channel num to 2 */ | |
976 | params->num_channels = 2; | |
8f1034e6 PT |
977 | ret = dev_read_u32_array(dev, "rockchip,pctl-timing", |
978 | (u32 *)¶ms->pctl_timing, | |
979 | sizeof(params->pctl_timing) / sizeof(u32)); | |
5ff093ab SG |
980 | if (ret) { |
981 | debug("%s: Cannot read rockchip,pctl-timing\n", __func__); | |
982 | return -EINVAL; | |
983 | } | |
8f1034e6 PT |
984 | ret = dev_read_u32_array(dev, "rockchip,phy-timing", |
985 | (u32 *)¶ms->phy_timing, | |
986 | sizeof(params->phy_timing) / sizeof(u32)); | |
5ff093ab SG |
987 | if (ret) { |
988 | debug("%s: Cannot read rockchip,phy-timing\n", __func__); | |
989 | return -EINVAL; | |
990 | } | |
8f1034e6 PT |
991 | ret = dev_read_u32_array(dev, "rockchip,sdram-params", |
992 | (u32 *)¶ms->base, | |
993 | sizeof(params->base) / sizeof(u32)); | |
5ff093ab SG |
994 | if (ret) { |
995 | debug("%s: Cannot read rockchip,sdram-params\n", __func__); | |
996 | return -EINVAL; | |
997 | } | |
fb4baf5d SG |
998 | #ifdef CONFIG_ROCKCHIP_FAST_SPL |
999 | struct dram_info *priv = dev_get_priv(dev); | |
5ff093ab | 1000 | |
fb4baf5d SG |
1001 | priv->is_veyron = !fdt_node_check_compatible(blob, 0, "google,veyron"); |
1002 | #endif | |
1003 | ret = regmap_init_mem(dev, ¶ms->map); | |
1004 | if (ret) | |
1005 | return ret; | |
086ec0e2 | 1006 | #endif |
dae594f2 | 1007 | |
fb4baf5d | 1008 | return 0; |
5ff093ab | 1009 | } |
fb4baf5d | 1010 | #endif /* CONFIG_SPL_BUILD */ |
5ff093ab | 1011 | |
086ec0e2 SG |
1012 | #if CONFIG_IS_ENABLED(OF_PLATDATA) |
1013 | static int conv_of_platdata(struct udevice *dev) | |
1014 | { | |
1015 | struct rk3288_sdram_params *plat = dev_get_platdata(dev); | |
1016 | struct dtd_rockchip_rk3288_dmc *of_plat = &plat->of_plat; | |
7d6c78f5 | 1017 | int ret; |
086ec0e2 | 1018 | |
086ec0e2 SG |
1019 | memcpy(&plat->pctl_timing, of_plat->rockchip_pctl_timing, |
1020 | sizeof(plat->pctl_timing)); | |
1021 | memcpy(&plat->phy_timing, of_plat->rockchip_phy_timing, | |
1022 | sizeof(plat->phy_timing)); | |
1023 | memcpy(&plat->base, of_plat->rockchip_sdram_params, sizeof(plat->base)); | |
7d6c78f5 KY |
1024 | /* Rk3288 supports dual-channel, set default channel num to 2 */ |
1025 | plat->num_channels = 2; | |
086ec0e2 SG |
1026 | ret = regmap_init_mem_platdata(dev, of_plat->reg, |
1027 | ARRAY_SIZE(of_plat->reg) / 2, | |
1028 | &plat->map); | |
1029 | if (ret) | |
1030 | return ret; | |
1031 | ||
1032 | return 0; | |
1033 | } | |
1034 | #endif | |
1035 | ||
5ff093ab SG |
1036 | static int rk3288_dmc_probe(struct udevice *dev) |
1037 | { | |
fb4baf5d SG |
1038 | #ifdef CONFIG_SPL_BUILD |
1039 | struct rk3288_sdram_params *plat = dev_get_platdata(dev); | |
7805cdf4 | 1040 | struct udevice *dev_clk; |
5ff093ab SG |
1041 | struct regmap *map; |
1042 | int ret; | |
7805cdf4 KY |
1043 | #endif |
1044 | struct dram_info *priv = dev_get_priv(dev); | |
5ff093ab | 1045 | |
7805cdf4 KY |
1046 | priv->pmu = syscon_get_first_range(ROCKCHIP_SYSCON_PMU); |
1047 | #ifdef CONFIG_SPL_BUILD | |
086ec0e2 SG |
1048 | #if CONFIG_IS_ENABLED(OF_PLATDATA) |
1049 | ret = conv_of_platdata(dev); | |
1050 | if (ret) | |
1051 | return ret; | |
1052 | #endif | |
5ff093ab SG |
1053 | map = syscon_get_regmap_by_driver_data(ROCKCHIP_SYSCON_NOC); |
1054 | if (IS_ERR(map)) | |
1055 | return PTR_ERR(map); | |
1056 | priv->chan[0].msch = regmap_get_range(map, 0); | |
1057 | priv->chan[1].msch = (struct rk3288_msch *) | |
1058 | (regmap_get_range(map, 0) + 0x80); | |
1059 | ||
2460d18c SG |
1060 | priv->grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF); |
1061 | priv->sgrf = syscon_get_first_range(ROCKCHIP_SYSCON_SGRF); | |
5ff093ab | 1062 | |
fb4baf5d SG |
1063 | priv->chan[0].pctl = regmap_get_range(plat->map, 0); |
1064 | priv->chan[0].publ = regmap_get_range(plat->map, 1); | |
1065 | priv->chan[1].pctl = regmap_get_range(plat->map, 2); | |
1066 | priv->chan[1].publ = regmap_get_range(plat->map, 3); | |
7805cdf4 | 1067 | |
c3aad6f6 | 1068 | ret = rockchip_get_clk(&dev_clk); |
135aa950 SW |
1069 | if (ret) |
1070 | return ret; | |
1071 | priv->ddr_clk.id = CLK_DDR; | |
1072 | ret = clk_request(dev_clk, &priv->ddr_clk); | |
5ff093ab SG |
1073 | if (ret) |
1074 | return ret; | |
1075 | ||
1076 | priv->cru = rockchip_get_cru(); | |
1077 | if (IS_ERR(priv->cru)) | |
1078 | return PTR_ERR(priv->cru); | |
5ff093ab SG |
1079 | ret = setup_sdram(dev); |
1080 | if (ret) | |
1081 | return ret; | |
7805cdf4 KY |
1082 | #else |
1083 | priv->info.base = CONFIG_SYS_SDRAM_BASE; | |
1084 | priv->info.size = rockchip_sdram_size( | |
1085 | (phys_addr_t)&priv->pmu->sys_reg[2]); | |
5ff093ab | 1086 | #endif |
5ff093ab SG |
1087 | |
1088 | return 0; | |
1089 | } | |
1090 | ||
1091 | static int rk3288_dmc_get_info(struct udevice *dev, struct ram_info *info) | |
1092 | { | |
1093 | struct dram_info *priv = dev_get_priv(dev); | |
1094 | ||
1095 | *info = priv->info; | |
1096 | ||
1097 | return 0; | |
1098 | } | |
1099 | ||
1100 | static struct ram_ops rk3288_dmc_ops = { | |
1101 | .get_info = rk3288_dmc_get_info, | |
1102 | }; | |
1103 | ||
1104 | static const struct udevice_id rk3288_dmc_ids[] = { | |
1105 | { .compatible = "rockchip,rk3288-dmc" }, | |
1106 | { } | |
1107 | }; | |
1108 | ||
1109 | U_BOOT_DRIVER(dmc_rk3288) = { | |
086ec0e2 | 1110 | .name = "rockchip_rk3288_dmc", |
5ff093ab SG |
1111 | .id = UCLASS_RAM, |
1112 | .of_match = rk3288_dmc_ids, | |
1113 | .ops = &rk3288_dmc_ops, | |
fb4baf5d SG |
1114 | #ifdef CONFIG_SPL_BUILD |
1115 | .ofdata_to_platdata = rk3288_dmc_ofdata_to_platdata, | |
1116 | #endif | |
5ff093ab SG |
1117 | .probe = rk3288_dmc_probe, |
1118 | .priv_auto_alloc_size = sizeof(struct dram_info), | |
fb4baf5d SG |
1119 | #ifdef CONFIG_SPL_BUILD |
1120 | .platdata_auto_alloc_size = sizeof(struct rk3288_sdram_params), | |
1121 | #endif | |
5ff093ab | 1122 | }; |