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