diff options
Diffstat (limited to 'arch/microblaze/include/asm/cacheflush.h')
| -rw-r--r-- | arch/microblaze/include/asm/cacheflush.h | 133 |
1 files changed, 86 insertions, 47 deletions
diff --git a/arch/microblaze/include/asm/cacheflush.h b/arch/microblaze/include/asm/cacheflush.h index 3300b785049..ffea82a16d2 100644 --- a/arch/microblaze/include/asm/cacheflush.h +++ b/arch/microblaze/include/asm/cacheflush.h @@ -1,5 +1,6 @@ /* - * Copyright (C) 2007 PetaLogix + * Copyright (C) 2007-2009 Michal Simek <monstr@monstr.eu> + * Copyright (C) 2007-2009 PetaLogix * Copyright (C) 2007 John Williams <john.williams@petalogix.com> * based on v850 version which was * Copyright (C) 2001,02,03 NEC Electronics Corporation @@ -16,6 +17,9 @@ /* Somebody depends on this; sigh... */ #include <linux/mm.h> +#include <linux/io.h> + +/* Look at Documentation/cachetlb.txt */ /* * Cache handling functions. @@ -26,60 +30,95 @@ * instruction cache to make sure we don't fetch old, bad code. */ +/* struct cache, d=dcache, i=icache, fl = flush, iv = invalidate, + * suffix r = range */ +struct scache { + /* icache */ + void (*ie)(void); /* enable */ + void (*id)(void); /* disable */ + void (*ifl)(void); /* flush */ + void (*iflr)(unsigned long a, unsigned long b); + void (*iin)(void); /* invalidate */ + void (*iinr)(unsigned long a, unsigned long b); + /* dcache */ + void (*de)(void); /* enable */ + void (*dd)(void); /* disable */ + void (*dfl)(void); /* flush */ + void (*dflr)(unsigned long a, unsigned long b); + void (*din)(void); /* invalidate */ + void (*dinr)(unsigned long a, unsigned long b); +}; + +/* microblaze cache */ +extern struct scache *mbc; + +void microblaze_cache_init(void); + +#define enable_icache() mbc->ie(); +#define disable_icache() mbc->id(); +#define flush_icache() mbc->ifl(); +#define flush_icache_range(start, end) mbc->iflr(start, end); +#define invalidate_icache() mbc->iin(); +#define invalidate_icache_range(start, end) mbc->iinr(start, end); + +#define flush_icache_user_range(vma, pg, adr, len) flush_icache(); +#define flush_icache_page(vma, pg) do { } while (0) + +#define enable_dcache() mbc->de(); +#define disable_dcache() mbc->dd(); /* FIXME for LL-temac driver */ -#define invalidate_dcache_range(start, end) \ - __invalidate_dcache_range(start, end) +#define invalidate_dcache() mbc->din(); +#define invalidate_dcache_range(start, end) mbc->dinr(start, end); +#define flush_dcache() mbc->dfl(); +#define flush_dcache_range(start, end) mbc->dflr(start, end); -#define flush_cache_all() __invalidate_cache_all() -#define flush_cache_mm(mm) do { } while (0) -#define flush_cache_range(vma, start, end) __invalidate_cache_all() -#define flush_cache_page(vma, vmaddr, pfn) do { } while (0) +#define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE 1 +/* MS: We have to implement it because of rootfs-jffs2 issue on WB */ +#define flush_dcache_page(page) \ +do { \ + unsigned long addr = (unsigned long) page_address(page); /* virtual */ \ + addr = (u32)virt_to_phys((void *)addr); \ + flush_dcache_range((unsigned) (addr), (unsigned) (addr) + PAGE_SIZE); \ +} while (0); -#define flush_dcache_range(start, end) __invalidate_dcache_range(start, end) -#define flush_dcache_page(page) do { } while (0) #define flush_dcache_mmap_lock(mapping) do { } while (0) #define flush_dcache_mmap_unlock(mapping) do { } while (0) -#define flush_icache_range(start, len) __invalidate_icache_range(start, len) -#define flush_icache_page(vma, pg) do { } while (0) - -#define flush_cache_vmap(start, end) do { } while (0) -#define flush_cache_vunmap(start, end) do { } while (0) - -struct page; -struct mm_struct; -struct vm_area_struct; - -/* see arch/microblaze/kernel/cache.c */ -extern void __invalidate_icache_all(void); -extern void __invalidate_icache_range(unsigned long start, unsigned long end); -extern void __invalidate_icache_page(struct vm_area_struct *vma, - struct page *page); -extern void __invalidate_icache_user_range(struct vm_area_struct *vma, - struct page *page, - unsigned long adr, int len); -extern void __invalidate_cache_sigtramp(unsigned long addr); - -extern void __invalidate_dcache_all(void); -extern void __invalidate_dcache_range(unsigned long start, unsigned long end); -extern void __invalidate_dcache_page(struct vm_area_struct *vma, - struct page *page); -extern void __invalidate_dcache_user_range(struct vm_area_struct *vma, - struct page *page, - unsigned long adr, int len); - -extern inline void __invalidate_cache_all(void) -{ - __invalidate_icache_all(); - __invalidate_dcache_all(); +#define flush_cache_dup_mm(mm) do { } while (0) +#define flush_cache_vmap(start, end) do { } while (0) +#define flush_cache_vunmap(start, end) do { } while (0) +#define flush_cache_mm(mm) do { } while (0) + +#define flush_cache_page(vma, vmaddr, pfn) \ + flush_dcache_range(pfn << PAGE_SHIFT, (pfn << PAGE_SHIFT) + PAGE_SIZE); + +/* MS: kgdb code use this macro, wrong len with FLASH */ +#if 0 +#define flush_cache_range(vma, start, len) { \ + flush_icache_range((unsigned) (start), (unsigned) (start) + (len)); \ + flush_dcache_range((unsigned) (start), (unsigned) (start) + (len)); \ } +#endif + +#define flush_cache_range(vma, start, len) do { } while (0) -#define copy_to_user_page(vma, page, vaddr, dst, src, len) \ -do { memcpy((dst), (src), (len)); \ - flush_icache_range((unsigned) (dst), (unsigned) (dst) + (len)); \ -} while (0) +static inline void copy_to_user_page(struct vm_area_struct *vma, + struct page *page, unsigned long vaddr, + void *dst, void *src, int len) +{ + u32 addr = virt_to_phys(dst); + memcpy(dst, src, len); + if (vma->vm_flags & VM_EXEC) { + invalidate_icache_range(addr, addr + PAGE_SIZE); + flush_dcache_range(addr, addr + PAGE_SIZE); + } +} -#define copy_from_user_page(vma, page, vaddr, dst, src, len) \ - memcpy((dst), (src), (len)) +static inline void copy_from_user_page(struct vm_area_struct *vma, + struct page *page, unsigned long vaddr, + void *dst, void *src, int len) +{ + memcpy(dst, src, len); +} #endif /* _ASM_MICROBLAZE_CACHEFLUSH_H */ |
