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