adm5120 timing specific routines, was part of the IRQ handling rewritte
[openwrt.git] / target / linux / adm5120-2.6 / files / arch / mips / adm5120 / adm5120_info.c
index 2ba21b8..fde86c8 100644 (file)
@@ -115,47 +115,82 @@ static struct adm5120_board __initdata adm5120_boards[] = {
                .flash0_size    = 4*1024*1024,
        },
        {
-               .name           = "RouterBOARD RB-111",
+               .name           = "RouterBOARD 111",
                .mach_type      = MACH_ADM5120_RB_111,
                .has_usb        = 0,
                .iface_num      = 1,
                .flash0_size    = 128*1024,
        },
        {
-               .name           = "RouterBOARD RB-112",
+               .name           = "RouterBOARD 112",
                .mach_type      = MACH_ADM5120_RB_112,
                .has_usb        = 0,
                .iface_num      = 1,
                .flash0_size    = 128*1024,
        },
        {
-               .name           = "RouterBOARD RB-133",
+               .name           = "RouterBOARD 133",
                .mach_type      = MACH_ADM5120_RB_133,
                .has_usb        = 0,
                .iface_num      = 3,
                .flash0_size    = 128*1024,
        },
        {
-               .name           = "RouterBOARD RB-133C",
+               .name           = "RouterBOARD 133C",
                .mach_type      = MACH_ADM5120_RB_133C,
                .has_usb        = 0,
                .iface_num      = 1,
                .flash0_size    = 128*1024,
        },
        {
-               .name           = "RouterBOARD RB-150",
+               .name           = "RouterBOARD 150",
                .mach_type      = MACH_ADM5120_RB_150,
                .has_usb        = 0,
                .iface_num      = 5,
                .flash0_size    = 128*1024,
        },
        {
-               .name           = "RouterBOARD RB-153",
+               .name           = "RouterBOARD 153",
                .mach_type      = MACH_ADM5120_RB_153,
                .has_usb        = 0,
                .iface_num      = 5,
                .flash0_size    = 128*1024,
        },
+       {
+               .name           = "ZyXEL ES-2108",
+               .mach_type      = MACH_ADM5120_ES2108,
+               .has_usb        = 0,
+               .iface_num      = 0,
+               .flash0_size    = 4*1024*1024,
+       },
+       {
+               .name           = "ZyXEL ES-2108-F",
+               .mach_type      = MACH_ADM5120_ES2108F,
+               .has_usb        = 0,
+               .iface_num      = 0,
+               .flash0_size    = 4*1024*1024,
+       },
+       {
+               .name           = "ZyXEL ES-2108-G",
+               .mach_type      = MACH_ADM5120_ES2108G,
+               .has_usb        = 0,
+               .iface_num      = 0,
+               .flash0_size    = 4*1024*1024,
+       },
+       {
+               .name           = "ZyXEL ES-2108-LC",
+               .mach_type      = MACH_ADM5120_ES2108LC,
+               .has_usb        = 0,
+               .iface_num      = 0,
+               .flash0_size    = 4*1024*1024,
+       },
+       {
+               .name           = "ZyXEL ES-2108PWR",
+               .mach_type      = MACH_ADM5120_ES2108PWR,
+               .has_usb        = 0,
+               .iface_num      = 0,
+               .flash0_size    = 4*1024*1024,
+       },
        {
                .name           = "ZyXEL HomeSafe 100/100W",
                .mach_type      = MACH_ADM5120_HS100,
@@ -235,6 +270,8 @@ static struct adm5120_board __initdata adm5120_boards[] = {
        }
 };
 
+#define DUMMY_BOARD()  {.mach_type = MACH_ADM5120_UNKNOWN}
+
 struct mylo_board {
        u16     vid;
        u16     did;
@@ -243,7 +280,6 @@ struct mylo_board {
        unsigned long   mach_type;
 };
 
-#define DUMMY_BOARD()  {.mach_type = MACH_ADM5120_UNKNOWN}
 
 #define MYLO_BOARD(v,d,sv,sd,mt) { .vid = (v), .did = (d), .svid = (sv), \
        .sdid = (sd), .mach_type = (mt) }
@@ -286,11 +322,6 @@ struct zynos_board {
        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) }
 
@@ -332,6 +363,23 @@ static inline u32 read_le32(void *buf)
                ((u32)p[3] << 24));
 }
 
