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