blob: 7ac93786be632375d57e140975a0d3a6d31b385d [file] [log] [blame]
Masahiro Yamada93d92d42016-01-09 01:51:15 +09001/*
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
22static void __iomem *get_phy_base(int ch)
23{
24 return (void __iomem *)(0x5b830000 + ch * 0x00200000);
25}
26
27static int get_nr_ch(void)
28{
29 const struct uniphier_board_data *bd = uniphier_get_board_param();
30
Masahiro Yamada51244a62016-03-04 15:54:29 +090031 return bd->dram_ch[2].size ? 3 : 2;
Masahiro Yamada93d92d42016-01-09 01:51:15 +090032}
33
34static int get_nr_datx8(int ch)
35{
Masahiro Yamada93d92d42016-01-09 01:51:15 +090036 const struct uniphier_board_data *bd = uniphier_get_board_param();
37
Masahiro Yamada51244a62016-03-04 15:54:29 +090038 return bd->dram_ch[ch].width / 8;
Masahiro Yamada93d92d42016-01-09 01:51:15 +090039}
40
41static 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
50static 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
70static 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
106static 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
116static 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
124static 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
137static 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
145static 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
160static 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
168static 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
182static 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
190static 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
199static 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
219static 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
273static 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
304U_BOOT_CMD(
305 ddrm, 2, 1, do_ddrm,
306 "UniPhier DDR PHY parameters dumper",
307 "- dump all of the followings\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);