From 8ed6f003520655bef682a07cb8f56250935233d4 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Thu, 14 Jun 2007 11:59:31 +0000 Subject: [PATCH] Fix memory detection and hcd compilation, thanks Gabor ! (closes #1813) SVN-Revision: 7631 --- .../files/arch/mips/adm5120/adm5120_info.c | 131 +++++++++++++++++- .../files/arch/mips/adm5120/memory.c | 61 ++------ .../files/drivers/usb/host/adm5120-hcd.c | 1 + .../asm-mips/mach-adm5120/adm5120_info.h | 2 + .../asm-mips/mach-adm5120/adm5120_switch.h | 13 ++ 5 files changed, 153 insertions(+), 55 deletions(-) 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 fde86c8f8607..ab96b0f6c92c 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 @@ -37,6 +37,7 @@ unsigned int adm5120_revision; unsigned int adm5120_package; unsigned int adm5120_nand_boot; unsigned long adm5120_speed; +unsigned long adm5120_memsize; /* * Locals @@ -266,7 +267,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, } }; @@ -728,6 +729,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 */ @@ -742,7 +746,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); @@ -758,6 +762,127 @@ 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 bank? */ + + 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 */ @@ -769,11 +894,13 @@ void __init adm5120_info_show(void) 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("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(); diff --git a/target/linux/adm5120-2.6/files/arch/mips/adm5120/memory.c b/target/linux/adm5120-2.6/files/arch/mips/adm5120/memory.c index 947b5b96a838..190a0788fcf9 100644 --- a/target/linux/adm5120-2.6/files/arch/mips/adm5120/memory.c +++ b/target/linux/adm5120-2.6/files/arch/mips/adm5120/memory.c @@ -35,49 +35,19 @@ #include #include +#include #include -extern char *prom_getenv(char *envname); -void prom_printf(char *, ...); - #define PFN_ALIGN(x) (((unsigned long)(x) + (PAGE_SIZE - 1)) & PAGE_MASK) -#define ADM5120_MEMCTRL 0x1200001c -#define ADM5120_MEMCTRL_SDRAM_MASK 0x7 - -static const unsigned long adm_sdramsize[] __initdata = { - 0x0, /* Reserved */ - 0x0400000, /* 4Mb */ - 0x0800000, /* 8Mb */ - 0x1000000, /* 16Mb */ - 0x4000000, /* 64Mb */ - 0x8000000, /* 128Mb */ -}; - -/* determined physical memory size, not overridden by command line args */ -unsigned long physical_memsize = 0L; - struct prom_pmemblock mdesc[PROM_MAX_PMEMBLOCKS]; struct prom_pmemblock * __init prom_getmdesc(void) { - char *memsize_str; unsigned int memsize; char cmdline[CL_SIZE], *ptr; - memsize_str = prom_getenv("memsize"); - - if (!memsize_str) - { - prom_printf("memsize not set in boot prom, set to default (8Mb)\n"); - physical_memsize = 0x00800000; - } - else -#ifdef DEBUG - prom_printf("prom_memsize = %s\n", memsize_str); -#endif - physical_memsize = simple_strtol(memsize_str, NULL, 0); - + memsize = adm5120_memsize; /* Check the command line for a memsize directive that overrides * the physical/default amount */ strcpy(cmdline, arcs_cmdline); @@ -87,16 +57,13 @@ struct prom_pmemblock * __init prom_getmdesc(void) if (ptr) memsize = memparse(ptr + 8, &ptr); - else - memsize = physical_memsize; + + memset(mdesc, 0, sizeof(mdesc)); + mdesc[0].type = BOOT_MEM_RAM; + mdesc[0].base = CPHYSADDR(PFN_ALIGN(&_end)); + mdesc[0].size = memsize - mdesc[0].base; - memset(mdesc, 0, sizeof(mdesc)); - - mdesc[0].type = BOOT_MEM_RAM; - mdesc[0].base = CPHYSADDR(PFN_ALIGN(&_end)); - mdesc[0].size = memsize - mdesc[0].base; - - return &mdesc[0]; + return &mdesc[0]; } void __init prom_meminit(void) @@ -117,18 +84,6 @@ void __init prom_meminit(void) } } -#if 0 -void __init prom_meminit(void) -{ - unsigned long base = CPHYSADDR(PFN_ALIGN(&_end)); - unsigned long size; - - u32 memctrl = *(u32*)KSEG1ADDR(ADM5120_MEMCTRL); - size = adm_sdramsize[memctrl & ADM5120_MEMCTRL_SDRAM_MASK]; - add_memory_region(base, size-base, BOOT_MEM_RAM); -} -#endif - void __init prom_free_prom_memory(void) { /* We do not have to prom memory to free */ diff --git a/target/linux/adm5120-2.6/files/drivers/usb/host/adm5120-hcd.c b/target/linux/adm5120-2.6/files/drivers/usb/host/adm5120-hcd.c index a9d0071dfa81..87bfcc6c728f 100644 --- a/target/linux/adm5120-2.6/files/drivers/usb/host/adm5120-hcd.c +++ b/target/linux/adm5120-2.6/files/drivers/usb/host/adm5120-hcd.c @@ -833,6 +833,7 @@ static int __init adm5120hcd_init(void) if (!adm5120_board.has_usb) { printk(KERN_DEBUG PFX "this board does not have USB\n"); return -ENODEV; + } printk(KERN_INFO PFX "registered\n"); return platform_driver_register(&adm5120hcd_driver); diff --git a/target/linux/adm5120-2.6/files/include/asm-mips/mach-adm5120/adm5120_info.h b/target/linux/adm5120-2.6/files/include/asm-mips/mach-adm5120/adm5120_info.h index c78c46b3b7a6..b4730dc0f046 100644 --- a/target/linux/adm5120-2.6/files/include/asm-mips/mach-adm5120/adm5120_info.h +++ b/target/linux/adm5120-2.6/files/include/asm-mips/mach-adm5120/adm5120_info.h @@ -50,6 +50,8 @@ extern unsigned int adm5120_package; #define ADM5120_PACKAGE_PQFP 0 #define ADM5120_PACKAGE_BGA 1 +extern unsigned long adm5120_memsize; + extern void adm5120_info_init(void); static inline int adm5120_package_pqfp(void) diff --git a/target/linux/adm5120-2.6/files/include/asm-mips/mach-adm5120/adm5120_switch.h b/target/linux/adm5120-2.6/files/include/asm-mips/mach-adm5120/adm5120_switch.h index a0fc1e44ec06..f7664587d762 100644 --- a/target/linux/adm5120-2.6/files/include/asm-mips/mach-adm5120/adm5120_switch.h +++ b/target/linux/adm5120-2.6/files/include/asm-mips/mach-adm5120/adm5120_switch.h @@ -85,6 +85,19 @@ #define CODE_PK_BGA 0 /* BGA package */ #define CODE_PK_PQFP 1 /* PQFP package */ +/* MEMCTRL register bits */ +#define MEMCTRL_SDRS_MASK BITMASK(3) /* SDRAM bank size */ +#define MEMCTRL_SDRS_4M 0x01 +#define MEMCTRL_SDRS_8M 0x02 +#define MEMCTRL_SDRS_16M 0x03 +#define MEMCTRL_SDRS_64M 0x04 +#define MEMCTRL_SDRS_128M 0x05 +#define MEMCTRL_SDR1_ENABLE ONEBIT(5) /* enable SDRAM bank 1 */ +#define MEMCTRL_SR0S_MASK BITMASK(3) /* SRAM0 size */ +#define MEMCTRL_SR0S_SHIFT 8 +#define MEMCTRL_SR1S_MASK BITMAKS(3) /* SRAM1 size */ +#define MEMCTRL_SR1S_SHIFT 16 + /* GPIO_CONF0 register bits */ #define GPIO_CONF0_MASK BITMASK(8) #define GPIO_CONF0_IM_SHIFT 0 -- 2.30.2