Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 25284
b: refs/heads/master
c: 23759dc
h: refs/heads/master
v: v3
  • Loading branch information
Lennert Buytenhek authored and Russell King committed Apr 1, 2006
1 parent a7c7ca2 commit a1c2dd0
Show file tree
Hide file tree
Showing 11 changed files with 81 additions and 9 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: d3f4c571b6e596f9d39c596426269006a309d3b8
refs/heads/master: 23759dc6430428897a36c4d493f611eca55c9481
3 changes: 3 additions & 0 deletions trunk/arch/arm/kernel/setup.c
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,9 @@ static void __init dump_cpu_info(int cpu)
dump_cache("cache", cpu, CACHE_ISIZE(info));
}
}

if (arch_is_coherent())
printk("Cache coherency enabled\n");
}

int cpu_architecture(void)
Expand Down
6 changes: 6 additions & 0 deletions trunk/arch/arm/mach-ixp23xx/pci.c
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,12 @@ static void __init ixp23xx_pci_common_init(void)
*IXP23XX_PCI_CPP_ADDR_BITS &= ~(1 << 1);
} else {
*IXP23XX_PCI_CPP_ADDR_BITS |= (1 << 1);

/*
* Enable coherency on A2 silicon.
*/
if (arch_is_coherent())
*IXP23XX_CPP2XSI_CURR_XFER_REG3 &= ~IXP23XX_CPP2XSI_COH_OFF;
}
}

Expand Down
17 changes: 17 additions & 0 deletions trunk/arch/arm/mm/consistent.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#include <linux/device.h>
#include <linux/dma-mapping.h>

#include <asm/memory.h>
#include <asm/cacheflush.h>
#include <asm/tlbflush.h>
#include <asm/sizes.h>
Expand Down Expand Up @@ -272,6 +273,17 @@ __dma_alloc(struct device *dev, size_t size, dma_addr_t *handle, gfp_t gfp,
void *
dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *handle, gfp_t gfp)
{
if (arch_is_coherent()) {
void *virt;

virt = kmalloc(size, gfp);
if (!virt)
return NULL;
*handle = virt_to_dma(dev, virt);

return virt;
}

return __dma_alloc(dev, size, handle, gfp,
pgprot_noncached(pgprot_kernel));
}
Expand Down Expand Up @@ -350,6 +362,11 @@ void dma_free_coherent(struct device *dev, size_t size, void *cpu_addr, dma_addr

WARN_ON(irqs_disabled());

if (arch_is_coherent()) {
kfree(cpu_addr);
return;
}

size = PAGE_ALIGN(size);

spin_lock_irqsave(&consistent_lock, flags);
Expand Down
11 changes: 11 additions & 0 deletions trunk/arch/arm/mm/mm-armv.c
Original file line number Diff line number Diff line change
Expand Up @@ -388,6 +388,17 @@ void __init build_mem_type_table(void)
cp = &cache_policies[cachepolicy];
kern_pgprot = user_pgprot = cp->pte;

/*
* Enable CPU-specific coherency if supported.
* (Only available on XSC3 at the moment.)
*/
if (arch_is_coherent()) {
if (cpu_is_xsc3()) {
mem_types[MT_MEMORY].prot_sect |= PMD_SECT_S;
mem_types[MT_MEMORY].prot_pte |= L_PTE_COHERENT;
}
}

/*
* ARMv6 and above have extended page tables.
*/
Expand Down
2 changes: 1 addition & 1 deletion trunk/arch/arm/mm/proc-xsc3.S
Original file line number Diff line number Diff line change
Expand Up @@ -371,7 +371,7 @@ ENTRY(cpu_xsc3_switch_mm)
ENTRY(cpu_xsc3_set_pte)
str r1, [r0], #-2048 @ linux version

bic r2, r1, #0xff0
bic r2, r1, #0xdf0 @ Keep C, B, coherency bits
orr r2, r2, #PTE_TYPE_EXT @ extended page

eor r3, r1, #L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_WRITE | L_PTE_DIRTY
Expand Down
17 changes: 17 additions & 0 deletions trunk/include/asm-arm/arch-ixp23xx/memory.h
Original file line number Diff line number Diff line change
Expand Up @@ -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; \
Expand All @@ -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


Expand Down
22 changes: 15 additions & 7 deletions trunk/include/asm-arm/dma-mapping.h
Original file line number Diff line number Diff line change
Expand Up @@ -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();
}

/*
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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);
}
}

Expand All @@ -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
Expand Down
8 changes: 8 additions & 0 deletions trunk/include/asm-arm/memory.h
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down
1 change: 1 addition & 0 deletions trunk/include/asm-arm/pgtable-hwdef.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 */

Expand Down
1 change: 1 addition & 0 deletions trunk/include/asm-arm/pgtable.h
Original file line number Diff line number Diff line change
Expand Up @@ -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) */

Expand Down

0 comments on commit a1c2dd0

Please sign in to comment.