diff options
author | Rafał Miłecki | 2014-07-17 23:26:33 +0200 |
---|---|---|
committer | Ralf Baechle | 2014-07-30 23:27:02 +0200 |
commit | 6ee1d93455384cef8a0426effe85da241b525b63 (patch) | |
tree | b3e66dbb882a5dbcdbcbc45cda66639d3141a5ca /arch/mips/bcm47xx | |
parent | d377732c8c9aac14ccb900b65678558b0fb8f0f3 (diff) |
MIPS: BCM47XX: Detect more then 128 MiB of RAM (HIGHMEM)
So far BCM47XX can only detect amount of HIGHMEM. It still requires
adding (registering) and well-testing before enabling by default.
Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
Acked-by: Hauke Mehrtens <hauke@hauke-m.de>
Cc: linux-mips@linux-mips.org
Patchwork: https://patchwork.linux-mips.org/patch/7396/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Diffstat (limited to 'arch/mips/bcm47xx')
-rw-r--r-- | arch/mips/bcm47xx/bcm47xx_private.h | 3 | ||||
-rw-r--r-- | arch/mips/bcm47xx/prom.c | 68 | ||||
-rw-r--r-- | arch/mips/bcm47xx/setup.c | 3 |
3 files changed, 73 insertions, 1 deletions
diff --git a/arch/mips/bcm47xx/bcm47xx_private.h b/arch/mips/bcm47xx/bcm47xx_private.h index 0194c3b9a729..f1cc9d0495d8 100644 --- a/arch/mips/bcm47xx/bcm47xx_private.h +++ b/arch/mips/bcm47xx/bcm47xx_private.h @@ -3,6 +3,9 @@ #include <linux/kernel.h> +/* prom.c */ +void __init bcm47xx_prom_highmem_init(void); + /* buttons.c */ int __init bcm47xx_buttons_register(void); diff --git a/arch/mips/bcm47xx/prom.c b/arch/mips/bcm47xx/prom.c index 1a03a2f43496..1b170bf5f7f0 100644 --- a/arch/mips/bcm47xx/prom.c +++ b/arch/mips/bcm47xx/prom.c @@ -51,6 +51,8 @@ __init void bcm47xx_set_system_type(u16 chip_id) chip_id); } +static unsigned long lowmem __initdata; + static __init void prom_init_mem(void) { unsigned long mem; @@ -87,6 +89,7 @@ static __init void prom_init_mem(void) if (!memcmp(prom_init, prom_init + mem, 32)) break; } + lowmem = mem; /* Ignoring the last page when ddr size is 128M. Cached * accesses to last page is causing the processor to prefetch @@ -95,7 +98,6 @@ static __init void prom_init_mem(void) */ if (c->cputype == CPU_74K && (mem == (128 << 20))) mem -= 0x1000; - add_memory_region(0, mem, BOOT_MEM_RAM); } @@ -114,3 +116,67 @@ void __init prom_init(void) void __init prom_free_prom_memory(void) { } + +#if defined(CONFIG_BCM47XX_BCMA) && defined(CONFIG_HIGHMEM) + +#define EXTVBASE 0xc0000000 +#define ENTRYLO(x) ((pte_val(pfn_pte((x) >> _PFN_SHIFT, PAGE_KERNEL_UNCACHED)) >> 6) | 1) + +#include <asm/tlbflush.h> + +/* Stripped version of tlb_init, with the call to build_tlb_refill_handler + * dropped. Calling it at this stage causes a hang. + */ +void __cpuinit early_tlb_init(void) +{ + write_c0_pagemask(PM_DEFAULT_MASK); + write_c0_wired(0); + temp_tlb_entry = current_cpu_data.tlbsize - 1; + local_flush_tlb_all(); +} + +void __init bcm47xx_prom_highmem_init(void) +{ + unsigned long off = (unsigned long)prom_init; + unsigned long extmem = 0; + bool highmem_region = false; + + if (WARN_ON(bcm47xx_bus_type != BCM47XX_BUS_TYPE_BCMA)) + return; + + if (bcm47xx_bus.bcma.bus.chipinfo.id == BCMA_CHIP_ID_BCM4706) + highmem_region = true; + + if (lowmem != 128 << 20 || !highmem_region) + return; + + early_tlb_init(); + + /* Add one temporary TLB entry to map SDRAM Region 2. + * Physical Virtual + * 0x80000000 0xc0000000 (1st: 256MB) + * 0x90000000 0xd0000000 (2nd: 256MB) + */ + add_temporary_entry(ENTRYLO(0x80000000), + ENTRYLO(0x80000000 + (256 << 20)), + EXTVBASE, PM_256M); + + off = EXTVBASE + __pa(off); + for (extmem = 128 << 20; extmem < 512 << 20; extmem <<= 1) { + if (!memcmp(prom_init, (void *)(off + extmem), 16)) + break; + } + extmem -= lowmem; + + early_tlb_init(); + + if (!extmem) + return; + + pr_warn("Found %lu MiB of extra memory, but highmem is unsupported yet!\n", + extmem >> 20); + + /* TODO: Register extra memory */ +} + +#endif /* defined(CONFIG_BCM47XX_BCMA) && defined(CONFIG_HIGHMEM) */ diff --git a/arch/mips/bcm47xx/setup.c b/arch/mips/bcm47xx/setup.c index cc75861c0187..2b63e7e7d3d3 100644 --- a/arch/mips/bcm47xx/setup.c +++ b/arch/mips/bcm47xx/setup.c @@ -218,6 +218,9 @@ void __init plat_mem_setup(void) bcm47xx_bus_type = BCM47XX_BUS_TYPE_BCMA; bcm47xx_register_bcma(); bcm47xx_set_system_type(bcm47xx_bus.bcma.bus.chipinfo.id); +#ifdef CONFIG_HIGHMEM + bcm47xx_prom_highmem_init(); +#endif #endif } else { printk(KERN_INFO "bcm47xx: using ssb bus\n"); |