]> git.kernelconcepts.de Git - karo-tx-redboot.git/blob - packages/hal/arm/mx53/var/v2_0/src/soc_misc.c
i.MX53: support mask revision 4
[karo-tx-redboot.git] / packages / hal / arm / mx53 / var / v2_0 / src / soc_misc.c
1 //==========================================================================
2 //
3 //      soc_misc.c
4 //
5 //      HAL misc board support code
6 //
7 //==========================================================================
8 //####ECOSGPLCOPYRIGHTBEGIN####
9 // -------------------------------------------
10 // This file is part of eCos, the Embedded Configurable Operating System.
11 // Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
12 //
13 // eCos is free software; you can redistribute it and/or modify it under
14 // the terms of the GNU General Public License as published by the Free
15 // Software Foundation; either version 2 or (at your option) any later version.
16 //
17 // eCos is distributed in the hope that it will be useful, but WITHOUT ANY
18 // WARRANTY; without even the implied warranty of MERCHANTABILITY or
19 // FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
20 // for more details.
21 //
22 // You should have received a copy of the GNU General Public License along
23 // with eCos; if not, write to the Free Software Foundation, Inc.,
24 // 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
25 //
26 // As a special exception, if other files instantiate templates or use macros
27 // or inline functions from this file, or you compile this file and link it
28 // with other works to produce a work based on this file, this file does not
29 // by itself cause the resulting work to be covered by the GNU General Public
30 // License. However the source code for this file must still be made available
31 // in accordance with section (3) of the GNU General Public License.
32 //
33 // This exception does not invalidate any other reasons why a work based on
34 // this file might be covered by the GNU General Public License.
35 //
36 // Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
37 // at http://sources.redhat.com/ecos/ecos-license/
38 // -------------------------------------------
39 //####ECOSGPLCOPYRIGHTEND####
40 //========================================================================*/
41
42 #include <redboot.h>
43 #include <pkgconf/hal.h>
44 #include <pkgconf/system.h>
45 #include CYGBLD_HAL_PLATFORM_H
46
47 #include <cyg/infra/cyg_type.h>                 // base types
48 #include <cyg/infra/cyg_trac.h>                 // tracing macros
49 #include <cyg/infra/cyg_ass.h>                  // assertion macros
50
51 #include <cyg/hal/hal_misc.h>                   // Size constants
52 #include <cyg/hal/hal_io.h>                             // IO macros
53 #include <cyg/hal/hal_arch.h>                   // Register state info
54 #include <cyg/hal/hal_diag.h>
55 #include <cyg/hal/hal_intr.h>                   // Interrupt names
56 #include <cyg/hal/hal_cache.h>                  // Cache control
57 #include <cyg/hal/hal_soc.h>                    // Hardware definitions
58 #include <cyg/hal/hal_mm.h>                             // MMap table definitions
59 #include <cyg/infra/diag.h>                             // diag_printf
60 #ifdef MXCFLASH_SELECT_NAND
61 #include <cyg/io/imx_nfc.h>
62 #endif
63
64 // Most initialization has already been done before we get here.
65 // All we do here is set up the interrupt environment.
66 // FIXME: some of the stuff in hal_platform_setup could be moved here.
67
68 /*
69  * System_rev will have the following format
70  * 31-12 = part # (0x31, 0x32, 0x27, 0x91131, 0x91321, etc)
71  * 11-8 = unused
72  * 7-4 = major (1.y)
73  * 3-0 = minor (x.0)
74  */
75 unsigned int system_rev = CHIP_REV_1_0;
76 static int find_correct_chip;
77
78 #define SBMR_BOOT_CFG1_SHIFT            0
79 #define SBMR_BOOT_CFG1_MASK                     (0xff << SBMR_BOOT_CFG1_SHIFT)
80 #define SBMR_BOOT_CFG1(r)                       (((r) & SBMR_BOOT_CFG1_MASK) >> SBMR_BOOT_CFG1_SHIFT)
81
82 #define SBMR_BOOT_CFG2_SHIFT            8
83 #define SBMR_BOOT_CFG2_MASK                     (0xff << SBMR_BOOT_CFG2_SHIFT)
84 #define SBMR_BOOT_CFG2(r)                       (((r) & SBMR_BOOT_CFG2_MASK) >> SBMR_BOOT_CFG2_SHIFT)
85
86 #define SBMR_BOOT_CFG3_SHIFT            16
87 #define SBMR_BOOT_CFG3_MASK                     (0xff << SBMR_BOOT_CFG3_SHIFT)
88 #define SBMR_BOOT_CFG3(r)                       (((r) & SBMR_BOOT_CFG3_MASK) >> SBMR_BOOT_CFG3_SHIFT)
89
90 #define SBMR_BMOD_SHIFT                         24
91 #define SBMR_BMOD_MASK                          (0x3 << SBMR_BMOD_SHIFT)
92 #define SBMR_BMOD(r)                            (((r) & SBMR_BMOD_MASK) >> SBMR_BMOD_SHIFT)
93
94 #define SBMR_BT_FUSE_SEL_SHIFT          26
95 #define SBMR_BT_FUSE_SEL_MASK           (3 << SBMR_BT_FUSE_SEL_SHIFT)
96 #define SBMR_BT_FUSE_SEL(r)                     (((r) & SBMR_BT_FUSE_SEL_MASK) >> SBMR_BT_FUSE_SEL_SHIFT)
97
98 /*
99  * This functions reads the IIM module and returns the system revision number.
100  * It returns the IIM silicon revision reg value if valid product rev is found.
101  . Otherwise, it returns -1.
102  */
103 static int read_system_rev(void)
104 {
105         int prev, srev;
106
107         prev = readl(IIM_BASE_ADDR + IIM_PREV_OFF) >> 3;
108         srev = readl(IIM_BASE_ADDR + IIM_SREV_OFF);
109
110         system_rev = 0x53 << PART_NUMBER_OFFSET; /* For MX53 Platform*/
111
112         /* Now try to retrieve the silicon rev from IIM's SREV register */
113         return srev;
114 }
115
116 #ifdef MXCFLASH_SELECT_NAND
117 unsigned int mxc_nfc_soc_setup(unsigned int pg_sz, unsigned int io_sz,
118                                                         unsigned int is_mlc, unsigned int num_of_chips);
119 extern nfc_setup_func_t *nfc_setup;
120 #endif
121
122 #ifdef MXCFLASH_SELECT_MMC
123 //extern mxc_mmc_check_sdhc_boot_slot *check_sdhc_slot;
124 #endif
125
126 int mxc_check_sdhc_boot_slot(unsigned int port, unsigned int *sdhc_addr);
127
128 void hal_hardware_init(void)
129 {
130         int ver;
131
132         ver = read_system_rev();
133
134         find_correct_chip = ver;
135
136         if (ver != CHIP_VERSION_NONE) {
137                 /* Valid product revision found. Check actual silicon rev from the ROM code. */
138                 if (ver == 0x1) {
139                         HAL_PLATFORM_EXTRA[5] = '1';
140                         HAL_PLATFORM_EXTRA[7] = '0';
141                         system_rev |= 1 << MAJOR_NUMBER_OFFSET;
142                         system_rev |= 0 << MINOR_NUMBER_OFFSET;
143                 } else if (ver == 0x2) {
144                         HAL_PLATFORM_EXTRA[5] = '1';
145                         HAL_PLATFORM_EXTRA[7] = '1';
146                         system_rev |= 1 << MAJOR_NUMBER_OFFSET;
147                         system_rev |= 1 << MINOR_NUMBER_OFFSET;
148                 } else if (ver == 0x10) {
149                         HAL_PLATFORM_EXTRA[5] = '2';
150                         HAL_PLATFORM_EXTRA[7] = '0';
151                         system_rev |= 2 << MAJOR_NUMBER_OFFSET;
152                         system_rev |= 0 << MINOR_NUMBER_OFFSET;
153                 } else if (ver == 0x3) {
154                         HAL_PLATFORM_EXTRA[5] = '2';
155                         HAL_PLATFORM_EXTRA[7] = '1';
156                         system_rev |= 2 << MAJOR_NUMBER_OFFSET;
157                         system_rev |= 1 << MINOR_NUMBER_OFFSET;
158                 } else if (ver == 0x4) {
159                         HAL_PLATFORM_EXTRA[5] = '3';
160                         HAL_PLATFORM_EXTRA[7] = '0';
161                         system_rev |= 3 << MAJOR_NUMBER_OFFSET;
162                         system_rev |= 0 << MINOR_NUMBER_OFFSET;
163                 } else {
164                         HAL_PLATFORM_EXTRA[5] = 'x';
165                         HAL_PLATFORM_EXTRA[7] = 'x';
166                         system_rev |= 3 << MAJOR_NUMBER_OFFSET;
167                         system_rev |= 0 << MINOR_NUMBER_OFFSET;
168                         find_correct_chip = CHIP_VERSION_UNKNOWN;
169                 }
170
171         }
172         // Enable caches
173 #ifdef CYGSEM_HAL_ENABLE_ICACHE_ON_STARTUP
174         HAL_ICACHE_ENABLE();
175 #endif
176 #ifdef CYGSEM_HAL_ENABLE_DCACHE_ON_STARTUP
177         HAL_DCACHE_ENABLE();
178 #endif
179         // enable EPIT and start it with 32KHz input clock
180         writel(0x00010000, EPIT_BASE_ADDR + EPITCR);
181
182         // make sure reset is complete
183         while ((readl(EPIT_BASE_ADDR + EPITCR) & 0x10000) != 0) {
184                 static int retries = 10000;
185                 if (retries--)
186                         break;
187         }
188
189         writel(0x030E0002, EPIT_BASE_ADDR + EPITCR);
190         writel(0x030E0003, EPIT_BASE_ADDR + EPITCR);
191
192         writel(0, EPIT_BASE_ADDR + EPITCMPR);  // always compare with 0
193
194         if ((readw(WDOG_BASE_ADDR) & 4) != 0) {
195                 // increase the WDOG timeout value to the max
196                 writew(readw(WDOG_BASE_ADDR) | 0xFF00, WDOG_BASE_ADDR);
197         }
198         // Perform any platform specific initializations
199         plf_hardware_init();
200
201         // Set up eCos/ROM interfaces
202         hal_if_init();
203
204 #ifdef MXCFLASH_SELECT_NAND
205         nfc_setup = mxc_nfc_soc_setup;
206 #endif
207 }
208
209 // -------------------------------------------------------------------------
210 void hal_clock_initialize(cyg_uint32 period)
211 {
212 }
213
214 // This routine is called during a clock interrupt.
215
216 // Define this if you want to ensure that the clock is perfect (i.e. does
217 // not drift).  One reason to leave it turned off is that it costs some
218 // us per system clock interrupt for this maintenance.
219 #undef COMPENSATE_FOR_CLOCK_DRIFT
220
221 void hal_clock_reset(cyg_uint32 vector, cyg_uint32 period)
222 {
223 }
224
225 // Read the current value of the clock, returning the number of hardware
226 // "ticks" that have occurred (i.e. how far away the current value is from
227 // the start)
228
229 // Note: The "contract" for this function is that the value is the number
230 // of hardware clocks that have happened since the last interrupt (i.e.
231 // when it was reset).  This value is used to measure interrupt latencies.
232 // However, since the hardware counter runs freely, this routine computes
233 // the difference between the current clock period and the number of hardware
234 // ticks left before the next timer interrupt.
235 void hal_clock_read(cyg_uint32 *pvalue)
236 {
237 }
238
239 // This is to cope with the test read used by tm_basic with
240 // CYGVAR_KERNEL_COUNTERS_CLOCK_LATENCY defined; we read the count ASAP
241 // in the ISR, *before* resetting the clock.  Which returns 1tick +
242 // latency if we just use plain hal_clock_read().
243 void hal_clock_latency(cyg_uint32 *pvalue)
244 {
245 }
246
247 unsigned int hal_timer_count(void)
248 {
249         return (0xFFFFFFFF - readl(EPIT_BASE_ADDR + EPITCNR));
250 }
251
252 #define WDT_MAGIC_1                             0x5555
253 #define WDT_MAGIC_2                             0xAAAA
254 #define MXC_WDT_WSR                             0x2
255
256 unsigned int i2c_base_addr[] = {
257         I2C_BASE_ADDR,
258         I2C2_BASE_ADDR,
259 };
260 unsigned int i2c_num = 2;
261
262 static unsigned int led_on = 0;
263 //
264 // Delay for some number of micro-seconds
265 //
266 void hal_delay_us(unsigned int usecs)
267 {
268         /*
269          * This causes overflow.
270          * unsigned int delayCount = (usecs * 32768) / 1000000;
271          * So use the following one instead
272          */
273         unsigned int delayCount = (usecs * 512) / 15625;
274
275         // issue the service sequence instructions
276         if ((readw(WDOG_BASE_ADDR) & 4) != 0) {
277                 writew(WDT_MAGIC_1, WDOG_BASE_ADDR + MXC_WDT_WSR);
278                 writew(WDT_MAGIC_2, WDOG_BASE_ADDR + MXC_WDT_WSR);
279         }
280
281         if (delayCount == 0) {
282                 return;
283         }
284
285         writel(0x01, EPIT_BASE_ADDR + EPITSR); // clear the compare status bit
286
287         writel(delayCount, EPIT_BASE_ADDR + EPITLR);
288
289         while ((0x1 & readl(EPIT_BASE_ADDR + EPITSR)) == 0); // return until compare bit is set
290         if ((++led_on % 3000) == 0)
291                 BOARD_DEBUG_LED(0);
292 }
293
294 // -------------------------------------------------------------------------
295
296 // This routine is called to respond to a hardware interrupt (IRQ).  It
297 // should interrogate the hardware and return the IRQ vector number.
298 int hal_IRQ_handler(void)
299 {
300 #ifdef HAL_EXTENDED_IRQ_HANDLER
301         cyg_uint32 index;
302
303         // Use platform specific IRQ handler, if defined
304         // Note: this macro should do a 'return' with the appropriate
305         // interrupt number if such an extended interrupt exists.  The
306         // assumption is that the line after the macro starts 'normal' processing.
307         HAL_EXTENDED_IRQ_HANDLER(index);
308 #endif
309
310         return CYGNUM_HAL_INTERRUPT_NONE; // This shouldn't happen!
311 }
312
313 //
314 // Interrupt control
315 //
316
317 void hal_interrupt_mask(int vector)
318 {
319 //    diag_printf("6hal_interrupt_mask(vector=%d) \n", vector);
320 #ifdef HAL_EXTENDED_INTERRUPT_MASK
321         // Use platform specific handling, if defined
322         // Note: this macro should do a 'return' for "extended" values of 'vector'
323         // Normal vectors are handled by code subsequent to the macro call.
324         HAL_EXTENDED_INTERRUPT_MASK(vector);
325 #endif
326 }
327
328 void hal_interrupt_unmask(int vector)
329 {
330 //    diag_printf("7hal_interrupt_unmask(vector=%d) \n", vector);
331
332 #ifdef HAL_EXTENDED_INTERRUPT_UNMASK
333         // Use platform specific handling, if defined
334         // Note: this macro should do a 'return' for "extended" values of 'vector'
335         // Normal vectors are handled by code subsequent to the macro call.
336         HAL_EXTENDED_INTERRUPT_UNMASK(vector);
337 #endif
338 }
339
340 void hal_interrupt_acknowledge(int vector)
341 {
342
343 //    diag_printf("8hal_interrupt_acknowledge(vector=%d) \n", vector);
344 #ifdef HAL_EXTENDED_INTERRUPT_UNMASK
345         // Use platform specific handling, if defined
346         // Note: this macro should do a 'return' for "extended" values of 'vector'
347         // Normal vectors are handled by code subsequent to the macro call.
348         HAL_EXTENDED_INTERRUPT_ACKNOWLEDGE(vector);
349 #endif
350 }
351
352 void hal_interrupt_configure(int vector, int level, int up)
353 {
354
355 #ifdef HAL_EXTENDED_INTERRUPT_CONFIGURE
356         // Use platform specific handling, if defined
357         // Note: this macro should do a 'return' for "extended" values of 'vector'
358         // Normal vectors are handled by code subsequent to the macro call.
359         HAL_EXTENDED_INTERRUPT_CONFIGURE(vector, level, up);
360 #endif
361 }
362
363 void hal_interrupt_set_level(int vector, int level)
364 {
365
366 #ifdef HAL_EXTENDED_INTERRUPT_SET_LEVEL
367         // Use platform specific handling, if defined
368         // Note: this macro should do a 'return' for "extended" values of 'vector'
369         // Normal vectors are handled by code subsequent to the macro call.
370         HAL_EXTENDED_INTERRUPT_SET_LEVEL(vector, level);
371 #endif
372
373         // Interrupt priorities are not configurable.
374 }
375
376 #ifdef MXCFLASH_SELECT_NAND
377 unsigned int mxc_nfc_soc_setup(unsigned int pg_sz, unsigned int io_sz,
378                                                         unsigned int is_mlc, unsigned int num_of_chips)
379 {
380         unsigned int tmp;
381
382         tmp = readl(NFC_FLASH_CONFIG2_REG);
383
384         /* Set the ST_CMD to be 0x70 for all NAND devices */
385         tmp &= ~(0xFF << 24);
386         tmp |= 0x70 << 24;
387         /* spare size = 64 byte */
388         tmp = (tmp & ~(0xff << 16)) | ((64 / 2) << 16);
389
390         /* Set the Page Size */
391         tmp &= ~0x3;
392         switch (pg_sz) {
393         case 512:
394                 tmp |= 0x0;
395                 break;
396
397         case 2048:
398                 tmp |= 0x1;
399                 break;
400
401         case 4096:
402         default:
403                 tmp |= 0x2;
404                 break;
405         }
406
407         /* set ECC_MODE to 4bit ECC */
408         tmp = (tmp & ~(3 << 6)) | (0 << 6);
409         /* set pages/block to 64 */
410         tmp = (tmp & ~(3 << 8)) | (1 << 8);
411
412         /* Set the number of addr phases & ECC mode to default value */
413         tmp &= ~(0x3 << 12);
414         tmp |= (0x2 << 12) | 0x038;
415         writel(tmp, NFC_FLASH_CONFIG2_REG);
416
417         tmp = readl(NFC_FLASH_CONFIG3_REG);
418
419         /* Set the No SDMA bit */
420         tmp |= 0x1 << 20;
421
422         /* Set the Status Busy Bit to 0x6 (default) */
423         tmp &= ~(0x7 << 8);
424         tmp |= 0x6 << 8;
425
426         /* Set the Flash Width */
427         if (io_sz == MXC_NAND_16_BIT) {
428                 tmp &= ~(1 << 3);
429         } else {
430                 tmp |= 1 << 3;
431         }
432
433         /* Set the Number of Nand Chips */
434         tmp &= ~(0x7 << 12);
435         tmp |= (num_of_chips - 1) << 12;
436         if (num_of_chips > 1)
437                 tmp |= 0x1;
438
439 #if 0
440         /* STATUS_SAMP_SEL */
441         tmp |= 1 << 19;
442 #endif
443         writel(tmp, NFC_FLASH_CONFIG3_REG);
444
445         return MXC_NFC_V3;
446 }
447 #endif
448
449 int mx53_iomux_setup(iomux_v3_cfg_t pad)
450 {
451 #if 0
452         diag_printf("pad=%016llx MUX_OFS=%03x PAD_OFS=%03x INP_SEL_OFS=%03x MUX_MODE=%02x PAD_CTL=%04x INP_SEL=%x PAD_CTL_VALID=%d\n",
453                                 pad, IOMUX_MUX_CTRL_OFS(pad), IOMUX_PAD_CTRL_OFS(pad),
454                                 IOMUX_INP_SEL_OFS(pad), IOMUX_MUX_MODE(pad), IOMUX_PAD_CTRL(pad),
455                                 IOMUX_INP_SEL(pad), IOMUX_PAD_CTRL_VALID(pad));
456         if (readl(IOMUXC_BASE_ADDR + IOMUX_MUX_CTRL_OFS(pad)) !=
457                 IOMUX_MUX_MODE(pad)) {
458                 diag_printf("Changing IOMUX[%03x] from %02x to %02x\n",
459                                         IOMUX_MUX_CTRL_OFS(pad),
460                                         readl(IOMUXC_BASE_ADDR + IOMUX_MUX_CTRL_OFS(pad)),
461                                         IOMUX_MUX_MODE(pad));
462         }
463 #endif
464         writel(IOMUX_MUX_MODE(pad),
465                 IOMUXC_BASE_ADDR + IOMUX_MUX_CTRL_OFS(pad));
466
467         if (IOMUX_PAD_CTRL_VALID(pad)) {
468 #if 0
469                 if (readl(IOMUXC_BASE_ADDR + IOMUX_PAD_CTRL_OFS(pad)) !=
470                         IOMUX_PAD_CTRL(pad)) {
471                         diag_printf("Changing PAD_CTRL[%03x] from %04x to %04x\n",
472                                                 IOMUX_PAD_CTRL_OFS(pad),
473                                                 readl(IOMUXC_BASE_ADDR + IOMUX_PAD_CTRL_OFS(pad)),
474                                                 IOMUX_PAD_CTRL(pad));
475                 }
476 #endif
477                 writel(IOMUX_PAD_CTRL(pad), IOMUXC_BASE_ADDR + IOMUX_PAD_CTRL_OFS(pad));
478         }
479         if (IOMUX_INP_SEL_OFS(pad)) {
480 #if 0
481                 if (readl(IOMUXC_BASE_ADDR + IOMUX_INP_SEL_OFS(pad)) !=
482                         IOMUX_INP_SEL(pad)) {
483                         diag_printf("Changing INP_SEL[%03x] from %x to %x\n",
484                                                 IOMUX_INP_SEL_OFS(pad),
485                                                 readl(IOMUXC_BASE_ADDR + IOMUX_INP_SEL_OFS(pad)),
486                                                 IOMUX_INP_SEL(pad));
487                 }
488 #endif
489                 writel(IOMUX_INP_SEL(pad), IOMUXC_BASE_ADDR + IOMUX_INP_SEL_OFS(pad));
490         }
491         return 0;
492 }
493
494 int mx53_iomux_setup_pads(iomux_v3_cfg_t *pad, int num_pads)
495 {
496         int ret = 0;
497         int i;
498
499         for (i = 0; i < num_pads; i++) {
500                 ret = mx53_iomux_setup(pad[i]);
501                 if (ret)
502                         break;
503         }
504         return ret;
505 }
506
507 static void show_sys_info(void)
508 {
509         cyg_uint32 sbmr = readl(SRC_BASE_ADDR + 0x4);
510         cyg_uint32 srsr = readl(SRC_BASE_ADDR + 0x8);
511         const char *dlm = "";
512         int bt_mem = (SBMR_BOOT_CFG1(sbmr) & (0xf << 4)) >> 4;
513
514         if (find_correct_chip == CHIP_VERSION_UNKNOWN) {
515                 diag_printf("Unrecognized chip version: 0x%08x!\n", read_system_rev());
516                 diag_printf("Assuming chip version=0x%08x\n", system_rev);
517         } else if (find_correct_chip == CHIP_VERSION_NONE) {
518                 diag_printf("Unrecognized chip: 0x%08x!!!\n", readl(IIM_BASE_ADDR + IIM_PREV_OFF));
519         }
520
521         diag_printf("Reset reason: ");
522
523         if (srsr & (1 << 0)) {
524                 diag_printf("%sPOWER_ON", dlm);
525                 dlm = " | ";
526         }
527         if (srsr & (1 << 2)) {
528                 diag_printf("%sCSU", dlm);
529                 dlm = " | ";
530         }
531         if (srsr & (1 << 3)) {
532                 diag_printf("%sUSER", dlm);
533                 dlm = " | ";
534         }
535         if (srsr & (1 << 4)) {
536                 CYG_WORD16 wrsr;
537
538                 HAL_READ_UINT16(WDOG_BASE_ADDR + 4, wrsr);
539                 if (wrsr & (1 << 0)) {
540                         diag_printf("%sSOFT", dlm);
541                         dlm = " | ";
542                 }
543                 if (wrsr & (1 << 1)) {
544                         diag_printf("%sWATCHDOG", dlm);
545                         dlm = " | ";
546                 }
547         }
548         if (srsr & (1 << 5)) {
549                 diag_printf("%sJTAG_HW", dlm);
550                 dlm = " | ";
551         }
552         if (srsr & (1 << 6)) {
553                 diag_printf("%sJTAG_SW", dlm);
554                 dlm = " | ";
555         }
556         if (srsr & (1 << 16)) {
557                 diag_printf("%sWARM BOOT", dlm);
558                 dlm = " | ";
559         }
560
561         if (*dlm == '\0') {
562                 diag_printf("UNKNOWN: %08x\n", srsr);
563         } else {
564                 diag_printf(" RESET\n");
565         }
566
567         diag_printf("BOOT_MODE:   ");
568         switch (SBMR_BMOD(sbmr)) {
569         case 0:
570                 diag_printf("Internal Boot (from %s)\n",
571                                         SBMR_BT_FUSE_SEL(sbmr) ? "FUSES" : "GPIO");
572                 break;
573
574         case 1:
575                 diag_printf("FSL Test Mode\n");
576                 break;
577
578         case 2:
579                 diag_printf("Internal Boot (from %s)\n",
580                                         SBMR_BT_FUSE_SEL(sbmr) ? "FUSES" : "UART/USB");
581                 break;
582
583         case 3:
584                 diag_printf("Serial Boot Loader\n");
585         }
586         diag_printf("Boot Medium: ");
587         switch (SBMR_BMOD(sbmr)) {
588         case 0:
589         case 2:
590                 if (bt_mem == 0) {
591                         diag_printf("WEIM %s\n", SBMR_BOOT_CFG1(sbmr) & (1 << 3) ?
592                                                 "NOR" : "OneNAND");
593                 } else if (bt_mem == 2) {
594                         diag_printf("HD %sATA\n", SBMR_BOOT_CFG1(sbmr) & (1 << 3) ?
595                                                 "S" : "P");
596                 } else if (bt_mem == 3) {
597                         diag_printf("Serial ROM %s\n", SBMR_BOOT_CFG1(sbmr) & (1 << 3) ?
598                                                 "SPI" : "I2C");
599                 } else if ((bt_mem & ~1) == 4) {
600                         diag_printf("SD %s speed\n", SBMR_BOOT_CFG1(sbmr) & (1 << 3) ?
601                                                 "low" : "high");
602                 } else if ((bt_mem & ~1) == 6) {
603                         diag_printf("MMC %s speed\n", SBMR_BOOT_CFG1(sbmr) & (1 << 3) ?
604                                                 "low" : "high");
605                 } else if (bt_mem & (1 << 3)) {
606                         diag_printf("NAND\n");
607                 } else {
608                         diag_printf("UNKNOWN: 0x%x\n", bt_mem);
609                 }
610                 break;
611
612         case 1:
613                 diag_printf("UNKNOWN\n");
614                 break;
615
616         case 3:
617                 diag_printf("UART/USB\n");
618         }
619         diag_printf("Boot Clock:  %d MHz\n",
620                                 (SBMR_BOOT_CFG1(sbmr) & (1 << 1)) ? 400 : 800);
621         diag_printf("OSC Freq:    %s\n",
622                                 (SBMR_BOOT_CFG2(sbmr) & (1 << 3)) ? " 24 MHz" : "auto");
623         diag_printf("PLL2 Freq:   %d MHz\n",
624                                 (SBMR_BOOT_CFG2(sbmr) & (1 << 4)) ? 333 : 400);
625         diag_printf("Secure Boot: %s\n",
626                                 (SBMR_BOOT_CFG2(sbmr) & (2 << 0)) ? "On" : "Off");
627 }
628
629 RedBoot_init(show_sys_info, RedBoot_INIT_LAST);