aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips/bcm47xx
diff options
context:
space:
mode:
authorRafał Miłecki <zajec5@gmail.com>2014-07-17 17:26:33 -0400
committerRalf Baechle <ralf@linux-mips.org>2014-07-30 17:27:02 -0400
commit6ee1d93455384cef8a0426effe85da241b525b63 (patch)
treeb3e66dbb882a5dbcdbcbc45cda66639d3141a5ca /arch/mips/bcm47xx
parentd377732c8c9aac14ccb900b65678558b0fb8f0f3 (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.h3
-rw-r--r--arch/mips/bcm47xx/prom.c68
-rw-r--r--arch/mips/bcm47xx/setup.c3
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 @@
3 3
4#include <linux/kernel.h> 4#include <linux/kernel.h>
5 5
6/* prom.c */
7void __init bcm47xx_prom_highmem_init(void);
8
6/* buttons.c */ 9/* buttons.c */
7int __init bcm47xx_buttons_register(void); 10int __init bcm47xx_buttons_register(void);
8 11
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)
51 chip_id); 51 chip_id);
52} 52}
53 53
54static unsigned long lowmem __initdata;
55
54static __init void prom_init_mem(void) 56static __init void prom_init_mem(void)
55{ 57{
56 unsigned long mem; 58 unsigned long mem;
@@ -87,6 +89,7 @@ static __init void prom_init_mem(void)
87 if (!memcmp(prom_init, prom_init + mem, 32)) 89 if (!memcmp(prom_init, prom_init + mem, 32))
88 break; 90 break;
89 } 91 }
92 lowmem = mem;
90 93
91 /* Ignoring the last page when ddr size is 128M. Cached 94 /* Ignoring the last page when ddr size is 128M. Cached
92 * accesses to last page is causing the processor to prefetch 95 * accesses to last page is causing the processor to prefetch
@@ -95,7 +98,6 @@ static __init void prom_init_mem(void)
95 */ 98 */
96 if (c->cputype == CPU_74K && (mem == (128 << 20))) 99 if (c->cputype == CPU_74K && (mem == (128 << 20)))
97 mem -= 0x1000; 100 mem -= 0x1000;
98
99 add_memory_region(0, mem, BOOT_MEM_RAM); 101 add_memory_region(0, mem, BOOT_MEM_RAM);
100} 102}
101 103
@@ -114,3 +116,67 @@ void __init prom_init(void)
114void __init prom_free_prom_memory(void) 116void __init prom_free_prom_memory(void)
115{ 117{
116} 118}
119
120#if defined(CONFIG_BCM47XX_BCMA) && defined(CONFIG_HIGHMEM)
121
122#define EXTVBASE 0xc0000000
123#define ENTRYLO(x) ((pte_val(pfn_pte((x) >> _PFN_SHIFT, PAGE_KERNEL_UNCACHED)) >> 6) | 1)
124
125#include <asm/tlbflush.h>
126
127/* Stripped version of tlb_init, with the call to build_tlb_refill_handler
128 * dropped. Calling it at this stage causes a hang.
129 */
130void __cpuinit early_tlb_init(void)
131{
132 write_c0_pagemask(PM_DEFAULT_MASK);
133 write_c0_wired(0);
134 temp_tlb_entry = current_cpu_data.tlbsize - 1;
135 local_flush_tlb_all();
136}
137
138void __init bcm47xx_prom_highmem_init(void)
139{
140 unsigned long off = (unsigned long)prom_init;
141 unsigned long extmem = 0;
142 bool highmem_region = false;
143
144 if (WARN_ON(bcm47xx_bus_type != BCM47XX_BUS_TYPE_BCMA))
145 return;
146
147 if (bcm47xx_bus.bcma.bus.chipinfo.id == BCMA_CHIP_ID_BCM4706)
148 highmem_region = true;
149
150 if (lowmem != 128 << 20 || !highmem_region)
151 return;
152
153 early_tlb_init();
154
155 /* Add one temporary TLB entry to map SDRAM Region 2.
156 * Physical Virtual
157 * 0x80000000 0xc0000000 (1st: 256MB)
158 * 0x90000000 0xd0000000 (2nd: 256MB)
159 */
160 add_temporary_entry(ENTRYLO(0x80000000),
161 ENTRYLO(0x80000000 + (256 << 20)),
162 EXTVBASE, PM_256M);
163
164 off = EXTVBASE + __pa(off);
165 for (extmem = 128 << 20; extmem < 512 << 20; extmem <<= 1) {
166 if (!memcmp(prom_init, (void *)(off + extmem), 16))
167 break;
168 }
169 extmem -= lowmem;
170
171 early_tlb_init();
172
173 if (!extmem)
174 return;
175
176 pr_warn("Found %lu MiB of extra memory, but highmem is unsupported yet!\n",
177 extmem >> 20);
178
179 /* TODO: Register extra memory */
180}
181
182#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)
218 bcm47xx_bus_type = BCM47XX_BUS_TYPE_BCMA; 218 bcm47xx_bus_type = BCM47XX_BUS_TYPE_BCMA;
219 bcm47xx_register_bcma(); 219 bcm47xx_register_bcma();
220 bcm47xx_set_system_type(bcm47xx_bus.bcma.bus.chipinfo.id); 220 bcm47xx_set_system_type(bcm47xx_bus.bcma.bus.chipinfo.id);
221#ifdef CONFIG_HIGHMEM
222 bcm47xx_prom_highmem_init();
223#endif
221#endif 224#endif
222 } else { 225 } else {
223 printk(KERN_INFO "bcm47xx: using ssb bus\n"); 226 printk(KERN_INFO "bcm47xx: using ssb bus\n");