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 ); 316