]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - board/bc3450/cmd_bc3450.c
Merge branch 'master' of git://git.denx.de/u-boot-microblaze
[karo-tx-uboot.git] / board / bc3450 / cmd_bc3450.c
1 /*
2  * (C) Copyright 2005
3  * Stefan Strobl, GERSYS GmbH, stefan.strobl@gersys.de
4  *
5  * (C) Copyright 2005
6  * Martin Krause, TQ-Systems GmbH, martin.krause@tqs.de.
7  *
8  * See file CREDITS for list of people who contributed to this
9  * project.
10  *
11  * This program is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU General Public License as
13  * published by the Free Software Foundation; either version 2 of
14  * the License, or (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
24  * MA 02111-1307 USA
25  */
26
27 #include <common.h>
28 #include <command.h>
29
30 /*
31  * BC3450 specific commands
32  */
33 #if defined(CONFIG_CMD_BSP)
34
35 /*
36  * Definitions for DS1620 chip
37  */
38 #define THERM_START_CONVERT     0xee
39 #define THERM_RESET             0xaf
40 #define THERM_READ_CONFIG       0xac
41 #define THERM_READ_TEMP         0xaa
42 #define THERM_READ_TL           0xa2
43 #define THERM_READ_TH           0xa1
44 #define THERM_WRITE_CONFIG      0x0c
45 #define THERM_WRITE_TL          0x02
46 #define THERM_WRITE_TH          0x01
47
48 #define CONFIG_SYS_1SHOT                1
49 #define CONFIG_SYS_STANDALONE           0
50
51 struct therm {
52         int hi;
53         int lo;
54 };
55
56 /*
57  * SM501 Register
58  */
59 #define SM501_GPIO_CTRL_LOW             0x00000008UL    /* gpio pins 0..31  */
60 #define SM501_GPIO_CTRL_HIGH            0x0000000CUL    /* gpio pins 32..63 */
61 #define SM501_POWER_MODE0_GATE          0x00000040UL
62 #define SM501_POWER_MODE1_GATE          0x00000048UL
63 #define POWER_MODE_GATE_GPIO_PWM_I2C    0x00000040UL
64 #define SM501_GPIO_DATA_LOW             0x00010000UL
65 #define SM501_GPIO_DATA_HIGH            0x00010004UL
66 #define SM501_GPIO_DATA_DIR_LOW         0x00010008UL
67 #define SM501_GPIO_DATA_DIR_HIGH        0x0001000CUL
68 #define SM501_PANEL_DISPLAY_CONTROL     0x00080000UL
69 #define SM501_CRT_DISPLAY_CONTROL       0x00080200UL
70
71 /* SM501 CRT Display Control Bits */
72 #define SM501_CDC_SEL                   (1 << 9)
73 #define SM501_CDC_TE                    (1 << 8)
74 #define SM501_CDC_E                     (1 << 2)
75
76 /* SM501 Panel Display Control Bits */
77 #define SM501_PDC_FPEN                  (1 << 27)
78 #define SM501_PDC_BIAS                  (1 << 26)
79 #define SM501_PDC_DATA                  (1 << 25)
80 #define SM501_PDC_VDDEN                 (1 << 24)
81
82 /* SM501 GPIO Data LOW Bits */
83 #define SM501_GPIO24                    0x01000000
84 #define SM501_GPIO25                    0x02000000
85 #define SM501_GPIO26                    0x04000000
86 #define SM501_GPIO27                    0x08000000
87 #define SM501_GPIO28                    0x10000000
88 #define SM501_GPIO29                    0x20000000
89 #define SM501_GPIO30                    0x40000000
90 #define SM501_GPIO31                    0x80000000
91
92 /* SM501 GPIO Data HIGH Bits */
93 #define SM501_GPIO46                    0x00004000
94 #define SM501_GPIO47                    0x00008000
95 #define SM501_GPIO48                    0x00010000
96 #define SM501_GPIO49                    0x00020000
97 #define SM501_GPIO50                    0x00040000
98 #define SM501_GPIO51                    0x00080000
99
100 /* BC3450 GPIOs @ SM501 Data LOW */
101 #define DIP                             (SM501_GPIO24 | SM501_GPIO25 | SM501_GPIO26 | SM501_GPIO27)
102 #define DS1620_DQ                       SM501_GPIO29    /* I/O             */
103 #define DS1620_CLK                      SM501_GPIO30    /* High active O/P */
104 #define DS1620_RES                      SM501_GPIO31    /* Low active O/P  */
105 /* BC3450 GPIOs @ SM501 Data HIGH */
106 #define BUZZER                          SM501_GPIO47    /* Low active O/P  */
107 #define DS1620_TLOW                     SM501_GPIO48    /* High active I/P */
108 #define PWR_OFF                         SM501_GPIO49    /* Low active O/P  */
109 #define FP_DATA_TRI                     SM501_GPIO50    /* High active O/P */
110
111
112 /*
113  * Initialise GPIO on SM501
114  *
115  * This function may be called from several other functions.
116  * Yet, the initialisation sequence is executed only the first
117  * time the function is called.
118  */
119 int sm501_gpio_init (void)
120 {
121         static int init_done = 0;
122
123         if (init_done) {
124                 debug("sm501_gpio_init: nothing to be done.\n");
125                 return 1;
126         }
127
128         /* enable SM501 GPIO control (in both power modes) */
129         *(vu_long *) (SM501_MMIO_BASE + SM501_POWER_MODE0_GATE) |=
130                 POWER_MODE_GATE_GPIO_PWM_I2C;
131         *(vu_long *) (SM501_MMIO_BASE + SM501_POWER_MODE1_GATE) |=
132                 POWER_MODE_GATE_GPIO_PWM_I2C;
133
134         /* set up default O/Ps */
135         *(vu_long *) (SM501_MMIO_BASE + SM501_GPIO_DATA_LOW) &=
136                 ~(DS1620_RES | DS1620_CLK);
137         *(vu_long *) (SM501_MMIO_BASE + SM501_GPIO_DATA_LOW) |= DS1620_DQ;
138         *(vu_long *) (SM501_MMIO_BASE + SM501_GPIO_DATA_HIGH) &=
139                 ~(FP_DATA_TRI);
140         *(vu_long *) (SM501_MMIO_BASE + SM501_GPIO_DATA_HIGH) |=
141                 (BUZZER | PWR_OFF);
142
143         /* configure directions for SM501 GPIO pins */
144         *(vu_long *) (SM501_MMIO_BASE + SM501_GPIO_CTRL_LOW) &= ~(0xFF << 24);
145         *(vu_long *) (SM501_MMIO_BASE + SM501_GPIO_CTRL_HIGH) &=
146                 ~(0x3F << 14);
147         *(vu_long *) (SM501_MMIO_BASE + SM501_GPIO_DATA_DIR_LOW) &=
148                 ~(DIP | DS1620_DQ);
149         *(vu_long *) (SM501_MMIO_BASE + SM501_GPIO_DATA_DIR_LOW) |=
150                 (DS1620_RES | DS1620_CLK);
151         *(vu_long *) (SM501_MMIO_BASE + SM501_GPIO_DATA_DIR_HIGH) &=
152                 ~DS1620_TLOW;
153         *(vu_long *) (SM501_MMIO_BASE + SM501_GPIO_DATA_DIR_HIGH) |=
154                 (PWR_OFF | BUZZER | FP_DATA_TRI);
155
156         init_done = 1;
157         debug("sm501_gpio_init: done.\n");
158
159         return 0;
160 }
161
162
163 /*
164  * dip - read Config Inputs
165  *
166  * read and prints the dip switch
167  * and/or external config inputs (4bits) 0...0x0F
168  */
169 int cmd_dip (cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
170 {
171         vu_long rc = 0;
172
173         sm501_gpio_init ();
174
175         /* read dip switch */
176         rc = *(vu_long *) (SM501_MMIO_BASE + SM501_GPIO_DATA_LOW);
177         rc = ~rc;
178         rc &= DIP;
179         rc = (int) (rc >> 24);
180
181         /* plausibility check */
182         if (rc > 0x0F)
183                 return -1;
184
185         printf ("0x%lx\n", rc);
186         return 0;
187 }
188
189 U_BOOT_CMD (dip, 1, 1, cmd_dip,
190             "read dip switch and config inputs",
191             "\n"
192             "     - prints the state of the dip switch and/or\n"
193             "       external configuration inputs as hex value.\n"
194             "     - \"Config 1\" is the LSB");
195
196
197 /*
198  * buz - turns Buzzer on/off
199  */
200 #ifdef CONFIG_BC3450_BUZZER
201 static int cmd_buz (cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
202 {
203         if (argc != 2) {
204                 printf ("Usage:\nspecify one argument: \"on\" or \"off\"\n");
205                 return 1;
206         }
207
208         sm501_gpio_init ();
209
210         if (strncmp (argv[1], "on", 2) == 0) {
211                 *(vu_long *) (SM501_MMIO_BASE + SM501_GPIO_DATA_HIGH) &=
212                         ~(BUZZER);
213                 return 0;
214         } else if (strncmp (argv[1], "off", 3) == 0) {
215                 *(vu_long *) (SM501_MMIO_BASE + SM501_GPIO_DATA_HIGH) |=
216                         BUZZER;
217                 return 0;
218         }
219         printf ("Usage:\nspecify one argument: \"on\" or \"off\"\n");
220         return 1;
221 }
222
223 U_BOOT_CMD (buz, 2, 1, cmd_buz,
224             "turns buzzer on/off",
225             "\n" "buz <on/off>\n" "     - turns the buzzer on or off");
226 #endif /* CONFIG_BC3450_BUZZER */
227
228
229 /*
230  * fp - front panel commands
231  */
232 static int cmd_fp (cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
233 {
234         sm501_gpio_init ();
235
236         if (strncmp (argv[1], "on", 2) == 0) {
237                 /* turn on VDD first */
238                 *(vu_long *) (SM501_MMIO_BASE +
239                               SM501_PANEL_DISPLAY_CONTROL) |= SM501_PDC_VDDEN;
240                 udelay (1000);
241                 /* then put data on */
242                 *(vu_long *) (SM501_MMIO_BASE +
243                               SM501_PANEL_DISPLAY_CONTROL) |= SM501_PDC_DATA;
244                 /* wait some time and enable backlight */
245                 udelay (1000);
246                 *(vu_long *) (SM501_MMIO_BASE +
247                               SM501_PANEL_DISPLAY_CONTROL) |= SM501_PDC_BIAS;
248                 udelay (1000);
249                 *(vu_long *) (SM501_MMIO_BASE +
250                               SM501_PANEL_DISPLAY_CONTROL) |= SM501_PDC_FPEN;
251                 return 0;
252         } else if (strncmp (argv[1], "off", 3) == 0) {
253                 /* turn off the backlight first */
254                 *(vu_long *) (SM501_MMIO_BASE +
255                               SM501_PANEL_DISPLAY_CONTROL) &= ~SM501_PDC_FPEN;
256                 udelay (1000);
257                 *(vu_long *) (SM501_MMIO_BASE +
258                               SM501_PANEL_DISPLAY_CONTROL) &= ~SM501_PDC_BIAS;
259                 udelay (200000);
260                 /* wait some time, then remove data */
261                 *(vu_long *) (SM501_MMIO_BASE +
262                               SM501_PANEL_DISPLAY_CONTROL) &= ~SM501_PDC_DATA;
263                 udelay (1000);
264                 /* and remove VDD last */
265                 *(vu_long *) (SM501_MMIO_BASE +
266                               SM501_PANEL_DISPLAY_CONTROL) &=
267                         ~SM501_PDC_VDDEN;
268                 return 0;
269         } else if (strncmp (argv[1], "bl", 2) == 0) {
270                 /* turn on/off backlight only */
271                 if (strncmp (argv[2], "on", 2) == 0) {
272                         *(vu_long *) (SM501_MMIO_BASE +
273                                       SM501_PANEL_DISPLAY_CONTROL) |=
274                                 SM501_PDC_BIAS;
275                         udelay (1000);
276                         *(vu_long *) (SM501_MMIO_BASE +
277                                       SM501_PANEL_DISPLAY_CONTROL) |=
278                                 SM501_PDC_FPEN;
279                         return 0;
280                 } else if (strncmp (argv[2], "off", 3) == 0) {
281                         *(vu_long *) (SM501_MMIO_BASE +
282                                       SM501_PANEL_DISPLAY_CONTROL) &=
283                                 ~SM501_PDC_FPEN;
284                         udelay (1000);
285                         *(vu_long *) (SM501_MMIO_BASE +
286                                       SM501_PANEL_DISPLAY_CONTROL) &=
287                                 ~SM501_PDC_BIAS;
288                         return 0;
289                 }
290         }
291 #ifdef CONFIG_BC3450_CRT
292         else if (strncmp (argv[1], "crt", 3) == 0) {
293                 /* enables/disables the crt output (debug only) */
294                 if (strncmp (argv[2], "on", 2) == 0) {
295                         *(vu_long *) (SM501_MMIO_BASE +
296                                       SM501_CRT_DISPLAY_CONTROL) |=
297                                 (SM501_CDC_TE | SM501_CDC_E);
298                         *(vu_long *) (SM501_MMIO_BASE +
299                                       SM501_CRT_DISPLAY_CONTROL) &=
300                                 ~SM501_CDC_SEL;
301                         return 0;
302                 } else if (strncmp (argv[2], "off", 3) == 0) {
303                         *(vu_long *) (SM501_MMIO_BASE +
304                                       SM501_CRT_DISPLAY_CONTROL) &=
305                                 ~(SM501_CDC_TE | SM501_CDC_E);
306                         *(vu_long *) (SM501_MMIO_BASE +
307                                       SM501_CRT_DISPLAY_CONTROL) |=
308                                 SM501_CDC_SEL;
309                         return 0;
310                 }
311         }
312 #endif /* CONFIG_BC3450_CRT */
313         printf ("Usage:%s\n", cmdtp->help);
314         return 1;
315 }
316
317 U_BOOT_CMD (fp, 3, 1, cmd_fp,
318             "front panes access functions",
319             "\n"
320             "fp bl <on/off>\n"
321             "     - turns the CCFL backlight of the display on/off\n"
322             "fp <on/off>\n" "     - turns the whole display on/off"
323 #ifdef CONFIG_BC3450_CRT
324             "\n"
325             "fp crt <on/off>\n"
326             "     - enables/disables the crt output (debug only)"
327 #endif /* CONFIG_BC3450_CRT */
328         );
329
330 /*
331  * temp - DS1620 thermometer
332  */
333 /* GERSYS BC3450 specific functions */
334 static inline void bc_ds1620_set_clk (int clk)
335 {
336         if (clk)
337                 *(vu_long *) (SM501_MMIO_BASE + SM501_GPIO_DATA_LOW) |=
338                         DS1620_CLK;
339         else
340                 *(vu_long *) (SM501_MMIO_BASE + SM501_GPIO_DATA_LOW) &=
341                         ~DS1620_CLK;
342 }
343
344 static inline void bc_ds1620_set_data (int dat)
345 {
346         if (dat)
347                 *(vu_long *) (SM501_MMIO_BASE + SM501_GPIO_DATA_LOW) |=
348                         DS1620_DQ;
349         else
350                 *(vu_long *) (SM501_MMIO_BASE + SM501_GPIO_DATA_LOW) &=
351                         ~DS1620_DQ;
352 }
353
354 static inline int bc_ds1620_get_data (void)
355 {
356         vu_long rc;
357
358         rc = *(vu_long *) (SM501_MMIO_BASE + SM501_GPIO_DATA_LOW);
359         rc &= DS1620_DQ;
360         if (rc != 0)
361                 rc = 1;
362         return (int) rc;
363 }
364
365 static inline void bc_ds1620_set_data_dir (int dir)
366 {
367         if (dir)                /* in */
368                 *(vu_long *) (SM501_MMIO_BASE + SM501_GPIO_DATA_DIR_LOW) &= ~DS1620_DQ;
369         else                    /* out */
370                 *(vu_long *) (SM501_MMIO_BASE + SM501_GPIO_DATA_DIR_LOW) |= DS1620_DQ;
371 }
372
373 static inline void bc_ds1620_set_reset (int res)
374 {
375         if (res)
376                 *(vu_long *) (SM501_MMIO_BASE + SM501_GPIO_DATA_LOW) |= DS1620_RES;
377         else
378                 *(vu_long *) (SM501_MMIO_BASE + SM501_GPIO_DATA_LOW) &= ~DS1620_RES;
379 }
380
381 /* hardware independent functions */
382 static void ds1620_send_bits (int nr, int value)
383 {
384         int i;
385
386         for (i = 0; i < nr; i++) {
387                 bc_ds1620_set_data (value & 1);
388                 bc_ds1620_set_clk (0);
389                 udelay (1);
390                 bc_ds1620_set_clk (1);
391                 udelay (1);
392
393                 value >>= 1;
394         }
395 }
396
397 static unsigned int ds1620_recv_bits (int nr)
398 {
399         unsigned int value = 0, mask = 1;
400         int i;
401
402         bc_ds1620_set_data (0);
403
404         for (i = 0; i < nr; i++) {
405                 bc_ds1620_set_clk (0);
406                 udelay (1);
407
408                 if (bc_ds1620_get_data ())
409                         value |= mask;
410
411                 mask <<= 1;
412
413                 bc_ds1620_set_clk (1);
414                 udelay (1);
415         }
416
417         return value;
418 }
419
420 static void ds1620_out (int cmd, int bits, int value)
421 {
422         bc_ds1620_set_clk (1);
423         bc_ds1620_set_data_dir (0);
424
425         bc_ds1620_set_reset (0);
426         udelay (1);
427         bc_ds1620_set_reset (1);
428
429         udelay (1);
430
431         ds1620_send_bits (8, cmd);
432         if (bits)
433                 ds1620_send_bits (bits, value);
434
435         udelay (1);
436
437         /* go stand alone */
438         bc_ds1620_set_data_dir (1);
439         bc_ds1620_set_reset (0);
440         bc_ds1620_set_clk (0);
441
442         udelay (10000);
443 }
444
445 static unsigned int ds1620_in (int cmd, int bits)
446 {
447         unsigned int value;
448
449         bc_ds1620_set_clk (1);
450         bc_ds1620_set_data_dir (0);
451
452         bc_ds1620_set_reset (0);
453         udelay (1);
454         bc_ds1620_set_reset (1);
455
456         udelay (1);
457
458         ds1620_send_bits (8, cmd);
459
460         bc_ds1620_set_data_dir (1);
461         value = ds1620_recv_bits (bits);
462
463         /* go stand alone */
464         bc_ds1620_set_data_dir (1);
465         bc_ds1620_set_reset (0);
466         bc_ds1620_set_clk (0);
467
468         return value;
469 }
470
471 static int cvt_9_to_int (unsigned int val)
472 {
473         if (val & 0x100)
474                 val |= 0xfffffe00;
475
476         return val;
477 }
478
479 /* set thermostate thresholds */
480 static void ds1620_write_state (struct therm *therm)
481 {
482         ds1620_out (THERM_WRITE_TL, 9, therm->lo);
483         ds1620_out (THERM_WRITE_TH, 9, therm->hi);
484         ds1620_out (THERM_START_CONVERT, 0, 0);
485 }
486
487 static int cmd_temp (cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
488 {
489         int i;
490         struct therm therm;
491
492         sm501_gpio_init ();
493
494         /* print temperature */
495         if (argc == 1) {
496                 i = cvt_9_to_int (ds1620_in (THERM_READ_TEMP, 9));
497                 printf ("%d.%d C\n", i >> 1, i & 1 ? 5 : 0);
498                 return 0;
499         }
500
501         /* set to default operation */
502         if (strncmp (argv[1], "set", 3) == 0) {
503                 if (strncmp (argv[2], "default", 3) == 0) {
504                         therm.hi = +88;
505                         therm.lo = -20;
506                         therm.hi <<= 1;
507                         therm.lo <<= 1;
508                         ds1620_write_state (&therm);
509                         ds1620_out (THERM_WRITE_CONFIG, 8, CONFIG_SYS_STANDALONE);
510                         return 0;
511                 }
512         }
513
514         printf ("Usage:%s\n", cmdtp->help);
515         return 1;
516 }
517
518 U_BOOT_CMD (temp, 3, 1, cmd_temp,
519             "print current temperature",
520             "\n" "temp\n" "     - print current temperature");
521
522 #ifdef CONFIG_BC3450_CAN
523 /*
524  * Initialise CAN interface
525  *
526  * return 1 on CAN initialization failure
527  * return 0 if no failure
528  */
529 int can_init (void)
530 {
531         static int init_done = 0;
532         int i;
533         struct mpc5xxx_mscan *can1 =
534                 (struct mpc5xxx_mscan *) (CONFIG_SYS_MBAR + 0x0900);
535         struct mpc5xxx_mscan *can2 =
536                 (struct mpc5xxx_mscan *) (CONFIG_SYS_MBAR + 0x0980);
537
538         /* GPIO configuration of the CAN pins is done in BC3450.h */
539
540         if (!init_done) {
541                 /* init CAN 1 */
542                 can1->canctl1 |= 0x80;  /* CAN enable */
543                 udelay (100);
544
545                 i = 0;
546                 can1->canctl0 |= 0x02;  /* sleep mode */
547                 /* wait until sleep mode reached */
548                 while (!(can1->canctl1 & 0x02)) {
549                         udelay (10);
550                         i++;
551                         if (i == 10) {
552                                 printf ("%s: CAN1 initialize error, "
553                                         "can not enter sleep mode!\n",
554                                         __FUNCTION__);
555                                 return 1;
556                         }
557                 }
558                 i = 0;
559                 can1->canctl0 = 0x01;   /* enter init mode */
560                 /* wait until init mode reached */
561                 while (!(can1->canctl1 & 0x01)) {
562                         udelay (10);
563                         i++;
564                         if (i == 10) {
565                                 printf ("%s: CAN1 initialize error, "
566                                         "can not enter init mode!\n",
567                                         __FUNCTION__);
568                                 return 1;
569                         }
570                 }
571                 can1->canctl1 = 0x80;
572                 can1->canctl1 |= 0x40;
573                 can1->canbtr0 = 0x0F;
574                 can1->canbtr1 = 0x7F;
575                 can1->canidac &= ~(0x30);
576                 can1->canidar1 = 0x00;
577                 can1->canidar3 = 0x00;
578                 can1->canidar5 = 0x00;
579                 can1->canidar7 = 0x00;
580                 can1->canidmr0 = 0xFF;
581                 can1->canidmr1 = 0xFF;
582                 can1->canidmr2 = 0xFF;
583                 can1->canidmr3 = 0xFF;
584                 can1->canidmr4 = 0xFF;
585                 can1->canidmr5 = 0xFF;
586                 can1->canidmr6 = 0xFF;
587                 can1->canidmr7 = 0xFF;
588
589                 i = 0;
590                 can1->canctl0 &= ~(0x01);       /* leave init mode */
591                 can1->canctl0 &= ~(0x02);
592                 /* wait until init and sleep mode left */
593                 while ((can1->canctl1 & 0x01) || (can1->canctl1 & 0x02)) {
594                         udelay (10);
595                         i++;
596                         if (i == 10) {
597                                 printf ("%s: CAN1 initialize error, "
598                                         "can not leave init/sleep mode!\n",
599                                         __FUNCTION__);
600                                 return 1;
601                         }
602                 }
603
604                 /* init CAN 2 */
605                 can2->canctl1 |= 0x80;  /* CAN enable */
606                 udelay (100);
607
608                 i = 0;
609                 can2->canctl0 |= 0x02;  /* sleep mode */
610                 /* wait until sleep mode reached */
611                 while (!(can2->canctl1 & 0x02)) {
612                         udelay (10);
613                         i++;
614                         if (i == 10) {
615                                 printf ("%s: CAN2 initialize error, "
616                                         "can not enter sleep mode!\n",
617                                         __FUNCTION__);
618                                 return 1;
619                         }
620                 }
621                 i = 0;
622                 can2->canctl0 = 0x01;   /* enter init mode */
623                 /* wait until init mode reached */
624                 while (!(can2->canctl1 & 0x01)) {
625                         udelay (10);
626                         i++;
627                         if (i == 10) {
628                                 printf ("%s: CAN2 initialize error, "
629                                         "can not enter init mode!\n",
630                                         __FUNCTION__);
631                                 return 1;
632                         }
633                 }
634                 can2->canctl1 = 0x80;
635                 can2->canctl1 |= 0x40;
636                 can2->canbtr0 = 0x0F;
637                 can2->canbtr1 = 0x7F;
638                 can2->canidac &= ~(0x30);
639                 can2->canidar1 = 0x00;
640                 can2->canidar3 = 0x00;
641                 can2->canidar5 = 0x00;
642                 can2->canidar7 = 0x00;
643                 can2->canidmr0 = 0xFF;
644                 can2->canidmr1 = 0xFF;
645                 can2->canidmr2 = 0xFF;
646                 can2->canidmr3 = 0xFF;
647                 can2->canidmr4 = 0xFF;
648                 can2->canidmr5 = 0xFF;
649                 can2->canidmr6 = 0xFF;
650                 can2->canidmr7 = 0xFF;
651                 can2->canctl0 &= ~(0x01);       /* leave init mode */
652                 can2->canctl0 &= ~(0x02);
653
654                 i = 0;
655                 /* wait until init mode left */
656                 while ((can2->canctl1 & 0x01) || (can2->canctl1 & 0x02)) {
657                         udelay (10);
658                         i++;
659                         if (i == 10) {
660                                 printf ("%s: CAN2 initialize error, "
661                                         "can not leave init/sleep mode!\n",
662                                         __FUNCTION__);
663                                 return 1;
664                         }
665                 }
666                 init_done = 1;
667         }
668         return 0;
669 }
670
671 /*
672  * Do CAN test
673  * by sending message between CAN1 and CAN2
674  *
675  * return 1 on CAN failure
676  * return 0 if no failure
677  */
678 int do_can (char * const argv[])
679 {
680         int i;
681         struct mpc5xxx_mscan *can1 =
682                 (struct mpc5xxx_mscan *) (CONFIG_SYS_MBAR + 0x0900);
683         struct mpc5xxx_mscan *can2 =
684                 (struct mpc5xxx_mscan *) (CONFIG_SYS_MBAR + 0x0980);
685
686         /* send a message on CAN1 */
687         can1->cantbsel = 0x01;
688         can1->cantxfg.idr[0] = 0x55;
689         can1->cantxfg.idr[1] = 0x00;
690         can1->cantxfg.idr[1] &= ~0x8;
691         can1->cantxfg.idr[1] &= ~0x10;
692         can1->cantxfg.dsr[0] = 0xCC;
693         can1->cantxfg.dlr = 1;
694         can1->cantxfg.tbpr = 0;
695         can1->cantflg = 0x01;
696
697         i = 0;
698         while ((can1->cantflg & 0x01) == 0) {
699                 i++;
700                 if (i == 10) {
701                         printf ("%s: CAN1 send timeout, "
702                                 "can not send message!\n", __FUNCTION__);
703                         return 1;
704                 }
705                 udelay (1000);
706         }
707         udelay (1000);
708
709         i = 0;
710         while (!(can2->canrflg & 0x01)) {
711                 i++;
712                 if (i == 10) {
713                         printf ("%s: CAN2 receive timeout, "
714                                 "no message received!\n", __FUNCTION__);
715                         return 1;
716                 }
717                 udelay (1000);
718         }
719
720         if (can2->canrxfg.dsr[0] != 0xCC) {
721                 printf ("%s: CAN2 receive error, "
722                         "data mismatch!\n", __FUNCTION__);
723                 return 1;
724         }
725
726         /* send a message on CAN2 */
727         can2->cantbsel = 0x01;
728         can2->cantxfg.idr[0] = 0x55;
729         can2->cantxfg.idr[1] = 0x00;
730         can2->cantxfg.idr[1] &= ~0x8;
731         can2->cantxfg.idr[1] &= ~0x10;
732         can2->cantxfg.dsr[0] = 0xCC;
733         can2->cantxfg.dlr = 1;
734         can2->cantxfg.tbpr = 0;
735         can2->cantflg = 0x01;
736
737         i = 0;
738         while ((can2->cantflg & 0x01) == 0) {
739                 i++;
740                 if (i == 10) {
741                         printf ("%s: CAN2 send error, "
742                                 "can not send message!\n", __FUNCTION__);
743                         return 1;
744                 }
745                 udelay (1000);
746         }
747         udelay (1000);
748
749         i = 0;
750         while (!(can1->canrflg & 0x01)) {
751                 i++;
752                 if (i == 10) {
753                         printf ("%s: CAN1 receive timeout, "
754                                 "no message received!\n", __FUNCTION__);
755                         return 1;
756                 }
757                 udelay (1000);
758         }
759
760         if (can1->canrxfg.dsr[0] != 0xCC) {
761                 printf ("%s: CAN1 receive error 0x%02x\n",
762                         __FUNCTION__, (can1->canrxfg.dsr[0]));
763                 return 1;
764         }
765
766         return 0;
767 }
768 #endif /* CONFIG_BC3450_CAN */
769
770 /*
771  * test - BC3450 HW test routines
772  */
773 int cmd_test (cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
774 {
775 #ifdef CONFIG_BC3450_CAN
776         int rcode;
777
778         can_init ();
779 #endif /* CONFIG_BC3450_CAN */
780
781         sm501_gpio_init ();
782
783         if (argc != 2) {
784                 printf ("Usage:%s\n", cmdtp->help);
785                 return 1;
786         }
787
788         if (strncmp (argv[1], "unit-off", 8) == 0) {
789                 printf ("waiting 2 seconds...\n");
790                 udelay (2000000);
791                 *(vu_long *) (SM501_MMIO_BASE + SM501_GPIO_DATA_HIGH) &=
792                         ~PWR_OFF;
793                 return 0;
794         }
795 #ifdef CONFIG_BC3450_CAN
796         else if (strncmp (argv[1], "can", 2) == 0) {
797                 rcode = do_can (argv);
798                 if (simple_strtoul (argv[2], NULL, 10) == 2) {
799                         if (rcode == 0)
800                                 printf ("OK\n");
801                         else
802                                 printf ("Error\n");
803                 }
804                 return rcode;
805         }
806 #endif /* CONFIG_BC3450_CAN */
807
808         printf ("Usage:%s\n", cmdtp->help);
809         return 1;
810 }
811
812 U_BOOT_CMD (test, 2, 1, cmd_test, "unit test routines", "\n"
813 #ifdef CONFIG_BC3450_CAN
814         "test can\n"
815         "     - connect CAN1 (X8) with CAN2 (X9) for this test\n"
816 #endif /* CONFIG_BC3450_CAN */
817         "test unit-off\n"
818         "     - turns off the BC3450 unit\n"
819         "       WARNING: Unsaved environment variables will be lost!"
820 );
821 #endif