diff options
author | Sascha Hauer <s.hauer@pengutronix.de> | 2019-02-13 20:31:46 +0100 |
---|---|---|
committer | Sascha Hauer <s.hauer@pengutronix.de> | 2019-02-13 20:31:46 +0100 |
commit | 17b6909dd1b1e222764728e62124726a2581c6aa (patch) | |
tree | 5d40a57903b3361dcfa68a26438906312497d85f /arch | |
parent | 02b7a84385627508a7a7227e8cea0c8953a5bedc (diff) | |
parent | 7179471fd7651e8ddd7758d2c3c94928421e5493 (diff) | |
download | barebox-17b6909dd1b1e222764728e62124726a2581c6aa.tar.gz barebox-17b6909dd1b1e222764728e62124726a2581c6aa.tar.xz |
Merge branch 'for-next/arm-mmu'
Diffstat (limited to 'arch')
-rw-r--r-- | arch/arm/cpu/Makefile | 2 | ||||
-rw-r--r-- | arch/arm/cpu/mmu-common.c | 82 | ||||
-rw-r--r-- | arch/arm/cpu/mmu-common.h | 20 | ||||
-rw-r--r-- | arch/arm/cpu/mmu.c | 96 | ||||
-rw-r--r-- | arch/arm/cpu/mmu.h | 2 | ||||
-rw-r--r-- | arch/arm/cpu/mmu_64.c | 96 | ||||
-rw-r--r-- | arch/arm/cpu/mmu_64.h | 2 | ||||
-rw-r--r-- | arch/arm/include/asm/io.h | 5 |
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 */ |