+static inline u16 read_be16(void *buf)
+{
+       u8 *p;
+
+       p = buf;
+       return (((u16)p[0] << 8) + (u16)p[1]);
+}
+
+static inline u32 read_be32(void *buf)
+{
+       u8 *p;
+
+       p = buf;
+       return (((u32)p[0] << 24) + ((u32)p[1] << 16) + ((u32)p[2] << 8) +
+               ((u32)p[3]));
+}
+
 /*
  * CFE based boards
  */
@@ -354,8 +402,7 @@ static int __init cfe_present(void)
                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 */
        if (cfe_a1_val != 0) {
                return 0;
        }
@@ -421,131 +468,203 @@ out:
 /*
  * RouterBOOT based boards
  */
-static int __init routerboot_find_tag(u8 *buf, u16 tagid, void **tagval,
-       u16 *taglen)
+static int __init routerboot_load_hs(u8 *buf, u16 buflen,
+       struct rb_hard_settings *hs)
 {
        u16 id,len;
-       int ret;
+       u8 *mac;
+       int i,j;
+
+       if (buflen < 4)
+               return -1;
 
-       ret = -1;
-       /* skip header */
-       buf += 8;
-       for (;;) {
+       if (read_le32(buf) != RB_MAGIC_HARD)
+               return -1;
+
+       /* skip magic value */
+       buf += 4;
+       buflen -= 4;
+
+       while (buflen > 2) {
                id = read_le16(buf);
                buf += 2;
-               if (id == RB_ID_TERMINATOR)
+               buflen -= 2;
+               if (id == RB_ID_TERMINATOR || buflen < 2)
                        break;
 
                len = read_le16(buf);
                buf += 2;
-               if (id == tagid) {
-                       *tagval = buf;
-                       *taglen = len;
-                       ret = 0;
+               buflen -= 2;
+
+               if (buflen < len)
+                       break;
+
+               switch (id) {
+               case RB_ID_BIOS_VERSION:
+                       hs->bios_ver = (char *)buf;
+                       break;
+               case RB_ID_BOARD_NAME:
+                       hs->name = (char *)buf;
+                       break;
+               case RB_ID_MEMORY_SIZE:
+                       hs->mem_size = read_le32(buf);
+                       break;
+               case RB_ID_MAC_ADDRESS_COUNT:
+                       hs->mac_count = read_le32(buf);
+                       break;
+               case RB_ID_MAC_ADDRESS_PACK:
+                       hs->mac_count = len/RB_MAC_SIZE;
+                       if (hs->mac_count > RB_MAX_MAC_COUNT)
+                               hs->mac_count = RB_MAX_MAC_COUNT;
+                       mac = buf;
+                       for (i=0; i < hs->mac_count; i++) {
+                               for (j=0; j < RB_MAC_SIZE; j++)
+                                       hs->macs[i][j] = mac[j];
+                               mac += RB_MAC_SIZE;
+                       }
                        break;
                }
 
                buf += len;
+               buflen -= len;
+
        }
 
-       return ret;
+       return 0;
 }
 
-#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)
+#define RB_BS_OFFS     0x14
+#define RB_OFFS_MAX    (128*1024)
 
 static unsigned long __init routerboot_detect_board(void)
 {
        struct routerboard *board;
-       u32 magic;
-       char *name;
-       u16 namelen;
+       struct rb_hard_settings hs;
+       struct rb_bios_settings *bs;
+       u8 *base;
+       u32 off,len;
        unsigned long ret;
 
        ret = MACH_ADM5120_UNKNOWN;
 
-       magic = le32_to_cpu(*(u32 *)RB_HS_ADDR);
-       if (magic != RB_MAGIC_HARD)
-               goto out;
+       base = (u8 *)KSEG1ADDR(ADM5120_SRAM0_BASE);
+       bs = (struct rb_bios_settings *)(base + RB_BS_OFFS);
 
-       magic = le32_to_cpu(*(u32 *)RB_SS_ADDR);
-       if ((magic != RB_MAGIC_SOFT) && (magic != RB_MAGIC_DAWN))
-               goto out;
+       off = read_le32(&bs->hs_offs);
+       len = read_le32(&bs->hs_size);
+       if (off > RB_OFFS_MAX)
+               return ret;
 
-       if (routerboot_find_tag((u8 *)RB_HS_ADDR, RB_ID_BOARD_NAME,
-               (void *)&name, &namelen))
-               goto out;
+       memset(&hs, 0, sizeof(hs));
+       if (routerboot_load_hs(base+off, len, &hs) != 0)
+               return ret;
+
+       /* assume RouterBOOT as the boot-loader */
+       adm5120_boot_loader = BOOT_LOADER_ROUTERBOOT;
+
+       if (hs.name == NULL)
+               return ret;
 
        for (board = routerboards; board->mach_type != MACH_ADM5120_UNKNOWN;
                board++) {
-               if (strncmp(board->name, name, strlen(board->name)) == 0) {
+               if (strncmp(board->name, hs.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 inline u32 zynos_dbgarea_present(u8 *data)
+{
+       u32 t;
 
-static unsigned int __init zynos_get_vendor_id(unsigned char *vendor)
+       t = read_be32(data+5);
+       if (t != ZYNOS_MAGIC_DBGAREA1)
+               return 0;
+
+       t = read_be32(data+9);
+       if (t != ZYNOS_MAGIC_DBGAREA2)
+               return 0;
+
+       return 1;
+}
+
+#define CHECK_VENDOR(n) (strnicmp(vendor,(n),strlen(n)) == 0)
+
+static inline unsigned int zynos_get_vendor_id(struct zynos_board_info *info)
 {
-       int ret;
+       unsigned char vendor[ZYNOS_NAME_LEN];
+       int i;
 
-       ret = ZYNOS_VENDOR_ID_INVALID;
+       for (i=0; i<ZYNOS_NAME_LEN; i++)
+               vendor[i]=info->vendor[i];
 
        if CHECK_VENDOR(ZYNOS_VENDOR_ZYXEL)
-               ret = ZYNOS_VENDOR_ID_ZYXEL;
+               return 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;
+       if CHECK_VENDOR(ZYNOS_VENDOR_DLINK)
+               return ZYNOS_VENDOR_ID_DLINK;
+
+       if CHECK_VENDOR(ZYNOS_VENDOR_LUCENT)
+               return ZYNOS_VENDOR_ID_LUCENT;
+
+       if CHECK_VENDOR(ZYNOS_VENDOR_NETGEAR)
+               return ZYNOS_VENDOR_ID_NETGEAR;
 #endif
 
-       return ret;
+       return ZYNOS_VENDOR_ID_OTHER;
 }
 
-#define ZYNOS_INFO_ADDR        KSEG1ADDR(ADM5120_SRAM0_BASE+0x3F90)
-#define BOOTEXT_ADDR_2M        0xBFC08000
-#define BOOTEXT_ADDR_4M        0xBFC10000
+static inline u16 zynos_get_board_id(struct zynos_board_info *info)
+{
+       return read_be16(&info->board_id);
+}
+
+static inline u32 zynos_get_bootext_addr(struct zynos_board_info *info)
+{
+       return read_be32(&info->bootext_addr);
+}
+
+
+#define ZYNOS_INFO_ADDR                KSEG1ADDR(ADM5120_SRAM0_BASE+0x3F90)
+#define ZYNOS_HDBG_ADDR                KSEG1ADDR(ADM5120_SRAM0_BASE+0x4000)
+#define BOOTEXT_ADDR_MIN       KSEG1ADDR(ADM5120_SRAM0_BASE)
+#define BOOTEXT_ADDR_MAX       (BOOTEXT_ADDR_MIN + (2*1024*1024))
 
 static unsigned long __init zynos_detect_board(void)
 {
        struct zynos_board_info *info;
        struct zynos_board *board;
        unsigned int vendor_id;
-       u32     bootext_addr;
+       u16     board_id;
+       u32     t;
        unsigned long ret;
 
        ret = MACH_ADM5120_UNKNOWN;
+       /* check presence of the dbgarea */
+       if (zynos_dbgarea_present((u8 *)ZYNOS_HDBG_ADDR) == 0)
+               goto out;
 
        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))
+       /* check for a valid BootExt address */
+       t = zynos_get_bootext_addr(info);
+       if ((t < BOOTEXT_ADDR_MIN) || (t > BOOTEXT_ADDR_MAX))
                goto out;
 
+       vendor_id = zynos_get_vendor_id(info);
+       board_id = zynos_get_board_id(info);
+
        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))) {
+                       (board->board_id == board_id)) {
                        ret = board->mach_type;
                        break;
                }
This page took 0.030036 seconds and 4 git commands to generate.