X-Git-Url: http://git.rohieb.name/openwrt.git/blobdiff_plain/8bfda76892a39c033b5abf2c17035a444fffad08..8b2c7d0c931af2ea427f3a22d2b7b373f8d6cd1a:/target/linux/adm5120-2.6/files/arch/mips/adm5120/adm5120_info.c diff --git a/target/linux/adm5120-2.6/files/arch/mips/adm5120/adm5120_info.c b/target/linux/adm5120-2.6/files/arch/mips/adm5120/adm5120_info.c index 67b3e42ee..6d512f1a7 100644 --- a/target/linux/adm5120-2.6/files/arch/mips/adm5120/adm5120_info.c +++ b/target/linux/adm5120-2.6/files/arch/mips/adm5120/adm5120_info.c @@ -18,6 +18,7 @@ #include #include +#include #include #include @@ -26,6 +27,7 @@ #include #include +extern char *prom_getenv(char *envname); /* * Globals */ @@ -37,6 +39,7 @@ unsigned int adm5120_revision; unsigned int adm5120_package; unsigned int adm5120_nand_boot; unsigned long adm5120_speed; +unsigned long adm5120_memsize; /* * Locals @@ -51,6 +54,63 @@ static char *boot_loader_names[BOOT_LOADER_LAST+1] = { }; static struct adm5120_board __initdata adm5120_boards[] = { + /* FIXME: some boards have invalid fields */ + { + .name = "Cellvision CAS-630/630W", + .mach_type = MACH_ADM5120_CAS630, + .has_usb = 0, + .iface_num = 1, + .flash0_size = 4*1024*1024, + }, + { + .name = "Cellvision CAS-670/670W", + .mach_type = MACH_ADM5120_CAS670, + .has_usb = 0, + .iface_num = 1, + .flash0_size = 4*1024*1024, + }, + { + .name = "Cellvision CAS-700/700W", + .mach_type = MACH_ADM5120_CAS700, + .has_usb = 0, + .iface_num = 1, + .flash0_size = 4*1024*1024, + }, + { + .name = "Cellvision CAS-771/771W", + .mach_type = MACH_ADM5120_CAS771, + .has_usb = 0, + .iface_num = 5, + .flash0_size = 4*1024*1024, + }, + { + .name = "Cellvision CAS-790", + .mach_type = MACH_ADM5120_CAS790, + .has_usb = 0, + .iface_num = 1, + .flash0_size = 4*1024*1024, + }, + { + .name = "Cellvision CAS-861/861W", + .mach_type = MACH_ADM5120_CAS861, + .has_usb = 0, + .iface_num = 1, + .flash0_size = 4*1024*1024, + }, + { + .name = "Cellvision NFS-101U/101WU", + .mach_type = MACH_ADM5120_NFS101U, + .has_usb = 0, + .iface_num = 1, + .flash0_size = 4*1024*1024, + }, + { + .name = "Cellvision NFS-202U/202WU", + .mach_type = MACH_ADM5120_NFS202U, + .has_usb = 0, + .iface_num = 1, + .flash0_size = 4*1024*1024, + }, { .name = "Compex NetPassage 27G", .mach_type = MACH_ADM5120_NP27G, @@ -115,47 +175,131 @@ static struct adm5120_board __initdata adm5120_boards[] = { .flash0_size = 4*1024*1024, }, { - .name = "RouterBOARD RB-111", + .name = "Edimax BR-6104K", + .mach_type = MACH_ADM5120_BR6104K, + .has_usb = 0, + .iface_num = 5, + .flash0_size = 2*1024*1024, + }, + { + .name = "Infineon EASY 5120", + .mach_type = MACH_ADM5120_EASY5120, + .has_usb = 0, + .iface_num = 0, + .flash0_size = 2*1024*1024, + }, + { + .name = "Infineon EASY 5120-RT", + .mach_type = MACH_ADM5120_EASY5120RT, + .has_usb = 0, + .iface_num = 0, + .flash0_size = 2*1024*1024, + }, + { + .name = "Infineon EASY 5120P-ATA", + .mach_type = MACH_ADM5120_EASY5120PATA, + .has_usb = 0, + .iface_num = 0, + .flash0_size = 2*1024*1024, + }, + { + .name = "Infineon EASY 83000", + .mach_type = MACH_ADM5120_EASY83000, + .has_usb = 0, + .iface_num = 6, + .flash0_size = 4*1024*1024, + }, + { + .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-2024A", + .mach_type = MACH_ADM5120_ES2024A, + .has_usb = 0, + .iface_num = 0, + .flash0_size = 4*1024*1024, + }, + { + .name = "ZyXEL ES-2024PWR", + .mach_type = MACH_ADM5120_ES2024PWR, + .has_usb = 0, + .iface_num = 0, + .flash0_size = 4*1024*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-2108-PWR", + .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, @@ -231,7 +375,7 @@ static struct adm5120_board __initdata adm5120_boards[] = { .mach_type = MACH_ADM5120_UNKNOWN, .has_usb = 1, .iface_num = 5, - .flash0_size = 0, + .flash0_size = 4*1024*1024, } }; @@ -251,7 +395,7 @@ struct mylo_board { #define COMPEX_BOARD(d,mt) MYLO_BOARD(VENID_COMPEX,(d),VENID_COMPEX,(d),(mt)) -static struct mylo_board __initdata mylo_boards[] = { +static struct mylo_board mylo_boards[] __initdata = { COMPEX_BOARD(DEVID_COMPEX_NP27G, MACH_ADM5120_NP27G), COMPEX_BOARD(DEVID_COMPEX_NP28G, MACH_ADM5120_NP28G), COMPEX_BOARD(DEVID_COMPEX_NP28GHS, MACH_ADM5120_NP28GHS), @@ -271,7 +415,7 @@ struct routerboard { }; #define ROUTERBOARD(n, mt) { .name = (n), .mach_type = (mt) } -static struct routerboard __initdata routerboards[] = { +static struct routerboard routerboards[] __initdata = { ROUTERBOARD("111", MACH_ADM5120_RB_111), ROUTERBOARD("112", MACH_ADM5120_RB_112), ROUTERBOARD("133", MACH_ADM5120_RB_133), @@ -294,7 +438,7 @@ struct zynos_board { #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[] = { +static struct zynos_board zynos_boards[] __initdata = { ZYXEL_BOARD(ZYNOS_BOARD_HS100, MACH_ADM5120_HS100), ZYXEL_BOARD(ZYNOS_BOARD_P334, MACH_ADM5120_P334), ZYXEL_BOARD(ZYNOS_BOARD_P334U, MACH_ADM5120_P334U), @@ -308,6 +452,31 @@ static struct zynos_board __initdata zynos_boards[] = { DUMMY_BOARD() }; +struct common_board { + char *name; + unsigned long mach_type; +}; + +#define DEFBOARD(n, mt) { .name = (n), .mach_type = (mt) } +static struct common_board common_boards[] __initdata = { + DEFBOARD("CAS-630", MACH_ADM5120_CAS630), + DEFBOARD("CAS-670", MACH_ADM5120_CAS670), + DEFBOARD("CAS-700", MACH_ADM5120_CAS700), + DEFBOARD("CAS-771", MACH_ADM5120_CAS771), + DEFBOARD("CAS-790", MACH_ADM5120_CAS790), + DEFBOARD("CAS-861", MACH_ADM5120_CAS861), + DEFBOARD("NFS-101U", MACH_ADM5120_NFS101U), + DEFBOARD("NFS-202U", MACH_ADM5120_NFS202U), + DEFBOARD("EASY 5120", MACH_ADM5120_EASY5120), + DEFBOARD("EASY 5120-RT", MACH_ADM5120_EASY5120RT), + DEFBOARD("EASY 5120P-ATA", MACH_ADM5120_EASY5120PATA), + DEFBOARD("EASY 83000", MACH_ADM5120_EASY83000), + DEFBOARD("BR-6104K", MACH_ADM5120_BR6104K), + DEFBOARD("WP54G-WRT", MACH_ADM5120_WP54G_WRT), + DEFBOARD("P-334WT", MACH_ADM5120_P334WT), + DEFBOARD("P-335", MACH_ADM5120_P335), +}; + /* * Helper routines */ @@ -367,8 +536,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; } @@ -434,75 +602,111 @@ 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; + + if (read_le32(buf) != RB_MAGIC_HARD) + return -1; + + /* skip magic value */ + buf += 4; + buflen -= 4; - ret = -1; - /* skip header */ - buf += 8; - for (;;) { + 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; } @@ -622,6 +826,34 @@ static unsigned long __init uboot_detect_board(void) return MACH_ADM5120_UNKNOWN; } +/* + * Misc boards + */ +static unsigned long __init prom_detect_board(void) +{ + char *name; + unsigned long ret; + int i; + + ret = MACH_ADM5120_UNKNOWN; + name = prom_getenv("board_name"); + if (name == NULL) + goto out; + + if (*name == '\0') + goto out; + + for (i=0; imach_type != MACH_ADM5120_UNKNOWN; @@ -658,6 +893,9 @@ static void __init adm5120_detect_board(void) memcpy(&adm5120_board, board, sizeof(adm5120_board)); } +#define SWITCH_READ(r) *(u32 *)(KSEG1ADDR(ADM5120_SWITCH_BASE)+(r)) +#define SWITCH_WRITE(r,v) *(u32 *)(KSEG1ADDR(ADM5120_SWITCH_BASE)+(r))=(v) + /* * CPU settings detection */ @@ -672,7 +910,7 @@ static void __init adm5120_detect_cpuinfo(void) u32 code; u32 clks; - code = *(u32 *)KSEG1ADDR(ADM5120_SWITCH_BASE+SWITCH_REG_CODE); + code = SWITCH_READ(SWITCH_REG_CODE); adm5120_product_code = CODE_GET_PC(code); adm5120_revision = CODE_GET_REV(code); @@ -688,22 +926,146 @@ static void __init adm5120_detect_cpuinfo(void) adm5120_speed += 50000000; } +#if 1 +# define mem_dbg(f, ...) prom_printf("mem_detect: " f, ## __VA_ARGS__) +extern void prom_printf(char *, ...); +#else +# define mem_dbg(f, ...) +#endif + +static void __init adm5120_detect_memsize(void) +{ + u32 memctrl; + u32 size, maxsize; + volatile u8 *p,*r; + u8 t; + + memctrl = SWITCH_READ(SWITCH_REG_MEMCTRL); + switch (memctrl & MEMCTRL_SDRS_MASK) { + case MEMCTRL_SDRS_4M: + maxsize = 4 << 20; + break; + case MEMCTRL_SDRS_8M: + maxsize = 8 << 20; + break; + case MEMCTRL_SDRS_16M: + maxsize = 16 << 20; + break; + default: + maxsize = 64 << 20; + break; + } + + /* FIXME: need to disable buffers for both SDRAM banks? */ + + mem_dbg("checking for %ldMB chip\n",maxsize >> 20); + + /* detect size of the 1st SDRAM bank */ + p = (volatile u8 *)KSEG1ADDR(0); + t = *p; + for (size = 2<<20; size <= (maxsize >> 1); size <<= 1) { +#if 1 + r = (p+size); + *p = 0x55; + mem_dbg("1st pattern at 0x%lx is 0x%02x\n", size, *r); + if (*r == 0x55) { + *p = 0xAA; + mem_dbg("2nd pattern at 0x%lx is 0x%02x\n", size, *r); + if (*r == 0xAA) { + /* mirrored address */ + mem_dbg("mirrored data found at 0x%lx\n", size); + break; + } + } +#else + p[0] = 0x55; + mem_dbg("1st pattern at 0x%lx is 0x%02x\n", size, p[size]); + if (p[size] != 0x55) + continue; + + p[0] = 0xAA; + mem_dbg("2nd pattern at 0x%lx is 0x%02x\n", size, p[size]); + if (p[size] != 0xAA) + continue; + + /* mirrored address */ + mem_dbg("mirrored data found at 0x%lx\n", size); + break; +#endif + } + *p = t; + + mem_dbg("%ldMB chip found\n", size >> 20); + + if (size == (32 << 20)) + /* if bank size is 32MB, 2nd bank is not supported */ + goto out; + + if ((memctrl & MEMCTRL_SDR1_ENABLE) == 0) + /* if 2nd bank is not enabled, we are done */ + goto out; + + /* + * some bootloaders enable 2nd bank, even if the 2nd SDRAM chip + * are missing. + */ + mem_dbg("checking second bank\n"); + p += (maxsize+size)-1; + t = *p; + *p = 0x55; + if (*p != 0x55) + goto out; + + *p = 0xAA; + if (*p != 0xAA) + goto out; + + *p = t; + if (maxsize != size) { + /* adjusting MECTRL register */ + memctrl &= ~(MEMCTRL_SDRS_MASK); + switch (size>>20) { + case 4: + memctrl |= MEMCTRL_SDRS_4M; + break; + case 8: + memctrl |= MEMCTRL_SDRS_8M; + break; + case 16: + memctrl |= MEMCTRL_SDRS_16M; + break; + default: + memctrl |= MEMCTRL_SDRS_64M; + break; + } + SWITCH_WRITE(SWITCH_REG_MEMCTRL, memctrl); + } + size <<= 1; + +out: + adm5120_memsize = size; + mem_dbg("%ldMB memory found\n",size>>20); +} + void __init adm5120_info_show(void) { /* FIXME: move this somewhere else */ - printk("ADM%04X%s revision %d, running at %ldMHz\n", + printk(KERN_INFO "ADM%04X%s revision %d, running at %ldMHz\n", adm5120_product_code, (adm5120_package == ADM5120_PACKAGE_BGA) ? "" : "P", adm5120_revision, (adm5120_speed / 1000000) ); - 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()); + printk(KERN_INFO "Boot loader is: %s\n", boot_loader_names[adm5120_boot_loader]); + printk(KERN_INFO "Booted from : %s flash\n", adm5120_nand_boot ? "NAND":"NOR"); + printk(KERN_INFO "Board is : %s\n", adm5120_board_name()); + printk(KERN_INFO "Memory size : %ldMB\n", adm5120_memsize >> 20); } void __init adm5120_info_init(void) { + adm5120_detect_cpuinfo(); + adm5120_detect_memsize(); adm5120_detect_board(); adm5120_info_show();