xref: /openbmc/u-boot/cmd/aspeed/plltest.c (revision 02294997)
1 /*
2  *  This program is distributed in the hope that it will be useful,
3  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
4  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
5  *  GNU General Public License for more details.
6  *
7  *  You should have received a copy of the GNU General Public License
8  *  along with this program; if not, write to the Free Software
9  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
10  */
11 
12 #include <common.h>
13 #include <console.h>
14 #include <bootretry.h>
15 #include <cli.h>
16 #include <command.h>
17 #include <console.h>
18 
19 #include <inttypes.h>
20 #include <mapmem.h>
21 #include <asm/io.h>
22 #include <linux/compiler.h>
23 
24 #include <common.h>
25 #include <clk-uclass.h>
26 #include <dm.h>
27 #include <asm/io.h>
28 #include <dm/lists.h>
29 #include <asm/arch/scu_ast2600.h>
30 #include <dt-bindings/clock/ast2600-clock.h>
31 
32 #include <asm/arch/scu_ast2600.h>
33 #include <dt-bindings/clock/ast2600-clock.h>
34 
35 DECLARE_GLOBAL_DATA_PTR;
36 
37 /* ------------------------------------------------------------------------- */
get_ast2600_pll_rate(struct udevice * scu_dev,unsigned int pll_idx)38 unsigned long get_ast2600_pll_rate(struct udevice *scu_dev, unsigned int pll_idx)
39 {
40 	struct clk clk;
41 	unsigned long ret = 0;
42 
43 	clk.id = pll_idx;
44 	ret = clk_request(scu_dev, &clk);
45 	if (ret < 0) {
46 		return ret;
47 	}
48 
49 	ret = clk_get_rate(&clk);
50 
51 	clk_free(&clk);
52 
53 	return ret;
54 }
55 
cal_ast2600_28nm_pll_rate(unsigned long pll_rate,unsigned int pll_idx)56 static int cal_ast2600_28nm_pll_rate(unsigned long pll_rate, unsigned int pll_idx)
57 {
58 	u32 ulCounter, ulLowLimit, ulHighLimit;
59     u32 ulData;
60 	u32 ulErrRate = 2;
61 	int i = 0;
62 
63 //	printf("pll rate : %ld \n", pll_rate);
64 
65 	ulCounter = (pll_rate/1000) * 512 / 25000 - 1;
66     ulLowLimit = ulCounter * (100 - ulErrRate) / 100;
67     ulHighLimit = ulCounter * (100 + ulErrRate) / 100;
68 	writel((ulLowLimit << 16) | ulHighLimit, 0x1e6e2324);
69 //	printf("ulCounter %lx , ulLowLimit %lx , ulHighLimit  %lx \n", ulCounter, ulLowLimit, ulHighLimit);
70 
71 	//1. Set SCU320 = 0x24 use hclk reset freq measurement counter
72 	writel(0x24, 0x1e6e2320);
73 	//2. Wait until SCU320[29:16] = 0
74     do {
75         ulData = readl(0x1e6e2320);
76         mdelay(1);
77     } while ((ulData & 0x3fff0000) && (i++<1000));	 //wait until SCU320[29:16]=0
78 
79     if (i>= 1000)
80     {
81         printf("Fre Count Eng No idle %x\n", ulData);
82         return 1;
83     }
84 	//3. Set SCU320[0] = 1 and SCU320[5:2] = clock for measurement
85 	writel((pll_idx << 2) | 0x1, 0x1e6e2320);
86 	//4. Delay 1ms
87 	mdelay(1);
88 	//5. Set SCU320[1] = 1
89 	writel((pll_idx << 2) | 0x3, 0x1e6e2320);
90 
91 	//6. Wait until SCU320[6] = 1
92     i = 0;
93     do {
94         ulData = readl(0x1e6e2320);
95         mdelay(1);
96     } while ((!(ulData & 0x40)) && (i++<1000));
97 
98     if (i>= 1000)
99     {
100         printf("PLL Detec No idle %x\n", ulData);
101         return 1;
102     }
103 
104 	//7. Read SCU320[29:16] and calculate the result frequency using following equation
105 //	printf("ulCounter val : %lx \n", (readl(0x1e6e2320) & GENMASK(29, 16)) >> 16);
106 	//When the reference clock CLK25M count from 0 to 512, measure the OSCCLK counting value, then
107 	//OSCCLK frequency = CLK25M / 512 * (SCU320[29:16] + 1)
108 //	printf("rate %ld \n", (25000000 / 512) * (((readl(0x1e6e2320) & GENMASK(29, 16)) >> 16) + 1));
109 
110 	ulData = readl(0x1e6e2320);
111 
112 	writel(0x2C, 0x1e6e2320); //disable ring
113 
114 	if(ulData & 0x80)
115 		return 0;
116 	else
117 		return 1;
118 }
119 
cal_ast2600_13nm_pll_rate(unsigned long pll_rate,unsigned int pll_idx)120 static int cal_ast2600_13nm_pll_rate(unsigned long pll_rate, unsigned int pll_idx)
121 {
122     u32 ulData;
123 	u32 ulCounter, ulLowLimit, ulHighLimit;
124 	u32 ulErrRate = 2;
125 	int i = 0;
126 
127 //	printf("pll rate : %ld \n", pll_rate);
128 
129 	ulCounter = (pll_rate/1000) * 512 / 25000 - 1;
130     ulLowLimit = ulCounter * (100 - ulErrRate) / 100;
131     ulHighLimit = ulCounter * (100 + ulErrRate) / 100;
132 	writel((ulHighLimit << 16) | ulLowLimit, 0x1e6e2334);
133 //	printf("ulCounter %lx , ulLowLimit %lx , ulHighLimit  %lx \n", ulCounter, ulLowLimit, ulHighLimit);
134 
135 	//1. Set SCU320 = 0x30
136 	writel(0x30, 0x1e6e2330);
137 	//2. Wait until SCU320[29:16] = 0
138     do {
139         ulData = readl(0x1e6e2330);
140         mdelay(1);
141     } while ((ulData & 0x3fff0000) && (i++<1000));	 //wait until SCU320[29:16]=0
142 
143     if (i>= 1000)
144     {
145         printf("Fre Count Eng No idle %x\n", ulData);
146         return 1;
147     }
148 	//3. Set SCU320[0] = 1 and SCU320[5:2] = clock for measurement
149 	writel((pll_idx << 2) | 0x1, 0x1e6e2330);
150 	//4. Delay 1ms
151 	mdelay(1);
152 	//5. Set SCU320[1] = 1
153 	writel((pll_idx << 2) | 0x3, 0x1e6e2330);
154 
155 	//6. Wait until SCU320[6] = 1
156     i = 0;
157     do {
158         ulData = readl(0x1e6e2330);
159         mdelay(1);
160     } while ((!(ulData & 0x40)) && (i++<1000));
161 
162     if (i>= 1000)
163     {
164         printf("PLL Detec No idle %x\n", ulData);
165         return 1;
166     }
167 
168 	//7. Read SCU320[29:16] and calculate the result frequency using following equation
169 //	printf("ulCounter val : %lx \n", (readl(0x1e6e2330) & GENMASK(29, 16)) >> 16);
170 	//When the reference clock CLK25M count from 0 to 512, measure the OSCCLK counting value, then
171 	//OSCCLK frequency = CLK25M / 512 * (SCU320[29:16] + 1)
172 //	printf("rate %ld \n", (25000000 / 512) * (((readl(0x1e6e2330) & GENMASK(29, 16)) >> 16) + 1));
173 
174 	ulData = readl(0x1e6e2330);
175 
176     writel(0x2C, 0x1e6e2330); //disable ring
177 
178 	if(ulData & 0x80)
179 		return 0;
180 	else
181 		return 1;
182 }
183 
184 
do_ast2600_pll_test(struct udevice * scu_dev,unsigned int pll_idx)185 int do_ast2600_pll_test(struct udevice *scu_dev, unsigned int pll_idx)
186 {
187 	int ret = 0;
188 	unsigned long pll_rate = 0;
189 
190 	switch(pll_idx) {
191 		case 0:	//delay cell
192 			printf("Delay Cell : BYPASS \n");
193 			break;
194 		case 1: //nand gate
195 			printf("NAND Gate : BYPASS \n");
196 			break;
197 		case 2:
198 			printf("DLY 16 : BYPASS \n");
199 			break;
200 		case 3:
201 			printf("DLY 32 : BYPASS \n");
202 			break;
203 		case 4:
204 			pll_rate = get_ast2600_pll_rate(scu_dev, ASPEED_CLK_DPLL);
205 			if(cal_ast2600_28nm_pll_rate(pll_rate/2, 4)) {
206 				printf("D-PLL : Fail \n");
207 				ret = 1;
208 			} else
209 				printf("D-PLL : PASS \n");
210 			break;
211 		case 5:
212 			pll_rate = get_ast2600_pll_rate(scu_dev, ASPEED_CLK_EPLL);
213 			if(cal_ast2600_28nm_pll_rate(pll_rate/4, 5))
214 				printf("E-PLL : Fail \n");
215 			else
216 				printf("E-PLL : PASS \n");
217 			break;
218 		case 6:
219 			if(readl(0x1e6ed0c0) & BIT(5)) {
220 				switch((readl(0x1e6ed0d0) >> 16) & 0x3) {
221 					case 1: //2.5G 125Mhz
222 						pll_rate = 125000000;
223 						break;
224 					case 2:
225 						pll_rate = 250000000;
226 						break;
227 				}
228 				if(cal_ast2600_28nm_pll_rate(pll_rate, 6))
229 					printf("XPCLK-EP : Fail \n");
230 				else
231 					printf("XPCLK-EP : PASS \n");
232 			} else
233 				printf("XPCLK-EP : Fail 0 \n");
234 			break;
235 		case 8:
236 			pll_rate = get_ast2600_pll_rate(scu_dev, ASPEED_CLK_MPLL);
237 			if(cal_ast2600_28nm_pll_rate(pll_rate/2, 8)) {
238 				printf("MCLK : Fail \n");
239 				ret = 1;
240 			} else
241 				printf("MCLK : PASS \n");
242 			break;
243 		case 9:
244 			pll_rate = get_ast2600_pll_rate(scu_dev, ASPEED_CLK_AHB);
245 			if(cal_ast2600_28nm_pll_rate(pll_rate, 9)) {
246 				printf("HCLK-28nm : Fail \n");
247 				ret = 1;
248 			} else
249 				printf("HCLK-28nm : PASS \n");
250 			break;
251 		case 16:
252 			pll_rate = get_ast2600_pll_rate(scu_dev, ASPEED_CLK_APLL);
253 			if(cal_ast2600_13nm_pll_rate(pll_rate/8, 0)) {
254 				printf("APLL : Fail \n");
255 				ret = 1;
256 			} else
257 				printf("APLL : PASS \n");
258 			break;
259 		case 17:
260 			pll_rate = get_ast2600_pll_rate(scu_dev, ASPEED_CLK_AHB);
261 			if(cal_ast2600_13nm_pll_rate(pll_rate, 1)) {
262 				printf("HCLK-13nm : Fail \n");
263 				ret = 1;
264 			} else
265 				printf("HCLK-13nm : PASS \n");
266 			break;
267 		case 18:
268 			pll_rate = get_ast2600_pll_rate(scu_dev, ASPEED_CLK_APB2);
269 			if(cal_ast2600_13nm_pll_rate(pll_rate, 2))
270 				printf("PCLK : Fail \n");
271 			else
272 				printf("PCLK : PASS \n");
273 			break;
274 	}
275 
276 	return ret;
277 }
278 
do_aspeed_full_pll_test(struct udevice * scu_dev)279 int do_aspeed_full_pll_test(struct udevice *scu_dev)
280 {
281 	int i = 0;
282 	int ret = 0;
283 	for(i = 0; i < 32; i++) {
284 		ret += do_ast2600_pll_test(scu_dev, i);
285 	}
286 
287 	printf("**************************************************** \n");
288 	if(ret)
289 		printf("PLL Test : Fail \n");
290 	else
291 		printf("PLL Test : Pass \n");
292 	printf("**************************************************** \n");
293 
294 	return 1;
295 }
296 
297 static int
do_aspeed_plltest(cmd_tbl_t * cmdtp,int flag,int argc,char * const argv[])298 do_aspeed_plltest(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
299 {
300 	struct udevice *scu_dev;
301 	char *pll_cmd;
302 	unsigned long pll_idx;
303 	int ret;
304 
305 	ret = uclass_get_device_by_driver(UCLASS_CLK,
306 					  DM_GET_DRIVER(aspeed_scu), &scu_dev);
307 	if (ret)
308 		return ret;
309 
310 	if (argc != 2)
311 		return CMD_RET_USAGE;
312 
313 	pll_cmd = argv[1];
314 
315 	if (!strcmp(pll_cmd, "full"))
316 		ret = do_aspeed_full_pll_test(scu_dev);
317 	else {
318 		pll_idx = strtoul(argv[1], 0, 0);
319 		ret = do_ast2600_pll_test(scu_dev, pll_idx);
320 	}
321 
322 	return ret;
323 }
324 
325 U_BOOT_CMD(
326 	plltest,   3, 0,  do_aspeed_plltest,
327 	"ASPEED PLL test",
328 	"ping d2 - Ping to check if the device at the targeted address can respond\n"
329 	""
330 );
331