#include <linux/autoconf.h>
#include <linux/kernel.h>
#include <linux/init.h>
+#include <linux/string.h>
#include <asm/bootinfo.h>
#include <asm/addrspace.h>
-#include <adm5120_info.h>
-#include <adm5120_defs.h>
-#include <adm5120_switch.h>
-#include <myloader.h>
+#include <asm/mach-adm5120/adm5120_defs.h>
+#include <asm/mach-adm5120/adm5120_switch.h>
+#include <asm/mach-adm5120/adm5120_info.h>
+#include <asm/mach-adm5120/myloader.h>
+#include <asm/mach-adm5120/routerboot.h>
+#include <asm/mach-adm5120/zynos.h>
-/* boot loaders specific definitions */
-#define CFE_EPTSEAL 0x43464531 /* CFE1 is the magic number to recognize CFE from other bootloaders */
+/*
+ * Globals
+ */
+struct adm5120_board adm5120_board;
+unsigned int adm5120_boot_loader;
-struct adm5120_info adm5120_info = {
- .cpu_speed = CPU_SPEED_175,
- .cpu_package = CPU_PACKAGE_PQFP,
- .boot_loader = BOOT_LOADER_UNKNOWN,
- .board_type = BOARD_TYPE_UNKNOWN
-};
+unsigned int adm5120_product_code;
+unsigned int adm5120_revision;
+unsigned int adm5120_package;
+unsigned int adm5120_nand_boot;
+unsigned long adm5120_speed;
+/*
+ * Locals
+ */
static char *boot_loader_names[BOOT_LOADER_LAST+1] = {
[BOOT_LOADER_UNKNOWN] = "Unknown",
[BOOT_LOADER_CFE] = "CFE",
[BOOT_LOADER_UBOOT] = "U-Boot",
[BOOT_LOADER_MYLOADER] = "MyLoader",
- [BOOT_LOADER_ROUTERBOOT]= "RouterBOOT"
+ [BOOT_LOADER_ROUTERBOOT]= "RouterBOOT",
+ [BOOT_LOADER_BOOTBASE] = "Bootbase"
};
-/*
- * CPU settings detection
- */
-#define CODE_GET_PC(c) ((c) & CODE_PC_MASK)
-#define CODE_GET_REV(c) (((c) >> CODE_REV_SHIFT) & CODE_REV_MASK)
-#define CODE_GET_PK(c) (((c) >> CODE_PK_SHIFT) & CODE_PK_MASK)
-#define CODE_GET_CLKS(c) (((c) >> CODE_CLKS_SHIFT) & CODE_CLKS_MASK)
-#define CODE_GET_NAB(c) (((c) & CODE_NAB) != 0)
+static struct adm5120_board __initdata adm5120_boards[] = {
+ {
+ .name = "Compex NetPassage 27G",
+ .mach_type = MACH_ADM5120_NP27G,
+ .has_usb = 1,
+ .iface_num = 5,
+ .flash0_size = 4*1024*1024,
+ },
+ {
+ .name = "Compex NetPassage 28G",
+ .mach_type = MACH_ADM5120_NP28G,
+ .has_usb = 0,
+ .iface_num = 4,
+ .flash0_size = 4*1024*1024,
+ },
+ {
+ .name = "Compex NP28G (HotSpot)",
+ .mach_type = MACH_ADM5120_NP28GHS,
+ .has_usb = 0,
+ .iface_num = 4,
+ .flash0_size = 4*1024*1024,
+ },
+ {
+ .name = "Compex WP54AG",
+ .mach_type = MACH_ADM5120_WP54AG,
+ .has_usb = 0,
+ .iface_num = 2,
+ .flash0_size = 4*1024*1024,
+ },
+ {
+ .name = "Compex WP54G",
+ .mach_type = MACH_ADM5120_WP54G,
+ .has_usb = 0,
+ .iface_num = 2,
+ .flash0_size = 4*1024*1024,
+ },
+ {
+ .name = "Compex WP54G-WRT",
+ .mach_type = MACH_ADM5120_WP54G_WRT,
+ .has_usb = 0,
+ .iface_num = 2,
+ .flash0_size = 4*1024*1024,
+ },
+ {
+ .name = "Compex WP54G v1C",
+ .mach_type = MACH_ADM5120_WP54Gv1C,
+ .has_usb = 0,
+ .iface_num = 2,
+ .flash0_size = 2*1024*1024,
+ },
+ {
+ .name = "Compex WPP54AG",
+ .mach_type = MACH_ADM5120_WPP54AG,
+ .has_usb = 0,
+ .iface_num = 2,
+ .flash0_size = 4*1024*1024,
+ },
+ {
+ .name = "Compex WPP54G",
+ .mach_type = MACH_ADM5120_WPP54G,
+ .has_usb = 0,
+ .iface_num = 2,
+ .flash0_size = 4*1024*1024,
+ },
+ {
+ .name = "RouterBOARD RB-111",
+ .mach_type = MACH_ADM5120_RB_111,
+ .has_usb = 0,
+ .iface_num = 1,
+ .flash0_size = 128*1024,
+ },
+ {
+ .name = "RouterBOARD RB-112",
+ .mach_type = MACH_ADM5120_RB_112,
+ .has_usb = 0,
+ .iface_num = 1,
+ .flash0_size = 128*1024,
+ },
+ {
+ .name = "RouterBOARD RB-133",
+ .mach_type = MACH_ADM5120_RB_133,
+ .has_usb = 0,
+ .iface_num = 3,
+ .flash0_size = 128*1024,
+ },
+ {
+ .name = "RouterBOARD RB-133C",
+ .mach_type = MACH_ADM5120_RB_133C,
+ .has_usb = 0,
+ .iface_num = 1,
+ .flash0_size = 128*1024,
+ },
+ {
+ .name = "RouterBOARD RB-150",
+ .mach_type = MACH_ADM5120_RB_150,
+ .has_usb = 0,
+ .iface_num = 5,
+ .flash0_size = 128*1024,
+ },
+ {
+ .name = "RouterBOARD RB-153",
+ .mach_type = MACH_ADM5120_RB_153,
+ .has_usb = 0,
+ .iface_num = 5,
+ .flash0_size = 128*1024,
+ },
+ {
+ .name = "ZyXEL HomeSafe 100/100W",
+ .mach_type = MACH_ADM5120_HS100,
+ .has_usb = 0,
+ .iface_num = 5,
+ .flash0_size = 4*1024*1024,
+ },
+ {
+ .name = "ZyXEL Prestige 334",
+ .mach_type = MACH_ADM5120_P334,
+ .has_usb = 0,
+ .iface_num = 5,
+ .flash0_size = 2*1024*1024,
+ },
+ {
+ .name = "ZyXEL Prestige 334U",
+ .mach_type = MACH_ADM5120_P334U,
+ .has_usb = 0,
+ .iface_num = 5,
+ .flash0_size = 4*1024*1024,
+ },
+ {
+ .name = "ZyXEL Prestige 334W",
+ .mach_type = MACH_ADM5120_P334W,
+ .has_usb = 0,
+ .iface_num = 5,
+ .flash0_size = 2*1024*1024,
+ },
+ {
+ .name = "ZyXEL Prestige 334WH",
+ .mach_type = MACH_ADM5120_P334WH,
+ .has_usb = 0,
+ .iface_num = 5,
+ .flash0_size = 4*1024*1024,
+ },
+ {
+ .name = "ZyXEL Prestige 334WHD",
+ .mach_type = MACH_ADM5120_P334WHD,
+ .has_usb = 0,
+ .iface_num = 5,
+ .flash0_size = 4*1024*1024,
+ },
+ {
+ .name = "ZyXEL Prestige 334WT",
+ .mach_type = MACH_ADM5120_P334WT,
+ .has_usb = 1,
+ .iface_num = 5,
+ .flash0_size = 4*1024*1024,
+ },
+ {
+ .name = "ZyXEL Prestige 335/335WT",
+ .mach_type = MACH_ADM5120_P335,
+ .has_usb = 1,
+ .iface_num = 5,
+ .flash0_size = 4*1024*1024,
+ },
+ {
+ .name = "ZyXEL Prestige 335Plus",
+ .mach_type = MACH_ADM5120_P335PLUS,
+ .has_usb = 1,
+ .iface_num = 5,
+ .flash0_size = 4*1024*1024,
+ },
+ {
+ .name = "ZyXEL Prestige 335U",
+ .mach_type = MACH_ADM5120_P335U,
+ .has_usb = 1,
+ .iface_num = 5,
+ .flash0_size = 4*1024*1024,
+ },
+ {
+ .name = "Unknown ADM5120 board",
+ .mach_type = MACH_ADM5120_UNKNOWN,
+ .has_usb = 1,
+ .iface_num = 5,
+ .flash0_size = 0,
+ }
+};
-static void __init detect_cpu_info(void)
-{
- uint32_t *reg;
- uint32_t code;
- uint32_t clks;
+struct mylo_board {
+ u16 vid;
+ u16 did;
+ u16 svid;
+ u16 sdid;
+ unsigned long mach_type;
+};
- reg = (uint32_t *)KSEG1ADDR(ADM5120_SWITCH_BASE+SWITCH_REG_CODE);
- code = *reg;
+#define DUMMY_BOARD() {.mach_type = MACH_ADM5120_UNKNOWN}
- clks = CODE_GET_CLKS(code);
+#define MYLO_BOARD(v,d,sv,sd,mt) { .vid = (v), .did = (d), .svid = (sv), \
+ .sdid = (sd), .mach_type = (mt) }
- adm5120_info.product_code = CODE_GET_PC(code);
- adm5120_info.revision = CODE_GET_REV(code);
+#define COMPEX_BOARD(d,mt) MYLO_BOARD(VENID_COMPEX,(d),VENID_COMPEX,(d),(mt))
- adm5120_info.cpu_speed = CPU_SPEED_175;
- if (clks & 1)
- adm5120_info.cpu_speed += 25000000;
- if (clks & 2)
- adm5120_info.cpu_speed += 50000000;
+static struct mylo_board __initdata mylo_boards[] = {
+ COMPEX_BOARD(DEVID_COMPEX_NP27G, MACH_ADM5120_NP27G),
+ COMPEX_BOARD(DEVID_COMPEX_NP28G, MACH_ADM5120_NP28G),
+ COMPEX_BOARD(DEVID_COMPEX_NP28GHS, MACH_ADM5120_NP28GHS),
+ COMPEX_BOARD(DEVID_COMPEX_WP54G, MACH_ADM5120_WP54G),
+ COMPEX_BOARD(DEVID_COMPEX_WP54Gv1C, MACH_ADM5120_WP54Gv1C),
+ COMPEX_BOARD(DEVID_COMPEX_WP54AG, MACH_ADM5120_WP54AG),
+ COMPEX_BOARD(DEVID_COMPEX_WPP54G, MACH_ADM5120_WPP54G),
+ COMPEX_BOARD(DEVID_COMPEX_WPP54AG, MACH_ADM5120_WPP54AG),
+ DUMMY_BOARD()
+};
+
+#define ROUTERBOARD_NAME_LEN 16
+
+struct routerboard {
+ unsigned long mach_type;
+ char name[ROUTERBOARD_NAME_LEN];
+};
+
+#define ROUTERBOARD(n, mt) { .name = (n), .mach_type = (mt) }
+static struct routerboard __initdata routerboards[] = {
+ ROUTERBOARD("111", MACH_ADM5120_RB_111),
+ ROUTERBOARD("112", MACH_ADM5120_RB_112),
+ ROUTERBOARD("133", MACH_ADM5120_RB_133),
+ ROUTERBOARD("133C", MACH_ADM5120_RB_133C),
+ ROUTERBOARD("miniROUTER", MACH_ADM5120_RB_150),
+ ROUTERBOARD("153", MACH_ADM5120_RB_150),
+ DUMMY_BOARD()
+};
+
+struct zynos_board {
+ unsigned long mach_type;
+ unsigned int vendor_id;
+ u16 board_id;
+};
+
+#define ZYNOS_VENDOR_ID_INVALID 0
+#define ZYNOS_VENDOR_ID_ZYXEL 1
+#define ZYNOS_VENDOR_ID_DLINK 2
+#define ZYNOS_VENDOR_ID_LUCENT 3
+
+#define ZYNOS_BOARD(vi, bi, mt) { .vendor_id = (vi), .board_id = (bi), \
+ .mach_type = (mt) }
+
+#define ZYXEL_BOARD(bi, mt) ZYNOS_BOARD(ZYNOS_VENDOR_ID_ZYXEL, bi, mt)
+#define DLINK_BOARD(bi, mt) ZYNOS_BOARD(ZYNOS_VENDOR_ID_DLINK, bi, mt)
+#define LUCENT_BOARD(bi, mt) ZYNOS_BOARD(ZYNOS_VENDOR_ID_LUCENT, bi, mt)
+
+static struct zynos_board __initdata zynos_boards[] = {
+ ZYXEL_BOARD(ZYNOS_BOARD_HS100, MACH_ADM5120_HS100),
+ ZYXEL_BOARD(ZYNOS_BOARD_P334, MACH_ADM5120_P334),
+ ZYXEL_BOARD(ZYNOS_BOARD_P334U, MACH_ADM5120_P334U),
+ ZYXEL_BOARD(ZYNOS_BOARD_P334W, MACH_ADM5120_P334W),
+ ZYXEL_BOARD(ZYNOS_BOARD_P334WH, MACH_ADM5120_P334WH),
+ ZYXEL_BOARD(ZYNOS_BOARD_P334WHD, MACH_ADM5120_P334WHD),
+ ZYXEL_BOARD(ZYNOS_BOARD_P334WT, MACH_ADM5120_P334WT),
+ ZYXEL_BOARD(ZYNOS_BOARD_P335, MACH_ADM5120_P335),
+ ZYXEL_BOARD(ZYNOS_BOARD_P335PLUS, MACH_ADM5120_P335PLUS),
+ ZYXEL_BOARD(ZYNOS_BOARD_P335U, MACH_ADM5120_P335U),
+ DUMMY_BOARD()
+};
+
+/*
+ * Helper routines
+ */
+static inline u16 read_le16(void *buf)
+{
+ u8 *p;
- adm5120_info.cpu_package = (CODE_GET_PK(code) == CODE_PK_BGA) ?
- CPU_PACKAGE_BGA : CPU_PACKAGE_PQFP;
+ p = buf;
+ return ((u16)p[0] + ((u16)p[1] << 8));
+}
- adm5120_info.nand_boot = CODE_GET_NAB(code);
+static inline u32 read_le32(void *buf)
+{
+ u8 *p;
+ p = buf;
+ return ((u32)p[0] + ((u32)p[1] << 8) + ((u32)p[2] << 16) +
+ ((u32)p[3] << 24));
}
/*
- * Boot loader detection routines
+ * CFE based boards
*/
-static int __init detect_cfe(void)
+#define CFE_EPTSEAL 0x43464531 /* CFE1 is the magic number to recognize CFE
+from other bootloaders */
+
+static int __init cfe_present(void)
{
/*
* This method only works, when we are booted directly from the CFE.
*/
- uint32_t cfe_handle = (uint32_t) fw_arg0;
- uint32_t cfe_a1_val = (uint32_t) fw_arg1;
- uint32_t cfe_entry = (uint32_t) fw_arg2;
- uint32_t cfe_seal = (uint32_t) fw_arg3;
+ u32 cfe_handle = (u32) fw_arg0;
+ u32 cfe_a1_val = (u32) fw_arg1;
+ u32 cfe_entry = (u32) fw_arg2;
+ u32 cfe_seal = (u32) fw_arg3;
/* Check for CFE by finding the CFE magic number */
if (cfe_seal != CFE_EPTSEAL) {
return 0;
}
- /* cfe_a1_val must be 0, because only one CPU present in the ADM5120 SoC */
+ /* cfe_a1_val must be 0, because only one CPU present in the ADM5120 SoC
+*/
if (cfe_a1_val != 0) {
return 0;
}
return 1;
}
-static int __init detect_uboot(void)
+static unsigned long __init cfe_detect_board(void)
{
- /* FIXME: not yet implemented */
- return 0;
+ return MACH_ADM5120_WP54G_WRT;
}
-static int __init detect_myloader(void)
+/*
+ * MyLoader based boards
+ */
+#define SYS_PARAMS_ADDR KSEG1ADDR(ADM5120_SRAM0_BASE+0x0F000)
+#define BOARD_PARAMS_ADDR KSEG1ADDR(ADM5120_SRAM0_BASE+0x0F800)
+#define PART_TABLE_ADDR KSEG1ADDR(ADM5120_SRAM0_BASE+0x10000)
+
+static unsigned long __init myloader_detect_board(void)
{
struct mylo_system_params *sysp;
struct mylo_board_params *boardp;
struct mylo_partition_table *parts;
+ struct mylo_board *board;
+ unsigned long ret;
+
+ ret = MACH_ADM5120_UNKNOWN;
- sysp = (struct mylo_system_params *)(MYLO_MIPS_SYS_PARAMS);
- boardp = (struct mylo_board_params *)(MYLO_MIPS_BOARD_PARAMS);
- parts = (struct mylo_partition_table *)(MYLO_MIPS_PARTITIONS);
+ sysp = (struct mylo_system_params *)(SYS_PARAMS_ADDR);
+ boardp = (struct mylo_board_params *)(BOARD_PARAMS_ADDR);
+ parts = (struct mylo_partition_table *)(PART_TABLE_ADDR);
/* Check for some magic numbers */
- if ((sysp->magic != MYLO_MAGIC_SYS_PARAMS) ||
- (boardp->magic != MYLO_MAGIC_BOARD_PARAMS) ||
- (parts->magic != MYLO_MAGIC_PARTITIONS))
- return 0;
+ if ((le32_to_cpu(sysp->magic) != MYLO_MAGIC_SYS_PARAMS) ||
+ (le32_to_cpu(boardp->magic) != MYLO_MAGIC_BOARD_PARAMS) ||
+ (le32_to_cpu(parts->magic) != MYLO_MAGIC_PARTITIONS))
+ goto out;
+
+ for (board = mylo_boards; board->mach_type != MACH_ADM5120_UNKNOWN;
+ board++) {
+ if ((le16_to_cpu(sysp->vid) == board->vid) &&
+ (le16_to_cpu(sysp->did) == board->did) &&
+ (le16_to_cpu(sysp->svid) == board->svid) &&
+ (le16_to_cpu(sysp->sdid) == board->sdid)) {
+ ret = board->mach_type;
+ break;
+ }
+ }
- return 1;
+ /* assume MyLoader as the boot-loader */
+ adm5120_boot_loader = BOOT_LOADER_MYLOADER;
+
+out:
+ return ret;
+}
+
+/*
+ * RouterBOOT based boards
+ */
+static int __init routerboot_find_tag(u8 *buf, u16 tagid, void **tagval,
+ u16 *taglen)
+{
+ u16 id,len;
+ int ret;
+
+ ret = -1;
+ /* skip header */
+ buf += 8;
+ for (;;) {
+ id = read_le16(buf);
+ buf += 2;
+ if (id == RB_ID_TERMINATOR)
+ break;
+
+ len = read_le16(buf);
+ buf += 2;
+ if (id == tagid) {
+ *tagval = buf;
+ *taglen = len;
+ ret = 0;
+ break;
+ }
+
+ buf += len;
+ }
+
+ return ret;
}
-static int __init detect_routerboot(void)
+#define RB_HS_ADDR KSEG1ADDR(ADM5120_SRAM0_BASE+0x1000)
+#define RB_SS_ADDR KSEG1ADDR(ADM5120_SRAM0_BASE+0x2000)
+#define RB_FW_ADDR KSEG1ADDR(ADM5120_SRAM0_BASE+0x10000)
+
+static unsigned long __init routerboot_detect_board(void)
+{
+ struct routerboard *board;
+ u32 magic;
+ char *name;
+ u16 namelen;
+ unsigned long ret;
+
+ ret = MACH_ADM5120_UNKNOWN;
+
+ magic = le32_to_cpu(*(u32 *)RB_HS_ADDR);
+ if (magic != RB_MAGIC_HARD)
+ goto out;
+
+ magic = le32_to_cpu(*(u32 *)RB_SS_ADDR);
+ if ((magic != RB_MAGIC_SOFT) && (magic != RB_MAGIC_DAWN))
+ goto out;
+
+ if (routerboot_find_tag((u8 *)RB_HS_ADDR, RB_ID_BOARD_NAME,
+ (void *)&name, &namelen))
+ goto out;
+
+ for (board = routerboards; board->mach_type != MACH_ADM5120_UNKNOWN;
+ board++) {
+ if (strncmp(board->name, name, strlen(board->name)) == 0) {
+ ret = board->mach_type;
+ break;
+ }
+
+ }
+
+ /* assume RouterBOOT as the boot-loader */
+ adm5120_boot_loader = BOOT_LOADER_ROUTERBOOT;
+
+out:
+ return ret;
+}
+
+/*
+ * ZyNOS based boards
+ */
+#define CHECK_VENDOR(n) (strnicmp(vendor, ZYNOS_VENDOR_ZYXEL, \
+ strlen(ZYNOS_VENDOR_ZYXEL)) == 0)
+
+static unsigned int __init zynos_get_vendor_id(unsigned char *vendor)
+{
+ int ret;
+
+ ret = ZYNOS_VENDOR_ID_INVALID;
+
+ if CHECK_VENDOR(ZYNOS_VENDOR_ZYXEL)
+ ret = ZYNOS_VENDOR_ID_ZYXEL;
+#if 0
+ /* TODO: there are no known ADM5120 based boards from other vendors */
+ else if CHECK_VENDOR(ZYNOS_VENDOR_DLINK)
+ ret = ZYNOS_VENDOR_ID_DLINK;
+ else if CHECK_VENDOR(ZYNOS_VENDOR_LUCENT)
+ ret = ZYNOS_VENDOR_ID_LUCENT;
+#endif
+
+ return ret;
+}
+
+#define ZYNOS_INFO_ADDR KSEG1ADDR(ADM5120_SRAM0_BASE+0x3F90)
+#define BOOTEXT_ADDR_2M 0xBFC08000
+#define BOOTEXT_ADDR_4M 0xBFC10000
+
+static unsigned long __init zynos_detect_board(void)
+{
+ struct zynos_board_info *info;
+ struct zynos_board *board;
+ unsigned int vendor_id;
+ u32 bootext_addr;
+ unsigned long ret;
+
+ ret = MACH_ADM5120_UNKNOWN;
+
+ info = (struct zynos_board_info *)(ZYNOS_INFO_ADDR);
+ vendor_id = zynos_get_vendor_id(&info->vendor);
+ if (vendor_id == ZYNOS_VENDOR_ID_INVALID)
+ goto out;
+
+ bootext_addr = be32_to_cpu(info->bootext_addr);
+ if ((bootext_addr != BOOTEXT_ADDR_2M) ||
+ (bootext_addr != BOOTEXT_ADDR_4M))
+ goto out;
+
+ for (board = zynos_boards; board->mach_type != MACH_ADM5120_UNKNOWN;
+ board++) {
+ if ((board->vendor_id == vendor_id) &&
+ (board->board_id == be16_to_cpu(info->board_id))) {
+ ret = board->mach_type;
+ break;
+ }
+ }
+
+ /* assume Bootbase as the boot-loader */
+ adm5120_boot_loader = BOOT_LOADER_BOOTBASE;
+
+out:
+ return ret;
+}
+
+/*
+ * U-Boot based boards
+ */
+static int __init uboot_present(void)
{
/* FIXME: not yet implemented */
return 0;
}
-static int __init detect_bootloader(void)
+static unsigned long __init uboot_detect_board(void)
+{
+ /* FIXME: not yet implemented */
+ return MACH_ADM5120_UNKNOWN;
+}
+
+static void __init adm5120_detect_board(void)
{
- if (detect_cfe())
- return BOOT_LOADER_CFE;
+ struct adm5120_board *board;
+ unsigned long t;
+
+ adm5120_boot_loader = BOOT_LOADER_UNKNOWN;
- if (detect_uboot())
- return BOOT_LOADER_UBOOT;
+ /* Try to detect board type without bootloader */
+ t = routerboot_detect_board();
- if (detect_myloader())
- return BOOT_LOADER_MYLOADER;
+ if (t == MACH_ADM5120_UNKNOWN)
+ t = zynos_detect_board();
- if (detect_routerboot())
- return BOOT_LOADER_ROUTERBOOT;
+ if (t == MACH_ADM5120_UNKNOWN)
+ t = myloader_detect_board();
+
+ /* Try to detect bootloader type */
+ if (cfe_present()) {
+ adm5120_boot_loader = BOOT_LOADER_CFE;
+ if (t == MACH_ADM5120_UNKNOWN)
+ t = cfe_detect_board();
+ } else if (uboot_present()) {
+ adm5120_boot_loader = BOOT_LOADER_UBOOT;
+ if (t == MACH_ADM5120_UNKNOWN)
+ t = uboot_detect_board();
+ }
- return BOOT_LOADER_UNKNOWN;
+ for (board = adm5120_boards; board->mach_type != MACH_ADM5120_UNKNOWN;
+ board++) {
+ if (board->mach_type == t)
+ break;
+ }
+
+ memcpy(&adm5120_board, board, sizeof(adm5120_board));
}
/*
- * Board detection
+ * CPU settings detection
*/
-static void __init detect_board_type(void)
+#define CODE_GET_PC(c) ((c) & CODE_PC_MASK)
+#define CODE_GET_REV(c) (((c) >> CODE_REV_SHIFT) & CODE_REV_MASK)
+#define CODE_GET_PK(c) (((c) >> CODE_PK_SHIFT) & CODE_PK_MASK)
+#define CODE_GET_CLKS(c) (((c) >> CODE_CLKS_SHIFT) & CODE_CLKS_MASK)
+#define CODE_GET_NAB(c) (((c) & CODE_NAB) != 0)
+
+static void __init adm5120_detect_cpuinfo(void)
{
- switch(adm5120_info.boot_loader) {
- case BOOT_LOADER_CFE:
- adm5120_info.board_type = BOARD_TYPE_WP54G_WRT;
- adm5120_info.iface_num = 2;
- adm5120_info.has_usb = 0;
- printk("Board is a Compex WP54G-WRT\n");
- default:
- adm5120_info.board_type = BOARD_TYPE_UNKNOWN;
- printk("Board type is unknown\n");
- }
+ u32 code;
+ u32 clks;
+
+ code = *(u32 *)KSEG1ADDR(ADM5120_SWITCH_BASE+SWITCH_REG_CODE);
+
+ adm5120_product_code = CODE_GET_PC(code);
+ adm5120_revision = CODE_GET_REV(code);
+ adm5120_package = (CODE_GET_PK(code) == CODE_PK_BGA) ?
+ ADM5120_PACKAGE_BGA : ADM5120_PACKAGE_PQFP;
+ adm5120_nand_boot = CODE_GET_NAB(code);
+
+ clks = CODE_GET_CLKS(code);
+ adm5120_speed = ADM5120_SPEED_175;
+ if (clks & 1)
+ adm5120_speed += 25000000;
+ if (clks & 2)
+ adm5120_speed += 50000000;
}
void __init adm5120_info_show(void)
{
+ /* FIXME: move this somewhere else */
printk("ADM%04X%s revision %d, running at %ldMHz\n",
- adm5120_info.product_code,
- (adm5120_info.cpu_package == CPU_PACKAGE_BGA) ? "" : "P",
- adm5120_info.revision,
- (adm5120_info.cpu_speed / 1000000)
+ adm5120_product_code,
+ (adm5120_package == ADM5120_PACKAGE_BGA) ? "" : "P",
+ adm5120_revision, (adm5120_speed / 1000000)
);
- printk("Boot loader is: %s\n", boot_loader_names[adm5120_info.boot_loader]);
- printk("Booted from : %s flash\n", adm5120_info.nand_boot ? "NAND" : "NOR");
+ printk("Boot loader is: %s\n", boot_loader_names[adm5120_boot_loader]);
+ printk("Booted from : %s flash\n", adm5120_nand_boot ? "NAND":"NOR");
+ printk("Board is : %s\n", adm5120_board_name());
}
void __init adm5120_info_init(void)
{
- detect_cpu_info();
- adm5120_info.boot_loader = detect_bootloader();
- detect_board_type();
+ adm5120_detect_cpuinfo();
+ adm5120_detect_board();
adm5120_info_show();
}
* Copyright (C) 2005 Waldemar Brodkorb <wbx@openwrt.org>
* Copyright (C) 2004 Florian Schirmer (jolt@tuxbox.org)
*
- * original functions for finding root filesystem from Mike Baker
+ * original functions for finding root filesystem from Mike Baker
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 675 Mass Ave, Cambridge, MA 02139, USA.
- *
+ *
* Copyright 2001-2003, Broadcom Corporation
* All Rights Reserved.
- *
+ *
* THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY
* KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM
* SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
struct mtd_partition **pparts,
unsigned long origin);
-/* Macros for switching flash bank
+/* Macros for switching flash bank
ADM5120 only support 2MB flash address space
so GPIO5 is used as A20
*/
#define TRX_MAGIC 0x30524448 /* "HDR0" */
#define TRX_VERSION 1
#define TRX_MAX_LEN 0x3A0000
-#define TRX_NO_HEADER 1 /* Do not write TRX header */
+#define TRX_NO_HEADER 1 /* Do not write TRX header */
#define TRX_GZ_FILES 0x2 /* Contains up to TRX_MAX_OFFSET individual gzip files */
#define TRX_MAX_OFFSET 3
flash_switch_bank(FLASH_BOUNDARY);
inline_map_copy_from(map, to, from, len);
}
-
+
}
static int __init
memset(buf, 0xe5, sizeof(buf));
/*
- * Read into buffer
+ * Read into buffer
*/
if (mtd->read(mtd, off, sizeof(buf), &len, buf) ||
len != sizeof(buf))
* Copied from mtdblock.c
*
* Cache stuff...
- *
+ *
* Since typical flash erasable sectors are much larger than what Linux's
* buffer cache can handle, we must implement read-modify-write on flash
* sectors for each block write requests. To avoid over-erasing flash sectors
wake_up(wait_q);
}
-static int erase_write (struct mtd_info *mtd, unsigned long pos,
+static int erase_write (struct mtd_info *mtd, unsigned long pos,
int len, const char *buf)
{
struct erase_info erase;
memset(&trx, 0xe5, sizeof(trx));
/*
- * Read into buffer
+ * Read into buffer
*/
if (mtd->read(mtd, off, sizeof(trx), &len, (char *) &trx) ||
len != sizeof(trx))
/* found a TRX header */
if (le32_to_cpu(trx.magic) == TRX_MAGIC) {
- part->offset = le32_to_cpu(trx.offsets[2]) ? :
+ part->offset = le32_to_cpu(trx.offsets[2]) ? :
le32_to_cpu(trx.offsets[1]);
- part->size = le32_to_cpu(trx.len);
+ part->size = le32_to_cpu(trx.len);
part->size -= part->offset;
part->offset += off;
found:
if (part->size == 0)
return 0;
-
+
if (mtd->read(mtd, part->offset, sizeof(buf), &len, buf) || len != sizeof(buf))
return 0;
if (trx.len != part->offset + part->size - off) {
/* Update the trx offsets and length */
trx.len = part->offset + part->size - off;
-
+
/* Update the trx crc32 */
for (i = (u32) &(((struct trx_header *)NULL)->flag_version); i <= trx.len; i += sizeof(buf)) {
if (mtd->read(mtd, off + i, sizeof(buf), &len, buf) || len != sizeof(buf))
printk("Error accessing the first trx eraseblock\n");
return 0;
}
-
+
printk("Updating TRX offsets and length:\n");
printk("old trx = [0x%08x, 0x%08x, 0x%08x], len=0x%08x crc32=0x%08x\n", trx2->offsets[0], trx2->offsets[1], trx2->offsets[2], trx2->len, trx2->crc32);
printk("new trx = [0x%08x, 0x%08x, 0x%08x], len=0x%08x crc32=0x%08x\n", trx.offsets[0], trx.offsets[1], trx.offsets[2], trx.len, trx.crc32);
kfree(block);
printk("Done\n");
}
-
+
return part->size;
}
/* linux (kernel and rootfs) */
if (cfe_size != 384 * 1024) {
adm5120_cfe_parts[1].offset = adm5120_cfe_parts[0].size;
- adm5120_cfe_parts[1].size = adm5120_cfe_parts[3].offset -
+ adm5120_cfe_parts[1].size = adm5120_cfe_parts[3].offset -
adm5120_cfe_parts[1].offset;
} else {
/* do not count the elf loader, which is on one block */
- adm5120_cfe_parts[1].offset = adm5120_cfe_parts[0].size +
+ adm5120_cfe_parts[1].offset = adm5120_cfe_parts[0].size +
adm5120_cfe_parts[3].size + mtd->erasesize;
- adm5120_cfe_parts[1].size = size -
- adm5120_cfe_parts[0].size -
- (2*adm5120_cfe_parts[3].size) -
+ adm5120_cfe_parts[1].size = size -
+ adm5120_cfe_parts[0].size -
+ (2*adm5120_cfe_parts[3].size) -
mtd->erasesize;
}
if (find_root(mtd,size,&adm5120_cfe_parts[2])==0) {
/* entirely jffs2 */
adm5120_cfe_parts[4].name = NULL;
- adm5120_cfe_parts[2].size = size - adm5120_cfe_parts[2].offset -
+ adm5120_cfe_parts[2].size = size - adm5120_cfe_parts[2].offset -
adm5120_cfe_parts[3].size;
} else {
/* legacy setup */
/* calculate leftover flash, and assign it to the jffs2 partition */
if (cfe_size != 384 * 1024) {
- adm5120_cfe_parts[4].offset = adm5120_cfe_parts[2].offset +
+ adm5120_cfe_parts[4].offset = adm5120_cfe_parts[2].offset +
adm5120_cfe_parts[2].size;
if ((adm5120_cfe_parts[4].offset % mtd->erasesize) > 0) {
- adm5120_cfe_parts[4].offset += mtd->erasesize -
+ adm5120_cfe_parts[4].offset += mtd->erasesize -
(adm5120_cfe_parts[4].offset % mtd->erasesize);
}
- adm5120_cfe_parts[4].size = adm5120_cfe_parts[3].offset -
+ adm5120_cfe_parts[4].size = adm5120_cfe_parts[3].offset -
adm5120_cfe_parts[4].offset;
} else {
- adm5120_cfe_parts[4].offset = adm5120_cfe_parts[2].offset +
+ adm5120_cfe_parts[4].offset = adm5120_cfe_parts[2].offset +
adm5120_cfe_parts[2].size;
if ((adm5120_cfe_parts[4].offset % mtd->erasesize) > 0) {
- adm5120_cfe_parts[4].offset += mtd->erasesize -
+ adm5120_cfe_parts[4].offset += mtd->erasesize -
(adm5120_cfe_parts[4].offset % mtd->erasesize);
}
- adm5120_cfe_parts[4].size = size - adm5120_cfe_parts[3].size -
+ adm5120_cfe_parts[4].size = size - adm5120_cfe_parts[3].size -
adm5120_cfe_parts[4].offset;
}
}
adm5120_map.read = adm5120_map_read;
adm5120_map.write = adm5120_map_write;
adm5120_map.copy_from = adm5120_map_copy_from;
-
+
if (!(adm5120_mtd = do_map_probe("cfi_probe", &adm5120_map))) {
printk("Failed to do_map_probe\n");
iounmap((void *)adm5120_map.virt);
#ifdef CONFIG_MTD_PARTITIONS
- if (adm5120_info.boot_loader == BOOT_LOADER_CFE)
+ if (adm5120_boot_loader == BOOT_LOADER_CFE)
{
printk(KERN_NOTICE "adm5120 : using CFE flash mapping\n");
parts = init_mtd_partitions(adm5120_mtd, size);
-
+
for (i = 0; parts[i].name; i++);
ret = add_mtd_partitions(adm5120_mtd, parts, i);
-
+
if (ret) {
printk(KERN_ERR "Flash: add_mtd_partitions failed\n");
goto fail;
}
#endif
#ifdef CONFIG_MTD_MYLOADER_PARTS
- if (adm5120_info.boot_loader == BOOT_LOADER_MYLOADER)
+ if (adm5120_boot_loader == BOOT_LOADER_MYLOADER)
{
printk(KERN_NOTICE "adm5120 : using MyLoader flash mapping\n");
char *part_type;
-
+
if (parsed_nr_parts == 0) {
ret = parse_myloader_partitions(adm5120_mtd, &parts, 0);