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_ch2_width ? 3 : 2; 32 } 33 34 static int get_nr_datx8(int ch) 35 { 36 unsigned int width; 37 38 const struct uniphier_board_data *bd = uniphier_get_board_param(); 39 40 switch (ch) { 41 case 0: 42 width = bd->dram_ch0_width; 43 break; 44 case 1: 45 width = bd->dram_ch1_width; 46 break; 47 default: 48 width = bd->dram_ch2_width; 49 break; 50 } 51 52 return width / 8; 53 } 54 55 static void print_bdl(void __iomem *reg, int n) 56 { 57 u32 val = readl(reg); 58 int i; 59 60 for (i = 0; i < n; i++) 61 printf(FS PRINTF_FORMAT, (val >> i * 8) & 0x1f); 62 } 63 64 static void dump_loop(void (*callback)(void __iomem *)) 65 { 66 int ch, dx, nr_ch, nr_dx; 67 void __iomem *dx_base; 68 69 nr_ch = get_nr_ch(); 70 71 for (ch = 0; ch < nr_ch; ch++) { 72 dx_base = get_phy_base(ch) + DMPHY_DX_BASE; 73 nr_dx = get_nr_datx8(ch); 74 75 for (dx = 0; dx < nr_dx; dx++) { 76 printf("CH%dDX%d:", ch, dx); 77 (*callback)(dx_base); 78 dx_base += DMPHY_DX_STRIDE; 79 printf("\n"); 80 } 81 } 82 } 83 84 static void zq_dump(void) 85 { 86 int ch, zq, nr_ch, nr_zq, i; 87 void __iomem *zq_base; 88 u32 dr, pr; 89 90 printf("\n--- Impedance Data ---\n"); 91 printf(" ZPD ZPU OPD OPU ZDV ODV\n"); 92 93 nr_ch = get_nr_ch(); 94 95 for (ch = 0; ch < nr_ch; ch++) { 96 zq_base = get_phy_base(ch) + DMPHY_ZQ_BASE; 97 nr_zq = 3; 98 99 for (zq = 0; zq < nr_zq; zq++) { 100 printf("CH%dZQ%d:", ch, zq); 101 102 dr = readl(zq_base + DMPHY_ZQ_DR); 103 for (i = 0; i < 4; i++) { 104 printf(FS PRINTF_FORMAT, dr & 0x7f); 105 dr >>= 7; 106 } 107 108 pr = readl(zq_base + DMPHY_ZQ_PR); 109 for (i = 0; i < 2; i++) { 110 printf(FS PRINTF_FORMAT, pr & 0xf); 111 pr >>= 4; 112 } 113 114 zq_base += DMPHY_ZQ_STRIDE; 115 printf("\n"); 116 } 117 } 118 } 119 120 static void __wbdl_dump(void __iomem *dx_base) 121 { 122 print_bdl(dx_base + DMPHY_DX_BDLR0, 4); 123 print_bdl(dx_base + DMPHY_DX_BDLR1, 4); 124 print_bdl(dx_base + DMPHY_DX_BDLR2, 2); 125 126 printf(FS "(+" PRINTF_FORMAT ")", 127 readl(dx_base + DMPHY_DX_LCDLR1) & 0xff); 128 } 129 130 static void wbdl_dump(void) 131 { 132 printf("\n--- Write Bit Delay Line ---\n"); 133 printf(" DQ0 DQ1 DQ2 DQ3 DQ4 DQ5 DQ6 DQ7 DM DQS (WDQD)\n"); 134 135 dump_loop(&__wbdl_dump); 136 } 137 138 static void __rbdl_dump(void __iomem *dx_base) 139 { 140 print_bdl(dx_base + DMPHY_DX_BDLR3, 4); 141 print_bdl(dx_base + DMPHY_DX_BDLR4, 4); 142 print_bdl(dx_base + DMPHY_DX_BDLR5, 1); 143 144 printf(FS "(+" PRINTF_FORMAT ")", 145 (readl(dx_base + DMPHY_DX_LCDLR1) >> 8) & 0xff); 146 147 printf(FS "(+" PRINTF_FORMAT ")", 148 (readl(dx_base + DMPHY_DX_LCDLR1) >> 16) & 0xff); 149 } 150 151 static void rbdl_dump(void) 152 { 153 printf("\n--- Read Bit Delay Line ---\n"); 154 printf(" DQ0 DQ1 DQ2 DQ3 DQ4 DQ5 DQ6 DQ7 DM (RDQSD) (RDQSND)\n"); 155 156 dump_loop(&__rbdl_dump); 157 } 158 159 static void __wld_dump(void __iomem *dx_base) 160 { 161 int rank; 162 u32 lcdlr0 = readl(dx_base + DMPHY_DX_LCDLR0); 163 u32 gtr = readl(dx_base + DMPHY_DX_GTR); 164 165 for (rank = 0; rank < 4; rank++) { 166 u32 wld = (lcdlr0 >> (8 * rank)) & 0xff; /* Delay */ 167 u32 wlsl = (gtr >> (12 + 2 * rank)) & 0x3; /* System Latency */ 168 169 printf(FS PRINTF_FORMAT "%sT", wld, 170 wlsl == 0 ? "-1" : wlsl == 1 ? "+0" : "+1"); 171 } 172 } 173 174 static void wld_dump(void) 175 { 176 printf("\n--- Write Leveling Delay ---\n"); 177 printf(" Rank0 Rank1 Rank2 Rank3\n"); 178 179 dump_loop(&__wld_dump); 180 } 181 182 static void __dqsgd_dump(void __iomem *dx_base) 183 { 184 int rank; 185 u32 lcdlr2 = readl(dx_base + DMPHY_DX_LCDLR2); 186 u32 gtr = readl(dx_base + DMPHY_DX_GTR); 187 188 for (rank = 0; rank < 4; rank++) { 189 u32 dqsgd = (lcdlr2 >> (8 * rank)) & 0xff; /* Delay */ 190 u32 dgsl = (gtr >> (3 * rank)) & 0x7; /* System Latency */ 191 192 printf(FS PRINTF_FORMAT "+%dT", dqsgd, dgsl); 193 } 194 } 195 196 static void dqsgd_dump(void) 197 { 198 printf("\n--- DQS Gating Delay ---\n"); 199 printf(" Rank0 Rank1 Rank2 Rank3\n"); 200 201 dump_loop(&__dqsgd_dump); 202 } 203 204 static void __mdl_dump(void __iomem *dx_base) 205 { 206 int i; 207 u32 mdl = readl(dx_base + DMPHY_DX_MDLR); 208 209 for (i = 0; i < 3; i++) 210 printf(FS PRINTF_FORMAT, (mdl >> (8 * i)) & 0xff); 211 } 212 213 static void mdl_dump(void) 214 { 215 printf("\n--- Master Delay Line ---\n"); 216 printf(" IPRD TPRD MDLD\n"); 217 218 dump_loop(&__mdl_dump); 219 } 220 221 #define REG_DUMP(x) \ 222 { int ofst = DMPHY_ ## x; void __iomem *reg = phy_base + ofst; \ 223 printf("%3d: %-10s: %p : %08x\n", \ 224 ofst >> DMPHY_SHIFT, #x, reg, readl(reg)); } 225 226 #define DX_REG_DUMP(dx, x) \ 227 { int ofst = DMPHY_DX_BASE + DMPHY_DX_STRIDE * (dx) + \ 228 DMPHY_DX_## x; \ 229 void __iomem *reg = phy_base + ofst; \ 230 printf("%3d: DX%d%-7s: %p : %08x\n", \ 231 ofst >> DMPHY_SHIFT, (dx), #x, reg, readl(reg)); } 232 233 static void reg_dump(void) 234 { 235 int ch, dx, nr_ch, nr_dx; 236 void __iomem *phy_base; 237 238 printf("\n--- DDR PHY registers ---\n"); 239 240 nr_ch = get_nr_ch(); 241 242 for (ch = 0; ch < nr_ch; ch++) { 243 phy_base = get_phy_base(ch); 244 nr_dx = get_nr_datx8(ch); 245 246 printf("== Ch%d ==\n", ch); 247 printf(" No: Name : Address : Data\n"); 248 249 REG_DUMP(RIDR); 250 REG_DUMP(PIR); 251 REG_DUMP(PGCR0); 252 REG_DUMP(PGCR1); 253 REG_DUMP(PGCR2); 254 REG_DUMP(PGCR3); 255 REG_DUMP(PGSR0); 256 REG_DUMP(PGSR1); 257 REG_DUMP(PLLCR); 258 REG_DUMP(PTR0); 259 REG_DUMP(PTR1); 260 REG_DUMP(PTR2); 261 REG_DUMP(PTR3); 262 REG_DUMP(PTR4); 263 REG_DUMP(ACMDLR); 264 REG_DUMP(ACBDLR0); 265 REG_DUMP(DXCCR); 266 REG_DUMP(DSGCR); 267 REG_DUMP(DCR); 268 REG_DUMP(DTPR0); 269 REG_DUMP(DTPR1); 270 REG_DUMP(DTPR2); 271 REG_DUMP(DTPR3); 272 REG_DUMP(MR0); 273 REG_DUMP(MR1); 274 REG_DUMP(MR2); 275 REG_DUMP(MR3); 276 277 for (dx = 0; dx < nr_dx; dx++) { 278 DX_REG_DUMP(dx, GCR0); 279 DX_REG_DUMP(dx, GCR1); 280 DX_REG_DUMP(dx, GCR2); 281 DX_REG_DUMP(dx, GCR3); 282 DX_REG_DUMP(dx, GTR); 283 } 284 } 285 } 286 287 static int do_ddrm(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) 288 { 289 char *cmd = argv[1]; 290 291 if (argc == 1) 292 cmd = "all"; 293 294 if (!strcmp(cmd, "zq") || !strcmp(cmd, "all")) 295 zq_dump(); 296 297 if (!strcmp(cmd, "wbdl") || !strcmp(cmd, "all")) 298 wbdl_dump(); 299 300 if (!strcmp(cmd, "rbdl") || !strcmp(cmd, "all")) 301 rbdl_dump(); 302 303 if (!strcmp(cmd, "wld") || !strcmp(cmd, "all")) 304 wld_dump(); 305 306 if (!strcmp(cmd, "dqsgd") || !strcmp(cmd, "all")) 307 dqsgd_dump(); 308 309 if (!strcmp(cmd, "mdl") || !strcmp(cmd, "all")) 310 mdl_dump(); 311 312 if (!strcmp(cmd, "reg") || !strcmp(cmd, "all")) 313 reg_dump(); 314 315 return 0; 316 } 317 318 U_BOOT_CMD( 319 ddrm, 2, 1, do_ddrm, 320 "UniPhier DDR PHY parameters dumper", 321 "- dump all of the followings\n" 322 "ddrm zq - dump Impedance Data\n" 323 "ddrm wbdl - dump Write Bit Delay\n" 324 "ddrm rbdl - dump Read Bit Delay\n" 325 "ddrm wld - dump Write Leveling\n" 326 "ddrm dqsgd - dump DQS Gating Delay\n" 327 "ddrm mdl - dump Master Delay Line\n" 328 "ddrm reg - dump registers\n" 329 ); 330