summaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorSascha Hauer <s.hauer@pengutronix.de>2019-02-13 20:31:46 +0100
committerSascha Hauer <s.hauer@pengutronix.de>2019-02-13 20:31:46 +0100
commit17b6909dd1b1e222764728e62124726a2581c6aa (patch)
tree5d40a57903b3361dcfa68a26438906312497d85f /arch
parent02b7a84385627508a7a7227e8cea0c8953a5bedc (diff)
parent7179471fd7651e8ddd7758d2c3c94928421e5493 (diff)
downloadbarebox-17b6909dd1b1e222764728e62124726a2581c6aa.tar.gz
barebox-17b6909dd1b1e222764728e62124726a2581c6aa.tar.xz
Merge branch 'for-next/arm-mmu'
Diffstat (limited to 'arch')
-rw-r--r--arch/arm/cpu/Makefile2
-rw-r--r--arch/arm/cpu/mmu-common.c82
-rw-r--r--arch/arm/cpu/mmu-common.h20
-rw-r--r--arch/arm/cpu/mmu.c96
-rw-r--r--arch/arm/cpu/mmu.h2
-rw-r--r--arch/arm/cpu/mmu_64.c96
-rw-r--r--arch/arm/cpu/mmu_64.h2
-rw-r--r--arch/arm/include/asm/io.h5
8 files changed, 128 insertions, 177 deletions
diff --git a/arch/arm/cpu/Makefile b/arch/arm/cpu/Makefile
index a35db435c1..8e1af8bf8d 100644
--- a/arch/arm/cpu/Makefile
+++ b/arch/arm/cpu/Makefile
@@ -1,7 +1,7 @@
obj-y += cpu.o
obj-$(CONFIG_ARM_EXCEPTIONS) += exceptions$(S64).o interrupts$(S64).o
-obj-$(CONFIG_MMU) += mmu$(S64).o
+obj-$(CONFIG_MMU) += mmu$(S64).o mmu-common.o
lwl-y += lowlevel$(S64).o
obj-pbl-$(CONFIG_MMU) += mmu-early$(S64).o
obj-pbl-$(CONFIG_CPU_32v7) += hyp.o
diff --git a/arch/arm/cpu/mmu-common.c b/arch/arm/cpu/mmu-common.c
new file mode 100644
index 0000000000..aeefbb2daa
--- /dev/null
+++ b/arch/arm/cpu/mmu-common.c
@@ -0,0 +1,82 @@
+
+#define pr_fmt(fmt) "mmu: " fmt
+
+#include <common.h>
+#include <init.h>
+#include <dma-dir.h>
+#include <dma.h>
+#include <mmu.h>
+#include <asm/system.h>
+#include <memory.h>
+#include "mmu.h"
+
+
+void dma_sync_single_for_cpu(dma_addr_t address, size_t size,
+ enum dma_data_direction dir)
+{
+ if (dir != DMA_TO_DEVICE)
+ dma_inv_range((void *)address, size);
+}
+
+dma_addr_t dma_map_single(struct device_d *dev, void *ptr, size_t size,
+ enum dma_data_direction dir)
+{
+ unsigned long addr = (unsigned long)ptr;
+
+ dma_sync_single_for_device(addr, size, dir);
+
+ return addr;
+}
+
+void dma_unmap_single(struct device_d *dev, dma_addr_t addr, size_t size,
+ enum dma_data_direction dir)
+{
+ dma_sync_single_for_cpu(addr, size, dir);
+}
+
+void *dma_alloc_map(size_t size, dma_addr_t *dma_handle, unsigned flags)
+{
+ void *ret;
+
+ size = PAGE_ALIGN(size);
+ ret = xmemalign(PAGE_SIZE, size);
+ if (dma_handle)
+ *dma_handle = (dma_addr_t)ret;
+
+ memset(ret, 0, size);
+ dma_flush_range(ret, size);
+
+ arch_remap_range(ret, size, flags);
+
+ return ret;
+}
+
+void *dma_alloc_coherent(size_t size, dma_addr_t *dma_handle)
+{
+ return dma_alloc_map(size, dma_handle, MAP_UNCACHED);
+}
+
+void dma_free_coherent(void *mem, dma_addr_t dma_handle, size_t size)
+{
+ size = PAGE_ALIGN(size);
+ arch_remap_range(mem, size, MAP_CACHED);
+
+ free(mem);
+}
+
+static int mmu_init(void)
+{
+ if (list_empty(&memory_banks))
+ /*
+ * If you see this it means you have no memory registered.
+ * This can be done either with arm_add_mem_device() in an
+ * initcall prior to mmu_initcall or via devicetree in the
+ * memory node.
+ */
+ panic("MMU: No memory bank found! Cannot continue\n");
+
+ __mmu_init(get_cr() & CR_M);
+
+ return 0;
+}
+mmu_initcall(mmu_init); \ No newline at end of file
diff --git a/arch/arm/cpu/mmu-common.h b/arch/arm/cpu/mmu-common.h
new file mode 100644
index 0000000000..0a33b138e1
--- /dev/null
+++ b/arch/arm/cpu/mmu-common.h
@@ -0,0 +1,20 @@
+#ifndef __ARM_MMU_COMMON_H
+#define __ARM_MMU_COMMON_H
+
+void dma_inv_range(void *ptr, size_t size);
+void dma_flush_range(void *ptr, size_t size);
+void *dma_alloc_map(size_t size, dma_addr_t *dma_handle, unsigned flags);
+void __mmu_init(bool mmu_on);
+
+static inline void arm_mmu_not_initialized_error(void)
+{
+ /*
+ * This means:
+ * - one of the MMU functions like dma_alloc_coherent
+ * or remap_range is called too early, before the MMU is initialized
+ * - Or the MMU initialization has failed earlier
+ */
+ panic("MMU not initialized\n");
+}
+
+#endif \ No newline at end of file
diff --git a/arch/arm/cpu/mmu.c b/arch/arm/cpu/mmu.c
index fc48376f66..29816ad563 100644
--- a/arch/arm/cpu/mmu.c
+++ b/arch/arm/cpu/mmu.c
@@ -75,17 +75,6 @@ static uint32_t pgd_flags_wc;
#define PTE_MASK ((1 << 12) - 1)
-static void arm_mmu_not_initialized_error(void)
-{
- /*
- * This means:
- * - one of the MMU functions like dma_alloc_coherent
- * or remap_range is called too early, before the MMU is initialized
- * - Or the MMU initialization has failed earlier
- */
- panic("MMU not initialized\n");
-}
-
static bool pgd_type_table(u32 pgd)
{
return (pgd & PMD_TYPE_MASK) == PMD_TYPE_TABLE;
@@ -108,7 +97,7 @@ static u32 *find_pte(unsigned long adr)
return &table[(adr >> PAGE_SHIFT) & 0xff];
}
-static void dma_flush_range(void *ptr, size_t size)
+void dma_flush_range(void *ptr, size_t size)
{
unsigned long start = (unsigned long)ptr;
unsigned long end = start + size;
@@ -118,8 +107,11 @@ static void dma_flush_range(void *ptr, size_t size)
outer_cache.flush_range(start, end);
}
-static void dma_inv_range(unsigned long start, unsigned long end)
+void dma_inv_range(void *ptr, size_t size)
{
+ unsigned long start = (unsigned long)ptr;
+ unsigned long end = start + size;
+
if (outer_cache.inv_range)
outer_cache.inv_range(start, end);
__dma_inv_range(start, end);
@@ -409,19 +401,10 @@ static void vectors_init(void)
/*
* Prepare MMU for usage enable it.
*/
-static int mmu_init(void)
+void __mmu_init(bool mmu_on)
{
struct memory_bank *bank;
- if (list_empty(&memory_banks))
- /*
- * If you see this it means you have no memory registered.
- * This can be done either with arm_add_mem_device() in an
- * initcall prior to mmu_initcall or via devicetree in the
- * memory node.
- */
- panic("MMU: No memory bank found! Cannot continue\n");
-
arm_set_cache_functions();
if (cpu_architecture() >= CPU_ARCH_ARMv7) {
@@ -436,7 +419,7 @@ static int mmu_init(void)
pte_flags_uncached = PTE_FLAGS_UNCACHED_V4;
}
- if (get_cr() & CR_M) {
+ if (mmu_on) {
/*
* Early MMU code has already enabled the MMU. We assume a
* flat 1:1 section mapping in this case.
@@ -480,10 +463,7 @@ static int mmu_init(void)
}
__mmu_cache_on();
-
- return 0;
}
-mmu_initcall(mmu_init);
/*
* Clean and invalide caches, disable MMU
@@ -498,57 +478,11 @@ void mmu_disable(void)
__mmu_cache_off();
}
-static void *dma_alloc_map(size_t size, dma_addr_t *dma_handle, unsigned flags)
-{
- void *ret;
-
- size = PAGE_ALIGN(size);
- ret = xmemalign(PAGE_SIZE, size);
- if (dma_handle)
- *dma_handle = (dma_addr_t)ret;
-
- dma_inv_range((unsigned long)ret, (unsigned long)ret + size);
-
- arch_remap_range(ret, size, flags);
-
- return ret;
-}
-
-void *dma_alloc_coherent(size_t size, dma_addr_t *dma_handle)
-{
- return dma_alloc_map(size, dma_handle, MAP_UNCACHED);
-}
-
void *dma_alloc_writecombine(size_t size, dma_addr_t *dma_handle)
{
return dma_alloc_map(size, dma_handle, ARCH_MAP_WRITECOMBINE);
}
-unsigned long virt_to_phys(volatile void *virt)
-{
- return (unsigned long)virt;
-}
-
-void *phys_to_virt(unsigned long phys)
-{
- return (void *)phys;
-}
-
-void dma_free_coherent(void *mem, dma_addr_t dma_handle, size_t size)
-{
- size = PAGE_ALIGN(size);
- arch_remap_range(mem, size, MAP_CACHED);
-
- free(mem);
-}
-
-void dma_sync_single_for_cpu(dma_addr_t address, size_t size,
- enum dma_data_direction dir)
-{
- if (dir != DMA_TO_DEVICE)
- dma_inv_range(address, address + size);
-}
-
void dma_sync_single_for_device(dma_addr_t address, size_t size,
enum dma_data_direction dir)
{
@@ -562,19 +496,3 @@ void dma_sync_single_for_device(dma_addr_t address, size_t size,
outer_cache.clean_range(address, address + size);
}
}
-
-dma_addr_t dma_map_single(struct device_d *dev, void *ptr, size_t size,
- enum dma_data_direction dir)
-{
- unsigned long addr = (unsigned long)ptr;
-
- dma_sync_single_for_device(addr, size, dir);
-
- return addr;
-}
-
-void dma_unmap_single(struct device_d *dev, dma_addr_t addr, size_t size,
- enum dma_data_direction dir)
-{
- dma_sync_single_for_cpu(addr, size, dir);
-}
diff --git a/arch/arm/cpu/mmu.h b/arch/arm/cpu/mmu.h
index 2e425e092e..338728aacd 100644
--- a/arch/arm/cpu/mmu.h
+++ b/arch/arm/cpu/mmu.h
@@ -4,6 +4,8 @@
#include <asm/pgtable.h>
#include <linux/sizes.h>
+#include "mmu-common.h"
+
#define PGDIR_SHIFT 20
#define PGDIR_SIZE (1UL << PGDIR_SHIFT)
diff --git a/arch/arm/cpu/mmu_64.c b/arch/arm/cpu/mmu_64.c
index 99ddd5a441..b45a69661e 100644
--- a/arch/arm/cpu/mmu_64.c
+++ b/arch/arm/cpu/mmu_64.c
@@ -37,17 +37,6 @@
static uint64_t *ttb;
-static void arm_mmu_not_initialized_error(void)
-{
- /*
- * This means:
- * - one of the MMU functions like dma_alloc_coherent
- * or remap_range is called too early, before the MMU is initialized
- * - Or the MMU initialization has failed earlier
- */
- panic("MMU not initialized\n");
-}
-
static void set_table(uint64_t *pt, uint64_t *table_addr)
{
uint64_t val;
@@ -119,7 +108,8 @@ static void split_block(uint64_t *pte, int level)
set_table(pte, new_table);
}
-static void map_region(uint64_t virt, uint64_t phys, uint64_t size, uint64_t attr)
+static void create_sections(uint64_t virt, uint64_t phys, uint64_t size,
+ uint64_t attr)
{
uint64_t block_size;
uint64_t block_shift;
@@ -162,11 +152,7 @@ static void map_region(uint64_t virt, uint64_t phys, uint64_t size, uint64_t att
}
}
-}
-static void create_sections(uint64_t virt, uint64_t phys, uint64_t size, uint64_t flags)
-{
- map_region(virt, phys, size, flags);
tlb_invalidate();
}
@@ -183,9 +169,8 @@ int arch_remap_range(void *_start, size_t size, unsigned flags)
return -EINVAL;
}
- map_region((uint64_t)_start, (uint64_t)_start, (uint64_t)size, flags);
- tlb_invalidate();
-
+ create_sections((uint64_t)_start, (uint64_t)_start, (uint64_t)size,
+ flags);
return 0;
}
@@ -198,21 +183,12 @@ static void mmu_enable(void)
/*
* Prepare MMU for usage enable it.
*/
-static int mmu_init(void)
+void __mmu_init(bool mmu_on)
{
struct memory_bank *bank;
unsigned int el;
- if (list_empty(&memory_banks))
- /*
- * If you see this it means you have no memory registered.
- * This can be done either with arm_add_mem_device() in an
- * initcall prior to mmu_initcall or via devicetree in the
- * memory node.
- */
- panic("MMU: No memory bank found! Cannot continue\n");
-
- if (get_cr() & CR_M)
+ if (mmu_on)
mmu_disable();
ttb = create_table();
@@ -232,10 +208,7 @@ static int mmu_init(void)
create_sections(0x0, 0x0, 0x1000, 0x0);
mmu_enable();
-
- return 0;
}
-mmu_initcall(mmu_init);
void mmu_disable(void)
{
@@ -252,45 +225,20 @@ void mmu_disable(void)
isb();
}
-unsigned long virt_to_phys(volatile void *virt)
-{
- return (unsigned long)virt;
-}
-
-void *phys_to_virt(unsigned long phys)
-{
- return (void *)phys;
-}
-
-void *dma_alloc_coherent(size_t size, dma_addr_t *dma_handle)
+void dma_inv_range(void *ptr, size_t size)
{
- void *ret;
+ unsigned long start = (unsigned long)ptr;
+ unsigned long end = start + size - 1;
- size = PAGE_ALIGN(size);
- ret = xmemalign(PAGE_SIZE, size);
- if (dma_handle)
- *dma_handle = (dma_addr_t)ret;
-
- map_region((unsigned long)ret, (unsigned long)ret, size, UNCACHED_MEM);
- tlb_invalidate();
-
- return ret;
+ v8_inv_dcache_range(start, end);
}
-void dma_free_coherent(void *mem, dma_addr_t dma_handle, size_t size)
+void dma_flush_range(void *ptr, size_t size)
{
- size = PAGE_ALIGN(size);
-
- map_region((unsigned long)mem, (unsigned long)mem, size, CACHED_MEM);
+ unsigned long start = (unsigned long)ptr;
+ unsigned long end = start + size - 1;
- free(mem);
-}
-
-void dma_sync_single_for_cpu(dma_addr_t address, size_t size,
- enum dma_data_direction dir)
-{
- if (dir != DMA_TO_DEVICE)
- v8_inv_dcache_range(address, address + size - 1);
+ v8_flush_dcache_range(start, end);
}
void dma_sync_single_for_device(dma_addr_t address, size_t size,
@@ -301,19 +249,3 @@ void dma_sync_single_for_device(dma_addr_t address, size_t size,
else
v8_flush_dcache_range(address, address + size - 1);
}
-
-dma_addr_t dma_map_single(struct device_d *dev, void *ptr, size_t size,
- enum dma_data_direction dir)
-{
- unsigned long addr = (unsigned long)ptr;
-
- dma_sync_single_for_device(addr, size, dir);
-
- return addr;
-}
-
-void dma_unmap_single(struct device_d *dev, dma_addr_t addr, size_t size,
- enum dma_data_direction dir)
-{
- dma_sync_single_for_cpu(addr, size, dir);
-}
diff --git a/arch/arm/cpu/mmu_64.h b/arch/arm/cpu/mmu_64.h
index 2cbe720625..e2e125686d 100644
--- a/arch/arm/cpu/mmu_64.h
+++ b/arch/arm/cpu/mmu_64.h
@@ -1,4 +1,6 @@
+#include "mmu-common.h"
+
#define CACHED_MEM (PTE_BLOCK_MEMTYPE(MT_NORMAL) | \
PTE_BLOCK_OUTER_SHARE | \
PTE_BLOCK_AF)
diff --git a/arch/arm/include/asm/io.h b/arch/arm/include/asm/io.h
index d06ff8323f..56db546341 100644
--- a/arch/arm/include/asm/io.h
+++ b/arch/arm/include/asm/io.h
@@ -69,10 +69,6 @@ extern void memset_io(volatile void __iomem *, int, size_t);
#define setbits_8(addr, set) setbits(8, addr, set)
#define clrsetbits_8(addr, clear, set) clrsetbits(8, addr, clear, set)
-#ifdef CONFIG_MMU
-void *phys_to_virt(unsigned long phys);
-unsigned long virt_to_phys(volatile void *virt);
-#else
static inline void *phys_to_virt(unsigned long phys)
{
return (void *)phys;
@@ -82,6 +78,5 @@ static inline unsigned long virt_to_phys(volatile void *mem)
{
return (unsigned long)mem;
}
-#endif
#endif /* __ASM_ARM_IO_H */