Commit 5b67d7010b73a6e17b593f1f3af25dd06996830a
Committed by
Philipp Tomsich
1 parent
b5934cf67c
Exists in
smarc_8mq_lf_v2020.04
and in
17 other branches
rockchip: rk3188: move sdram driver to driver/ram
Since we have CONFIG_RAM framwork and its driver folder, move the driver into it. Signed-off-by: Kever Yang <kever.yang@rock-chips.com> Acked-by: Philipp Tomsich <philipp.tomsich@theobroma-systems.com> Reviewed-by: Philipp Tomsich <philipp.tomsich@theobroma-systems.com>
Showing 4 changed files with 954 additions and 954 deletions Side-by-side Diff
arch/arm/mach-rockchip/rk3188/Makefile
arch/arm/mach-rockchip/rk3188/sdram_rk3188.c
1 | -/* | |
2 | - * (C) Copyright 2015 Google, Inc | |
3 | - * Copyright 2014 Rockchip Inc. | |
4 | - * | |
5 | - * SPDX-License-Identifier: GPL-2.0 | |
6 | - * | |
7 | - * Adapted from the very similar rk3288 ddr init. | |
8 | - */ | |
9 | - | |
10 | -#include <common.h> | |
11 | -#include <clk.h> | |
12 | -#include <dm.h> | |
13 | -#include <dt-structs.h> | |
14 | -#include <errno.h> | |
15 | -#include <ram.h> | |
16 | -#include <regmap.h> | |
17 | -#include <syscon.h> | |
18 | -#include <asm/io.h> | |
19 | -#include <asm/arch/clock.h> | |
20 | -#include <asm/arch/cru_rk3188.h> | |
21 | -#include <asm/arch/ddr_rk3188.h> | |
22 | -#include <asm/arch/grf_rk3188.h> | |
23 | -#include <asm/arch/pmu_rk3188.h> | |
24 | -#include <asm/arch/sdram.h> | |
25 | -#include <asm/arch/sdram_common.h> | |
26 | -#include <linux/err.h> | |
27 | - | |
28 | -DECLARE_GLOBAL_DATA_PTR; | |
29 | - | |
30 | -struct chan_info { | |
31 | - struct rk3288_ddr_pctl *pctl; | |
32 | - struct rk3288_ddr_publ *publ; | |
33 | - struct rk3188_msch *msch; | |
34 | -}; | |
35 | - | |
36 | -struct dram_info { | |
37 | - struct chan_info chan[1]; | |
38 | - struct ram_info info; | |
39 | - struct clk ddr_clk; | |
40 | - struct rk3188_cru *cru; | |
41 | - struct rk3188_grf *grf; | |
42 | - struct rk3188_sgrf *sgrf; | |
43 | - struct rk3188_pmu *pmu; | |
44 | -}; | |
45 | - | |
46 | -struct rk3188_sdram_params { | |
47 | -#if CONFIG_IS_ENABLED(OF_PLATDATA) | |
48 | - struct dtd_rockchip_rk3188_dmc of_plat; | |
49 | -#endif | |
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; | |
56 | -}; | |
57 | - | |
58 | -const int ddrconf_table[] = { | |
59 | - /* | |
60 | - * [5:4] row(13+n) | |
61 | - * [1:0] col(9+n), assume bw=2 | |
62 | - * row col,bw | |
63 | - */ | |
64 | - 0, | |
65 | - ((2 << DDRCONF_ROW_SHIFT) | 1 << DDRCONF_COL_SHIFT), | |
66 | - ((1 << DDRCONF_ROW_SHIFT) | 1 << DDRCONF_COL_SHIFT), | |
67 | - ((0 << DDRCONF_ROW_SHIFT) | 1 << DDRCONF_COL_SHIFT), | |
68 | - ((2 << DDRCONF_ROW_SHIFT) | 2 << DDRCONF_COL_SHIFT), | |
69 | - ((1 << DDRCONF_ROW_SHIFT) | 2 << DDRCONF_COL_SHIFT), | |
70 | - ((0 << DDRCONF_ROW_SHIFT) | 2 << DDRCONF_COL_SHIFT), | |
71 | - ((1 << DDRCONF_ROW_SHIFT) | 0 << DDRCONF_COL_SHIFT), | |
72 | - ((0 << DDRCONF_ROW_SHIFT) | 0 << DDRCONF_COL_SHIFT), | |
73 | - 0, | |
74 | - 0, | |
75 | - 0, | |
76 | - 0, | |
77 | - 0, | |
78 | - 0, | |
79 | - 0, | |
80 | -}; | |
81 | - | |
82 | -#define TEST_PATTEN 0x5aa5f00f | |
83 | -#define DQS_GATE_TRAINING_ERROR_RANK0 (1 << 4) | |
84 | -#define DQS_GATE_TRAINING_ERROR_RANK1 (2 << 4) | |
85 | - | |
86 | -#ifdef CONFIG_SPL_BUILD | |
87 | -static void copy_to_reg(u32 *dest, const u32 *src, u32 n) | |
88 | -{ | |
89 | - int i; | |
90 | - | |
91 | - for (i = 0; i < n / sizeof(u32); i++) { | |
92 | - writel(*src, dest); | |
93 | - src++; | |
94 | - dest++; | |
95 | - } | |
96 | -} | |
97 | - | |
98 | -static void ddr_reset(struct rk3188_cru *cru, u32 ch, u32 ctl, u32 phy) | |
99 | -{ | |
100 | - u32 phy_ctl_srstn_shift = 13; | |
101 | - u32 ctl_psrstn_shift = 11; | |
102 | - u32 ctl_srstn_shift = 10; | |
103 | - u32 phy_psrstn_shift = 9; | |
104 | - u32 phy_srstn_shift = 8; | |
105 | - | |
106 | - rk_clrsetreg(&cru->cru_softrst_con[5], | |
107 | - 1 << phy_ctl_srstn_shift | 1 << ctl_psrstn_shift | | |
108 | - 1 << ctl_srstn_shift | 1 << phy_psrstn_shift | | |
109 | - 1 << phy_srstn_shift, | |
110 | - phy << phy_ctl_srstn_shift | ctl << ctl_psrstn_shift | | |
111 | - ctl << ctl_srstn_shift | phy << phy_psrstn_shift | | |
112 | - phy << phy_srstn_shift); | |
113 | -} | |
114 | - | |
115 | -static void ddr_phy_ctl_reset(struct rk3188_cru *cru, u32 ch, u32 n) | |
116 | -{ | |
117 | - u32 phy_ctl_srstn_shift = 13; | |
118 | - | |
119 | - rk_clrsetreg(&cru->cru_softrst_con[5], | |
120 | - 1 << phy_ctl_srstn_shift, n << phy_ctl_srstn_shift); | |
121 | -} | |
122 | - | |
123 | -static void phy_pctrl_reset(struct rk3188_cru *cru, | |
124 | - struct rk3288_ddr_publ *publ, | |
125 | - int channel) | |
126 | -{ | |
127 | - int i; | |
128 | - | |
129 | - ddr_reset(cru, channel, 1, 1); | |
130 | - udelay(1); | |
131 | - clrbits_le32(&publ->acdllcr, ACDLLCR_DLLSRST); | |
132 | - for (i = 0; i < 4; i++) | |
133 | - clrbits_le32(&publ->datx8[i].dxdllcr, DXDLLCR_DLLSRST); | |
134 | - | |
135 | - udelay(10); | |
136 | - setbits_le32(&publ->acdllcr, ACDLLCR_DLLSRST); | |
137 | - for (i = 0; i < 4; i++) | |
138 | - setbits_le32(&publ->datx8[i].dxdllcr, DXDLLCR_DLLSRST); | |
139 | - | |
140 | - udelay(10); | |
141 | - ddr_reset(cru, channel, 1, 0); | |
142 | - udelay(10); | |
143 | - ddr_reset(cru, channel, 0, 0); | |
144 | - udelay(10); | |
145 | -} | |
146 | - | |
147 | -static void phy_dll_bypass_set(struct rk3288_ddr_publ *publ, | |
148 | - u32 freq) | |
149 | -{ | |
150 | - int i; | |
151 | - | |
152 | - if (freq <= 250000000) { | |
153 | - if (freq <= 150000000) | |
154 | - clrbits_le32(&publ->dllgcr, SBIAS_BYPASS); | |
155 | - else | |
156 | - setbits_le32(&publ->dllgcr, SBIAS_BYPASS); | |
157 | - setbits_le32(&publ->acdllcr, ACDLLCR_DLLDIS); | |
158 | - for (i = 0; i < 4; i++) | |
159 | - setbits_le32(&publ->datx8[i].dxdllcr, | |
160 | - DXDLLCR_DLLDIS); | |
161 | - | |
162 | - setbits_le32(&publ->pir, PIR_DLLBYP); | |
163 | - } else { | |
164 | - clrbits_le32(&publ->dllgcr, SBIAS_BYPASS); | |
165 | - clrbits_le32(&publ->acdllcr, ACDLLCR_DLLDIS); | |
166 | - for (i = 0; i < 4; i++) { | |
167 | - clrbits_le32(&publ->datx8[i].dxdllcr, | |
168 | - DXDLLCR_DLLDIS); | |
169 | - } | |
170 | - | |
171 | - clrbits_le32(&publ->pir, PIR_DLLBYP); | |
172 | - } | |
173 | -} | |
174 | - | |
175 | -static void dfi_cfg(struct rk3288_ddr_pctl *pctl, u32 dramtype) | |
176 | -{ | |
177 | - writel(DFI_INIT_START, &pctl->dfistcfg0); | |
178 | - writel(DFI_DRAM_CLK_SR_EN | DFI_DRAM_CLK_DPD_EN, | |
179 | - &pctl->dfistcfg1); | |
180 | - writel(DFI_PARITY_INTR_EN | DFI_PARITY_EN, &pctl->dfistcfg2); | |
181 | - writel(7 << TLP_RESP_TIME_SHIFT | LP_SR_EN | LP_PD_EN, | |
182 | - &pctl->dfilpcfg0); | |
183 | - | |
184 | - writel(2 << TCTRL_DELAY_TIME_SHIFT, &pctl->dfitctrldelay); | |
185 | - writel(1 << TPHY_WRDATA_TIME_SHIFT, &pctl->dfitphywrdata); | |
186 | - writel(0xf << TPHY_RDLAT_TIME_SHIFT, &pctl->dfitphyrdlat); | |
187 | - writel(2 << TDRAM_CLK_DIS_TIME_SHIFT, &pctl->dfitdramclkdis); | |
188 | - writel(2 << TDRAM_CLK_EN_TIME_SHIFT, &pctl->dfitdramclken); | |
189 | - writel(1, &pctl->dfitphyupdtype0); | |
190 | - | |
191 | - /* cs0 and cs1 write odt enable */ | |
192 | - writel((RANK0_ODT_WRITE_SEL | RANK1_ODT_WRITE_SEL), | |
193 | - &pctl->dfiodtcfg); | |
194 | - /* odt write length */ | |
195 | - writel(7 << ODT_LEN_BL8_W_SHIFT, &pctl->dfiodtcfg1); | |
196 | - /* phyupd and ctrlupd disabled */ | |
197 | - writel(0, &pctl->dfiupdcfg); | |
198 | -} | |
199 | - | |
200 | -static void ddr_set_enable(struct rk3188_grf *grf, uint channel, bool enable) | |
201 | -{ | |
202 | - uint val = 0; | |
203 | - | |
204 | - if (enable) | |
205 | - val = 1 << DDR_16BIT_EN_SHIFT; | |
206 | - | |
207 | - rk_clrsetreg(&grf->ddrc_con0, 1 << DDR_16BIT_EN_SHIFT, val); | |
208 | -} | |
209 | - | |
210 | -static void ddr_set_ddr3_mode(struct rk3188_grf *grf, uint channel, | |
211 | - bool ddr3_mode) | |
212 | -{ | |
213 | - uint mask, val; | |
214 | - | |
215 | - mask = MSCH4_MAINDDR3_MASK << MSCH4_MAINDDR3_SHIFT; | |
216 | - val = ddr3_mode << MSCH4_MAINDDR3_SHIFT; | |
217 | - rk_clrsetreg(&grf->soc_con2, mask, val); | |
218 | -} | |
219 | - | |
220 | -static void ddr_rank_2_row15en(struct rk3188_grf *grf, bool enable) | |
221 | -{ | |
222 | - uint mask, val; | |
223 | - | |
224 | - mask = RANK_TO_ROW15_EN_MASK << RANK_TO_ROW15_EN_SHIFT; | |
225 | - val = enable << RANK_TO_ROW15_EN_SHIFT; | |
226 | - rk_clrsetreg(&grf->soc_con2, mask, val); | |
227 | -} | |
228 | - | |
229 | -static void pctl_cfg(int channel, struct rk3288_ddr_pctl *pctl, | |
230 | - struct rk3188_sdram_params *sdram_params, | |
231 | - struct rk3188_grf *grf) | |
232 | -{ | |
233 | - copy_to_reg(&pctl->togcnt1u, &sdram_params->pctl_timing.togcnt1u, | |
234 | - sizeof(sdram_params->pctl_timing)); | |
235 | - switch (sdram_params->base.dramtype) { | |
236 | - case DDR3: | |
237 | - if (sdram_params->phy_timing.mr[1] & DDR3_DLL_DISABLE) { | |
238 | - writel(sdram_params->pctl_timing.tcl - 3, | |
239 | - &pctl->dfitrddataen); | |
240 | - } else { | |
241 | - writel(sdram_params->pctl_timing.tcl - 2, | |
242 | - &pctl->dfitrddataen); | |
243 | - } | |
244 | - writel(sdram_params->pctl_timing.tcwl - 1, | |
245 | - &pctl->dfitphywrlat); | |
246 | - writel(0 << MDDR_LPDDR2_CLK_STOP_IDLE_SHIFT | DDR3_EN | | |
247 | - DDR2_DDR3_BL_8 | (6 - 4) << TFAW_SHIFT | PD_EXIT_SLOW | | |
248 | - 1 << PD_TYPE_SHIFT | 0 << PD_IDLE_SHIFT, | |
249 | - &pctl->mcfg); | |
250 | - ddr_set_ddr3_mode(grf, channel, true); | |
251 | - ddr_set_enable(grf, channel, true); | |
252 | - break; | |
253 | - } | |
254 | - | |
255 | - setbits_le32(&pctl->scfg, 1); | |
256 | -} | |
257 | - | |
258 | -static void phy_cfg(const struct chan_info *chan, int channel, | |
259 | - struct rk3188_sdram_params *sdram_params) | |
260 | -{ | |
261 | - struct rk3288_ddr_publ *publ = chan->publ; | |
262 | - struct rk3188_msch *msch = chan->msch; | |
263 | - uint ddr_freq_mhz = sdram_params->base.ddr_freq / 1000000; | |
264 | - u32 dinit2; | |
265 | - int i; | |
266 | - | |
267 | - dinit2 = DIV_ROUND_UP(ddr_freq_mhz * 200000, 1000); | |
268 | - /* DDR PHY Timing */ | |
269 | - copy_to_reg(&publ->dtpr[0], &sdram_params->phy_timing.dtpr0, | |
270 | - sizeof(sdram_params->phy_timing)); | |
271 | - writel(sdram_params->base.noc_timing, &msch->ddrtiming); | |
272 | - writel(0x3f, &msch->readlatency); | |
273 | - writel(DIV_ROUND_UP(ddr_freq_mhz * 5120, 1000) << PRT_DLLLOCK_SHIFT | | |
274 | - DIV_ROUND_UP(ddr_freq_mhz * 50, 1000) << PRT_DLLSRST_SHIFT | | |
275 | - 8 << PRT_ITMSRST_SHIFT, &publ->ptr[0]); | |
276 | - writel(DIV_ROUND_UP(ddr_freq_mhz * 500000, 1000) << PRT_DINIT0_SHIFT | | |
277 | - DIV_ROUND_UP(ddr_freq_mhz * 400, 1000) << PRT_DINIT1_SHIFT, | |
278 | - &publ->ptr[1]); | |
279 | - writel(min(dinit2, 0x1ffffU) << PRT_DINIT2_SHIFT | | |
280 | - DIV_ROUND_UP(ddr_freq_mhz * 1000, 1000) << PRT_DINIT3_SHIFT, | |
281 | - &publ->ptr[2]); | |
282 | - | |
283 | - switch (sdram_params->base.dramtype) { | |
284 | - case DDR3: | |
285 | - clrbits_le32(&publ->pgcr, 0x1f); | |
286 | - clrsetbits_le32(&publ->dcr, DDRMD_MASK << DDRMD_SHIFT, | |
287 | - DDRMD_DDR3 << DDRMD_SHIFT); | |
288 | - break; | |
289 | - } | |
290 | - if (sdram_params->base.odt) { | |
291 | - /*dynamic RTT enable */ | |
292 | - for (i = 0; i < 4; i++) | |
293 | - setbits_le32(&publ->datx8[i].dxgcr, DQSRTT | DQRTT); | |
294 | - } else { | |
295 | - /*dynamic RTT disable */ | |
296 | - for (i = 0; i < 4; i++) | |
297 | - clrbits_le32(&publ->datx8[i].dxgcr, DQSRTT | DQRTT); | |
298 | - } | |
299 | -} | |
300 | - | |
301 | -static void phy_init(struct rk3288_ddr_publ *publ) | |
302 | -{ | |
303 | - setbits_le32(&publ->pir, PIR_INIT | PIR_DLLSRST | |
304 | - | PIR_DLLLOCK | PIR_ZCAL | PIR_ITMSRST | PIR_CLRSR); | |
305 | - udelay(1); | |
306 | - while ((readl(&publ->pgsr) & | |
307 | - (PGSR_IDONE | PGSR_DLDONE | PGSR_ZCDONE)) != | |
308 | - (PGSR_IDONE | PGSR_DLDONE | PGSR_ZCDONE)) | |
309 | - ; | |
310 | -} | |
311 | - | |
312 | -static void send_command(struct rk3288_ddr_pctl *pctl, u32 rank, | |
313 | - u32 cmd, u32 arg) | |
314 | -{ | |
315 | - writel((START_CMD | (rank << 20) | arg | cmd), &pctl->mcmd); | |
316 | - udelay(1); | |
317 | - while (readl(&pctl->mcmd) & START_CMD) | |
318 | - ; | |
319 | -} | |
320 | - | |
321 | -static inline void send_command_op(struct rk3288_ddr_pctl *pctl, | |
322 | - u32 rank, u32 cmd, u32 ma, u32 op) | |
323 | -{ | |
324 | - send_command(pctl, rank, cmd, (ma & LPDDR2_MA_MASK) << LPDDR2_MA_SHIFT | | |
325 | - (op & LPDDR2_OP_MASK) << LPDDR2_OP_SHIFT); | |
326 | -} | |
327 | - | |
328 | -static void memory_init(struct rk3288_ddr_publ *publ, | |
329 | - u32 dramtype) | |
330 | -{ | |
331 | - setbits_le32(&publ->pir, | |
332 | - (PIR_INIT | PIR_DRAMINIT | PIR_LOCKBYP | |
333 | - | PIR_ZCALBYP | PIR_CLRSR | PIR_ICPC | |
334 | - | (dramtype == DDR3 ? PIR_DRAMRST : 0))); | |
335 | - udelay(1); | |
336 | - while ((readl(&publ->pgsr) & (PGSR_IDONE | PGSR_DLDONE)) | |
337 | - != (PGSR_IDONE | PGSR_DLDONE)) | |
338 | - ; | |
339 | -} | |
340 | - | |
341 | -static void move_to_config_state(struct rk3288_ddr_publ *publ, | |
342 | - struct rk3288_ddr_pctl *pctl) | |
343 | -{ | |
344 | - unsigned int state; | |
345 | - | |
346 | - while (1) { | |
347 | - state = readl(&pctl->stat) & PCTL_STAT_MSK; | |
348 | - | |
349 | - switch (state) { | |
350 | - case LOW_POWER: | |
351 | - writel(WAKEUP_STATE, &pctl->sctl); | |
352 | - while ((readl(&pctl->stat) & PCTL_STAT_MSK) | |
353 | - != ACCESS) | |
354 | - ; | |
355 | - /* wait DLL lock */ | |
356 | - while ((readl(&publ->pgsr) & PGSR_DLDONE) | |
357 | - != PGSR_DLDONE) | |
358 | - ; | |
359 | - /* | |
360 | - * if at low power state,need wakeup first, | |
361 | - * and then enter the config, so | |
362 | - * fallthrough | |
363 | - */ | |
364 | - case ACCESS: | |
365 | - /* fallthrough */ | |
366 | - case INIT_MEM: | |
367 | - writel(CFG_STATE, &pctl->sctl); | |
368 | - while ((readl(&pctl->stat) & PCTL_STAT_MSK) != CONFIG) | |
369 | - ; | |
370 | - break; | |
371 | - case CONFIG: | |
372 | - return; | |
373 | - default: | |
374 | - break; | |
375 | - } | |
376 | - } | |
377 | -} | |
378 | - | |
379 | -static void set_bandwidth_ratio(const struct chan_info *chan, int channel, | |
380 | - u32 n, struct rk3188_grf *grf) | |
381 | -{ | |
382 | - struct rk3288_ddr_pctl *pctl = chan->pctl; | |
383 | - struct rk3288_ddr_publ *publ = chan->publ; | |
384 | - struct rk3188_msch *msch = chan->msch; | |
385 | - | |
386 | - if (n == 1) { | |
387 | - setbits_le32(&pctl->ppcfg, 1); | |
388 | - ddr_set_enable(grf, channel, 1); | |
389 | - setbits_le32(&msch->ddrtiming, 1 << 31); | |
390 | - /* Data Byte disable*/ | |
391 | - clrbits_le32(&publ->datx8[2].dxgcr, 1); | |
392 | - clrbits_le32(&publ->datx8[3].dxgcr, 1); | |
393 | - /* disable DLL */ | |
394 | - setbits_le32(&publ->datx8[2].dxdllcr, DXDLLCR_DLLDIS); | |
395 | - setbits_le32(&publ->datx8[3].dxdllcr, DXDLLCR_DLLDIS); | |
396 | - } else { | |
397 | - clrbits_le32(&pctl->ppcfg, 1); | |
398 | - ddr_set_enable(grf, channel, 0); | |
399 | - clrbits_le32(&msch->ddrtiming, 1 << 31); | |
400 | - /* Data Byte enable*/ | |
401 | - setbits_le32(&publ->datx8[2].dxgcr, 1); | |
402 | - setbits_le32(&publ->datx8[3].dxgcr, 1); | |
403 | - | |
404 | - /* enable DLL */ | |
405 | - clrbits_le32(&publ->datx8[2].dxdllcr, DXDLLCR_DLLDIS); | |
406 | - clrbits_le32(&publ->datx8[3].dxdllcr, DXDLLCR_DLLDIS); | |
407 | - /* reset DLL */ | |
408 | - clrbits_le32(&publ->datx8[2].dxdllcr, DXDLLCR_DLLSRST); | |
409 | - clrbits_le32(&publ->datx8[3].dxdllcr, DXDLLCR_DLLSRST); | |
410 | - udelay(10); | |
411 | - setbits_le32(&publ->datx8[2].dxdllcr, DXDLLCR_DLLSRST); | |
412 | - setbits_le32(&publ->datx8[3].dxdllcr, DXDLLCR_DLLSRST); | |
413 | - } | |
414 | - setbits_le32(&pctl->dfistcfg0, 1 << 2); | |
415 | -} | |
416 | - | |
417 | -static int data_training(const struct chan_info *chan, int channel, | |
418 | - struct rk3188_sdram_params *sdram_params) | |
419 | -{ | |
420 | - unsigned int j; | |
421 | - int ret = 0; | |
422 | - u32 rank; | |
423 | - int i; | |
424 | - u32 step[2] = { PIR_QSTRN, PIR_RVTRN }; | |
425 | - struct rk3288_ddr_publ *publ = chan->publ; | |
426 | - struct rk3288_ddr_pctl *pctl = chan->pctl; | |
427 | - | |
428 | - /* disable auto refresh */ | |
429 | - writel(0, &pctl->trefi); | |
430 | - | |
431 | - if (sdram_params->base.dramtype != LPDDR3) | |
432 | - setbits_le32(&publ->pgcr, 1 << PGCR_DQSCFG_SHIFT); | |
433 | - rank = sdram_params->ch[channel].rank | 1; | |
434 | - for (j = 0; j < ARRAY_SIZE(step); j++) { | |
435 | - /* | |
436 | - * trigger QSTRN and RVTRN | |
437 | - * clear DTDONE status | |
438 | - */ | |
439 | - setbits_le32(&publ->pir, PIR_CLRSR); | |
440 | - | |
441 | - /* trigger DTT */ | |
442 | - setbits_le32(&publ->pir, | |
443 | - PIR_INIT | step[j] | PIR_LOCKBYP | PIR_ZCALBYP | | |
444 | - PIR_CLRSR); | |
445 | - udelay(1); | |
446 | - /* wait echo byte DTDONE */ | |
447 | - while ((readl(&publ->datx8[0].dxgsr[0]) & rank) | |
448 | - != rank) | |
449 | - ; | |
450 | - while ((readl(&publ->datx8[1].dxgsr[0]) & rank) | |
451 | - != rank) | |
452 | - ; | |
453 | - if (!(readl(&pctl->ppcfg) & 1)) { | |
454 | - while ((readl(&publ->datx8[2].dxgsr[0]) | |
455 | - & rank) != rank) | |
456 | - ; | |
457 | - while ((readl(&publ->datx8[3].dxgsr[0]) | |
458 | - & rank) != rank) | |
459 | - ; | |
460 | - } | |
461 | - if (readl(&publ->pgsr) & | |
462 | - (PGSR_DTERR | PGSR_RVERR | PGSR_RVEIRR)) { | |
463 | - ret = -1; | |
464 | - break; | |
465 | - } | |
466 | - } | |
467 | - /* send some auto refresh to complement the lost while DTT */ | |
468 | - for (i = 0; i < (rank > 1 ? 8 : 4); i++) | |
469 | - send_command(pctl, rank, REF_CMD, 0); | |
470 | - | |
471 | - if (sdram_params->base.dramtype != LPDDR3) | |
472 | - clrbits_le32(&publ->pgcr, 1 << PGCR_DQSCFG_SHIFT); | |
473 | - | |
474 | - /* resume auto refresh */ | |
475 | - writel(sdram_params->pctl_timing.trefi, &pctl->trefi); | |
476 | - | |
477 | - return ret; | |
478 | -} | |
479 | - | |
480 | -static void move_to_access_state(const struct chan_info *chan) | |
481 | -{ | |
482 | - struct rk3288_ddr_publ *publ = chan->publ; | |
483 | - struct rk3288_ddr_pctl *pctl = chan->pctl; | |
484 | - unsigned int state; | |
485 | - | |
486 | - while (1) { | |
487 | - state = readl(&pctl->stat) & PCTL_STAT_MSK; | |
488 | - | |
489 | - switch (state) { | |
490 | - case LOW_POWER: | |
491 | - if (((readl(&pctl->stat) >> LP_TRIG_SHIFT) & | |
492 | - LP_TRIG_MASK) == 1) | |
493 | - return; | |
494 | - | |
495 | - writel(WAKEUP_STATE, &pctl->sctl); | |
496 | - while ((readl(&pctl->stat) & PCTL_STAT_MSK) != ACCESS) | |
497 | - ; | |
498 | - /* wait DLL lock */ | |
499 | - while ((readl(&publ->pgsr) & PGSR_DLDONE) | |
500 | - != PGSR_DLDONE) | |
501 | - ; | |
502 | - break; | |
503 | - case INIT_MEM: | |
504 | - writel(CFG_STATE, &pctl->sctl); | |
505 | - while ((readl(&pctl->stat) & PCTL_STAT_MSK) != CONFIG) | |
506 | - ; | |
507 | - /* fallthrough */ | |
508 | - case CONFIG: | |
509 | - writel(GO_STATE, &pctl->sctl); | |
510 | - while ((readl(&pctl->stat) & PCTL_STAT_MSK) == CONFIG) | |
511 | - ; | |
512 | - break; | |
513 | - case ACCESS: | |
514 | - return; | |
515 | - default: | |
516 | - break; | |
517 | - } | |
518 | - } | |
519 | -} | |
520 | - | |
521 | -static void dram_cfg_rbc(const struct chan_info *chan, u32 chnum, | |
522 | - struct rk3188_sdram_params *sdram_params) | |
523 | -{ | |
524 | - struct rk3288_ddr_publ *publ = chan->publ; | |
525 | - | |
526 | - if (sdram_params->ch[chnum].bk == 3) | |
527 | - clrsetbits_le32(&publ->dcr, PDQ_MASK << PDQ_SHIFT, | |
528 | - 1 << PDQ_SHIFT); | |
529 | - else | |
530 | - clrbits_le32(&publ->dcr, PDQ_MASK << PDQ_SHIFT); | |
531 | - | |
532 | - writel(sdram_params->base.ddrconfig, &chan->msch->ddrconf); | |
533 | -} | |
534 | - | |
535 | -static void dram_all_config(const struct dram_info *dram, | |
536 | - struct rk3188_sdram_params *sdram_params) | |
537 | -{ | |
538 | - unsigned int chan; | |
539 | - u32 sys_reg = 0; | |
540 | - | |
541 | - sys_reg |= sdram_params->base.dramtype << SYS_REG_DDRTYPE_SHIFT; | |
542 | - sys_reg |= (sdram_params->num_channels - 1) << SYS_REG_NUM_CH_SHIFT; | |
543 | - for (chan = 0; chan < sdram_params->num_channels; chan++) { | |
544 | - const struct rk3288_sdram_channel *info = | |
545 | - &sdram_params->ch[chan]; | |
546 | - | |
547 | - sys_reg |= info->row_3_4 << SYS_REG_ROW_3_4_SHIFT(chan); | |
548 | - sys_reg |= 1 << SYS_REG_CHINFO_SHIFT(chan); | |
549 | - sys_reg |= (info->rank - 1) << SYS_REG_RANK_SHIFT(chan); | |
550 | - sys_reg |= (info->col - 9) << SYS_REG_COL_SHIFT(chan); | |
551 | - sys_reg |= info->bk == 3 ? 0 : 1 << SYS_REG_BK_SHIFT(chan); | |
552 | - sys_reg |= (info->cs0_row - 13) << SYS_REG_CS0_ROW_SHIFT(chan); | |
553 | - sys_reg |= (info->cs1_row - 13) << SYS_REG_CS1_ROW_SHIFT(chan); | |
554 | - sys_reg |= (2 >> info->bw) << SYS_REG_BW_SHIFT(chan); | |
555 | - sys_reg |= (2 >> info->dbw) << SYS_REG_DBW_SHIFT(chan); | |
556 | - | |
557 | - dram_cfg_rbc(&dram->chan[chan], chan, sdram_params); | |
558 | - } | |
559 | - if (sdram_params->ch[0].rank == 2) | |
560 | - ddr_rank_2_row15en(dram->grf, 0); | |
561 | - else | |
562 | - ddr_rank_2_row15en(dram->grf, 1); | |
563 | - | |
564 | - writel(sys_reg, &dram->pmu->sys_reg[2]); | |
565 | -} | |
566 | - | |
567 | -static int sdram_rank_bw_detect(struct dram_info *dram, int channel, | |
568 | - struct rk3188_sdram_params *sdram_params) | |
569 | -{ | |
570 | - int reg; | |
571 | - int need_trainig = 0; | |
572 | - const struct chan_info *chan = &dram->chan[channel]; | |
573 | - struct rk3288_ddr_publ *publ = chan->publ; | |
574 | - | |
575 | - ddr_rank_2_row15en(dram->grf, 0); | |
576 | - | |
577 | - if (data_training(chan, channel, sdram_params) < 0) { | |
578 | - printf("first data training fail!\n"); | |
579 | - reg = readl(&publ->datx8[0].dxgsr[0]); | |
580 | - /* Check the result for rank 0 */ | |
581 | - if ((channel == 0) && (reg & DQS_GATE_TRAINING_ERROR_RANK0)) { | |
582 | - printf("data training fail!\n"); | |
583 | - return -EIO; | |
584 | - } | |
585 | - | |
586 | - /* Check the result for rank 1 */ | |
587 | - if (reg & DQS_GATE_TRAINING_ERROR_RANK1) { | |
588 | - sdram_params->ch[channel].rank = 1; | |
589 | - clrsetbits_le32(&publ->pgcr, 0xF << 18, | |
590 | - sdram_params->ch[channel].rank << 18); | |
591 | - need_trainig = 1; | |
592 | - } | |
593 | - reg = readl(&publ->datx8[2].dxgsr[0]); | |
594 | - if (reg & (1 << 4)) { | |
595 | - sdram_params->ch[channel].bw = 1; | |
596 | - set_bandwidth_ratio(chan, channel, | |
597 | - sdram_params->ch[channel].bw, | |
598 | - dram->grf); | |
599 | - need_trainig = 1; | |
600 | - } | |
601 | - } | |
602 | - /* Assume the Die bit width are the same with the chip bit width */ | |
603 | - sdram_params->ch[channel].dbw = sdram_params->ch[channel].bw; | |
604 | - | |
605 | - if (need_trainig && | |
606 | - (data_training(chan, channel, sdram_params) < 0)) { | |
607 | - if (sdram_params->base.dramtype == LPDDR3) { | |
608 | - ddr_phy_ctl_reset(dram->cru, channel, 1); | |
609 | - udelay(10); | |
610 | - ddr_phy_ctl_reset(dram->cru, channel, 0); | |
611 | - udelay(10); | |
612 | - } | |
613 | - printf("2nd data training failed!"); | |
614 | - return -EIO; | |
615 | - } | |
616 | - | |
617 | - return 0; | |
618 | -} | |
619 | - | |
620 | -/* | |
621 | - * Detect ram columns and rows. | |
622 | - * @dram: dram info struct | |
623 | - * @channel: channel number to handle | |
624 | - * @sdram_params: sdram parameters, function will fill in col and row values | |
625 | - * | |
626 | - * Returns 0 or negative on error. | |
627 | - */ | |
628 | -static int sdram_col_row_detect(struct dram_info *dram, int channel, | |
629 | - struct rk3188_sdram_params *sdram_params) | |
630 | -{ | |
631 | - int row, col; | |
632 | - unsigned int addr; | |
633 | - const struct chan_info *chan = &dram->chan[channel]; | |
634 | - struct rk3288_ddr_pctl *pctl = chan->pctl; | |
635 | - struct rk3288_ddr_publ *publ = chan->publ; | |
636 | - int ret = 0; | |
637 | - | |
638 | - /* Detect col */ | |
639 | - for (col = 11; col >= 9; col--) { | |
640 | - writel(0, CONFIG_SYS_SDRAM_BASE); | |
641 | - addr = CONFIG_SYS_SDRAM_BASE + | |
642 | - (1 << (col + sdram_params->ch[channel].bw - 1)); | |
643 | - writel(TEST_PATTEN, addr); | |
644 | - if ((readl(addr) == TEST_PATTEN) && | |
645 | - (readl(CONFIG_SYS_SDRAM_BASE) == 0)) | |
646 | - break; | |
647 | - } | |
648 | - if (col == 8) { | |
649 | - printf("Col detect error\n"); | |
650 | - ret = -EINVAL; | |
651 | - goto out; | |
652 | - } else { | |
653 | - sdram_params->ch[channel].col = col; | |
654 | - } | |
655 | - | |
656 | - ddr_rank_2_row15en(dram->grf, 1); | |
657 | - move_to_config_state(publ, pctl); | |
658 | - writel(1, &chan->msch->ddrconf); | |
659 | - move_to_access_state(chan); | |
660 | - /* Detect row, max 15,min13 in rk3188*/ | |
661 | - for (row = 16; row >= 13; row--) { | |
662 | - writel(0, CONFIG_SYS_SDRAM_BASE); | |
663 | - addr = CONFIG_SYS_SDRAM_BASE + (1 << (row + 15 - 1)); | |
664 | - writel(TEST_PATTEN, addr); | |
665 | - if ((readl(addr) == TEST_PATTEN) && | |
666 | - (readl(CONFIG_SYS_SDRAM_BASE) == 0)) | |
667 | - break; | |
668 | - } | |
669 | - if (row == 12) { | |
670 | - printf("Row detect error\n"); | |
671 | - ret = -EINVAL; | |
672 | - } else { | |
673 | - sdram_params->ch[channel].cs1_row = row; | |
674 | - sdram_params->ch[channel].row_3_4 = 0; | |
675 | - debug("chn %d col %d, row %d\n", channel, col, row); | |
676 | - sdram_params->ch[channel].cs0_row = row; | |
677 | - } | |
678 | - | |
679 | -out: | |
680 | - return ret; | |
681 | -} | |
682 | - | |
683 | -static int sdram_get_niu_config(struct rk3188_sdram_params *sdram_params) | |
684 | -{ | |
685 | - int i, tmp, size, ret = 0; | |
686 | - | |
687 | - tmp = sdram_params->ch[0].col - 9; | |
688 | - tmp -= (sdram_params->ch[0].bw == 2) ? 0 : 1; | |
689 | - tmp |= ((sdram_params->ch[0].cs0_row - 13) << 4); | |
690 | - size = sizeof(ddrconf_table)/sizeof(ddrconf_table[0]); | |
691 | - for (i = 0; i < size; i++) | |
692 | - if (tmp == ddrconf_table[i]) | |
693 | - break; | |
694 | - if (i >= size) { | |
695 | - printf("niu config not found\n"); | |
696 | - ret = -EINVAL; | |
697 | - } else { | |
698 | - debug("niu config %d\n", i); | |
699 | - sdram_params->base.ddrconfig = i; | |
700 | - } | |
701 | - | |
702 | - return ret; | |
703 | -} | |
704 | - | |
705 | -static int sdram_init(struct dram_info *dram, | |
706 | - struct rk3188_sdram_params *sdram_params) | |
707 | -{ | |
708 | - int channel; | |
709 | - int zqcr; | |
710 | - int ret; | |
711 | - | |
712 | - if ((sdram_params->base.dramtype == DDR3 && | |
713 | - sdram_params->base.ddr_freq > 800000000)) { | |
714 | - printf("SDRAM frequency is too high!"); | |
715 | - return -E2BIG; | |
716 | - } | |
717 | - | |
718 | - ret = clk_set_rate(&dram->ddr_clk, sdram_params->base.ddr_freq); | |
719 | - if (ret) { | |
720 | - printf("Could not set DDR clock\n"); | |
721 | - return ret; | |
722 | - } | |
723 | - | |
724 | - for (channel = 0; channel < 1; channel++) { | |
725 | - const struct chan_info *chan = &dram->chan[channel]; | |
726 | - struct rk3288_ddr_pctl *pctl = chan->pctl; | |
727 | - struct rk3288_ddr_publ *publ = chan->publ; | |
728 | - | |
729 | - phy_pctrl_reset(dram->cru, publ, channel); | |
730 | - phy_dll_bypass_set(publ, sdram_params->base.ddr_freq); | |
731 | - | |
732 | - dfi_cfg(pctl, sdram_params->base.dramtype); | |
733 | - | |
734 | - pctl_cfg(channel, pctl, sdram_params, dram->grf); | |
735 | - | |
736 | - phy_cfg(chan, channel, sdram_params); | |
737 | - | |
738 | - phy_init(publ); | |
739 | - | |
740 | - writel(POWER_UP_START, &pctl->powctl); | |
741 | - while (!(readl(&pctl->powstat) & POWER_UP_DONE)) | |
742 | - ; | |
743 | - | |
744 | - memory_init(publ, sdram_params->base.dramtype); | |
745 | - move_to_config_state(publ, pctl); | |
746 | - | |
747 | - /* Using 32bit bus width for detect */ | |
748 | - sdram_params->ch[channel].bw = 2; | |
749 | - set_bandwidth_ratio(chan, channel, | |
750 | - sdram_params->ch[channel].bw, dram->grf); | |
751 | - /* | |
752 | - * set cs, using n=3 for detect | |
753 | - * CS0, n=1 | |
754 | - * CS1, n=2 | |
755 | - * CS0 & CS1, n = 3 | |
756 | - */ | |
757 | - sdram_params->ch[channel].rank = 2, | |
758 | - clrsetbits_le32(&publ->pgcr, 0xF << 18, | |
759 | - (sdram_params->ch[channel].rank | 1) << 18); | |
760 | - | |
761 | - /* DS=40ohm,ODT=155ohm */ | |
762 | - zqcr = 1 << ZDEN_SHIFT | 2 << PU_ONDIE_SHIFT | | |
763 | - 2 << PD_ONDIE_SHIFT | 0x19 << PU_OUTPUT_SHIFT | | |
764 | - 0x19 << PD_OUTPUT_SHIFT; | |
765 | - writel(zqcr, &publ->zq1cr[0]); | |
766 | - writel(zqcr, &publ->zq0cr[0]); | |
767 | - | |
768 | - /* Detect the rank and bit-width with data-training */ | |
769 | - writel(1, &chan->msch->ddrconf); | |
770 | - sdram_rank_bw_detect(dram, channel, sdram_params); | |
771 | - | |
772 | - if (sdram_params->base.dramtype == LPDDR3) { | |
773 | - u32 i; | |
774 | - writel(0, &pctl->mrrcfg0); | |
775 | - for (i = 0; i < 17; i++) | |
776 | - send_command_op(pctl, 1, MRR_CMD, i, 0); | |
777 | - } | |
778 | - writel(4, &chan->msch->ddrconf); | |
779 | - move_to_access_state(chan); | |
780 | - /* DDR3 and LPDDR3 are always 8 bank, no need detect */ | |
781 | - sdram_params->ch[channel].bk = 3; | |
782 | - /* Detect Col and Row number*/ | |
783 | - ret = sdram_col_row_detect(dram, channel, sdram_params); | |
784 | - if (ret) | |
785 | - goto error; | |
786 | - } | |
787 | - /* Find NIU DDR configuration */ | |
788 | - ret = sdram_get_niu_config(sdram_params); | |
789 | - if (ret) | |
790 | - goto error; | |
791 | - | |
792 | - dram_all_config(dram, sdram_params); | |
793 | - debug("%s done\n", __func__); | |
794 | - | |
795 | - return 0; | |
796 | -error: | |
797 | - printf("DRAM init failed!\n"); | |
798 | - hang(); | |
799 | -} | |
800 | - | |
801 | -static int setup_sdram(struct udevice *dev) | |
802 | -{ | |
803 | - struct dram_info *priv = dev_get_priv(dev); | |
804 | - struct rk3188_sdram_params *params = dev_get_platdata(dev); | |
805 | - | |
806 | - return sdram_init(priv, params); | |
807 | -} | |
808 | - | |
809 | -static int rk3188_dmc_ofdata_to_platdata(struct udevice *dev) | |
810 | -{ | |
811 | -#if !CONFIG_IS_ENABLED(OF_PLATDATA) | |
812 | - struct rk3188_sdram_params *params = dev_get_platdata(dev); | |
813 | - int ret; | |
814 | - | |
815 | - /* rk3188 supports only one-channel */ | |
816 | - params->num_channels = 1; | |
817 | - ret = dev_read_u32_array(dev, "rockchip,pctl-timing", | |
818 | - (u32 *)¶ms->pctl_timing, | |
819 | - sizeof(params->pctl_timing) / sizeof(u32)); | |
820 | - if (ret) { | |
821 | - printf("%s: Cannot read rockchip,pctl-timing\n", __func__); | |
822 | - return -EINVAL; | |
823 | - } | |
824 | - ret = dev_read_u32_array(dev, "rockchip,phy-timing", | |
825 | - (u32 *)¶ms->phy_timing, | |
826 | - sizeof(params->phy_timing) / sizeof(u32)); | |
827 | - if (ret) { | |
828 | - printf("%s: Cannot read rockchip,phy-timing\n", __func__); | |
829 | - return -EINVAL; | |
830 | - } | |
831 | - ret = dev_read_u32_array(dev, "rockchip,sdram-params", | |
832 | - (u32 *)¶ms->base, | |
833 | - sizeof(params->base) / sizeof(u32)); | |
834 | - if (ret) { | |
835 | - printf("%s: Cannot read rockchip,sdram-params\n", __func__); | |
836 | - return -EINVAL; | |
837 | - } | |
838 | - ret = regmap_init_mem(dev, ¶ms->map); | |
839 | - if (ret) | |
840 | - return ret; | |
841 | -#endif | |
842 | - | |
843 | - return 0; | |
844 | -} | |
845 | -#endif /* CONFIG_SPL_BUILD */ | |
846 | - | |
847 | -#if CONFIG_IS_ENABLED(OF_PLATDATA) | |
848 | -static int conv_of_platdata(struct udevice *dev) | |
849 | -{ | |
850 | - struct rk3188_sdram_params *plat = dev_get_platdata(dev); | |
851 | - struct dtd_rockchip_rk3188_dmc *of_plat = &plat->of_plat; | |
852 | - int ret; | |
853 | - | |
854 | - memcpy(&plat->pctl_timing, of_plat->rockchip_pctl_timing, | |
855 | - sizeof(plat->pctl_timing)); | |
856 | - memcpy(&plat->phy_timing, of_plat->rockchip_phy_timing, | |
857 | - sizeof(plat->phy_timing)); | |
858 | - memcpy(&plat->base, of_plat->rockchip_sdram_params, sizeof(plat->base)); | |
859 | - /* rk3188 supports dual-channel, set default channel num to 2 */ | |
860 | - plat->num_channels = 1; | |
861 | - ret = regmap_init_mem_platdata(dev, of_plat->reg, | |
862 | - ARRAY_SIZE(of_plat->reg) / 2, | |
863 | - &plat->map); | |
864 | - if (ret) | |
865 | - return ret; | |
866 | - | |
867 | - return 0; | |
868 | -} | |
869 | -#endif | |
870 | - | |
871 | -static int rk3188_dmc_probe(struct udevice *dev) | |
872 | -{ | |
873 | -#ifdef CONFIG_SPL_BUILD | |
874 | - struct rk3188_sdram_params *plat = dev_get_platdata(dev); | |
875 | - struct regmap *map; | |
876 | - struct udevice *dev_clk; | |
877 | - int ret; | |
878 | -#endif | |
879 | - struct dram_info *priv = dev_get_priv(dev); | |
880 | - | |
881 | - priv->pmu = syscon_get_first_range(ROCKCHIP_SYSCON_PMU); | |
882 | - | |
883 | -#ifdef CONFIG_SPL_BUILD | |
884 | -#if CONFIG_IS_ENABLED(OF_PLATDATA) | |
885 | - ret = conv_of_platdata(dev); | |
886 | - if (ret) | |
887 | - return ret; | |
888 | -#endif | |
889 | - map = syscon_get_regmap_by_driver_data(ROCKCHIP_SYSCON_NOC); | |
890 | - if (IS_ERR(map)) | |
891 | - return PTR_ERR(map); | |
892 | - priv->chan[0].msch = regmap_get_range(map, 0); | |
893 | - | |
894 | - priv->grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF); | |
895 | - | |
896 | - priv->chan[0].pctl = regmap_get_range(plat->map, 0); | |
897 | - priv->chan[0].publ = regmap_get_range(plat->map, 1); | |
898 | - | |
899 | - ret = rockchip_get_clk(&dev_clk); | |
900 | - if (ret) | |
901 | - return ret; | |
902 | - priv->ddr_clk.id = CLK_DDR; | |
903 | - ret = clk_request(dev_clk, &priv->ddr_clk); | |
904 | - if (ret) | |
905 | - return ret; | |
906 | - | |
907 | - priv->cru = rockchip_get_cru(); | |
908 | - if (IS_ERR(priv->cru)) | |
909 | - return PTR_ERR(priv->cru); | |
910 | - ret = setup_sdram(dev); | |
911 | - if (ret) | |
912 | - return ret; | |
913 | -#else | |
914 | - priv->info.base = CONFIG_SYS_SDRAM_BASE; | |
915 | - priv->info.size = rockchip_sdram_size( | |
916 | - (phys_addr_t)&priv->pmu->sys_reg[2]); | |
917 | -#endif | |
918 | - | |
919 | - return 0; | |
920 | -} | |
921 | - | |
922 | -static int rk3188_dmc_get_info(struct udevice *dev, struct ram_info *info) | |
923 | -{ | |
924 | - struct dram_info *priv = dev_get_priv(dev); | |
925 | - | |
926 | - *info = priv->info; | |
927 | - | |
928 | - return 0; | |
929 | -} | |
930 | - | |
931 | -static struct ram_ops rk3188_dmc_ops = { | |
932 | - .get_info = rk3188_dmc_get_info, | |
933 | -}; | |
934 | - | |
935 | -static const struct udevice_id rk3188_dmc_ids[] = { | |
936 | - { .compatible = "rockchip,rk3188-dmc" }, | |
937 | - { } | |
938 | -}; | |
939 | - | |
940 | -U_BOOT_DRIVER(dmc_rk3188) = { | |
941 | - .name = "rockchip_rk3188_dmc", | |
942 | - .id = UCLASS_RAM, | |
943 | - .of_match = rk3188_dmc_ids, | |
944 | - .ops = &rk3188_dmc_ops, | |
945 | -#ifdef CONFIG_SPL_BUILD | |
946 | - .ofdata_to_platdata = rk3188_dmc_ofdata_to_platdata, | |
947 | -#endif | |
948 | - .probe = rk3188_dmc_probe, | |
949 | - .priv_auto_alloc_size = sizeof(struct dram_info), | |
950 | -#ifdef CONFIG_SPL_BUILD | |
951 | - .platdata_auto_alloc_size = sizeof(struct rk3188_sdram_params), | |
952 | -#endif | |
953 | -}; |
drivers/ram/rockchip/Makefile
drivers/ram/rockchip/sdram_rk3188.c
1 | +/* | |
2 | + * (C) Copyright 2015 Google, Inc | |
3 | + * Copyright 2014 Rockchip Inc. | |
4 | + * | |
5 | + * SPDX-License-Identifier: GPL-2.0 | |
6 | + * | |
7 | + * Adapted from the very similar rk3288 ddr init. | |
8 | + */ | |
9 | + | |
10 | +#include <common.h> | |
11 | +#include <clk.h> | |
12 | +#include <dm.h> | |
13 | +#include <dt-structs.h> | |
14 | +#include <errno.h> | |
15 | +#include <ram.h> | |
16 | +#include <regmap.h> | |
17 | +#include <syscon.h> | |
18 | +#include <asm/io.h> | |
19 | +#include <asm/arch/clock.h> | |
20 | +#include <asm/arch/cru_rk3188.h> | |
21 | +#include <asm/arch/ddr_rk3188.h> | |
22 | +#include <asm/arch/grf_rk3188.h> | |
23 | +#include <asm/arch/pmu_rk3188.h> | |
24 | +#include <asm/arch/sdram.h> | |
25 | +#include <asm/arch/sdram_common.h> | |
26 | +#include <linux/err.h> | |
27 | + | |
28 | +DECLARE_GLOBAL_DATA_PTR; | |
29 | + | |
30 | +struct chan_info { | |
31 | + struct rk3288_ddr_pctl *pctl; | |
32 | + struct rk3288_ddr_publ *publ; | |
33 | + struct rk3188_msch *msch; | |
34 | +}; | |
35 | + | |
36 | +struct dram_info { | |
37 | + struct chan_info chan[1]; | |
38 | + struct ram_info info; | |
39 | + struct clk ddr_clk; | |
40 | + struct rk3188_cru *cru; | |
41 | + struct rk3188_grf *grf; | |
42 | + struct rk3188_sgrf *sgrf; | |
43 | + struct rk3188_pmu *pmu; | |
44 | +}; | |
45 | + | |
46 | +struct rk3188_sdram_params { | |
47 | +#if CONFIG_IS_ENABLED(OF_PLATDATA) | |
48 | + struct dtd_rockchip_rk3188_dmc of_plat; | |
49 | +#endif | |
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; | |
56 | +}; | |
57 | + | |
58 | +const int ddrconf_table[] = { | |
59 | + /* | |
60 | + * [5:4] row(13+n) | |
61 | + * [1:0] col(9+n), assume bw=2 | |
62 | + * row col,bw | |
63 | + */ | |
64 | + 0, | |
65 | + ((2 << DDRCONF_ROW_SHIFT) | 1 << DDRCONF_COL_SHIFT), | |
66 | + ((1 << DDRCONF_ROW_SHIFT) | 1 << DDRCONF_COL_SHIFT), | |
67 | + ((0 << DDRCONF_ROW_SHIFT) | 1 << DDRCONF_COL_SHIFT), | |
68 | + ((2 << DDRCONF_ROW_SHIFT) | 2 << DDRCONF_COL_SHIFT), | |
69 | + ((1 << DDRCONF_ROW_SHIFT) | 2 << DDRCONF_COL_SHIFT), | |
70 | + ((0 << DDRCONF_ROW_SHIFT) | 2 << DDRCONF_COL_SHIFT), | |
71 | + ((1 << DDRCONF_ROW_SHIFT) | 0 << DDRCONF_COL_SHIFT), | |
72 | + ((0 << DDRCONF_ROW_SHIFT) | 0 << DDRCONF_COL_SHIFT), | |
73 | + 0, | |
74 | + 0, | |
75 | + 0, | |
76 | + 0, | |
77 | + 0, | |
78 | + 0, | |
79 | + 0, | |
80 | +}; | |
81 | + | |
82 | +#define TEST_PATTEN 0x5aa5f00f | |
83 | +#define DQS_GATE_TRAINING_ERROR_RANK0 (1 << 4) | |
84 | +#define DQS_GATE_TRAINING_ERROR_RANK1 (2 << 4) | |
85 | + | |
86 | +#ifdef CONFIG_SPL_BUILD | |
87 | +static void copy_to_reg(u32 *dest, const u32 *src, u32 n) | |
88 | +{ | |
89 | + int i; | |
90 | + | |
91 | + for (i = 0; i < n / sizeof(u32); i++) { | |
92 | + writel(*src, dest); | |
93 | + src++; | |
94 | + dest++; | |
95 | + } | |
96 | +} | |
97 | + | |
98 | +static void ddr_reset(struct rk3188_cru *cru, u32 ch, u32 ctl, u32 phy) | |
99 | +{ | |
100 | + u32 phy_ctl_srstn_shift = 13; | |
101 | + u32 ctl_psrstn_shift = 11; | |
102 | + u32 ctl_srstn_shift = 10; | |
103 | + u32 phy_psrstn_shift = 9; | |
104 | + u32 phy_srstn_shift = 8; | |
105 | + | |
106 | + rk_clrsetreg(&cru->cru_softrst_con[5], | |
107 | + 1 << phy_ctl_srstn_shift | 1 << ctl_psrstn_shift | | |
108 | + 1 << ctl_srstn_shift | 1 << phy_psrstn_shift | | |
109 | + 1 << phy_srstn_shift, | |
110 | + phy << phy_ctl_srstn_shift | ctl << ctl_psrstn_shift | | |
111 | + ctl << ctl_srstn_shift | phy << phy_psrstn_shift | | |
112 | + phy << phy_srstn_shift); | |
113 | +} | |
114 | + | |
115 | +static void ddr_phy_ctl_reset(struct rk3188_cru *cru, u32 ch, u32 n) | |
116 | +{ | |
117 | + u32 phy_ctl_srstn_shift = 13; | |
118 | + | |
119 | + rk_clrsetreg(&cru->cru_softrst_con[5], | |
120 | + 1 << phy_ctl_srstn_shift, n << phy_ctl_srstn_shift); | |
121 | +} | |
122 | + | |
123 | +static void phy_pctrl_reset(struct rk3188_cru *cru, | |
124 | + struct rk3288_ddr_publ *publ, | |
125 | + int channel) | |
126 | +{ | |
127 | + int i; | |
128 | + | |
129 | + ddr_reset(cru, channel, 1, 1); | |
130 | + udelay(1); | |
131 | + clrbits_le32(&publ->acdllcr, ACDLLCR_DLLSRST); | |
132 | + for (i = 0; i < 4; i++) | |
133 | + clrbits_le32(&publ->datx8[i].dxdllcr, DXDLLCR_DLLSRST); | |
134 | + | |
135 | + udelay(10); | |
136 | + setbits_le32(&publ->acdllcr, ACDLLCR_DLLSRST); | |
137 | + for (i = 0; i < 4; i++) | |
138 | + setbits_le32(&publ->datx8[i].dxdllcr, DXDLLCR_DLLSRST); | |
139 | + | |
140 | + udelay(10); | |
141 | + ddr_reset(cru, channel, 1, 0); | |
142 | + udelay(10); | |
143 | + ddr_reset(cru, channel, 0, 0); | |
144 | + udelay(10); | |
145 | +} | |
146 | + | |
147 | +static void phy_dll_bypass_set(struct rk3288_ddr_publ *publ, | |
148 | + u32 freq) | |
149 | +{ | |
150 | + int i; | |
151 | + | |
152 | + if (freq <= 250000000) { | |
153 | + if (freq <= 150000000) | |
154 | + clrbits_le32(&publ->dllgcr, SBIAS_BYPASS); | |
155 | + else | |
156 | + setbits_le32(&publ->dllgcr, SBIAS_BYPASS); | |
157 | + setbits_le32(&publ->acdllcr, ACDLLCR_DLLDIS); | |
158 | + for (i = 0; i < 4; i++) | |
159 | + setbits_le32(&publ->datx8[i].dxdllcr, | |
160 | + DXDLLCR_DLLDIS); | |
161 | + | |
162 | + setbits_le32(&publ->pir, PIR_DLLBYP); | |
163 | + } else { | |
164 | + clrbits_le32(&publ->dllgcr, SBIAS_BYPASS); | |
165 | + clrbits_le32(&publ->acdllcr, ACDLLCR_DLLDIS); | |
166 | + for (i = 0; i < 4; i++) { | |
167 | + clrbits_le32(&publ->datx8[i].dxdllcr, | |
168 | + DXDLLCR_DLLDIS); | |
169 | + } | |
170 | + | |
171 | + clrbits_le32(&publ->pir, PIR_DLLBYP); | |
172 | + } | |
173 | +} | |
174 | + | |
175 | +static void dfi_cfg(struct rk3288_ddr_pctl *pctl, u32 dramtype) | |
176 | +{ | |
177 | + writel(DFI_INIT_START, &pctl->dfistcfg0); | |
178 | + writel(DFI_DRAM_CLK_SR_EN | DFI_DRAM_CLK_DPD_EN, | |
179 | + &pctl->dfistcfg1); | |
180 | + writel(DFI_PARITY_INTR_EN | DFI_PARITY_EN, &pctl->dfistcfg2); | |
181 | + writel(7 << TLP_RESP_TIME_SHIFT | LP_SR_EN | LP_PD_EN, | |
182 | + &pctl->dfilpcfg0); | |
183 | + | |
184 | + writel(2 << TCTRL_DELAY_TIME_SHIFT, &pctl->dfitctrldelay); | |
185 | + writel(1 << TPHY_WRDATA_TIME_SHIFT, &pctl->dfitphywrdata); | |
186 | + writel(0xf << TPHY_RDLAT_TIME_SHIFT, &pctl->dfitphyrdlat); | |
187 | + writel(2 << TDRAM_CLK_DIS_TIME_SHIFT, &pctl->dfitdramclkdis); | |
188 | + writel(2 << TDRAM_CLK_EN_TIME_SHIFT, &pctl->dfitdramclken); | |
189 | + writel(1, &pctl->dfitphyupdtype0); | |
190 | + | |
191 | + /* cs0 and cs1 write odt enable */ | |
192 | + writel((RANK0_ODT_WRITE_SEL | RANK1_ODT_WRITE_SEL), | |
193 | + &pctl->dfiodtcfg); | |
194 | + /* odt write length */ | |
195 | + writel(7 << ODT_LEN_BL8_W_SHIFT, &pctl->dfiodtcfg1); | |
196 | + /* phyupd and ctrlupd disabled */ | |
197 | + writel(0, &pctl->dfiupdcfg); | |
198 | +} | |
199 | + | |
200 | +static void ddr_set_enable(struct rk3188_grf *grf, uint channel, bool enable) | |
201 | +{ | |
202 | + uint val = 0; | |
203 | + | |
204 | + if (enable) | |
205 | + val = 1 << DDR_16BIT_EN_SHIFT; | |
206 | + | |
207 | + rk_clrsetreg(&grf->ddrc_con0, 1 << DDR_16BIT_EN_SHIFT, val); | |
208 | +} | |
209 | + | |
210 | +static void ddr_set_ddr3_mode(struct rk3188_grf *grf, uint channel, | |
211 | + bool ddr3_mode) | |
212 | +{ | |
213 | + uint mask, val; | |
214 | + | |
215 | + mask = MSCH4_MAINDDR3_MASK << MSCH4_MAINDDR3_SHIFT; | |
216 | + val = ddr3_mode << MSCH4_MAINDDR3_SHIFT; | |
217 | + rk_clrsetreg(&grf->soc_con2, mask, val); | |
218 | +} | |
219 | + | |
220 | +static void ddr_rank_2_row15en(struct rk3188_grf *grf, bool enable) | |
221 | +{ | |
222 | + uint mask, val; | |
223 | + | |
224 | + mask = RANK_TO_ROW15_EN_MASK << RANK_TO_ROW15_EN_SHIFT; | |
225 | + val = enable << RANK_TO_ROW15_EN_SHIFT; | |
226 | + rk_clrsetreg(&grf->soc_con2, mask, val); | |
227 | +} | |
228 | + | |
229 | +static void pctl_cfg(int channel, struct rk3288_ddr_pctl *pctl, | |
230 | + struct rk3188_sdram_params *sdram_params, | |
231 | + struct rk3188_grf *grf) | |
232 | +{ | |
233 | + copy_to_reg(&pctl->togcnt1u, &sdram_params->pctl_timing.togcnt1u, | |
234 | + sizeof(sdram_params->pctl_timing)); | |
235 | + switch (sdram_params->base.dramtype) { | |
236 | + case DDR3: | |
237 | + if (sdram_params->phy_timing.mr[1] & DDR3_DLL_DISABLE) { | |
238 | + writel(sdram_params->pctl_timing.tcl - 3, | |
239 | + &pctl->dfitrddataen); | |
240 | + } else { | |
241 | + writel(sdram_params->pctl_timing.tcl - 2, | |
242 | + &pctl->dfitrddataen); | |
243 | + } | |
244 | + writel(sdram_params->pctl_timing.tcwl - 1, | |
245 | + &pctl->dfitphywrlat); | |
246 | + writel(0 << MDDR_LPDDR2_CLK_STOP_IDLE_SHIFT | DDR3_EN | | |
247 | + DDR2_DDR3_BL_8 | (6 - 4) << TFAW_SHIFT | PD_EXIT_SLOW | | |
248 | + 1 << PD_TYPE_SHIFT | 0 << PD_IDLE_SHIFT, | |
249 | + &pctl->mcfg); | |
250 | + ddr_set_ddr3_mode(grf, channel, true); | |
251 | + ddr_set_enable(grf, channel, true); | |
252 | + break; | |
253 | + } | |
254 | + | |
255 | + setbits_le32(&pctl->scfg, 1); | |
256 | +} | |
257 | + | |
258 | +static void phy_cfg(const struct chan_info *chan, int channel, | |
259 | + struct rk3188_sdram_params *sdram_params) | |
260 | +{ | |
261 | + struct rk3288_ddr_publ *publ = chan->publ; | |
262 | + struct rk3188_msch *msch = chan->msch; | |
263 | + uint ddr_freq_mhz = sdram_params->base.ddr_freq / 1000000; | |
264 | + u32 dinit2; | |
265 | + int i; | |
266 | + | |
267 | + dinit2 = DIV_ROUND_UP(ddr_freq_mhz * 200000, 1000); | |
268 | + /* DDR PHY Timing */ | |
269 | + copy_to_reg(&publ->dtpr[0], &sdram_params->phy_timing.dtpr0, | |
270 | + sizeof(sdram_params->phy_timing)); | |
271 | + writel(sdram_params->base.noc_timing, &msch->ddrtiming); | |
272 | + writel(0x3f, &msch->readlatency); | |
273 | + writel(DIV_ROUND_UP(ddr_freq_mhz * 5120, 1000) << PRT_DLLLOCK_SHIFT | | |
274 | + DIV_ROUND_UP(ddr_freq_mhz * 50, 1000) << PRT_DLLSRST_SHIFT | | |
275 | + 8 << PRT_ITMSRST_SHIFT, &publ->ptr[0]); | |
276 | + writel(DIV_ROUND_UP(ddr_freq_mhz * 500000, 1000) << PRT_DINIT0_SHIFT | | |
277 | + DIV_ROUND_UP(ddr_freq_mhz * 400, 1000) << PRT_DINIT1_SHIFT, | |
278 | + &publ->ptr[1]); | |
279 | + writel(min(dinit2, 0x1ffffU) << PRT_DINIT2_SHIFT | | |
280 | + DIV_ROUND_UP(ddr_freq_mhz * 1000, 1000) << PRT_DINIT3_SHIFT, | |
281 | + &publ->ptr[2]); | |
282 | + | |
283 | + switch (sdram_params->base.dramtype) { | |
284 | + case DDR3: | |
285 | + clrbits_le32(&publ->pgcr, 0x1f); | |
286 | + clrsetbits_le32(&publ->dcr, DDRMD_MASK << DDRMD_SHIFT, | |
287 | + DDRMD_DDR3 << DDRMD_SHIFT); | |
288 | + break; | |
289 | + } | |
290 | + if (sdram_params->base.odt) { | |
291 | + /*dynamic RTT enable */ | |
292 | + for (i = 0; i < 4; i++) | |
293 | + setbits_le32(&publ->datx8[i].dxgcr, DQSRTT | DQRTT); | |
294 | + } else { | |
295 | + /*dynamic RTT disable */ | |
296 | + for (i = 0; i < 4; i++) | |
297 | + clrbits_le32(&publ->datx8[i].dxgcr, DQSRTT | DQRTT); | |
298 | + } | |
299 | +} | |
300 | + | |
301 | +static void phy_init(struct rk3288_ddr_publ *publ) | |
302 | +{ | |
303 | + setbits_le32(&publ->pir, PIR_INIT | PIR_DLLSRST | |
304 | + | PIR_DLLLOCK | PIR_ZCAL | PIR_ITMSRST | PIR_CLRSR); | |
305 | + udelay(1); | |
306 | + while ((readl(&publ->pgsr) & | |
307 | + (PGSR_IDONE | PGSR_DLDONE | PGSR_ZCDONE)) != | |
308 | + (PGSR_IDONE | PGSR_DLDONE | PGSR_ZCDONE)) | |
309 | + ; | |
310 | +} | |
311 | + | |
312 | +static void send_command(struct rk3288_ddr_pctl *pctl, u32 rank, | |
313 | + u32 cmd, u32 arg) | |
314 | +{ | |
315 | + writel((START_CMD | (rank << 20) | arg | cmd), &pctl->mcmd); | |
316 | + udelay(1); | |
317 | + while (readl(&pctl->mcmd) & START_CMD) | |
318 | + ; | |
319 | +} | |
320 | + | |
321 | +static inline void send_command_op(struct rk3288_ddr_pctl *pctl, | |
322 | + u32 rank, u32 cmd, u32 ma, u32 op) | |
323 | +{ | |
324 | + send_command(pctl, rank, cmd, (ma & LPDDR2_MA_MASK) << LPDDR2_MA_SHIFT | | |
325 | + (op & LPDDR2_OP_MASK) << LPDDR2_OP_SHIFT); | |
326 | +} | |
327 | + | |
328 | +static void memory_init(struct rk3288_ddr_publ *publ, | |
329 | + u32 dramtype) | |
330 | +{ | |
331 | + setbits_le32(&publ->pir, | |
332 | + (PIR_INIT | PIR_DRAMINIT | PIR_LOCKBYP | |
333 | + | PIR_ZCALBYP | PIR_CLRSR | PIR_ICPC | |
334 | + | (dramtype == DDR3 ? PIR_DRAMRST : 0))); | |
335 | + udelay(1); | |
336 | + while ((readl(&publ->pgsr) & (PGSR_IDONE | PGSR_DLDONE)) | |
337 | + != (PGSR_IDONE | PGSR_DLDONE)) | |
338 | + ; | |
339 | +} | |
340 | + | |
341 | +static void move_to_config_state(struct rk3288_ddr_publ *publ, | |
342 | + struct rk3288_ddr_pctl *pctl) | |
343 | +{ | |
344 | + unsigned int state; | |
345 | + | |
346 | + while (1) { | |
347 | + state = readl(&pctl->stat) & PCTL_STAT_MSK; | |
348 | + | |
349 | + switch (state) { | |
350 | + case LOW_POWER: | |
351 | + writel(WAKEUP_STATE, &pctl->sctl); | |
352 | + while ((readl(&pctl->stat) & PCTL_STAT_MSK) | |
353 | + != ACCESS) | |
354 | + ; | |
355 | + /* wait DLL lock */ | |
356 | + while ((readl(&publ->pgsr) & PGSR_DLDONE) | |
357 | + != PGSR_DLDONE) | |
358 | + ; | |
359 | + /* | |
360 | + * if at low power state,need wakeup first, | |
361 | + * and then enter the config, so | |
362 | + * fallthrough | |
363 | + */ | |
364 | + case ACCESS: | |
365 | + /* fallthrough */ | |
366 | + case INIT_MEM: | |
367 | + writel(CFG_STATE, &pctl->sctl); | |
368 | + while ((readl(&pctl->stat) & PCTL_STAT_MSK) != CONFIG) | |
369 | + ; | |
370 | + break; | |
371 | + case CONFIG: | |
372 | + return; | |
373 | + default: | |
374 | + break; | |
375 | + } | |
376 | + } | |
377 | +} | |
378 | + | |
379 | +static void set_bandwidth_ratio(const struct chan_info *chan, int channel, | |
380 | + u32 n, struct rk3188_grf *grf) | |
381 | +{ | |
382 | + struct rk3288_ddr_pctl *pctl = chan->pctl; | |
383 | + struct rk3288_ddr_publ *publ = chan->publ; | |
384 | + struct rk3188_msch *msch = chan->msch; | |
385 | + | |
386 | + if (n == 1) { | |
387 | + setbits_le32(&pctl->ppcfg, 1); | |
388 | + ddr_set_enable(grf, channel, 1); | |
389 | + setbits_le32(&msch->ddrtiming, 1 << 31); | |
390 | + /* Data Byte disable*/ | |
391 | + clrbits_le32(&publ->datx8[2].dxgcr, 1); | |
392 | + clrbits_le32(&publ->datx8[3].dxgcr, 1); | |
393 | + /* disable DLL */ | |
394 | + setbits_le32(&publ->datx8[2].dxdllcr, DXDLLCR_DLLDIS); | |
395 | + setbits_le32(&publ->datx8[3].dxdllcr, DXDLLCR_DLLDIS); | |
396 | + } else { | |
397 | + clrbits_le32(&pctl->ppcfg, 1); | |
398 | + ddr_set_enable(grf, channel, 0); | |
399 | + clrbits_le32(&msch->ddrtiming, 1 << 31); | |
400 | + /* Data Byte enable*/ | |
401 | + setbits_le32(&publ->datx8[2].dxgcr, 1); | |
402 | + setbits_le32(&publ->datx8[3].dxgcr, 1); | |
403 | + | |
404 | + /* enable DLL */ | |
405 | + clrbits_le32(&publ->datx8[2].dxdllcr, DXDLLCR_DLLDIS); | |
406 | + clrbits_le32(&publ->datx8[3].dxdllcr, DXDLLCR_DLLDIS); | |
407 | + /* reset DLL */ | |
408 | + clrbits_le32(&publ->datx8[2].dxdllcr, DXDLLCR_DLLSRST); | |
409 | + clrbits_le32(&publ->datx8[3].dxdllcr, DXDLLCR_DLLSRST); | |
410 | + udelay(10); | |
411 | + setbits_le32(&publ->datx8[2].dxdllcr, DXDLLCR_DLLSRST); | |
412 | + setbits_le32(&publ->datx8[3].dxdllcr, DXDLLCR_DLLSRST); | |
413 | + } | |
414 | + setbits_le32(&pctl->dfistcfg0, 1 << 2); | |
415 | +} | |
416 | + | |
417 | +static int data_training(const struct chan_info *chan, int channel, | |
418 | + struct rk3188_sdram_params *sdram_params) | |
419 | +{ | |
420 | + unsigned int j; | |
421 | + int ret = 0; | |
422 | + u32 rank; | |
423 | + int i; | |
424 | + u32 step[2] = { PIR_QSTRN, PIR_RVTRN }; | |
425 | + struct rk3288_ddr_publ *publ = chan->publ; | |
426 | + struct rk3288_ddr_pctl *pctl = chan->pctl; | |
427 | + | |
428 | + /* disable auto refresh */ | |
429 | + writel(0, &pctl->trefi); | |
430 | + | |
431 | + if (sdram_params->base.dramtype != LPDDR3) | |
432 | + setbits_le32(&publ->pgcr, 1 << PGCR_DQSCFG_SHIFT); | |
433 | + rank = sdram_params->ch[channel].rank | 1; | |
434 | + for (j = 0; j < ARRAY_SIZE(step); j++) { | |
435 | + /* | |
436 | + * trigger QSTRN and RVTRN | |
437 | + * clear DTDONE status | |
438 | + */ | |
439 | + setbits_le32(&publ->pir, PIR_CLRSR); | |
440 | + | |
441 | + /* trigger DTT */ | |
442 | + setbits_le32(&publ->pir, | |
443 | + PIR_INIT | step[j] | PIR_LOCKBYP | PIR_ZCALBYP | | |
444 | + PIR_CLRSR); | |
445 | + udelay(1); | |
446 | + /* wait echo byte DTDONE */ | |
447 | + while ((readl(&publ->datx8[0].dxgsr[0]) & rank) | |
448 | + != rank) | |
449 | + ; | |
450 | + while ((readl(&publ->datx8[1].dxgsr[0]) & rank) | |
451 | + != rank) | |
452 | + ; | |
453 | + if (!(readl(&pctl->ppcfg) & 1)) { | |
454 | + while ((readl(&publ->datx8[2].dxgsr[0]) | |
455 | + & rank) != rank) | |
456 | + ; | |
457 | + while ((readl(&publ->datx8[3].dxgsr[0]) | |
458 | + & rank) != rank) | |
459 | + ; | |
460 | + } | |
461 | + if (readl(&publ->pgsr) & | |
462 | + (PGSR_DTERR | PGSR_RVERR | PGSR_RVEIRR)) { | |
463 | + ret = -1; | |
464 | + break; | |
465 | + } | |
466 | + } | |
467 | + /* send some auto refresh to complement the lost while DTT */ | |
468 | + for (i = 0; i < (rank > 1 ? 8 : 4); i++) | |
469 | + send_command(pctl, rank, REF_CMD, 0); | |
470 | + | |
471 | + if (sdram_params->base.dramtype != LPDDR3) | |
472 | + clrbits_le32(&publ->pgcr, 1 << PGCR_DQSCFG_SHIFT); | |
473 | + | |
474 | + /* resume auto refresh */ | |
475 | + writel(sdram_params->pctl_timing.trefi, &pctl->trefi); | |
476 | + | |
477 | + return ret; | |
478 | +} | |
479 | + | |
480 | +static void move_to_access_state(const struct chan_info *chan) | |
481 | +{ | |
482 | + struct rk3288_ddr_publ *publ = chan->publ; | |
483 | + struct rk3288_ddr_pctl *pctl = chan->pctl; | |
484 | + unsigned int state; | |
485 | + | |
486 | + while (1) { | |
487 | + state = readl(&pctl->stat) & PCTL_STAT_MSK; | |
488 | + | |
489 | + switch (state) { | |
490 | + case LOW_POWER: | |
491 | + if (((readl(&pctl->stat) >> LP_TRIG_SHIFT) & | |
492 | + LP_TRIG_MASK) == 1) | |
493 | + return; | |
494 | + | |
495 | + writel(WAKEUP_STATE, &pctl->sctl); | |
496 | + while ((readl(&pctl->stat) & PCTL_STAT_MSK) != ACCESS) | |
497 | + ; | |
498 | + /* wait DLL lock */ | |
499 | + while ((readl(&publ->pgsr) & PGSR_DLDONE) | |
500 | + != PGSR_DLDONE) | |
501 | + ; | |
502 | + break; | |
503 | + case INIT_MEM: | |
504 | + writel(CFG_STATE, &pctl->sctl); | |
505 | + while ((readl(&pctl->stat) & PCTL_STAT_MSK) != CONFIG) | |
506 | + ; | |
507 | + /* fallthrough */ | |
508 | + case CONFIG: | |
509 | + writel(GO_STATE, &pctl->sctl); | |
510 | + while ((readl(&pctl->stat) & PCTL_STAT_MSK) == CONFIG) | |
511 | + ; | |
512 | + break; | |
513 | + case ACCESS: | |
514 | + return; | |
515 | + default: | |
516 | + break; | |
517 | + } | |
518 | + } | |
519 | +} | |
520 | + | |
521 | +static void dram_cfg_rbc(const struct chan_info *chan, u32 chnum, | |
522 | + struct rk3188_sdram_params *sdram_params) | |
523 | +{ | |
524 | + struct rk3288_ddr_publ *publ = chan->publ; | |
525 | + | |
526 | + if (sdram_params->ch[chnum].bk == 3) | |
527 | + clrsetbits_le32(&publ->dcr, PDQ_MASK << PDQ_SHIFT, | |
528 | + 1 << PDQ_SHIFT); | |
529 | + else | |
530 | + clrbits_le32(&publ->dcr, PDQ_MASK << PDQ_SHIFT); | |
531 | + | |
532 | + writel(sdram_params->base.ddrconfig, &chan->msch->ddrconf); | |
533 | +} | |
534 | + | |
535 | +static void dram_all_config(const struct dram_info *dram, | |
536 | + struct rk3188_sdram_params *sdram_params) | |
537 | +{ | |
538 | + unsigned int chan; | |
539 | + u32 sys_reg = 0; | |
540 | + | |
541 | + sys_reg |= sdram_params->base.dramtype << SYS_REG_DDRTYPE_SHIFT; | |
542 | + sys_reg |= (sdram_params->num_channels - 1) << SYS_REG_NUM_CH_SHIFT; | |
543 | + for (chan = 0; chan < sdram_params->num_channels; chan++) { | |
544 | + const struct rk3288_sdram_channel *info = | |
545 | + &sdram_params->ch[chan]; | |
546 | + | |
547 | + sys_reg |= info->row_3_4 << SYS_REG_ROW_3_4_SHIFT(chan); | |
548 | + sys_reg |= 1 << SYS_REG_CHINFO_SHIFT(chan); | |
549 | + sys_reg |= (info->rank - 1) << SYS_REG_RANK_SHIFT(chan); | |
550 | + sys_reg |= (info->col - 9) << SYS_REG_COL_SHIFT(chan); | |
551 | + sys_reg |= info->bk == 3 ? 0 : 1 << SYS_REG_BK_SHIFT(chan); | |
552 | + sys_reg |= (info->cs0_row - 13) << SYS_REG_CS0_ROW_SHIFT(chan); | |
553 | + sys_reg |= (info->cs1_row - 13) << SYS_REG_CS1_ROW_SHIFT(chan); | |
554 | + sys_reg |= (2 >> info->bw) << SYS_REG_BW_SHIFT(chan); | |
555 | + sys_reg |= (2 >> info->dbw) << SYS_REG_DBW_SHIFT(chan); | |
556 | + | |
557 | + dram_cfg_rbc(&dram->chan[chan], chan, sdram_params); | |
558 | + } | |
559 | + if (sdram_params->ch[0].rank == 2) | |
560 | + ddr_rank_2_row15en(dram->grf, 0); | |
561 | + else | |
562 | + ddr_rank_2_row15en(dram->grf, 1); | |
563 | + | |
564 | + writel(sys_reg, &dram->pmu->sys_reg[2]); | |
565 | +} | |
566 | + | |
567 | +static int sdram_rank_bw_detect(struct dram_info *dram, int channel, | |
568 | + struct rk3188_sdram_params *sdram_params) | |
569 | +{ | |
570 | + int reg; | |
571 | + int need_trainig = 0; | |
572 | + const struct chan_info *chan = &dram->chan[channel]; | |
573 | + struct rk3288_ddr_publ *publ = chan->publ; | |
574 | + | |
575 | + ddr_rank_2_row15en(dram->grf, 0); | |
576 | + | |
577 | + if (data_training(chan, channel, sdram_params) < 0) { | |
578 | + printf("first data training fail!\n"); | |
579 | + reg = readl(&publ->datx8[0].dxgsr[0]); | |
580 | + /* Check the result for rank 0 */ | |
581 | + if ((channel == 0) && (reg & DQS_GATE_TRAINING_ERROR_RANK0)) { | |
582 | + printf("data training fail!\n"); | |
583 | + return -EIO; | |
584 | + } | |
585 | + | |
586 | + /* Check the result for rank 1 */ | |
587 | + if (reg & DQS_GATE_TRAINING_ERROR_RANK1) { | |
588 | + sdram_params->ch[channel].rank = 1; | |
589 | + clrsetbits_le32(&publ->pgcr, 0xF << 18, | |
590 | + sdram_params->ch[channel].rank << 18); | |
591 | + need_trainig = 1; | |
592 | + } | |
593 | + reg = readl(&publ->datx8[2].dxgsr[0]); | |
594 | + if (reg & (1 << 4)) { | |
595 | + sdram_params->ch[channel].bw = 1; | |
596 | + set_bandwidth_ratio(chan, channel, | |
597 | + sdram_params->ch[channel].bw, | |
598 | + dram->grf); | |
599 | + need_trainig = 1; | |
600 | + } | |
601 | + } | |
602 | + /* Assume the Die bit width are the same with the chip bit width */ | |
603 | + sdram_params->ch[channel].dbw = sdram_params->ch[channel].bw; | |
604 | + | |
605 | + if (need_trainig && | |
606 | + (data_training(chan, channel, sdram_params) < 0)) { | |
607 | + if (sdram_params->base.dramtype == LPDDR3) { | |
608 | + ddr_phy_ctl_reset(dram->cru, channel, 1); | |
609 | + udelay(10); | |
610 | + ddr_phy_ctl_reset(dram->cru, channel, 0); | |
611 | + udelay(10); | |
612 | + } | |
613 | + printf("2nd data training failed!"); | |
614 | + return -EIO; | |
615 | + } | |
616 | + | |
617 | + return 0; | |
618 | +} | |
619 | + | |
620 | +/* | |
621 | + * Detect ram columns and rows. | |
622 | + * @dram: dram info struct | |
623 | + * @channel: channel number to handle | |
624 | + * @sdram_params: sdram parameters, function will fill in col and row values | |
625 | + * | |
626 | + * Returns 0 or negative on error. | |
627 | + */ | |
628 | +static int sdram_col_row_detect(struct dram_info *dram, int channel, | |
629 | + struct rk3188_sdram_params *sdram_params) | |
630 | +{ | |
631 | + int row, col; | |
632 | + unsigned int addr; | |
633 | + const struct chan_info *chan = &dram->chan[channel]; | |
634 | + struct rk3288_ddr_pctl *pctl = chan->pctl; | |
635 | + struct rk3288_ddr_publ *publ = chan->publ; | |
636 | + int ret = 0; | |
637 | + | |
638 | + /* Detect col */ | |
639 | + for (col = 11; col >= 9; col--) { | |
640 | + writel(0, CONFIG_SYS_SDRAM_BASE); | |
641 | + addr = CONFIG_SYS_SDRAM_BASE + | |
642 | + (1 << (col + sdram_params->ch[channel].bw - 1)); | |
643 | + writel(TEST_PATTEN, addr); | |
644 | + if ((readl(addr) == TEST_PATTEN) && | |
645 | + (readl(CONFIG_SYS_SDRAM_BASE) == 0)) | |
646 | + break; | |
647 | + } | |
648 | + if (col == 8) { | |
649 | + printf("Col detect error\n"); | |
650 | + ret = -EINVAL; | |
651 | + goto out; | |
652 | + } else { | |
653 | + sdram_params->ch[channel].col = col; | |
654 | + } | |
655 | + | |
656 | + ddr_rank_2_row15en(dram->grf, 1); | |
657 | + move_to_config_state(publ, pctl); | |
658 | + writel(1, &chan->msch->ddrconf); | |
659 | + move_to_access_state(chan); | |
660 | + /* Detect row, max 15,min13 in rk3188*/ | |
661 | + for (row = 16; row >= 13; row--) { | |
662 | + writel(0, CONFIG_SYS_SDRAM_BASE); | |
663 | + addr = CONFIG_SYS_SDRAM_BASE + (1 << (row + 15 - 1)); | |
664 | + writel(TEST_PATTEN, addr); | |
665 | + if ((readl(addr) == TEST_PATTEN) && | |
666 | + (readl(CONFIG_SYS_SDRAM_BASE) == 0)) | |
667 | + break; | |
668 | + } | |
669 | + if (row == 12) { | |
670 | + printf("Row detect error\n"); | |
671 | + ret = -EINVAL; | |
672 | + } else { | |
673 | + sdram_params->ch[channel].cs1_row = row; | |
674 | + sdram_params->ch[channel].row_3_4 = 0; | |
675 | + debug("chn %d col %d, row %d\n", channel, col, row); | |
676 | + sdram_params->ch[channel].cs0_row = row; | |
677 | + } | |
678 | + | |
679 | +out: | |
680 | + return ret; | |
681 | +} | |
682 | + | |
683 | +static int sdram_get_niu_config(struct rk3188_sdram_params *sdram_params) | |
684 | +{ | |
685 | + int i, tmp, size, ret = 0; | |
686 | + | |
687 | + tmp = sdram_params->ch[0].col - 9; | |
688 | + tmp -= (sdram_params->ch[0].bw == 2) ? 0 : 1; | |
689 | + tmp |= ((sdram_params->ch[0].cs0_row - 13) << 4); | |
690 | + size = sizeof(ddrconf_table)/sizeof(ddrconf_table[0]); | |
691 | + for (i = 0; i < size; i++) | |
692 | + if (tmp == ddrconf_table[i]) | |
693 | + break; | |
694 | + if (i >= size) { | |
695 | + printf("niu config not found\n"); | |
696 | + ret = -EINVAL; | |
697 | + } else { | |
698 | + debug("niu config %d\n", i); | |
699 | + sdram_params->base.ddrconfig = i; | |
700 | + } | |
701 | + | |
702 | + return ret; | |
703 | +} | |
704 | + | |
705 | +static int sdram_init(struct dram_info *dram, | |
706 | + struct rk3188_sdram_params *sdram_params) | |
707 | +{ | |
708 | + int channel; | |
709 | + int zqcr; | |
710 | + int ret; | |
711 | + | |
712 | + if ((sdram_params->base.dramtype == DDR3 && | |
713 | + sdram_params->base.ddr_freq > 800000000)) { | |
714 | + printf("SDRAM frequency is too high!"); | |
715 | + return -E2BIG; | |
716 | + } | |
717 | + | |
718 | + ret = clk_set_rate(&dram->ddr_clk, sdram_params->base.ddr_freq); | |
719 | + if (ret) { | |
720 | + printf("Could not set DDR clock\n"); | |
721 | + return ret; | |
722 | + } | |
723 | + | |
724 | + for (channel = 0; channel < 1; channel++) { | |
725 | + const struct chan_info *chan = &dram->chan[channel]; | |
726 | + struct rk3288_ddr_pctl *pctl = chan->pctl; | |
727 | + struct rk3288_ddr_publ *publ = chan->publ; | |
728 | + | |
729 | + phy_pctrl_reset(dram->cru, publ, channel); | |
730 | + phy_dll_bypass_set(publ, sdram_params->base.ddr_freq); | |
731 | + | |
732 | + dfi_cfg(pctl, sdram_params->base.dramtype); | |
733 | + | |
734 | + pctl_cfg(channel, pctl, sdram_params, dram->grf); | |
735 | + | |
736 | + phy_cfg(chan, channel, sdram_params); | |
737 | + | |
738 | + phy_init(publ); | |
739 | + | |
740 | + writel(POWER_UP_START, &pctl->powctl); | |
741 | + while (!(readl(&pctl->powstat) & POWER_UP_DONE)) | |
742 | + ; | |
743 | + | |
744 | + memory_init(publ, sdram_params->base.dramtype); | |
745 | + move_to_config_state(publ, pctl); | |
746 | + | |
747 | + /* Using 32bit bus width for detect */ | |
748 | + sdram_params->ch[channel].bw = 2; | |
749 | + set_bandwidth_ratio(chan, channel, | |
750 | + sdram_params->ch[channel].bw, dram->grf); | |
751 | + /* | |
752 | + * set cs, using n=3 for detect | |
753 | + * CS0, n=1 | |
754 | + * CS1, n=2 | |
755 | + * CS0 & CS1, n = 3 | |
756 | + */ | |
757 | + sdram_params->ch[channel].rank = 2, | |
758 | + clrsetbits_le32(&publ->pgcr, 0xF << 18, | |
759 | + (sdram_params->ch[channel].rank | 1) << 18); | |
760 | + | |
761 | + /* DS=40ohm,ODT=155ohm */ | |
762 | + zqcr = 1 << ZDEN_SHIFT | 2 << PU_ONDIE_SHIFT | | |
763 | + 2 << PD_ONDIE_SHIFT | 0x19 << PU_OUTPUT_SHIFT | | |
764 | + 0x19 << PD_OUTPUT_SHIFT; | |
765 | + writel(zqcr, &publ->zq1cr[0]); | |
766 | + writel(zqcr, &publ->zq0cr[0]); | |
767 | + | |
768 | + /* Detect the rank and bit-width with data-training */ | |
769 | + writel(1, &chan->msch->ddrconf); | |
770 | + sdram_rank_bw_detect(dram, channel, sdram_params); | |
771 | + | |
772 | + if (sdram_params->base.dramtype == LPDDR3) { | |
773 | + u32 i; | |
774 | + writel(0, &pctl->mrrcfg0); | |
775 | + for (i = 0; i < 17; i++) | |
776 | + send_command_op(pctl, 1, MRR_CMD, i, 0); | |
777 | + } | |
778 | + writel(4, &chan->msch->ddrconf); | |
779 | + move_to_access_state(chan); | |
780 | + /* DDR3 and LPDDR3 are always 8 bank, no need detect */ | |
781 | + sdram_params->ch[channel].bk = 3; | |
782 | + /* Detect Col and Row number*/ | |
783 | + ret = sdram_col_row_detect(dram, channel, sdram_params); | |
784 | + if (ret) | |
785 | + goto error; | |
786 | + } | |
787 | + /* Find NIU DDR configuration */ | |
788 | + ret = sdram_get_niu_config(sdram_params); | |
789 | + if (ret) | |
790 | + goto error; | |
791 | + | |
792 | + dram_all_config(dram, sdram_params); | |
793 | + debug("%s done\n", __func__); | |
794 | + | |
795 | + return 0; | |
796 | +error: | |
797 | + printf("DRAM init failed!\n"); | |
798 | + hang(); | |
799 | +} | |
800 | + | |
801 | +static int setup_sdram(struct udevice *dev) | |
802 | +{ | |
803 | + struct dram_info *priv = dev_get_priv(dev); | |
804 | + struct rk3188_sdram_params *params = dev_get_platdata(dev); | |
805 | + | |
806 | + return sdram_init(priv, params); | |
807 | +} | |
808 | + | |
809 | +static int rk3188_dmc_ofdata_to_platdata(struct udevice *dev) | |
810 | +{ | |
811 | +#if !CONFIG_IS_ENABLED(OF_PLATDATA) | |
812 | + struct rk3188_sdram_params *params = dev_get_platdata(dev); | |
813 | + int ret; | |
814 | + | |
815 | + /* rk3188 supports only one-channel */ | |
816 | + params->num_channels = 1; | |
817 | + ret = dev_read_u32_array(dev, "rockchip,pctl-timing", | |
818 | + (u32 *)¶ms->pctl_timing, | |
819 | + sizeof(params->pctl_timing) / sizeof(u32)); | |
820 | + if (ret) { | |
821 | + printf("%s: Cannot read rockchip,pctl-timing\n", __func__); | |
822 | + return -EINVAL; | |
823 | + } | |
824 | + ret = dev_read_u32_array(dev, "rockchip,phy-timing", | |
825 | + (u32 *)¶ms->phy_timing, | |
826 | + sizeof(params->phy_timing) / sizeof(u32)); | |
827 | + if (ret) { | |
828 | + printf("%s: Cannot read rockchip,phy-timing\n", __func__); | |
829 | + return -EINVAL; | |
830 | + } | |
831 | + ret = dev_read_u32_array(dev, "rockchip,sdram-params", | |
832 | + (u32 *)¶ms->base, | |
833 | + sizeof(params->base) / sizeof(u32)); | |
834 | + if (ret) { | |
835 | + printf("%s: Cannot read rockchip,sdram-params\n", __func__); | |
836 | + return -EINVAL; | |
837 | + } | |
838 | + ret = regmap_init_mem(dev, ¶ms->map); | |
839 | + if (ret) | |
840 | + return ret; | |
841 | +#endif | |
842 | + | |
843 | + return 0; | |
844 | +} | |
845 | +#endif /* CONFIG_SPL_BUILD */ | |
846 | + | |
847 | +#if CONFIG_IS_ENABLED(OF_PLATDATA) | |
848 | +static int conv_of_platdata(struct udevice *dev) | |
849 | +{ | |
850 | + struct rk3188_sdram_params *plat = dev_get_platdata(dev); | |
851 | + struct dtd_rockchip_rk3188_dmc *of_plat = &plat->of_plat; | |
852 | + int ret; | |
853 | + | |
854 | + memcpy(&plat->pctl_timing, of_plat->rockchip_pctl_timing, | |
855 | + sizeof(plat->pctl_timing)); | |
856 | + memcpy(&plat->phy_timing, of_plat->rockchip_phy_timing, | |
857 | + sizeof(plat->phy_timing)); | |
858 | + memcpy(&plat->base, of_plat->rockchip_sdram_params, sizeof(plat->base)); | |
859 | + /* rk3188 supports dual-channel, set default channel num to 2 */ | |
860 | + plat->num_channels = 1; | |
861 | + ret = regmap_init_mem_platdata(dev, of_plat->reg, | |
862 | + ARRAY_SIZE(of_plat->reg) / 2, | |
863 | + &plat->map); | |
864 | + if (ret) | |
865 | + return ret; | |
866 | + | |
867 | + return 0; | |
868 | +} | |
869 | +#endif | |
870 | + | |
871 | +static int rk3188_dmc_probe(struct udevice *dev) | |
872 | +{ | |
873 | +#ifdef CONFIG_SPL_BUILD | |
874 | + struct rk3188_sdram_params *plat = dev_get_platdata(dev); | |
875 | + struct regmap *map; | |
876 | + struct udevice *dev_clk; | |
877 | + int ret; | |
878 | +#endif | |
879 | + struct dram_info *priv = dev_get_priv(dev); | |
880 | + | |
881 | + priv->pmu = syscon_get_first_range(ROCKCHIP_SYSCON_PMU); | |
882 | + | |
883 | +#ifdef CONFIG_SPL_BUILD | |
884 | +#if CONFIG_IS_ENABLED(OF_PLATDATA) | |
885 | + ret = conv_of_platdata(dev); | |
886 | + if (ret) | |
887 | + return ret; | |
888 | +#endif | |
889 | + map = syscon_get_regmap_by_driver_data(ROCKCHIP_SYSCON_NOC); | |
890 | + if (IS_ERR(map)) | |
891 | + return PTR_ERR(map); | |
892 | + priv->chan[0].msch = regmap_get_range(map, 0); | |
893 | + | |
894 | + priv->grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF); | |
895 | + | |
896 | + priv->chan[0].pctl = regmap_get_range(plat->map, 0); | |
897 | + priv->chan[0].publ = regmap_get_range(plat->map, 1); | |
898 | + | |
899 | + ret = rockchip_get_clk(&dev_clk); | |
900 | + if (ret) | |
901 | + return ret; | |
902 | + priv->ddr_clk.id = CLK_DDR; | |
903 | + ret = clk_request(dev_clk, &priv->ddr_clk); | |
904 | + if (ret) | |
905 | + return ret; | |
906 | + | |
907 | + priv->cru = rockchip_get_cru(); | |
908 | + if (IS_ERR(priv->cru)) | |
909 | + return PTR_ERR(priv->cru); | |
910 | + ret = setup_sdram(dev); | |
911 | + if (ret) | |
912 | + return ret; | |
913 | +#else | |
914 | + priv->info.base = CONFIG_SYS_SDRAM_BASE; | |
915 | + priv->info.size = rockchip_sdram_size( | |
916 | + (phys_addr_t)&priv->pmu->sys_reg[2]); | |
917 | +#endif | |
918 | + | |
919 | + return 0; | |
920 | +} | |
921 | + | |
922 | +static int rk3188_dmc_get_info(struct udevice *dev, struct ram_info *info) | |
923 | +{ | |
924 | + struct dram_info *priv = dev_get_priv(dev); | |
925 | + | |
926 | + *info = priv->info; | |
927 | + | |
928 | + return 0; | |
929 | +} | |
930 | + | |
931 | +static struct ram_ops rk3188_dmc_ops = { | |
932 | + .get_info = rk3188_dmc_get_info, | |
933 | +}; | |
934 | + | |
935 | +static const struct udevice_id rk3188_dmc_ids[] = { | |
936 | + { .compatible = "rockchip,rk3188-dmc" }, | |
937 | + { } | |
938 | +}; | |
939 | + | |
940 | +U_BOOT_DRIVER(dmc_rk3188) = { | |
941 | + .name = "rockchip_rk3188_dmc", | |
942 | + .id = UCLASS_RAM, | |
943 | + .of_match = rk3188_dmc_ids, | |
944 | + .ops = &rk3188_dmc_ops, | |
945 | +#ifdef CONFIG_SPL_BUILD | |
946 | + .ofdata_to_platdata = rk3188_dmc_ofdata_to_platdata, | |
947 | +#endif | |
948 | + .probe = rk3188_dmc_probe, | |
949 | + .priv_auto_alloc_size = sizeof(struct dram_info), | |
950 | +#ifdef CONFIG_SPL_BUILD | |
951 | + .platdata_auto_alloc_size = sizeof(struct rk3188_sdram_params), | |
952 | +#endif | |
953 | +}; |