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