Commit 1ad77a876da48331451698cc4172c90ab9b6372f

Authored by Lennert Buytenhek
Committed by Russell King
1 parent 65846909d6

[ARM] 5241/1: provide ioremap_wc()

This patch provides an ARM implementation of ioremap_wc().

We use different page table attributes depending on which CPU we
are running on:

- Non-XScale ARMv5 and earlier systems: The ARMv5 ARM documents four
  possible mapping types (CB=00/01/10/11).  We can't use any of the
  cached memory types (CB=10/11), since that breaks coherency with
  peripheral devices.  Both CB=00 and CB=01 are suitable for _wc, and
  CB=01 (Uncached/Buffered) allows the hardware more freedom than
  CB=00, so we'll use that.

  (The ARMv5 ARM seems to suggest that CB=01 is allowed to delay stores
  but isn't allowed to merge them, but there is no other mapping type
  we can use that allows the hardware to delay and merge stores, so
  we'll go with CB=01.)

- XScale v1/v2 (ARMv5): same as the ARMv5 case above, with the slight
  difference that on these platforms, CB=01 actually _does_ allow
  merging stores.  (If you want noncoalescing bufferable behavior
  on Xscale v1/v2, you need to use XCB=101.)

- Xscale v3 (ARMv5) and ARMv6+: on these systems, we use TEXCB=00100
  mappings (Inner/Outer Uncacheable in xsc3 parlance, Uncached Normal
  in ARMv6 parlance).

  The ARMv6 ARM explicitly says that any accesses to Normal memory can
  be merged, which makes Normal memory more suitable for _wc mappings
  than Device or Strongly Ordered memory, as the latter two mapping
  types are guaranteed to maintain transaction number, size and order.
  We use the Uncached variety of Normal mappings for the same reason
  that we can't use C=1 mappings on ARMv5.

  The xsc3 Architecture Specification documents TEXCB=00100 as being
  Uncacheable and allowing coalescing of writes, which is also just
  what we need.

Signed-off-by: Lennert Buytenhek <buytenh@marvell.com>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>

Showing 3 changed files with 31 additions and 8 deletions Side-by-side Diff

arch/arm/include/asm/io.h
... ... @@ -61,8 +61,9 @@
61 61 #define MT_DEVICE_NONSHARED 1
62 62 #define MT_DEVICE_CACHED 2
63 63 #define MT_DEVICE_IXP2000 3
  64 +#define MT_DEVICE_WC 4
64 65 /*
65   - * types 4 onwards can be found in asm/mach/map.h and are undefined
  66 + * types 5 onwards can be found in asm/mach/map.h and are undefined
66 67 * for ioremap
67 68 */
68 69  
69 70  
... ... @@ -215,11 +216,13 @@
215 216 #define ioremap(cookie,size) __arm_ioremap(cookie, size, MT_DEVICE)
216 217 #define ioremap_nocache(cookie,size) __arm_ioremap(cookie, size, MT_DEVICE)
217 218 #define ioremap_cached(cookie,size) __arm_ioremap(cookie, size, MT_DEVICE_CACHED)
  219 +#define ioremap_wc(cookie,size) __arm_ioremap(cookie, size, MT_DEVICE_WC)
218 220 #define iounmap(cookie) __iounmap(cookie)
219 221 #else
220 222 #define ioremap(cookie,size) __arch_ioremap((cookie), (size), MT_DEVICE)
221 223 #define ioremap_nocache(cookie,size) __arch_ioremap((cookie), (size), MT_DEVICE)
222 224 #define ioremap_cached(cookie,size) __arch_ioremap((cookie), (size), MT_DEVICE_CACHED)
  225 +#define ioremap_wc(cookie,size) __arch_ioremap((cookie), (size), MT_DEVICE_WC)
223 226 #define iounmap(cookie) __arch_iounmap(cookie)
224 227 #endif
225 228  
arch/arm/include/asm/mach/map.h
... ... @@ -18,13 +18,13 @@
18 18 unsigned int type;
19 19 };
20 20  
21   -/* types 0-3 are defined in asm/io.h */
22   -#define MT_CACHECLEAN 4
23   -#define MT_MINICLEAN 5
24   -#define MT_LOW_VECTORS 6
25   -#define MT_HIGH_VECTORS 7
26   -#define MT_MEMORY 8
27   -#define MT_ROM 9
  21 +/* types 0-4 are defined in asm/io.h */
  22 +#define MT_CACHECLEAN 5
  23 +#define MT_MINICLEAN 6
  24 +#define MT_LOW_VECTORS 7
  25 +#define MT_HIGH_VECTORS 8
  26 +#define MT_MEMORY 9
  27 +#define MT_ROM 10
28 28  
29 29 #define MT_NONSHARED_DEVICE MT_DEVICE_NONSHARED
30 30 #define MT_IXP2000_DEVICE MT_DEVICE_IXP2000
... ... @@ -211,6 +211,12 @@
211 211 PMD_SECT_TEX(1),
212 212 .domain = DOMAIN_IO,
213 213 },
  214 + [MT_DEVICE_WC] = { /* ioremap_wc */
  215 + .prot_pte = PROT_PTE_DEVICE,
  216 + .prot_l1 = PMD_TYPE_TABLE,
  217 + .prot_sect = PROT_SECT_DEVICE,
  218 + .domain = DOMAIN_IO,
  219 + },
214 220 [MT_CACHECLEAN] = {
215 221 .prot_sect = PMD_TYPE_SECT | PMD_SECT_XN,
216 222 .domain = DOMAIN_KERNEL,
... ... @@ -270,6 +276,20 @@
270 276 if (cachepolicy >= CPOLICY_WRITEALLOC)
271 277 cachepolicy = CPOLICY_WRITEBACK;
272 278 ecc_mask = 0;
  279 + }
  280 +
  281 + /*
  282 + * On non-Xscale3 ARMv5-and-older systems, use CB=01
  283 + * (Uncached/Buffered) for ioremap_wc() mappings. On XScale3
  284 + * and ARMv6+, use TEXCB=00100 mappings (Inner/Outer Uncacheable
  285 + * in xsc3 parlance, Uncached Normal in ARMv6 parlance).
  286 + */
  287 + if (cpu_is_xsc3() || cpu_arch >= CPU_ARCH_ARMv6) {
  288 + mem_types[MT_DEVICE_WC].prot_pte_ext |= PTE_EXT_TEX(1);
  289 + mem_types[MT_DEVICE_WC].prot_sect |= PMD_SECT_TEX(1);
  290 + } else {
  291 + mem_types[MT_DEVICE_WC].prot_pte |= L_PTE_BUFFERABLE;
  292 + mem_types[MT_DEVICE_WC].prot_sect |= PMD_SECT_BUFFERABLE;
273 293 }
274 294  
275 295 /*