uboot/board/bc3450/cmd_bc3450.c
<<
>>
Prefs
   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
  35struct 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 */
 103int 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 */
 153int 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
 173U_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
 185static 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
 207U_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 */
 216static 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
 301U_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 */
 318static 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
 328static 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
 338static 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
 349static 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
 357static 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 */
 366static 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
 381static 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
 404static 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
 429static 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
 455static 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 */
 464static 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
 471static 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
 502U_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 */
 513int 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 */
 662int 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 */
 757int 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
 796U_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
 806