]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - board/freescale/common/pixis.c
Merge branch 'master' of /home/wd/git/u-boot/custodians
[karo-tx-uboot.git] / board / freescale / common / pixis.c
1 /*
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>
26 #include <command.h>
27 #include <watchdog.h>
28 #include <asm/cache.h>
29 #include <asm/io.h>
30
31 #include "pixis.h"
32
33
34 static ulong strfractoint(uchar *strptr);
35
36
37 /*
38  * Simple board reset.
39  */
40 void pixis_reset(void)
41 {
42         u8 *pixis_base = (u8 *)PIXIS_BASE;
43         out_8(pixis_base + PIXIS_RST, 0);
44 }
45
46
47 /*
48  * Per table 27, page 58 of MPC8641HPCN spec.
49  */
50 int set_px_sysclk(ulong sysclk)
51 {
52         u8 sysclk_s, sysclk_r, sysclk_v, vclkh, vclkl, sysclk_aux;
53         u8 *pixis_base = (u8 *)PIXIS_BASE;
54
55         switch (sysclk) {
56         case 33:
57                 sysclk_s = 0x04;
58                 sysclk_r = 0x04;
59                 sysclk_v = 0x07;
60                 sysclk_aux = 0x00;
61                 break;
62         case 40:
63                 sysclk_s = 0x01;
64                 sysclk_r = 0x1F;
65                 sysclk_v = 0x20;
66                 sysclk_aux = 0x01;
67                 break;
68         case 50:
69                 sysclk_s = 0x01;
70                 sysclk_r = 0x1F;
71                 sysclk_v = 0x2A;
72                 sysclk_aux = 0x02;
73                 break;
74         case 66:
75                 sysclk_s = 0x01;
76                 sysclk_r = 0x04;
77                 sysclk_v = 0x04;
78                 sysclk_aux = 0x03;
79                 break;
80         case 83:
81                 sysclk_s = 0x01;
82                 sysclk_r = 0x1F;
83                 sysclk_v = 0x4B;
84                 sysclk_aux = 0x04;
85                 break;
86         case 100:
87                 sysclk_s = 0x01;
88                 sysclk_r = 0x1F;
89                 sysclk_v = 0x5C;
90                 sysclk_aux = 0x05;
91                 break;
92         case 134:
93                 sysclk_s = 0x06;
94                 sysclk_r = 0x1F;
95                 sysclk_v = 0x3B;
96                 sysclk_aux = 0x06;
97                 break;
98         case 166:
99                 sysclk_s = 0x06;
100                 sysclk_r = 0x1F;
101                 sysclk_v = 0x4B;
102                 sysclk_aux = 0x07;
103                 break;
104         default:
105                 printf("Unsupported SYSCLK frequency.\n");
106                 return 0;
107         }
108
109         vclkh = (sysclk_s << 5) | sysclk_r;
110         vclkl = sysclk_v;
111
112         out_8(pixis_base + PIXIS_VCLKH, vclkh);
113         out_8(pixis_base + PIXIS_VCLKL, vclkl);
114
115         out_8(pixis_base + PIXIS_AUX, sysclk_aux);
116
117         return 1;
118 }
119
120
121 int set_px_mpxpll(ulong mpxpll)
122 {
123         u8 tmp;
124         u8 val;
125         u8 *pixis_base = (u8 *)PIXIS_BASE;
126
127         switch (mpxpll) {
128         case 2:
129         case 4:
130         case 6:
131         case 8:
132         case 10:
133         case 12:
134         case 14:
135         case 16:
136                 val = (u8) mpxpll;
137                 break;
138         default:
139                 printf("Unsupported MPXPLL ratio.\n");
140                 return 0;
141         }
142
143         tmp = in_8(pixis_base + PIXIS_VSPEED1);
144         tmp = (tmp & 0xF0) | (val & 0x0F);
145         out_8(pixis_base + PIXIS_VSPEED1, tmp);
146
147         return 1;
148 }
149
150
151 int set_px_corepll(ulong corepll)
152 {
153         u8 tmp;
154         u8 val;
155         u8 *pixis_base = (u8 *)PIXIS_BASE;
156
157         switch ((int)corepll) {
158         case 20:
159                 val = 0x08;
160                 break;
161         case 25:
162                 val = 0x0C;
163                 break;
164         case 30:
165                 val = 0x10;
166                 break;
167         case 35:
168                 val = 0x1C;
169                 break;
170         case 40:
171                 val = 0x14;
172                 break;
173         case 45:
174                 val = 0x0E;
175                 break;
176         default:
177                 printf("Unsupported COREPLL ratio.\n");
178                 return 0;
179         }
180
181         tmp = in_8(pixis_base + PIXIS_VSPEED0);
182         tmp = (tmp & 0xE0) | (val & 0x1F);
183         out_8(pixis_base + PIXIS_VSPEED0, tmp);
184
185         return 1;
186 }
187
188
189 void read_from_px_regs(int set)
190 {
191         u8 *pixis_base = (u8 *)PIXIS_BASE;
192         u8 mask = 0x1C; /* COREPLL, MPXPLL, SYSCLK controlled by PIXIS */
193         u8 tmp = in_8(pixis_base + PIXIS_VCFGEN0);
194
195         if (set)
196                 tmp = tmp | mask;
197         else
198                 tmp = tmp & ~mask;
199         out_8(pixis_base + PIXIS_VCFGEN0, tmp);
200 }
201
202
203 void read_from_px_regs_altbank(int set)
204 {
205         u8 *pixis_base = (u8 *)PIXIS_BASE;
206         u8 mask = 0x04; /* FLASHBANK and FLASHMAP controlled by PIXIS */
207         u8 tmp = in_8(pixis_base + PIXIS_VCFGEN1);
208
209         if (set)
210                 tmp = tmp | mask;
211         else
212                 tmp = tmp & ~mask;
213         out_8(pixis_base + PIXIS_VCFGEN1, tmp);
214 }
215
216 #ifndef CONFIG_SYS_PIXIS_VBOOT_MASK
217 #define CONFIG_SYS_PIXIS_VBOOT_MASK     (0x40)
218 #endif
219
220 void clear_altbank(void)
221 {
222         u8 tmp;
223         u8 *pixis_base = (u8 *)PIXIS_BASE;
224
225         tmp = in_8(pixis_base + PIXIS_VBOOT);
226         tmp &= ~CONFIG_SYS_PIXIS_VBOOT_MASK;
227
228         out_8(pixis_base + PIXIS_VBOOT, tmp);
229 }
230
231
232 void set_altbank(void)
233 {
234         u8 tmp;
235         u8 *pixis_base = (u8 *)PIXIS_BASE;
236
237         tmp = in_8(pixis_base + PIXIS_VBOOT);
238         tmp |= CONFIG_SYS_PIXIS_VBOOT_MASK;
239
240         out_8(pixis_base + PIXIS_VBOOT, tmp);
241 }
242
243
244 void set_px_go(void)
245 {
246         u8 tmp;
247         u8 *pixis_base = (u8 *)PIXIS_BASE;
248
249         tmp = in_8(pixis_base + PIXIS_VCTL);
250         tmp = tmp & 0x1E;                       /* clear GO bit */
251         out_8(pixis_base + PIXIS_VCTL, tmp);
252
253         tmp = in_8(pixis_base + PIXIS_VCTL);
254         tmp = tmp | 0x01;       /* set GO bit - start reset sequencer */
255         out_8(pixis_base + PIXIS_VCTL, tmp);
256 }
257
258
259 void set_px_go_with_watchdog(void)
260 {
261         u8 tmp;
262         u8 *pixis_base = (u8 *)PIXIS_BASE;
263
264         tmp = in_8(pixis_base + PIXIS_VCTL);
265         tmp = tmp & 0x1E;
266         out_8(pixis_base + PIXIS_VCTL, tmp);
267
268         tmp = in_8(pixis_base + PIXIS_VCTL);
269         tmp = tmp | 0x09;
270         out_8(pixis_base + PIXIS_VCTL, tmp);
271 }
272
273
274 int pixis_disable_watchdog_cmd(cmd_tbl_t *cmdtp,
275                                int flag, int argc, char *argv[])
276 {
277         u8 tmp;
278         u8 *pixis_base = (u8 *)PIXIS_BASE;
279
280         tmp = in_8(pixis_base + PIXIS_VCTL);
281         tmp = tmp & 0x1E;
282         out_8(pixis_base + PIXIS_VCTL, tmp);
283
284         /* setting VCTL[WDEN] to 0 to disable watch dog */
285         tmp = in_8(pixis_base + PIXIS_VCTL);
286         tmp &= ~0x08;
287         out_8(pixis_base + PIXIS_VCTL, tmp);
288
289         return 0;
290 }
291
292 U_BOOT_CMD(
293         diswd, 1, 0, pixis_disable_watchdog_cmd,
294         "Disable watchdog timer",
295         ""
296 );
297
298 #ifdef CONFIG_PIXIS_SGMII_CMD
299 int pixis_set_sgmii(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
300 {
301         int which_tsec = -1;
302         u8 *pixis_base = (u8 *)PIXIS_BASE;
303         uchar mask;
304         uchar switch_mask;
305
306         if (argc > 2)
307                 if (strcmp(argv[1], "all") != 0)
308                         which_tsec = simple_strtoul(argv[1], NULL, 0);
309
310         switch (which_tsec) {
311 #ifdef CONFIG_TSEC1
312         case 1:
313                 mask = PIXIS_VSPEED2_TSEC1SER;
314                 switch_mask = PIXIS_VCFGEN1_TSEC1SER;
315                 break;
316 #endif
317 #ifdef CONFIG_TSEC2
318         case 2:
319                 mask = PIXIS_VSPEED2_TSEC2SER;
320                 switch_mask = PIXIS_VCFGEN1_TSEC2SER;
321                 break;
322 #endif
323 #ifdef CONFIG_TSEC3
324         case 3:
325                 mask = PIXIS_VSPEED2_TSEC3SER;
326                 switch_mask = PIXIS_VCFGEN1_TSEC3SER;
327                 break;
328 #endif
329 #ifdef CONFIG_TSEC4
330         case 4:
331                 mask = PIXIS_VSPEED2_TSEC4SER;
332                 switch_mask = PIXIS_VCFGEN1_TSEC4SER;
333                 break;
334 #endif
335         default:
336                 mask = PIXIS_VSPEED2_MASK;
337                 switch_mask = PIXIS_VCFGEN1_MASK;
338                 break;
339         }
340
341         /* Toggle whether the switches or FPGA control the settings */
342         if (!strcmp(argv[argc - 1], "switch"))
343                 clrbits_8(pixis_base + PIXIS_VCFGEN1, switch_mask);
344         else
345                 setbits_8(pixis_base + PIXIS_VCFGEN1, switch_mask);
346
347         /* If it's not the switches, enable or disable SGMII, as specified */
348         if (!strcmp(argv[argc - 1], "on"))
349                 clrbits_8(pixis_base + PIXIS_VSPEED2, mask);
350         else if (!strcmp(argv[argc - 1], "off"))
351                 setbits_8(pixis_base + PIXIS_VSPEED2, mask);
352
353         return 0;
354 }
355
356 U_BOOT_CMD(
357         pixis_set_sgmii, CONFIG_SYS_MAXARGS, 1, pixis_set_sgmii,
358         "pixis_set_sgmii"
359         " - Enable or disable SGMII mode for a given TSEC \n",
360         "\npixis_set_sgmii [TSEC num] <on|off|switch>\n"
361         "    TSEC num: 1,2,3,4 or 'all'.  'all' is default.\n"
362         "    on - enables SGMII\n"
363         "    off - disables SGMII\n"
364         "    switch - use switch settings"
365 );
366 #endif
367
368 /*
369  * This function takes the non-integral cpu:mpx pll ratio
370  * and converts it to an integer that can be used to assign
371  * FPGA register values.
372  * input: strptr i.e. argv[2]
373  */
374
375 static ulong strfractoint(uchar *strptr)
376 {
377         int i, j, retval;
378         int mulconst;
379         int intarr_len = 0, decarr_len = 0, no_dec = 0;
380         ulong intval = 0, decval = 0;
381         uchar intarr[3], decarr[3];
382
383         /* Assign the integer part to intarr[]
384          * If there is no decimal point i.e.
385          * if the ratio is an integral value
386          * simply create the intarr.
387          */
388         i = 0;
389         while (strptr[i] != '.') {
390                 if (strptr[i] == 0) {
391                         no_dec = 1;
392                         break;
393                 }
394                 intarr[i] = strptr[i];
395                 i++;
396         }
397
398         /* Assign length of integer part to intarr_len. */
399         intarr_len = i;
400         intarr[i] = '\0';
401
402         if (no_dec) {
403                 /* Currently needed only for single digit corepll ratios */
404                 mulconst = 10;
405                 decval = 0;
406         } else {
407                 j = 0;
408                 i++;            /* Skipping the decimal point */
409                 while ((strptr[i] >= '0') && (strptr[i] <= '9')) {
410                         decarr[j] = strptr[i];
411                         i++;
412                         j++;
413                 }
414
415                 decarr_len = j;
416                 decarr[j] = '\0';
417
418                 mulconst = 1;
419                 for (i = 0; i < decarr_len; i++)
420                         mulconst *= 10;
421                 decval = simple_strtoul((char *)decarr, NULL, 10);
422         }
423
424         intval = simple_strtoul((char *)intarr, NULL, 10);
425         intval = intval * mulconst;
426
427         retval = intval + decval;
428
429         return retval;
430 }
431
432
433 int
434 pixis_reset_cmd(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
435 {
436         unsigned int i;
437         char *p_cf = NULL;
438         char *p_cf_sysclk = NULL;
439         char *p_cf_corepll = NULL;
440         char *p_cf_mpxpll = NULL;
441         char *p_altbank = NULL;
442         char *p_wd = NULL;
443         unsigned int unknown_param = 0;
444
445         /*
446          * No args is a simple reset request.
447          */
448         if (argc <= 1) {
449                 pixis_reset();
450                 /* not reached */
451         }
452
453         for (i = 1; i < argc; i++) {
454                 if (strcmp(argv[i], "cf") == 0) {
455                         p_cf = argv[i];
456                         if (i + 3 >= argc) {
457                                 break;
458                         }
459                         p_cf_sysclk = argv[i+1];
460                         p_cf_corepll = argv[i+2];
461                         p_cf_mpxpll = argv[i+3];
462                         i += 3;
463                         continue;
464                 }
465
466                 if (strcmp(argv[i], "altbank") == 0) {
467                         p_altbank = argv[i];
468                         continue;
469                 }
470
471                 if (strcmp(argv[i], "wd") == 0) {
472                         p_wd = argv[i];
473                         continue;
474                 }
475
476                 unknown_param = 1;
477         }
478
479         /*
480          * Check that cf has all required parms
481          */
482         if ((p_cf && !(p_cf_sysclk && p_cf_corepll && p_cf_mpxpll))
483             ||  unknown_param) {
484 #ifdef CONFIG_SYS_LONGHELP
485                 puts(cmdtp->help);
486 #endif
487                 return 1;
488         }
489
490         /*
491          * PIXIS seems to be sensitive to the ordering of
492          * the registers that are touched.
493          */
494         read_from_px_regs(0);
495
496         if (p_altbank) {
497                 read_from_px_regs_altbank(0);
498         }
499         clear_altbank();
500
501         /*
502          * Clock configuration specified.
503          */
504         if (p_cf) {
505                 unsigned long sysclk;
506                 unsigned long corepll;
507                 unsigned long mpxpll;
508
509                 sysclk = simple_strtoul(p_cf_sysclk, NULL, 10);
510                 corepll = strfractoint((uchar *) p_cf_corepll);
511                 mpxpll = simple_strtoul(p_cf_mpxpll, NULL, 10);
512
513                 if (!(set_px_sysclk(sysclk)
514                       && set_px_corepll(corepll)
515                       && set_px_mpxpll(mpxpll))) {
516 #ifdef CONFIG_SYS_LONGHELP
517                         puts(cmdtp->help);
518 #endif
519                         return 1;
520                 }
521                 read_from_px_regs(1);
522         }
523
524         /*
525          * Altbank specified
526          *
527          * NOTE CHANGE IN BEHAVIOR: previous code would default
528          * to enabling watchdog if altbank is specified.
529          * Now the watchdog must be enabled explicitly using 'wd'.
530          */
531         if (p_altbank) {
532                 set_altbank();
533                 read_from_px_regs_altbank(1);
534         }
535
536         /*
537          * Reset with watchdog specified.
538          */
539         if (p_wd) {
540                 set_px_go_with_watchdog();
541         } else {
542                 set_px_go();
543         }
544
545         /*
546          * Shouldn't be reached.
547          */
548         return 0;
549 }
550
551
552 U_BOOT_CMD(
553         pixis_reset, CONFIG_SYS_MAXARGS, 1, pixis_reset_cmd,
554         "Reset the board using the FPGA sequencer",
555         "    pixis_reset\n"
556         "    pixis_reset [altbank]\n"
557         "    pixis_reset altbank wd\n"
558         "    pixis_reset altbank cf <SYSCLK freq> <COREPLL ratio> <MPXPLL ratio>\n"
559         "    pixis_reset cf <SYSCLK freq> <COREPLL ratio> <MPXPLL ratio>"
560 );