xref: /openbmc/linux/arch/hexagon/mm/cache.c (revision 08dbd0f8)
108dbd0f8SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
22d3cbc78SRichard Kuo /*
32d3cbc78SRichard Kuo  * Cache management functions for Hexagon
42d3cbc78SRichard Kuo  *
5e1858b2aSRichard Kuo  * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
62d3cbc78SRichard Kuo  */
72d3cbc78SRichard Kuo 
82d3cbc78SRichard Kuo #include <linux/mm.h>
92d3cbc78SRichard Kuo #include <asm/cacheflush.h>
102d3cbc78SRichard Kuo #include <asm/hexagon_vm.h>
112d3cbc78SRichard Kuo 
122d3cbc78SRichard Kuo #define spanlines(start, end) \
132d3cbc78SRichard Kuo 	(((end - (start & ~(LINESIZE - 1))) >> LINEBITS) + 1)
142d3cbc78SRichard Kuo 
flush_dcache_range(unsigned long start,unsigned long end)152d3cbc78SRichard Kuo void flush_dcache_range(unsigned long start, unsigned long end)
162d3cbc78SRichard Kuo {
172d3cbc78SRichard Kuo 	unsigned long lines = spanlines(start, end-1);
182d3cbc78SRichard Kuo 	unsigned long i, flags;
192d3cbc78SRichard Kuo 
202d3cbc78SRichard Kuo 	start &= ~(LINESIZE - 1);
212d3cbc78SRichard Kuo 
222d3cbc78SRichard Kuo 	local_irq_save(flags);
232d3cbc78SRichard Kuo 
242d3cbc78SRichard Kuo 	for (i = 0; i < lines; i++) {
252d3cbc78SRichard Kuo 		__asm__ __volatile__ (
262d3cbc78SRichard Kuo 		"	dccleaninva(%0);	"
272d3cbc78SRichard Kuo 		:
282d3cbc78SRichard Kuo 		: "r" (start)
292d3cbc78SRichard Kuo 		);
302d3cbc78SRichard Kuo 		start += LINESIZE;
312d3cbc78SRichard Kuo 	}
322d3cbc78SRichard Kuo 	local_irq_restore(flags);
332d3cbc78SRichard Kuo }
342d3cbc78SRichard Kuo 
flush_icache_range(unsigned long start,unsigned long end)352d3cbc78SRichard Kuo void flush_icache_range(unsigned long start, unsigned long end)
362d3cbc78SRichard Kuo {
372d3cbc78SRichard Kuo 	unsigned long lines = spanlines(start, end-1);
382d3cbc78SRichard Kuo 	unsigned long i, flags;
392d3cbc78SRichard Kuo 
402d3cbc78SRichard Kuo 	start &= ~(LINESIZE - 1);
412d3cbc78SRichard Kuo 
422d3cbc78SRichard Kuo 	local_irq_save(flags);
432d3cbc78SRichard Kuo 
442d3cbc78SRichard Kuo 	for (i = 0; i < lines; i++) {
452d3cbc78SRichard Kuo 		__asm__ __volatile__ (
462d3cbc78SRichard Kuo 			"	dccleana(%0); "
472d3cbc78SRichard Kuo 			"	icinva(%0);	"
482d3cbc78SRichard Kuo 			:
492d3cbc78SRichard Kuo 			: "r" (start)
502d3cbc78SRichard Kuo 		);
512d3cbc78SRichard Kuo 		start += LINESIZE;
522d3cbc78SRichard Kuo 	}
532d3cbc78SRichard Kuo 	__asm__ __volatile__ (
542d3cbc78SRichard Kuo 		"isync"
552d3cbc78SRichard Kuo 	);
562d3cbc78SRichard Kuo 	local_irq_restore(flags);
572d3cbc78SRichard Kuo }
58e3560305SPranith Kumar EXPORT_SYMBOL(flush_icache_range);
592d3cbc78SRichard Kuo 
hexagon_clean_dcache_range(unsigned long start,unsigned long end)602d3cbc78SRichard Kuo void hexagon_clean_dcache_range(unsigned long start, unsigned long end)
612d3cbc78SRichard Kuo {
622d3cbc78SRichard Kuo 	unsigned long lines = spanlines(start, end-1);
632d3cbc78SRichard Kuo 	unsigned long i, flags;
642d3cbc78SRichard Kuo 
652d3cbc78SRichard Kuo 	start &= ~(LINESIZE - 1);
662d3cbc78SRichard Kuo 
672d3cbc78SRichard Kuo 	local_irq_save(flags);
682d3cbc78SRichard Kuo 
692d3cbc78SRichard Kuo 	for (i = 0; i < lines; i++) {
702d3cbc78SRichard Kuo 		__asm__ __volatile__ (
712d3cbc78SRichard Kuo 		"	dccleana(%0);	"
722d3cbc78SRichard Kuo 		:
732d3cbc78SRichard Kuo 		: "r" (start)
742d3cbc78SRichard Kuo 		);
752d3cbc78SRichard Kuo 		start += LINESIZE;
762d3cbc78SRichard Kuo 	}
772d3cbc78SRichard Kuo 	local_irq_restore(flags);
782d3cbc78SRichard Kuo }
792d3cbc78SRichard Kuo 
hexagon_inv_dcache_range(unsigned long start,unsigned long end)802d3cbc78SRichard Kuo void hexagon_inv_dcache_range(unsigned long start, unsigned long end)
812d3cbc78SRichard Kuo {
822d3cbc78SRichard Kuo 	unsigned long lines = spanlines(start, end-1);
832d3cbc78SRichard Kuo 	unsigned long i, flags;
842d3cbc78SRichard Kuo 
852d3cbc78SRichard Kuo 	start &= ~(LINESIZE - 1);
862d3cbc78SRichard Kuo 
872d3cbc78SRichard Kuo 	local_irq_save(flags);
882d3cbc78SRichard Kuo 
892d3cbc78SRichard Kuo 	for (i = 0; i < lines; i++) {
902d3cbc78SRichard Kuo 		__asm__ __volatile__ (
912d3cbc78SRichard Kuo 		"	dcinva(%0);	"
922d3cbc78SRichard Kuo 		:
932d3cbc78SRichard Kuo 		: "r" (start)
942d3cbc78SRichard Kuo 		);
952d3cbc78SRichard Kuo 		start += LINESIZE;
962d3cbc78SRichard Kuo 	}
972d3cbc78SRichard Kuo 	local_irq_restore(flags);
982d3cbc78SRichard Kuo }
992d3cbc78SRichard Kuo 
1002d3cbc78SRichard Kuo 
1012d3cbc78SRichard Kuo 
1022d3cbc78SRichard Kuo 
1032d3cbc78SRichard Kuo /*
1042d3cbc78SRichard Kuo  * This is just really brutal and shouldn't be used anyways,
1052d3cbc78SRichard Kuo  * especially on V2.  Left here just in case.
1062d3cbc78SRichard Kuo  */
flush_cache_all_hexagon(void)1072d3cbc78SRichard Kuo void flush_cache_all_hexagon(void)
1082d3cbc78SRichard Kuo {
1092d3cbc78SRichard Kuo 	unsigned long flags;
1102d3cbc78SRichard Kuo 	local_irq_save(flags);
1112d3cbc78SRichard Kuo 	__vmcache_ickill();
1122d3cbc78SRichard Kuo 	__vmcache_dckill();
1132d3cbc78SRichard Kuo 	__vmcache_l2kill();
1142d3cbc78SRichard Kuo 	local_irq_restore(flags);
1152d3cbc78SRichard Kuo 	mb();
1162d3cbc78SRichard Kuo }
117cb84c2b4SGuenter Roeck 
copy_to_user_page(struct vm_area_struct * vma,struct page * page,unsigned long vaddr,void * dst,void * src,int len)118cb84c2b4SGuenter Roeck void copy_to_user_page(struct vm_area_struct *vma, struct page *page,
119cb84c2b4SGuenter Roeck 		       unsigned long vaddr, void *dst, void *src, int len)
120cb84c2b4SGuenter Roeck {
121cb84c2b4SGuenter Roeck 	memcpy(dst, src, len);
122cb84c2b4SGuenter Roeck 	if (vma->vm_flags & VM_EXEC) {
123cb84c2b4SGuenter Roeck 		flush_icache_range((unsigned long) dst,
124cb84c2b4SGuenter Roeck 		(unsigned long) dst + len);
125cb84c2b4SGuenter Roeck 	}
126cb84c2b4SGuenter Roeck }
127