uboot/board/lwmon/lwmon.c
<<
>>
Prefs
   1/***********************************************************************
   2 *
   3M* Modul:         lwmon.c
   4M*
   5M* Content:       LWMON specific U-Boot commands.
   6 *
   7 * (C) Copyright 2001, 2002
   8 * DENX Software Engineering
   9 * Wolfgang Denk, wd@denx.de
  10 *
  11D* Design:        wd@denx.de
  12C* Coding:        wd@denx.de
  13V* Verification:  dzu@denx.de
  14 *
  15 * See file CREDITS for list of people who contributed to this
  16 * project.
  17 *
  18 * This program is free software; you can redistribute it and/or
  19 * modify it under the terms of the GNU General Public License as
  20 * published by the Free Software Foundation; either version 2 of
  21 * the License, or (at your option) any later version.
  22 *
  23 * This program is distributed in the hope that it will be useful,
  24 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  25 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  26 * GNU General Public License for more details.
  27 *
  28 * You should have received a copy of the GNU General Public License
  29 * along with this program; if not, write to the Free Software
  30 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  31 * MA 02111-1307 USA
  32 ***********************************************************************/
  33
  34/*---------------------------- Headerfiles ----------------------------*/
  35#include <common.h>
  36#include <mpc8xx.h>
  37#include <commproc.h>
  38#include <i2c.h>
  39#include <command.h>
  40#include <malloc.h>
  41#include <post.h>
  42#include <serial.h>
  43
  44#include <linux/types.h>
  45#include <linux/string.h>       /* for strdup */
  46
  47DECLARE_GLOBAL_DATA_PTR;
  48
  49/*------------------------ Local prototypes ---------------------------*/
  50static long int dram_size (long int, long int *, long int);
  51static void kbd_init (void);
  52static int compare_magic (uchar *kbd_data, uchar *str);
  53
  54
  55/*--------------------- Local macros and constants --------------------*/
  56#define _NOT_USED_      0xFFFFFFFF
  57
  58#ifdef CONFIG_MODEM_SUPPORT
  59static int key_pressed(void);
  60extern void disable_putc(void);
  61#endif /* CONFIG_MODEM_SUPPORT */
  62
  63/*
  64 * 66 MHz SDRAM access using UPM A
  65 */
  66const uint sdram_table[] =
  67{
  68#if defined(CONFIG_SYS_MEMORY_75) || defined(CONFIG_SYS_MEMORY_8E)
  69        /*
  70         * Single Read. (Offset 0 in UPM RAM)
  71         */
  72        0x1F0DFC04, 0xEEAFBC04, 0x11AF7C04, 0xEFBAFC00,
  73        0x1FF5FC47, /* last */
  74        /*
  75         * SDRAM Initialization (offset 5 in UPM RAM)
  76         *
  77         * This is no UPM entry point. The following definition uses
  78         * the remaining space to establish an initialization
  79         * sequence, which is executed by a RUN command.
  80         *
  81         */
  82                    0x1FF5FC34, 0xEFEABC34, 0x1FB57C35, /* last */
  83        /*
  84         * Burst Read. (Offset 8 in UPM RAM)
  85         */
  86        0x1F0DFC04, 0xEEAFBC04, 0x10AF7C04, 0xF0AFFC00,
  87        0xF0AFFC00, 0xF1AFFC00, 0xEFBAFC00, 0x1FF5FC47, /* last */
  88        _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_,
  89        _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_,
  90        /*
  91         * Single Write. (Offset 18 in UPM RAM)
  92         */
  93        0x1F2DFC04, 0xEEABBC00, 0x01B27C04, 0x1FF5FC47, /* last */
  94        _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_,
  95        /*
  96         * Burst Write. (Offset 20 in UPM RAM)
  97         */
  98        0x1F0DFC04, 0xEEABBC00, 0x10A77C00, 0xF0AFFC00,
  99        0xF0AFFC00, 0xE1BAFC04, 0x01FF5FC47, /* last */
 100                                            _NOT_USED_,
 101        _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_,
 102        _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_,
 103        /*
 104         * Refresh  (Offset 30 in UPM RAM)
 105         */
 106        0x1FFD7C84, 0xFFFFFC04, 0xFFFFFC04, 0xFFFFFC04,
 107        0xFFFFFC84, 0xFFFFFC07, /* last */
 108                                _NOT_USED_, _NOT_USED_,
 109        _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_,
 110        /*
 111         * Exception. (Offset 3c in UPM RAM)
 112         */
 113        0x7FFFFC07, /* last */
 114                    0xFFFFFCFF, 0xFFFFFCFF, 0xFFFFFCFF,
 115#endif
 116#ifdef CONFIG_SYS_MEMORY_7E
 117        /*
 118         * Single Read. (Offset 0 in UPM RAM)
 119         */
 120        0x0E2DBC04, 0x11AF7C04, 0xEFBAFC00, 0x1FF5FC47, /* last */
 121        _NOT_USED_,
 122        /*
 123         * SDRAM Initialization (offset 5 in UPM RAM)
 124         *
 125         * This is no UPM entry point. The following definition uses
 126         * the remaining space to establish an initialization
 127         * sequence, which is executed by a RUN command.
 128         *
 129         */
 130                    0x1FF5FC34, 0xEFEABC34, 0x1FB57C35, /* last */
 131        /*
 132         * Burst Read. (Offset 8 in UPM RAM)
 133         */
 134        0x0E2DBC04, 0x10AF7C04, 0xF0AFFC00, 0xF0AFFC00,
 135        0xF1AFFC00, 0xEFBAFC00, 0x1FF5FC47, /* last */
 136                                            _NOT_USED_,
 137        _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_,
 138        _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_,
 139        /*
 140         * Single Write. (Offset 18 in UPM RAM)
 141         */
 142        0x0E29BC04, 0x01B27C04, 0x1FF5FC47, /* last */
 143                                            _NOT_USED_,
 144        _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_,
 145        /*
 146         * Burst Write. (Offset 20 in UPM RAM)
 147         */
 148        0x0E29BC04, 0x10A77C00, 0xF0AFFC00, 0xF0AFFC00,
 149        0xE1BAFC04, 0x1FF5FC47, /* last */
 150                                _NOT_USED_, _NOT_USED_,
 151        _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_,
 152        _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_,
 153        /*
 154         * Refresh  (Offset 30 in UPM RAM)
 155         */
 156        0x1FFD7C84, 0xFFFFFC04, 0xFFFFFC04, 0xFFFFFC04,
 157        0xFFFFFC84, 0xFFFFFC07, /* last */
 158                                _NOT_USED_, _NOT_USED_,
 159        _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_,
 160        /*
 161         * Exception. (Offset 3c in UPM RAM)
 162         */
 163        0x7FFFFC07, /* last */
 164                    0xFFFFFCFF, 0xFFFFFCFF, 0xFFFFFCFF,
 165#endif
 166};
 167
 168/*
 169 * Check Board Identity:
 170 *
 171 */
 172
 173/***********************************************************************
 174F* Function:     int checkboard (void) P*A*Z*
 175 *
 176P* Parameters:   none
 177P*
 178P* Returnvalue:  int - 0 is always returned
 179 *
 180Z* Intention:    This function is the checkboard() method implementation
 181Z*               for the lwmon board.  Only a standard message is printed.
 182 *
 183D* Design:       wd@denx.de
 184C* Coding:       wd@denx.de
 185V* Verification: dzu@denx.de
 186 ***********************************************************************/
 187int checkboard (void)
 188{
 189        puts ("Board: LICCON Konsole LCD3\n");
 190        return (0);
 191}
 192
 193/***********************************************************************
 194F* Function:     phys_size_t initdram (int board_type) P*A*Z*
 195 *
 196P* Parameters:   int board_type
 197P*                - Usually type of the board - ignored here.
 198P*
 199P* Returnvalue:  long int
 200P*                - Size of initialized memory
 201 *
 202Z* Intention:    This function is the initdram() method implementation
 203Z*               for the lwmon board.
 204Z*               The memory controller is initialized to access the
 205Z*               DRAM.
 206 *
 207D* Design:       wd@denx.de
 208C* Coding:       wd@denx.de
 209V* Verification: dzu@denx.de
 210 ***********************************************************************/
 211phys_size_t initdram (int board_type)
 212{
 213        volatile immap_t *immr = (immap_t *) CONFIG_SYS_IMMR;
 214        volatile memctl8xx_t *memctl = &immr->im_memctl;
 215        long int size_b0;
 216        long int size8, size9;
 217        int i;
 218
 219        /*
 220         * Configure UPMA for SDRAM
 221         */
 222        upmconfig (UPMA, (uint *)sdram_table, sizeof(sdram_table)/sizeof(uint));
 223
 224        memctl->memc_mptpr = CONFIG_SYS_MPTPR;
 225
 226        /* burst length=4, burst type=sequential, CAS latency=2 */
 227        memctl->memc_mar = CONFIG_SYS_MAR;
 228
 229        /*
 230         * Map controller bank 3 to the SDRAM bank at preliminary address.
 231         */
 232        memctl->memc_or3 = CONFIG_SYS_OR3_PRELIM;
 233        memctl->memc_br3 = CONFIG_SYS_BR3_PRELIM;
 234
 235        /* initialize memory address register */
 236        memctl->memc_mamr = CONFIG_SYS_MAMR_8COL;       /* refresh not enabled yet */
 237
 238        /* mode initialization (offset 5) */
 239        udelay (200);                           /* 0x80006105 */
 240        memctl->memc_mcr = MCR_OP_RUN | MCR_MB_CS3 | MCR_MLCF (1) | MCR_MAD (0x05);
 241
 242        /* run 2 refresh sequence with 4-beat refresh burst (offset 0x30) */
 243        udelay (1);                             /* 0x80006130 */
 244        memctl->memc_mcr = MCR_OP_RUN | MCR_MB_CS3 | MCR_MLCF (1) | MCR_MAD (0x30);
 245        udelay (1);                             /* 0x80006130 */
 246        memctl->memc_mcr = MCR_OP_RUN | MCR_MB_CS3 | MCR_MLCF (1) | MCR_MAD (0x30);
 247
 248        udelay (1);                             /* 0x80006106 */
 249        memctl->memc_mcr = MCR_OP_RUN | MCR_MB_CS3 | MCR_MLCF (1) | MCR_MAD (0x06);
 250
 251        memctl->memc_mamr |= MAMR_PTAE; /* refresh enabled */
 252
 253        udelay (200);
 254
 255        /* Need at least 10 DRAM accesses to stabilize */
 256        for (i = 0; i < 10; ++i) {
 257                volatile unsigned long *addr =
 258                        (volatile unsigned long *) SDRAM_BASE3_PRELIM;
 259                unsigned long val;
 260
 261                val = *(addr + i);
 262                *(addr + i) = val;
 263        }
 264
 265        /*
 266         * Check Bank 0 Memory Size for re-configuration
 267         *
 268         * try 8 column mode
 269         */
 270        size8 = dram_size (CONFIG_SYS_MAMR_8COL, (long *)SDRAM_BASE3_PRELIM, SDRAM_MAX_SIZE);
 271
 272        udelay (1000);
 273
 274        /*
 275         * try 9 column mode
 276         */
 277        size9 = dram_size (CONFIG_SYS_MAMR_9COL, (long *)SDRAM_BASE3_PRELIM, SDRAM_MAX_SIZE);
 278
 279        if (size8 < size9) {            /* leave configuration at 9 columns */
 280                size_b0 = size9;
 281                memctl->memc_mamr = CONFIG_SYS_MAMR_9COL | MAMR_PTAE;
 282                udelay (500);
 283        } else {                        /* back to 8 columns            */
 284                size_b0 = size8;
 285                memctl->memc_mamr = CONFIG_SYS_MAMR_8COL | MAMR_PTAE;
 286                udelay (500);
 287        }
 288
 289        /*
 290         * Final mapping:
 291         */
 292
 293        memctl->memc_or3 = ((-size_b0) & 0xFFFF0000) |
 294                        OR_CSNT_SAM | OR_G5LS | SDRAM_TIMING;
 295        memctl->memc_br3 = (CONFIG_SYS_SDRAM_BASE & BR_BA_MSK) | BR_MS_UPMA | BR_V;
 296        udelay (1000);
 297
 298        return (size_b0);
 299}
 300
 301/***********************************************************************
 302F* Function:     static long int dram_size (long int mamr_value,
 303F*                                          long int *base,
 304F*                                          long int maxsize) P*A*Z*
 305 *
 306P* Parameters:   long int mamr_value
 307P*                - Value for MAMR for the test
 308P*               long int *base
 309P*                - Base address for the test
 310P*               long int maxsize
 311P*                - Maximum size to test for
 312P*
 313P* Returnvalue:  long int
 314P*                - Size of probed memory
 315 *
 316Z* Intention:    Check memory range for valid RAM. A simple memory test
 317Z*               determines the actually available RAM size between
 318Z*               addresses `base' and `base + maxsize'. Some (not all)
 319Z*               hardware errors are detected:
 320Z*                - short between address lines
 321Z*                - short between data lines
 322 *
 323D* Design:       wd@denx.de
 324C* Coding:       wd@denx.de
 325V* Verification: dzu@denx.de
 326 ***********************************************************************/
 327static long int dram_size (long int mamr_value, long int *base, long int maxsize)
 328{
 329        volatile immap_t *immr = (immap_t *) CONFIG_SYS_IMMR;
 330        volatile memctl8xx_t *memctl = &immr->im_memctl;
 331
 332        memctl->memc_mamr = mamr_value;
 333
 334        return (get_ram_size(base, maxsize));
 335}
 336
 337/* ------------------------------------------------------------------------- */
 338
 339#ifndef PB_ENET_TENA
 340# define PB_ENET_TENA   ((uint)0x00002000)      /* PB 18 */
 341#endif
 342
 343/***********************************************************************
 344F* Function:     int board_early_init_f (void) P*A*Z*
 345 *
 346P* Parameters:   none
 347P*
 348P* Returnvalue:  int
 349P*                - 0 is always returned.
 350 *
 351Z* Intention:    This function is the board_early_init_f() method implementation
 352Z*               for the lwmon board.
 353Z*               Disable Ethernet TENA on Port B.
 354 *
 355D* Design:       wd@denx.de
 356C* Coding:       wd@denx.de
 357V* Verification: dzu@denx.de
 358 ***********************************************************************/
 359int board_early_init_f (void)
 360{
 361        volatile immap_t *immr = (immap_t *) CONFIG_SYS_IMMR;
 362
 363        /* Disable Ethernet TENA on Port B
 364         * Necessary because of pull up in COM3 port.
 365         *
 366         * This is just a preliminary fix, intended to turn off TENA
 367         * as soon as possible to avoid noise on the network. Once
 368         * I2C is running we will make sure the interface is
 369         * correctly initialized.
 370         */
 371        immr->im_cpm.cp_pbpar &= ~PB_ENET_TENA;
 372        immr->im_cpm.cp_pbodr &= ~PB_ENET_TENA;
 373        immr->im_cpm.cp_pbdat &= ~PB_ENET_TENA; /* set to 0 = disabled */
 374        immr->im_cpm.cp_pbdir |= PB_ENET_TENA;
 375
 376        return (0);
 377}
 378
 379/* ------------------------------------------------------------------------- */
 380
 381/***********************************************************************
 382F* Function:     void reset_phy (void) P*A*Z*
 383 *
 384P* Parameters:   none
 385P*
 386P* Returnvalue:  none
 387 *
 388Z* Intention:    Reset the PHY.  In the lwmon case we do this by the
 389Z*               signaling the PIC I/O expander.
 390 *
 391D* Design:       wd@denx.de
 392C* Coding:       wd@denx.de
 393V* Verification: dzu@denx.de
 394 ***********************************************************************/
 395void reset_phy (void)
 396{
 397        uchar c;
 398
 399#ifdef DEBUG
 400        printf ("### Switch on Ethernet for SCC2 ###\n");
 401#endif
 402        c = pic_read (0x61);
 403#ifdef DEBUG
 404        printf ("Old PIC read: reg_61 = 0x%02x\n", c);
 405#endif
 406        c |= 0x40;                                      /* disable COM3 */
 407        c &= ~0x80;                                     /* enable Ethernet */
 408        pic_write (0x61, c);
 409#ifdef DEBUG
 410        c = pic_read (0x61);
 411        printf ("New PIC read: reg_61 = 0x%02x\n", c);
 412#endif
 413        udelay (1000);
 414}
 415
 416
 417/*------------------------- Keyboard controller -----------------------*/
 418/* command codes */
 419#define KEYBD_CMD_READ_KEYS     0x01
 420#define KEYBD_CMD_READ_VERSION  0x02
 421#define KEYBD_CMD_READ_STATUS   0x03
 422#define KEYBD_CMD_RESET_ERRORS  0x10
 423
 424/* status codes */
 425#define KEYBD_STATUS_MASK       0x3F
 426#define KEYBD_STATUS_H_RESET    0x20
 427#define KEYBD_STATUS_BROWNOUT   0x10
 428#define KEYBD_STATUS_WD_RESET   0x08
 429#define KEYBD_STATUS_OVERLOAD   0x04
 430#define KEYBD_STATUS_ILLEGAL_WR 0x02
 431#define KEYBD_STATUS_ILLEGAL_RD 0x01
 432
 433/* Number of bytes returned from Keyboard Controller */
 434#define KEYBD_VERSIONLEN        2       /* version information */
 435#define KEYBD_DATALEN           9       /* normal key scan data */
 436
 437/* maximum number of "magic" key codes that can be assigned */
 438
 439static uchar kbd_addr = CONFIG_SYS_I2C_KEYBD_ADDR;
 440
 441static uchar *key_match (uchar *);
 442
 443#define KEYBD_SET_DEBUGMODE     '#'     /* Magic key to enable debug output */
 444
 445/***********************************************************************
 446F* Function:     int board_postclk_init (void) P*A*Z*
 447 *
 448P* Parameters:   none
 449P*
 450P* Returnvalue:  int
 451P*                - 0 is always returned.
 452 *
 453Z* Intention:    This function is the board_postclk_init() method implementation
 454Z*               for the lwmon board.
 455 *
 456 ***********************************************************************/
 457int board_postclk_init (void)
 458{
 459        kbd_init();
 460
 461#ifdef CONFIG_MODEM_SUPPORT
 462        if (key_pressed()) {
 463                disable_putc(); /* modem doesn't understand banner etc */
 464                gd->do_mdm_init = 1;
 465        }
 466#endif
 467
 468        return (0);
 469}
 470
 471struct serial_device * default_serial_console (void)
 472{
 473        return gd->do_mdm_init ? &serial_scc_device : &serial_smc_device;
 474}
 475
 476static void kbd_init (void)
 477{
 478        uchar kbd_data[KEYBD_DATALEN];
 479        uchar tmp_data[KEYBD_DATALEN];
 480        uchar val, errcd;
 481        int i;
 482
 483        i2c_init (CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE);
 484
 485        gd->kbd_status = 0;
 486
 487        /* Forced by PIC. Delays <= 175us loose */
 488        udelay(1000);
 489
 490        /* Read initial keyboard error code */
 491        val = KEYBD_CMD_READ_STATUS;
 492        i2c_write (kbd_addr, 0, 0, &val, 1);
 493        i2c_read (kbd_addr, 0, 0, &errcd, 1);
 494        /* clear unused bits */
 495        errcd &= KEYBD_STATUS_MASK;
 496        /* clear "irrelevant" bits. Recommended by Martin Rajek, LWN */
 497        errcd &= ~(KEYBD_STATUS_H_RESET|KEYBD_STATUS_BROWNOUT);
 498        if (errcd) {
 499                gd->kbd_status |= errcd << 8;
 500        }
 501        /* Reset error code and verify */
 502        val = KEYBD_CMD_RESET_ERRORS;
 503        i2c_write (kbd_addr, 0, 0, &val, 1);
 504        udelay(1000);   /* delay NEEDED by keyboard PIC !!! */
 505
 506        val = KEYBD_CMD_READ_STATUS;
 507        i2c_write (kbd_addr, 0, 0, &val, 1);
 508        i2c_read (kbd_addr, 0, 0, &val, 1);
 509
 510        val &= KEYBD_STATUS_MASK;       /* clear unused bits */
 511        if (val) {                      /* permanent error, report it */
 512                gd->kbd_status |= val;
 513                return;
 514        }
 515
 516        /*
 517         * Read current keyboard state.
 518         *
 519         * After the error reset it may take some time before the
 520         * keyboard PIC picks up a valid keyboard scan - the total
 521         * scan time is approx. 1.6 ms (information by Martin Rajek,
 522         * 28 Sep 2002). We read a couple of times for the keyboard
 523         * to stabilize, using a big enough delay.
 524         * 10 times should be enough. If the data is still changing,
 525         * we use what we get :-(
 526         */
 527
 528        memset (tmp_data, 0xFF, KEYBD_DATALEN); /* impossible value */
 529        for (i=0; i<10; ++i) {
 530                val = KEYBD_CMD_READ_KEYS;
 531                i2c_write (kbd_addr, 0, 0, &val, 1);
 532                i2c_read (kbd_addr, 0, 0, kbd_data, KEYBD_DATALEN);
 533
 534                if (memcmp(kbd_data, tmp_data, KEYBD_DATALEN) == 0) {
 535                        /* consistent state, done */
 536                        break;
 537                }
 538                /* remeber last state, delay, and retry */
 539                memcpy (tmp_data, kbd_data, KEYBD_DATALEN);
 540                udelay (5000);
 541        }
 542}
 543
 544/***********************************************************************
 545F* Function:     int misc_init_r (void) P*A*Z*
 546 *
 547P* Parameters:   none
 548P*
 549P* Returnvalue:  int
 550P*                - 0 is always returned, even in the case of a keyboard
 551P*                    error.
 552 *
 553Z* Intention:    This function is the misc_init_r() method implementation
 554Z*               for the lwmon board.
 555Z*               The keyboard controller is initialized and the result
 556Z*               of a read copied to the environment variable "keybd".
 557Z*               If KEYBD_SET_DEBUGMODE is defined, a check is made for
 558Z*               this key, and if found display to the LCD will be enabled.
 559Z*               The keys in "keybd" are checked against the magic
 560Z*               keycommands defined in the environment.
 561Z*               See also key_match().
 562 *
 563D* Design:       wd@denx.de
 564C* Coding:       wd@denx.de
 565V* Verification: dzu@denx.de
 566 ***********************************************************************/
 567int misc_init_r (void)
 568{
 569        uchar kbd_data[KEYBD_DATALEN];
 570        char keybd_env[2 * KEYBD_DATALEN + 1];
 571        uchar kbd_init_status = gd->kbd_status >> 8;
 572        uchar kbd_status = gd->kbd_status;
 573        uchar val;
 574        char *str;
 575        int i;
 576
 577        if (kbd_init_status) {
 578                printf ("KEYBD: Error %02X\n", kbd_init_status);
 579        }
 580        if (kbd_status) {               /* permanent error, report it */
 581                printf ("*** Keyboard error code %02X ***\n", kbd_status);
 582                sprintf (keybd_env, "%02X", kbd_status);
 583                setenv ("keybd", keybd_env);
 584                return 0;
 585        }
 586
 587        /*
 588         * Now we know that we have a working  keyboard,  so  disable
 589         * all output to the LCD except when a key press is detected.
 590         */
 591
 592        if ((console_assign (stdout, "serial") < 0) ||
 593                (console_assign (stderr, "serial") < 0)) {
 594                printf ("Can't assign serial port as output device\n");
 595        }
 596
 597        /* Read Version */
 598        val = KEYBD_CMD_READ_VERSION;
 599        i2c_write (kbd_addr, 0, 0, &val, 1);
 600        i2c_read (kbd_addr, 0, 0, kbd_data, KEYBD_VERSIONLEN);
 601        printf ("KEYBD: Version %d.%d\n", kbd_data[0], kbd_data[1]);
 602
 603        /* Read current keyboard state */
 604        val = KEYBD_CMD_READ_KEYS;
 605        i2c_write (kbd_addr, 0, 0, &val, 1);
 606        i2c_read (kbd_addr, 0, 0, kbd_data, KEYBD_DATALEN);
 607
 608        for (i = 0; i < KEYBD_DATALEN; ++i) {
 609                sprintf (keybd_env + i + i, "%02X", kbd_data[i]);
 610        }
 611        setenv ("keybd", keybd_env);
 612
 613        str = strdup ((char *)key_match (kbd_data));    /* decode keys */
 614#ifdef KEYBD_SET_DEBUGMODE
 615        if (kbd_data[0] == KEYBD_SET_DEBUGMODE) {       /* set debug mode */
 616                if ((console_assign (stdout, "lcd") < 0) ||
 617                        (console_assign (stderr, "lcd") < 0)) {
 618                        printf ("Can't assign LCD display as output device\n");
 619                }
 620        }
 621#endif /* KEYBD_SET_DEBUGMODE */
 622#ifdef CONFIG_PREBOOT   /* automatically configure "preboot" command on key match */
 623        setenv ("preboot", str);        /* set or delete definition */
 624#endif /* CONFIG_PREBOOT */
 625        if (str != NULL) {
 626                free (str);
 627        }
 628        return (0);
 629}
 630
 631#ifdef CONFIG_PREBOOT
 632
 633static uchar kbd_magic_prefix[] = "key_magic";
 634static uchar kbd_command_prefix[] = "key_cmd";
 635
 636static int compare_magic (uchar *kbd_data, uchar *str)
 637{
 638        uchar compare[KEYBD_DATALEN-1];
 639        char *nxt;
 640        int i;
 641
 642        /* Don't include modifier byte */
 643        memcpy (compare, kbd_data+1, KEYBD_DATALEN-1);
 644
 645        for (; str != NULL; str = (*nxt) ? (uchar *)(nxt+1) : (uchar *)nxt) {
 646                uchar c;
 647                int k;
 648
 649                c = (uchar) simple_strtoul ((char *)str, (char **) (&nxt), 16);
 650
 651                if (str == (uchar *)nxt) {      /* invalid character */
 652                        break;
 653                }
 654
 655                /*
 656                 * Check if this key matches the input.
 657                 * Set matches to zero, so they match only once
 658                 * and we can find duplicates or extra keys
 659                 */
 660                for (k = 0; k < sizeof(compare); ++k) {
 661                        if (compare[k] == '\0') /* only non-zero entries */
 662                                continue;
 663                        if (c == compare[k]) {  /* found matching key */
 664                                compare[k] = '\0';
 665                                break;
 666                        }
 667                }
 668                if (k == sizeof(compare)) {
 669                        return -1;              /* unmatched key */
 670                }
 671        }
 672
 673        /*
 674         * A full match leaves no keys in the `compare' array,
 675         */
 676        for (i = 0; i < sizeof(compare); ++i) {
 677                if (compare[i])
 678                {
 679                        return -1;
 680                }
 681        }
 682
 683        return 0;
 684}
 685
 686/***********************************************************************
 687F* Function:     static uchar *key_match (uchar *kbd_data) P*A*Z*
 688 *
 689P* Parameters:   uchar *kbd_data
 690P*                - The keys to match against our magic definitions
 691P*
 692P* Returnvalue:  uchar *
 693P*                - != NULL: Pointer to the corresponding command(s)
 694P*                     NULL: No magic is about to happen
 695 *
 696Z* Intention:    Check if pressed key(s) match magic sequence,
 697Z*               and return the command string associated with that key(s).
 698Z*
 699Z*               If no key press was decoded, NULL is returned.
 700Z*
 701Z*               Note: the first character of the argument will be
 702Z*                     overwritten with the "magic charcter code" of the
 703Z*                     decoded key(s), or '\0'.
 704Z*
 705Z*               Note: the string points to static environment data
 706Z*                     and must be saved before you call any function that
 707Z*                     modifies the environment.
 708 *
 709D* Design:       wd@denx.de
 710C* Coding:       wd@denx.de
 711V* Verification: dzu@denx.de
 712 ***********************************************************************/
 713static uchar *key_match (uchar *kbd_data)
 714{
 715        char magic[sizeof (kbd_magic_prefix) + 1];
 716        uchar *suffix;
 717        char *kbd_magic_keys;
 718
 719        /*
 720         * The following string defines the characters that can pe appended
 721         * to "key_magic" to form the names of environment variables that
 722         * hold "magic" key codes, i. e. such key codes that can cause
 723         * pre-boot actions. If the string is empty (""), then only
 724         * "key_magic" is checked (old behaviour); the string "125" causes
 725         * checks for "key_magic1", "key_magic2" and "key_magic5", etc.
 726         */
 727        if ((kbd_magic_keys = getenv ("magic_keys")) == NULL)
 728                kbd_magic_keys = "";
 729
 730        /* loop over all magic keys;
 731         * use '\0' suffix in case of empty string
 732         */
 733        for (suffix=(uchar *)kbd_magic_keys; *suffix || suffix==(uchar *)kbd_magic_keys; ++suffix) {
 734                sprintf (magic, "%s%c", kbd_magic_prefix, *suffix);
 735#if 0
 736                printf ("### Check magic \"%s\"\n", magic);
 737#endif
 738                if (compare_magic(kbd_data, (uchar *)getenv(magic)) == 0) {
 739                        char cmd_name[sizeof (kbd_command_prefix) + 1];
 740                        char *cmd;
 741
 742                        sprintf (cmd_name, "%s%c", kbd_command_prefix, *suffix);
 743
 744                        cmd = getenv (cmd_name);
 745#if 0
 746                        printf ("### Set PREBOOT to $(%s): \"%s\"\n",
 747                                        cmd_name, cmd ? cmd : "<<NULL>>");
 748#endif
 749                        *kbd_data = *suffix;
 750                        return ((uchar *)cmd);
 751                }
 752        }
 753#if 0
 754        printf ("### Delete PREBOOT\n");
 755#endif
 756        *kbd_data = '\0';
 757        return (NULL);
 758}
 759#endif /* CONFIG_PREBOOT */
 760
 761#ifdef CONFIG_LCD_INFO
 762#include <lcd.h>
 763#include <version.h>
 764#include <timestamp.h>
 765
 766void lcd_show_board_info(void)
 767{
 768        char temp[32];
 769
 770        lcd_printf ("%s (%s - %s)\n", U_BOOT_VERSION, U_BOOT_DATE, U_BOOT_TIME);
 771        lcd_printf ("(C) 2008 DENX Software Engineering GmbH\n");
 772        lcd_printf ("    Wolfgang DENK, wd@denx.de\n");
 773#ifdef CONFIG_LCD_INFO_BELOW_LOGO
 774        lcd_printf ("MPC823 CPU at %s MHz\n",
 775                strmhz(temp, gd->cpu_clk));
 776        lcd_printf ("  %ld MB RAM, %ld MB Flash\n",
 777                gd->ram_size >> 20,
 778                gd->bd->bi_flashsize >> 20 );
 779#else
 780        /* leave one blank line */
 781        lcd_printf ("\nMPC823 CPU at %s MHz, %ld MB RAM, %ld MB Flash\n",
 782                strmhz(temp, gd->cpu_clk),
 783                gd->ram_size >> 20,
 784                gd->bd->bi_flashsize >> 20 );
 785#endif /* CONFIG_LCD_INFO_BELOW_LOGO */
 786}
 787#endif /* CONFIG_LCD_INFO */
 788
 789/*---------------Board Special Commands: PIC read/write ---------------*/
 790
 791#if defined(CONFIG_CMD_BSP)
 792/***********************************************************************
 793F* Function:     int do_pic (cmd_tbl_t *cmdtp, int flag,
 794F*                           int argc, char * const argv[]) P*A*Z*
 795 *
 796P* Parameters:   cmd_tbl_t *cmdtp
 797P*                - Pointer to our command table entry
 798P*               int flag
 799P*                - If the CMD_FLAG_REPEAT bit is set, then this call is
 800P*                  a repetition
 801P*               int argc
 802P*                - Argument count
 803P*               char * const argv[]
 804P*                - Array of the actual arguments
 805P*
 806P* Returnvalue:  int
 807P*                - 0  The command was handled successfully
 808P*                  1  An error occurred
 809 *
 810Z* Intention:    Implement the "pic [read|write]" commands.
 811Z*               The read subcommand takes one argument, the register,
 812Z*               whereas the write command takes two, the register and
 813Z*               the new value.
 814 *
 815D* Design:       wd@denx.de
 816C* Coding:       wd@denx.de
 817V* Verification: dzu@denx.de
 818 ***********************************************************************/
 819int do_pic (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 820{
 821        uchar reg, val;
 822
 823        switch (argc) {
 824        case 3:                                 /* PIC read reg */
 825                if (strcmp (argv[1], "read") != 0)
 826                        break;
 827
 828                reg = simple_strtoul (argv[2], NULL, 16);
 829
 830                printf ("PIC read: reg %02x: %02x\n\n", reg, pic_read (reg));
 831
 832                return 0;
 833        case 4:                                 /* PIC write reg val */
 834                if (strcmp (argv[1], "write") != 0)
 835                        break;
 836
 837                reg = simple_strtoul (argv[2], NULL, 16);
 838                val = simple_strtoul (argv[3], NULL, 16);
 839
 840                printf ("PIC write: reg %02x val 0x%02x: %02x => ",
 841                                reg, val, pic_read (reg));
 842                pic_write (reg, val);
 843                printf ("%02x\n\n", pic_read (reg));
 844                return 0;
 845        default:
 846                break;
 847        }
 848        return cmd_usage(cmdtp);
 849}
 850U_BOOT_CMD(
 851        pic,    4,      1,      do_pic,
 852        "read and write PIC registers",
 853        "read  reg      - read PIC register `reg'\n"
 854        "pic write reg val  - write value `val' to PIC register `reg'"
 855);
 856
 857/***********************************************************************
 858F* Function:     int do_kbd (cmd_tbl_t *cmdtp, int flag,
 859F*                           int argc, char * const argv[]) P*A*Z*
 860 *
 861P* Parameters:   cmd_tbl_t *cmdtp
 862P*                - Pointer to our command table entry
 863P*               int flag
 864P*                - If the CMD_FLAG_REPEAT bit is set, then this call is
 865P*                  a repetition
 866P*               int argc
 867P*                - Argument count
 868P*               char * const argv[]
 869P*                - Array of the actual arguments
 870P*
 871P* Returnvalue:  int
 872P*                - 0 is always returned.
 873 *
 874Z* Intention:    Implement the "kbd" command.
 875Z*               The keyboard status is read.  The result is printed on
 876Z*               the console and written into the "keybd" environment
 877Z*               variable.
 878 *
 879D* Design:       wd@denx.de
 880C* Coding:       wd@denx.de
 881V* Verification: dzu@denx.de
 882 ***********************************************************************/
 883int do_kbd (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 884{
 885        uchar kbd_data[KEYBD_DATALEN];
 886        char keybd_env[2 * KEYBD_DATALEN + 1];
 887        uchar val;
 888        int i;
 889
 890#if 0 /* Done in kbd_init */
 891        i2c_init (CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE);
 892#endif
 893
 894        /* Read keys */
 895        val = KEYBD_CMD_READ_KEYS;
 896        i2c_write (kbd_addr, 0, 0, &val, 1);
 897        i2c_read (kbd_addr, 0, 0, kbd_data, KEYBD_DATALEN);
 898
 899        puts ("Keys:");
 900        for (i = 0; i < KEYBD_DATALEN; ++i) {
 901                sprintf (keybd_env + i + i, "%02X", kbd_data[i]);
 902                printf (" %02x", kbd_data[i]);
 903        }
 904        putc ('\n');
 905        setenv ("keybd", keybd_env);
 906        return 0;
 907}
 908
 909U_BOOT_CMD(
 910        kbd,    1,      1,      do_kbd,
 911        "read keyboard status",
 912        ""
 913);
 914
 915/* Read and set LSB switch */
 916#define CONFIG_SYS_PC_TXD1_ENA          0x0008          /* PC.12 */
 917
 918/***********************************************************************
 919F* Function:     int do_lsb (cmd_tbl_t *cmdtp, int flag,
 920F*                           int argc, char * const argv[]) P*A*Z*
 921 *
 922P* Parameters:   cmd_tbl_t *cmdtp
 923P*                - Pointer to our command table entry
 924P*               int flag
 925P*                - If the CMD_FLAG_REPEAT bit is set, then this call is
 926P*                  a repetition
 927P*               int argc
 928P*                - Argument count
 929P*               char * const argv[]
 930P*                - Array of the actual arguments
 931P*
 932P* Returnvalue:  int
 933P*                - 0  The command was handled successfully
 934P*                  1  An error occurred
 935 *
 936Z* Intention:    Implement the "lsb [on|off]" commands.
 937Z*               The lsb is switched according to the first parameter by
 938Z*               by signaling the PIC I/O expander.
 939Z*               Called with no arguments, the current setting is
 940Z*               printed.
 941 *
 942D* Design:       wd@denx.de
 943C* Coding:       wd@denx.de
 944V* Verification: dzu@denx.de
 945 ***********************************************************************/
 946int do_lsb (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 947{
 948        uchar val;
 949        immap_t *immr = (immap_t *) CONFIG_SYS_IMMR;
 950
 951        switch (argc) {
 952        case 1:                                 /* lsb - print setting */
 953                val = pic_read (0x60);
 954                printf ("LSB is o%s\n", (val & 0x20) ? "n" : "ff");
 955                return 0;
 956        case 2:                                 /* lsb on or lsb off - set switch */
 957                val = pic_read (0x60);
 958
 959                if (strcmp (argv[1], "on") == 0) {
 960                        val |= 0x20;
 961                        immr->im_ioport.iop_pcpar &= ~(CONFIG_SYS_PC_TXD1_ENA);
 962                        immr->im_ioport.iop_pcdat |= CONFIG_SYS_PC_TXD1_ENA;
 963                        immr->im_ioport.iop_pcdir |= CONFIG_SYS_PC_TXD1_ENA;
 964                } else if (strcmp (argv[1], "off") == 0) {
 965                        val &= ~0x20;
 966                        immr->im_ioport.iop_pcpar &= ~(CONFIG_SYS_PC_TXD1_ENA);
 967                        immr->im_ioport.iop_pcdat &= ~(CONFIG_SYS_PC_TXD1_ENA);
 968                        immr->im_ioport.iop_pcdir |= CONFIG_SYS_PC_TXD1_ENA;
 969                } else {
 970                        break;
 971                }
 972                pic_write (0x60, val);
 973                return 0;
 974        default:
 975                break;
 976        }
 977        return cmd_usage(cmdtp);
 978}
 979
 980U_BOOT_CMD(
 981        lsb,    2,      1,      do_lsb,
 982        "check and set LSB switch",
 983        "on  - switch LSB on\n"
 984        "lsb off - switch LSB off\n"
 985        "lsb     - print current setting"
 986);
 987
 988#endif
 989
 990/*----------------------------- Utilities -----------------------------*/
 991/***********************************************************************
 992F* Function:     uchar pic_read (uchar reg) P*A*Z*
 993 *
 994P* Parameters:   uchar reg
 995P*                - Register to read
 996P*
 997P* Returnvalue:  uchar
 998P*                - Value read from register
 999 *
1000Z* Intention:    Read a register from the PIC I/O expander.
1001 *
1002D* Design:       wd@denx.de
1003C* Coding:       wd@denx.de
1004V* Verification: dzu@denx.de
1005 ***********************************************************************/
1006uchar pic_read (uchar reg)
1007{
1008        return (i2c_reg_read (CONFIG_SYS_I2C_PICIO_ADDR, reg));
1009}
1010
1011/***********************************************************************
1012F* Function:     void pic_write (uchar reg, uchar val) P*A*Z*
1013 *
1014P* Parameters:   uchar reg
1015P*                - Register to read
1016P*               uchar val
1017P*                - Value to write
1018P*
1019P* Returnvalue:  none
1020 *
1021Z* Intention:    Write to a register on the PIC I/O expander.
1022 *
1023D* Design:       wd@denx.de
1024C* Coding:       wd@denx.de
1025V* Verification: dzu@denx.de
1026 ***********************************************************************/
1027void pic_write (uchar reg, uchar val)
1028{
1029        i2c_reg_write (CONFIG_SYS_I2C_PICIO_ADDR, reg, val);
1030}
1031
1032/*---------------------- Board Control Functions ----------------------*/
1033/***********************************************************************
1034F* Function:     void board_poweroff (void) P*A*Z*
1035 *
1036P* Parameters:   none
1037P*
1038P* Returnvalue:  none
1039 *
1040Z* Intention:    Turn off the battery power and loop endless, so this
1041Z*               should better be the last function you call...
1042 *
1043D* Design:       wd@denx.de
1044C* Coding:       wd@denx.de
1045V* Verification: dzu@denx.de
1046 ***********************************************************************/
1047void board_poweroff (void)
1048{
1049    /* Turn battery off */
1050    ((volatile immap_t *)CONFIG_SYS_IMMR)->im_ioport.iop_pcdat &= ~(1 << (31 - 13));
1051
1052    while (1);
1053}
1054
1055#ifdef CONFIG_MODEM_SUPPORT
1056static int key_pressed(void)
1057{
1058        uchar kbd_data[KEYBD_DATALEN];
1059        uchar val;
1060
1061        /* Read keys */
1062        val = KEYBD_CMD_READ_KEYS;
1063        i2c_write (kbd_addr, 0, 0, &val, 1);
1064        i2c_read (kbd_addr, 0, 0, kbd_data, KEYBD_DATALEN);
1065
1066        return (compare_magic(kbd_data, (uchar *)CONFIG_MODEM_KEY_MAGIC) == 0);
1067}
1068#endif  /* CONFIG_MODEM_SUPPORT */
1069
1070#ifdef CONFIG_POST
1071/*
1072 * Returns 1 if keys pressed to start the power-on long-running tests
1073 * Called from board_init_f().
1074 */
1075int post_hotkeys_pressed(void)
1076{
1077        uchar kbd_data[KEYBD_DATALEN];
1078        uchar val;
1079
1080        /* Read keys */
1081        val = KEYBD_CMD_READ_KEYS;
1082        i2c_write (kbd_addr, 0, 0, &val, 1);
1083        i2c_read (kbd_addr, 0, 0, kbd_data, KEYBD_DATALEN);
1084
1085        return (compare_magic(kbd_data, (uchar *)CONFIG_POST_KEY_MAGIC) == 0);
1086}
1087#endif
1088