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