Linux 5.7.6
[linux/fpc-iii.git] / arch / hexagon / mm / cache.c
blob7e46f40c8b540671a52a79a82782b16f31dfad70
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3 * Cache management functions for Hexagon
5 * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
6 */
8 #include <linux/mm.h>
9 #include <asm/cacheflush.h>
10 #include <asm/hexagon_vm.h>
12 #define spanlines(start, end) \
13 (((end - (start & ~(LINESIZE - 1))) >> LINEBITS) + 1)
15 void flush_dcache_range(unsigned long start, unsigned long end)
17 unsigned long lines = spanlines(start, end-1);
18 unsigned long i, flags;
20 start &= ~(LINESIZE - 1);
22 local_irq_save(flags);
24 for (i = 0; i < lines; i++) {
25 __asm__ __volatile__ (
26 " dccleaninva(%0); "
28 : "r" (start)
30 start += LINESIZE;
32 local_irq_restore(flags);
35 void flush_icache_range(unsigned long start, unsigned long end)
37 unsigned long lines = spanlines(start, end-1);
38 unsigned long i, flags;
40 start &= ~(LINESIZE - 1);
42 local_irq_save(flags);
44 for (i = 0; i < lines; i++) {
45 __asm__ __volatile__ (
46 " dccleana(%0); "
47 " icinva(%0); "
49 : "r" (start)
51 start += LINESIZE;
53 __asm__ __volatile__ (
54 "isync"
56 local_irq_restore(flags);
58 EXPORT_SYMBOL(flush_icache_range);
60 void hexagon_clean_dcache_range(unsigned long start, unsigned long end)
62 unsigned long lines = spanlines(start, end-1);
63 unsigned long i, flags;
65 start &= ~(LINESIZE - 1);
67 local_irq_save(flags);
69 for (i = 0; i < lines; i++) {
70 __asm__ __volatile__ (
71 " dccleana(%0); "
73 : "r" (start)
75 start += LINESIZE;
77 local_irq_restore(flags);
80 void hexagon_inv_dcache_range(unsigned long start, unsigned long end)
82 unsigned long lines = spanlines(start, end-1);
83 unsigned long i, flags;
85 start &= ~(LINESIZE - 1);
87 local_irq_save(flags);
89 for (i = 0; i < lines; i++) {
90 __asm__ __volatile__ (
91 " dcinva(%0); "
93 : "r" (start)
95 start += LINESIZE;
97 local_irq_restore(flags);
104 * This is just really brutal and shouldn't be used anyways,
105 * especially on V2. Left here just in case.
107 void flush_cache_all_hexagon(void)
109 unsigned long flags;
110 local_irq_save(flags);
111 __vmcache_ickill();
112 __vmcache_dckill();
113 __vmcache_l2kill();
114 local_irq_restore(flags);
115 mb();
118 void copy_to_user_page(struct vm_area_struct *vma, struct page *page,
119 unsigned long vaddr, void *dst, void *src, int len)
121 memcpy(dst, src, len);
122 if (vma->vm_flags & VM_EXEC) {
123 flush_icache_range((unsigned long) dst,
124 (unsigned long) dst + len);