Merge branch 'drm-fixes-5.2' of git://people.freedesktop.org/~agd5f/linux into drm...
[sfrench/cifs-2.6.git] / arch / hexagon / mm / cache.c
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Cache management functions for Hexagon
4  *
5  * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
6  */
7
8 #include <linux/mm.h>
9 #include <asm/cacheflush.h>
10 #include <asm/hexagon_vm.h>
11
12 #define spanlines(start, end) \
13         (((end - (start & ~(LINESIZE - 1))) >> LINEBITS) + 1)
14
15 void flush_dcache_range(unsigned long start, unsigned long end)
16 {
17         unsigned long lines = spanlines(start, end-1);
18         unsigned long i, flags;
19
20         start &= ~(LINESIZE - 1);
21
22         local_irq_save(flags);
23
24         for (i = 0; i < lines; i++) {
25                 __asm__ __volatile__ (
26                 "       dccleaninva(%0);        "
27                 :
28                 : "r" (start)
29                 );
30                 start += LINESIZE;
31         }
32         local_irq_restore(flags);
33 }
34
35 void flush_icache_range(unsigned long start, unsigned long end)
36 {
37         unsigned long lines = spanlines(start, end-1);
38         unsigned long i, flags;
39
40         start &= ~(LINESIZE - 1);
41
42         local_irq_save(flags);
43
44         for (i = 0; i < lines; i++) {
45                 __asm__ __volatile__ (
46                         "       dccleana(%0); "
47                         "       icinva(%0);     "
48                         :
49                         : "r" (start)
50                 );
51                 start += LINESIZE;
52         }
53         __asm__ __volatile__ (
54                 "isync"
55         );
56         local_irq_restore(flags);
57 }
58 EXPORT_SYMBOL(flush_icache_range);
59
60 void hexagon_clean_dcache_range(unsigned long start, unsigned long end)
61 {
62         unsigned long lines = spanlines(start, end-1);
63         unsigned long i, flags;
64
65         start &= ~(LINESIZE - 1);
66
67         local_irq_save(flags);
68
69         for (i = 0; i < lines; i++) {
70                 __asm__ __volatile__ (
71                 "       dccleana(%0);   "
72                 :
73                 : "r" (start)
74                 );
75                 start += LINESIZE;
76         }
77         local_irq_restore(flags);
78 }
79
80 void hexagon_inv_dcache_range(unsigned long start, unsigned long end)
81 {
82         unsigned long lines = spanlines(start, end-1);
83         unsigned long i, flags;
84
85         start &= ~(LINESIZE - 1);
86
87         local_irq_save(flags);
88
89         for (i = 0; i < lines; i++) {
90                 __asm__ __volatile__ (
91                 "       dcinva(%0);     "
92                 :
93                 : "r" (start)
94                 );
95                 start += LINESIZE;
96         }
97         local_irq_restore(flags);
98 }
99
100
101
102
103 /*
104  * This is just really brutal and shouldn't be used anyways,
105  * especially on V2.  Left here just in case.
106  */
107 void flush_cache_all_hexagon(void)
108 {
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();
116 }
117
118 void copy_to_user_page(struct vm_area_struct *vma, struct page *page,
119                        unsigned long vaddr, void *dst, void *src, int len)
120 {
121         memcpy(dst, src, len);
122         if (vma->vm_flags & VM_EXEC) {
123                 flush_icache_range((unsigned long) dst,
124                 (unsigned long) dst + len);
125         }
126 }