]> git.ipfire.org Git - people/ms/u-boot.git/blob - board/bc3450/cmd_bc3450.c
Add support for BC3450 board
[people/ms/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 */