Merge branch 'master' of http://git.denx.de/u-boot-sunxi
[platform/kernel/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 );