]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - board/lwmon/lwmon.c
Merge branch 'master' of git://git.denx.de/u-boot-x86
[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  *
11 D* Design:        wd@denx.de
12 C* Coding:        wd@denx.de
13 V* 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
47 DECLARE_GLOBAL_DATA_PTR;
48
49 /*------------------------ Local prototypes ---------------------------*/
50 static long int dram_size (long int, long int *, long int);
51 static void kbd_init (void);
52 static 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
59 static int key_pressed(void);
60 extern void disable_putc(void);
61 #endif /* CONFIG_MODEM_SUPPORT */
62
63 /*
64  * 66 MHz SDRAM access using UPM A
65  */
66 const 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 /***********************************************************************
174 F* Function:     int checkboard (void) P*A*Z*
175  *
176 P* Parameters:   none
177 P*
178 P* Returnvalue:  int - 0 is always returned
179  *
180 Z* Intention:    This function is the checkboard() method implementation
181 Z*               for the lwmon board.  Only a standard message is printed.
182  *
183 D* Design:       wd@denx.de
184 C* Coding:       wd@denx.de
185 V* Verification: dzu@denx.de
186  ***********************************************************************/
187 int checkboard (void)
188 {
189         puts ("Board: LICCON Konsole LCD3\n");
190         return (0);
191 }
192
193 /***********************************************************************
194 F* Function:     phys_size_t initdram (int board_type) P*A*Z*
195  *
196 P* Parameters:   int board_type
197 P*                - Usually type of the board - ignored here.
198 P*
199 P* Returnvalue:  long int
200 P*                - Size of initialized memory
201  *
202 Z* Intention:    This function is the initdram() method implementation
203 Z*               for the lwmon board.
204 Z*               The memory controller is initialized to access the
205 Z*               DRAM.
206  *
207 D* Design:       wd@denx.de
208 C* Coding:       wd@denx.de
209 V* Verification: dzu@denx.de
210  ***********************************************************************/
211 phys_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 /***********************************************************************
302 F* Function:     static long int dram_size (long int mamr_value,
303 F*                                          long int *base,
304 F*                                          long int maxsize) P*A*Z*
305  *
306 P* Parameters:   long int mamr_value
307 P*                - Value for MAMR for the test
308 P*               long int *base
309 P*                - Base address for the test
310 P*               long int maxsize
311 P*                - Maximum size to test for
312 P*
313 P* Returnvalue:  long int
314 P*                - Size of probed memory
315  *
316 Z* Intention:    Check memory range for valid RAM. A simple memory test
317 Z*               determines the actually available RAM size between
318 Z*               addresses `base' and `base + maxsize'. Some (not all)
319 Z*               hardware errors are detected:
320 Z*                - short between address lines
321 Z*                - short between data lines
322  *
323 D* Design:       wd@denx.de
324 C* Coding:       wd@denx.de
325 V* Verification: dzu@denx.de
326  ***********************************************************************/
327 static 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 /***********************************************************************
344 F* Function:     int board_early_init_f (void) P*A*Z*
345  *
346 P* Parameters:   none
347 P*
348 P* Returnvalue:  int
349 P*                - 0 is always returned.
350  *
351 Z* Intention:    This function is the board_early_init_f() method implementation
352 Z*               for the lwmon board.
353 Z*               Disable Ethernet TENA on Port B.
354  *
355 D* Design:       wd@denx.de
356 C* Coding:       wd@denx.de
357 V* Verification: dzu@denx.de
358  ***********************************************************************/
359 int 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 /***********************************************************************
382 F* Function:     void reset_phy (void) P*A*Z*
383  *
384 P* Parameters:   none
385 P*
386 P* Returnvalue:  none
387  *
388 Z* Intention:    Reset the PHY.  In the lwmon case we do this by the
389 Z*               signaling the PIC I/O expander.
390  *
391 D* Design:       wd@denx.de
392 C* Coding:       wd@denx.de
393 V* Verification: dzu@denx.de
394  ***********************************************************************/
395 void 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
439 static uchar kbd_addr = CONFIG_SYS_I2C_KEYBD_ADDR;
440
441 static uchar *key_match (uchar *);
442
443 #define KEYBD_SET_DEBUGMODE     '#'     /* Magic key to enable debug output */
444
445 /***********************************************************************
446 F* Function:     int board_postclk_init (void) P*A*Z*
447  *
448 P* Parameters:   none
449 P*
450 P* Returnvalue:  int
451 P*                - 0 is always returned.
452  *
453 Z* Intention:    This function is the board_postclk_init() method implementation
454 Z*               for the lwmon board.
455  *
456  ***********************************************************************/
457 int 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
471 struct serial_device * default_serial_console (void)
472 {
473         return gd->do_mdm_init ? &serial_scc_device : &serial_smc_device;
474 }
475
476 static 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->arch.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->arch.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->arch.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 /***********************************************************************
545 F* Function:     int misc_init_r (void) P*A*Z*
546  *
547 P* Parameters:   none
548 P*
549 P* Returnvalue:  int
550 P*                - 0 is always returned, even in the case of a keyboard
551 P*                    error.
552  *
553 Z* Intention:    This function is the misc_init_r() method implementation
554 Z*               for the lwmon board.
555 Z*               The keyboard controller is initialized and the result
556 Z*               of a read copied to the environment variable "keybd".
557 Z*               If KEYBD_SET_DEBUGMODE is defined, a check is made for
558 Z*               this key, and if found display to the LCD will be enabled.
559 Z*               The keys in "keybd" are checked against the magic
560 Z*               keycommands defined in the environment.
561 Z*               See also key_match().
562  *
563 D* Design:       wd@denx.de
564 C* Coding:       wd@denx.de
565 V* Verification: dzu@denx.de
566  ***********************************************************************/
567 int 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->arch.kbd_status >> 8;
572         uchar kbd_status = gd->arch.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
633 static uchar kbd_magic_prefix[] = "key_magic";
634 static uchar kbd_command_prefix[] = "key_cmd";
635
636 static 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 /***********************************************************************
687 F* Function:     static uchar *key_match (uchar *kbd_data) P*A*Z*
688  *
689 P* Parameters:   uchar *kbd_data
690 P*                - The keys to match against our magic definitions
691 P*
692 P* Returnvalue:  uchar *
693 P*                - != NULL: Pointer to the corresponding command(s)
694 P*                     NULL: No magic is about to happen
695  *
696 Z* Intention:    Check if pressed key(s) match magic sequence,
697 Z*               and return the command string associated with that key(s).
698 Z*
699 Z*               If no key press was decoded, NULL is returned.
700 Z*
701 Z*               Note: the first character of the argument will be
702 Z*                     overwritten with the "magic charcter code" of the
703 Z*                     decoded key(s), or '\0'.
704 Z*
705 Z*               Note: the string points to static environment data
706 Z*                     and must be saved before you call any function that
707 Z*                     modifies the environment.
708  *
709 D* Design:       wd@denx.de
710 C* Coding:       wd@denx.de
711 V* Verification: dzu@denx.de
712  ***********************************************************************/
713 static 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
766 void 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 /***********************************************************************
793 F* Function:     int do_pic (cmd_tbl_t *cmdtp, int flag,
794 F*                           int argc, char * const argv[]) P*A*Z*
795  *
796 P* Parameters:   cmd_tbl_t *cmdtp
797 P*                - Pointer to our command table entry
798 P*               int flag
799 P*                - If the CMD_FLAG_REPEAT bit is set, then this call is
800 P*                  a repetition
801 P*               int argc
802 P*                - Argument count
803 P*               char * const argv[]
804 P*                - Array of the actual arguments
805 P*
806 P* Returnvalue:  int
807 P*                - 0  The command was handled successfully
808 P*                  1  An error occurred
809  *
810 Z* Intention:    Implement the "pic [read|write]" commands.
811 Z*               The read subcommand takes one argument, the register,
812 Z*               whereas the write command takes two, the register and
813 Z*               the new value.
814  *
815 D* Design:       wd@denx.de
816 C* Coding:       wd@denx.de
817 V* Verification: dzu@denx.de
818  ***********************************************************************/
819 int 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 }
850 U_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 /***********************************************************************
858 F* Function:     int do_kbd (cmd_tbl_t *cmdtp, int flag,
859 F*                           int argc, char * const argv[]) P*A*Z*
860  *
861 P* Parameters:   cmd_tbl_t *cmdtp
862 P*                - Pointer to our command table entry
863 P*               int flag
864 P*                - If the CMD_FLAG_REPEAT bit is set, then this call is
865 P*                  a repetition
866 P*               int argc
867 P*                - Argument count
868 P*               char * const argv[]
869 P*                - Array of the actual arguments
870 P*
871 P* Returnvalue:  int
872 P*                - 0 is always returned.
873  *
874 Z* Intention:    Implement the "kbd" command.
875 Z*               The keyboard status is read.  The result is printed on
876 Z*               the console and written into the "keybd" environment
877 Z*               variable.
878  *
879 D* Design:       wd@denx.de
880 C* Coding:       wd@denx.de
881 V* Verification: dzu@denx.de
882  ***********************************************************************/
883 int 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
909 U_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 /***********************************************************************
919 F* Function:     int do_lsb (cmd_tbl_t *cmdtp, int flag,
920 F*                           int argc, char * const argv[]) P*A*Z*
921  *
922 P* Parameters:   cmd_tbl_t *cmdtp
923 P*                - Pointer to our command table entry
924 P*               int flag
925 P*                - If the CMD_FLAG_REPEAT bit is set, then this call is
926 P*                  a repetition
927 P*               int argc
928 P*                - Argument count
929 P*               char * const argv[]
930 P*                - Array of the actual arguments
931 P*
932 P* Returnvalue:  int
933 P*                - 0  The command was handled successfully
934 P*                  1  An error occurred
935  *
936 Z* Intention:    Implement the "lsb [on|off]" commands.
937 Z*               The lsb is switched according to the first parameter by
938 Z*               by signaling the PIC I/O expander.
939 Z*               Called with no arguments, the current setting is
940 Z*               printed.
941  *
942 D* Design:       wd@denx.de
943 C* Coding:       wd@denx.de
944 V* Verification: dzu@denx.de
945  ***********************************************************************/
946 int 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
980 U_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 /***********************************************************************
992 F* Function:     uchar pic_read (uchar reg) P*A*Z*
993  *
994 P* Parameters:   uchar reg
995 P*                - Register to read
996 P*
997 P* Returnvalue:  uchar
998 P*                - Value read from register
999  *
1000 Z* Intention:    Read a register from the PIC I/O expander.
1001  *
1002 D* Design:       wd@denx.de
1003 C* Coding:       wd@denx.de
1004 V* Verification: dzu@denx.de
1005  ***********************************************************************/
1006 uchar pic_read (uchar reg)
1007 {
1008         return (i2c_reg_read (CONFIG_SYS_I2C_PICIO_ADDR, reg));
1009 }
1010
1011 /***********************************************************************
1012 F* Function:     void pic_write (uchar reg, uchar val) P*A*Z*
1013  *
1014 P* Parameters:   uchar reg
1015 P*                - Register to read
1016 P*               uchar val
1017 P*                - Value to write
1018 P*
1019 P* Returnvalue:  none
1020  *
1021 Z* Intention:    Write to a register on the PIC I/O expander.
1022  *
1023 D* Design:       wd@denx.de
1024 C* Coding:       wd@denx.de
1025 V* Verification: dzu@denx.de
1026  ***********************************************************************/
1027 void 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 /***********************************************************************
1034 F* Function:     void board_poweroff (void) P*A*Z*
1035  *
1036 P* Parameters:   none
1037 P*
1038 P* Returnvalue:  none
1039  *
1040 Z* Intention:    Turn off the battery power and loop endless, so this
1041 Z*               should better be the last function you call...
1042  *
1043 D* Design:       wd@denx.de
1044 C* Coding:       wd@denx.de
1045 V* Verification: dzu@denx.de
1046  ***********************************************************************/
1047 void 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
1056 static 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  */
1075 int 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