]> git.karo-electronics.de Git - karo-tx-redboot.git/blob - packages/hal/arm/mx53/var/v2_0/src/soc_misc.c
75ef8bffa51f07ee4570ce30263474b870fc066d
[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 {
159                         HAL_PLATFORM_EXTRA[5] = 'x';
160                         HAL_PLATFORM_EXTRA[7] = 'x';
161                         system_rev |= 3 << MAJOR_NUMBER_OFFSET;
162                         system_rev |= 0 << MINOR_NUMBER_OFFSET;
163                         find_correct_chip = CHIP_VERSION_UNKNOWN;
164                 }
165
166         }
167         // Enable caches
168 #ifdef CYGSEM_HAL_ENABLE_ICACHE_ON_STARTUP
169         HAL_ICACHE_ENABLE();
170 #endif
171 #ifdef CYGSEM_HAL_ENABLE_DCACHE_ON_STARTUP
172         HAL_DCACHE_ENABLE();
173 #endif
174         // enable EPIT and start it with 32KHz input clock
175         writel(0x00010000, EPIT_BASE_ADDR + EPITCR);
176
177         // make sure reset is complete
178         while ((readl(EPIT_BASE_ADDR + EPITCR) & 0x10000) != 0) {
179                 static int retries = 10000;
180                 if (retries--)
181                         break;
182         }
183
184         writel(0x030E0002, EPIT_BASE_ADDR + EPITCR);
185         writel(0x030E0003, EPIT_BASE_ADDR + EPITCR);
186
187         writel(0, EPIT_BASE_ADDR + EPITCMPR);  // always compare with 0
188
189         if ((readw(WDOG_BASE_ADDR) & 4) != 0) {
190                 // increase the WDOG timeout value to the max
191                 writew(readw(WDOG_BASE_ADDR) | 0xFF00, WDOG_BASE_ADDR);
192         }
193         // Perform any platform specific initializations
194         plf_hardware_init();
195
196         // Set up eCos/ROM interfaces
197         hal_if_init();
198
199 #ifdef MXCFLASH_SELECT_NAND
200         nfc_setup = mxc_nfc_soc_setup;
201 #endif
202 }
203
204 // -------------------------------------------------------------------------
205 void hal_clock_initialize(cyg_uint32 period)
206 {
207 }
208
209 // This routine is called during a clock interrupt.
210
211 // Define this if you want to ensure that the clock is perfect (i.e. does
212 // not drift).  One reason to leave it turned off is that it costs some
213 // us per system clock interrupt for this maintenance.
214 #undef COMPENSATE_FOR_CLOCK_DRIFT
215
216 void hal_clock_reset(cyg_uint32 vector, cyg_uint32 period)
217 {
218 }
219
220 // Read the current value of the clock, returning the number of hardware
221 // "ticks" that have occurred (i.e. how far away the current value is from
222 // the start)
223
224 // Note: The "contract" for this function is that the value is the number
225 // of hardware clocks that have happened since the last interrupt (i.e.
226 // when it was reset).  This value is used to measure interrupt latencies.
227 // However, since the hardware counter runs freely, this routine computes
228 // the difference between the current clock period and the number of hardware
229 // ticks left before the next timer interrupt.
230 void hal_clock_read(cyg_uint32 *pvalue)
231 {
232 }
233
234 // This is to cope with the test read used by tm_basic with
235 // CYGVAR_KERNEL_COUNTERS_CLOCK_LATENCY defined; we read the count ASAP
236 // in the ISR, *before* resetting the clock.  Which returns 1tick +
237 // latency if we just use plain hal_clock_read().
238 void hal_clock_latency(cyg_uint32 *pvalue)
239 {
240 }
241
242 unsigned int hal_timer_count(void)
243 {
244         return (0xFFFFFFFF - readl(EPIT_BASE_ADDR + EPITCNR));
245 }
246
247 #define WDT_MAGIC_1                             0x5555
248 #define WDT_MAGIC_2                             0xAAAA
249 #define MXC_WDT_WSR                             0x2
250
251 unsigned int i2c_base_addr[] = {
252         I2C_BASE_ADDR,
253         I2C2_BASE_ADDR,
254 };
255 unsigned int i2c_num = 2;
256
257 static unsigned int led_on = 0;
258 //
259 // Delay for some number of micro-seconds
260 //
261 void hal_delay_us(unsigned int usecs)
262 {
263         /*
264          * This causes overflow.
265          * unsigned int delayCount = (usecs * 32768) / 1000000;
266          * So use the following one instead
267          */
268         unsigned int delayCount = (usecs * 512) / 15625;
269
270         // issue the service sequence instructions
271         if ((readw(WDOG_BASE_ADDR) & 4) != 0) {
272                 writew(WDT_MAGIC_1, WDOG_BASE_ADDR + MXC_WDT_WSR);
273                 writew(WDT_MAGIC_2, WDOG_BASE_ADDR + MXC_WDT_WSR);
274         }
275
276         if (delayCount == 0) {
277                 return;
278         }
279
280         writel(0x01, EPIT_BASE_ADDR + EPITSR); // clear the compare status bit
281
282         writel(delayCount, EPIT_BASE_ADDR + EPITLR);
283
284         while ((0x1 & readl(EPIT_BASE_ADDR + EPITSR)) == 0); // return until compare bit is set
285         if ((++led_on % 3000) == 0)
286                 BOARD_DEBUG_LED(0);
287 }
288
289 // -------------------------------------------------------------------------
290
291 // This routine is called to respond to a hardware interrupt (IRQ).  It
292 // should interrogate the hardware and return the IRQ vector number.
293 int hal_IRQ_handler(void)
294 {
295 #ifdef HAL_EXTENDED_IRQ_HANDLER
296         cyg_uint32 index;
297
298         // Use platform specific IRQ handler, if defined
299         // Note: this macro should do a 'return' with the appropriate
300         // interrupt number if such an extended interrupt exists.  The
301         // assumption is that the line after the macro starts 'normal' processing.
302         HAL_EXTENDED_IRQ_HANDLER(index);
303 #endif
304
305         return CYGNUM_HAL_INTERRUPT_NONE; // This shouldn't happen!
306 }
307
308 //
309 // Interrupt control
310 //
311
312 void hal_interrupt_mask(int vector)
313 {
314 //    diag_printf("6hal_interrupt_mask(vector=%d) \n", vector);
315 #ifdef HAL_EXTENDED_INTERRUPT_MASK
316         // Use platform specific handling, if defined
317         // Note: this macro should do a 'return' for "extended" values of 'vector'
318         // Normal vectors are handled by code subsequent to the macro call.
319         HAL_EXTENDED_INTERRUPT_MASK(vector);
320 #endif
321 }
322
323 void hal_interrupt_unmask(int vector)
324 {
325 //    diag_printf("7hal_interrupt_unmask(vector=%d) \n", vector);
326
327 #ifdef HAL_EXTENDED_INTERRUPT_UNMASK
328         // Use platform specific handling, if defined
329         // Note: this macro should do a 'return' for "extended" values of 'vector'
330         // Normal vectors are handled by code subsequent to the macro call.
331         HAL_EXTENDED_INTERRUPT_UNMASK(vector);
332 #endif
333 }
334
335 void hal_interrupt_acknowledge(int vector)
336 {
337
338 //    diag_printf("8hal_interrupt_acknowledge(vector=%d) \n", vector);
339 #ifdef HAL_EXTENDED_INTERRUPT_UNMASK
340         // Use platform specific handling, if defined
341         // Note: this macro should do a 'return' for "extended" values of 'vector'
342         // Normal vectors are handled by code subsequent to the macro call.
343         HAL_EXTENDED_INTERRUPT_ACKNOWLEDGE(vector);
344 #endif
345 }
346
347 void hal_interrupt_configure(int vector, int level, int up)
348 {
349
350 #ifdef HAL_EXTENDED_INTERRUPT_CONFIGURE
351         // Use platform specific handling, if defined
352         // Note: this macro should do a 'return' for "extended" values of 'vector'
353         // Normal vectors are handled by code subsequent to the macro call.
354         HAL_EXTENDED_INTERRUPT_CONFIGURE(vector, level, up);
355 #endif
356 }
357
358 void hal_interrupt_set_level(int vector, int level)
359 {
360
361 #ifdef HAL_EXTENDED_INTERRUPT_SET_LEVEL
362         // Use platform specific handling, if defined
363         // Note: this macro should do a 'return' for "extended" values of 'vector'
364         // Normal vectors are handled by code subsequent to the macro call.
365         HAL_EXTENDED_INTERRUPT_SET_LEVEL(vector, level);
366 #endif
367
368         // Interrupt priorities are not configurable.
369 }
370
371 #ifdef MXCFLASH_SELECT_NAND
372 unsigned int mxc_nfc_soc_setup(unsigned int pg_sz, unsigned int io_sz,
373                                                         unsigned int is_mlc, unsigned int num_of_chips)
374 {
375         unsigned int tmp;
376
377         tmp = readl(NFC_FLASH_CONFIG2_REG);
378
379         /* Set the ST_CMD to be 0x70 for all NAND devices */
380         tmp &= ~(0xFF << 24);
381         tmp |= 0x70 << 24;
382         /* spare size = 64 byte */
383         tmp = (tmp & ~(0xff << 16)) | ((64 / 2) << 16);
384
385         /* Set the Page Size */
386         tmp &= ~0x3;
387         switch (pg_sz) {
388         case 512:
389                 tmp |= 0x0;
390                 break;
391
392         case 2048:
393                 tmp |= 0x1;
394                 break;
395
396         case 4096:
397         default:
398                 tmp |= 0x2;
399                 break;
400         }
401
402         /* set ECC_MODE to 4bit ECC */
403         tmp = (tmp & ~(3 << 6)) | (0 << 6);
404         /* set pages/block to 64 */
405         tmp = (tmp & ~(3 << 8)) | (1 << 8);
406
407         /* Set the number of addr phases & ECC mode to default value */
408         tmp &= ~(0x3 << 12);
409         tmp |= (0x2 << 12) | 0x038;
410         writel(tmp, NFC_FLASH_CONFIG2_REG);
411
412         tmp = readl(NFC_FLASH_CONFIG3_REG);
413
414         /* Set the No SDMA bit */
415         tmp |= 0x1 << 20;
416
417         /* Set the Status Busy Bit to 0x6 (default) */
418         tmp &= ~(0x7 << 8);
419         tmp |= 0x6 << 8;
420
421         /* Set the Flash Width */
422         if (io_sz == MXC_NAND_16_BIT) {
423                 tmp &= ~(1 << 3);
424         } else {
425                 tmp |= 1 << 3;
426         }
427
428         /* Set the Number of Nand Chips */
429         tmp &= ~(0x7 << 12);
430         tmp |= (num_of_chips - 1) << 12;
431         if (num_of_chips > 1)
432                 tmp |= 0x1;
433
434 #if 0
435         /* STATUS_SAMP_SEL */
436         tmp |= 1 << 19;
437 #endif
438         writel(tmp, NFC_FLASH_CONFIG3_REG);
439
440         return MXC_NFC_V3;
441 }
442 #endif
443
444 int mx53_iomux_setup(iomux_v3_cfg_t pad)
445 {
446 #if 0
447         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",
448                                 pad, IOMUX_MUX_CTRL_OFS(pad), IOMUX_PAD_CTRL_OFS(pad),
449                                 IOMUX_INP_SEL_OFS(pad), IOMUX_MUX_MODE(pad), IOMUX_PAD_CTRL(pad),
450                                 IOMUX_INP_SEL(pad), IOMUX_PAD_CTRL_VALID(pad));
451         if (readl(IOMUXC_BASE_ADDR + IOMUX_MUX_CTRL_OFS(pad)) !=
452                 IOMUX_MUX_MODE(pad)) {
453                 diag_printf("Changing IOMUX[%03x] from %02x to %02x\n",
454                                         IOMUX_MUX_CTRL_OFS(pad),
455                                         readl(IOMUXC_BASE_ADDR + IOMUX_MUX_CTRL_OFS(pad)),
456                                         IOMUX_MUX_MODE(pad));
457         }
458 #endif
459         writel(IOMUX_MUX_MODE(pad),
460                 IOMUXC_BASE_ADDR + IOMUX_MUX_CTRL_OFS(pad));
461
462         if (IOMUX_PAD_CTRL_VALID(pad)) {
463 #if 0
464                 if (readl(IOMUXC_BASE_ADDR + IOMUX_PAD_CTRL_OFS(pad)) !=
465                         IOMUX_PAD_CTRL(pad)) {
466                         diag_printf("Changing PAD_CTRL[%03x] from %04x to %04x\n",
467                                                 IOMUX_PAD_CTRL_OFS(pad),
468                                                 readl(IOMUXC_BASE_ADDR + IOMUX_PAD_CTRL_OFS(pad)),
469                                                 IOMUX_PAD_CTRL(pad));
470                 }
471 #endif
472                 writel(IOMUX_PAD_CTRL(pad), IOMUXC_BASE_ADDR + IOMUX_PAD_CTRL_OFS(pad));
473         }
474         if (IOMUX_INP_SEL_OFS(pad)) {
475 #if 0
476                 if (readl(IOMUXC_BASE_ADDR + IOMUX_INP_SEL_OFS(pad)) !=
477                         IOMUX_INP_SEL(pad)) {
478                         diag_printf("Changing INP_SEL[%03x] from %x to %x\n",
479                                                 IOMUX_INP_SEL_OFS(pad),
480                                                 readl(IOMUXC_BASE_ADDR + IOMUX_INP_SEL_OFS(pad)),
481                                                 IOMUX_INP_SEL(pad));
482                 }
483 #endif
484                 writel(IOMUX_INP_SEL(pad), IOMUXC_BASE_ADDR + IOMUX_INP_SEL_OFS(pad));
485         }
486         return 0;
487 }
488
489 int mx53_iomux_setup_pads(iomux_v3_cfg_t *pad, int num_pads)
490 {
491         int ret = 0;
492         int i;
493
494         for (i = 0; i < num_pads; i++) {
495                 ret = mx53_iomux_setup(pad[i]);
496                 if (ret)
497                         break;
498         }
499         return ret;
500 }
501
502 static void show_sys_info(void)
503 {
504         cyg_uint32 sbmr = readl(SRC_BASE_ADDR + 0x4);
505         cyg_uint32 srsr = readl(SRC_BASE_ADDR + 0x8);
506         const char *dlm = "";
507         int bt_mem = (SBMR_BOOT_CFG1(sbmr) & (0xf << 4)) >> 4;
508
509         if (find_correct_chip == CHIP_VERSION_UNKNOWN) {
510                 diag_printf("Unrecognized chip version: 0x%08x!\n", read_system_rev());
511                 diag_printf("Assuming chip version=0x%08x\n", system_rev);
512         } else if (find_correct_chip == CHIP_VERSION_NONE) {
513                 diag_printf("Unrecognized chip: 0x%08x!!!\n", readl(IIM_BASE_ADDR + IIM_PREV_OFF));
514         }
515
516         diag_printf("Reset reason: ");
517
518         if (srsr & (1 << 0)) {
519                 diag_printf("%sPOWER_ON", dlm);
520                 dlm = " | ";
521         }
522         if (srsr & (1 << 2)) {
523                 diag_printf("%sCSU", dlm);
524                 dlm = " | ";
525         }
526         if (srsr & (1 << 3)) {
527                 diag_printf("%sUSER", dlm);
528                 dlm = " | ";
529         }
530         if (srsr & (1 << 4)) {
531                 CYG_WORD16 wrsr;
532
533                 HAL_READ_UINT16(WDOG_BASE_ADDR + 4, wrsr);
534                 if (wrsr & (1 << 0)) {
535                         diag_printf("%sSOFT", dlm);
536                         dlm = " | ";
537                 }
538                 if (wrsr & (1 << 1)) {
539                         diag_printf("%sWATCHDOG", dlm);
540                         dlm = " | ";
541                 }
542         }
543         if (srsr & (1 << 5)) {
544                 diag_printf("%sJTAG_HW", dlm);
545                 dlm = " | ";
546         }
547         if (srsr & (1 << 6)) {
548                 diag_printf("%sJTAG_SW", dlm);
549                 dlm = " | ";
550         }
551         if (srsr & (1 << 16)) {
552                 diag_printf("%sWARM BOOT", dlm);
553                 dlm = " | ";
554         }
555
556         if (*dlm == '\0') {
557                 diag_printf("UNKNOWN: %08x\n", srsr);
558         } else {
559                 diag_printf(" RESET\n");
560         }
561
562         diag_printf("BOOT_MODE:   ");
563         switch (SBMR_BMOD(sbmr)) {
564         case 0:
565                 diag_printf("Internal Boot (from %s)\n",
566                                         SBMR_BT_FUSE_SEL(sbmr) ? "FUSES" : "GPIO");
567                 break;
568
569         case 1:
570                 diag_printf("FSL Test Mode\n");
571                 break;
572
573         case 2:
574                 diag_printf("Internal Boot (from %s)\n",
575                                         SBMR_BT_FUSE_SEL(sbmr) ? "FUSES" : "UART/USB");
576                 break;
577
578         case 3:
579                 diag_printf("Serial Boot Loader\n");
580         }
581         diag_printf("Boot Medium: ");
582         switch (SBMR_BMOD(sbmr)) {
583         case 0:
584         case 2:
585                 if (bt_mem == 0) {
586                         diag_printf("WEIM %s\n", SBMR_BOOT_CFG1(sbmr) & (1 << 3) ?
587                                                 "NOR" : "OneNAND");
588                 } else if (bt_mem == 2) {
589                         diag_printf("HD %sATA\n", SBMR_BOOT_CFG1(sbmr) & (1 << 3) ?
590                                                 "S" : "P");
591                 } else if (bt_mem == 3) {
592                         diag_printf("Serial ROM %s\n", SBMR_BOOT_CFG1(sbmr) & (1 << 3) ?
593                                                 "SPI" : "I2C");
594                 } else if ((bt_mem & ~1) == 4) {
595                         diag_printf("SD %s speed\n", SBMR_BOOT_CFG1(sbmr) & (1 << 3) ?
596                                                 "low" : "high");
597                 } else if ((bt_mem & ~1) == 6) {
598                         diag_printf("MMC %s speed\n", SBMR_BOOT_CFG1(sbmr) & (1 << 3) ?
599                                                 "low" : "high");
600                 } else if (bt_mem & (1 << 3)) {
601                         diag_printf("NAND\n");
602                 } else {
603                         diag_printf("UNKNOWN: 0x%x\n", bt_mem);
604                 }
605                 break;
606
607         case 1:
608                 diag_printf("UNKNOWN\n");
609                 break;
610
611         case 3:
612                 diag_printf("UART/USB\n");
613         }
614         diag_printf("Boot Clock:  %d MHz\n",
615                                 (SBMR_BOOT_CFG1(sbmr) & (1 << 1)) ? 400 : 800);
616         diag_printf("OSC Freq:    %s\n",
617                                 (SBMR_BOOT_CFG2(sbmr) & (1 << 3)) ? " 24 MHz" : "auto");
618         diag_printf("PLL2 Freq:   %d MHz\n",
619                                 (SBMR_BOOT_CFG2(sbmr) & (1 << 4)) ? 333 : 400);
620         diag_printf("Secure Boot: %s\n",
621                                 (SBMR_BOOT_CFG2(sbmr) & (2 << 0)) ? "On" : "Off");
622 }
623
624 RedBoot_init(show_sys_info, RedBoot_INIT_LAST);