18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * Copyright (C) 2007-2009 Michal Simek <monstr@monstr.eu>
48c2ecf20Sopenharmony_ci * Copyright (C) 2007-2009 PetaLogix
58c2ecf20Sopenharmony_ci * Copyright (C) 2007 John Williams <john.williams@petalogix.com>
68c2ecf20Sopenharmony_ci * based on v850 version which was
78c2ecf20Sopenharmony_ci * Copyright (C) 2001,02,03 NEC Electronics Corporation
88c2ecf20Sopenharmony_ci * Copyright (C) 2001,02,03 Miles Bader <miles@gnu.org>
98c2ecf20Sopenharmony_ci */
108c2ecf20Sopenharmony_ci
118c2ecf20Sopenharmony_ci#ifndef _ASM_MICROBLAZE_CACHEFLUSH_H
128c2ecf20Sopenharmony_ci#define _ASM_MICROBLAZE_CACHEFLUSH_H
138c2ecf20Sopenharmony_ci
148c2ecf20Sopenharmony_ci/* Somebody depends on this; sigh... */
158c2ecf20Sopenharmony_ci#include <linux/mm.h>
168c2ecf20Sopenharmony_ci#include <linux/io.h>
178c2ecf20Sopenharmony_ci
188c2ecf20Sopenharmony_ci/* Look at Documentation/core-api/cachetlb.rst */
198c2ecf20Sopenharmony_ci
208c2ecf20Sopenharmony_ci/*
218c2ecf20Sopenharmony_ci * Cache handling functions.
228c2ecf20Sopenharmony_ci * Microblaze has a write-through data cache, meaning that the data cache
238c2ecf20Sopenharmony_ci * never needs to be flushed.  The only flushing operations that are
248c2ecf20Sopenharmony_ci * implemented are to invalidate the instruction cache.  These are called
258c2ecf20Sopenharmony_ci * after loading a user application into memory, we must invalidate the
268c2ecf20Sopenharmony_ci * instruction cache to make sure we don't fetch old, bad code.
278c2ecf20Sopenharmony_ci */
288c2ecf20Sopenharmony_ci
298c2ecf20Sopenharmony_ci/* struct cache, d=dcache, i=icache, fl = flush, iv = invalidate,
308c2ecf20Sopenharmony_ci * suffix r = range */
318c2ecf20Sopenharmony_cistruct scache {
328c2ecf20Sopenharmony_ci	/* icache */
338c2ecf20Sopenharmony_ci	void (*ie)(void); /* enable */
348c2ecf20Sopenharmony_ci	void (*id)(void); /* disable */
358c2ecf20Sopenharmony_ci	void (*ifl)(void); /* flush */
368c2ecf20Sopenharmony_ci	void (*iflr)(unsigned long a, unsigned long b);
378c2ecf20Sopenharmony_ci	void (*iin)(void); /* invalidate */
388c2ecf20Sopenharmony_ci	void (*iinr)(unsigned long a, unsigned long b);
398c2ecf20Sopenharmony_ci	/* dcache */
408c2ecf20Sopenharmony_ci	void (*de)(void); /* enable */
418c2ecf20Sopenharmony_ci	void (*dd)(void); /* disable */
428c2ecf20Sopenharmony_ci	void (*dfl)(void); /* flush */
438c2ecf20Sopenharmony_ci	void (*dflr)(unsigned long a, unsigned long b);
448c2ecf20Sopenharmony_ci	void (*din)(void); /* invalidate */
458c2ecf20Sopenharmony_ci	void (*dinr)(unsigned long a, unsigned long b);
468c2ecf20Sopenharmony_ci};
478c2ecf20Sopenharmony_ci
488c2ecf20Sopenharmony_ci/* microblaze cache */
498c2ecf20Sopenharmony_ciextern struct scache *mbc;
508c2ecf20Sopenharmony_ci
518c2ecf20Sopenharmony_civoid microblaze_cache_init(void);
528c2ecf20Sopenharmony_ci
538c2ecf20Sopenharmony_ci#define enable_icache()					mbc->ie();
548c2ecf20Sopenharmony_ci#define disable_icache()				mbc->id();
558c2ecf20Sopenharmony_ci#define flush_icache()					mbc->ifl();
568c2ecf20Sopenharmony_ci#define flush_icache_range(start, end)			mbc->iflr(start, end);
578c2ecf20Sopenharmony_ci#define invalidate_icache()				mbc->iin();
588c2ecf20Sopenharmony_ci#define invalidate_icache_range(start, end)		mbc->iinr(start, end);
598c2ecf20Sopenharmony_ci
608c2ecf20Sopenharmony_ci#define enable_dcache()					mbc->de();
618c2ecf20Sopenharmony_ci#define disable_dcache()				mbc->dd();
628c2ecf20Sopenharmony_ci/* FIXME for LL-temac driver */
638c2ecf20Sopenharmony_ci#define invalidate_dcache()				mbc->din();
648c2ecf20Sopenharmony_ci#define invalidate_dcache_range(start, end)		mbc->dinr(start, end);
658c2ecf20Sopenharmony_ci#define flush_dcache()					mbc->dfl();
668c2ecf20Sopenharmony_ci#define flush_dcache_range(start, end)			mbc->dflr(start, end);
678c2ecf20Sopenharmony_ci
688c2ecf20Sopenharmony_ci#define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE 1
698c2ecf20Sopenharmony_ci/* MS: We have to implement it because of rootfs-jffs2 issue on WB */
708c2ecf20Sopenharmony_ci#define flush_dcache_page(page) \
718c2ecf20Sopenharmony_cido { \
728c2ecf20Sopenharmony_ci	unsigned long addr = (unsigned long) page_address(page); /* virtual */ \
738c2ecf20Sopenharmony_ci	addr = (u32)virt_to_phys((void *)addr); \
748c2ecf20Sopenharmony_ci	flush_dcache_range((unsigned) (addr), (unsigned) (addr) + PAGE_SIZE); \
758c2ecf20Sopenharmony_ci} while (0);
768c2ecf20Sopenharmony_ci
778c2ecf20Sopenharmony_ci#define flush_cache_page(vma, vmaddr, pfn) \
788c2ecf20Sopenharmony_ci	flush_dcache_range(pfn << PAGE_SHIFT, (pfn << PAGE_SHIFT) + PAGE_SIZE);
798c2ecf20Sopenharmony_ci
808c2ecf20Sopenharmony_cistatic inline void copy_to_user_page(struct vm_area_struct *vma,
818c2ecf20Sopenharmony_ci				     struct page *page, unsigned long vaddr,
828c2ecf20Sopenharmony_ci				     void *dst, void *src, int len)
838c2ecf20Sopenharmony_ci{
848c2ecf20Sopenharmony_ci	u32 addr = virt_to_phys(dst);
858c2ecf20Sopenharmony_ci	memcpy(dst, src, len);
868c2ecf20Sopenharmony_ci	if (vma->vm_flags & VM_EXEC) {
878c2ecf20Sopenharmony_ci		invalidate_icache_range(addr, addr + PAGE_SIZE);
888c2ecf20Sopenharmony_ci		flush_dcache_range(addr, addr + PAGE_SIZE);
898c2ecf20Sopenharmony_ci	}
908c2ecf20Sopenharmony_ci}
918c2ecf20Sopenharmony_ci#define copy_to_user_page copy_to_user_page
928c2ecf20Sopenharmony_ci
938c2ecf20Sopenharmony_ci#include <asm-generic/cacheflush.h>
948c2ecf20Sopenharmony_ci
958c2ecf20Sopenharmony_ci#endif /* _ASM_MICROBLAZE_CACHEFLUSH_H */
96