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