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