]> git.ipfire.org Git - people/ms/u-boot.git/blob - arch/arm/mach-uniphier/dram/cmd_ddrmphy.c
treewide: fix "followings" to "following"
[people/ms/u-boot.git] / arch / arm / mach-uniphier / dram / cmd_ddrmphy.c
1 /*
2 * Copyright (C) 2015 Masahiro Yamada <yamada.masahiro@socionext.com>
3 *
4 * SPDX-License-Identifier: GPL-2.0+
5 */
6
7 #include <common.h>
8 #include <linux/io.h>
9
10 #include "../init.h"
11 #include "ddrmphy-regs.h"
12
13 /* Select either decimal or hexadecimal */
14 #if 1
15 #define PRINTF_FORMAT "%2d"
16 #else
17 #define PRINTF_FORMAT "%02x"
18 #endif
19 /* field separator */
20 #define FS " "
21
22 static void __iomem *get_phy_base(int ch)
23 {
24 return (void __iomem *)(0x5b830000 + ch * 0x00200000);
25 }
26
27 static int get_nr_ch(void)
28 {
29 const struct uniphier_board_data *bd = uniphier_get_board_param();
30
31 return bd->dram_ch[2].size ? 3 : 2;
32 }
33
34 static int get_nr_datx8(int ch)
35 {
36 const struct uniphier_board_data *bd = uniphier_get_board_param();
37
38 return bd->dram_ch[ch].width / 8;
39 }
40
41 static void print_bdl(void __iomem *reg, int n)
42 {
43 u32 val = readl(reg);
44 int i;
45
46 for (i = 0; i < n; i++)
47 printf(FS PRINTF_FORMAT, (val >> i * 8) & 0x1f);
48 }
49
50 static void dump_loop(void (*callback)(void __iomem *))
51 {
52 int ch, dx, nr_ch, nr_dx;
53 void __iomem *dx_base;
54
55 nr_ch = get_nr_ch();
56
57 for (ch = 0; ch < nr_ch; ch++) {
58 dx_base = get_phy_base(ch) + DMPHY_DX_BASE;
59 nr_dx = get_nr_datx8(ch);
60
61 for (dx = 0; dx < nr_dx; dx++) {
62 printf("CH%dDX%d:", ch, dx);
63 (*callback)(dx_base);
64 dx_base += DMPHY_DX_STRIDE;
65 printf("\n");
66 }
67 }
68 }
69
70 static void zq_dump(void)
71 {
72 int ch, zq, nr_ch, nr_zq, i;
73 void __iomem *zq_base;
74 u32 dr, pr;
75
76 printf("\n--- Impedance Data ---\n");
77 printf(" ZPD ZPU OPD OPU ZDV ODV\n");
78
79 nr_ch = get_nr_ch();
80
81 for (ch = 0; ch < nr_ch; ch++) {
82 zq_base = get_phy_base(ch) + DMPHY_ZQ_BASE;
83 nr_zq = 3;
84
85 for (zq = 0; zq < nr_zq; zq++) {
86 printf("CH%dZQ%d:", ch, zq);
87
88 dr = readl(zq_base + DMPHY_ZQ_DR);
89 for (i = 0; i < 4; i++) {
90 printf(FS PRINTF_FORMAT, dr & 0x7f);
91 dr >>= 7;
92 }
93
94 pr = readl(zq_base + DMPHY_ZQ_PR);
95 for (i = 0; i < 2; i++) {
96 printf(FS PRINTF_FORMAT, pr & 0xf);
97 pr >>= 4;
98 }
99
100 zq_base += DMPHY_ZQ_STRIDE;
101 printf("\n");
102 }
103 }
104 }
105
106 static void __wbdl_dump(void __iomem *dx_base)
107 {
108 print_bdl(dx_base + DMPHY_DX_BDLR0, 4);
109 print_bdl(dx_base + DMPHY_DX_BDLR1, 4);
110 print_bdl(dx_base + DMPHY_DX_BDLR2, 2);
111
112 printf(FS "(+" PRINTF_FORMAT ")",
113 readl(dx_base + DMPHY_DX_LCDLR1) & 0xff);
114 }
115
116 static void wbdl_dump(void)
117 {
118 printf("\n--- Write Bit Delay Line ---\n");
119 printf(" DQ0 DQ1 DQ2 DQ3 DQ4 DQ5 DQ6 DQ7 DM DQS (WDQD)\n");
120
121 dump_loop(&__wbdl_dump);
122 }
123
124 static void __rbdl_dump(void __iomem *dx_base)
125 {
126 print_bdl(dx_base + DMPHY_DX_BDLR3, 4);
127 print_bdl(dx_base + DMPHY_DX_BDLR4, 4);
128 print_bdl(dx_base + DMPHY_DX_BDLR5, 1);
129
130 printf(FS "(+" PRINTF_FORMAT ")",
131 (readl(dx_base + DMPHY_DX_LCDLR1) >> 8) & 0xff);
132
133 printf(FS "(+" PRINTF_FORMAT ")",
134 (readl(dx_base + DMPHY_DX_LCDLR1) >> 16) & 0xff);
135 }
136
137 static void rbdl_dump(void)
138 {
139 printf("\n--- Read Bit Delay Line ---\n");
140 printf(" DQ0 DQ1 DQ2 DQ3 DQ4 DQ5 DQ6 DQ7 DM (RDQSD) (RDQSND)\n");
141
142 dump_loop(&__rbdl_dump);
143 }
144
145 static void __wld_dump(void __iomem *dx_base)
146 {
147 int rank;
148 u32 lcdlr0 = readl(dx_base + DMPHY_DX_LCDLR0);
149 u32 gtr = readl(dx_base + DMPHY_DX_GTR);
150
151 for (rank = 0; rank < 4; rank++) {
152 u32 wld = (lcdlr0 >> (8 * rank)) & 0xff; /* Delay */
153 u32 wlsl = (gtr >> (12 + 2 * rank)) & 0x3; /* System Latency */
154
155 printf(FS PRINTF_FORMAT "%sT", wld,
156 wlsl == 0 ? "-1" : wlsl == 1 ? "+0" : "+1");
157 }
158 }
159
160 static void wld_dump(void)
161 {
162 printf("\n--- Write Leveling Delay ---\n");
163 printf(" Rank0 Rank1 Rank2 Rank3\n");
164
165 dump_loop(&__wld_dump);
166 }
167
168 static void __dqsgd_dump(void __iomem *dx_base)
169 {
170 int rank;
171 u32 lcdlr2 = readl(dx_base + DMPHY_DX_LCDLR2);
172 u32 gtr = readl(dx_base + DMPHY_DX_GTR);
173
174 for (rank = 0; rank < 4; rank++) {
175 u32 dqsgd = (lcdlr2 >> (8 * rank)) & 0xff; /* Delay */
176 u32 dgsl = (gtr >> (3 * rank)) & 0x7; /* System Latency */
177
178 printf(FS PRINTF_FORMAT "+%dT", dqsgd, dgsl);
179 }
180 }
181
182 static void dqsgd_dump(void)
183 {
184 printf("\n--- DQS Gating Delay ---\n");
185 printf(" Rank0 Rank1 Rank2 Rank3\n");
186
187 dump_loop(&__dqsgd_dump);
188 }
189
190 static void __mdl_dump(void __iomem *dx_base)
191 {
192 int i;
193 u32 mdl = readl(dx_base + DMPHY_DX_MDLR);
194
195 for (i = 0; i < 3; i++)
196 printf(FS PRINTF_FORMAT, (mdl >> (8 * i)) & 0xff);
197 }
198
199 static void mdl_dump(void)
200 {
201 printf("\n--- Master Delay Line ---\n");
202 printf(" IPRD TPRD MDLD\n");
203
204 dump_loop(&__mdl_dump);
205 }
206
207 #define REG_DUMP(x) \
208 { int ofst = DMPHY_ ## x; void __iomem *reg = phy_base + ofst; \
209 printf("%3d: %-10s: %p : %08x\n", \
210 ofst >> DMPHY_SHIFT, #x, reg, readl(reg)); }
211
212 #define DX_REG_DUMP(dx, x) \
213 { int ofst = DMPHY_DX_BASE + DMPHY_DX_STRIDE * (dx) + \
214 DMPHY_DX_## x; \
215 void __iomem *reg = phy_base + ofst; \
216 printf("%3d: DX%d%-7s: %p : %08x\n", \
217 ofst >> DMPHY_SHIFT, (dx), #x, reg, readl(reg)); }
218
219 static void reg_dump(void)
220 {
221 int ch, dx, nr_ch, nr_dx;
222 void __iomem *phy_base;
223
224 printf("\n--- DDR PHY registers ---\n");
225
226 nr_ch = get_nr_ch();
227
228 for (ch = 0; ch < nr_ch; ch++) {
229 phy_base = get_phy_base(ch);
230 nr_dx = get_nr_datx8(ch);
231
232 printf("== Ch%d ==\n", ch);
233 printf(" No: Name : Address : Data\n");
234
235 REG_DUMP(RIDR);
236 REG_DUMP(PIR);
237 REG_DUMP(PGCR0);
238 REG_DUMP(PGCR1);
239 REG_DUMP(PGCR2);
240 REG_DUMP(PGCR3);
241 REG_DUMP(PGSR0);
242 REG_DUMP(PGSR1);
243 REG_DUMP(PLLCR);
244 REG_DUMP(PTR0);
245 REG_DUMP(PTR1);
246 REG_DUMP(PTR2);
247 REG_DUMP(PTR3);
248 REG_DUMP(PTR4);
249 REG_DUMP(ACMDLR);
250 REG_DUMP(ACBDLR0);
251 REG_DUMP(DXCCR);
252 REG_DUMP(DSGCR);
253 REG_DUMP(DCR);
254 REG_DUMP(DTPR0);
255 REG_DUMP(DTPR1);
256 REG_DUMP(DTPR2);
257 REG_DUMP(DTPR3);
258 REG_DUMP(MR0);
259 REG_DUMP(MR1);
260 REG_DUMP(MR2);
261 REG_DUMP(MR3);
262
263 for (dx = 0; dx < nr_dx; dx++) {
264 DX_REG_DUMP(dx, GCR0);
265 DX_REG_DUMP(dx, GCR1);
266 DX_REG_DUMP(dx, GCR2);
267 DX_REG_DUMP(dx, GCR3);
268 DX_REG_DUMP(dx, GTR);
269 }
270 }
271 }
272
273 static int do_ddrm(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
274 {
275 char *cmd = argv[1];
276
277 if (argc == 1)
278 cmd = "all";
279
280 if (!strcmp(cmd, "zq") || !strcmp(cmd, "all"))
281 zq_dump();
282
283 if (!strcmp(cmd, "wbdl") || !strcmp(cmd, "all"))
284 wbdl_dump();
285
286 if (!strcmp(cmd, "rbdl") || !strcmp(cmd, "all"))
287 rbdl_dump();
288
289 if (!strcmp(cmd, "wld") || !strcmp(cmd, "all"))
290 wld_dump();
291
292 if (!strcmp(cmd, "dqsgd") || !strcmp(cmd, "all"))
293 dqsgd_dump();
294
295 if (!strcmp(cmd, "mdl") || !strcmp(cmd, "all"))
296 mdl_dump();
297
298 if (!strcmp(cmd, "reg") || !strcmp(cmd, "all"))
299 reg_dump();
300
301 return 0;
302 }
303
304 U_BOOT_CMD(
305 ddrm, 2, 1, do_ddrm,
306 "UniPhier DDR PHY parameters dumper",
307 "- dump all of the following\n"
308 "ddrm zq - dump Impedance Data\n"
309 "ddrm wbdl - dump Write Bit Delay\n"
310 "ddrm rbdl - dump Read Bit Delay\n"
311 "ddrm wld - dump Write Leveling\n"
312 "ddrm dqsgd - dump DQS Gating Delay\n"
313 "ddrm mdl - dump Master Delay Line\n"
314 "ddrm reg - dump registers\n"
315 );