blob: ae4bef1877e909a7982d4b1ac5c92a3651dce2da [file] [log] [blame]
Jon Loeliger126aa702006-05-30 17:47:00 -05001/*
2 * Copyright 2006 Freescale Semiconductor
3 * Jeff Brown
4 * Srikanth Srinivasan (srikanth.srinivasan@freescale.com)
5 *
6 * See file CREDITS for list of people who contributed to this
7 * project.
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License as
11 * published by the Free Software Foundation; either version 2 of
12 * the License, or (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
22 * MA 02111-1307 USA
23 */
24
25#include <common.h>
Jon Loeliger126aa702006-05-30 17:47:00 -050026#include <command.h>
Haiying Wang3d98b852007-01-22 12:37:30 -060027#include <watchdog.h>
Jon Loeliger126aa702006-05-30 17:47:00 -050028#include <asm/cache.h>
Jon Loeliger126aa702006-05-30 17:47:00 -050029
Kim Phillips7608d752007-08-21 17:00:17 -050030#ifdef CONFIG_FSL_PIXIS
31
Jon Loeliger126aa702006-05-30 17:47:00 -050032#include "pixis.h"
33
34
Haiying Wang3d98b852007-01-22 12:37:30 -060035static ulong strfractoint(uchar *strptr);
36
37
38/*
39 * Simple board reset.
40 */
41void pixis_reset(void)
42{
43 out8(PIXIS_BASE + PIXIS_RST, 0);
44}
45
46
Jon Loeliger126aa702006-05-30 17:47:00 -050047/*
48 * Per table 27, page 58 of MPC8641HPCN spec.
49 */
50int set_px_sysclk(ulong sysclk)
51{
52 u8 sysclk_s, sysclk_r, sysclk_v, vclkh, vclkl, sysclk_aux;
53
54 switch (sysclk) {
55 case 33:
56 sysclk_s = 0x04;
57 sysclk_r = 0x04;
58 sysclk_v = 0x07;
59 sysclk_aux = 0x00;
60 break;
61 case 40:
62 sysclk_s = 0x01;
63 sysclk_r = 0x1F;
64 sysclk_v = 0x20;
65 sysclk_aux = 0x01;
66 break;
67 case 50:
68 sysclk_s = 0x01;
69 sysclk_r = 0x1F;
70 sysclk_v = 0x2A;
71 sysclk_aux = 0x02;
72 break;
73 case 66:
74 sysclk_s = 0x01;
75 sysclk_r = 0x04;
76 sysclk_v = 0x04;
77 sysclk_aux = 0x03;
78 break;
79 case 83:
80 sysclk_s = 0x01;
81 sysclk_r = 0x1F;
82 sysclk_v = 0x4B;
83 sysclk_aux = 0x04;
84 break;
85 case 100:
86 sysclk_s = 0x01;
87 sysclk_r = 0x1F;
88 sysclk_v = 0x5C;
89 sysclk_aux = 0x05;
90 break;
91 case 134:
92 sysclk_s = 0x06;
93 sysclk_r = 0x1F;
94 sysclk_v = 0x3B;
95 sysclk_aux = 0x06;
96 break;
97 case 166:
98 sysclk_s = 0x06;
99 sysclk_r = 0x1F;
100 sysclk_v = 0x4B;
101 sysclk_aux = 0x07;
102 break;
103 default:
104 printf("Unsupported SYSCLK frequency.\n");
105 return 0;
106 }
107
Jon Loeliger80e955c2006-08-22 12:25:27 -0500108 vclkh = (sysclk_s << 5) | sysclk_r;
Jon Loeliger126aa702006-05-30 17:47:00 -0500109 vclkl = sysclk_v;
110
111 out8(PIXIS_BASE + PIXIS_VCLKH, vclkh);
112 out8(PIXIS_BASE + PIXIS_VCLKL, vclkl);
113
Jon Loeliger80e955c2006-08-22 12:25:27 -0500114 out8(PIXIS_BASE + PIXIS_AUX, sysclk_aux);
Jon Loeliger126aa702006-05-30 17:47:00 -0500115
116 return 1;
117}
118
119
120int set_px_mpxpll(ulong mpxpll)
121{
122 u8 tmp;
123 u8 val;
124
125 switch (mpxpll) {
126 case 2:
127 case 4:
128 case 6:
129 case 8:
130 case 10:
131 case 12:
132 case 14:
133 case 16:
Jon Loeliger80e955c2006-08-22 12:25:27 -0500134 val = (u8) mpxpll;
Jon Loeliger126aa702006-05-30 17:47:00 -0500135 break;
136 default:
137 printf("Unsupported MPXPLL ratio.\n");
138 return 0;
139 }
140
141 tmp = in8(PIXIS_BASE + PIXIS_VSPEED1);
142 tmp = (tmp & 0xF0) | (val & 0x0F);
143 out8(PIXIS_BASE + PIXIS_VSPEED1, tmp);
144
145 return 1;
146}
147
148
149int set_px_corepll(ulong corepll)
150{
151 u8 tmp;
152 u8 val;
153
154 switch ((int)corepll) {
155 case 20:
156 val = 0x08;
157 break;
158 case 25:
159 val = 0x0C;
160 break;
161 case 30:
162 val = 0x10;
163 break;
164 case 35:
165 val = 0x1C;
166 break;
167 case 40:
168 val = 0x14;
169 break;
170 case 45:
171 val = 0x0E;
172 break;
173 default:
174 printf("Unsupported COREPLL ratio.\n");
175 return 0;
176 }
177
178 tmp = in8(PIXIS_BASE + PIXIS_VSPEED0);
179 tmp = (tmp & 0xE0) | (val & 0x1F);
180 out8(PIXIS_BASE + PIXIS_VSPEED0, tmp);
181
182 return 1;
183}
184
185
186void read_from_px_regs(int set)
187{
188 u8 mask = 0x1C;
189 u8 tmp = in8(PIXIS_BASE + PIXIS_VCFGEN0);
190
191 if (set)
192 tmp = tmp | mask;
193 else
194 tmp = tmp & ~mask;
195 out8(PIXIS_BASE + PIXIS_VCFGEN0, tmp);
196}
197
198
199void read_from_px_regs_altbank(int set)
200{
201 u8 mask = 0x04;
202 u8 tmp = in8(PIXIS_BASE + PIXIS_VCFGEN1);
203
204 if (set)
205 tmp = tmp | mask;
206 else
207 tmp = tmp & ~mask;
208 out8(PIXIS_BASE + PIXIS_VCFGEN1, tmp);
209}
210
211
212void set_altbank(void)
213{
214 u8 tmp;
215
216 tmp = in8(PIXIS_BASE + PIXIS_VBOOT);
217 tmp ^= 0x40;
218
219 out8(PIXIS_BASE + PIXIS_VBOOT, tmp);
220}
221
222
223void set_px_go(void)
224{
225 u8 tmp;
226
227 tmp = in8(PIXIS_BASE + PIXIS_VCTL);
228 tmp = tmp & 0x1E;
229 out8(PIXIS_BASE + PIXIS_VCTL, tmp);
230
231 tmp = in8(PIXIS_BASE + PIXIS_VCTL);
232 tmp = tmp | 0x01;
233 out8(PIXIS_BASE + PIXIS_VCTL, tmp);
234}
235
236
237void set_px_go_with_watchdog(void)
238{
239 u8 tmp;
240
241 tmp = in8(PIXIS_BASE + PIXIS_VCTL);
242 tmp = tmp & 0x1E;
243 out8(PIXIS_BASE + PIXIS_VCTL, tmp);
244
245 tmp = in8(PIXIS_BASE + PIXIS_VCTL);
246 tmp = tmp | 0x09;
247 out8(PIXIS_BASE + PIXIS_VCTL, tmp);
248}
249
250
Haiying Wang3d98b852007-01-22 12:37:30 -0600251int pixis_disable_watchdog_cmd(cmd_tbl_t *cmdtp,
252 int flag, int argc, char *argv[])
Jon Loeliger126aa702006-05-30 17:47:00 -0500253{
254 u8 tmp;
255
256 tmp = in8(PIXIS_BASE + PIXIS_VCTL);
257 tmp = tmp & 0x1E;
258 out8(PIXIS_BASE + PIXIS_VCTL, tmp);
259
260 /* setting VCTL[WDEN] to 0 to disable watch dog */
261 tmp = in8(PIXIS_BASE + PIXIS_VCTL);
Jon Loeliger80e955c2006-08-22 12:25:27 -0500262 tmp &= ~0x08;
Jon Loeliger126aa702006-05-30 17:47:00 -0500263 out8(PIXIS_BASE + PIXIS_VCTL, tmp);
264
265 return 0;
266}
267
Jon Loeliger126aa702006-05-30 17:47:00 -0500268U_BOOT_CMD(
Haiying Wang3d98b852007-01-22 12:37:30 -0600269 diswd, 1, 0, pixis_disable_watchdog_cmd,
Jon Loeliger80e955c2006-08-22 12:25:27 -0500270 "diswd - Disable watchdog timer \n",
271 NULL);
Jon Loeliger126aa702006-05-30 17:47:00 -0500272
273/*
274 * This function takes the non-integral cpu:mpx pll ratio
275 * and converts it to an integer that can be used to assign
276 * FPGA register values.
277 * input: strptr i.e. argv[2]
278 */
279
Haiying Wang3d98b852007-01-22 12:37:30 -0600280static ulong strfractoint(uchar *strptr)
Jon Loeliger126aa702006-05-30 17:47:00 -0500281{
282 int i, j, retval;
283 int mulconst;
284 int intarr_len = 0, decarr_len = 0, no_dec = 0;
285 ulong intval = 0, decval = 0;
286 uchar intarr[3], decarr[3];
287
288 /* Assign the integer part to intarr[]
289 * If there is no decimal point i.e.
290 * if the ratio is an integral value
291 * simply create the intarr.
292 */
293 i = 0;
294 while (strptr[i] != 46) {
295 if (strptr[i] == 0) {
296 no_dec = 1;
297 break;
298 }
299 intarr[i] = strptr[i];
300 i++;
301 }
302
303 /* Assign length of integer part to intarr_len. */
304 intarr_len = i;
305 intarr[i] = '\0';
306
307 if (no_dec) {
308 /* Currently needed only for single digit corepll ratios */
Jon Loeliger80e955c2006-08-22 12:25:27 -0500309 mulconst = 10;
Jon Loeliger126aa702006-05-30 17:47:00 -0500310 decval = 0;
311 } else {
312 j = 0;
Jon Loeliger80e955c2006-08-22 12:25:27 -0500313 i++; /* Skipping the decimal point */
Jon Loeliger126aa702006-05-30 17:47:00 -0500314 while ((strptr[i] > 47) && (strptr[i] < 58)) {
315 decarr[j] = strptr[i];
316 i++;
317 j++;
318 }
319
320 decarr_len = j;
321 decarr[j] = '\0';
322
323 mulconst = 1;
324 for (i = 0; i < decarr_len; i++)
325 mulconst *= 10;
Wolfgang Denkcdd917a2007-08-02 00:48:45 +0200326 decval = simple_strtoul((char *)decarr, NULL, 10);
Jon Loeliger126aa702006-05-30 17:47:00 -0500327 }
328
Wolfgang Denkcdd917a2007-08-02 00:48:45 +0200329 intval = simple_strtoul((char *)intarr, NULL, 10);
Jon Loeliger126aa702006-05-30 17:47:00 -0500330 intval = intval * mulconst;
331
332 retval = intval + decval;
333
334 return retval;
335}
Haiying Wang3d98b852007-01-22 12:37:30 -0600336
337
338int
339pixis_reset_cmd(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
340{
341 ulong val;
342 ulong corepll;
343
344 /*
345 * No args is a simple reset request.
346 */
347 if (argc <= 1) {
348 pixis_reset();
349 /* not reached */
350 }
351
352 if (strcmp(argv[1], "cf") == 0) {
353
354 /*
355 * Reset with frequency changed:
356 * cf <SYSCLK freq> <COREPLL ratio> <MPXPLL ratio>
357 */
358 if (argc < 5) {
359 puts(cmdtp->usage);
360 return 1;
361 }
362
363 read_from_px_regs(0);
364
365 val = set_px_sysclk(simple_strtoul(argv[2], NULL, 10));
366
Wolfgang Denkcdd917a2007-08-02 00:48:45 +0200367 corepll = strfractoint((uchar *)argv[3]);
Haiying Wang3d98b852007-01-22 12:37:30 -0600368 val = val + set_px_corepll(corepll);
369 val = val + set_px_mpxpll(simple_strtoul(argv[4], NULL, 10));
370 if (val == 3) {
371 puts("Setting registers VCFGEN0 and VCTL\n");
372 read_from_px_regs(1);
373 puts("Resetting board with values from ");
374 puts("VSPEED0, VSPEED1, VCLKH, and VCLKL \n");
375 set_px_go();
376 } else {
377 puts(cmdtp->usage);
378 return 1;
379 }
380
381 while (1) ; /* Not reached */
382
383 } else if (strcmp(argv[1], "altbank") == 0) {
384
385 /*
386 * Reset using alternate flash bank:
387 */
388 if (argv[2] == 0) {
389 /*
390 * Reset from alternate bank without changing
391 * frequency and without watchdog timer enabled.
392 * altbank
393 */
394 read_from_px_regs(0);
395 read_from_px_regs_altbank(0);
396 if (argc > 2) {
397 puts(cmdtp->usage);
398 return 1;
399 }
400 puts("Setting registers VCFGNE1, VBOOT, and VCTL\n");
401 set_altbank();
402 read_from_px_regs_altbank(1);
403 puts("Resetting board to boot from the other bank.\n");
404 set_px_go();
405
406 } else if (strcmp(argv[2], "cf") == 0) {
407 /*
408 * Reset with frequency changed
409 * altbank cf <SYSCLK freq> <COREPLL ratio>
410 * <MPXPLL ratio>
411 */
412 read_from_px_regs(0);
413 read_from_px_regs_altbank(0);
414 val = set_px_sysclk(simple_strtoul(argv[3], NULL, 10));
Wolfgang Denkcdd917a2007-08-02 00:48:45 +0200415 corepll = strfractoint((uchar *)argv[4]);
Haiying Wang3d98b852007-01-22 12:37:30 -0600416 val = val + set_px_corepll(corepll);
417 val = val + set_px_mpxpll(simple_strtoul(argv[5],
418 NULL, 10));
419 if (val == 3) {
420 puts("Setting registers VCFGEN0, VCFGEN1, VBOOT, and VCTL\n");
421 set_altbank();
422 read_from_px_regs(1);
423 read_from_px_regs_altbank(1);
424 puts("Enabling watchdog timer on the FPGA\n");
425 puts("Resetting board with values from ");
426 puts("VSPEED0, VSPEED1, VCLKH and VCLKL ");
427 puts("to boot from the other bank.\n");
428 set_px_go_with_watchdog();
429 } else {
430 puts(cmdtp->usage);
431 return 1;
432 }
433
434 while (1) ; /* Not reached */
435
436 } else if (strcmp(argv[2], "wd") == 0) {
437 /*
438 * Reset from alternate bank without changing
439 * frequencies but with watchdog timer enabled:
440 * altbank wd
441 */
442 read_from_px_regs(0);
443 read_from_px_regs_altbank(0);
444 puts("Setting registers VCFGEN1, VBOOT, and VCTL\n");
445 set_altbank();
446 read_from_px_regs_altbank(1);
447 puts("Enabling watchdog timer on the FPGA\n");
448 puts("Resetting board to boot from the other bank.\n");
449 set_px_go_with_watchdog();
450 while (1) ; /* Not reached */
451
452 } else {
453 puts(cmdtp->usage);
454 return 1;
455 }
456
457 } else {
458 puts(cmdtp->usage);
459 return 1;
460 }
461
462 return 0;
463}
464
465
466U_BOOT_CMD(
467 pixis_reset, CFG_MAXARGS, 1, pixis_reset_cmd,
468 "pixis_reset - Reset the board using the FPGA sequencer\n",
469 " pixis_reset\n"
470 " pixis_reset [altbank]\n"
471 " pixis_reset altbank wd\n"
472 " pixis_reset altbank cf <SYSCLK freq> <COREPLL ratio> <MPXPLL ratio>\n"
473 " pixis_reset cf <SYSCLK freq> <COREPLL ratio> <MPXPLL ratio>\n"
474 );
Kim Phillips7608d752007-08-21 17:00:17 -0500475#endif /* CONFIG_FSL_PIXIS */