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