Message ID | 1367907913-11859-2-git-send-email-dantesu@gmail.com |
---|---|
State | Changes Requested |
Delegated to: | Albert ARIBAUD |
Headers | show |
Hi Kuo-Jung, On Tue, 7 May 2013 14:25:07 +0800, Kuo-Jung Su <dantesu@gmail.com> wrote: > diff --git a/arch/arm/include/asm/dma-mapping.h b/arch/arm/include/asm/dma-mapping.h > index 5bbb0a0..5a13af5 100644 > --- a/arch/arm/include/asm/dma-mapping.h > +++ b/arch/arm/include/asm/dma-mapping.h > @@ -3,6 +3,9 @@ > * Stelian Pop <stelian@popies.net> > * Lead Tech Design <www.leadtechdesign.com> > * > + * (C) Copyright 2010 > + * Dante Su <dantesu@faraday-tech.com> Fix Copyright notices (dates) throughout the patch (and series as needed). > * See file CREDITS for list of people who contributed to this > * project. > * > @@ -24,22 +27,76 @@ > #ifndef __ASM_ARM_DMA_MAPPING_H > #define __ASM_ARM_DMA_MAPPING_H > > +#if defined(CONFIG_FARADAY) && !defined(CONFIG_SYS_DCACHE_OFF) > +#include <asm/u-boot.h> > +#include <asm/global_data.h> > +#include <asm/io.h> > +#include <malloc.h> > + > +DECLARE_GLOBAL_DATA_PTR; > +#endif /* CONFIG_FARADAY && !CONFIG_SYS_DCACHE_OFF */ > + > enum dma_data_direction { > DMA_BIDIRECTIONAL = 0, > DMA_TO_DEVICE = 1, > DMA_FROM_DEVICE = 2, > }; > > -static void *dma_alloc_coherent(size_t len, unsigned long *handle) > +static inline void *dma_alloc_coherent(size_t len, unsigned long *handle) > { > - *handle = (unsigned long)malloc(len); > +#if defined(CONFIG_FARADAY) && !defined(CONFIG_SYS_DCACHE_OFF) > + void *map, *va = memalign(ARCH_DMA_MINALIGN, len); > + > + if (va && gd->arch.cpu_mmu) { > + invalidate_dcache_range((ulong)va, (ulong)va + len); > + map = map_physmem((phys_addr_t)va, len, MAP_NOCACHE); > + if (!map) > + free(va); > + va = map; > + } > + > + if (handle) > + *handle = virt_to_phys(va); > + > + return va; > +#else /* CONFIG_FARADAY && !CONFIG_SYS_DCACHE_OFF */ > + *handle = (unsigned long)memalign(ARCH_DMA_MINALIGN, len); > return (void *)*handle; This is not identical to what the code was before the patch. Why the difference? > 1.7.9.5 Amicalement,
2013/6/11 Albert ARIBAUD <albert.u.boot@aribaud.net>: > Hi Kuo-Jung, > > On Tue, 7 May 2013 14:25:07 +0800, Kuo-Jung Su <dantesu@gmail.com> > wrote: > >> diff --git a/arch/arm/include/asm/dma-mapping.h b/arch/arm/include/asm/dma-mapping.h >> index 5bbb0a0..5a13af5 100644 >> --- a/arch/arm/include/asm/dma-mapping.h >> +++ b/arch/arm/include/asm/dma-mapping.h >> @@ -3,6 +3,9 @@ >> * Stelian Pop <stelian@popies.net> >> * Lead Tech Design <www.leadtechdesign.com> >> * >> + * (C) Copyright 2010 >> + * Dante Su <dantesu@faraday-tech.com> > > Fix Copyright notices (dates) throughout the patch (and series as > needed). > Got it, thanks. >> * See file CREDITS for list of people who contributed to this >> * project. >> * >> @@ -24,22 +27,76 @@ >> #ifndef __ASM_ARM_DMA_MAPPING_H >> #define __ASM_ARM_DMA_MAPPING_H >> >> +#if defined(CONFIG_FARADAY) && !defined(CONFIG_SYS_DCACHE_OFF) >> +#include <asm/u-boot.h> >> +#include <asm/global_data.h> >> +#include <asm/io.h> >> +#include <malloc.h> >> + >> +DECLARE_GLOBAL_DATA_PTR; >> +#endif /* CONFIG_FARADAY && !CONFIG_SYS_DCACHE_OFF */ >> + >> enum dma_data_direction { >> DMA_BIDIRECTIONAL = 0, >> DMA_TO_DEVICE = 1, >> DMA_FROM_DEVICE = 2, >> }; >> >> -static void *dma_alloc_coherent(size_t len, unsigned long *handle) >> +static inline void *dma_alloc_coherent(size_t len, unsigned long *handle) >> { >> - *handle = (unsigned long)malloc(len); >> +#if defined(CONFIG_FARADAY) && !defined(CONFIG_SYS_DCACHE_OFF) >> + void *map, *va = memalign(ARCH_DMA_MINALIGN, len); >> + >> + if (va && gd->arch.cpu_mmu) { >> + invalidate_dcache_range((ulong)va, (ulong)va + len); >> + map = map_physmem((phys_addr_t)va, len, MAP_NOCACHE); >> + if (!map) >> + free(va); >> + va = map; >> + } >> + >> + if (handle) >> + *handle = virt_to_phys(va); >> + >> + return va; >> +#else /* CONFIG_FARADAY && !CONFIG_SYS_DCACHE_OFF */ >> + *handle = (unsigned long)memalign(ARCH_DMA_MINALIGN, len); >> return (void *)*handle; > > This is not identical to what the code was before the patch. Why the > difference? > Yes, it's not identical to what the code was. It was: *handle = (unsigned long)malloc(len); But I think it should be *handle = (unsigned long)memalign(ARCH_DMA_MINALIGN, len); Because even though the MMU/D-cache is off, some DMA engines still requires strict address alignment. For example, the Faraday FTMAC110 & FTGMAC100 ether-net controllers expect the descriptors are always aligned to 16-bytes boundary. -- Best wishes, Kuo-Jung Su
Hi Kuo-Jung, On Tue, 11 Jun 2013 11:09:57 +0800, Kuo-Jung Su <dantesu@gmail.com> wrote: > 2013/6/11 Albert ARIBAUD <albert.u.boot@aribaud.net>: > > Hi Kuo-Jung, > > > > On Tue, 7 May 2013 14:25:07 +0800, Kuo-Jung Su <dantesu@gmail.com> > > wrote: > > > >> diff --git a/arch/arm/include/asm/dma-mapping.h b/arch/arm/include/asm/dma-mapping.h > >> index 5bbb0a0..5a13af5 100644 > >> --- a/arch/arm/include/asm/dma-mapping.h > >> +++ b/arch/arm/include/asm/dma-mapping.h > >> @@ -3,6 +3,9 @@ > >> * Stelian Pop <stelian@popies.net> > >> * Lead Tech Design <www.leadtechdesign.com> > >> * > >> + * (C) Copyright 2010 > >> + * Dante Su <dantesu@faraday-tech.com> > > > > Fix Copyright notices (dates) throughout the patch (and series as > > needed). > > > > Got it, thanks. > > >> * See file CREDITS for list of people who contributed to this > >> * project. > >> * > >> @@ -24,22 +27,76 @@ > >> #ifndef __ASM_ARM_DMA_MAPPING_H > >> #define __ASM_ARM_DMA_MAPPING_H > >> > >> +#if defined(CONFIG_FARADAY) && !defined(CONFIG_SYS_DCACHE_OFF) > >> +#include <asm/u-boot.h> > >> +#include <asm/global_data.h> > >> +#include <asm/io.h> > >> +#include <malloc.h> > >> + > >> +DECLARE_GLOBAL_DATA_PTR; > >> +#endif /* CONFIG_FARADAY && !CONFIG_SYS_DCACHE_OFF */ > >> + > >> enum dma_data_direction { > >> DMA_BIDIRECTIONAL = 0, > >> DMA_TO_DEVICE = 1, > >> DMA_FROM_DEVICE = 2, > >> }; > >> > >> -static void *dma_alloc_coherent(size_t len, unsigned long *handle) > >> +static inline void *dma_alloc_coherent(size_t len, unsigned long *handle) > >> { > >> - *handle = (unsigned long)malloc(len); > >> +#if defined(CONFIG_FARADAY) && !defined(CONFIG_SYS_DCACHE_OFF) > >> + void *map, *va = memalign(ARCH_DMA_MINALIGN, len); > >> + > >> + if (va && gd->arch.cpu_mmu) { > >> + invalidate_dcache_range((ulong)va, (ulong)va + len); > >> + map = map_physmem((phys_addr_t)va, len, MAP_NOCACHE); > >> + if (!map) > >> + free(va); > >> + va = map; > >> + } > >> + > >> + if (handle) > >> + *handle = virt_to_phys(va); > >> + > >> + return va; > >> +#else /* CONFIG_FARADAY && !CONFIG_SYS_DCACHE_OFF */ > >> + *handle = (unsigned long)memalign(ARCH_DMA_MINALIGN, len); > >> return (void *)*handle; > > > > This is not identical to what the code was before the patch. Why the > > difference? > > > > Yes, it's not identical to what the code was. > > It was: > *handle = (unsigned long)malloc(len); > But I think it should be > *handle = (unsigned long)memalign(ARCH_DMA_MINALIGN, len); > > Because even though the MMU/D-cache is off, some DMA engines still > requires strict address alignment. > > For example, the Faraday FTMAC110 & FTGMAC100 ether-net controllers > expect the descriptors are always aligned to 16-bytes boundary. Unless there exists an actual case where the current form causes an issue, please leave it unchanged. And if it is needed, then please make it a separate patch. > Best wishes, > Kuo-Jung Su Amicalement,
2013/6/11 Albert ARIBAUD <albert.u.boot@aribaud.net>: > Hi Kuo-Jung, > > On Tue, 11 Jun 2013 11:09:57 +0800, Kuo-Jung Su <dantesu@gmail.com> > wrote: > >> 2013/6/11 Albert ARIBAUD <albert.u.boot@aribaud.net>: >> > Hi Kuo-Jung, >> > >> > On Tue, 7 May 2013 14:25:07 +0800, Kuo-Jung Su <dantesu@gmail.com> >> > wrote: >> > >> >> diff --git a/arch/arm/include/asm/dma-mapping.h b/arch/arm/include/asm/dma-mapping.h >> >> index 5bbb0a0..5a13af5 100644 >> >> --- a/arch/arm/include/asm/dma-mapping.h >> >> +++ b/arch/arm/include/asm/dma-mapping.h >> >> @@ -3,6 +3,9 @@ >> >> * Stelian Pop <stelian@popies.net> >> >> * Lead Tech Design <www.leadtechdesign.com> >> >> * >> >> + * (C) Copyright 2010 >> >> + * Dante Su <dantesu@faraday-tech.com> >> > >> > Fix Copyright notices (dates) throughout the patch (and series as >> > needed). >> > >> >> Got it, thanks. >> >> >> * See file CREDITS for list of people who contributed to this >> >> * project. >> >> * >> >> @@ -24,22 +27,76 @@ >> >> #ifndef __ASM_ARM_DMA_MAPPING_H >> >> #define __ASM_ARM_DMA_MAPPING_H >> >> >> >> +#if defined(CONFIG_FARADAY) && !defined(CONFIG_SYS_DCACHE_OFF) >> >> +#include <asm/u-boot.h> >> >> +#include <asm/global_data.h> >> >> +#include <asm/io.h> >> >> +#include <malloc.h> >> >> + >> >> +DECLARE_GLOBAL_DATA_PTR; >> >> +#endif /* CONFIG_FARADAY && !CONFIG_SYS_DCACHE_OFF */ >> >> + >> >> enum dma_data_direction { >> >> DMA_BIDIRECTIONAL = 0, >> >> DMA_TO_DEVICE = 1, >> >> DMA_FROM_DEVICE = 2, >> >> }; >> >> >> >> -static void *dma_alloc_coherent(size_t len, unsigned long *handle) >> >> +static inline void *dma_alloc_coherent(size_t len, unsigned long *handle) >> >> { >> >> - *handle = (unsigned long)malloc(len); >> >> +#if defined(CONFIG_FARADAY) && !defined(CONFIG_SYS_DCACHE_OFF) >> >> + void *map, *va = memalign(ARCH_DMA_MINALIGN, len); >> >> + >> >> + if (va && gd->arch.cpu_mmu) { >> >> + invalidate_dcache_range((ulong)va, (ulong)va + len); >> >> + map = map_physmem((phys_addr_t)va, len, MAP_NOCACHE); >> >> + if (!map) >> >> + free(va); >> >> + va = map; >> >> + } >> >> + >> >> + if (handle) >> >> + *handle = virt_to_phys(va); >> >> + >> >> + return va; >> >> +#else /* CONFIG_FARADAY && !CONFIG_SYS_DCACHE_OFF */ >> >> + *handle = (unsigned long)memalign(ARCH_DMA_MINALIGN, len); >> >> return (void *)*handle; >> > >> > This is not identical to what the code was before the patch. Why the >> > difference? >> > >> >> Yes, it's not identical to what the code was. >> >> It was: >> *handle = (unsigned long)malloc(len); >> But I think it should be >> *handle = (unsigned long)memalign(ARCH_DMA_MINALIGN, len); >> >> Because even though the MMU/D-cache is off, some DMA engines still >> requires strict address alignment. >> >> For example, the Faraday FTMAC110 & FTGMAC100 ether-net controllers >> expect the descriptors are always aligned to 16-bytes boundary. > > Unless there exists an actual case where the current form causes an > issue, please leave it unchanged. And if it is needed, then please make > it a separate patch. > Got it, thanks. I'll make it a separate patch. -- Best wishes, Kuo-Jung Su
diff --git a/arch/arm/include/asm/dma-mapping.h b/arch/arm/include/asm/dma-mapping.h index 5bbb0a0..5a13af5 100644 --- a/arch/arm/include/asm/dma-mapping.h +++ b/arch/arm/include/asm/dma-mapping.h @@ -3,6 +3,9 @@ * Stelian Pop <stelian@popies.net> * Lead Tech Design <www.leadtechdesign.com> * + * (C) Copyright 2010 + * Dante Su <dantesu@faraday-tech.com> + * * See file CREDITS for list of people who contributed to this * project. * @@ -24,22 +27,76 @@ #ifndef __ASM_ARM_DMA_MAPPING_H #define __ASM_ARM_DMA_MAPPING_H +#if defined(CONFIG_FARADAY) && !defined(CONFIG_SYS_DCACHE_OFF) +#include <asm/u-boot.h> +#include <asm/global_data.h> +#include <asm/io.h> +#include <malloc.h> + +DECLARE_GLOBAL_DATA_PTR; +#endif /* CONFIG_FARADAY && !CONFIG_SYS_DCACHE_OFF */ + enum dma_data_direction { DMA_BIDIRECTIONAL = 0, DMA_TO_DEVICE = 1, DMA_FROM_DEVICE = 2, }; -static void *dma_alloc_coherent(size_t len, unsigned long *handle) +static inline void *dma_alloc_coherent(size_t len, unsigned long *handle) { - *handle = (unsigned long)malloc(len); +#if defined(CONFIG_FARADAY) && !defined(CONFIG_SYS_DCACHE_OFF) + void *map, *va = memalign(ARCH_DMA_MINALIGN, len); + + if (va && gd->arch.cpu_mmu) { + invalidate_dcache_range((ulong)va, (ulong)va + len); + map = map_physmem((phys_addr_t)va, len, MAP_NOCACHE); + if (!map) + free(va); + va = map; + } + + if (handle) + *handle = virt_to_phys(va); + + return va; +#else /* CONFIG_FARADAY && !CONFIG_SYS_DCACHE_OFF */ + *handle = (unsigned long)memalign(ARCH_DMA_MINALIGN, len); return (void *)*handle; +#endif /* CONFIG_FARADAY && !CONFIG_SYS_DCACHE_OFF */ +} + +static inline void dma_free_coherent(void *vaddr, ulong len) +{ +#if defined(CONFIG_FARADAY) && !defined(CONFIG_SYS_DCACHE_OFF) + void *tmp = (void *)virt_to_phys(vaddr); + unmap_physmem(vaddr, len); + vaddr = tmp; +#endif + free(vaddr); } static inline unsigned long dma_map_single(volatile void *vaddr, size_t len, enum dma_data_direction dir) { +#if defined(CONFIG_FARADAY) && !defined(CONFIG_SYS_DCACHE_OFF) + if (gd->arch.cpu_mmu) { + 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); +#else /* CONFIG_FARADAY && !CONFIG_SYS_DCACHE_OFF */ return (unsigned long)vaddr; +#endif /* CONFIG_FARADAY && !CONFIG_SYS_DCACHE_OFF */ } static inline void dma_unmap_single(volatile void *vaddr, size_t len, diff --git a/arch/arm/include/asm/global_data.h b/arch/arm/include/asm/global_data.h index 37ac0da..bd18ff7 100644 --- a/arch/arm/include/asm/global_data.h +++ b/arch/arm/include/asm/global_data.h @@ -38,6 +38,10 @@ struct arch_global_data { unsigned long pllb_rate_hz; unsigned long at91_pllb_usb_init; #endif +#ifdef CONFIG_FARADAY + unsigned long cpu_id; + unsigned long cpu_mmu; /* has mmu */ +#endif /* "static data" needed by most of timer.c on ARM platforms */ unsigned long timer_rate_hz; unsigned long tbu; diff --git a/arch/arm/include/asm/io.h b/arch/arm/include/asm/io.h index 1fbc531..37c737e 100644 --- a/arch/arm/include/asm/io.h +++ b/arch/arm/include/asm/io.h @@ -2,6 +2,7 @@ * linux/include/asm-arm/io.h * * Copyright (C) 1996-2000 Russell King + * Copyright (C) 2009-2010 Dante Su <dantesu@faraday-tech.com> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -28,9 +29,36 @@ #if 0 /* XXX###XXX */ #include <asm/arch/hardware.h> #endif /* XXX###XXX */ +#if defined(CONFIG_FARADAY) && !defined(CONFIG_SYS_DCACHE_OFF) +#include <asm/system.h> +#include <asm/u-boot.h> +#include <asm/global_data.h> + +#ifndef CONFIG_MMAP_START +#define CONFIG_MMAP_START 0xd0000000 +#endif + +#ifndef CONFIG_MMAP_END +#define CONFIG_MMAP_END 0xfff00000 +#endif + +DECLARE_GLOBAL_DATA_PTR; + +#endif /* CONFIG_FARADAY && !CONFIG_SYS_DCACHE_OFF */ + +/* arch/$(ARCH)/lib/cache.c */ +void invalidate_icache_all(void); +void flush_dcache_all(void); +void flush_dcache_range(ulong start, ulong stop); static inline void sync(void) { +#ifndef CONFIG_SYS_DCACHE_OFF + flush_dcache_all(); +#endif +#ifndef CONFIG_SYS_ICACHE_OFF + invalidate_icache_all(); +#endif } /* @@ -39,27 +67,143 @@ static inline void sync(void) * properties specified by "flags". */ #define MAP_NOCACHE (0) -#define MAP_WRCOMBINE (0) -#define MAP_WRBACK (0) -#define MAP_WRTHROUGH (0) +#define MAP_WRCOMBINE (1) +#define MAP_WRBACK (2) +#define MAP_WRTHROUGH (3) + +#if defined(CONFIG_FARADAY) && !defined(CONFIG_SYS_DCACHE_OFF) +static inline void map_flush(ulong start, ulong end) +{ + flush_dcache_range(start, end); + + /* invalidate D-TLB */ + start &= 0xfff00000; + end = (end + 0x000fffff) & 0xfff00000; + __asm__ __volatile__ ( + "mov r3, %0\n" + "1:\n" + "mcr p15, 0, r3, c8, c6, 1\n" + "add r3, r3, #4096\n" + "cmp r3, %1\n" + "blo 1b\n" + : /* output */ + : "r"(start), "r"(end) /* input */ + : "r3" /* clobber list */ + ); +} +#endif /* CONFIG_FARADAY && !CONFIG_SYS_DCACHE_OFF */ static inline void * -map_physmem(phys_addr_t paddr, unsigned long len, unsigned long flags) +map_physmem(phys_addr_t paddr, ulong len, ulong flags) { +#if defined(CONFIG_FARADAY) && !defined(CONFIG_SYS_DCACHE_OFF) + u32 *page_table = (u32 *)gd->arch.tlb_addr; + u32 vaddr, nattr, oattr, addr, size, end; + + /* 1. check if we have to create a mapping for it */ + vaddr = paddr; + addr = page_table[vaddr >> 20] & 0xfff00000; + oattr = page_table[vaddr >> 20] & 0x1f; + switch (flags) { + case MAP_WRCOMBINE: + nattr = DCACHE_WRITECOMBINE; + break; + case MAP_WRTHROUGH: + nattr = DCACHE_WRITETHROUGH; + break; + case MAP_WRBACK: + nattr = DCACHE_WRITEBACK; + break; + default: + nattr = DCACHE_OFF; + break; + } + if ((nattr == oattr) && (vaddr == addr)) + return (void *)paddr; + + /* 2. find a contiguous region for it */ + end = (paddr + len + 0x000fffff) & 0xfff00000; + len = end - (paddr & 0xfff00000); + size = 0; + addr = CONFIG_MMAP_START; + vaddr = addr; + while (addr < CONFIG_MMAP_END) { + /* if va == pa, then it's free to use */ + if (addr == (page_table[addr >> 20] & 0xfff00000)) { + size += SZ_1M; + } else { + size = 0; + vaddr = addr + SZ_1M; + } + if (size >= len) + break; + addr += SZ_1M; + } + if (size < len) + return NULL; + + /* 3. create the map */ + map_flush(vaddr, vaddr + size); + addr = vaddr; + vaddr += paddr & 0x000fffff; + paddr &= 0xfff00000; + while (size) { + page_table[addr >> 20] = paddr | (3 << 10) | nattr; + size -= SZ_1M; + addr += SZ_1M; + paddr += SZ_1M; + } + return (void *)vaddr; +#else /* CONFIG_FARADAY && !CONFIG_SYS_DCACHE_OFF */ return (void *)paddr; +#endif /* CONFIG_FARADAY && !CONFIG_SYS_DCACHE_OFF */ } /* * Take down a mapping set up by map_physmem(). */ -static inline void unmap_physmem(void *vaddr, unsigned long flags) +static inline void unmap_physmem(void *vaddr, ulong len) { - +#if defined(CONFIG_FARADAY) && !defined(CONFIG_SYS_DCACHE_OFF) + u32 *page_table = (u32 *)gd->arch.tlb_addr; + u32 addr, end; + + /* 1. skip on NULL pointer */ + if (!vaddr) + return; + + /* 2. check if it's the right address map */ + addr = (u32)vaddr; + if ((page_table[addr >> 20] & 0xfff00000) == addr) + return; + + /* 3. reset the map */ + end = (addr + len + 0x000fffff) & 0xfff00000; + addr &= 0xfff00000; + map_flush(addr, end); + while (addr < end) { + page_table[addr >> 20] = addr | (3 << 10) | DCACHE_OFF; + addr += SZ_1M; + } +#endif /* CONFIG_FARADAY && !CONFIG_SYS_DCACHE_OFF */ } -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_FARADAY) && !defined(CONFIG_SYS_DCACHE_OFF) + u32 *page_table = (u32 *)gd->arch.tlb_addr; + phys_addr_t phys = (phys_addr_t)vaddr; + + if (!gd->arch.cpu_mmu || !vaddr) + return phys; + + phys = page_table[(u32)vaddr >> 20] & 0xfff00000; + phys += (u32)vaddr & 0x000fffff; + + return phys; +#else /* CONFIG_FARADAY && !CONFIG_SYS_DCACHE_OFF */ + return (phys_addr_t)vaddr; +#endif /* CONFIG_FARADAY && !CONFIG_SYS_DCACHE_OFF */ } /* diff --git a/arch/arm/include/asm/system.h b/arch/arm/include/asm/system.h index 760345f..050b707 100644 --- a/arch/arm/include/asm/system.h +++ b/arch/arm/include/asm/system.h @@ -97,9 +97,10 @@ static inline void set_dacr(unsigned int val) /* options available for data cache on each page */ enum dcache_option { - DCACHE_OFF = 0x12, - DCACHE_WRITETHROUGH = 0x1a, - DCACHE_WRITEBACK = 0x1e, + DCACHE_OFF = 0x12, /* non-cached + non-buffered */ + DCACHE_WRITECOMBINE = 0x16, /* non-cached + buffered */ + DCACHE_WRITETHROUGH = 0x1a, /* cached + non-buffered */ + DCACHE_WRITEBACK = 0x1e, /* cached + buffered */ }; /* Size of an MMU section */ diff --git a/arch/arm/lib/cache-cp15.c b/arch/arm/lib/cache-cp15.c index 4abe1cf..ea29e83 100644 --- a/arch/arm/lib/cache-cp15.c +++ b/arch/arm/lib/cache-cp15.c @@ -1,6 +1,8 @@ /* * (C) Copyright 2002 * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * (C) Copyright 2010 + * Dante Su <dantesu@faraday-tech.com> * * See file CREDITS for list of people who contributed to this * project. @@ -98,6 +100,24 @@ __weak void dram_bank_mmu_setup(int bank) set_section_dcache(i, DCACHE_WRITEBACK); #endif } + +#if defined(CONFIG_FARADAY) && !defined(CONFIG_SYS_DCACHE_OFF) + +# ifdef CONFIG_USE_IRQ + /* make sure the exception table is at 0x00000000 */ + if (!bank && bd->bi_dram[bank].start) { + u32 pa = bd->bi_dram[bank].start; + u32 *page_table = (u32 *)gd->arch.tlb_addr; + +# ifdef CONFIG_SYS_ARM_CACHE_WRITETHROUGH + page_table[0] = pa | (3 << 10) | DCACHE_WRITETHROUGH; +# else + page_table[0] = pa | (3 << 10) | DCACHE_WRITEBACK; +# endif + } +# endif /* # ifdef CONFIG_USE_IRQ */ + +#endif /* CONFIG_FARADAY && !CONFIG_SYS_DCACHE_OFF */ } /* to activate the MMU we need to set up virtual memory: use 1M areas */ @@ -126,6 +146,10 @@ static inline void mmu_setup(void) /* and enable the mmu */ reg = get_cr(); /* get control reg. */ +#ifdef CONFIG_FARADAY + reg |= CR_W; /* enable write buffer */ + reg |= CR_Z; /* enable branch prediction */ +#endif cp_delay(); set_cr(reg | CR_M); } @@ -140,9 +164,15 @@ static void cache_enable(uint32_t cache_bit) { uint32_t reg; +#ifdef CONFIG_FARADAY + if (!gd->arch.cpu_mmu && (cache_bit == CR_C)) + return; +#endif + /* The data cache is not active unless the mmu is enabled too */ if ((cache_bit == CR_C) && !mmu_enabled()) mmu_setup(); + reg = get_cr(); /* get control reg. */ cp_delay(); set_cr(reg | cache_bit); diff --git a/drivers/mtd/cfi_flash.c b/drivers/mtd/cfi_flash.c index 22d8440..49bdcff 100644 --- a/drivers/mtd/cfi_flash.c +++ b/drivers/mtd/cfi_flash.c @@ -1818,7 +1818,7 @@ static int flash_detect_legacy(phys_addr_t base, int banknum) break; else unmap_physmem((void *)info->start[0], - MAP_NOCACHE); + info->portwidth); } }