@@ -31,9 +31,10 @@ ffff0000 ffff0fff CPU vector page.
CPU supports vector relocation (control
register V bit.)
-fffe0000 fffeffff XScale cache flush area. This is used
- in proc-xscale.S to flush the whole data
- cache. (XScale does not have TCM.)
+fffe0000 fffeffff StrongARM and XScale cache flush area.
+ This is used in cache-v4wb.S and proc-xscale.S
+ to flush the whole data cache.
+ (Neither StrongARM nor XScale have TCM.)
fffe8000 fffeffff DTCM mapping area for platforms with
DTCM mounted inside the CPU.
@@ -157,6 +157,16 @@ extern void dmac_flush_range(const void *, const void *);
#endif
+#ifdef CONFIG_CPU_CACHE_V4WB
+
+enum cache_v4wb_cputype { CACHE_CPU_SA110, CACHE_CPU_SA1100 };
+
+extern void cache_v4wb_init(unsigned long flush_phys_addr,
+ unsigned long uncached_phys_addr,
+ enum cache_v4wb_cputype cpu_type);
+
+#endif
+
/*
* Copy user data from/to a page which is mapped into a different
* processes address space. Really, we want to allow our "user
@@ -23,6 +23,7 @@
#include <asm/pgtable.h>
#include <asm/page.h>
#include <asm/system.h>
+#include <asm/cacheflush.h>
#include <asm/mach/arch.h>
#include <asm/mach/irq.h>
@@ -114,9 +115,12 @@ static struct map_desc ebsa110_io_desc[] __initdata = {
}
};
+#define SRAM_PHYS 0x40000000
+
static void __init ebsa110_map_io(void)
{
iotable_init(ebsa110_io_desc, ARRAY_SIZE(ebsa110_io_desc));
+ cache_v4wb_init(SRAM_PHYS, TRICK4_PHYS, CACHE_CPU_SA110);
}
@@ -54,10 +54,5 @@
#define PIT_BASE 0xfc000000
#define SOFT_BASE 0xfd000000
-/*
- * RAM definitions
- */
-#define UNCACHEABLE_ADDR 0xff000000 /* IRQ_STAT */
-
#endif
@@ -21,10 +21,4 @@
*/
#define PLAT_PHYS_OFFSET UL(0x00000000)
-/*
- * Cache flushing area - SRAM
- */
-#define FLUSH_BASE_PHYS 0x40000000
-#define FLUSH_BASE 0xdf000000
-
#endif
@@ -21,6 +21,7 @@
#include <asm/irq.h>
#include <asm/mach-types.h>
#include <asm/setup.h>
+#include <asm/cacheflush.h>
#include <asm/hardware/dec21285.h>
#include <asm/mach/irq.h>
@@ -185,6 +186,8 @@ static struct map_desc ebsa285_host_io_desc[] __initdata = {
void __init footbridge_map_io(void)
{
+ cache_v4wb_init(0x50000000, 0x50010000, CACHE_CPU_SA110);
+
/*
* Set up the common mapping first; we need this to
* determine whether we're in host mode or not.
@@ -63,8 +63,6 @@
#define XBUS_SWITCH_J17_11 ((*XBUS_SWITCH) & (1 << 5))
#define XBUS_SWITCH_J17_9 ((*XBUS_SWITCH) & (1 << 6))
-#define UNCACHEABLE_ADDR (ARMCSR_BASE + 0x108)
-
/* PIC irq control */
#define PIC_LO 0x20
@@ -55,15 +55,8 @@ extern unsigned long __bus_to_pfn(unsigned long);
#endif
/*
- * Cache flushing area.
- */
-#define FLUSH_BASE 0xf9000000
-
-/*
* Physical DRAM offset.
*/
#define PLAT_PHYS_OFFSET UL(0x00000000)
-#define FLUSH_BASE_PHYS 0x50000000
-
#endif
@@ -46,8 +46,6 @@
#define SCREEN_END 0xdfc00000
#define SCREEN_BASE 0xdf800000
-#define UNCACHEABLE_ADDR 0xdf010000
-
/*
* IO Addresses
*/
@@ -24,12 +24,6 @@
#define PLAT_PHYS_OFFSET UL(0x10000000)
/*
- * Cache flushing area - ROM
- */
-#define FLUSH_BASE_PHYS 0x00000000
-#define FLUSH_BASE 0xdf000000
-
-/*
* Sparsemem support. Each section is a maximum of 64MB. The sections
* are offset by 128MB and can cover 128MB, so that gives us a maximum
* of 29 physmem bits.
@@ -27,6 +27,7 @@
#include <asm/page.h>
#include <asm/domain.h>
#include <asm/setup.h>
+#include <asm/cacheflush.h>
#include <asm/mach/map.h>
#include <asm/mach/arch.h>
@@ -84,6 +85,9 @@ static struct map_desc rpc_io_desc[] __initdata = {
static void __init rpc_map_io(void)
{
iotable_init(rpc_io_desc, ARRAY_SIZE(rpc_io_desc));
+#ifdef CPU_CACHE_V4WB
+ cache_v4wb_init(0, 0x10000, CACHE_CPU_SA110);
+#endif
/*
* Turn off floppy.
@@ -21,6 +21,7 @@
#include <asm/div64.h>
#include <mach/hardware.h>
#include <asm/system.h>
+#include <asm/cacheflush.h>
#include <asm/mach/map.h>
#include <asm/mach/flash.h>
#include <asm/irq.h>
@@ -406,9 +407,13 @@ static struct map_desc standard_io_desc[] __initdata = {
},
};
+#define SA1100_ZERO_BANK 0xe0000000
+#define ICIP_PHYS_ADDR 0x90050000
+
void __init sa1100_map_io(void)
{
iotable_init(standard_io_desc, ARRAY_SIZE(standard_io_desc));
+ cache_v4wb_init(SA1100_ZERO_BANK, ICIP_PHYS_ADDR, CACHE_CPU_SA1100);
}
/*
@@ -12,10 +12,6 @@
#ifndef __ASM_ARCH_HARDWARE_H
#define __ASM_ARCH_HARDWARE_H
-
-#define UNCACHEABLE_ADDR 0xfa050000
-
-
/*
* SA1100 internal I/O mappings
*
@@ -31,11 +31,4 @@
#define MAX_PHYSMEM_BITS 32
#define SECTION_SIZE_BITS 27
-/*
- * Cache flushing area - SA1100 zero bank
- */
-#define FLUSH_BASE_PHYS 0xe0000000
-#define FLUSH_BASE 0xf5000000
-#define FLUSH_BASE_MINICACHE 0xf5100000
-
#endif
@@ -15,6 +15,7 @@
#include <asm/mach-types.h>
#include <asm/leds.h>
#include <asm/param.h>
+#include <asm/cacheflush.h>
#include <asm/mach/map.h>
#include <asm/mach/arch.h>
@@ -116,6 +117,7 @@ static struct map_desc shark_io_desc[] __initdata = {
static void __init shark_map_io(void)
{
iotable_init(shark_io_desc, ARRAY_SIZE(shark_io_desc));
+ cache_v4wb_init(0x80000000, 0x80010000, CACHE_CPU_SA110);
}
#define IRQ_TIMER 0
@@ -10,8 +10,6 @@
#ifndef __ASM_ARCH_HARDWARE_H
#define __ASM_ARCH_HARDWARE_H
-#define UNCACHEABLE_ADDR 0xdf010000
-
#define pcibios_assign_all_busses() 1
#define PCIBIOS_MIN_IO 0x6000
@@ -17,10 +17,4 @@
*/
#define PLAT_PHYS_OFFSET UL(0x08000000)
-/*
- * Cache flushing area
- */
-#define FLUSH_BASE_PHYS 0x80000000
-#define FLUSH_BASE 0xdf000000
-
#endif
@@ -36,7 +36,7 @@ obj-$(CONFIG_CPU_PABRT_V7) += pabort-v7.o
obj-$(CONFIG_CPU_CACHE_V3) += cache-v3.o
obj-$(CONFIG_CPU_CACHE_V4) += cache-v4.o
obj-$(CONFIG_CPU_CACHE_V4WT) += cache-v4wt.o
-obj-$(CONFIG_CPU_CACHE_V4WB) += cache-v4wb.o
+obj-$(CONFIG_CPU_CACHE_V4WB) += cache-v4wb.o cache-v4wb-init.o
obj-$(CONFIG_CPU_CACHE_V6) += cache-v6.o
obj-$(CONFIG_CPU_CACHE_V7) += cache-v7.o
obj-$(CONFIG_CPU_CACHE_FA) += cache-fa.o
new file mode 100644
@@ -0,0 +1,89 @@
+/*
+ * linux/arch/arm/mm/cache-v4wb-init.c
+ *
+ * Author: Nicolas Pitre
+ * Copyright: (C) 2011 Linaro Limited
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Runtime initialization for the code in cache-v4wb.S.
+ */
+
+#include <linux/init.h>
+#include <asm/sizes.h>
+#include <asm/cacheflush.h>
+#include <asm/mach/map.h>
+
+#define FLUSH_BASE 0xfffe0000
+#define FLUSH_OFF_ALT SZ_32K
+#define FLUSH_BASE_ALT (FLUSH_BASE + FLUSH_OFF_ALT)
+#define UNCACHEABLE_ADDR 0xfffee000
+
+static struct map_desc cache_v4wb_map[] __initdata = {
+ {
+ .virtual = FLUSH_BASE,
+ .length = SZ_16K,
+ .type = MT_CACHECLEAN,
+ }, {
+ .virtual = FLUSH_BASE + SZ_16K,
+ .length = PAGE_SIZE,
+ .type = MT_MINICLEAN,
+ }, {
+ .virtual = FLUSH_BASE_ALT,
+ .length = SZ_16K,
+ .type = MT_CACHECLEAN,
+ }, {
+ .virtual = FLUSH_BASE_ALT + SZ_16K,
+ .length = PAGE_SIZE,
+ .type = MT_MINICLEAN,
+ }, {
+ .virtual = UNCACHEABLE_ADDR,
+ .length = PAGE_SIZE,
+ .type = MT_UNCACHED,
+ }
+};
+
+/* shared with cache-v4wb.S */
+struct {
+ unsigned long addr;
+ unsigned long size;
+} cache_v4wb_params;
+
+/*
+ * This sets up cache flushing areas for the SA110 and SA11x0 processors.
+ * For convenience, uncached_phys_addr is used here to create an uncacheable
+ * mapping as needed by proc-sa110.S and proc-sa1100.S.
+ */
+void __init cache_v4wb_init(unsigned long flush_phys_addr,
+ unsigned long uncached_phys_addr,
+ enum cache_v4wb_cputype cpu_type)
+{
+ cache_v4wb_map[0].pfn = __phys_to_pfn(flush_phys_addr);
+ cache_v4wb_map[1].pfn = __phys_to_pfn(flush_phys_addr + SZ_16K);
+ cache_v4wb_map[2].pfn = __phys_to_pfn(flush_phys_addr + FLUSH_OFF_ALT);
+ cache_v4wb_map[3].pfn = __phys_to_pfn(flush_phys_addr + FLUSH_OFF_ALT + SZ_16K);
+ cache_v4wb_map[4].pfn = __phys_to_pfn(uncached_phys_addr);
+
+ /*
+ * SA110 has a 16KB cache and no minicache.
+ * SA1100 has a 8KB cache and a 512-byte minicache.
+ * To make the flush code straight forward, we simply pretend
+ * that the SA1100 has a cache of 8704 bytes in size and its
+ * flush area is located at an offset of 8192 bytes into
+ * the mapped area.
+ */
+ switch (cpu_type) {
+ case CACHE_CPU_SA110:
+ cache_v4wb_params.addr = FLUSH_BASE;
+ cache_v4wb_params.size = SZ_16K;
+ break;
+ case CACHE_CPU_SA1100:
+ cache_v4wb_params.addr = FLUSH_BASE + SZ_8K;
+ cache_v4wb_params.size = SZ_8K + 512;
+ break;
+ }
+
+ iotable_init(cache_v4wb_map, ARRAY_SIZE(cache_v4wb_map));
+}
@@ -19,17 +19,6 @@
#define CACHE_DLINESIZE 32
/*
- * The total size of the data cache.
- */
-#if defined(CONFIG_CPU_SA110)
-# define CACHE_DSIZE 16384
-#elif defined(CONFIG_CPU_SA1100)
-# define CACHE_DSIZE 8192
-#else
-# error Unknown cache size
-#endif
-
-/*
* This is the size at which it becomes more efficient to
* clean the whole cache, rather than using the individual
* cache line maintenance instructions.
@@ -43,11 +32,8 @@
* 131072 591 591 591 656 657 651
* Whole 132 136 132 221 217 207 <---
*/
-#define CACHE_DLIMIT (CACHE_DSIZE * 4)
+#define CACHE_DLIMIT 32768
- .data
-flush_base:
- .long FLUSH_BASE
.text
/*
@@ -78,21 +64,14 @@ ENTRY(v4wb_flush_kern_cache_all)
mov ip, #0
mcr p15, 0, ip, c7, c5, 0 @ invalidate I cache
__flush_whole_cache:
- ldr r3, =flush_base
- ldr r1, [r3, #0]
- eor r1, r1, #CACHE_DSIZE
+ ldr r3, =cache_v4wb_params
+ ldmia r3, {r1, r2}
+ eor r1, r1, #32768 @ FLUSH_OFF_ALT
str r1, [r3, #0]
- add r2, r1, #CACHE_DSIZE
-1: ldr r3, [r1], #32
- cmp r1, r2
- blo 1b
-#ifdef FLUSH_BASE_MINICACHE
- add r2, r2, #FLUSH_BASE_MINICACHE - FLUSH_BASE
- sub r1, r2, #512 @ only 512 bytes
+ add r2, r1, r2
1: ldr r3, [r1], #32
cmp r1, r2
blo 1b
-#endif
mcr p15, 0, ip, c7, c10, 4 @ drain write buffer
mov pc, lr
@@ -225,12 +225,16 @@ static struct mem_type mem_types[] = {
.domain = DOMAIN_IO,
},
[MT_CACHECLEAN] = {
- .prot_sect = PMD_TYPE_SECT | PMD_SECT_XN,
- .domain = DOMAIN_KERNEL,
+ .prot_pte = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY |
+ L_PTE_XN,
+ .prot_l1 = PMD_TYPE_TABLE,
+ .domain = DOMAIN_KERNEL,
},
[MT_MINICLEAN] = {
- .prot_sect = PMD_TYPE_SECT | PMD_SECT_XN | PMD_SECT_MINICACHE,
- .domain = DOMAIN_KERNEL,
+ .prot_pte = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY |
+ L_PTE_XN | L_PTE_MT_MINICACHE,
+ .prot_l1 = PMD_TYPE_TABLE,
+ .domain = DOMAIN_KERNEL,
},
[MT_LOW_VECTORS] = {
.prot_pte = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY |
@@ -426,8 +430,6 @@ static void __init build_mem_type_table(void)
* from SVC mode and no access from userspace.
*/
mem_types[MT_ROM].prot_sect |= PMD_SECT_APX|PMD_SECT_AP_WRITE;
- mem_types[MT_MINICLEAN].prot_sect |= PMD_SECT_APX|PMD_SECT_AP_WRITE;
- mem_types[MT_CACHECLEAN].prot_sect |= PMD_SECT_APX|PMD_SECT_AP_WRITE;
if (is_smp()) {
/*
@@ -484,16 +486,8 @@ static void __init build_mem_type_table(void)
mem_types[MT_MEMORY].prot_pte |= kern_pgprot;
mem_types[MT_MEMORY_NONCACHED].prot_sect |= ecc_mask;
mem_types[MT_ROM].prot_sect |= cp->pmd;
+ mem_types[MT_CACHECLEAN].prot_pte |= kern_pgprot;
- switch (cp->pmd) {
- case PMD_SECT_WT:
- mem_types[MT_CACHECLEAN].prot_sect |= PMD_SECT_WT;
- break;
- case PMD_SECT_WB:
- case PMD_SECT_WBWA:
- mem_types[MT_CACHECLEAN].prot_sect |= PMD_SECT_WB;
- break;
- }
printk("Memory policy: ECC %sabled, Data cache %s\n",
ecc_mask ? "en" : "dis", cp->policy);
@@ -942,24 +936,6 @@ static void __init devicemaps_init(struct machine_desc *mdesc)
#endif
/*
- * Map the cache flushing regions.
- */
-#ifdef FLUSH_BASE
- map.pfn = __phys_to_pfn(FLUSH_BASE_PHYS);
- map.virtual = FLUSH_BASE;
- map.length = SZ_1M;
- map.type = MT_CACHECLEAN;
- create_mapping(&map);
-#endif
-#ifdef FLUSH_BASE_MINICACHE
- map.pfn = __phys_to_pfn(FLUSH_BASE_PHYS + SZ_1M);
- map.virtual = FLUSH_BASE_MINICACHE;
- map.length = SZ_1M;
- map.type = MT_MINICLEAN;
- create_mapping(&map);
-#endif
-
- /*
* Create a mapping for the machine vectors at the high-vectors
* location (0xffff0000). If we aren't using high-vectors, also
* create a mapping at the low-vectors virtual address.
@@ -978,6 +954,7 @@ static void __init devicemaps_init(struct machine_desc *mdesc)
/*
* Ask the machine support to map in the statically mapped devices.
+ * This may include mappings for cache flush regions on some machines.
*/
if (mdesc->map_io)
mdesc->map_io();
@@ -30,6 +30,11 @@
*/
#define DCACHELINESIZE 32
+/*
+ * Address used for uncached access (mapping set up in cache-v4wb-init.c)
+ */
+#define UNCACHEABLE_ADDR 0xfffee000
+
.text
/*
@@ -34,6 +34,11 @@
*/
#define DCACHELINESIZE 32
+/*
+ * Address used for uncached access (mapping set up in cache-v4wb-init.c)
+ */
+#define UNCACHEABLE_ADDR 0xfffee000
+
__INIT
/*