blob: 11b14ae6520f911268297eb9f1dab4c11395372c [file] [log] [blame]
Tom Rini8b0c8a12018-05-06 18:27:01 -04001// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
Patrick Delaunay939d5362018-03-12 10:46:11 +01002/*
3 * Copyright (C) 2018, STMicroelectronics - All Rights Reserved
Patrick Delaunay939d5362018-03-12 10:46:11 +01004 */
5
6#include <common.h>
7#include <clk.h>
8#include <ram.h>
9#include <reset.h>
10#include <timer.h>
11#include <asm/io.h>
12#include <asm/arch/ddr.h>
13#include <linux/iopoll.h>
14#include "stm32mp1_ddr.h"
15#include "stm32mp1_ddr_regs.h"
16
17#define RCC_DDRITFCR 0xD8
18
19#define RCC_DDRITFCR_DDRCAPBRST (BIT(14))
20#define RCC_DDRITFCR_DDRCAXIRST (BIT(15))
21#define RCC_DDRITFCR_DDRCORERST (BIT(16))
22#define RCC_DDRITFCR_DPHYAPBRST (BIT(17))
23#define RCC_DDRITFCR_DPHYRST (BIT(18))
24#define RCC_DDRITFCR_DPHYCTLRST (BIT(19))
25
26struct reg_desc {
27 const char *name;
28 u16 offset; /* offset for base address */
29 u8 par_offset; /* offset for parameter array */
30};
31
32#define INVALID_OFFSET 0xFF
33
34#define DDRCTL_REG(x, y) \
35 {#x,\
36 offsetof(struct stm32mp1_ddrctl, x),\
37 offsetof(struct y, x)}
38
39#define DDRPHY_REG(x, y) \
40 {#x,\
41 offsetof(struct stm32mp1_ddrphy, x),\
42 offsetof(struct y, x)}
43
Patrick Delaunaybbee2702019-04-10 14:09:27 +020044#define DDR_REG_DYN(x) \
45 {#x,\
46 offsetof(struct stm32mp1_ddrctl, x),\
47 INVALID_OFFSET}
48
49#define DDRPHY_REG_DYN(x) \
50 {#x,\
51 offsetof(struct stm32mp1_ddrphy, x),\
52 INVALID_OFFSET}
53
Patrick Delaunayd892d272019-04-10 14:09:25 +020054/***********************************************************
55 * PARAMETERS: value get from device tree :
56 * size / order need to be aligned with binding
57 * modification NOT ALLOWED !!!
58 ***********************************************************/
59#define DDRCTL_REG_REG_SIZE 25 /* st,ctl-reg */
60#define DDRCTL_REG_TIMING_SIZE 12 /* st,ctl-timing */
61#define DDRCTL_REG_MAP_SIZE 9 /* st,ctl-map */
62#define DDRCTL_REG_PERF_SIZE 17 /* st,ctl-perf */
63
64#define DDRPHY_REG_REG_SIZE 11 /* st,phy-reg */
65#define DDRPHY_REG_TIMING_SIZE 10 /* st,phy-timing */
66#define DDRPHY_REG_CAL_SIZE 12 /* st,phy-cal */
67
Patrick Delaunay939d5362018-03-12 10:46:11 +010068#define DDRCTL_REG_REG(x) DDRCTL_REG(x, stm32mp1_ddrctrl_reg)
Patrick Delaunayd892d272019-04-10 14:09:25 +020069static const struct reg_desc ddr_reg[DDRCTL_REG_REG_SIZE] = {
Patrick Delaunay939d5362018-03-12 10:46:11 +010070 DDRCTL_REG_REG(mstr),
71 DDRCTL_REG_REG(mrctrl0),
72 DDRCTL_REG_REG(mrctrl1),
73 DDRCTL_REG_REG(derateen),
74 DDRCTL_REG_REG(derateint),
75 DDRCTL_REG_REG(pwrctl),
76 DDRCTL_REG_REG(pwrtmg),
77 DDRCTL_REG_REG(hwlpctl),
78 DDRCTL_REG_REG(rfshctl0),
79 DDRCTL_REG_REG(rfshctl3),
80 DDRCTL_REG_REG(crcparctl0),
81 DDRCTL_REG_REG(zqctl0),
82 DDRCTL_REG_REG(dfitmg0),
83 DDRCTL_REG_REG(dfitmg1),
84 DDRCTL_REG_REG(dfilpcfg0),
85 DDRCTL_REG_REG(dfiupd0),
86 DDRCTL_REG_REG(dfiupd1),
87 DDRCTL_REG_REG(dfiupd2),
88 DDRCTL_REG_REG(dfiphymstr),
89 DDRCTL_REG_REG(odtmap),
90 DDRCTL_REG_REG(dbg0),
91 DDRCTL_REG_REG(dbg1),
92 DDRCTL_REG_REG(dbgcmd),
93 DDRCTL_REG_REG(poisoncfg),
94 DDRCTL_REG_REG(pccfg),
95};
96
97#define DDRCTL_REG_TIMING(x) DDRCTL_REG(x, stm32mp1_ddrctrl_timing)
Patrick Delaunayd892d272019-04-10 14:09:25 +020098static const struct reg_desc ddr_timing[DDRCTL_REG_TIMING_SIZE] = {
Patrick Delaunay939d5362018-03-12 10:46:11 +010099 DDRCTL_REG_TIMING(rfshtmg),
100 DDRCTL_REG_TIMING(dramtmg0),
101 DDRCTL_REG_TIMING(dramtmg1),
102 DDRCTL_REG_TIMING(dramtmg2),
103 DDRCTL_REG_TIMING(dramtmg3),
104 DDRCTL_REG_TIMING(dramtmg4),
105 DDRCTL_REG_TIMING(dramtmg5),
106 DDRCTL_REG_TIMING(dramtmg6),
107 DDRCTL_REG_TIMING(dramtmg7),
108 DDRCTL_REG_TIMING(dramtmg8),
109 DDRCTL_REG_TIMING(dramtmg14),
110 DDRCTL_REG_TIMING(odtcfg),
111};
112
113#define DDRCTL_REG_MAP(x) DDRCTL_REG(x, stm32mp1_ddrctrl_map)
Patrick Delaunayd892d272019-04-10 14:09:25 +0200114static const struct reg_desc ddr_map[DDRCTL_REG_MAP_SIZE] = {
Patrick Delaunay939d5362018-03-12 10:46:11 +0100115 DDRCTL_REG_MAP(addrmap1),
116 DDRCTL_REG_MAP(addrmap2),
117 DDRCTL_REG_MAP(addrmap3),
118 DDRCTL_REG_MAP(addrmap4),
119 DDRCTL_REG_MAP(addrmap5),
120 DDRCTL_REG_MAP(addrmap6),
121 DDRCTL_REG_MAP(addrmap9),
122 DDRCTL_REG_MAP(addrmap10),
123 DDRCTL_REG_MAP(addrmap11),
124};
125
126#define DDRCTL_REG_PERF(x) DDRCTL_REG(x, stm32mp1_ddrctrl_perf)
Patrick Delaunayd892d272019-04-10 14:09:25 +0200127static const struct reg_desc ddr_perf[DDRCTL_REG_PERF_SIZE] = {
Patrick Delaunay939d5362018-03-12 10:46:11 +0100128 DDRCTL_REG_PERF(sched),
129 DDRCTL_REG_PERF(sched1),
130 DDRCTL_REG_PERF(perfhpr1),
131 DDRCTL_REG_PERF(perflpr1),
132 DDRCTL_REG_PERF(perfwr1),
133 DDRCTL_REG_PERF(pcfgr_0),
134 DDRCTL_REG_PERF(pcfgw_0),
135 DDRCTL_REG_PERF(pcfgqos0_0),
136 DDRCTL_REG_PERF(pcfgqos1_0),
137 DDRCTL_REG_PERF(pcfgwqos0_0),
138 DDRCTL_REG_PERF(pcfgwqos1_0),
139 DDRCTL_REG_PERF(pcfgr_1),
140 DDRCTL_REG_PERF(pcfgw_1),
141 DDRCTL_REG_PERF(pcfgqos0_1),
142 DDRCTL_REG_PERF(pcfgqos1_1),
143 DDRCTL_REG_PERF(pcfgwqos0_1),
144 DDRCTL_REG_PERF(pcfgwqos1_1),
145};
146
147#define DDRPHY_REG_REG(x) DDRPHY_REG(x, stm32mp1_ddrphy_reg)
Patrick Delaunayd892d272019-04-10 14:09:25 +0200148static const struct reg_desc ddrphy_reg[DDRPHY_REG_REG_SIZE] = {
Patrick Delaunay939d5362018-03-12 10:46:11 +0100149 DDRPHY_REG_REG(pgcr),
150 DDRPHY_REG_REG(aciocr),
151 DDRPHY_REG_REG(dxccr),
152 DDRPHY_REG_REG(dsgcr),
153 DDRPHY_REG_REG(dcr),
154 DDRPHY_REG_REG(odtcr),
155 DDRPHY_REG_REG(zq0cr1),
156 DDRPHY_REG_REG(dx0gcr),
157 DDRPHY_REG_REG(dx1gcr),
158 DDRPHY_REG_REG(dx2gcr),
159 DDRPHY_REG_REG(dx3gcr),
160};
161
162#define DDRPHY_REG_TIMING(x) DDRPHY_REG(x, stm32mp1_ddrphy_timing)
Patrick Delaunayd892d272019-04-10 14:09:25 +0200163static const struct reg_desc ddrphy_timing[DDRPHY_REG_TIMING_SIZE] = {
Patrick Delaunay939d5362018-03-12 10:46:11 +0100164 DDRPHY_REG_TIMING(ptr0),
165 DDRPHY_REG_TIMING(ptr1),
166 DDRPHY_REG_TIMING(ptr2),
167 DDRPHY_REG_TIMING(dtpr0),
168 DDRPHY_REG_TIMING(dtpr1),
169 DDRPHY_REG_TIMING(dtpr2),
170 DDRPHY_REG_TIMING(mr0),
171 DDRPHY_REG_TIMING(mr1),
172 DDRPHY_REG_TIMING(mr2),
173 DDRPHY_REG_TIMING(mr3),
174};
175
176#define DDRPHY_REG_CAL(x) DDRPHY_REG(x, stm32mp1_ddrphy_cal)
Patrick Delaunayd892d272019-04-10 14:09:25 +0200177static const struct reg_desc ddrphy_cal[DDRPHY_REG_CAL_SIZE] = {
Patrick Delaunay939d5362018-03-12 10:46:11 +0100178 DDRPHY_REG_CAL(dx0dllcr),
179 DDRPHY_REG_CAL(dx0dqtr),
180 DDRPHY_REG_CAL(dx0dqstr),
181 DDRPHY_REG_CAL(dx1dllcr),
182 DDRPHY_REG_CAL(dx1dqtr),
183 DDRPHY_REG_CAL(dx1dqstr),
184 DDRPHY_REG_CAL(dx2dllcr),
185 DDRPHY_REG_CAL(dx2dqtr),
186 DDRPHY_REG_CAL(dx2dqstr),
187 DDRPHY_REG_CAL(dx3dllcr),
188 DDRPHY_REG_CAL(dx3dqtr),
189 DDRPHY_REG_CAL(dx3dqstr),
190};
191
Patrick Delaunaybbee2702019-04-10 14:09:27 +0200192/**************************************************************
193 * DYNAMIC REGISTERS: only used for debug purpose (read/modify)
194 **************************************************************/
195#ifdef CONFIG_STM32MP1_DDR_INTERACTIVE
196static const struct reg_desc ddr_dyn[] = {
197 DDR_REG_DYN(stat),
198 DDR_REG_DYN(init0),
199 DDR_REG_DYN(dfimisc),
200 DDR_REG_DYN(dfistat),
201 DDR_REG_DYN(swctl),
202 DDR_REG_DYN(swstat),
203 DDR_REG_DYN(pctrl_0),
204 DDR_REG_DYN(pctrl_1),
205};
206
207#define DDR_REG_DYN_SIZE ARRAY_SIZE(ddr_dyn)
208
209static const struct reg_desc ddrphy_dyn[] = {
210 DDRPHY_REG_DYN(pir),
211 DDRPHY_REG_DYN(pgsr),
212 DDRPHY_REG_DYN(zq0sr0),
213 DDRPHY_REG_DYN(zq0sr1),
214 DDRPHY_REG_DYN(dx0gsr0),
215 DDRPHY_REG_DYN(dx0gsr1),
216 DDRPHY_REG_DYN(dx1gsr0),
217 DDRPHY_REG_DYN(dx1gsr1),
218 DDRPHY_REG_DYN(dx2gsr0),
219 DDRPHY_REG_DYN(dx2gsr1),
220 DDRPHY_REG_DYN(dx3gsr0),
221 DDRPHY_REG_DYN(dx3gsr1),
222};
223
224#define DDRPHY_REG_DYN_SIZE ARRAY_SIZE(ddrphy_dyn)
225
226#endif
227
Patrick Delaunayd892d272019-04-10 14:09:25 +0200228/*****************************************************************
229 * REGISTERS ARRAY: used to parse device tree and interactive mode
230 *****************************************************************/
Patrick Delaunay939d5362018-03-12 10:46:11 +0100231enum reg_type {
232 REG_REG,
233 REG_TIMING,
234 REG_PERF,
235 REG_MAP,
236 REGPHY_REG,
237 REGPHY_TIMING,
238 REGPHY_CAL,
Patrick Delaunaybbee2702019-04-10 14:09:27 +0200239#ifdef CONFIG_STM32MP1_DDR_INTERACTIVE
240/* dynamic registers => managed in driver or not changed,
241 * can be dumped in interactive mode
242 */
243 REG_DYN,
244 REGPHY_DYN,
245#endif
Patrick Delaunay939d5362018-03-12 10:46:11 +0100246 REG_TYPE_NB
247};
248
249enum base_type {
250 DDR_BASE,
251 DDRPHY_BASE,
252 NONE_BASE
253};
254
255struct ddr_reg_info {
256 const char *name;
257 const struct reg_desc *desc;
258 u8 size;
259 enum base_type base;
260};
261
262#define DDRPHY_REG_CAL(x) DDRPHY_REG(x, stm32mp1_ddrphy_cal)
263
264const struct ddr_reg_info ddr_registers[REG_TYPE_NB] = {
265[REG_REG] = {
Patrick Delaunayd892d272019-04-10 14:09:25 +0200266 "static", ddr_reg, DDRCTL_REG_REG_SIZE, DDR_BASE},
Patrick Delaunay939d5362018-03-12 10:46:11 +0100267[REG_TIMING] = {
Patrick Delaunayd892d272019-04-10 14:09:25 +0200268 "timing", ddr_timing, DDRCTL_REG_TIMING_SIZE, DDR_BASE},
Patrick Delaunay939d5362018-03-12 10:46:11 +0100269[REG_PERF] = {
Patrick Delaunayd892d272019-04-10 14:09:25 +0200270 "perf", ddr_perf, DDRCTL_REG_PERF_SIZE, DDR_BASE},
Patrick Delaunay939d5362018-03-12 10:46:11 +0100271[REG_MAP] = {
Patrick Delaunayd892d272019-04-10 14:09:25 +0200272 "map", ddr_map, DDRCTL_REG_MAP_SIZE, DDR_BASE},
Patrick Delaunay939d5362018-03-12 10:46:11 +0100273[REGPHY_REG] = {
Patrick Delaunayd892d272019-04-10 14:09:25 +0200274 "static", ddrphy_reg, DDRPHY_REG_REG_SIZE, DDRPHY_BASE},
Patrick Delaunay939d5362018-03-12 10:46:11 +0100275[REGPHY_TIMING] = {
Patrick Delaunayd892d272019-04-10 14:09:25 +0200276 "timing", ddrphy_timing, DDRPHY_REG_TIMING_SIZE, DDRPHY_BASE},
Patrick Delaunay939d5362018-03-12 10:46:11 +0100277[REGPHY_CAL] = {
Patrick Delaunayd892d272019-04-10 14:09:25 +0200278 "cal", ddrphy_cal, DDRPHY_REG_CAL_SIZE, DDRPHY_BASE},
Patrick Delaunaybbee2702019-04-10 14:09:27 +0200279#ifdef CONFIG_STM32MP1_DDR_INTERACTIVE
280[REG_DYN] = {
281 "dyn", ddr_dyn, DDR_REG_DYN_SIZE, DDR_BASE},
282[REGPHY_DYN] = {
283 "dyn", ddrphy_dyn, DDRPHY_REG_DYN_SIZE, DDRPHY_BASE},
284#endif
285
Patrick Delaunay939d5362018-03-12 10:46:11 +0100286};
287
288const char *base_name[] = {
289 [DDR_BASE] = "ctl",
290 [DDRPHY_BASE] = "phy",
291};
292
293static u32 get_base_addr(const struct ddr_info *priv, enum base_type base)
294{
295 if (base == DDRPHY_BASE)
296 return (u32)priv->phy;
297 else
298 return (u32)priv->ctl;
299}
300
301static void set_reg(const struct ddr_info *priv,
302 enum reg_type type,
303 const void *param)
304{
305 unsigned int i;
306 unsigned int *ptr, value;
307 enum base_type base = ddr_registers[type].base;
308 u32 base_addr = get_base_addr(priv, base);
309 const struct reg_desc *desc = ddr_registers[type].desc;
310
311 debug("init %s\n", ddr_registers[type].name);
312 for (i = 0; i < ddr_registers[type].size; i++) {
313 ptr = (unsigned int *)(base_addr + desc[i].offset);
314 if (desc[i].par_offset == INVALID_OFFSET) {
315 pr_err("invalid parameter offset for %s", desc[i].name);
316 } else {
317 value = *((u32 *)((u32)param +
318 desc[i].par_offset));
319 writel(value, ptr);
320 debug("[0x%x] %s= 0x%08x\n",
321 (u32)ptr, desc[i].name, value);
322 }
323 }
Patrick Delaunaybbee2702019-04-10 14:09:27 +0200324}
325
326#ifdef CONFIG_STM32MP1_DDR_INTERACTIVE
327static void stm32mp1_dump_reg_desc(u32 base_addr, const struct reg_desc *desc)
328{
329 unsigned int *ptr;
330
331 ptr = (unsigned int *)(base_addr + desc->offset);
332 printf("%s= 0x%08x\n", desc->name, readl(ptr));
333}
334
335static void stm32mp1_dump_param_desc(u32 par_addr, const struct reg_desc *desc)
336{
337 unsigned int *ptr;
338
339 ptr = (unsigned int *)(par_addr + desc->par_offset);
340 printf("%s= 0x%08x\n", desc->name, readl(ptr));
341}
342
343static const struct reg_desc *found_reg(const char *name, enum reg_type *type)
344{
345 unsigned int i, j;
346 const struct reg_desc *desc;
347
348 for (i = 0; i < ARRAY_SIZE(ddr_registers); i++) {
349 desc = ddr_registers[i].desc;
350 for (j = 0; j < ddr_registers[i].size; j++) {
351 if (strcmp(name, desc[j].name) == 0) {
352 *type = i;
353 return &desc[j];
354 }
355 }
356 }
357 *type = REG_TYPE_NB;
358 return NULL;
359}
360
361int stm32mp1_dump_reg(const struct ddr_info *priv,
362 const char *name)
363{
364 unsigned int i, j;
365 const struct reg_desc *desc;
366 u32 base_addr;
367 enum base_type p_base;
368 enum reg_type type;
369 const char *p_name;
370 enum base_type filter = NONE_BASE;
371 int result = -1;
372
373 if (name) {
374 if (strcmp(name, base_name[DDR_BASE]) == 0)
375 filter = DDR_BASE;
376 else if (strcmp(name, base_name[DDRPHY_BASE]) == 0)
377 filter = DDRPHY_BASE;
378 }
379
380 for (i = 0; i < ARRAY_SIZE(ddr_registers); i++) {
381 p_base = ddr_registers[i].base;
382 p_name = ddr_registers[i].name;
383 if (!name || (filter == p_base || !strcmp(name, p_name))) {
384 result = 0;
385 desc = ddr_registers[i].desc;
386 base_addr = get_base_addr(priv, p_base);
387 printf("==%s.%s==\n", base_name[p_base], p_name);
388 for (j = 0; j < ddr_registers[i].size; j++)
389 stm32mp1_dump_reg_desc(base_addr, &desc[j]);
390 }
391 }
392 if (result) {
393 desc = found_reg(name, &type);
394 if (desc) {
395 p_base = ddr_registers[type].base;
396 base_addr = get_base_addr(priv, p_base);
397 stm32mp1_dump_reg_desc(base_addr, desc);
398 result = 0;
399 }
400 }
401 return result;
Patrick Delaunay939d5362018-03-12 10:46:11 +0100402}
403
Patrick Delaunaybbee2702019-04-10 14:09:27 +0200404void stm32mp1_edit_reg(const struct ddr_info *priv,
405 char *name, char *string)
406{
407 unsigned long *ptr, value;
408 enum reg_type type;
409 enum base_type base;
410 const struct reg_desc *desc;
411 u32 base_addr;
412
413 desc = found_reg(name, &type);
414
415 if (!desc) {
416 printf("%s not found\n", name);
417 return;
418 }
419 if (strict_strtoul(string, 16, &value) < 0) {
420 printf("invalid value %s\n", string);
421 return;
422 }
423 base = ddr_registers[type].base;
424 base_addr = get_base_addr(priv, base);
425 ptr = (unsigned long *)(base_addr + desc->offset);
426 writel(value, ptr);
427 printf("%s= 0x%08x\n", desc->name, readl(ptr));
428}
429
430static u32 get_par_addr(const struct stm32mp1_ddr_config *config,
431 enum reg_type type)
432{
433 u32 par_addr = 0x0;
434
435 switch (type) {
436 case REG_REG:
437 par_addr = (u32)&config->c_reg;
438 break;
439 case REG_TIMING:
440 par_addr = (u32)&config->c_timing;
441 break;
442 case REG_PERF:
443 par_addr = (u32)&config->c_perf;
444 break;
445 case REG_MAP:
446 par_addr = (u32)&config->c_map;
447 break;
448 case REGPHY_REG:
449 par_addr = (u32)&config->p_reg;
450 break;
451 case REGPHY_TIMING:
452 par_addr = (u32)&config->p_timing;
453 break;
454 case REGPHY_CAL:
455 par_addr = (u32)&config->p_cal;
456 break;
457 case REG_DYN:
458 case REGPHY_DYN:
459 case REG_TYPE_NB:
460 par_addr = (u32)NULL;
461 break;
462 }
463
464 return par_addr;
465}
466
467int stm32mp1_dump_param(const struct stm32mp1_ddr_config *config,
468 const char *name)
469{
470 unsigned int i, j;
471 const struct reg_desc *desc;
472 u32 par_addr;
473 enum base_type p_base;
474 enum reg_type type;
475 const char *p_name;
476 enum base_type filter = NONE_BASE;
477 int result = -EINVAL;
478
479 if (name) {
480 if (strcmp(name, base_name[DDR_BASE]) == 0)
481 filter = DDR_BASE;
482 else if (strcmp(name, base_name[DDRPHY_BASE]) == 0)
483 filter = DDRPHY_BASE;
484 }
485
486 for (i = 0; i < ARRAY_SIZE(ddr_registers); i++) {
487 par_addr = get_par_addr(config, i);
488 if (!par_addr)
489 continue;
490 p_base = ddr_registers[i].base;
491 p_name = ddr_registers[i].name;
492 if (!name || (filter == p_base || !strcmp(name, p_name))) {
493 result = 0;
494 desc = ddr_registers[i].desc;
495 printf("==%s.%s==\n", base_name[p_base], p_name);
496 for (j = 0; j < ddr_registers[i].size; j++)
497 stm32mp1_dump_param_desc(par_addr, &desc[j]);
498 }
499 }
500 if (result) {
501 desc = found_reg(name, &type);
502 if (desc) {
503 par_addr = get_par_addr(config, type);
504 if (par_addr) {
505 stm32mp1_dump_param_desc(par_addr, desc);
506 result = 0;
507 }
508 }
509 }
510 return result;
511}
512
513void stm32mp1_edit_param(const struct stm32mp1_ddr_config *config,
514 char *name, char *string)
515{
516 unsigned long *ptr, value;
517 enum reg_type type;
518 const struct reg_desc *desc;
519 u32 par_addr;
520
521 desc = found_reg(name, &type);
522 if (!desc) {
523 printf("%s not found\n", name);
524 return;
525 }
526 if (strict_strtoul(string, 16, &value) < 0) {
527 printf("invalid value %s\n", string);
528 return;
529 }
530 par_addr = get_par_addr(config, type);
531 if (!par_addr) {
532 printf("no parameter %s\n", name);
533 return;
534 }
535 ptr = (unsigned long *)(par_addr + desc->par_offset);
536 writel(value, ptr);
537 printf("%s= 0x%08x\n", desc->name, readl(ptr));
538}
539#endif
540
541__weak bool stm32mp1_ddr_interactive(void *priv,
542 enum stm32mp1_ddr_interact_step step,
543 const struct stm32mp1_ddr_config *config)
544{
545 return false;
546}
547
548#define INTERACTIVE(step)\
549 stm32mp1_ddr_interactive(priv, step, config)
550
Patrick Delaunay939d5362018-03-12 10:46:11 +0100551static void ddrphy_idone_wait(struct stm32mp1_ddrphy *phy)
552{
553 u32 pgsr;
554 int ret;
555
556 ret = readl_poll_timeout(&phy->pgsr, pgsr,
557 pgsr & (DDRPHYC_PGSR_IDONE |
558 DDRPHYC_PGSR_DTERR |
559 DDRPHYC_PGSR_DTIERR |
560 DDRPHYC_PGSR_DFTERR |
561 DDRPHYC_PGSR_RVERR |
562 DDRPHYC_PGSR_RVEIRR),
563 1000000);
564 debug("\n[0x%08x] pgsr = 0x%08x ret=%d\n",
565 (u32)&phy->pgsr, pgsr, ret);
566}
567
568void stm32mp1_ddrphy_init(struct stm32mp1_ddrphy *phy, u32 pir)
569{
570 pir |= DDRPHYC_PIR_INIT;
571 writel(pir, &phy->pir);
572 debug("[0x%08x] pir = 0x%08x -> 0x%08x\n",
573 (u32)&phy->pir, pir, readl(&phy->pir));
574
575 /* need to wait 10 configuration clock before start polling */
576 udelay(10);
577
578 /* Wait DRAM initialization and Gate Training Evaluation complete */
579 ddrphy_idone_wait(phy);
580}
581
582/* start quasi dynamic register update */
583static void start_sw_done(struct stm32mp1_ddrctl *ctl)
584{
585 clrbits_le32(&ctl->swctl, DDRCTRL_SWCTL_SW_DONE);
586}
587
588/* wait quasi dynamic register update */
589static void wait_sw_done_ack(struct stm32mp1_ddrctl *ctl)
590{
591 int ret;
592 u32 swstat;
593
594 setbits_le32(&ctl->swctl, DDRCTRL_SWCTL_SW_DONE);
595
596 ret = readl_poll_timeout(&ctl->swstat, swstat,
597 swstat & DDRCTRL_SWSTAT_SW_DONE_ACK,
598 1000000);
599 if (ret)
600 panic("Timeout initialising DRAM : DDR->swstat = %x\n",
601 swstat);
602
603 debug("[0x%08x] swstat = 0x%08x\n", (u32)&ctl->swstat, swstat);
604}
605
606/* wait quasi dynamic register update */
607static void wait_operating_mode(struct ddr_info *priv, int mode)
608{
609 u32 stat, val, mask, val2 = 0, mask2 = 0;
610 int ret;
611
612 mask = DDRCTRL_STAT_OPERATING_MODE_MASK;
613 val = mode;
614 /* self-refresh due to software => check also STAT.selfref_type */
615 if (mode == DDRCTRL_STAT_OPERATING_MODE_SR) {
616 mask |= DDRCTRL_STAT_SELFREF_TYPE_MASK;
Patrick Delaunay250bf902019-04-10 14:09:21 +0200617 val |= DDRCTRL_STAT_SELFREF_TYPE_SR;
Patrick Delaunay939d5362018-03-12 10:46:11 +0100618 } else if (mode == DDRCTRL_STAT_OPERATING_MODE_NORMAL) {
619 /* normal mode: handle also automatic self refresh */
620 mask2 = DDRCTRL_STAT_OPERATING_MODE_MASK |
621 DDRCTRL_STAT_SELFREF_TYPE_MASK;
622 val2 = DDRCTRL_STAT_OPERATING_MODE_SR |
623 DDRCTRL_STAT_SELFREF_TYPE_ASR;
624 }
625
626 ret = readl_poll_timeout(&priv->ctl->stat, stat,
627 ((stat & mask) == val) ||
628 (mask2 && ((stat & mask2) == val2)),
629 1000000);
630
631 if (ret)
632 panic("Timeout DRAM : DDR->stat = %x\n", stat);
633
634 debug("[0x%08x] stat = 0x%08x\n", (u32)&priv->ctl->stat, stat);
635}
636
637void stm32mp1_refresh_disable(struct stm32mp1_ddrctl *ctl)
638{
639 start_sw_done(ctl);
640 /* quasi-dynamic register update*/
641 setbits_le32(&ctl->rfshctl3, DDRCTRL_RFSHCTL3_DIS_AUTO_REFRESH);
Patrick Delaunayeca9bc02020-03-06 11:14:09 +0100642 clrbits_le32(&ctl->pwrctl, DDRCTRL_PWRCTL_POWERDOWN_EN |
643 DDRCTRL_PWRCTL_SELFREF_EN);
Patrick Delaunay939d5362018-03-12 10:46:11 +0100644 clrbits_le32(&ctl->dfimisc, DDRCTRL_DFIMISC_DFI_INIT_COMPLETE_EN);
645 wait_sw_done_ack(ctl);
646}
647
648void stm32mp1_refresh_restore(struct stm32mp1_ddrctl *ctl,
649 u32 rfshctl3, u32 pwrctl)
650{
651 start_sw_done(ctl);
652 if (!(rfshctl3 & DDRCTRL_RFSHCTL3_DIS_AUTO_REFRESH))
653 clrbits_le32(&ctl->rfshctl3, DDRCTRL_RFSHCTL3_DIS_AUTO_REFRESH);
654 if (pwrctl & DDRCTRL_PWRCTL_POWERDOWN_EN)
655 setbits_le32(&ctl->pwrctl, DDRCTRL_PWRCTL_POWERDOWN_EN);
Patrick Delaunayeca9bc02020-03-06 11:14:09 +0100656 if ((pwrctl & DDRCTRL_PWRCTL_SELFREF_EN))
657 setbits_le32(&ctl->pwrctl, DDRCTRL_PWRCTL_SELFREF_EN);
Patrick Delaunay939d5362018-03-12 10:46:11 +0100658 setbits_le32(&ctl->dfimisc, DDRCTRL_DFIMISC_DFI_INIT_COMPLETE_EN);
659 wait_sw_done_ack(ctl);
660}
661
662/* board-specific DDR power initializations. */
Patrick Delaunay4175f452019-04-10 14:09:26 +0200663__weak int board_ddr_power_init(enum ddr_type ddr_type)
Patrick Delaunay939d5362018-03-12 10:46:11 +0100664{
665 return 0;
666}
667
668__maybe_unused
669void stm32mp1_ddr_init(struct ddr_info *priv,
670 const struct stm32mp1_ddr_config *config)
671{
672 u32 pir;
Patrick Delaunay4175f452019-04-10 14:09:26 +0200673 int ret = -EINVAL;
Patrick Delaunay2ebc2112020-03-06 11:14:03 +0100674 char bus_width;
675
676 switch (config->c_reg.mstr & DDRCTRL_MSTR_DATA_BUS_WIDTH_MASK) {
677 case DDRCTRL_MSTR_DATA_BUS_WIDTH_QUARTER:
678 bus_width = 8;
679 break;
680 case DDRCTRL_MSTR_DATA_BUS_WIDTH_HALF:
681 bus_width = 16;
682 break;
683 default:
684 bus_width = 32;
685 break;
686 }
687
Patrick Delaunay939d5362018-03-12 10:46:11 +0100688
Patrick Delaunay4175f452019-04-10 14:09:26 +0200689 if (config->c_reg.mstr & DDRCTRL_MSTR_DDR3)
690 ret = board_ddr_power_init(STM32MP_DDR3);
Patrick Delaunay2ebc2112020-03-06 11:14:03 +0100691 else if (config->c_reg.mstr & DDRCTRL_MSTR_LPDDR2) {
692 if (bus_width == 32)
693 ret = board_ddr_power_init(STM32MP_LPDDR2_32);
694 else
695 ret = board_ddr_power_init(STM32MP_LPDDR2_16);
696 } else if (config->c_reg.mstr & DDRCTRL_MSTR_LPDDR3) {
697 if (bus_width == 32)
698 ret = board_ddr_power_init(STM32MP_LPDDR3_32);
699 else
700 ret = board_ddr_power_init(STM32MP_LPDDR3_16);
701 }
Patrick Delaunay939d5362018-03-12 10:46:11 +0100702 if (ret)
703 panic("ddr power init failed\n");
704
Patrick Delaunaybbee2702019-04-10 14:09:27 +0200705start:
Patrick Delaunay939d5362018-03-12 10:46:11 +0100706 debug("name = %s\n", config->info.name);
Patrick Delaunay29e1a942019-04-10 14:09:23 +0200707 debug("speed = %d kHz\n", config->info.speed);
Patrick Delaunay939d5362018-03-12 10:46:11 +0100708 debug("size = 0x%x\n", config->info.size);
709/*
710 * 1. Program the DWC_ddr_umctl2 registers
711 * 1.1 RESETS: presetn, core_ddrc_rstn, aresetn
712 */
713 /* Assert All DDR part */
714 setbits_le32(priv->rcc + RCC_DDRITFCR, RCC_DDRITFCR_DDRCAPBRST);
715 setbits_le32(priv->rcc + RCC_DDRITFCR, RCC_DDRITFCR_DDRCAXIRST);
716 setbits_le32(priv->rcc + RCC_DDRITFCR, RCC_DDRITFCR_DDRCORERST);
717 setbits_le32(priv->rcc + RCC_DDRITFCR, RCC_DDRITFCR_DPHYAPBRST);
718 setbits_le32(priv->rcc + RCC_DDRITFCR, RCC_DDRITFCR_DPHYRST);
719 setbits_le32(priv->rcc + RCC_DDRITFCR, RCC_DDRITFCR_DPHYCTLRST);
720
721/* 1.2. start CLOCK */
722 if (stm32mp1_ddr_clk_enable(priv, config->info.speed))
Patrick Delaunay29e1a942019-04-10 14:09:23 +0200723 panic("invalid DRAM clock : %d kHz\n",
Patrick Delaunay939d5362018-03-12 10:46:11 +0100724 config->info.speed);
725
726/* 1.3. deassert reset */
727 /* de-assert PHY rstn and ctl_rstn via DPHYRST and DPHYCTLRST */
728 clrbits_le32(priv->rcc + RCC_DDRITFCR, RCC_DDRITFCR_DPHYRST);
729 clrbits_le32(priv->rcc + RCC_DDRITFCR, RCC_DDRITFCR_DPHYCTLRST);
730 /* De-assert presetn once the clocks are active
731 * and stable via DDRCAPBRST bit
732 */
733 clrbits_le32(priv->rcc + RCC_DDRITFCR, RCC_DDRITFCR_DDRCAPBRST);
734
Patrick Delaunay1f987042019-04-10 14:09:22 +0200735/* 1.4. wait 128 cycles to permit initialization of end logic */
736 udelay(2);
737 /* for PCLK = 133MHz => 1 us is enough, 2 to allow lower frequency */
Patrick Delaunay939d5362018-03-12 10:46:11 +0100738
Patrick Delaunaybbee2702019-04-10 14:09:27 +0200739 if (INTERACTIVE(STEP_DDR_RESET))
740 goto start;
741
Patrick Delaunay939d5362018-03-12 10:46:11 +0100742/* 1.5. initialize registers ddr_umctl2 */
743 /* Stop uMCTL2 before PHY is ready */
744 clrbits_le32(&priv->ctl->dfimisc, DDRCTRL_DFIMISC_DFI_INIT_COMPLETE_EN);
745 debug("[0x%08x] dfimisc = 0x%08x\n",
746 (u32)&priv->ctl->dfimisc, readl(&priv->ctl->dfimisc));
747
748 set_reg(priv, REG_REG, &config->c_reg);
749 set_reg(priv, REG_TIMING, &config->c_timing);
750 set_reg(priv, REG_MAP, &config->c_map);
751
752 /* skip CTRL init, SDRAM init is done by PHY PUBL */
753 clrsetbits_le32(&priv->ctl->init0,
754 DDRCTRL_INIT0_SKIP_DRAM_INIT_MASK,
755 DDRCTRL_INIT0_SKIP_DRAM_INIT_NORMAL);
756
757 set_reg(priv, REG_PERF, &config->c_perf);
758
Patrick Delaunaybbee2702019-04-10 14:09:27 +0200759 if (INTERACTIVE(STEP_CTL_INIT))
760 goto start;
761
Patrick Delaunay939d5362018-03-12 10:46:11 +0100762/* 2. deassert reset signal core_ddrc_rstn, aresetn and presetn */
763 clrbits_le32(priv->rcc + RCC_DDRITFCR, RCC_DDRITFCR_DDRCORERST);
764 clrbits_le32(priv->rcc + RCC_DDRITFCR, RCC_DDRITFCR_DDRCAXIRST);
765 clrbits_le32(priv->rcc + RCC_DDRITFCR, RCC_DDRITFCR_DPHYAPBRST);
766
767/* 3. start PHY init by accessing relevant PUBL registers
768 * (DXGCR, DCR, PTR*, MR*, DTPR*)
769 */
770 set_reg(priv, REGPHY_REG, &config->p_reg);
771 set_reg(priv, REGPHY_TIMING, &config->p_timing);
Patrick Delaunaya68e2d62020-03-06 11:14:11 +0100772 if (config->p_cal_present)
773 set_reg(priv, REGPHY_CAL, &config->p_cal);
Patrick Delaunay939d5362018-03-12 10:46:11 +0100774
Patrick Delaunaybbee2702019-04-10 14:09:27 +0200775 if (INTERACTIVE(STEP_PHY_INIT))
776 goto start;
777
Patrick Delaunay939d5362018-03-12 10:46:11 +0100778/* 4. Monitor PHY init status by polling PUBL register PGSR.IDONE
779 * Perform DDR PHY DRAM initialization and Gate Training Evaluation
780 */
781 ddrphy_idone_wait(priv->phy);
782
783/* 5. Indicate to PUBL that controller performs SDRAM initialization
784 * by setting PIR.INIT and PIR CTLDINIT and pool PGSR.IDONE
785 * DRAM init is done by PHY, init0.skip_dram.init = 1
786 */
787 pir = DDRPHYC_PIR_DLLSRST | DDRPHYC_PIR_DLLLOCK | DDRPHYC_PIR_ZCAL |
788 DDRPHYC_PIR_ITMSRST | DDRPHYC_PIR_DRAMINIT | DDRPHYC_PIR_ICPC;
789
790 if (config->c_reg.mstr & DDRCTRL_MSTR_DDR3)
791 pir |= DDRPHYC_PIR_DRAMRST; /* only for DDR3 */
792
793 stm32mp1_ddrphy_init(priv->phy, pir);
794
795/* 6. SET DFIMISC.dfi_init_complete_en to 1 */
796 /* Enable quasi-dynamic register programming*/
797 start_sw_done(priv->ctl);
798 setbits_le32(&priv->ctl->dfimisc, DDRCTRL_DFIMISC_DFI_INIT_COMPLETE_EN);
799 wait_sw_done_ack(priv->ctl);
800
801/* 7. Wait for DWC_ddr_umctl2 to move to normal operation mode
802 * by monitoring STAT.operating_mode signal
803 */
804 /* wait uMCTL2 ready */
805
806 wait_operating_mode(priv, DDRCTRL_STAT_OPERATING_MODE_NORMAL);
807
Patrick Delaunaya68e2d62020-03-06 11:14:11 +0100808 if (config->p_cal_present) {
809 debug("DDR DQS training skipped.\n");
810 } else {
811 debug("DDR DQS training : ");
Patrick Delaunay939d5362018-03-12 10:46:11 +0100812/* 8. Disable Auto refresh and power down by setting
813 * - RFSHCTL3.dis_au_refresh = 1
814 * - PWRCTL.powerdown_en = 0
815 * - DFIMISC.dfiinit_complete_en = 0
816 */
Patrick Delaunaya68e2d62020-03-06 11:14:11 +0100817 stm32mp1_refresh_disable(priv->ctl);
Patrick Delaunay939d5362018-03-12 10:46:11 +0100818
819/* 9. Program PUBL PGCR to enable refresh during training and rank to train
820 * not done => keep the programed value in PGCR
821 */
822
823/* 10. configure PUBL PIR register to specify which training step to run */
824 /* warning : RVTRN is not supported by this PUBL */
Patrick Delaunaya68e2d62020-03-06 11:14:11 +0100825 stm32mp1_ddrphy_init(priv->phy, DDRPHYC_PIR_QSTRN);
Patrick Delaunay939d5362018-03-12 10:46:11 +0100826
827/* 11. monitor PUB PGSR.IDONE to poll cpmpletion of training sequence */
Patrick Delaunaya68e2d62020-03-06 11:14:11 +0100828 ddrphy_idone_wait(priv->phy);
Patrick Delaunay939d5362018-03-12 10:46:11 +0100829
830/* 12. set back registers in step 8 to the orginal values if desidered */
Patrick Delaunaya68e2d62020-03-06 11:14:11 +0100831 stm32mp1_refresh_restore(priv->ctl, config->c_reg.rfshctl3,
832 config->c_reg.pwrctl);
833 } /* if (config->p_cal_present) */
Patrick Delaunay939d5362018-03-12 10:46:11 +0100834
835 /* enable uMCTL2 AXI port 0 and 1 */
836 setbits_le32(&priv->ctl->pctrl_0, DDRCTRL_PCTRL_N_PORT_EN);
837 setbits_le32(&priv->ctl->pctrl_1, DDRCTRL_PCTRL_N_PORT_EN);
Patrick Delaunaybbee2702019-04-10 14:09:27 +0200838
839 if (INTERACTIVE(STEP_DDR_READY))
840 goto start;
Patrick Delaunay939d5362018-03-12 10:46:11 +0100841}