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