Updated support for Zynos/adm5120eb boards, thanks Gabor
[openwrt.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 #define DUMMY_BOARD()   {.mach_type = MACH_ADM5120_UNKNOWN}
239
240 struct mylo_board {
241         u16     vid;
242         u16     did;
243         u16     svid;
244         u16     sdid;
245         unsigned long   mach_type;
246 };
247
248
249 #define MYLO_BOARD(v,d,sv,sd,mt) { .vid = (v), .did = (d), .svid = (sv), \
250         .sdid = (sd), .mach_type = (mt) }
251
252 #define COMPEX_BOARD(d,mt) MYLO_BOARD(VENID_COMPEX,(d),VENID_COMPEX,(d),(mt))
253
254 static struct mylo_board  __initdata mylo_boards[] = {
255         COMPEX_BOARD(DEVID_COMPEX_NP27G, MACH_ADM5120_NP27G),
256         COMPEX_BOARD(DEVID_COMPEX_NP28G, MACH_ADM5120_NP28G),
257         COMPEX_BOARD(DEVID_COMPEX_NP28GHS, MACH_ADM5120_NP28GHS),
258         COMPEX_BOARD(DEVID_COMPEX_WP54G, MACH_ADM5120_WP54G),
259         COMPEX_BOARD(DEVID_COMPEX_WP54Gv1C, MACH_ADM5120_WP54Gv1C),
260         COMPEX_BOARD(DEVID_COMPEX_WP54AG, MACH_ADM5120_WP54AG),
261         COMPEX_BOARD(DEVID_COMPEX_WPP54G, MACH_ADM5120_WPP54G),
262         COMPEX_BOARD(DEVID_COMPEX_WPP54AG, MACH_ADM5120_WPP54AG),
263         DUMMY_BOARD()
264 };
265
266 #define ROUTERBOARD_NAME_LEN    16
267
268 struct routerboard {
269         unsigned long   mach_type;
270         char    name[ROUTERBOARD_NAME_LEN];
271 };
272
273 #define ROUTERBOARD(n, mt) { .name = (n), .mach_type = (mt) }
274 static struct routerboard  __initdata routerboards[] = {
275         ROUTERBOARD("111", MACH_ADM5120_RB_111),
276         ROUTERBOARD("112", MACH_ADM5120_RB_112),
277         ROUTERBOARD("133", MACH_ADM5120_RB_133),
278         ROUTERBOARD("133C", MACH_ADM5120_RB_133C),
279         ROUTERBOARD("miniROUTER", MACH_ADM5120_RB_150),
280         ROUTERBOARD("153", MACH_ADM5120_RB_150),
281         DUMMY_BOARD()
282 };
283
284 struct zynos_board {
285         unsigned long   mach_type;
286         unsigned int    vendor_id;
287         u16             board_id;
288 };
289
290 #define ZYNOS_BOARD(vi, bi, mt) { .vendor_id = (vi), .board_id = (bi), \
291                 .mach_type = (mt) }
292
293 #define ZYXEL_BOARD(bi, mt) ZYNOS_BOARD(ZYNOS_VENDOR_ID_ZYXEL, bi, mt)
294 #define DLINK_BOARD(bi, mt) ZYNOS_BOARD(ZYNOS_VENDOR_ID_DLINK, bi, mt)
295 #define LUCENT_BOARD(bi, mt) ZYNOS_BOARD(ZYNOS_VENDOR_ID_LUCENT, bi, mt)
296
297 static struct zynos_board __initdata zynos_boards[] = {
298         ZYXEL_BOARD(ZYNOS_BOARD_HS100, MACH_ADM5120_HS100),
299         ZYXEL_BOARD(ZYNOS_BOARD_P334, MACH_ADM5120_P334),
300         ZYXEL_BOARD(ZYNOS_BOARD_P334U, MACH_ADM5120_P334U),
301         ZYXEL_BOARD(ZYNOS_BOARD_P334W, MACH_ADM5120_P334W),
302         ZYXEL_BOARD(ZYNOS_BOARD_P334WH, MACH_ADM5120_P334WH),
303         ZYXEL_BOARD(ZYNOS_BOARD_P334WHD, MACH_ADM5120_P334WHD),
304         ZYXEL_BOARD(ZYNOS_BOARD_P334WT, MACH_ADM5120_P334WT),
305         ZYXEL_BOARD(ZYNOS_BOARD_P335, MACH_ADM5120_P335),
306         ZYXEL_BOARD(ZYNOS_BOARD_P335PLUS, MACH_ADM5120_P335PLUS),
307         ZYXEL_BOARD(ZYNOS_BOARD_P335U, MACH_ADM5120_P335U),
308         DUMMY_BOARD()
309 };
310
311 /*
312  * Helper routines
313  */
314 static inline u16 read_le16(void *buf)
315 {
316         u8 *p;
317
318         p = buf;
319         return ((u16)p[0] + ((u16)p[1] << 8));
320 }
321
322 static inline u32 read_le32(void *buf)
323 {
324         u8 *p;
325
326         p = buf;
327         return ((u32)p[0] + ((u32)p[1] << 8) + ((u32)p[2] << 16) +
328                 ((u32)p[3] << 24));
329 }
330
331 static inline u16 read_be16(void *buf)
332 {
333         u8 *p;
334
335         p = buf;
336         return (((u16)p[0] << 8) + (u16)p[1]);
337 }
338
339 static inline u32 read_be32(void *buf)
340 {
341         u8 *p;
342
343         p = buf;
344         return (((u32)p[0] << 24) + ((u32)p[1] << 16) + ((u32)p[2] << 8) +
345                 ((u32)p[3]));
346 }
347
348 /*
349  * CFE based boards
350  */
351 #define CFE_EPTSEAL     0x43464531 /* CFE1 is the magic number to recognize CFE
352 from other bootloaders */
353
354 static int __init cfe_present(void)
355 {
356         /*
357          * This method only works, when we are booted directly from the CFE.
358          */
359         u32 cfe_handle = (u32) fw_arg0;
360         u32 cfe_a1_val = (u32) fw_arg1;
361         u32 cfe_entry = (u32) fw_arg2;
362         u32 cfe_seal = (u32) fw_arg3;
363
364         /* Check for CFE by finding the CFE magic number */
365         if (cfe_seal != CFE_EPTSEAL) {
366                 /* We are not booted from CFE */
367                 return 0;
368         }
369
370         /* cfe_a1_val must be 0, because only one CPU present in the ADM5120 SoC
371 */
372         if (cfe_a1_val != 0) {
373                 return 0;
374         }
375
376         /* The cfe_handle, and the cfe_entry must be kernel mode addresses */
377         if ((cfe_handle < KSEG0) || (cfe_entry < KSEG0)) {
378                 return 0;
379         }
380
381         return 1;
382 }
383
384 static unsigned long __init cfe_detect_board(void)
385 {
386         return MACH_ADM5120_WP54G_WRT;
387 }
388
389 /*
390  * MyLoader based boards
391  */
392 #define SYS_PARAMS_ADDR         KSEG1ADDR(ADM5120_SRAM0_BASE+0x0F000)
393 #define BOARD_PARAMS_ADDR       KSEG1ADDR(ADM5120_SRAM0_BASE+0x0F800)
394 #define PART_TABLE_ADDR         KSEG1ADDR(ADM5120_SRAM0_BASE+0x10000)
395
396 static unsigned long __init myloader_detect_board(void)
397 {
398         struct mylo_system_params *sysp;
399         struct mylo_board_params *boardp;
400         struct mylo_partition_table *parts;
401         struct mylo_board *board;
402         unsigned long ret;
403
404         ret = MACH_ADM5120_UNKNOWN;
405
406         sysp = (struct mylo_system_params *)(SYS_PARAMS_ADDR);
407         boardp = (struct mylo_board_params *)(BOARD_PARAMS_ADDR);
408         parts = (struct mylo_partition_table *)(PART_TABLE_ADDR);
409
410         /* Check for some magic numbers */
411         if ((le32_to_cpu(sysp->magic) != MYLO_MAGIC_SYS_PARAMS) ||
412            (le32_to_cpu(boardp->magic) != MYLO_MAGIC_BOARD_PARAMS) ||
413            (le32_to_cpu(parts->magic) != MYLO_MAGIC_PARTITIONS))
414                 goto out;
415
416         for (board = mylo_boards; board->mach_type != MACH_ADM5120_UNKNOWN;
417                 board++) {
418                 if ((le16_to_cpu(sysp->vid) == board->vid) &&
419                         (le16_to_cpu(sysp->did) == board->did) &&
420                         (le16_to_cpu(sysp->svid) == board->svid) &&
421                         (le16_to_cpu(sysp->sdid) == board->sdid)) {
422                         ret = board->mach_type;
423                         break;
424                 }
425         }
426
427         /* assume MyLoader as the boot-loader */
428         adm5120_boot_loader = BOOT_LOADER_MYLOADER;
429
430 out:
431         return ret;
432 }
433
434 /*
435  * RouterBOOT based boards
436  */
437 static int __init routerboot_find_tag(u8 *buf, u16 tagid, void **tagval,
438         u16 *taglen)
439 {
440         u16 id,len;
441         int ret;
442
443         ret = -1;
444         /* skip header */
445         buf += 8;
446         for (;;) {
447                 id = read_le16(buf);
448                 buf += 2;
449                 if (id == RB_ID_TERMINATOR)
450                         break;
451
452                 len = read_le16(buf);
453                 buf += 2;
454                 if (id == tagid) {
455                         *tagval = buf;
456                         *taglen = len;
457                         ret = 0;
458                         break;
459                 }
460
461                 buf += len;
462         }
463
464         return ret;
465 }
466
467 #define RB_HS_ADDR      KSEG1ADDR(ADM5120_SRAM0_BASE+0x1000)
468 #define RB_SS_ADDR      KSEG1ADDR(ADM5120_SRAM0_BASE+0x2000)
469 #define RB_FW_ADDR      KSEG1ADDR(ADM5120_SRAM0_BASE+0x10000)
470
471 static unsigned long __init routerboot_detect_board(void)
472 {
473         struct routerboard *board;
474         u32 magic;
475         char *name;
476         u16 namelen;
477         unsigned long ret;
478
479         ret = MACH_ADM5120_UNKNOWN;
480
481         magic = le32_to_cpu(*(u32 *)RB_HS_ADDR);
482         if (magic != RB_MAGIC_HARD)
483                 goto out;
484
485         magic = le32_to_cpu(*(u32 *)RB_SS_ADDR);
486         if ((magic != RB_MAGIC_SOFT) && (magic != RB_MAGIC_DAWN))
487                 goto out;
488
489         if (routerboot_find_tag((u8 *)RB_HS_ADDR, RB_ID_BOARD_NAME,
490                 (void *)&name, &namelen))
491                 goto out;
492
493         for (board = routerboards; board->mach_type != MACH_ADM5120_UNKNOWN;
494                 board++) {
495                 if (strncmp(board->name, name, strlen(board->name)) == 0) {
496                         ret = board->mach_type;
497                         break;
498                 }
499
500         }
501
502         /* assume RouterBOOT as the boot-loader */
503         adm5120_boot_loader = BOOT_LOADER_ROUTERBOOT;
504
505 out:
506         return ret;
507 }
508
509 /*
510  * ZyNOS based boards
511  */
512 static inline u32 zynos_dbgarea_present(u8 *data)
513 {
514         u32 t;
515
516         t = read_be32(data+5);
517         if (t != ZYNOS_MAGIC_DBGAREA1)
518                 return 0;
519
520         t = read_be32(data+9);
521         if (t != ZYNOS_MAGIC_DBGAREA2)
522                 return 0;
523
524         return 1;
525 }
526
527 #define CHECK_VENDOR(n) (strnicmp(vendor,(n),strlen(n)) == 0)
528
529 static inline unsigned int zynos_get_vendor_id(struct zynos_board_info *info)
530 {
531         unsigned char vendor[ZYNOS_NAME_LEN];
532         int i;
533
534         for (i=0; i<ZYNOS_NAME_LEN; i++)
535                 vendor[i]=info->vendor[i];
536
537         if CHECK_VENDOR(ZYNOS_VENDOR_ZYXEL)
538                 return ZYNOS_VENDOR_ID_ZYXEL;
539 #if 0
540         /* TODO: there are no known ADM5120 based boards from other vendors */
541         if CHECK_VENDOR(ZYNOS_VENDOR_DLINK)
542                 return ZYNOS_VENDOR_ID_DLINK;
543
544         if CHECK_VENDOR(ZYNOS_VENDOR_LUCENT)
545                 return ZYNOS_VENDOR_ID_LUCENT;
546
547         if CHECK_VENDOR(ZYNOS_VENDOR_NETGEAR)
548                 return ZYNOS_VENDOR_ID_NETGEAR;
549 #endif
550
551         return ZYNOS_VENDOR_ID_OTHER;
552 }
553
554 static inline u16 zynos_get_board_id(struct zynos_board_info *info)
555 {
556         return read_be16(&info->board_id);
557 }
558
559 static inline u32 zynos_get_bootext_addr(struct zynos_board_info *info)
560 {
561         return read_be32(&info->bootext_addr);
562 }
563
564
565 #define ZYNOS_INFO_ADDR         KSEG1ADDR(ADM5120_SRAM0_BASE+0x3F90)
566 #define ZYNOS_HDBG_ADDR         KSEG1ADDR(ADM5120_SRAM0_BASE+0x4000)
567 #define BOOTEXT_ADDR_MIN        KSEG1ADDR(ADM5120_SRAM0_BASE)
568 #define BOOTEXT_ADDR_MAX        (BOOTEXT_ADDR_MIN + (2*1024*1024))
569
570 static unsigned long __init zynos_detect_board(void)
571 {
572         struct zynos_board_info *info;
573         struct zynos_board *board;
574         unsigned int vendor_id;
575         u16     board_id;
576         u32     t;
577         unsigned long ret;
578
579         ret = MACH_ADM5120_UNKNOWN;
580         /* check presence of the dbgarea */
581         if (zynos_dbgarea_present((u8 *)ZYNOS_HDBG_ADDR) == 0)
582                 goto out;
583
584         info = (struct zynos_board_info *)(ZYNOS_INFO_ADDR);
585
586         /* check for a valid BootExt address */
587         t = zynos_get_bootext_addr(info);
588         if ((t < BOOTEXT_ADDR_MIN) || (t > BOOTEXT_ADDR_MAX))
589                 goto out;
590
591         vendor_id = zynos_get_vendor_id(info);
592         board_id = zynos_get_board_id(info);
593
594         for (board = zynos_boards; board->mach_type != MACH_ADM5120_UNKNOWN;
595                 board++) {
596                 if ((board->vendor_id == vendor_id) &&
597                         (board->board_id == board_id)) {
598                         ret = board->mach_type;
599                         break;
600                 }
601         }
602
603         /* assume Bootbase as the boot-loader */
604         adm5120_boot_loader = BOOT_LOADER_BOOTBASE;
605
606 out:
607         return ret;
608 }
609
610 /*
611  * U-Boot based boards
612  */
613 static int __init uboot_present(void)
614 {
615         /* FIXME: not yet implemented */
616         return 0;
617 }
618
619 static unsigned long __init uboot_detect_board(void)
620 {
621         /* FIXME: not yet implemented */
622         return MACH_ADM5120_UNKNOWN;
623 }
624
625 static void __init adm5120_detect_board(void)
626 {
627         struct adm5120_board *board;
628         unsigned long t;
629
630         adm5120_boot_loader = BOOT_LOADER_UNKNOWN;
631
632         /* Try to detect board type without bootloader */
633         t = routerboot_detect_board();
634
635         if (t == MACH_ADM5120_UNKNOWN)
636                 t = zynos_detect_board();
637
638         if (t == MACH_ADM5120_UNKNOWN)
639                 t = myloader_detect_board();
640
641         /* Try to detect bootloader type */
642         if (cfe_present()) {
643                 adm5120_boot_loader = BOOT_LOADER_CFE;
644                 if (t == MACH_ADM5120_UNKNOWN)
645                         t = cfe_detect_board();
646         } else if (uboot_present()) {
647                 adm5120_boot_loader = BOOT_LOADER_UBOOT;
648                 if (t == MACH_ADM5120_UNKNOWN)
649                         t = uboot_detect_board();
650         }
651
652         for (board = adm5120_boards; board->mach_type != MACH_ADM5120_UNKNOWN;
653                 board++) {
654                 if (board->mach_type == t)
655                         break;
656         }
657
658         memcpy(&adm5120_board, board, sizeof(adm5120_board));
659 }
660
661 /*
662  * CPU settings detection
663  */
664 #define CODE_GET_PC(c)          ((c) & CODE_PC_MASK)
665 #define CODE_GET_REV(c)         (((c) >> CODE_REV_SHIFT) & CODE_REV_MASK)
666 #define CODE_GET_PK(c)          (((c) >> CODE_PK_SHIFT) & CODE_PK_MASK)
667 #define CODE_GET_CLKS(c)        (((c) >> CODE_CLKS_SHIFT) & CODE_CLKS_MASK)
668 #define CODE_GET_NAB(c)         (((c) & CODE_NAB) != 0)
669
670 static void __init adm5120_detect_cpuinfo(void)
671 {
672         u32 code;
673         u32 clks;
674
675         code = *(u32 *)KSEG1ADDR(ADM5120_SWITCH_BASE+SWITCH_REG_CODE);
676
677         adm5120_product_code = CODE_GET_PC(code);
678         adm5120_revision = CODE_GET_REV(code);
679         adm5120_package = (CODE_GET_PK(code) == CODE_PK_BGA) ?
680                 ADM5120_PACKAGE_BGA : ADM5120_PACKAGE_PQFP;
681         adm5120_nand_boot = CODE_GET_NAB(code);
682
683         clks = CODE_GET_CLKS(code);
684         adm5120_speed = ADM5120_SPEED_175;
685         if (clks & 1)
686                 adm5120_speed += 25000000;
687         if (clks & 2)
688                 adm5120_speed += 50000000;
689 }
690
691 void __init adm5120_info_show(void)
692 {
693         /* FIXME: move this somewhere else */
694         printk("ADM%04X%s revision %d, running at %ldMHz\n",
695                 adm5120_product_code,
696                 (adm5120_package == ADM5120_PACKAGE_BGA) ? "" : "P",
697                 adm5120_revision, (adm5120_speed / 1000000)
698                 );
699         printk("Boot loader is: %s\n", boot_loader_names[adm5120_boot_loader]);
700         printk("Booted from   : %s flash\n", adm5120_nand_boot ? "NAND":"NOR");
701         printk("Board is      : %s\n", adm5120_board_name());
702 }
703
704 void __init adm5120_info_init(void)
705 {
706         adm5120_detect_cpuinfo();
707         adm5120_detect_board();
708
709         adm5120_info_show();
710 }