summaryrefslogtreecommitdiffstats
path: root/include/asm-arm
diff options
context:
space:
mode:
authorLennert Buytenhek <buytenh@wantstofly.org>2006-04-02 00:07:39 +0100
committerRussell King <rmk+kernel@arm.linux.org.uk>2006-04-02 00:07:39 +0100
commit23759dc6430428897a36c4d493f611eca55c9481 (patch)
treec62050927599b36ed223753c35fd737e3c0c6762 /include/asm-arm
parentd3f4c571b6e596f9d39c596426269006a309d3b8 (diff)
[ARM] 3439/2: xsc3: add I/O coherency support
Patch from Lennert Buytenhek This patch adds support for the I/O coherent cache available on the xsc3. The approach is to provide a simple API to determine whether the chipset supports coherency by calling arch_is_coherent() and then setting the appropriate system memory PTE and PMD bits. In addition, we call this API on dma_alloc_coherent() and dma_map_single() calls. A generic version exists that will compile out all the coherency-related code that is not needed on the majority of ARM systems. Note that we do not check for coherency in the dma_alloc_writecombine() function as that still requires a special PTE setting. We also don't touch dma_mmap_coherent() as that is a special ARM-only API that is by definition only used on non-coherent system. Signed-off-by: Deepak Saxena <dsaxena@plexity.net> Signed-off-by: Lennert Buytenhek <buytenh@wantstofly.org> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'include/asm-arm')
-rw-r--r--include/asm-arm/arch-ixp23xx/memory.h17
-rw-r--r--include/asm-arm/dma-mapping.h22
-rw-r--r--include/asm-arm/memory.h8
-rw-r--r--include/asm-arm/pgtable-hwdef.h1
-rw-r--r--include/asm-arm/pgtable.h1
5 files changed, 42 insertions, 7 deletions
diff --git a/include/asm-arm/arch-ixp23xx/memory.h b/include/asm-arm/arch-ixp23xx/memory.h
index bebcf0aa0d7..6e19f46d54d 100644
--- a/include/asm-arm/arch-ixp23xx/memory.h
+++ b/include/asm-arm/arch-ixp23xx/memory.h
@@ -28,6 +28,7 @@
* to an address that the kernel can use.
*/
#ifndef __ASSEMBLY__
+#include <asm/mach-types.h>
#define __virt_to_bus(v) \
({ unsigned int ret; \
@@ -40,6 +41,22 @@
data = *((volatile int *)IXP23XX_PCI_SDRAM_BAR); \
__phys_to_virt((((b - (data & 0xfffffff0)) + 0x00000000))); })
+/*
+ * Coherency support. Only supported on A2 CPUs or on A1
+ * systems that have the cache coherency workaround.
+ */
+static inline int __ixp23xx_arch_is_coherent(void)
+{
+ extern unsigned int processor_id;
+
+ if (((processor_id & 15) >= 2) || machine_is_roadrunner())
+ return 1;
+
+ return 0;
+}
+
+#define arch_is_coherent() __ixp23xx_arch_is_coherent()
+
#endif
diff --git a/include/asm-arm/dma-mapping.h b/include/asm-arm/dma-mapping.h
index e3e8541ee63..63ca7412a46 100644
--- a/include/asm-arm/dma-mapping.h
+++ b/include/asm-arm/dma-mapping.h
@@ -47,7 +47,7 @@ static inline int dma_get_cache_alignment(void)
static inline int dma_is_consistent(dma_addr_t handle)
{
- return 0;
+ return !!arch_is_coherent();
}
/*
@@ -145,7 +145,9 @@ static inline dma_addr_t
dma_map_single(struct device *dev, void *cpu_addr, size_t size,
enum dma_data_direction dir)
{
- consistent_sync(cpu_addr, size, dir);
+ if (!arch_is_coherent())
+ consistent_sync(cpu_addr, size, dir);
+
return virt_to_dma(dev, (unsigned long)cpu_addr);
}
#else
@@ -255,7 +257,9 @@ dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
sg->dma_address = page_to_dma(dev, sg->page) + sg->offset;
virt = page_address(sg->page) + sg->offset;
- consistent_sync(virt, sg->length, dir);
+
+ if (!arch_is_coherent())
+ consistent_sync(virt, sg->length, dir);
}
return nents;
@@ -310,14 +314,16 @@ static inline void
dma_sync_single_for_cpu(struct device *dev, dma_addr_t handle, size_t size,
enum dma_data_direction dir)
{
- consistent_sync((void *)dma_to_virt(dev, handle), size, dir);
+ if (!arch_is_coherent())
+ consistent_sync((void *)dma_to_virt(dev, handle), size, dir);
}
static inline void
dma_sync_single_for_device(struct device *dev, dma_addr_t handle, size_t size,
enum dma_data_direction dir)
{
- consistent_sync((void *)dma_to_virt(dev, handle), size, dir);
+ if (!arch_is_coherent())
+ consistent_sync((void *)dma_to_virt(dev, handle), size, dir);
}
#else
extern void dma_sync_single_for_cpu(struct device*, dma_addr_t, size_t, enum dma_data_direction);
@@ -347,7 +353,8 @@ dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg, int nents,
for (i = 0; i < nents; i++, sg++) {
char *virt = page_address(sg->page) + sg->offset;
- consistent_sync(virt, sg->length, dir);
+ if (!arch_is_coherent())
+ consistent_sync(virt, sg->length, dir);
}
}
@@ -359,7 +366,8 @@ dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg, int nents,
for (i = 0; i < nents; i++, sg++) {
char *virt = page_address(sg->page) + sg->offset;
- consistent_sync(virt, sg->length, dir);
+ if (!arch_is_coherent())
+ consistent_sync(virt, sg->length, dir);
}
}
#else
diff --git a/include/asm-arm/memory.h b/include/asm-arm/memory.h
index afa5c3ea077..2b3cf69b3ed 100644
--- a/include/asm-arm/memory.h
+++ b/include/asm-arm/memory.h
@@ -234,6 +234,14 @@ static inline __deprecated void *bus_to_virt(unsigned long x)
#define virt_to_dma(dev, addr) (__arch_virt_to_dma(dev, addr))
#endif
+/*
+ * Optional coherency support. Currently used only by selected
+ * Intel XSC3-based systems.
+ */
+#ifndef arch_is_coherent
+#define arch_is_coherent() 0
+#endif
+
#endif
#include <asm-generic/memory_model.h>
diff --git a/include/asm-arm/pgtable-hwdef.h b/include/asm-arm/pgtable-hwdef.h
index 1d033495cc7..1bc1f997bda 100644
--- a/include/asm-arm/pgtable-hwdef.h
+++ b/include/asm-arm/pgtable-hwdef.h
@@ -73,6 +73,7 @@
#define PTE_EXT_AP_URW_SRW (PTE_EXT_AP1|PTE_EXT_AP0)
#define PTE_EXT_TEX(x) ((x) << 6) /* v5 */
#define PTE_EXT_APX (1 << 9) /* v6 */
+#define PTE_EXT_COHERENT (1 << 9) /* XScale3 */
#define PTE_EXT_SHARED (1 << 10) /* v6 */
#define PTE_EXT_NG (1 << 11) /* v6 */
diff --git a/include/asm-arm/pgtable.h b/include/asm-arm/pgtable.h
index e595ae24efe..e85c08d78dd 100644
--- a/include/asm-arm/pgtable.h
+++ b/include/asm-arm/pgtable.h
@@ -156,6 +156,7 @@ extern void __pgd_error(const char *file, int line, unsigned long val);
#define L_PTE_WRITE (1 << 5)
#define L_PTE_EXEC (1 << 6)
#define L_PTE_DIRTY (1 << 7)
+#define L_PTE_COHERENT (1 << 9) /* I/O coherent (xsc3) */
#define L_PTE_SHARED (1 << 10) /* shared between CPUs (v6) */
#define L_PTE_ASID (1 << 11) /* non-global (use ASID, v6) */