4 * Copyright (C) 2007 OpenWrt.org
5 * Copyright (C) 2007 Gabor Juhos <juhosg@freemail.hu>
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.
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 #include <linux/module.h>
20 #include <asm/bootinfo.h>
21 #include <asm/addrspace.h>
22 #include <asm/byteorder.h>
24 #include <asm/mach-adm5120/adm5120_defs.h>
25 #include <asm/mach-adm5120/adm5120_switch.h>
26 #include <asm/mach-adm5120/adm5120_mpmc.h>
27 #include <asm/mach-adm5120/adm5120_info.h>
28 #include <asm/mach-adm5120/myloader.h>
29 #include <asm/mach-adm5120/routerboot.h>
30 #include <asm/mach-adm5120/zynos.h>
32 extern char *prom_getenv(char *envname
);
36 struct adm5120_board adm5120_board
;
37 EXPORT_SYMBOL_GPL(adm5120_board
);
39 unsigned int adm5120_boot_loader
;
41 unsigned int adm5120_product_code
;
42 unsigned int adm5120_revision
;
43 unsigned int adm5120_package
;
44 unsigned int adm5120_nand_boot
;
45 unsigned long adm5120_speed
;
46 unsigned long adm5120_memsize
;
51 static char *boot_loader_names
[BOOT_LOADER_LAST
+1] = {
52 [BOOT_LOADER_UNKNOWN
] = "Unknown",
53 [BOOT_LOADER_CFE
] = "CFE",
54 [BOOT_LOADER_UBOOT
] = "U-Boot",
55 [BOOT_LOADER_MYLOADER
] = "MyLoader",
56 [BOOT_LOADER_ROUTERBOOT
]= "RouterBOOT",
57 [BOOT_LOADER_BOOTBASE
] = "Bootbase"
60 static struct adm5120_board __initdata adm5120_boards
[] = {
61 /* FIXME: some boards have invalid fields */
63 .name
= "Cellvision CAS-630/630W",
64 .mach_type
= MACH_ADM5120_CAS630
,
67 .flash0_size
= 4*1024*1024,
70 .name
= "Cellvision CAS-670/670W",
71 .mach_type
= MACH_ADM5120_CAS670
,
74 .flash0_size
= 4*1024*1024,
77 .name
= "Cellvision CAS-700/700W",
78 .mach_type
= MACH_ADM5120_CAS700
,
81 .flash0_size
= 4*1024*1024,
84 .name
= "Cellvision CAS-771/771W",
85 .mach_type
= MACH_ADM5120_CAS771
,
88 .mem_size
= (32 << 20),
89 .flash0_size
= 4*1024*1024,
92 .name
= "Cellvision CAS-790",
93 .mach_type
= MACH_ADM5120_CAS790
,
96 .flash0_size
= 4*1024*1024,
99 .name
= "Cellvision CAS-861/861W",
100 .mach_type
= MACH_ADM5120_CAS861
,
103 .flash0_size
= 4*1024*1024,
106 .name
= "Cellvision NFS-101U/101WU",
107 .mach_type
= MACH_ADM5120_NFS101U
,
110 .flash0_size
= 4*1024*1024,
113 .name
= "Cellvision NFS-202U/202WU",
114 .mach_type
= MACH_ADM5120_NFS202U
,
117 .flash0_size
= 4*1024*1024,
120 .name
= "Compex NetPassage 27G",
121 .mach_type
= MACH_ADM5120_NP27G
,
124 .flash0_size
= 4*1024*1024,
127 .name
= "Compex NetPassage 28G",
128 .mach_type
= MACH_ADM5120_NP28G
,
131 .flash0_size
= 4*1024*1024,
134 .name
= "Compex NP28G (HotSpot)",
135 .mach_type
= MACH_ADM5120_NP28GHS
,
138 .flash0_size
= 4*1024*1024,
141 .name
= "Compex WP54AG",
142 .mach_type
= MACH_ADM5120_WP54AG
,
145 .mem_size
= (16 << 20),
146 .flash0_size
= 4*1024*1024,
149 .name
= "Compex WP54G",
150 .mach_type
= MACH_ADM5120_WP54G
,
153 .flash0_size
= 4*1024*1024,
156 .name
= "Compex WP54G-WRT",
157 .mach_type
= MACH_ADM5120_WP54G_WRT
,
160 .flash0_size
= 4*1024*1024,
163 .name
= "Compex WP54G v1C",
164 .mach_type
= MACH_ADM5120_WP54Gv1C
,
167 .flash0_size
= 2*1024*1024,
170 .name
= "Compex WPP54AG",
171 .mach_type
= MACH_ADM5120_WPP54AG
,
174 .flash0_size
= 4*1024*1024,
177 .name
= "Compex WPP54G",
178 .mach_type
= MACH_ADM5120_WPP54G
,
181 .flash0_size
= 4*1024*1024,
184 .name
= "Edimax BR-6104K",
185 .mach_type
= MACH_ADM5120_BR6104K
,
188 .mem_size
= (16 << 20),
189 .flash0_size
= 2*1024*1024,
192 .name
= "Infineon EASY 5120",
193 .mach_type
= MACH_ADM5120_EASY5120
,
196 .flash0_size
= 2*1024*1024,
199 .name
= "Infineon EASY 5120-RT",
200 .mach_type
= MACH_ADM5120_EASY5120RT
,
203 .flash0_size
= 2*1024*1024,
206 .name
= "Infineon EASY 5120P-ATA",
207 .mach_type
= MACH_ADM5120_EASY5120PATA
,
210 .flash0_size
= 2*1024*1024,
213 .name
= "Infineon EASY 83000",
214 .mach_type
= MACH_ADM5120_EASY83000
,
217 .flash0_size
= 4*1024*1024,
220 .name
= "RouterBOARD 111",
221 .mach_type
= MACH_ADM5120_RB_111
,
224 .flash0_size
= 128*1024,
227 .name
= "RouterBOARD 112",
228 .mach_type
= MACH_ADM5120_RB_112
,
231 .flash0_size
= 128*1024,
234 .name
= "RouterBOARD 133",
235 .mach_type
= MACH_ADM5120_RB_133
,
238 .flash0_size
= 128*1024,
241 .name
= "RouterBOARD 133C",
242 .mach_type
= MACH_ADM5120_RB_133C
,
245 .flash0_size
= 128*1024,
248 .name
= "RouterBOARD 150",
249 .mach_type
= MACH_ADM5120_RB_150
,
252 .flash0_size
= 128*1024,
255 .name
= "RouterBOARD 153",
256 .mach_type
= MACH_ADM5120_RB_153
,
259 .flash0_size
= 128*1024,
262 .name
= "ZyXEL ES-2024A",
263 .mach_type
= MACH_ADM5120_ES2024A
,
266 .flash0_size
= 4*1024*1024,
269 .name
= "ZyXEL ES-2024PWR",
270 .mach_type
= MACH_ADM5120_ES2024PWR
,
273 .flash0_size
= 4*1024*1024,
276 .name
= "ZyXEL ES-2108",
277 .mach_type
= MACH_ADM5120_ES2108
,
280 .flash0_size
= 4*1024*1024,
283 .name
= "ZyXEL ES-2108-F",
284 .mach_type
= MACH_ADM5120_ES2108F
,
287 .flash0_size
= 4*1024*1024,
290 .name
= "ZyXEL ES-2108-G",
291 .mach_type
= MACH_ADM5120_ES2108G
,
294 .flash0_size
= 4*1024*1024,
297 .name
= "ZyXEL ES-2108-LC",
298 .mach_type
= MACH_ADM5120_ES2108LC
,
301 .flash0_size
= 4*1024*1024,
304 .name
= "ZyXEL ES-2108-PWR",
305 .mach_type
= MACH_ADM5120_ES2108PWR
,
308 .flash0_size
= 4*1024*1024,
311 .name
= "ZyXEL HomeSafe 100/100W",
312 .mach_type
= MACH_ADM5120_HS100
,
315 .flash0_size
= 4*1024*1024,
318 .name
= "ZyXEL Prestige 334",
319 .mach_type
= MACH_ADM5120_P334
,
322 .flash0_size
= 2*1024*1024,
325 .name
= "ZyXEL Prestige 334U",
326 .mach_type
= MACH_ADM5120_P334U
,
329 .flash0_size
= 4*1024*1024,
332 .name
= "ZyXEL Prestige 334W",
333 .mach_type
= MACH_ADM5120_P334W
,
336 .flash0_size
= 2*1024*1024,
339 .name
= "ZyXEL Prestige 334WH",
340 .mach_type
= MACH_ADM5120_P334WH
,
343 .flash0_size
= 4*1024*1024,
346 .name
= "ZyXEL Prestige 334WHD",
347 .mach_type
= MACH_ADM5120_P334WHD
,
350 .flash0_size
= 4*1024*1024,
353 .name
= "ZyXEL Prestige 334WT",
354 .mach_type
= MACH_ADM5120_P334WT
,
357 .flash0_size
= 4*1024*1024,
360 .name
= "ZyXEL Prestige 335/335WT",
361 .mach_type
= MACH_ADM5120_P335
,
364 .flash0_size
= 4*1024*1024,
367 .name
= "ZyXEL Prestige 335Plus",
368 .mach_type
= MACH_ADM5120_P335PLUS
,
371 .flash0_size
= 4*1024*1024,
374 .name
= "ZyXEL Prestige 335U",
375 .mach_type
= MACH_ADM5120_P335U
,
378 .flash0_size
= 4*1024*1024,
381 .name
= "Unknown ADM5120 board",
382 .mach_type
= MACH_ADM5120_UNKNOWN
,
385 .flash0_size
= 4*1024*1024,
389 #define DUMMY_BOARD() {.mach_type = MACH_ADM5120_UNKNOWN}
396 unsigned long mach_type
;
400 #define MYLO_BOARD(v,d,sv,sd,mt) { .vid = (v), .did = (d), .svid = (sv), \
401 .sdid = (sd), .mach_type = (mt) }
403 #define COMPEX_BOARD(d,mt) MYLO_BOARD(VENID_COMPEX,(d),VENID_COMPEX,(d),(mt))
405 static struct mylo_board mylo_boards
[] __initdata
= {
406 COMPEX_BOARD(DEVID_COMPEX_NP27G
, MACH_ADM5120_NP27G
),
407 COMPEX_BOARD(DEVID_COMPEX_NP28G
, MACH_ADM5120_NP28G
),
408 COMPEX_BOARD(DEVID_COMPEX_NP28GHS
, MACH_ADM5120_NP28GHS
),
409 COMPEX_BOARD(DEVID_COMPEX_WP54G
, MACH_ADM5120_WP54G
),
410 COMPEX_BOARD(DEVID_COMPEX_WP54Gv1C
, MACH_ADM5120_WP54Gv1C
),
411 COMPEX_BOARD(DEVID_COMPEX_WP54AG
, MACH_ADM5120_WP54AG
),
412 COMPEX_BOARD(DEVID_COMPEX_WPP54G
, MACH_ADM5120_WPP54G
),
413 COMPEX_BOARD(DEVID_COMPEX_WPP54AG
, MACH_ADM5120_WPP54AG
),
417 #define ROUTERBOARD_NAME_LEN 16
420 unsigned long mach_type
;
421 char name
[ROUTERBOARD_NAME_LEN
];
424 #define ROUTERBOARD(n, mt) { .name = (n), .mach_type = (mt) }
425 static struct routerboard routerboards
[] __initdata
= {
426 ROUTERBOARD("111", MACH_ADM5120_RB_111
),
427 ROUTERBOARD("112", MACH_ADM5120_RB_112
),
428 ROUTERBOARD("133", MACH_ADM5120_RB_133
),
429 ROUTERBOARD("133C", MACH_ADM5120_RB_133C
),
430 ROUTERBOARD("133C3", MACH_ADM5120_RB_133C
),
431 ROUTERBOARD("150", MACH_ADM5120_RB_153
), /* it's intentional */
432 ROUTERBOARD("153", MACH_ADM5120_RB_153
),
433 ROUTERBOARD("miniROUTER", MACH_ADM5120_RB_150
),
438 unsigned long mach_type
;
439 unsigned int vendor_id
;
443 #define ZYNOS_BOARD(vi, bi, mt) { .vendor_id = (vi), .board_id = (bi), \
446 #define ZYXEL_BOARD(bi, mt) ZYNOS_BOARD(ZYNOS_VENDOR_ID_ZYXEL, bi, mt)
447 #define DLINK_BOARD(bi, mt) ZYNOS_BOARD(ZYNOS_VENDOR_ID_DLINK, bi, mt)
448 #define LUCENT_BOARD(bi, mt) ZYNOS_BOARD(ZYNOS_VENDOR_ID_LUCENT, bi, mt)
450 static struct zynos_board zynos_boards
[] __initdata
= {
451 ZYXEL_BOARD(ZYNOS_BOARD_HS100
, MACH_ADM5120_HS100
),
452 ZYXEL_BOARD(ZYNOS_BOARD_P334
, MACH_ADM5120_P334
),
453 ZYXEL_BOARD(ZYNOS_BOARD_P334U
, MACH_ADM5120_P334U
),
454 ZYXEL_BOARD(ZYNOS_BOARD_P334W
, MACH_ADM5120_P334W
),
455 ZYXEL_BOARD(ZYNOS_BOARD_P334WH
, MACH_ADM5120_P334WH
),
456 ZYXEL_BOARD(ZYNOS_BOARD_P334WHD
, MACH_ADM5120_P334WHD
),
457 ZYXEL_BOARD(ZYNOS_BOARD_P334WT
, MACH_ADM5120_P334WT
),
458 ZYXEL_BOARD(ZYNOS_BOARD_P335
, MACH_ADM5120_P335
),
459 ZYXEL_BOARD(ZYNOS_BOARD_P335PLUS
, MACH_ADM5120_P335PLUS
),
460 ZYXEL_BOARD(ZYNOS_BOARD_P335U
, MACH_ADM5120_P335U
),
464 struct common_board
{
466 unsigned long mach_type
;
469 #define DEFBOARD(n, mt) { .name = (n), .mach_type = (mt) }
470 static struct common_board common_boards
[] __initdata
= {
471 DEFBOARD("CAS-630", MACH_ADM5120_CAS630
),
472 DEFBOARD("CAS-670", MACH_ADM5120_CAS670
),
473 DEFBOARD("CAS-700", MACH_ADM5120_CAS700
),
474 DEFBOARD("CAS-771", MACH_ADM5120_CAS771
),
475 DEFBOARD("CAS-790", MACH_ADM5120_CAS790
),
476 DEFBOARD("CAS-861", MACH_ADM5120_CAS861
),
477 DEFBOARD("NFS-101U", MACH_ADM5120_NFS101U
),
478 DEFBOARD("NFS-202U", MACH_ADM5120_NFS202U
),
479 DEFBOARD("EASY 5120", MACH_ADM5120_EASY5120
),
480 DEFBOARD("EASY 5120-RT", MACH_ADM5120_EASY5120RT
),
481 DEFBOARD("EASY 5120P-ATA", MACH_ADM5120_EASY5120PATA
),
482 DEFBOARD("EASY 83000", MACH_ADM5120_EASY83000
),
483 DEFBOARD("BR-6104K", MACH_ADM5120_BR6104K
),
484 DEFBOARD("WP54G-WRT", MACH_ADM5120_WP54G_WRT
),
485 DEFBOARD("P-334WT", MACH_ADM5120_P334WT
),
486 DEFBOARD("P-335", MACH_ADM5120_P335
),
492 static inline u16
read_le16(void *buf
)
497 return ((u16
)p
[0] + ((u16
)p
[1] << 8));
500 static inline u32
read_le32(void *buf
)
505 return ((u32
)p
[0] + ((u32
)p
[1] << 8) + ((u32
)p
[2] << 16) +
509 static inline u16
read_be16(void *buf
)
514 return (((u16
)p
[0] << 8) + (u16
)p
[1]);
517 static inline u32
read_be32(void *buf
)
522 return (((u32
)p
[0] << 24) + ((u32
)p
[1] << 16) + ((u32
)p
[2] << 8) +
529 #define CFE_EPTSEAL 0x43464531 /* CFE1 is the magic number to recognize CFE
530 from other bootloaders */
532 static int __init
cfe_present(void)
535 * This method only works, when we are booted directly from the CFE.
537 u32 cfe_handle
= (u32
) fw_arg0
;
538 u32 cfe_a1_val
= (u32
) fw_arg1
;
539 u32 cfe_entry
= (u32
) fw_arg2
;
540 u32 cfe_seal
= (u32
) fw_arg3
;
542 /* Check for CFE by finding the CFE magic number */
543 if (cfe_seal
!= CFE_EPTSEAL
) {
544 /* We are not booted from CFE */
548 /* cfe_a1_val must be 0, because only one CPU present in the ADM5120 */
549 if (cfe_a1_val
!= 0) {
553 /* The cfe_handle, and the cfe_entry must be kernel mode addresses */
554 if ((cfe_handle
< KSEG0
) || (cfe_entry
< KSEG0
)) {
561 static unsigned long __init
cfe_detect_board(void)
563 return MACH_ADM5120_WP54G_WRT
;
567 * MyLoader based boards
569 #define SYS_PARAMS_ADDR KSEG1ADDR(ADM5120_SRAM0_BASE+0x0F000)
570 #define BOARD_PARAMS_ADDR KSEG1ADDR(ADM5120_SRAM0_BASE+0x0F800)
571 #define PART_TABLE_ADDR KSEG1ADDR(ADM5120_SRAM0_BASE+0x10000)
573 static unsigned long __init
myloader_detect_board(void)
575 struct mylo_system_params
*sysp
;
576 struct mylo_board_params
*boardp
;
577 struct mylo_partition_table
*parts
;
578 struct mylo_board
*board
;
581 ret
= MACH_ADM5120_UNKNOWN
;
583 sysp
= (struct mylo_system_params
*)(SYS_PARAMS_ADDR
);
584 boardp
= (struct mylo_board_params
*)(BOARD_PARAMS_ADDR
);
585 parts
= (struct mylo_partition_table
*)(PART_TABLE_ADDR
);
587 /* Check for some magic numbers */
588 if ((le32_to_cpu(sysp
->magic
) != MYLO_MAGIC_SYS_PARAMS
) ||
589 (le32_to_cpu(boardp
->magic
) != MYLO_MAGIC_BOARD_PARAMS
) ||
590 (le32_to_cpu(parts
->magic
) != MYLO_MAGIC_PARTITIONS
))
593 for (board
= mylo_boards
; board
->mach_type
!= MACH_ADM5120_UNKNOWN
;
595 if ((le16_to_cpu(sysp
->vid
) == board
->vid
) &&
596 (le16_to_cpu(sysp
->did
) == board
->did
) &&
597 (le16_to_cpu(sysp
->svid
) == board
->svid
) &&
598 (le16_to_cpu(sysp
->sdid
) == board
->sdid
)) {
599 ret
= board
->mach_type
;
604 /* assume MyLoader as the boot-loader */
605 adm5120_boot_loader
= BOOT_LOADER_MYLOADER
;
612 * RouterBOOT based boards
614 static int __init
routerboot_load_hs(u8
*buf
, u16 buflen
,
615 struct rb_hard_settings
*hs
)
624 if (read_le32(buf
) != RB_MAGIC_HARD
)
627 /* skip magic value */
635 if (id
== RB_ID_TERMINATOR
|| buflen
< 2)
638 len
= read_le16(buf
);
646 case RB_ID_BIOS_VERSION
:
647 hs
->bios_ver
= (char *)buf
;
649 case RB_ID_BOARD_NAME
:
650 hs
->name
= (char *)buf
;
652 case RB_ID_MEMORY_SIZE
:
653 hs
->mem_size
= read_le32(buf
);
655 case RB_ID_MAC_ADDRESS_COUNT
:
656 hs
->mac_count
= read_le32(buf
);
658 case RB_ID_MAC_ADDRESS_PACK
:
659 hs
->mac_count
= len
/RB_MAC_SIZE
;
660 if (hs
->mac_count
> RB_MAX_MAC_COUNT
)
661 hs
->mac_count
= RB_MAX_MAC_COUNT
;
663 for (i
=0; i
< hs
->mac_count
; i
++) {
664 for (j
=0; j
< RB_MAC_SIZE
; j
++)
665 hs
->macs
[i
][j
] = mac
[j
];
679 #define RB_BS_OFFS 0x14
680 #define RB_OFFS_MAX (128*1024)
682 static unsigned long __init
routerboot_detect_board(void)
684 struct routerboard
*board
;
685 struct rb_hard_settings hs
;
686 struct rb_bios_settings
*bs
;
691 ret
= MACH_ADM5120_UNKNOWN
;
693 base
= (u8
*)KSEG1ADDR(ADM5120_SRAM0_BASE
);
694 bs
= (struct rb_bios_settings
*)(base
+ RB_BS_OFFS
);
696 off
= read_le32(&bs
->hs_offs
);
697 len
= read_le32(&bs
->hs_size
);
698 if (off
> RB_OFFS_MAX
)
701 memset(&hs
, 0, sizeof(hs
));
702 if (routerboot_load_hs(base
+off
, len
, &hs
) != 0)
705 /* assume RouterBOOT as the boot-loader */
706 adm5120_boot_loader
= BOOT_LOADER_ROUTERBOOT
;
711 for (board
= routerboards
; board
->mach_type
!= MACH_ADM5120_UNKNOWN
;
713 if (strncmp(board
->name
, hs
.name
, strlen(board
->name
)) == 0) {
714 ret
= board
->mach_type
;
725 static inline u32
zynos_dbgarea_present(u8
*data
)
729 t
= read_be32(data
+5);
730 if (t
!= ZYNOS_MAGIC_DBGAREA1
)
733 t
= read_be32(data
+9);
734 if (t
!= ZYNOS_MAGIC_DBGAREA2
)
740 #define CHECK_VENDOR(n) (strnicmp(vendor,(n),strlen(n)) == 0)
742 static inline unsigned int zynos_get_vendor_id(struct zynos_board_info
*info
)
744 unsigned char vendor
[ZYNOS_NAME_LEN
];
747 for (i
=0; i
<ZYNOS_NAME_LEN
; i
++)
748 vendor
[i
]=info
->vendor
[i
];
750 if CHECK_VENDOR(ZYNOS_VENDOR_ZYXEL
)
751 return ZYNOS_VENDOR_ID_ZYXEL
;
753 /* TODO: there are no known ADM5120 based boards from other vendors */
754 if CHECK_VENDOR(ZYNOS_VENDOR_DLINK
)
755 return ZYNOS_VENDOR_ID_DLINK
;
757 if CHECK_VENDOR(ZYNOS_VENDOR_LUCENT
)
758 return ZYNOS_VENDOR_ID_LUCENT
;
760 if CHECK_VENDOR(ZYNOS_VENDOR_NETGEAR
)
761 return ZYNOS_VENDOR_ID_NETGEAR
;
764 return ZYNOS_VENDOR_ID_OTHER
;
767 static inline u16
zynos_get_board_id(struct zynos_board_info
*info
)
769 return read_be16(&info
->board_id
);
772 static inline u32
zynos_get_bootext_addr(struct zynos_board_info
*info
)
774 return read_be32(&info
->bootext_addr
);
778 #define ZYNOS_INFO_ADDR KSEG1ADDR(ADM5120_SRAM0_BASE+0x3F90)
779 #define ZYNOS_HDBG_ADDR KSEG1ADDR(ADM5120_SRAM0_BASE+0x4000)
780 #define BOOTEXT_ADDR_MIN KSEG1ADDR(ADM5120_SRAM0_BASE)
781 #define BOOTEXT_ADDR_MAX (BOOTEXT_ADDR_MIN + (2*1024*1024))
783 static unsigned long __init
zynos_detect_board(void)
785 struct zynos_board_info
*info
;
786 struct zynos_board
*board
;
787 unsigned int vendor_id
;
792 ret
= MACH_ADM5120_UNKNOWN
;
793 /* check presence of the dbgarea */
794 if (zynos_dbgarea_present((u8
*)ZYNOS_HDBG_ADDR
) == 0)
797 info
= (struct zynos_board_info
*)(ZYNOS_INFO_ADDR
);
799 /* check for a valid BootExt address */
800 t
= zynos_get_bootext_addr(info
);
801 if ((t
< BOOTEXT_ADDR_MIN
) || (t
> BOOTEXT_ADDR_MAX
))
804 vendor_id
= zynos_get_vendor_id(info
);
805 board_id
= zynos_get_board_id(info
);
807 for (board
= zynos_boards
; board
->mach_type
!= MACH_ADM5120_UNKNOWN
;
809 if ((board
->vendor_id
== vendor_id
) &&
810 (board
->board_id
== board_id
)) {
811 ret
= board
->mach_type
;
816 /* assume Bootbase as the boot-loader */
817 adm5120_boot_loader
= BOOT_LOADER_BOOTBASE
;
824 * U-Boot based boards
826 static int __init
uboot_present(void)
828 /* FIXME: not yet implemented */
832 static unsigned long __init
uboot_detect_board(void)
834 /* FIXME: not yet implemented */
835 return MACH_ADM5120_UNKNOWN
;
841 static unsigned long __init
prom_detect_board(void)
847 ret
= MACH_ADM5120_UNKNOWN
;
848 name
= prom_getenv("board_name");
855 for (i
=0; i
<ARRAY_SIZE(common_boards
); i
++) {
856 if (strcmp(common_boards
[i
].name
, name
) == 0) {
857 ret
= common_boards
[i
].mach_type
;
866 static void __init
adm5120_detect_board(void)
868 struct adm5120_board
*board
;
871 adm5120_boot_loader
= BOOT_LOADER_UNKNOWN
;
873 /* Try to detect board type without bootloader */
874 t
= routerboot_detect_board();
876 if (t
== MACH_ADM5120_UNKNOWN
)
877 t
= zynos_detect_board();
879 if (t
== MACH_ADM5120_UNKNOWN
)
880 t
= myloader_detect_board();
882 /* Try to detect bootloader type */
884 adm5120_boot_loader
= BOOT_LOADER_CFE
;
885 if (t
== MACH_ADM5120_UNKNOWN
)
886 t
= cfe_detect_board();
887 } else if (uboot_present()) {
888 adm5120_boot_loader
= BOOT_LOADER_UBOOT
;
889 if (t
== MACH_ADM5120_UNKNOWN
)
890 t
= uboot_detect_board();
892 if (t
== MACH_ADM5120_UNKNOWN
)
893 t
= prom_detect_board();
896 for (board
= adm5120_boards
; board
->mach_type
!= MACH_ADM5120_UNKNOWN
;
898 if (board
->mach_type
== t
)
902 memcpy(&adm5120_board
, board
, sizeof(adm5120_board
));
905 #define SWITCH_READ(r) *(u32 *)(KSEG1ADDR(ADM5120_SWITCH_BASE)+(r))
906 #define SWITCH_WRITE(r,v) *(u32 *)(KSEG1ADDR(ADM5120_SWITCH_BASE)+(r))=(v)
909 * CPU settings detection
911 #define CODE_GET_PC(c) ((c) & CODE_PC_MASK)
912 #define CODE_GET_REV(c) (((c) >> CODE_REV_SHIFT) & CODE_REV_MASK)
913 #define CODE_GET_PK(c) (((c) >> CODE_PK_SHIFT) & CODE_PK_MASK)
914 #define CODE_GET_CLKS(c) (((c) >> CODE_CLKS_SHIFT) & CODE_CLKS_MASK)
915 #define CODE_GET_NAB(c) (((c) & CODE_NAB) != 0)
917 static void __init
adm5120_detect_cpuinfo(void)
922 code
= SWITCH_READ(SWITCH_REG_CODE
);
924 adm5120_product_code
= CODE_GET_PC(code
);
925 adm5120_revision
= CODE_GET_REV(code
);
926 adm5120_package
= (CODE_GET_PK(code
) == CODE_PK_BGA
) ?
927 ADM5120_PACKAGE_BGA
: ADM5120_PACKAGE_PQFP
;
928 adm5120_nand_boot
= CODE_GET_NAB(code
);
930 clks
= CODE_GET_CLKS(code
);
931 adm5120_speed
= ADM5120_SPEED_175
;
933 adm5120_speed
+= 25000000;
935 adm5120_speed
+= 50000000;
938 static void adm5120_ndelay(u32 ns
)
942 SWITCH_WRITE(SWITCH_REG_TIMER
, TIMER_PERIOD_DEFAULT
);
943 SWITCH_WRITE(SWITCH_REG_TIMER_INT
, (TIMER_INT_TOS
| TIMER_INT_TOM
));
946 t
&= TIMER_PERIOD_MASK
;
947 SWITCH_WRITE(SWITCH_REG_TIMER
, t
| TIMER_TE
);
949 /* wait until the timer expires */
951 t
= SWITCH_READ(SWITCH_REG_TIMER_INT
);
952 } while ((t
& TIMER_INT_TOS
) == 0);
954 /* leave the timer disabled */
955 SWITCH_WRITE(SWITCH_REG_TIMER
, TIMER_PERIOD_DEFAULT
);
956 SWITCH_WRITE(SWITCH_REG_TIMER_INT
, (TIMER_INT_TOS
| TIMER_INT_TOM
));
959 #define MPMC_READ(r) *(u32 *)(KSEG1ADDR(ADM5120_SWITCH_BASE)+(r))
960 #define MPMC_WRITE(r,v) *(u32 *)(KSEG1ADDR(ADM5120_SWITCH_BASE)+(r))=(v)
962 extern void prom_printf(char *, ...);
964 # define mem_dbg(f, a...) prom_printf("mem_detect: " f, ## a)
966 # define mem_dbg(f, a...)
969 #define MEM_WR_DELAY 10000 /* 0.01 usec */
971 static int mem_check_pattern(u8
*addr
, unsigned long offs
)
973 volatile u32
*p1
= (volatile u32
*)addr
;
974 volatile u32
*p2
= (volatile u32
*)(addr
+offs
);
977 /* save original value */
988 mem_dbg("write 0x%08lX to 0x%08lX\n", v
, (unsigned long)p1
);
991 mem_dbg("delay %d ns\n", MEM_WR_DELAY
);
992 adm5120_ndelay(MEM_WR_DELAY
);
995 mem_dbg("pattern at 0x%08lX is 0x%08lX\n", (unsigned long)p2
, u
);
997 /* restore original value */
1003 static void __init
adm5120_detect_memsize(void)
1009 memctrl
= SWITCH_READ(SWITCH_REG_MEMCTRL
);
1010 switch (memctrl
& MEMCTRL_SDRS_MASK
) {
1011 case MEMCTRL_SDRS_4M
:
1014 case MEMCTRL_SDRS_8M
:
1017 case MEMCTRL_SDRS_16M
:
1025 /* disable buffers for both SDRAM banks */
1026 mem_dbg("disable buffers for both banks\n");
1027 MPMC_WRITE(MPMC_REG_DC0
, MPMC_READ(MPMC_REG_DC0
) & ~DC_BE
);
1028 MPMC_WRITE(MPMC_REG_DC1
, MPMC_READ(MPMC_REG_DC1
) & ~DC_BE
);
1030 mem_dbg("checking for %ldMB chip in 1st bank\n", maxsize
>> 20);
1032 /* detect size of the 1st SDRAM bank */
1033 p
= (u8
*)KSEG1ADDR(0);
1034 for (size
= 2<<20; size
<= (maxsize
>> 1); size
<<= 1) {
1035 if (mem_check_pattern(p
, size
)) {
1036 /* mirrored address */
1037 mem_dbg("mirrored data found at offset 0x%lX\n", size
);
1042 mem_dbg("chip size in 1st bank is %ldMB\n", size
>> 20);
1043 adm5120_memsize
= size
;
1045 if (size
!= maxsize
)
1046 /* 2nd bank is not supported */
1049 if ((memctrl
& MEMCTRL_SDR1_ENABLE
) == 0)
1050 /* 2nd bank is disabled */
1054 * some bootloaders enable 2nd bank, even if the 2nd SDRAM chip
1057 mem_dbg("check presence of 2nd bank\n");
1059 p
= (u8
*)KSEG1ADDR(maxsize
+size
-4);
1060 if (mem_check_pattern(p
, 0)) {
1061 adm5120_memsize
+= size
;
1064 if (maxsize
!= size
) {
1065 /* adjusting MECTRL register */
1066 memctrl
&= ~(MEMCTRL_SDRS_MASK
);
1069 memctrl
|= MEMCTRL_SDRS_4M
;
1072 memctrl
|= MEMCTRL_SDRS_8M
;
1075 memctrl
|= MEMCTRL_SDRS_16M
;
1078 memctrl
|= MEMCTRL_SDRS_64M
;
1081 SWITCH_WRITE(SWITCH_REG_MEMCTRL
, memctrl
);
1085 /* reenable buffer for both SDRAM banks */
1086 mem_dbg("enable buffers for both banks\n");
1087 MPMC_WRITE(MPMC_REG_DC0
, MPMC_READ(MPMC_REG_DC0
) | DC_BE
);
1088 MPMC_WRITE(MPMC_REG_DC1
, MPMC_READ(MPMC_REG_DC1
) | DC_BE
);
1090 mem_dbg("%dx%ldMB memory found\n", (adm5120_memsize
== size
) ? 1 : 2 ,
1093 size
= adm5120_board_memsize();
1094 if (size
> 0 && size
!= adm5120_memsize
) {
1095 mem_dbg("wrong memory size detected, board settings will be used\n");
1096 adm5120_memsize
= size
;
1100 void __init
adm5120_info_show(void)
1102 /* FIXME: move this somewhere else */
1103 printk(KERN_INFO
"ADM%04X%s revision %d, running at %ldMHz\n",
1104 adm5120_product_code
,
1105 (adm5120_package
== ADM5120_PACKAGE_BGA
) ? "" : "P",
1106 adm5120_revision
, (adm5120_speed
/ 1000000)
1108 printk(KERN_INFO
"Boot loader is: %s\n", boot_loader_names
[adm5120_boot_loader
]);
1109 printk(KERN_INFO
"Booted from : %s flash\n", adm5120_nand_boot
? "NAND":"NOR");
1110 printk(KERN_INFO
"Board is : %s\n", adm5120_board_name());
1111 printk(KERN_INFO
"Memory size : %ldMB\n", adm5120_memsize
>> 20);
1114 void __init
adm5120_info_init(void)
1116 adm5120_detect_cpuinfo();
1117 adm5120_detect_board();
1118 adm5120_detect_memsize();
1120 adm5120_info_show();