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