xref: /openbmc/linux/arch/sh/mm/flush-sh4.c (revision 498495dba268b20e8eadd7fe93c140c68b6cc9d2)
1*b2441318SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0
281742527SPaul Mundt #include <linux/mm.h>
381742527SPaul Mundt #include <asm/mmu_context.h>
4f03c4866SPaul Mundt #include <asm/cache_insns.h>
581742527SPaul Mundt #include <asm/cacheflush.h>
6e839ca52SDavid Howells #include <asm/traps.h>
781742527SPaul Mundt 
881742527SPaul Mundt /*
981742527SPaul Mundt  * Write back the dirty D-caches, but not invalidate them.
1081742527SPaul Mundt  *
1181742527SPaul Mundt  * START: Virtual Address (U0, P1, or P3)
1281742527SPaul Mundt  * SIZE: Size of the region.
1381742527SPaul Mundt  */
sh4__flush_wback_region(void * start,int size)1437443ef3SPaul Mundt static void sh4__flush_wback_region(void *start, int size)
1581742527SPaul Mundt {
1643bc61d8SPaul Mundt 	reg_size_t aligned_start, v, cnt, end;
1781742527SPaul Mundt 
1843bc61d8SPaul Mundt 	aligned_start = register_align(start);
1943bc61d8SPaul Mundt 	v = aligned_start & ~(L1_CACHE_BYTES-1);
2043bc61d8SPaul Mundt 	end = (aligned_start + size + L1_CACHE_BYTES-1)
2181742527SPaul Mundt 		& ~(L1_CACHE_BYTES-1);
220837f524SPaul Mundt 	cnt = (end - v) / L1_CACHE_BYTES;
230837f524SPaul Mundt 
240837f524SPaul Mundt 	while (cnt >= 8) {
2594ecd224SPaul Mundt 		__ocbwb(v); v += L1_CACHE_BYTES;
2694ecd224SPaul Mundt 		__ocbwb(v); v += L1_CACHE_BYTES;
2794ecd224SPaul Mundt 		__ocbwb(v); v += L1_CACHE_BYTES;
2894ecd224SPaul Mundt 		__ocbwb(v); v += L1_CACHE_BYTES;
2994ecd224SPaul Mundt 		__ocbwb(v); v += L1_CACHE_BYTES;
3094ecd224SPaul Mundt 		__ocbwb(v); v += L1_CACHE_BYTES;
3194ecd224SPaul Mundt 		__ocbwb(v); v += L1_CACHE_BYTES;
3294ecd224SPaul Mundt 		__ocbwb(v); v += L1_CACHE_BYTES;
330837f524SPaul Mundt 		cnt -= 8;
340837f524SPaul Mundt 	}
350837f524SPaul Mundt 
360837f524SPaul Mundt 	while (cnt) {
3794ecd224SPaul Mundt 		__ocbwb(v); v += L1_CACHE_BYTES;
380837f524SPaul Mundt 		cnt--;
3981742527SPaul Mundt 	}
4081742527SPaul Mundt }
4181742527SPaul Mundt 
4281742527SPaul Mundt /*
4381742527SPaul Mundt  * Write back the dirty D-caches and invalidate them.
4481742527SPaul Mundt  *
4581742527SPaul Mundt  * START: Virtual Address (U0, P1, or P3)
4681742527SPaul Mundt  * SIZE: Size of the region.
4781742527SPaul Mundt  */
sh4__flush_purge_region(void * start,int size)4837443ef3SPaul Mundt static void sh4__flush_purge_region(void *start, int size)
4981742527SPaul Mundt {
5043bc61d8SPaul Mundt 	reg_size_t aligned_start, v, cnt, end;
5181742527SPaul Mundt 
5243bc61d8SPaul Mundt 	aligned_start = register_align(start);
5343bc61d8SPaul Mundt 	v = aligned_start & ~(L1_CACHE_BYTES-1);
5443bc61d8SPaul Mundt 	end = (aligned_start + size + L1_CACHE_BYTES-1)
5581742527SPaul Mundt 		& ~(L1_CACHE_BYTES-1);
560837f524SPaul Mundt 	cnt = (end - v) / L1_CACHE_BYTES;
570837f524SPaul Mundt 
580837f524SPaul Mundt 	while (cnt >= 8) {
5994ecd224SPaul Mundt 		__ocbp(v); v += L1_CACHE_BYTES;
6094ecd224SPaul Mundt 		__ocbp(v); v += L1_CACHE_BYTES;
6194ecd224SPaul Mundt 		__ocbp(v); v += L1_CACHE_BYTES;
6294ecd224SPaul Mundt 		__ocbp(v); v += L1_CACHE_BYTES;
6394ecd224SPaul Mundt 		__ocbp(v); v += L1_CACHE_BYTES;
6494ecd224SPaul Mundt 		__ocbp(v); v += L1_CACHE_BYTES;
6594ecd224SPaul Mundt 		__ocbp(v); v += L1_CACHE_BYTES;
6694ecd224SPaul Mundt 		__ocbp(v); v += L1_CACHE_BYTES;
670837f524SPaul Mundt 		cnt -= 8;
680837f524SPaul Mundt 	}
690837f524SPaul Mundt 	while (cnt) {
7094ecd224SPaul Mundt 		__ocbp(v); v += L1_CACHE_BYTES;
710837f524SPaul Mundt 		cnt--;
7281742527SPaul Mundt 	}
7381742527SPaul Mundt }
7481742527SPaul Mundt 
7581742527SPaul Mundt /*
7681742527SPaul Mundt  * No write back please
7781742527SPaul Mundt  */
sh4__flush_invalidate_region(void * start,int size)7837443ef3SPaul Mundt static void sh4__flush_invalidate_region(void *start, int size)
7981742527SPaul Mundt {
8043bc61d8SPaul Mundt 	reg_size_t aligned_start, v, cnt, end;
8181742527SPaul Mundt 
8243bc61d8SPaul Mundt 	aligned_start = register_align(start);
8343bc61d8SPaul Mundt 	v = aligned_start & ~(L1_CACHE_BYTES-1);
8443bc61d8SPaul Mundt 	end = (aligned_start + size + L1_CACHE_BYTES-1)
8581742527SPaul Mundt 		& ~(L1_CACHE_BYTES-1);
860837f524SPaul Mundt 	cnt = (end - v) / L1_CACHE_BYTES;
870837f524SPaul Mundt 
880837f524SPaul Mundt 	while (cnt >= 8) {
8994ecd224SPaul Mundt 		__ocbi(v); v += L1_CACHE_BYTES;
9094ecd224SPaul Mundt 		__ocbi(v); v += L1_CACHE_BYTES;
9194ecd224SPaul Mundt 		__ocbi(v); v += L1_CACHE_BYTES;
9294ecd224SPaul Mundt 		__ocbi(v); v += L1_CACHE_BYTES;
9394ecd224SPaul Mundt 		__ocbi(v); v += L1_CACHE_BYTES;
9494ecd224SPaul Mundt 		__ocbi(v); v += L1_CACHE_BYTES;
9594ecd224SPaul Mundt 		__ocbi(v); v += L1_CACHE_BYTES;
9694ecd224SPaul Mundt 		__ocbi(v); v += L1_CACHE_BYTES;
970837f524SPaul Mundt 		cnt -= 8;
980837f524SPaul Mundt 	}
990837f524SPaul Mundt 
1000837f524SPaul Mundt 	while (cnt) {
10194ecd224SPaul Mundt 		__ocbi(v); v += L1_CACHE_BYTES;
1020837f524SPaul Mundt 		cnt--;
10381742527SPaul Mundt 	}
10481742527SPaul Mundt }
10537443ef3SPaul Mundt 
sh4__flush_region_init(void)10637443ef3SPaul Mundt void __init sh4__flush_region_init(void)
10737443ef3SPaul Mundt {
10837443ef3SPaul Mundt 	__flush_wback_region		= sh4__flush_wback_region;
10937443ef3SPaul Mundt 	__flush_invalidate_region	= sh4__flush_invalidate_region;
11037443ef3SPaul Mundt 	__flush_purge_region		= sh4__flush_purge_region;
11137443ef3SPaul Mundt }
112