Fresh fixes from Gabor Juhos : detects RouterBoot, Bootbase, improve board specification
[openwrt/staging/dedeckeh.git] / target / linux / adm5120-2.6 / files / arch / mips / adm5120 / adm5120_info.c
1 /*
2 * $Id$
3 *
4 * Copyright (C) 2007 OpenWrt.org
5 * Copyright (C) 2007 Gabor Juhos <juhosg@freemail.hu>
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version.
11 */
12
13 #include <linux/types.h>
14 #include <linux/autoconf.h>
15 #include <linux/kernel.h>
16 #include <linux/init.h>
17 #include <linux/string.h>
18
19 #include <asm/bootinfo.h>
20 #include <asm/addrspace.h>
21
22 #include <asm/mach-adm5120/adm5120_defs.h>
23 #include <asm/mach-adm5120/adm5120_switch.h>
24 #include <asm/mach-adm5120/adm5120_info.h>
25 #include <asm/mach-adm5120/myloader.h>
26 #include <asm/mach-adm5120/routerboot.h>
27 #include <asm/mach-adm5120/zynos.h>
28
29 /*
30 * Globals
31 */
32 struct adm5120_board adm5120_board;
33 unsigned int adm5120_boot_loader;
34
35 unsigned int adm5120_product_code;
36 unsigned int adm5120_revision;
37 unsigned int adm5120_package;
38 unsigned int adm5120_nand_boot;
39 unsigned long adm5120_speed;
40
41 /*
42 * Locals
43 */
44 static char *boot_loader_names[BOOT_LOADER_LAST+1] = {
45 [BOOT_LOADER_UNKNOWN] = "Unknown",
46 [BOOT_LOADER_CFE] = "CFE",
47 [BOOT_LOADER_UBOOT] = "U-Boot",
48 [BOOT_LOADER_MYLOADER] = "MyLoader",
49 [BOOT_LOADER_ROUTERBOOT]= "RouterBOOT",
50 [BOOT_LOADER_BOOTBASE] = "Bootbase"
51 };
52
53 static struct adm5120_board __initdata adm5120_boards[] = {
54 {
55 .name = "Compex NetPassage 27G",
56 .mach_type = MACH_ADM5120_NP27G,
57 .has_usb = 1,
58 .iface_num = 5,
59 .flash0_size = 4*1024*1024,
60 },
61 {
62 .name = "Compex NetPassage 28G",
63 .mach_type = MACH_ADM5120_NP28G,
64 .has_usb = 0,
65 .iface_num = 4,
66 .flash0_size = 4*1024*1024,
67 },
68 {
69 .name = "Compex NP28G (HotSpot)",
70 .mach_type = MACH_ADM5120_NP28GHS,
71 .has_usb = 0,
72 .iface_num = 4,
73 .flash0_size = 4*1024*1024,
74 },
75 {
76 .name = "Compex WP54AG",
77 .mach_type = MACH_ADM5120_WP54AG,
78 .has_usb = 0,
79 .iface_num = 2,
80 .flash0_size = 4*1024*1024,
81 },
82 {
83 .name = "Compex WP54G",
84 .mach_type = MACH_ADM5120_WP54G,
85 .has_usb = 0,
86 .iface_num = 2,
87 .flash0_size = 4*1024*1024,
88 },
89 {
90 .name = "Compex WP54G-WRT",
91 .mach_type = MACH_ADM5120_WP54G_WRT,
92 .has_usb = 0,
93 .iface_num = 2,
94 .flash0_size = 4*1024*1024,
95 },
96 {
97 .name = "Compex WP54G v1C",
98 .mach_type = MACH_ADM5120_WP54Gv1C,
99 .has_usb = 0,
100 .iface_num = 2,
101 .flash0_size = 2*1024*1024,
102 },
103 {
104 .name = "Compex WPP54AG",
105 .mach_type = MACH_ADM5120_WPP54AG,
106 .has_usb = 0,
107 .iface_num = 2,
108 .flash0_size = 4*1024*1024,
109 },
110 {
111 .name = "Compex WPP54G",
112 .mach_type = MACH_ADM5120_WPP54G,
113 .has_usb = 0,
114 .iface_num = 2,
115 .flash0_size = 4*1024*1024,
116 },
117 {
118 .name = "RouterBOARD RB-111",
119 .mach_type = MACH_ADM5120_RB_111,
120 .has_usb = 0,
121 .iface_num = 1,
122 .flash0_size = 128*1024,
123 },
124 {
125 .name = "RouterBOARD RB-112",
126 .mach_type = MACH_ADM5120_RB_112,
127 .has_usb = 0,
128 .iface_num = 1,
129 .flash0_size = 128*1024,
130 },
131 {
132 .name = "RouterBOARD RB-133",
133 .mach_type = MACH_ADM5120_RB_133,
134 .has_usb = 0,
135 .iface_num = 3,
136 .flash0_size = 128*1024,
137 },
138 {
139 .name = "RouterBOARD RB-133C",
140 .mach_type = MACH_ADM5120_RB_133C,
141 .has_usb = 0,
142 .iface_num = 1,
143 .flash0_size = 128*1024,
144 },
145 {
146 .name = "RouterBOARD RB-150",
147 .mach_type = MACH_ADM5120_RB_150,
148 .has_usb = 0,
149 .iface_num = 5,
150 .flash0_size = 128*1024,
151 },
152 {
153 .name = "RouterBOARD RB-153",
154 .mach_type = MACH_ADM5120_RB_153,
155 .has_usb = 0,
156 .iface_num = 5,
157 .flash0_size = 128*1024,
158 },
159 {
160 .name = "ZyXEL HomeSafe 100/100W",
161 .mach_type = MACH_ADM5120_HS100,
162 .has_usb = 0,
163 .iface_num = 5,
164 .flash0_size = 4*1024*1024,
165 },
166 {
167 .name = "ZyXEL Prestige 334",
168 .mach_type = MACH_ADM5120_P334,
169 .has_usb = 0,
170 .iface_num = 5,
171 .flash0_size = 2*1024*1024,
172 },
173 {
174 .name = "ZyXEL Prestige 334U",
175 .mach_type = MACH_ADM5120_P334U,
176 .has_usb = 0,
177 .iface_num = 5,
178 .flash0_size = 4*1024*1024,
179 },
180 {
181 .name = "ZyXEL Prestige 334W",
182 .mach_type = MACH_ADM5120_P334W,
183 .has_usb = 0,
184 .iface_num = 5,
185 .flash0_size = 2*1024*1024,
186 },
187 {
188 .name = "ZyXEL Prestige 334WH",
189 .mach_type = MACH_ADM5120_P334WH,
190 .has_usb = 0,
191 .iface_num = 5,
192 .flash0_size = 4*1024*1024,
193 },
194 {
195 .name = "ZyXEL Prestige 334WHD",
196 .mach_type = MACH_ADM5120_P334WHD,
197 .has_usb = 0,
198 .iface_num = 5,
199 .flash0_size = 4*1024*1024,
200 },
201 {
202 .name = "ZyXEL Prestige 334WT",
203 .mach_type = MACH_ADM5120_P334WT,
204 .has_usb = 1,
205 .iface_num = 5,
206 .flash0_size = 4*1024*1024,
207 },
208 {
209 .name = "ZyXEL Prestige 335/335WT",
210 .mach_type = MACH_ADM5120_P335,
211 .has_usb = 1,
212 .iface_num = 5,
213 .flash0_size = 4*1024*1024,
214 },
215 {
216 .name = "ZyXEL Prestige 335Plus",
217 .mach_type = MACH_ADM5120_P335PLUS,
218 .has_usb = 1,
219 .iface_num = 5,
220 .flash0_size = 4*1024*1024,
221 },
222 {
223 .name = "ZyXEL Prestige 335U",
224 .mach_type = MACH_ADM5120_P335U,
225 .has_usb = 1,
226 .iface_num = 5,
227 .flash0_size = 4*1024*1024,
228 },
229 {
230 .name = "Unknown ADM5120 board",
231 .mach_type = MACH_ADM5120_UNKNOWN,
232 .has_usb = 1,
233 .iface_num = 5,
234 .flash0_size = 0,
235 }
236 };
237
238 struct mylo_board {
239 u16 vid;
240 u16 did;
241 u16 svid;
242 u16 sdid;
243 unsigned long mach_type;
244 };
245
246 #define DUMMY_BOARD() {.mach_type = MACH_ADM5120_UNKNOWN}
247
248 #define MYLO_BOARD(v,d,sv,sd,mt) { .vid = (v), .did = (d), .svid = (sv), \
249 .sdid = (sd), .mach_type = (mt) }
250
251 #define COMPEX_BOARD(d,mt) MYLO_BOARD(VENID_COMPEX,(d),VENID_COMPEX,(d),(mt))
252
253 static struct mylo_board __initdata mylo_boards[] = {
254 COMPEX_BOARD(DEVID_COMPEX_NP27G, MACH_ADM5120_NP27G),
255 COMPEX_BOARD(DEVID_COMPEX_NP28G, MACH_ADM5120_NP28G),
256 COMPEX_BOARD(DEVID_COMPEX_NP28GHS, MACH_ADM5120_NP28GHS),
257 COMPEX_BOARD(DEVID_COMPEX_WP54G, MACH_ADM5120_WP54G),
258 COMPEX_BOARD(DEVID_COMPEX_WP54Gv1C, MACH_ADM5120_WP54Gv1C),
259 COMPEX_BOARD(DEVID_COMPEX_WP54AG, MACH_ADM5120_WP54AG),
260 COMPEX_BOARD(DEVID_COMPEX_WPP54G, MACH_ADM5120_WPP54G),
261 COMPEX_BOARD(DEVID_COMPEX_WPP54AG, MACH_ADM5120_WPP54AG),
262 DUMMY_BOARD()
263 };
264
265 #define ROUTERBOARD_NAME_LEN 16
266
267 struct routerboard {
268 unsigned long mach_type;
269 char name[ROUTERBOARD_NAME_LEN];
270 };
271
272 #define ROUTERBOARD(n, mt) { .name = (n), .mach_type = (mt) }
273 static struct routerboard __initdata routerboards[] = {
274 ROUTERBOARD("111", MACH_ADM5120_RB_111),
275 ROUTERBOARD("112", MACH_ADM5120_RB_112),
276 ROUTERBOARD("133", MACH_ADM5120_RB_133),
277 ROUTERBOARD("133C", MACH_ADM5120_RB_133C),
278 ROUTERBOARD("miniROUTER", MACH_ADM5120_RB_150),
279 ROUTERBOARD("153", MACH_ADM5120_RB_150),
280 DUMMY_BOARD()
281 };
282
283 struct zynos_board {
284 unsigned long mach_type;
285 unsigned int vendor_id;
286 u16 board_id;
287 };
288
289 #define ZYNOS_VENDOR_ID_INVALID 0
290 #define ZYNOS_VENDOR_ID_ZYXEL 1
291 #define ZYNOS_VENDOR_ID_DLINK 2
292 #define ZYNOS_VENDOR_ID_LUCENT 3
293
294 #define ZYNOS_BOARD(vi, bi, mt) { .vendor_id = (vi), .board_id = (bi), \
295 .mach_type = (mt) }
296
297 #define ZYXEL_BOARD(bi, mt) ZYNOS_BOARD(ZYNOS_VENDOR_ID_ZYXEL, bi, mt)
298 #define DLINK_BOARD(bi, mt) ZYNOS_BOARD(ZYNOS_VENDOR_ID_DLINK, bi, mt)
299 #define LUCENT_BOARD(bi, mt) ZYNOS_BOARD(ZYNOS_VENDOR_ID_LUCENT, bi, mt)
300
301 static struct zynos_board __initdata zynos_boards[] = {
302 ZYXEL_BOARD(ZYNOS_BOARD_HS100, MACH_ADM5120_HS100),
303 ZYXEL_BOARD(ZYNOS_BOARD_P334, MACH_ADM5120_P334),
304 ZYXEL_BOARD(ZYNOS_BOARD_P334U, MACH_ADM5120_P334U),
305 ZYXEL_BOARD(ZYNOS_BOARD_P334W, MACH_ADM5120_P334W),
306 ZYXEL_BOARD(ZYNOS_BOARD_P334WH, MACH_ADM5120_P334WH),
307 ZYXEL_BOARD(ZYNOS_BOARD_P334WHD, MACH_ADM5120_P334WHD),
308 ZYXEL_BOARD(ZYNOS_BOARD_P334WT, MACH_ADM5120_P334WT),
309 ZYXEL_BOARD(ZYNOS_BOARD_P335, MACH_ADM5120_P335),
310 ZYXEL_BOARD(ZYNOS_BOARD_P335PLUS, MACH_ADM5120_P335PLUS),
311 ZYXEL_BOARD(ZYNOS_BOARD_P335U, MACH_ADM5120_P335U),
312 DUMMY_BOARD()
313 };
314
315 /*
316 * Helper routines
317 */
318 static inline u16 read_le16(void *buf)
319 {
320 u8 *p;
321
322 p = buf;
323 return ((u16)p[0] + ((u16)p[1] << 8));
324 }
325
326 static inline u32 read_le32(void *buf)
327 {
328 u8 *p;
329
330 p = buf;
331 return ((u32)p[0] + ((u32)p[1] << 8) + ((u32)p[2] << 16) +
332 ((u32)p[3] << 24));
333 }
334
335 /*
336 * CFE based boards
337 */
338 #define CFE_EPTSEAL 0x43464531 /* CFE1 is the magic number to recognize CFE
339 from other bootloaders */
340
341 static int __init cfe_present(void)
342 {
343 /*
344 * This method only works, when we are booted directly from the CFE.
345 */
346 u32 cfe_handle = (u32) fw_arg0;
347 u32 cfe_a1_val = (u32) fw_arg1;
348 u32 cfe_entry = (u32) fw_arg2;
349 u32 cfe_seal = (u32) fw_arg3;
350
351 /* Check for CFE by finding the CFE magic number */
352 if (cfe_seal != CFE_EPTSEAL) {
353 /* We are not booted from CFE */
354 return 0;
355 }
356
357 /* cfe_a1_val must be 0, because only one CPU present in the ADM5120 SoC
358 */
359 if (cfe_a1_val != 0) {
360 return 0;
361 }
362
363 /* The cfe_handle, and the cfe_entry must be kernel mode addresses */
364 if ((cfe_handle < KSEG0) || (cfe_entry < KSEG0)) {
365 return 0;
366 }
367
368 return 1;
369 }
370
371 static unsigned long __init cfe_detect_board(void)
372 {
373 return MACH_ADM5120_WP54G_WRT;
374 }
375
376 /*
377 * MyLoader based boards
378 */
379 #define SYS_PARAMS_ADDR KSEG1ADDR(ADM5120_SRAM0_BASE+0x0F000)
380 #define BOARD_PARAMS_ADDR KSEG1ADDR(ADM5120_SRAM0_BASE+0x0F800)
381 #define PART_TABLE_ADDR KSEG1ADDR(ADM5120_SRAM0_BASE+0x10000)
382
383 static unsigned long __init myloader_detect_board(void)
384 {
385 struct mylo_system_params *sysp;
386 struct mylo_board_params *boardp;
387 struct mylo_partition_table *parts;
388 struct mylo_board *board;
389 unsigned long ret;
390
391 ret = MACH_ADM5120_UNKNOWN;
392
393 sysp = (struct mylo_system_params *)(SYS_PARAMS_ADDR);
394 boardp = (struct mylo_board_params *)(BOARD_PARAMS_ADDR);
395 parts = (struct mylo_partition_table *)(PART_TABLE_ADDR);
396
397 /* Check for some magic numbers */
398 if ((le32_to_cpu(sysp->magic) != MYLO_MAGIC_SYS_PARAMS) ||
399 (le32_to_cpu(boardp->magic) != MYLO_MAGIC_BOARD_PARAMS) ||
400 (le32_to_cpu(parts->magic) != MYLO_MAGIC_PARTITIONS))
401 goto out;
402
403 for (board = mylo_boards; board->mach_type != MACH_ADM5120_UNKNOWN;
404 board++) {
405 if ((le16_to_cpu(sysp->vid) == board->vid) &&
406 (le16_to_cpu(sysp->did) == board->did) &&
407 (le16_to_cpu(sysp->svid) == board->svid) &&
408 (le16_to_cpu(sysp->sdid) == board->sdid)) {
409 ret = board->mach_type;
410 break;
411 }
412 }
413
414 /* assume MyLoader as the boot-loader */
415 adm5120_boot_loader = BOOT_LOADER_MYLOADER;
416
417 out:
418 return ret;
419 }
420
421 /*
422 * RouterBOOT based boards
423 */
424 static int __init routerboot_find_tag(u8 *buf, u16 tagid, void **tagval,
425 u16 *taglen)
426 {
427 u16 id,len;
428 int ret;
429
430 ret = -1;
431 /* skip header */
432 buf += 8;
433 for (;;) {
434 id = read_le16(buf);
435 buf += 2;
436 if (id == RB_ID_TERMINATOR)
437 break;
438
439 len = read_le16(buf);
440 buf += 2;
441 if (id == tagid) {
442 *tagval = buf;
443 *taglen = len;
444 ret = 0;
445 break;
446 }
447
448 buf += len;
449 }
450
451 return ret;
452 }
453
454 #define RB_HS_ADDR KSEG1ADDR(ADM5120_SRAM0_BASE+0x1000)
455 #define RB_SS_ADDR KSEG1ADDR(ADM5120_SRAM0_BASE+0x2000)
456 #define RB_FW_ADDR KSEG1ADDR(ADM5120_SRAM0_BASE+0x10000)
457
458 static unsigned long __init routerboot_detect_board(void)
459 {
460 struct routerboard *board;
461 u32 magic;
462 char *name;
463 u16 namelen;
464 unsigned long ret;
465
466 ret = MACH_ADM5120_UNKNOWN;
467
468 magic = le32_to_cpu(*(u32 *)RB_HS_ADDR);
469 if (magic != RB_MAGIC_HARD)
470 goto out;
471
472 magic = le32_to_cpu(*(u32 *)RB_SS_ADDR);
473 if ((magic != RB_MAGIC_SOFT) && (magic != RB_MAGIC_DAWN))
474 goto out;
475
476 if (routerboot_find_tag((u8 *)RB_HS_ADDR, RB_ID_BOARD_NAME,
477 (void *)&name, &namelen))
478 goto out;
479
480 for (board = routerboards; board->mach_type != MACH_ADM5120_UNKNOWN;
481 board++) {
482 if (strncmp(board->name, name, strlen(board->name)) == 0) {
483 ret = board->mach_type;
484 break;
485 }
486
487 }
488
489 /* assume RouterBOOT as the boot-loader */
490 adm5120_boot_loader = BOOT_LOADER_ROUTERBOOT;
491
492 out:
493 return ret;
494 }
495
496 /*
497 * ZyNOS based boards
498 */
499 #define CHECK_VENDOR(n) (strnicmp(vendor, ZYNOS_VENDOR_ZYXEL, \
500 strlen(ZYNOS_VENDOR_ZYXEL)) == 0)
501
502 static unsigned int __init zynos_get_vendor_id(unsigned char *vendor)
503 {
504 int ret;
505
506 ret = ZYNOS_VENDOR_ID_INVALID;
507
508 if CHECK_VENDOR(ZYNOS_VENDOR_ZYXEL)
509 ret = ZYNOS_VENDOR_ID_ZYXEL;
510 #if 0
511 /* TODO: there are no known ADM5120 based boards from other vendors */
512 else if CHECK_VENDOR(ZYNOS_VENDOR_DLINK)
513 ret = ZYNOS_VENDOR_ID_DLINK;
514 else if CHECK_VENDOR(ZYNOS_VENDOR_LUCENT)
515 ret = ZYNOS_VENDOR_ID_LUCENT;
516 #endif
517
518 return ret;
519 }
520
521 #define ZYNOS_INFO_ADDR KSEG1ADDR(ADM5120_SRAM0_BASE+0x3F90)
522 #define BOOTEXT_ADDR_2M 0xBFC08000
523 #define BOOTEXT_ADDR_4M 0xBFC10000
524
525 static unsigned long __init zynos_detect_board(void)
526 {
527 struct zynos_board_info *info;
528 struct zynos_board *board;
529 unsigned int vendor_id;
530 u32 bootext_addr;
531 unsigned long ret;
532
533 ret = MACH_ADM5120_UNKNOWN;
534
535 info = (struct zynos_board_info *)(ZYNOS_INFO_ADDR);
536 vendor_id = zynos_get_vendor_id(&info->vendor);
537 if (vendor_id == ZYNOS_VENDOR_ID_INVALID)
538 goto out;
539
540 bootext_addr = be32_to_cpu(info->bootext_addr);
541 if ((bootext_addr != BOOTEXT_ADDR_2M) ||
542 (bootext_addr != BOOTEXT_ADDR_4M))
543 goto out;
544
545 for (board = zynos_boards; board->mach_type != MACH_ADM5120_UNKNOWN;
546 board++) {
547 if ((board->vendor_id == vendor_id) &&
548 (board->board_id == be16_to_cpu(info->board_id))) {
549 ret = board->mach_type;
550 break;
551 }
552 }
553
554 /* assume Bootbase as the boot-loader */
555 adm5120_boot_loader = BOOT_LOADER_BOOTBASE;
556
557 out:
558 return ret;
559 }
560
561 /*
562 * U-Boot based boards
563 */
564 static int __init uboot_present(void)
565 {
566 /* FIXME: not yet implemented */
567 return 0;
568 }
569
570 static unsigned long __init uboot_detect_board(void)
571 {
572 /* FIXME: not yet implemented */
573 return MACH_ADM5120_UNKNOWN;
574 }
575
576 static void __init adm5120_detect_board(void)
577 {
578 struct adm5120_board *board;
579 unsigned long t;
580
581 adm5120_boot_loader = BOOT_LOADER_UNKNOWN;
582
583 /* Try to detect board type without bootloader */
584 t = routerboot_detect_board();
585
586 if (t == MACH_ADM5120_UNKNOWN)
587 t = zynos_detect_board();
588
589 if (t == MACH_ADM5120_UNKNOWN)
590 t = myloader_detect_board();
591
592 /* Try to detect bootloader type */
593 if (cfe_present()) {
594 adm5120_boot_loader = BOOT_LOADER_CFE;
595 if (t == MACH_ADM5120_UNKNOWN)
596 t = cfe_detect_board();
597 } else if (uboot_present()) {
598 adm5120_boot_loader = BOOT_LOADER_UBOOT;
599 if (t == MACH_ADM5120_UNKNOWN)
600 t = uboot_detect_board();
601 }
602
603 for (board = adm5120_boards; board->mach_type != MACH_ADM5120_UNKNOWN;
604 board++) {
605 if (board->mach_type == t)
606 break;
607 }
608
609 memcpy(&adm5120_board, board, sizeof(adm5120_board));
610 }
611
612 /*
613 * CPU settings detection
614 */
615 #define CODE_GET_PC(c) ((c) & CODE_PC_MASK)
616 #define CODE_GET_REV(c) (((c) >> CODE_REV_SHIFT) & CODE_REV_MASK)
617 #define CODE_GET_PK(c) (((c) >> CODE_PK_SHIFT) & CODE_PK_MASK)
618 #define CODE_GET_CLKS(c) (((c) >> CODE_CLKS_SHIFT) & CODE_CLKS_MASK)
619 #define CODE_GET_NAB(c) (((c) & CODE_NAB) != 0)
620
621 static void __init adm5120_detect_cpuinfo(void)
622 {
623 u32 code;
624 u32 clks;
625
626 code = *(u32 *)KSEG1ADDR(ADM5120_SWITCH_BASE+SWITCH_REG_CODE);
627
628 adm5120_product_code = CODE_GET_PC(code);
629 adm5120_revision = CODE_GET_REV(code);
630 adm5120_package = (CODE_GET_PK(code) == CODE_PK_BGA) ?
631 ADM5120_PACKAGE_BGA : ADM5120_PACKAGE_PQFP;
632 adm5120_nand_boot = CODE_GET_NAB(code);
633
634 clks = CODE_GET_CLKS(code);
635 adm5120_speed = ADM5120_SPEED_175;
636 if (clks & 1)
637 adm5120_speed += 25000000;
638 if (clks & 2)
639 adm5120_speed += 50000000;
640 }
641
642 void __init adm5120_info_show(void)
643 {
644 /* FIXME: move this somewhere else */
645 printk("ADM%04X%s revision %d, running at %ldMHz\n",
646 adm5120_product_code,
647 (adm5120_package == ADM5120_PACKAGE_BGA) ? "" : "P",
648 adm5120_revision, (adm5120_speed / 1000000)
649 );
650 printk("Boot loader is: %s\n", boot_loader_names[adm5120_boot_loader]);
651 printk("Booted from : %s flash\n", adm5120_nand_boot ? "NAND":"NOR");
652 printk("Board is : %s\n", adm5120_board_name());
653 }
654
655 void __init adm5120_info_init(void)
656 {
657 adm5120_detect_cpuinfo();
658 adm5120_detect_board();
659
660 adm5120_info_show();
661 }