Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 23759dc6 authored by Lennert Buytenhek's avatar Lennert Buytenhek Committed by Russell King
Browse files

[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: default avatarDeepak Saxena <dsaxena@plexity.net>
Signed-off-by: default avatarLennert Buytenhek <buytenh@wantstofly.org>
Signed-off-by: default avatarRussell King <rmk+kernel@arm.linux.org.uk>
parent d3f4c571
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -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)
+6 −0
Original line number Diff line number Diff line
@@ -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;
	}
}

+17 −0
Original line number Diff line number Diff line
@@ -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>
@@ -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));
}
@@ -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);
+11 −0
Original line number Diff line number Diff line
@@ -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.
	 */
+1 −1
Original line number Diff line number Diff line
@@ -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
Loading