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