11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
2f26b2a562b46ab186c8383993ab1332673ac4a47Paul Mundt * arch/sh/mm/cache.c
31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (C) 1999, 2000, 2002  Niibe Yutaka
5a6198a238baceae9d4e0ce3915f6d239c89b5c08Paul Mundt * Copyright (C) 2002 - 2010  Paul Mundt
61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Released under the terms of the GNU GPL v2.0.
81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/mm.h>
10acca4f4d9bd657e8bc7e1665ba5077465138f133Paul Mundt#include <linux/init.h>
1152e27782e1c4afa1feca0fdf194d279595e0431cPaul Mundt#include <linux/mutex.h>
12e06c4e5775b1efc4e476f2430439e45867775f5fPaul Mundt#include <linux/fs.h>
13f26b2a562b46ab186c8383993ab1332673ac4a47Paul Mundt#include <linux/smp.h>
147747b9a493a197cb4db44c98d25ce6d3d9f586d1Paul Mundt#include <linux/highmem.h>
157747b9a493a197cb4db44c98d25ce6d3d9f586d1Paul Mundt#include <linux/module.h>
161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/mmu_context.h>
171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/cacheflush.h>
181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
19f26b2a562b46ab186c8383993ab1332673ac4a47Paul Mundtvoid (*local_flush_cache_all)(void *args) = cache_noop;
20f26b2a562b46ab186c8383993ab1332673ac4a47Paul Mundtvoid (*local_flush_cache_mm)(void *args) = cache_noop;
21f26b2a562b46ab186c8383993ab1332673ac4a47Paul Mundtvoid (*local_flush_cache_dup_mm)(void *args) = cache_noop;
22f26b2a562b46ab186c8383993ab1332673ac4a47Paul Mundtvoid (*local_flush_cache_page)(void *args) = cache_noop;
23f26b2a562b46ab186c8383993ab1332673ac4a47Paul Mundtvoid (*local_flush_cache_range)(void *args) = cache_noop;
24f26b2a562b46ab186c8383993ab1332673ac4a47Paul Mundtvoid (*local_flush_dcache_page)(void *args) = cache_noop;
25f26b2a562b46ab186c8383993ab1332673ac4a47Paul Mundtvoid (*local_flush_icache_range)(void *args) = cache_noop;
26f26b2a562b46ab186c8383993ab1332673ac4a47Paul Mundtvoid (*local_flush_icache_page)(void *args) = cache_noop;
27f26b2a562b46ab186c8383993ab1332673ac4a47Paul Mundtvoid (*local_flush_cache_sigtramp)(void *args) = cache_noop;
28f26b2a562b46ab186c8383993ab1332673ac4a47Paul Mundt
2937443ef3f0406e855e169c87ae3f4ffb4b6ff635Paul Mundtvoid (*__flush_wback_region)(void *start, int size);
300a993b0a290a2672500000b0ce811efc093f8467Paul MundtEXPORT_SYMBOL(__flush_wback_region);
3137443ef3f0406e855e169c87ae3f4ffb4b6ff635Paul Mundtvoid (*__flush_purge_region)(void *start, int size);
320a993b0a290a2672500000b0ce811efc093f8467Paul MundtEXPORT_SYMBOL(__flush_purge_region);
3337443ef3f0406e855e169c87ae3f4ffb4b6ff635Paul Mundtvoid (*__flush_invalidate_region)(void *start, int size);
340a993b0a290a2672500000b0ce811efc093f8467Paul MundtEXPORT_SYMBOL(__flush_invalidate_region);
3537443ef3f0406e855e169c87ae3f4ffb4b6ff635Paul Mundt
3637443ef3f0406e855e169c87ae3f4ffb4b6ff635Paul Mundtstatic inline void noop__flush_region(void *start, int size)
3737443ef3f0406e855e169c87ae3f4ffb4b6ff635Paul Mundt{
3837443ef3f0406e855e169c87ae3f4ffb4b6ff635Paul Mundt}
3937443ef3f0406e855e169c87ae3f4ffb4b6ff635Paul Mundt
406f3795788b030c3c190fa063adfe519e016cc6fdPaul Mundtstatic inline void cacheop_on_each_cpu(void (*func) (void *info), void *info,
416f3795788b030c3c190fa063adfe519e016cc6fdPaul Mundt                                   int wait)
426f3795788b030c3c190fa063adfe519e016cc6fdPaul Mundt{
436f3795788b030c3c190fa063adfe519e016cc6fdPaul Mundt	preempt_disable();
44a6198a238baceae9d4e0ce3915f6d239c89b5c08Paul Mundt
45a6198a238baceae9d4e0ce3915f6d239c89b5c08Paul Mundt	/*
46a6198a238baceae9d4e0ce3915f6d239c89b5c08Paul Mundt	 * It's possible that this gets called early on when IRQs are
47a6198a238baceae9d4e0ce3915f6d239c89b5c08Paul Mundt	 * still disabled due to ioremapping by the boot CPU, so don't
48a6198a238baceae9d4e0ce3915f6d239c89b5c08Paul Mundt	 * even attempt IPIs unless there are other CPUs online.
49a6198a238baceae9d4e0ce3915f6d239c89b5c08Paul Mundt	 */
50a6198a238baceae9d4e0ce3915f6d239c89b5c08Paul Mundt	if (num_online_cpus() > 1)
51a6198a238baceae9d4e0ce3915f6d239c89b5c08Paul Mundt		smp_call_function(func, info, wait);
52a6198a238baceae9d4e0ce3915f6d239c89b5c08Paul Mundt
536f3795788b030c3c190fa063adfe519e016cc6fdPaul Mundt	func(info);
54a6198a238baceae9d4e0ce3915f6d239c89b5c08Paul Mundt
556f3795788b030c3c190fa063adfe519e016cc6fdPaul Mundt	preempt_enable();
566f3795788b030c3c190fa063adfe519e016cc6fdPaul Mundt}
576f3795788b030c3c190fa063adfe519e016cc6fdPaul Mundt
58ba1789efea81acc6633f427bfeb871fd608965b5Paul Mundtvoid copy_to_user_page(struct vm_area_struct *vma, struct page *page,
59ba1789efea81acc6633f427bfeb871fd608965b5Paul Mundt		       unsigned long vaddr, void *dst, const void *src,
60ba1789efea81acc6633f427bfeb871fd608965b5Paul Mundt		       unsigned long len)
611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
620dfae7d5a21901b28ec0452d71be64adf5ea323ePaul Mundt	if (boot_cpu_data.dcache.n_aliases && page_mapped(page) &&
6355661fc1f105ed75852e937bf8ea408270eb0ccaPaul Mundt	    test_bit(PG_dcache_clean, &page->flags)) {
642277ab4a1df50e05bc732fe9488d4e902bb8399aPaul Mundt		void *vto = kmap_coherent(page, vaddr) + (vaddr & ~PAGE_MASK);
652277ab4a1df50e05bc732fe9488d4e902bb8399aPaul Mundt		memcpy(vto, src, len);
660906a3ad33a254094fb74828e3ddb9af8771a6daPaul Mundt		kunmap_coherent(vto);
672277ab4a1df50e05bc732fe9488d4e902bb8399aPaul Mundt	} else {
682277ab4a1df50e05bc732fe9488d4e902bb8399aPaul Mundt		memcpy(dst, src, len);
690dfae7d5a21901b28ec0452d71be64adf5ea323ePaul Mundt		if (boot_cpu_data.dcache.n_aliases)
7055661fc1f105ed75852e937bf8ea408270eb0ccaPaul Mundt			clear_bit(PG_dcache_clean, &page->flags);
712277ab4a1df50e05bc732fe9488d4e902bb8399aPaul Mundt	}
72ba1789efea81acc6633f427bfeb871fd608965b5Paul Mundt
73ba1789efea81acc6633f427bfeb871fd608965b5Paul Mundt	if (vma->vm_flags & VM_EXEC)
74ba1789efea81acc6633f427bfeb871fd608965b5Paul Mundt		flush_cache_page(vma, vaddr, page_to_pfn(page));
75ba1789efea81acc6633f427bfeb871fd608965b5Paul Mundt}
76ba1789efea81acc6633f427bfeb871fd608965b5Paul Mundt
77ba1789efea81acc6633f427bfeb871fd608965b5Paul Mundtvoid copy_from_user_page(struct vm_area_struct *vma, struct page *page,
78ba1789efea81acc6633f427bfeb871fd608965b5Paul Mundt			 unsigned long vaddr, void *dst, const void *src,
79ba1789efea81acc6633f427bfeb871fd608965b5Paul Mundt			 unsigned long len)
80ba1789efea81acc6633f427bfeb871fd608965b5Paul Mundt{
810dfae7d5a21901b28ec0452d71be64adf5ea323ePaul Mundt	if (boot_cpu_data.dcache.n_aliases && page_mapped(page) &&
8255661fc1f105ed75852e937bf8ea408270eb0ccaPaul Mundt	    test_bit(PG_dcache_clean, &page->flags)) {
832277ab4a1df50e05bc732fe9488d4e902bb8399aPaul Mundt		void *vfrom = kmap_coherent(page, vaddr) + (vaddr & ~PAGE_MASK);
842277ab4a1df50e05bc732fe9488d4e902bb8399aPaul Mundt		memcpy(dst, vfrom, len);
850906a3ad33a254094fb74828e3ddb9af8771a6daPaul Mundt		kunmap_coherent(vfrom);
862277ab4a1df50e05bc732fe9488d4e902bb8399aPaul Mundt	} else {
872277ab4a1df50e05bc732fe9488d4e902bb8399aPaul Mundt		memcpy(dst, src, len);
880dfae7d5a21901b28ec0452d71be64adf5ea323ePaul Mundt		if (boot_cpu_data.dcache.n_aliases)
8955661fc1f105ed75852e937bf8ea408270eb0ccaPaul Mundt			clear_bit(PG_dcache_clean, &page->flags);
902277ab4a1df50e05bc732fe9488d4e902bb8399aPaul Mundt	}
911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
9239e688a94b94eaba768b1494e19e96f828fc2688Paul Mundt
937747b9a493a197cb4db44c98d25ce6d3d9f586d1Paul Mundtvoid copy_user_highpage(struct page *to, struct page *from,
947747b9a493a197cb4db44c98d25ce6d3d9f586d1Paul Mundt			unsigned long vaddr, struct vm_area_struct *vma)
957747b9a493a197cb4db44c98d25ce6d3d9f586d1Paul Mundt{
967747b9a493a197cb4db44c98d25ce6d3d9f586d1Paul Mundt	void *vfrom, *vto;
977747b9a493a197cb4db44c98d25ce6d3d9f586d1Paul Mundt
98bc3e11be88010e09692ed1d214407d56caa90075Cong Wang	vto = kmap_atomic(to);
997747b9a493a197cb4db44c98d25ce6d3d9f586d1Paul Mundt
1000dfae7d5a21901b28ec0452d71be64adf5ea323ePaul Mundt	if (boot_cpu_data.dcache.n_aliases && page_mapped(from) &&
10155661fc1f105ed75852e937bf8ea408270eb0ccaPaul Mundt	    test_bit(PG_dcache_clean, &from->flags)) {
1027e01c949989b984c074469e04ab99c47367c7187Paul Mundt		vfrom = kmap_coherent(from, vaddr);
1032277ab4a1df50e05bc732fe9488d4e902bb8399aPaul Mundt		copy_page(vto, vfrom);
1047e01c949989b984c074469e04ab99c47367c7187Paul Mundt		kunmap_coherent(vfrom);
1057e01c949989b984c074469e04ab99c47367c7187Paul Mundt	} else {
106bc3e11be88010e09692ed1d214407d56caa90075Cong Wang		vfrom = kmap_atomic(from);
1077e01c949989b984c074469e04ab99c47367c7187Paul Mundt		copy_page(vto, vfrom);
108bc3e11be88010e09692ed1d214407d56caa90075Cong Wang		kunmap_atomic(vfrom);
1097e01c949989b984c074469e04ab99c47367c7187Paul Mundt	}
1107747b9a493a197cb4db44c98d25ce6d3d9f586d1Paul Mundt
111a25bbe12224e649fe12cba7a2fa920180a35c8a9Stuart Menefy	if (pages_do_alias((unsigned long)vto, vaddr & PAGE_MASK) ||
112a25bbe12224e649fe12cba7a2fa920180a35c8a9Stuart Menefy	    (vma->vm_flags & VM_EXEC))
1137e01c949989b984c074469e04ab99c47367c7187Paul Mundt		__flush_purge_region(vto, PAGE_SIZE);
11439ac11c1607f1d566e7cf885acd403fa4f07f8a2Stuart Menefy
115bc3e11be88010e09692ed1d214407d56caa90075Cong Wang	kunmap_atomic(vto);
1167747b9a493a197cb4db44c98d25ce6d3d9f586d1Paul Mundt	/* Make sure this page is cleared on other CPU's too before using it */
1177747b9a493a197cb4db44c98d25ce6d3d9f586d1Paul Mundt	smp_wmb();
1187747b9a493a197cb4db44c98d25ce6d3d9f586d1Paul Mundt}
1197747b9a493a197cb4db44c98d25ce6d3d9f586d1Paul MundtEXPORT_SYMBOL(copy_user_highpage);
120dfff0fa65ab15db45acd64b3189787d37ab163cdPaul Mundt
121dfff0fa65ab15db45acd64b3189787d37ab163cdPaul Mundtvoid clear_user_highpage(struct page *page, unsigned long vaddr)
122dfff0fa65ab15db45acd64b3189787d37ab163cdPaul Mundt{
123bc3e11be88010e09692ed1d214407d56caa90075Cong Wang	void *kaddr = kmap_atomic(page);
124dfff0fa65ab15db45acd64b3189787d37ab163cdPaul Mundt
1257e01c949989b984c074469e04ab99c47367c7187Paul Mundt	clear_page(kaddr);
126dfff0fa65ab15db45acd64b3189787d37ab163cdPaul Mundt
1277e01c949989b984c074469e04ab99c47367c7187Paul Mundt	if (pages_do_alias((unsigned long)kaddr, vaddr & PAGE_MASK))
1287e01c949989b984c074469e04ab99c47367c7187Paul Mundt		__flush_purge_region(kaddr, PAGE_SIZE);
129dfff0fa65ab15db45acd64b3189787d37ab163cdPaul Mundt
130bc3e11be88010e09692ed1d214407d56caa90075Cong Wang	kunmap_atomic(kaddr);
131dfff0fa65ab15db45acd64b3189787d37ab163cdPaul Mundt}
132dfff0fa65ab15db45acd64b3189787d37ab163cdPaul MundtEXPORT_SYMBOL(clear_user_highpage);
1339cef7492696a416663b4edb953a4eade8517ebebPaul Mundt
1349cef7492696a416663b4edb953a4eade8517ebebPaul Mundtvoid __update_cache(struct vm_area_struct *vma,
1359cef7492696a416663b4edb953a4eade8517ebebPaul Mundt		    unsigned long address, pte_t pte)
1369cef7492696a416663b4edb953a4eade8517ebebPaul Mundt{
1379cef7492696a416663b4edb953a4eade8517ebebPaul Mundt	struct page *page;
1389cef7492696a416663b4edb953a4eade8517ebebPaul Mundt	unsigned long pfn = pte_pfn(pte);
1399cef7492696a416663b4edb953a4eade8517ebebPaul Mundt
1409cef7492696a416663b4edb953a4eade8517ebebPaul Mundt	if (!boot_cpu_data.dcache.n_aliases)
1419cef7492696a416663b4edb953a4eade8517ebebPaul Mundt		return;
1429cef7492696a416663b4edb953a4eade8517ebebPaul Mundt
1439cef7492696a416663b4edb953a4eade8517ebebPaul Mundt	page = pfn_to_page(pfn);
144964f7e5a56814b32c727821de77d22bd7ef782bcPaul Mundt	if (pfn_valid(pfn)) {
14555661fc1f105ed75852e937bf8ea408270eb0ccaPaul Mundt		int dirty = !test_and_set_bit(PG_dcache_clean, &page->flags);
14676382b5bdb77c29ab430e1b82ef1c604c8dd113bMarkus Pietrek		if (dirty)
14776382b5bdb77c29ab430e1b82ef1c604c8dd113bMarkus Pietrek			__flush_purge_region(page_address(page), PAGE_SIZE);
1489cef7492696a416663b4edb953a4eade8517ebebPaul Mundt	}
1499cef7492696a416663b4edb953a4eade8517ebebPaul Mundt}
150c0fe478dbb14fd32e71d1383dbe302b54ce94134Paul Mundt
151c0fe478dbb14fd32e71d1383dbe302b54ce94134Paul Mundtvoid __flush_anon_page(struct page *page, unsigned long vmaddr)
152c0fe478dbb14fd32e71d1383dbe302b54ce94134Paul Mundt{
153c0fe478dbb14fd32e71d1383dbe302b54ce94134Paul Mundt	unsigned long addr = (unsigned long) page_address(page);
154c0fe478dbb14fd32e71d1383dbe302b54ce94134Paul Mundt
155c0fe478dbb14fd32e71d1383dbe302b54ce94134Paul Mundt	if (pages_do_alias(addr, vmaddr)) {
156c0fe478dbb14fd32e71d1383dbe302b54ce94134Paul Mundt		if (boot_cpu_data.dcache.n_aliases && page_mapped(page) &&
15755661fc1f105ed75852e937bf8ea408270eb0ccaPaul Mundt		    test_bit(PG_dcache_clean, &page->flags)) {
158c0fe478dbb14fd32e71d1383dbe302b54ce94134Paul Mundt			void *kaddr;
159c0fe478dbb14fd32e71d1383dbe302b54ce94134Paul Mundt
160c0fe478dbb14fd32e71d1383dbe302b54ce94134Paul Mundt			kaddr = kmap_coherent(page, vmaddr);
1616e4154d4c2dd3d7e61d19ddd2527322ce34c2f5aPaul Mundt			/* XXX.. For now kunmap_coherent() does a purge */
1626e4154d4c2dd3d7e61d19ddd2527322ce34c2f5aPaul Mundt			/* __flush_purge_region((void *)kaddr, PAGE_SIZE); */
1630906a3ad33a254094fb74828e3ddb9af8771a6daPaul Mundt			kunmap_coherent(kaddr);
164c0fe478dbb14fd32e71d1383dbe302b54ce94134Paul Mundt		} else
1656e4154d4c2dd3d7e61d19ddd2527322ce34c2f5aPaul Mundt			__flush_purge_region((void *)addr, PAGE_SIZE);
166c0fe478dbb14fd32e71d1383dbe302b54ce94134Paul Mundt	}
167c0fe478dbb14fd32e71d1383dbe302b54ce94134Paul Mundt}
168ecba1060583635ab55092072441ff903b5e9a659Paul Mundt
169f26b2a562b46ab186c8383993ab1332673ac4a47Paul Mundtvoid flush_cache_all(void)
170f26b2a562b46ab186c8383993ab1332673ac4a47Paul Mundt{
1716f3795788b030c3c190fa063adfe519e016cc6fdPaul Mundt	cacheop_on_each_cpu(local_flush_cache_all, NULL, 1);
172f26b2a562b46ab186c8383993ab1332673ac4a47Paul Mundt}
1730a993b0a290a2672500000b0ce811efc093f8467Paul MundtEXPORT_SYMBOL(flush_cache_all);
174f26b2a562b46ab186c8383993ab1332673ac4a47Paul Mundt
175f26b2a562b46ab186c8383993ab1332673ac4a47Paul Mundtvoid flush_cache_mm(struct mm_struct *mm)
176f26b2a562b46ab186c8383993ab1332673ac4a47Paul Mundt{
177654d364e26c797e8a5f9e2a1393607e6ca0106ebPaul Mundt	if (boot_cpu_data.dcache.n_aliases == 0)
178654d364e26c797e8a5f9e2a1393607e6ca0106ebPaul Mundt		return;
179654d364e26c797e8a5f9e2a1393607e6ca0106ebPaul Mundt
1806f3795788b030c3c190fa063adfe519e016cc6fdPaul Mundt	cacheop_on_each_cpu(local_flush_cache_mm, mm, 1);
181f26b2a562b46ab186c8383993ab1332673ac4a47Paul Mundt}
182f26b2a562b46ab186c8383993ab1332673ac4a47Paul Mundt
183f26b2a562b46ab186c8383993ab1332673ac4a47Paul Mundtvoid flush_cache_dup_mm(struct mm_struct *mm)
184f26b2a562b46ab186c8383993ab1332673ac4a47Paul Mundt{
185654d364e26c797e8a5f9e2a1393607e6ca0106ebPaul Mundt	if (boot_cpu_data.dcache.n_aliases == 0)
186654d364e26c797e8a5f9e2a1393607e6ca0106ebPaul Mundt		return;
187654d364e26c797e8a5f9e2a1393607e6ca0106ebPaul Mundt
1886f3795788b030c3c190fa063adfe519e016cc6fdPaul Mundt	cacheop_on_each_cpu(local_flush_cache_dup_mm, mm, 1);
189f26b2a562b46ab186c8383993ab1332673ac4a47Paul Mundt}
190f26b2a562b46ab186c8383993ab1332673ac4a47Paul Mundt
191f26b2a562b46ab186c8383993ab1332673ac4a47Paul Mundtvoid flush_cache_page(struct vm_area_struct *vma, unsigned long addr,
192f26b2a562b46ab186c8383993ab1332673ac4a47Paul Mundt		      unsigned long pfn)
193f26b2a562b46ab186c8383993ab1332673ac4a47Paul Mundt{
194f26b2a562b46ab186c8383993ab1332673ac4a47Paul Mundt	struct flusher_data data;
195f26b2a562b46ab186c8383993ab1332673ac4a47Paul Mundt
196f26b2a562b46ab186c8383993ab1332673ac4a47Paul Mundt	data.vma = vma;
197f26b2a562b46ab186c8383993ab1332673ac4a47Paul Mundt	data.addr1 = addr;
198f26b2a562b46ab186c8383993ab1332673ac4a47Paul Mundt	data.addr2 = pfn;
199f26b2a562b46ab186c8383993ab1332673ac4a47Paul Mundt
2006f3795788b030c3c190fa063adfe519e016cc6fdPaul Mundt	cacheop_on_each_cpu(local_flush_cache_page, (void *)&data, 1);
201f26b2a562b46ab186c8383993ab1332673ac4a47Paul Mundt}
202f26b2a562b46ab186c8383993ab1332673ac4a47Paul Mundt
203f26b2a562b46ab186c8383993ab1332673ac4a47Paul Mundtvoid flush_cache_range(struct vm_area_struct *vma, unsigned long start,
204f26b2a562b46ab186c8383993ab1332673ac4a47Paul Mundt		       unsigned long end)
205f26b2a562b46ab186c8383993ab1332673ac4a47Paul Mundt{
206f26b2a562b46ab186c8383993ab1332673ac4a47Paul Mundt	struct flusher_data data;
207f26b2a562b46ab186c8383993ab1332673ac4a47Paul Mundt
208f26b2a562b46ab186c8383993ab1332673ac4a47Paul Mundt	data.vma = vma;
209f26b2a562b46ab186c8383993ab1332673ac4a47Paul Mundt	data.addr1 = start;
210f26b2a562b46ab186c8383993ab1332673ac4a47Paul Mundt	data.addr2 = end;
211f26b2a562b46ab186c8383993ab1332673ac4a47Paul Mundt
2126f3795788b030c3c190fa063adfe519e016cc6fdPaul Mundt	cacheop_on_each_cpu(local_flush_cache_range, (void *)&data, 1);
213f26b2a562b46ab186c8383993ab1332673ac4a47Paul Mundt}
2140a993b0a290a2672500000b0ce811efc093f8467Paul MundtEXPORT_SYMBOL(flush_cache_range);
215f26b2a562b46ab186c8383993ab1332673ac4a47Paul Mundt
216f26b2a562b46ab186c8383993ab1332673ac4a47Paul Mundtvoid flush_dcache_page(struct page *page)
217f26b2a562b46ab186c8383993ab1332673ac4a47Paul Mundt{
2186f3795788b030c3c190fa063adfe519e016cc6fdPaul Mundt	cacheop_on_each_cpu(local_flush_dcache_page, page, 1);
219f26b2a562b46ab186c8383993ab1332673ac4a47Paul Mundt}
2200a993b0a290a2672500000b0ce811efc093f8467Paul MundtEXPORT_SYMBOL(flush_dcache_page);
221f26b2a562b46ab186c8383993ab1332673ac4a47Paul Mundt
222f26b2a562b46ab186c8383993ab1332673ac4a47Paul Mundtvoid flush_icache_range(unsigned long start, unsigned long end)
223f26b2a562b46ab186c8383993ab1332673ac4a47Paul Mundt{
224f26b2a562b46ab186c8383993ab1332673ac4a47Paul Mundt	struct flusher_data data;
225f26b2a562b46ab186c8383993ab1332673ac4a47Paul Mundt
226f26b2a562b46ab186c8383993ab1332673ac4a47Paul Mundt	data.vma = NULL;
227f26b2a562b46ab186c8383993ab1332673ac4a47Paul Mundt	data.addr1 = start;
228f26b2a562b46ab186c8383993ab1332673ac4a47Paul Mundt	data.addr2 = end;
229f26b2a562b46ab186c8383993ab1332673ac4a47Paul Mundt
2306f3795788b030c3c190fa063adfe519e016cc6fdPaul Mundt	cacheop_on_each_cpu(local_flush_icache_range, (void *)&data, 1);
231f26b2a562b46ab186c8383993ab1332673ac4a47Paul Mundt}
232e3560305192cd51b3c07206c85eb4231594dd58bPranith KumarEXPORT_SYMBOL(flush_icache_range);
233f26b2a562b46ab186c8383993ab1332673ac4a47Paul Mundt
234f26b2a562b46ab186c8383993ab1332673ac4a47Paul Mundtvoid flush_icache_page(struct vm_area_struct *vma, struct page *page)
235f26b2a562b46ab186c8383993ab1332673ac4a47Paul Mundt{
236f26b2a562b46ab186c8383993ab1332673ac4a47Paul Mundt	/* Nothing uses the VMA, so just pass the struct page along */
2376f3795788b030c3c190fa063adfe519e016cc6fdPaul Mundt	cacheop_on_each_cpu(local_flush_icache_page, page, 1);
238f26b2a562b46ab186c8383993ab1332673ac4a47Paul Mundt}
239f26b2a562b46ab186c8383993ab1332673ac4a47Paul Mundt
240f26b2a562b46ab186c8383993ab1332673ac4a47Paul Mundtvoid flush_cache_sigtramp(unsigned long address)
241f26b2a562b46ab186c8383993ab1332673ac4a47Paul Mundt{
2426f3795788b030c3c190fa063adfe519e016cc6fdPaul Mundt	cacheop_on_each_cpu(local_flush_cache_sigtramp, (void *)address, 1);
243f26b2a562b46ab186c8383993ab1332673ac4a47Paul Mundt}
244f26b2a562b46ab186c8383993ab1332673ac4a47Paul Mundt
24527d59ec1709817a90aa3ab7169f60994a89ad2f5Paul Mundtstatic void compute_alias(struct cache_info *c)
24627d59ec1709817a90aa3ab7169f60994a89ad2f5Paul Mundt{
24727d59ec1709817a90aa3ab7169f60994a89ad2f5Paul Mundt	c->alias_mask = ((c->sets - 1) << c->entry_shift) & ~(PAGE_SIZE - 1);
24827d59ec1709817a90aa3ab7169f60994a89ad2f5Paul Mundt	c->n_aliases = c->alias_mask ? (c->alias_mask >> PAGE_SHIFT) + 1 : 0;
24927d59ec1709817a90aa3ab7169f60994a89ad2f5Paul Mundt}
25027d59ec1709817a90aa3ab7169f60994a89ad2f5Paul Mundt
25127d59ec1709817a90aa3ab7169f60994a89ad2f5Paul Mundtstatic void __init emit_cache_params(void)
25227d59ec1709817a90aa3ab7169f60994a89ad2f5Paul Mundt{
25327d59ec1709817a90aa3ab7169f60994a89ad2f5Paul Mundt	printk(KERN_NOTICE "I-cache : n_ways=%d n_sets=%d way_incr=%d\n",
25427d59ec1709817a90aa3ab7169f60994a89ad2f5Paul Mundt		boot_cpu_data.icache.ways,
25527d59ec1709817a90aa3ab7169f60994a89ad2f5Paul Mundt		boot_cpu_data.icache.sets,
25627d59ec1709817a90aa3ab7169f60994a89ad2f5Paul Mundt		boot_cpu_data.icache.way_incr);
25727d59ec1709817a90aa3ab7169f60994a89ad2f5Paul Mundt	printk(KERN_NOTICE "I-cache : entry_mask=0x%08x alias_mask=0x%08x n_aliases=%d\n",
25827d59ec1709817a90aa3ab7169f60994a89ad2f5Paul Mundt		boot_cpu_data.icache.entry_mask,
25927d59ec1709817a90aa3ab7169f60994a89ad2f5Paul Mundt		boot_cpu_data.icache.alias_mask,
26027d59ec1709817a90aa3ab7169f60994a89ad2f5Paul Mundt		boot_cpu_data.icache.n_aliases);
26127d59ec1709817a90aa3ab7169f60994a89ad2f5Paul Mundt	printk(KERN_NOTICE "D-cache : n_ways=%d n_sets=%d way_incr=%d\n",
26227d59ec1709817a90aa3ab7169f60994a89ad2f5Paul Mundt		boot_cpu_data.dcache.ways,
26327d59ec1709817a90aa3ab7169f60994a89ad2f5Paul Mundt		boot_cpu_data.dcache.sets,
26427d59ec1709817a90aa3ab7169f60994a89ad2f5Paul Mundt		boot_cpu_data.dcache.way_incr);
26527d59ec1709817a90aa3ab7169f60994a89ad2f5Paul Mundt	printk(KERN_NOTICE "D-cache : entry_mask=0x%08x alias_mask=0x%08x n_aliases=%d\n",
26627d59ec1709817a90aa3ab7169f60994a89ad2f5Paul Mundt		boot_cpu_data.dcache.entry_mask,
26727d59ec1709817a90aa3ab7169f60994a89ad2f5Paul Mundt		boot_cpu_data.dcache.alias_mask,
26827d59ec1709817a90aa3ab7169f60994a89ad2f5Paul Mundt		boot_cpu_data.dcache.n_aliases);
26927d59ec1709817a90aa3ab7169f60994a89ad2f5Paul Mundt
27027d59ec1709817a90aa3ab7169f60994a89ad2f5Paul Mundt	/*
27127d59ec1709817a90aa3ab7169f60994a89ad2f5Paul Mundt	 * Emit Secondary Cache parameters if the CPU has a probed L2.
27227d59ec1709817a90aa3ab7169f60994a89ad2f5Paul Mundt	 */
27327d59ec1709817a90aa3ab7169f60994a89ad2f5Paul Mundt	if (boot_cpu_data.flags & CPU_HAS_L2_CACHE) {
27427d59ec1709817a90aa3ab7169f60994a89ad2f5Paul Mundt		printk(KERN_NOTICE "S-cache : n_ways=%d n_sets=%d way_incr=%d\n",
27527d59ec1709817a90aa3ab7169f60994a89ad2f5Paul Mundt			boot_cpu_data.scache.ways,
27627d59ec1709817a90aa3ab7169f60994a89ad2f5Paul Mundt			boot_cpu_data.scache.sets,
27727d59ec1709817a90aa3ab7169f60994a89ad2f5Paul Mundt			boot_cpu_data.scache.way_incr);
27827d59ec1709817a90aa3ab7169f60994a89ad2f5Paul Mundt		printk(KERN_NOTICE "S-cache : entry_mask=0x%08x alias_mask=0x%08x n_aliases=%d\n",
27927d59ec1709817a90aa3ab7169f60994a89ad2f5Paul Mundt			boot_cpu_data.scache.entry_mask,
28027d59ec1709817a90aa3ab7169f60994a89ad2f5Paul Mundt			boot_cpu_data.scache.alias_mask,
28127d59ec1709817a90aa3ab7169f60994a89ad2f5Paul Mundt			boot_cpu_data.scache.n_aliases);
28227d59ec1709817a90aa3ab7169f60994a89ad2f5Paul Mundt	}
28327d59ec1709817a90aa3ab7169f60994a89ad2f5Paul Mundt}
28427d59ec1709817a90aa3ab7169f60994a89ad2f5Paul Mundt
285ecba1060583635ab55092072441ff903b5e9a659Paul Mundtvoid __init cpu_cache_init(void)
286ecba1060583635ab55092072441ff903b5e9a659Paul Mundt{
2873af539e59cf3213cbe31ce7008f1db51c52665caPaul Mundt	unsigned int cache_disabled = 0;
2883af539e59cf3213cbe31ce7008f1db51c52665caPaul Mundt
289a5f6ea29f9a918403629f8369ae55fac6b09cb53Geert Uytterhoeven#ifdef SH_CCR
290a5f6ea29f9a918403629f8369ae55fac6b09cb53Geert Uytterhoeven	cache_disabled = !(__raw_readl(SH_CCR) & CCR_CACHE_ENABLE);
2913af539e59cf3213cbe31ce7008f1db51c52665caPaul Mundt#endif
2925fb80ae8bd7549034845ebfba694d483070b768bMagnus Damm
29327d59ec1709817a90aa3ab7169f60994a89ad2f5Paul Mundt	compute_alias(&boot_cpu_data.icache);
29427d59ec1709817a90aa3ab7169f60994a89ad2f5Paul Mundt	compute_alias(&boot_cpu_data.dcache);
29527d59ec1709817a90aa3ab7169f60994a89ad2f5Paul Mundt	compute_alias(&boot_cpu_data.scache);
29627d59ec1709817a90aa3ab7169f60994a89ad2f5Paul Mundt
29737443ef3f0406e855e169c87ae3f4ffb4b6ff635Paul Mundt	__flush_wback_region		= noop__flush_region;
29837443ef3f0406e855e169c87ae3f4ffb4b6ff635Paul Mundt	__flush_purge_region		= noop__flush_region;
29937443ef3f0406e855e169c87ae3f4ffb4b6ff635Paul Mundt	__flush_invalidate_region	= noop__flush_region;
30037443ef3f0406e855e169c87ae3f4ffb4b6ff635Paul Mundt
3015fb80ae8bd7549034845ebfba694d483070b768bMagnus Damm	/*
3025fb80ae8bd7549034845ebfba694d483070b768bMagnus Damm	 * No flushing is necessary in the disabled cache case so we can
3035fb80ae8bd7549034845ebfba694d483070b768bMagnus Damm	 * just keep the noop functions in local_flush_..() and __flush_..()
3045fb80ae8bd7549034845ebfba694d483070b768bMagnus Damm	 */
3055fb80ae8bd7549034845ebfba694d483070b768bMagnus Damm	if (unlikely(cache_disabled))
3065fb80ae8bd7549034845ebfba694d483070b768bMagnus Damm		goto skip;
3075fb80ae8bd7549034845ebfba694d483070b768bMagnus Damm
308109b44a82a7a8ae32d7fb257480f92f2d96f0dafPaul Mundt	if (boot_cpu_data.family == CPU_FAMILY_SH2) {
309109b44a82a7a8ae32d7fb257480f92f2d96f0dafPaul Mundt		extern void __weak sh2_cache_init(void);
310109b44a82a7a8ae32d7fb257480f92f2d96f0dafPaul Mundt
311109b44a82a7a8ae32d7fb257480f92f2d96f0dafPaul Mundt		sh2_cache_init();
312109b44a82a7a8ae32d7fb257480f92f2d96f0dafPaul Mundt	}
313109b44a82a7a8ae32d7fb257480f92f2d96f0dafPaul Mundt
314a58e1a2ab4f6334c50dfbda83d3a5c6e0b2b4beePaul Mundt	if (boot_cpu_data.family == CPU_FAMILY_SH2A) {
315a58e1a2ab4f6334c50dfbda83d3a5c6e0b2b4beePaul Mundt		extern void __weak sh2a_cache_init(void);
316a58e1a2ab4f6334c50dfbda83d3a5c6e0b2b4beePaul Mundt
317a58e1a2ab4f6334c50dfbda83d3a5c6e0b2b4beePaul Mundt		sh2a_cache_init();
318a58e1a2ab4f6334c50dfbda83d3a5c6e0b2b4beePaul Mundt	}
319a58e1a2ab4f6334c50dfbda83d3a5c6e0b2b4beePaul Mundt
32079f1c9da5e5fc5f4705836d8c1cee2213fc80640Paul Mundt	if (boot_cpu_data.family == CPU_FAMILY_SH3) {
32179f1c9da5e5fc5f4705836d8c1cee2213fc80640Paul Mundt		extern void __weak sh3_cache_init(void);
32279f1c9da5e5fc5f4705836d8c1cee2213fc80640Paul Mundt
32379f1c9da5e5fc5f4705836d8c1cee2213fc80640Paul Mundt		sh3_cache_init();
3240d051d90bb08b516b9d6c30d25f83d3c6b5b1c1dPaul Mundt
3250d051d90bb08b516b9d6c30d25f83d3c6b5b1c1dPaul Mundt		if ((boot_cpu_data.type == CPU_SH7705) &&
3260d051d90bb08b516b9d6c30d25f83d3c6b5b1c1dPaul Mundt		    (boot_cpu_data.dcache.sets == 512)) {
3270d051d90bb08b516b9d6c30d25f83d3c6b5b1c1dPaul Mundt			extern void __weak sh7705_cache_init(void);
3280d051d90bb08b516b9d6c30d25f83d3c6b5b1c1dPaul Mundt
3290d051d90bb08b516b9d6c30d25f83d3c6b5b1c1dPaul Mundt			sh7705_cache_init();
3300d051d90bb08b516b9d6c30d25f83d3c6b5b1c1dPaul Mundt		}
33179f1c9da5e5fc5f4705836d8c1cee2213fc80640Paul Mundt	}
33279f1c9da5e5fc5f4705836d8c1cee2213fc80640Paul Mundt
333ecba1060583635ab55092072441ff903b5e9a659Paul Mundt	if ((boot_cpu_data.family == CPU_FAMILY_SH4) ||
334ecba1060583635ab55092072441ff903b5e9a659Paul Mundt	    (boot_cpu_data.family == CPU_FAMILY_SH4A) ||
335ecba1060583635ab55092072441ff903b5e9a659Paul Mundt	    (boot_cpu_data.family == CPU_FAMILY_SH4AL_DSP)) {
336ecba1060583635ab55092072441ff903b5e9a659Paul Mundt		extern void __weak sh4_cache_init(void);
337ecba1060583635ab55092072441ff903b5e9a659Paul Mundt
338ecba1060583635ab55092072441ff903b5e9a659Paul Mundt		sh4_cache_init();
3393cf6fa1e334a3a4af702f92229690195018b747fPaul Mundt
3403cf6fa1e334a3a4af702f92229690195018b747fPaul Mundt		if ((boot_cpu_data.type == CPU_SH7786) ||
3413cf6fa1e334a3a4af702f92229690195018b747fPaul Mundt		    (boot_cpu_data.type == CPU_SHX3)) {
3423cf6fa1e334a3a4af702f92229690195018b747fPaul Mundt			extern void __weak shx3_cache_init(void);
3433cf6fa1e334a3a4af702f92229690195018b747fPaul Mundt
3443cf6fa1e334a3a4af702f92229690195018b747fPaul Mundt			shx3_cache_init();
3453cf6fa1e334a3a4af702f92229690195018b747fPaul Mundt		}
346ecba1060583635ab55092072441ff903b5e9a659Paul Mundt	}
34727d59ec1709817a90aa3ab7169f60994a89ad2f5Paul Mundt
3482b4315185a06414c4ab40fb0db50dce1b534a1d9Paul Mundt	if (boot_cpu_data.family == CPU_FAMILY_SH5) {
3492b4315185a06414c4ab40fb0db50dce1b534a1d9Paul Mundt		extern void __weak sh5_cache_init(void);
3502b4315185a06414c4ab40fb0db50dce1b534a1d9Paul Mundt
3512b4315185a06414c4ab40fb0db50dce1b534a1d9Paul Mundt		sh5_cache_init();
3522b4315185a06414c4ab40fb0db50dce1b534a1d9Paul Mundt	}
3532b4315185a06414c4ab40fb0db50dce1b534a1d9Paul Mundt
3545fb80ae8bd7549034845ebfba694d483070b768bMagnus Dammskip:
35527d59ec1709817a90aa3ab7169f60994a89ad2f5Paul Mundt	emit_cache_params();
356ecba1060583635ab55092072441ff903b5e9a659Paul Mundt}
357