Commit 1ad77a87 authored by Lennert Buytenhek's avatar Lennert Buytenhek Committed by Russell King

[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: default avatarLennert Buytenhek <buytenh@marvell.com>
Signed-off-by: default avatarRussell King <rmk+kernel@arm.linux.org.uk>
parent 65846909
...@@ -61,8 +61,9 @@ extern void __raw_readsl(const void __iomem *addr, void *data, int longlen); ...@@ -61,8 +61,9 @@ extern void __raw_readsl(const void __iomem *addr, void *data, int longlen);
#define MT_DEVICE_NONSHARED 1 #define MT_DEVICE_NONSHARED 1
#define MT_DEVICE_CACHED 2 #define MT_DEVICE_CACHED 2
#define MT_DEVICE_IXP2000 3 #define MT_DEVICE_IXP2000 3
#define MT_DEVICE_WC 4
/* /*
* types 4 onwards can be found in asm/mach/map.h and are undefined * types 5 onwards can be found in asm/mach/map.h and are undefined
* for ioremap * for ioremap
*/ */
...@@ -215,11 +216,13 @@ extern void _memset_io(volatile void __iomem *, int, size_t); ...@@ -215,11 +216,13 @@ extern void _memset_io(volatile void __iomem *, int, size_t);
#define ioremap(cookie,size) __arm_ioremap(cookie, size, MT_DEVICE) #define ioremap(cookie,size) __arm_ioremap(cookie, size, MT_DEVICE)
#define ioremap_nocache(cookie,size) __arm_ioremap(cookie, size, MT_DEVICE) #define ioremap_nocache(cookie,size) __arm_ioremap(cookie, size, MT_DEVICE)
#define ioremap_cached(cookie,size) __arm_ioremap(cookie, size, MT_DEVICE_CACHED) #define ioremap_cached(cookie,size) __arm_ioremap(cookie, size, MT_DEVICE_CACHED)
#define ioremap_wc(cookie,size) __arm_ioremap(cookie, size, MT_DEVICE_WC)
#define iounmap(cookie) __iounmap(cookie) #define iounmap(cookie) __iounmap(cookie)
#else #else
#define ioremap(cookie,size) __arch_ioremap((cookie), (size), MT_DEVICE) #define ioremap(cookie,size) __arch_ioremap((cookie), (size), MT_DEVICE)
#define ioremap_nocache(cookie,size) __arch_ioremap((cookie), (size), MT_DEVICE) #define ioremap_nocache(cookie,size) __arch_ioremap((cookie), (size), MT_DEVICE)
#define ioremap_cached(cookie,size) __arch_ioremap((cookie), (size), MT_DEVICE_CACHED) #define ioremap_cached(cookie,size) __arch_ioremap((cookie), (size), MT_DEVICE_CACHED)
#define ioremap_wc(cookie,size) __arch_ioremap((cookie), (size), MT_DEVICE_WC)
#define iounmap(cookie) __arch_iounmap(cookie) #define iounmap(cookie) __arch_iounmap(cookie)
#endif #endif
......
...@@ -18,13 +18,13 @@ struct map_desc { ...@@ -18,13 +18,13 @@ struct map_desc {
unsigned int type; unsigned int type;
}; };
/* types 0-3 are defined in asm/io.h */ /* types 0-4 are defined in asm/io.h */
#define MT_CACHECLEAN 4 #define MT_CACHECLEAN 5
#define MT_MINICLEAN 5 #define MT_MINICLEAN 6
#define MT_LOW_VECTORS 6 #define MT_LOW_VECTORS 7
#define MT_HIGH_VECTORS 7 #define MT_HIGH_VECTORS 8
#define MT_MEMORY 8 #define MT_MEMORY 9
#define MT_ROM 9 #define MT_ROM 10
#define MT_NONSHARED_DEVICE MT_DEVICE_NONSHARED #define MT_NONSHARED_DEVICE MT_DEVICE_NONSHARED
#define MT_IXP2000_DEVICE MT_DEVICE_IXP2000 #define MT_IXP2000_DEVICE MT_DEVICE_IXP2000
......
...@@ -211,6 +211,12 @@ static struct mem_type mem_types[] = { ...@@ -211,6 +211,12 @@ static struct mem_type mem_types[] = {
PMD_SECT_TEX(1), PMD_SECT_TEX(1),
.domain = DOMAIN_IO, .domain = DOMAIN_IO,
}, },
[MT_DEVICE_WC] = { /* ioremap_wc */
.prot_pte = PROT_PTE_DEVICE,
.prot_l1 = PMD_TYPE_TABLE,
.prot_sect = PROT_SECT_DEVICE,
.domain = DOMAIN_IO,
},
[MT_CACHECLEAN] = { [MT_CACHECLEAN] = {
.prot_sect = PMD_TYPE_SECT | PMD_SECT_XN, .prot_sect = PMD_TYPE_SECT | PMD_SECT_XN,
.domain = DOMAIN_KERNEL, .domain = DOMAIN_KERNEL,
...@@ -272,6 +278,20 @@ static void __init build_mem_type_table(void) ...@@ -272,6 +278,20 @@ static void __init build_mem_type_table(void)
ecc_mask = 0; ecc_mask = 0;
} }
/*
* On non-Xscale3 ARMv5-and-older systems, use CB=01
* (Uncached/Buffered) for ioremap_wc() mappings. On XScale3
* and ARMv6+, use TEXCB=00100 mappings (Inner/Outer Uncacheable
* in xsc3 parlance, Uncached Normal in ARMv6 parlance).
*/
if (cpu_is_xsc3() || cpu_arch >= CPU_ARCH_ARMv6) {
mem_types[MT_DEVICE_WC].prot_pte_ext |= PTE_EXT_TEX(1);
mem_types[MT_DEVICE_WC].prot_sect |= PMD_SECT_TEX(1);
} else {
mem_types[MT_DEVICE_WC].prot_pte |= L_PTE_BUFFERABLE;
mem_types[MT_DEVICE_WC].prot_sect |= PMD_SECT_BUFFERABLE;
}
/* /*
* ARMv5 and lower, bit 4 must be set for page tables. * ARMv5 and lower, bit 4 must be set for page tables.
* (was: cache "update-able on write" bit on ARM610) * (was: cache "update-able on write" bit on ARM610)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment