From: Kuo-Jung Su <dant...@faraday-tech.com>

The DMA API is revised as follow:

1. Create an un-cached shadow memory for malloc(),
   the un-cached shadow memory is controlled by
   CONFIG_CONSISTENT_DMA_START and CONFIG_CONSISTENT_DMA_END,
   and initialized inside arch_early_init_r().

2. The virtual address returned by dma_alloc_coherent()
   always points to the corresponding uncached shadow memory
   initialized at step 1.

3. The dma_map_single() will now invalidate/flush caches.

4. The virt_to_phys() will now calculate the physical address
   from the section tables.

Signed-off-by: Kuo-Jung Su <dant...@faraday-tech.com>
CC: Albert Aribaud <albert.u.b...@aribaud.net>
---
Changes for v8:
        - Revised to use a shadow uncached region for malloc().

Changes for v6, v7:
        - Nothing updates

Changes for v5:
        - Add void dram_bank_mmu_setup() into 'arch/arm/cpu/faraday/cpu.c'
          to override the weak function in "cache-cp15.c".
        - Use small page (4KB) to map relocated exception table to 0x0000

Changes for v4:
        - Coding Style cleanup.

Changes for v3:
        - Coding Style cleanup.
        - Always insert a blank line between declarations and code.
        - dma-mapping.h: Have the global data ptr declared outside functions.
        - dma-mapping.h: Add #if...#else...#endif to dma_free_coherent().
        - Drop static non-cached region, now we use 
map_physmem()/unmap_physmem()
          for dynamic mappings.

Changes for v2:
        - Coding Style cleanup.
        - cache-cp15: Enable write buffer in write-through mode.

 arch/arm/cpu/faraday/cpu.c         |   30 +++++++++++++++++++++++++++++
 arch/arm/include/asm/config.h      |   12 ++++++++++++
 arch/arm/include/asm/dma-mapping.h |   37 ++++++++++++++++++++++++++++++++++++
 arch/arm/include/asm/io.h          |   19 ++++++++++++++++--
 4 files changed, 96 insertions(+), 2 deletions(-)

diff --git a/arch/arm/cpu/faraday/cpu.c b/arch/arm/cpu/faraday/cpu.c
index d3c8a9e..83bc7f7 100644
--- a/arch/arm/cpu/faraday/cpu.c
+++ b/arch/arm/cpu/faraday/cpu.c
@@ -101,6 +101,36 @@ int print_cpuinfo(void)
 }
 #endif /* CONFIG_DISPLAY_CPUINFO */

+#ifdef CONFIG_ARCH_EARLY_INIT_R
+int    arch_early_init_r(void)
+{
+#ifndef CONFIG_SYS_DCACHE_OFF
+       uint32_t mask = ~(SZ_1M - 1);
+       uint32_t phys = mem_malloc_start & mask;
+       uint32_t stop = (mem_malloc_end + (SZ_1M - 1)) & mask;
+       uint32_t size = stop - phys;
+       uint32_t virt = CONFIG_CONSISTENT_DMA_START & mask;
+       uint32_t *sect_table = (uint32_t *)gd->arch.tlb_addr;
+
+       if (!mmu_enabled())
+               return 0;
+
+       if (size > (CONFIG_CONSISTENT_DMA_END - virt))
+               panic("malloc size is too large for dma buffer\n");
+
+       while (size > 0) {
+               sect_table[virt >> 20] = phys | (3 << 10) | DCACHE_OFF;
+               virt += SZ_1M;
+               phys += SZ_1M;
+               size -= SZ_1M;
+       }
+
+       mmu_page_table_flush(mem_malloc_start & mask, stop);
+#endif /* !CONFIG_SYS_DCACHE_OFF */
+       return 0;
+}
+#endif /* CONFIG_ARCH_EARLY_INIT_R */
+
 int cleanup_before_linux(void)
 {
        /*
diff --git a/arch/arm/include/asm/config.h b/arch/arm/include/asm/config.h
index 99b703e..295907c 100644
--- a/arch/arm/include/asm/config.h
+++ b/arch/arm/include/asm/config.h
@@ -7,6 +7,18 @@
 #ifndef _ASM_CONFIG_H_
 #define _ASM_CONFIG_H_

+#if defined(CONFIG_SOC_FARADAY) && !defined(CONFIG_SYS_DCACHE_OFF)
+#ifndef CONFIG_ARCH_EARLY_INIT_R
+#define CONFIG_ARCH_EARLY_INIT_R
+#endif
+#ifndef CONFIG_CONSISTENT_DMA_START
+#define CONFIG_CONSISTENT_DMA_START   0xff000000
+#endif
+#ifndef CONFIG_CONSISTENT_DMA_END
+#define CONFIG_CONSISTENT_DMA_END     0xfff00000
+#endif
+#endif /* CONFIG_SOC_FARADAY && !CONFIG_SYS_DCACHE_OFF */
+
 #define CONFIG_LMB
 #define CONFIG_SYS_BOOT_RAMDISK_HIGH
 #endif
diff --git a/arch/arm/include/asm/dma-mapping.h 
b/arch/arm/include/asm/dma-mapping.h
index 55a4e26..3b76046 100644
--- a/arch/arm/include/asm/dma-mapping.h
+++ b/arch/arm/include/asm/dma-mapping.h
@@ -8,6 +8,10 @@
 #ifndef __ASM_ARM_DMA_MAPPING_H
 #define __ASM_ARM_DMA_MAPPING_H

+#if defined(CONFIG_SOC_FARADAY) && !defined(CONFIG_SYS_DCACHE_OFF)
+#include <malloc.h>
+#endif /* CONFIG_SOC_FARADAY && !CONFIG_SYS_DCACHE_OFF */
+
 enum dma_data_direction {
        DMA_BIDIRECTIONAL       = 0,
        DMA_TO_DEVICE           = 1,
@@ -16,13 +20,46 @@ enum dma_data_direction {

 static void *dma_alloc_coherent(size_t len, unsigned long *handle)
 {
+#if defined(CONFIG_SOC_FARADAY) && !defined(CONFIG_SYS_DCACHE_OFF)
+       uint32_t ofs;
+       void *mem = memalign(ARCH_DMA_MINALIGN, len);
+
+       if (handle)
+               *handle = (unsigned long)mem;
+
+       if (mem && mmu_enabled()) {
+               invalidate_dcache_range((ulong)mem, (ulong)mem + len);
+               ofs = (uint32_t)mem - (mem_malloc_start & 0xfff00000);
+               mem = (void *)(CONFIG_CONSISTENT_DMA_START + ofs);
+       }
+
+       return mem;
+#else  /* CONFIG_SOC_FARADAY && !CONFIG_SYS_DCACHE_OFF */
        *handle = (unsigned long)memalign(ARCH_DMA_MINALIGN, len);
+#endif /* CONFIG_SOC_FARADAY && !CONFIG_SYS_DCACHE_OFF */
        return (void *)*handle;
 }

 static inline unsigned long dma_map_single(volatile void *vaddr, size_t len,
                                           enum dma_data_direction dir)
 {
+#if defined(CONFIG_SOC_FARADAY) && !defined(CONFIG_SYS_DCACHE_OFF)
+       if (mmu_enabled()) {
+               switch (dir) {
+               case DMA_BIDIRECTIONAL:
+               case DMA_TO_DEVICE:
+                       flush_dcache_range((ulong)vaddr,
+                               (ulong)vaddr + len);
+                       break;
+
+               case DMA_FROM_DEVICE:
+                       invalidate_dcache_range((ulong)vaddr,
+                               (ulong)vaddr + len);
+                       break;
+               }
+               return virt_to_phys((void *)vaddr);
+       }
+#endif /* CONFIG_SOC_FARADAY && !CONFIG_SYS_DCACHE_OFF */
        return (unsigned long)vaddr;
 }

diff --git a/arch/arm/include/asm/io.h b/arch/arm/include/asm/io.h
index 1fbc531..b55d9e1 100644
--- a/arch/arm/include/asm/io.h
+++ b/arch/arm/include/asm/io.h
@@ -28,6 +28,9 @@
 #if 0  /* XXX###XXX */
 #include <asm/arch/hardware.h>
 #endif /* XXX###XXX */
+#if defined(CONFIG_SOC_FARADAY) && !defined(CONFIG_SYS_DCACHE_OFF)
+#include <common.h>
+#endif

 static inline void sync(void)
 {
@@ -57,9 +60,21 @@ static inline void unmap_physmem(void *vaddr, unsigned long 
flags)

 }

-static inline phys_addr_t virt_to_phys(void * vaddr)
+static inline phys_addr_t virt_to_phys(void *vaddr)
 {
-       return (phys_addr_t)(vaddr);
+#if defined(CONFIG_SOC_FARADAY) && !defined(CONFIG_SYS_DCACHE_OFF)
+       DECLARE_GLOBAL_DATA_PTR;
+       u32 *sect_table = (u32 *)gd->arch.tlb_addr;
+       phys_addr_t phys = (phys_addr_t)vaddr;
+
+       if (!vaddr || !mmu_enabled())
+               return phys;
+
+       phys = sect_table[(u32)vaddr >> 20] & 0xfff00000;
+       return phys + ((phys_addr_t)vaddr & 0x000fffff);
+#else  /* CONFIG_SOC_FARADAY && !CONFIG_SYS_DCACHE_OFF */
+       return (phys_addr_t)vaddr;
+#endif /* CONFIG_SOC_FARADAY && !CONFIG_SYS_DCACHE_OFF */
 }

 /*
--
1.7.9.5

_______________________________________________
U-Boot mailing list
U-Boot@lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot

Reply via email to