2 * Copyright (C) 2015 Masahiro Yamada <yamada.masahiro@socionext.com>
4 * SPDX-License-Identifier: GPL-2.0+
11 #include "ddrmphy-regs.h"
13 /* Select either decimal or hexadecimal */
15 #define PRINTF_FORMAT "%2d"
17 #define PRINTF_FORMAT "%02x"
22 static void __iomem *get_phy_base(int ch)
24 return (void __iomem *)(0x5b830000 + ch * 0x00200000);
27 static int get_nr_ch(void)
29 const struct uniphier_board_data *bd = uniphier_get_board_param();
31 return bd->dram_ch[2].size ? 3 : 2;
34 static int get_nr_datx8(int ch)
36 const struct uniphier_board_data *bd = uniphier_get_board_param();
38 return bd->dram_ch[ch].width / 8;
41 static void print_bdl(void __iomem *reg, int n)
46 for (i = 0; i < n; i++)
47 printf(FS PRINTF_FORMAT, (val >> i * 8) & 0x1f);
50 static void dump_loop(void (*callback)(void __iomem *))
52 int ch, dx, nr_ch, nr_dx;
53 void __iomem *dx_base;
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);
61 for (dx = 0; dx < nr_dx; dx++) {
62 printf("CH%dDX%d:", ch, dx);
64 dx_base += DMPHY_DX_STRIDE;
70 static void zq_dump(void)
72 int ch, zq, nr_ch, nr_zq, i;
73 void __iomem *zq_base;
76 printf("\n--- Impedance Data ---\n");
77 printf(" ZPD ZPU OPD OPU ZDV ODV\n");
81 for (ch = 0; ch < nr_ch; ch++) {
82 zq_base = get_phy_base(ch) + DMPHY_ZQ_BASE;
85 for (zq = 0; zq < nr_zq; zq++) {
86 printf("CH%dZQ%d:", ch, zq);
88 dr = readl(zq_base + DMPHY_ZQ_DR);
89 for (i = 0; i < 4; i++) {
90 printf(FS PRINTF_FORMAT, dr & 0x7f);
94 pr = readl(zq_base + DMPHY_ZQ_PR);
95 for (i = 0; i < 2; i++) {
96 printf(FS PRINTF_FORMAT, pr & 0xf);
100 zq_base += DMPHY_ZQ_STRIDE;
106 static void __wbdl_dump(void __iomem *dx_base)
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);
112 printf(FS "(+" PRINTF_FORMAT ")",
113 readl(dx_base + DMPHY_DX_LCDLR1) & 0xff);
116 static void wbdl_dump(void)
118 printf("\n--- Write Bit Delay Line ---\n");
119 printf(" DQ0 DQ1 DQ2 DQ3 DQ4 DQ5 DQ6 DQ7 DM DQS (WDQD)\n");
121 dump_loop(&__wbdl_dump);
124 static void __rbdl_dump(void __iomem *dx_base)
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);
130 printf(FS "(+" PRINTF_FORMAT ")",
131 (readl(dx_base + DMPHY_DX_LCDLR1) >> 8) & 0xff);
133 printf(FS "(+" PRINTF_FORMAT ")",
134 (readl(dx_base + DMPHY_DX_LCDLR1) >> 16) & 0xff);
137 static void rbdl_dump(void)
139 printf("\n--- Read Bit Delay Line ---\n");
140 printf(" DQ0 DQ1 DQ2 DQ3 DQ4 DQ5 DQ6 DQ7 DM (RDQSD) (RDQSND)\n");
142 dump_loop(&__rbdl_dump);
145 static void __wld_dump(void __iomem *dx_base)
148 u32 lcdlr0 = readl(dx_base + DMPHY_DX_LCDLR0);
149 u32 gtr = readl(dx_base + DMPHY_DX_GTR);
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 */
155 printf(FS PRINTF_FORMAT "%sT", wld,
156 wlsl == 0 ? "-1" : wlsl == 1 ? "+0" : "+1");
160 static void wld_dump(void)
162 printf("\n--- Write Leveling Delay ---\n");
163 printf(" Rank0 Rank1 Rank2 Rank3\n");
165 dump_loop(&__wld_dump);
168 static void __dqsgd_dump(void __iomem *dx_base)
171 u32 lcdlr2 = readl(dx_base + DMPHY_DX_LCDLR2);
172 u32 gtr = readl(dx_base + DMPHY_DX_GTR);
174 for (rank = 0; rank < 4; rank++) {
175 u32 dqsgd = (lcdlr2 >> (8 * rank)) & 0xff; /* Delay */
176 u32 dgsl = (gtr >> (3 * rank)) & 0x7; /* System Latency */
178 printf(FS PRINTF_FORMAT "+%dT", dqsgd, dgsl);
182 static void dqsgd_dump(void)
184 printf("\n--- DQS Gating Delay ---\n");
185 printf(" Rank0 Rank1 Rank2 Rank3\n");
187 dump_loop(&__dqsgd_dump);
190 static void __mdl_dump(void __iomem *dx_base)
193 u32 mdl = readl(dx_base + DMPHY_DX_MDLR);
195 for (i = 0; i < 3; i++)
196 printf(FS PRINTF_FORMAT, (mdl >> (8 * i)) & 0xff);
199 static void mdl_dump(void)
201 printf("\n--- Master Delay Line ---\n");
202 printf(" IPRD TPRD MDLD\n");
204 dump_loop(&__mdl_dump);
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)); }
212 #define DX_REG_DUMP(dx, x) \
213 { int ofst = DMPHY_DX_BASE + DMPHY_DX_STRIDE * (dx) + \
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)); }
219 static void reg_dump(void)
221 int ch, dx, nr_ch, nr_dx;
222 void __iomem *phy_base;
224 printf("\n--- DDR PHY registers ---\n");
228 for (ch = 0; ch < nr_ch; ch++) {
229 phy_base = get_phy_base(ch);
230 nr_dx = get_nr_datx8(ch);
232 printf("== Ch%d ==\n", ch);
233 printf(" No: Name : Address : Data\n");
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);
273 static int do_ddrm(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
280 if (!strcmp(cmd, "zq") || !strcmp(cmd, "all"))
283 if (!strcmp(cmd, "wbdl") || !strcmp(cmd, "all"))
286 if (!strcmp(cmd, "rbdl") || !strcmp(cmd, "all"))
289 if (!strcmp(cmd, "wld") || !strcmp(cmd, "all"))
292 if (!strcmp(cmd, "dqsgd") || !strcmp(cmd, "all"))
295 if (!strcmp(cmd, "mdl") || !strcmp(cmd, "all"))
298 if (!strcmp(cmd, "reg") || !strcmp(cmd, "all"))
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"