3dae12963b9faaaecbba7249a1a7c141a2210cd2
[oweals/u-boot.git] / arch / arm / mach-uniphier / dram / cmd_ddrphy.c
1 /*
2  * Copyright (C) 2014      Panasonic Corporation
3  * Copyright (C) 2015-2016 Socionext Inc.
4  *   Author: Masahiro Yamada <yamada.masahiro@socionext.com>
5  *
6  * SPDX-License-Identifier:     GPL-2.0+
7  */
8
9 #include <common.h>
10 #include <linux/io.h>
11 #include <linux/sizes.h>
12
13 #include "../soc-info.h"
14 #include "ddrphy-init.h"
15 #include "ddrphy-regs.h"
16
17 /* Select either decimal or hexadecimal */
18 #if 1
19 #define PRINTF_FORMAT "%2d"
20 #else
21 #define PRINTF_FORMAT "%02x"
22 #endif
23 /* field separator */
24 #define FS "   "
25
26 static unsigned long uniphier_ld4_base[] = {
27         0x5bc01000,
28         0x5be01000,
29         0 /* sentinel */
30 };
31
32 static unsigned long uniphier_pro4_base[] = {
33         0x5bc01000,
34         0x5be01000,
35         0 /* sentinel */
36 };
37
38 static unsigned long uniphier_sld8_base[] = {
39         0x5bc01000,
40         0x5be01000,
41         0 /* sentinel */
42 };
43
44 static void print_bdl(void __iomem *reg, int n)
45 {
46         u32 val = readl(reg);
47         int i;
48
49         for (i = 0; i < n; i++)
50                 printf(FS PRINTF_FORMAT, (val >> i * 6) & 0x3f);
51 }
52
53 static void dump_loop(unsigned long *base,
54                       void (*callback)(void __iomem *))
55 {
56         void __iomem *phy_base, *dx_base;
57         int p, dx;
58
59         for (p = 0; *base; base++, p++) {
60                 phy_base = ioremap(*base, SZ_4K);
61                 dx_base = phy_base + PHY_DX_BASE;
62
63                 for (dx = 0; dx < NR_DATX8_PER_DDRPHY; dx++) {
64                         printf("PHY%dDX%d:", p, dx);
65                         (*callback)(dx_base);
66                         dx_base += PHY_DX_STRIDE;
67                         printf("\n");
68                 }
69
70                 iounmap(phy_base);
71         }
72 }
73
74 static void __wbdl_dump(void __iomem *dx_base)
75 {
76         print_bdl(dx_base + PHY_DX_BDLR0, 5);
77         print_bdl(dx_base + PHY_DX_BDLR1, 5);
78
79         printf(FS "(+" PRINTF_FORMAT ")",
80                readl(dx_base + PHY_DX_LCDLR1) & 0xff);
81 }
82
83 static void wbdl_dump(unsigned long *base)
84 {
85         printf("\n--- Write Bit Delay Line ---\n");
86         printf("           DQ0  DQ1  DQ2  DQ3  DQ4  DQ5  DQ6  DQ7   DM  DQS  (WDQD)\n");
87
88         dump_loop(base, &__wbdl_dump);
89 }
90
91 static void __rbdl_dump(void __iomem *dx_base)
92 {
93         print_bdl(dx_base + PHY_DX_BDLR3, 5);
94         print_bdl(dx_base + PHY_DX_BDLR4, 4);
95
96         printf(FS "(+" PRINTF_FORMAT ")",
97                (readl(dx_base + PHY_DX_LCDLR1) >> 8) & 0xff);
98 }
99
100 static void rbdl_dump(unsigned long *base)
101 {
102         printf("\n--- Read Bit Delay Line ---\n");
103         printf("           DQ0  DQ1  DQ2  DQ3  DQ4  DQ5  DQ6  DQ7   DM  (RDQSD)\n");
104
105         dump_loop(base, &__rbdl_dump);
106 }
107
108 static void __wld_dump(void __iomem *dx_base)
109 {
110         int rank;
111         u32 lcdlr0 = readl(dx_base + PHY_DX_LCDLR0);
112         u32 gtr = readl(dx_base + PHY_DX_GTR);
113
114         for (rank = 0; rank < 4; rank++) {
115                 u32 wld = (lcdlr0 >> (8 * rank)) & 0xff; /* Delay */
116                 u32 wlsl = (gtr >> (12 + 2 * rank)) & 0x3; /* System Latency */
117
118                 printf(FS PRINTF_FORMAT "%sT", wld,
119                        wlsl == 0 ? "-1" : wlsl == 1 ? "+0" : "+1");
120         }
121 }
122
123 static void wld_dump(unsigned long *base)
124 {
125         printf("\n--- Write Leveling Delay ---\n");
126         printf("            Rank0   Rank1   Rank2   Rank3\n");
127
128         dump_loop(base, &__wld_dump);
129 }
130
131 static void __dqsgd_dump(void __iomem *dx_base)
132 {
133         int rank;
134         u32 lcdlr2 = readl(dx_base + PHY_DX_LCDLR2);
135         u32 gtr = readl(dx_base + PHY_DX_GTR);
136
137         for (rank = 0; rank < 4; rank++) {
138                 u32 dqsgd = (lcdlr2 >> (8 * rank)) & 0xff; /* Delay */
139                 u32 dgsl = (gtr >> (3 * rank)) & 0x7; /* System Latency */
140
141                 printf(FS PRINTF_FORMAT "+%dT", dqsgd, dgsl);
142         }
143 }
144
145 static void dqsgd_dump(unsigned long *base)
146 {
147         printf("\n--- DQS Gating Delay ---\n");
148         printf("            Rank0   Rank1   Rank2   Rank3\n");
149
150         dump_loop(base, &__dqsgd_dump);
151 }
152
153 static void __mdl_dump(void __iomem *dx_base)
154 {
155         int i;
156         u32 mdl = readl(dx_base + PHY_DX_MDLR);
157         for (i = 0; i < 3; i++)
158                 printf(FS PRINTF_FORMAT, (mdl >> (8 * i)) & 0xff);
159 }
160
161 static void mdl_dump(unsigned long *base)
162 {
163         printf("\n--- Master Delay Line ---\n");
164         printf("          IPRD TPRD MDLD\n");
165
166         dump_loop(base, &__mdl_dump);
167 }
168
169 #define REG_DUMP(x)                                                     \
170         { int ofst = PHY_ ## x; void __iomem *reg = phy_base + ofst;    \
171                 printf("%3d: %-10s: %p : %08x\n",                       \
172                        ofst >> PHY_REG_SHIFT, #x, reg, readl(reg)); }
173
174 #define DX_REG_DUMP(dx, x)                                              \
175         { int ofst = PHY_DX_BASE + PHY_DX_STRIDE * (dx) +               \
176                         PHY_DX_## x;                                    \
177                 void __iomem *reg = phy_base + ofst;                    \
178                 printf("%3d: DX%d%-7s: %p : %08x\n",                    \
179                        ofst >> PHY_REG_SHIFT, (dx), #x, reg, readl(reg)); }
180
181 static void reg_dump(unsigned long *base)
182 {
183         void __iomem *phy_base;
184         int p, dx;
185
186         printf("\n--- DDR PHY registers ---\n");
187
188         for (p = 0; *base; base++, p++) {
189                 phy_base = ioremap(*base, SZ_4K);
190
191                 printf("== PHY%d (base: %p) ==\n", p, phy_base);
192                 printf(" No: Name      : Address  : Data\n");
193
194                 REG_DUMP(RIDR);
195                 REG_DUMP(PIR);
196                 REG_DUMP(PGCR0);
197                 REG_DUMP(PGCR1);
198                 REG_DUMP(PGSR0);
199                 REG_DUMP(PGSR1);
200                 REG_DUMP(PLLCR);
201                 REG_DUMP(PTR0);
202                 REG_DUMP(PTR1);
203                 REG_DUMP(PTR2);
204                 REG_DUMP(PTR3);
205                 REG_DUMP(PTR4);
206                 REG_DUMP(ACMDLR);
207                 REG_DUMP(ACBDLR);
208                 REG_DUMP(DXCCR);
209                 REG_DUMP(DSGCR);
210                 REG_DUMP(DCR);
211                 REG_DUMP(DTPR0);
212                 REG_DUMP(DTPR1);
213                 REG_DUMP(DTPR2);
214                 REG_DUMP(MR0);
215                 REG_DUMP(MR1);
216                 REG_DUMP(MR2);
217                 REG_DUMP(MR3);
218
219                 for (dx = 0; dx < NR_DATX8_PER_DDRPHY; dx++) {
220                         DX_REG_DUMP(dx, GCR);
221                         DX_REG_DUMP(dx, GTR);
222                 }
223
224                 iounmap(phy_base);
225         }
226 }
227
228 static int do_ddr(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
229 {
230         char *cmd = argv[1];
231         unsigned long *base;
232
233         switch (uniphier_get_soc_type()) {
234         case SOC_UNIPHIER_LD4:
235                 base = uniphier_ld4_base;
236                 break;
237         case SOC_UNIPHIER_PRO4:
238                 base = uniphier_pro4_base;
239                 break;
240         case SOC_UNIPHIER_SLD8:
241                 base = uniphier_sld8_base;
242                 break;
243         default:
244                 printf("unsupported SoC\n");
245                 return CMD_RET_FAILURE;
246         }
247
248         if (argc == 1)
249                 cmd = "all";
250
251         if (!strcmp(cmd, "wbdl") || !strcmp(cmd, "all"))
252                 wbdl_dump(base);
253
254         if (!strcmp(cmd, "rbdl") || !strcmp(cmd, "all"))
255                 rbdl_dump(base);
256
257         if (!strcmp(cmd, "wld") || !strcmp(cmd, "all"))
258                 wld_dump(base);
259
260         if (!strcmp(cmd, "dqsgd") || !strcmp(cmd, "all"))
261                 dqsgd_dump(base);
262
263         if (!strcmp(cmd, "mdl") || !strcmp(cmd, "all"))
264                 mdl_dump(base);
265
266         if (!strcmp(cmd, "reg") || !strcmp(cmd, "all"))
267                 reg_dump(base);
268
269         return CMD_RET_SUCCESS;
270 }
271
272 U_BOOT_CMD(
273         ddr,    2,      1,      do_ddr,
274         "UniPhier DDR PHY parameters dumper",
275         "- dump all of the following\n"
276         "ddr wbdl - dump Write Bit Delay\n"
277         "ddr rbdl - dump Read Bit Delay\n"
278         "ddr wld - dump Write Leveling\n"
279         "ddr dqsgd - dump DQS Gating Delay\n"
280         "ddr mdl - dump Master Delay Line\n"
281         "ddr reg - dump registers\n"
282 );