Fix routeboard board detection, add some new ZyXEL boards, thanks to Gabor Juhos
[openwrt/svn-archive/archive.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 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 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 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 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 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 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 ES-2108",
161 .mach_type = MACH_ADM5120_ES2108,
162 .has_usb = 0,
163 .iface_num = 0,
164 .flash0_size = 4*1024*1024,
165 },
166 {
167 .name = "ZyXEL ES-2108-F",
168 .mach_type = MACH_ADM5120_ES2108F,
169 .has_usb = 0,
170 .iface_num = 0,
171 .flash0_size = 4*1024*1024,
172 },
173 {
174 .name = "ZyXEL ES-2108-G",
175 .mach_type = MACH_ADM5120_ES2108G,
176 .has_usb = 0,
177 .iface_num = 0,
178 .flash0_size = 4*1024*1024,
179 },
180 {
181 .name = "ZyXEL ES-2108-LC",
182 .mach_type = MACH_ADM5120_ES2108LC,
183 .has_usb = 0,
184 .iface_num = 0,
185 .flash0_size = 4*1024*1024,
186 },
187 {
188 .name = "ZyXEL ES-2108PWR",
189 .mach_type = MACH_ADM5120_ES2108PWR,
190 .has_usb = 0,
191 .iface_num = 0,
192 .flash0_size = 4*1024*1024,
193 },
194 {
195 .name = "ZyXEL HomeSafe 100/100W",
196 .mach_type = MACH_ADM5120_HS100,
197 .has_usb = 0,
198 .iface_num = 5,
199 .flash0_size = 4*1024*1024,
200 },
201 {
202 .name = "ZyXEL Prestige 334",
203 .mach_type = MACH_ADM5120_P334,
204 .has_usb = 0,
205 .iface_num = 5,
206 .flash0_size = 2*1024*1024,
207 },
208 {
209 .name = "ZyXEL Prestige 334U",
210 .mach_type = MACH_ADM5120_P334U,
211 .has_usb = 0,
212 .iface_num = 5,
213 .flash0_size = 4*1024*1024,
214 },
215 {
216 .name = "ZyXEL Prestige 334W",
217 .mach_type = MACH_ADM5120_P334W,
218 .has_usb = 0,
219 .iface_num = 5,
220 .flash0_size = 2*1024*1024,
221 },
222 {
223 .name = "ZyXEL Prestige 334WH",
224 .mach_type = MACH_ADM5120_P334WH,
225 .has_usb = 0,
226 .iface_num = 5,
227 .flash0_size = 4*1024*1024,
228 },
229 {
230 .name = "ZyXEL Prestige 334WHD",
231 .mach_type = MACH_ADM5120_P334WHD,
232 .has_usb = 0,
233 .iface_num = 5,
234 .flash0_size = 4*1024*1024,
235 },
236 {
237 .name = "ZyXEL Prestige 334WT",
238 .mach_type = MACH_ADM5120_P334WT,
239 .has_usb = 1,
240 .iface_num = 5,
241 .flash0_size = 4*1024*1024,
242 },
243 {
244 .name = "ZyXEL Prestige 335/335WT",
245 .mach_type = MACH_ADM5120_P335,
246 .has_usb = 1,
247 .iface_num = 5,
248 .flash0_size = 4*1024*1024,
249 },
250 {
251 .name = "ZyXEL Prestige 335Plus",
252 .mach_type = MACH_ADM5120_P335PLUS,
253 .has_usb = 1,
254 .iface_num = 5,
255 .flash0_size = 4*1024*1024,
256 },
257 {
258 .name = "ZyXEL Prestige 335U",
259 .mach_type = MACH_ADM5120_P335U,
260 .has_usb = 1,
261 .iface_num = 5,
262 .flash0_size = 4*1024*1024,
263 },
264 {
265 .name = "Unknown ADM5120 board",
266 .mach_type = MACH_ADM5120_UNKNOWN,
267 .has_usb = 1,
268 .iface_num = 5,
269 .flash0_size = 0,
270 }
271 };
272
273 #define DUMMY_BOARD() {.mach_type = MACH_ADM5120_UNKNOWN}
274
275 struct mylo_board {
276 u16 vid;
277 u16 did;
278 u16 svid;
279 u16 sdid;
280 unsigned long mach_type;
281 };
282
283
284 #define MYLO_BOARD(v,d,sv,sd,mt) { .vid = (v), .did = (d), .svid = (sv), \
285 .sdid = (sd), .mach_type = (mt) }
286
287 #define COMPEX_BOARD(d,mt) MYLO_BOARD(VENID_COMPEX,(d),VENID_COMPEX,(d),(mt))
288
289 static struct mylo_board __initdata mylo_boards[] = {
290 COMPEX_BOARD(DEVID_COMPEX_NP27G, MACH_ADM5120_NP27G),
291 COMPEX_BOARD(DEVID_COMPEX_NP28G, MACH_ADM5120_NP28G),
292 COMPEX_BOARD(DEVID_COMPEX_NP28GHS, MACH_ADM5120_NP28GHS),
293 COMPEX_BOARD(DEVID_COMPEX_WP54G, MACH_ADM5120_WP54G),
294 COMPEX_BOARD(DEVID_COMPEX_WP54Gv1C, MACH_ADM5120_WP54Gv1C),
295 COMPEX_BOARD(DEVID_COMPEX_WP54AG, MACH_ADM5120_WP54AG),
296 COMPEX_BOARD(DEVID_COMPEX_WPP54G, MACH_ADM5120_WPP54G),
297 COMPEX_BOARD(DEVID_COMPEX_WPP54AG, MACH_ADM5120_WPP54AG),
298 DUMMY_BOARD()
299 };
300
301 #define ROUTERBOARD_NAME_LEN 16
302
303 struct routerboard {
304 unsigned long mach_type;
305 char name[ROUTERBOARD_NAME_LEN];
306 };
307
308 #define ROUTERBOARD(n, mt) { .name = (n), .mach_type = (mt) }
309 static struct routerboard __initdata routerboards[] = {
310 ROUTERBOARD("111", MACH_ADM5120_RB_111),
311 ROUTERBOARD("112", MACH_ADM5120_RB_112),
312 ROUTERBOARD("133", MACH_ADM5120_RB_133),
313 ROUTERBOARD("133C", MACH_ADM5120_RB_133C),
314 ROUTERBOARD("miniROUTER", MACH_ADM5120_RB_150),
315 ROUTERBOARD("153", MACH_ADM5120_RB_150),
316 DUMMY_BOARD()
317 };
318
319 struct zynos_board {
320 unsigned long mach_type;
321 unsigned int vendor_id;
322 u16 board_id;
323 };
324
325 #define ZYNOS_BOARD(vi, bi, mt) { .vendor_id = (vi), .board_id = (bi), \
326 .mach_type = (mt) }
327
328 #define ZYXEL_BOARD(bi, mt) ZYNOS_BOARD(ZYNOS_VENDOR_ID_ZYXEL, bi, mt)
329 #define DLINK_BOARD(bi, mt) ZYNOS_BOARD(ZYNOS_VENDOR_ID_DLINK, bi, mt)
330 #define LUCENT_BOARD(bi, mt) ZYNOS_BOARD(ZYNOS_VENDOR_ID_LUCENT, bi, mt)
331
332 static struct zynos_board __initdata zynos_boards[] = {
333 ZYXEL_BOARD(ZYNOS_BOARD_HS100, MACH_ADM5120_HS100),
334 ZYXEL_BOARD(ZYNOS_BOARD_P334, MACH_ADM5120_P334),
335 ZYXEL_BOARD(ZYNOS_BOARD_P334U, MACH_ADM5120_P334U),
336 ZYXEL_BOARD(ZYNOS_BOARD_P334W, MACH_ADM5120_P334W),
337 ZYXEL_BOARD(ZYNOS_BOARD_P334WH, MACH_ADM5120_P334WH),
338 ZYXEL_BOARD(ZYNOS_BOARD_P334WHD, MACH_ADM5120_P334WHD),
339 ZYXEL_BOARD(ZYNOS_BOARD_P334WT, MACH_ADM5120_P334WT),
340 ZYXEL_BOARD(ZYNOS_BOARD_P335, MACH_ADM5120_P335),
341 ZYXEL_BOARD(ZYNOS_BOARD_P335PLUS, MACH_ADM5120_P335PLUS),
342 ZYXEL_BOARD(ZYNOS_BOARD_P335U, MACH_ADM5120_P335U),
343 DUMMY_BOARD()
344 };
345
346 /*
347 * Helper routines
348 */
349 static inline u16 read_le16(void *buf)
350 {
351 u8 *p;
352
353 p = buf;
354 return ((u16)p[0] + ((u16)p[1] << 8));
355 }
356
357 static inline u32 read_le32(void *buf)
358 {
359 u8 *p;
360
361 p = buf;
362 return ((u32)p[0] + ((u32)p[1] << 8) + ((u32)p[2] << 16) +
363 ((u32)p[3] << 24));
364 }
365
366 static inline u16 read_be16(void *buf)
367 {
368 u8 *p;
369
370 p = buf;
371 return (((u16)p[0] << 8) + (u16)p[1]);
372 }
373
374 static inline u32 read_be32(void *buf)
375 {
376 u8 *p;
377
378 p = buf;
379 return (((u32)p[0] << 24) + ((u32)p[1] << 16) + ((u32)p[2] << 8) +
380 ((u32)p[3]));
381 }
382
383 /*
384 * CFE based boards
385 */
386 #define CFE_EPTSEAL 0x43464531 /* CFE1 is the magic number to recognize CFE
387 from other bootloaders */
388
389 static int __init cfe_present(void)
390 {
391 /*
392 * This method only works, when we are booted directly from the CFE.
393 */
394 u32 cfe_handle = (u32) fw_arg0;
395 u32 cfe_a1_val = (u32) fw_arg1;
396 u32 cfe_entry = (u32) fw_arg2;
397 u32 cfe_seal = (u32) fw_arg3;
398
399 /* Check for CFE by finding the CFE magic number */
400 if (cfe_seal != CFE_EPTSEAL) {
401 /* We are not booted from CFE */
402 return 0;
403 }
404
405 /* cfe_a1_val must be 0, because only one CPU present in the ADM5120 */
406 if (cfe_a1_val != 0) {
407 return 0;
408 }
409
410 /* The cfe_handle, and the cfe_entry must be kernel mode addresses */
411 if ((cfe_handle < KSEG0) || (cfe_entry < KSEG0)) {
412 return 0;
413 }
414
415 return 1;
416 }
417
418 static unsigned long __init cfe_detect_board(void)
419 {
420 return MACH_ADM5120_WP54G_WRT;
421 }
422
423 /*
424 * MyLoader based boards
425 */
426 #define SYS_PARAMS_ADDR KSEG1ADDR(ADM5120_SRAM0_BASE+0x0F000)
427 #define BOARD_PARAMS_ADDR KSEG1ADDR(ADM5120_SRAM0_BASE+0x0F800)
428 #define PART_TABLE_ADDR KSEG1ADDR(ADM5120_SRAM0_BASE+0x10000)
429
430 static unsigned long __init myloader_detect_board(void)
431 {
432 struct mylo_system_params *sysp;
433 struct mylo_board_params *boardp;
434 struct mylo_partition_table *parts;
435 struct mylo_board *board;
436 unsigned long ret;
437
438 ret = MACH_ADM5120_UNKNOWN;
439
440 sysp = (struct mylo_system_params *)(SYS_PARAMS_ADDR);
441 boardp = (struct mylo_board_params *)(BOARD_PARAMS_ADDR);
442 parts = (struct mylo_partition_table *)(PART_TABLE_ADDR);
443
444 /* Check for some magic numbers */
445 if ((le32_to_cpu(sysp->magic) != MYLO_MAGIC_SYS_PARAMS) ||
446 (le32_to_cpu(boardp->magic) != MYLO_MAGIC_BOARD_PARAMS) ||
447 (le32_to_cpu(parts->magic) != MYLO_MAGIC_PARTITIONS))
448 goto out;
449
450 for (board = mylo_boards; board->mach_type != MACH_ADM5120_UNKNOWN;
451 board++) {
452 if ((le16_to_cpu(sysp->vid) == board->vid) &&
453 (le16_to_cpu(sysp->did) == board->did) &&
454 (le16_to_cpu(sysp->svid) == board->svid) &&
455 (le16_to_cpu(sysp->sdid) == board->sdid)) {
456 ret = board->mach_type;
457 break;
458 }
459 }
460
461 /* assume MyLoader as the boot-loader */
462 adm5120_boot_loader = BOOT_LOADER_MYLOADER;
463
464 out:
465 return ret;
466 }
467
468 /*
469 * RouterBOOT based boards
470 */
471 static int __init routerboot_load_hs(u8 *buf, u16 buflen,
472 struct rb_hard_settings *hs)
473 {
474 u16 id,len;
475 u8 *mac;
476 int i,j;
477
478 if (buflen < 4)
479 return -1;
480
481 if (read_le32(buf) != RB_MAGIC_HARD)
482 return -1;
483
484 /* skip magic value */
485 buf += 4;
486 buflen -= 4;
487
488 while (buflen > 2) {
489 id = read_le16(buf);
490 buf += 2;
491 buflen -= 2;
492 if (id == RB_ID_TERMINATOR || buflen < 2)
493 break;
494
495 len = read_le16(buf);
496 buf += 2;
497 buflen -= 2;
498
499 if (buflen < len)
500 break;
501
502 switch (id) {
503 case RB_ID_BIOS_VERSION:
504 hs->bios_ver = (char *)buf;
505 break;
506 case RB_ID_BOARD_NAME:
507 hs->name = (char *)buf;
508 break;
509 case RB_ID_MEMORY_SIZE:
510 hs->mem_size = read_le32(buf);
511 break;
512 case RB_ID_MAC_ADDRESS_COUNT:
513 hs->mac_count = read_le32(buf);
514 break;
515 case RB_ID_MAC_ADDRESS_PACK:
516 hs->mac_count = len/RB_MAC_SIZE;
517 if (hs->mac_count > RB_MAX_MAC_COUNT)
518 hs->mac_count = RB_MAX_MAC_COUNT;
519 mac = buf;
520 for (i=0; i < hs->mac_count; i++) {
521 for (j=0; j < RB_MAC_SIZE; j++)
522 hs->macs[i][j] = mac[j];
523 mac += RB_MAC_SIZE;
524 }
525 break;
526 }
527
528 buf += len;
529 buflen -= len;
530
531 }
532
533 return 0;
534 }
535
536 #define RB_BS_OFFS 0x14
537 #define RB_OFFS_MAX (128*1024)
538
539 static unsigned long __init routerboot_detect_board(void)
540 {
541 struct routerboard *board;
542 struct rb_hard_settings hs;
543 struct rb_bios_settings *bs;
544 u8 *base;
545 u32 off,len;
546 unsigned long ret;
547
548 ret = MACH_ADM5120_UNKNOWN;
549
550 base = (u8 *)KSEG1ADDR(ADM5120_SRAM0_BASE);
551 bs = (struct rb_bios_settings *)(base + RB_BS_OFFS);
552
553 off = read_le32(&bs->hs_offs);
554 len = read_le32(&bs->hs_size);
555 if (off > RB_OFFS_MAX)
556 return ret;
557
558 memset(&hs, 0, sizeof(hs));
559 if (routerboot_load_hs(base+off, len, &hs) != 0)
560 return ret;
561
562 /* assume RouterBOOT as the boot-loader */
563 adm5120_boot_loader = BOOT_LOADER_ROUTERBOOT;
564
565 if (hs.name == NULL)
566 return ret;
567
568 for (board = routerboards; board->mach_type != MACH_ADM5120_UNKNOWN;
569 board++) {
570 if (strncmp(board->name, hs.name, strlen(board->name)) == 0) {
571 ret = board->mach_type;
572 break;
573 }
574 }
575
576 return ret;
577 }
578
579 /*
580 * ZyNOS based boards
581 */
582 static inline u32 zynos_dbgarea_present(u8 *data)
583 {
584 u32 t;
585
586 t = read_be32(data+5);
587 if (t != ZYNOS_MAGIC_DBGAREA1)
588 return 0;
589
590 t = read_be32(data+9);
591 if (t != ZYNOS_MAGIC_DBGAREA2)
592 return 0;
593
594 return 1;
595 }
596
597 #define CHECK_VENDOR(n) (strnicmp(vendor,(n),strlen(n)) == 0)
598
599 static inline unsigned int zynos_get_vendor_id(struct zynos_board_info *info)
600 {
601 unsigned char vendor[ZYNOS_NAME_LEN];
602 int i;
603
604 for (i=0; i<ZYNOS_NAME_LEN; i++)
605 vendor[i]=info->vendor[i];
606
607 if CHECK_VENDOR(ZYNOS_VENDOR_ZYXEL)
608 return ZYNOS_VENDOR_ID_ZYXEL;
609 #if 0
610 /* TODO: there are no known ADM5120 based boards from other vendors */
611 if CHECK_VENDOR(ZYNOS_VENDOR_DLINK)
612 return ZYNOS_VENDOR_ID_DLINK;
613
614 if CHECK_VENDOR(ZYNOS_VENDOR_LUCENT)
615 return ZYNOS_VENDOR_ID_LUCENT;
616
617 if CHECK_VENDOR(ZYNOS_VENDOR_NETGEAR)
618 return ZYNOS_VENDOR_ID_NETGEAR;
619 #endif
620
621 return ZYNOS_VENDOR_ID_OTHER;
622 }
623
624 static inline u16 zynos_get_board_id(struct zynos_board_info *info)
625 {
626 return read_be16(&info->board_id);
627 }
628
629 static inline u32 zynos_get_bootext_addr(struct zynos_board_info *info)
630 {
631 return read_be32(&info->bootext_addr);
632 }
633
634
635 #define ZYNOS_INFO_ADDR KSEG1ADDR(ADM5120_SRAM0_BASE+0x3F90)
636 #define ZYNOS_HDBG_ADDR KSEG1ADDR(ADM5120_SRAM0_BASE+0x4000)
637 #define BOOTEXT_ADDR_MIN KSEG1ADDR(ADM5120_SRAM0_BASE)
638 #define BOOTEXT_ADDR_MAX (BOOTEXT_ADDR_MIN + (2*1024*1024))
639
640 static unsigned long __init zynos_detect_board(void)
641 {
642 struct zynos_board_info *info;
643 struct zynos_board *board;
644 unsigned int vendor_id;
645 u16 board_id;
646 u32 t;
647 unsigned long ret;
648
649 ret = MACH_ADM5120_UNKNOWN;
650 /* check presence of the dbgarea */
651 if (zynos_dbgarea_present((u8 *)ZYNOS_HDBG_ADDR) == 0)
652 goto out;
653
654 info = (struct zynos_board_info *)(ZYNOS_INFO_ADDR);
655
656 /* check for a valid BootExt address */
657 t = zynos_get_bootext_addr(info);
658 if ((t < BOOTEXT_ADDR_MIN) || (t > BOOTEXT_ADDR_MAX))
659 goto out;
660
661 vendor_id = zynos_get_vendor_id(info);
662 board_id = zynos_get_board_id(info);
663
664 for (board = zynos_boards; board->mach_type != MACH_ADM5120_UNKNOWN;
665 board++) {
666 if ((board->vendor_id == vendor_id) &&
667 (board->board_id == board_id)) {
668 ret = board->mach_type;
669 break;
670 }
671 }
672
673 /* assume Bootbase as the boot-loader */
674 adm5120_boot_loader = BOOT_LOADER_BOOTBASE;
675
676 out:
677 return ret;
678 }
679
680 /*
681 * U-Boot based boards
682 */
683 static int __init uboot_present(void)
684 {
685 /* FIXME: not yet implemented */
686 return 0;
687 }
688
689 static unsigned long __init uboot_detect_board(void)
690 {
691 /* FIXME: not yet implemented */
692 return MACH_ADM5120_UNKNOWN;
693 }
694
695 static void __init adm5120_detect_board(void)
696 {
697 struct adm5120_board *board;
698 unsigned long t;
699
700 adm5120_boot_loader = BOOT_LOADER_UNKNOWN;
701
702 /* Try to detect board type without bootloader */
703 t = routerboot_detect_board();
704
705 if (t == MACH_ADM5120_UNKNOWN)
706 t = zynos_detect_board();
707
708 if (t == MACH_ADM5120_UNKNOWN)
709 t = myloader_detect_board();
710
711 /* Try to detect bootloader type */
712 if (cfe_present()) {
713 adm5120_boot_loader = BOOT_LOADER_CFE;
714 if (t == MACH_ADM5120_UNKNOWN)
715 t = cfe_detect_board();
716 } else if (uboot_present()) {
717 adm5120_boot_loader = BOOT_LOADER_UBOOT;
718 if (t == MACH_ADM5120_UNKNOWN)
719 t = uboot_detect_board();
720 }
721
722 for (board = adm5120_boards; board->mach_type != MACH_ADM5120_UNKNOWN;
723 board++) {
724 if (board->mach_type == t)
725 break;
726 }
727
728 memcpy(&adm5120_board, board, sizeof(adm5120_board));
729 }
730
731 /*
732 * CPU settings detection
733 */
734 #define CODE_GET_PC(c) ((c) & CODE_PC_MASK)
735 #define CODE_GET_REV(c) (((c) >> CODE_REV_SHIFT) & CODE_REV_MASK)
736 #define CODE_GET_PK(c) (((c) >> CODE_PK_SHIFT) & CODE_PK_MASK)
737 #define CODE_GET_CLKS(c) (((c) >> CODE_CLKS_SHIFT) & CODE_CLKS_MASK)
738 #define CODE_GET_NAB(c) (((c) & CODE_NAB) != 0)
739
740 static void __init adm5120_detect_cpuinfo(void)
741 {
742 u32 code;
743 u32 clks;
744
745 code = *(u32 *)KSEG1ADDR(ADM5120_SWITCH_BASE+SWITCH_REG_CODE);
746
747 adm5120_product_code = CODE_GET_PC(code);
748 adm5120_revision = CODE_GET_REV(code);
749 adm5120_package = (CODE_GET_PK(code) == CODE_PK_BGA) ?
750 ADM5120_PACKAGE_BGA : ADM5120_PACKAGE_PQFP;
751 adm5120_nand_boot = CODE_GET_NAB(code);
752
753 clks = CODE_GET_CLKS(code);
754 adm5120_speed = ADM5120_SPEED_175;
755 if (clks & 1)
756 adm5120_speed += 25000000;
757 if (clks & 2)
758 adm5120_speed += 50000000;
759 }
760
761 void __init adm5120_info_show(void)
762 {
763 /* FIXME: move this somewhere else */
764 printk("ADM%04X%s revision %d, running at %ldMHz\n",
765 adm5120_product_code,
766 (adm5120_package == ADM5120_PACKAGE_BGA) ? "" : "P",
767 adm5120_revision, (adm5120_speed / 1000000)
768 );
769 printk("Boot loader is: %s\n", boot_loader_names[adm5120_boot_loader]);
770 printk("Booted from : %s flash\n", adm5120_nand_boot ? "NAND":"NOR");
771 printk("Board is : %s\n", adm5120_board_name());
772 }
773
774 void __init adm5120_info_init(void)
775 {
776 adm5120_detect_cpuinfo();
777 adm5120_detect_board();
778
779 adm5120_info_show();
780 }