root/arch/m68k/include/asm/cacheflush_mm.h

/* [<][>][^][v][top][bottom][index][help] */

INCLUDED FROM


DEFINITIONS

This source file includes following definitions.
  1. clear_cf_icache
  2. clear_cf_dcache
  3. clear_cf_bcache
  4. flush_cf_icache
  5. flush_cf_dcache
  6. flush_cf_bcache
  7. flush_icache
  8. flush_cache_mm
  9. flush_cache_range
  10. flush_cache_page
  11. __flush_page_to_ram
  12. copy_to_user_page
  13. copy_from_user_page

   1 /* SPDX-License-Identifier: GPL-2.0 */
   2 #ifndef _M68K_CACHEFLUSH_H
   3 #define _M68K_CACHEFLUSH_H
   4 
   5 #include <linux/mm.h>
   6 #ifdef CONFIG_COLDFIRE
   7 #include <asm/mcfsim.h>
   8 #endif
   9 
  10 /* cache code */
  11 #define FLUSH_I_AND_D   (0x00000808)
  12 #define FLUSH_I         (0x00000008)
  13 
  14 #ifndef ICACHE_MAX_ADDR
  15 #define ICACHE_MAX_ADDR 0
  16 #define ICACHE_SET_MASK 0
  17 #define DCACHE_MAX_ADDR 0
  18 #define DCACHE_SETMASK  0
  19 #endif
  20 #ifndef CACHE_MODE
  21 #define CACHE_MODE      0
  22 #define CACR_ICINVA     0
  23 #define CACR_DCINVA     0
  24 #define CACR_BCINVA     0
  25 #endif
  26 
  27 /*
  28  * ColdFire architecture has no way to clear individual cache lines, so we
  29  * are stuck invalidating all the cache entries when we want a clear operation.
  30  */
  31 static inline void clear_cf_icache(unsigned long start, unsigned long end)
  32 {
  33         __asm__ __volatile__ (
  34                 "movec  %0,%%cacr\n\t"
  35                 "nop"
  36                 :
  37                 : "r" (CACHE_MODE | CACR_ICINVA | CACR_BCINVA));
  38 }
  39 
  40 static inline void clear_cf_dcache(unsigned long start, unsigned long end)
  41 {
  42         __asm__ __volatile__ (
  43                 "movec  %0,%%cacr\n\t"
  44                 "nop"
  45                 :
  46                 : "r" (CACHE_MODE | CACR_DCINVA));
  47 }
  48 
  49 static inline void clear_cf_bcache(unsigned long start, unsigned long end)
  50 {
  51         __asm__ __volatile__ (
  52                 "movec  %0,%%cacr\n\t"
  53                 "nop"
  54                 :
  55                 : "r" (CACHE_MODE | CACR_ICINVA | CACR_BCINVA | CACR_DCINVA));
  56 }
  57 
  58 /*
  59  * Use the ColdFire cpushl instruction to push (and invalidate) cache lines.
  60  * The start and end addresses are cache line numbers not memory addresses.
  61  */
  62 static inline void flush_cf_icache(unsigned long start, unsigned long end)
  63 {
  64         unsigned long set;
  65 
  66         for (set = start; set <= end; set += (0x10 - 3)) {
  67                 __asm__ __volatile__ (
  68                         "cpushl %%ic,(%0)\n\t"
  69                         "addq%.l #1,%0\n\t"
  70                         "cpushl %%ic,(%0)\n\t"
  71                         "addq%.l #1,%0\n\t"
  72                         "cpushl %%ic,(%0)\n\t"
  73                         "addq%.l #1,%0\n\t"
  74                         "cpushl %%ic,(%0)"
  75                         : "=a" (set)
  76                         : "a" (set));
  77         }
  78 }
  79 
  80 static inline void flush_cf_dcache(unsigned long start, unsigned long end)
  81 {
  82         unsigned long set;
  83 
  84         for (set = start; set <= end; set += (0x10 - 3)) {
  85                 __asm__ __volatile__ (
  86                         "cpushl %%dc,(%0)\n\t"
  87                         "addq%.l #1,%0\n\t"
  88                         "cpushl %%dc,(%0)\n\t"
  89                         "addq%.l #1,%0\n\t"
  90                         "cpushl %%dc,(%0)\n\t"
  91                         "addq%.l #1,%0\n\t"
  92                         "cpushl %%dc,(%0)"
  93                         : "=a" (set)
  94                         : "a" (set));
  95         }
  96 }
  97 
  98 static inline void flush_cf_bcache(unsigned long start, unsigned long end)
  99 {
 100         unsigned long set;
 101 
 102         for (set = start; set <= end; set += (0x10 - 3)) {
 103                 __asm__ __volatile__ (
 104                         "cpushl %%bc,(%0)\n\t"
 105                         "addq%.l #1,%0\n\t"
 106                         "cpushl %%bc,(%0)\n\t"
 107                         "addq%.l #1,%0\n\t"
 108                         "cpushl %%bc,(%0)\n\t"
 109                         "addq%.l #1,%0\n\t"
 110                         "cpushl %%bc,(%0)"
 111                         : "=a" (set)
 112                         : "a" (set));
 113         }
 114 }
 115 
 116 /*
 117  * Cache handling functions
 118  */
 119 
 120 static inline void flush_icache(void)
 121 {
 122         if (CPU_IS_COLDFIRE) {
 123                 flush_cf_icache(0, ICACHE_MAX_ADDR);
 124         } else if (CPU_IS_040_OR_060) {
 125                 asm volatile (  "nop\n"
 126                         "       .chip   68040\n"
 127                         "       cpusha  %bc\n"
 128                         "       .chip   68k");
 129         } else {
 130                 unsigned long tmp;
 131                 asm volatile (  "movec  %%cacr,%0\n"
 132                         "       or.w    %1,%0\n"
 133                         "       movec   %0,%%cacr"
 134                         : "=&d" (tmp)
 135                         : "id" (FLUSH_I));
 136         }
 137 }
 138 
 139 /*
 140  * invalidate the cache for the specified memory range.
 141  * It starts at the physical address specified for
 142  * the given number of bytes.
 143  */
 144 extern void cache_clear(unsigned long paddr, int len);
 145 /*
 146  * push any dirty cache in the specified memory range.
 147  * It starts at the physical address specified for
 148  * the given number of bytes.
 149  */
 150 extern void cache_push(unsigned long paddr, int len);
 151 
 152 /*
 153  * push and invalidate pages in the specified user virtual
 154  * memory range.
 155  */
 156 extern void cache_push_v(unsigned long vaddr, int len);
 157 
 158 /* This is needed whenever the virtual mapping of the current
 159    process changes.  */
 160 #define __flush_cache_all()                                     \
 161 ({                                                              \
 162         if (CPU_IS_COLDFIRE) {                                  \
 163                 flush_cf_dcache(0, DCACHE_MAX_ADDR);            \
 164         } else if (CPU_IS_040_OR_060) {                         \
 165                 __asm__ __volatile__("nop\n\t"                  \
 166                                      ".chip 68040\n\t"          \
 167                                      "cpusha %dc\n\t"           \
 168                                      ".chip 68k");              \
 169         } else {                                                \
 170                 unsigned long _tmp;                             \
 171                 __asm__ __volatile__("movec %%cacr,%0\n\t"      \
 172                                      "orw %1,%0\n\t"            \
 173                                      "movec %0,%%cacr"          \
 174                                      : "=&d" (_tmp)             \
 175                                      : "di" (FLUSH_I_AND_D));   \
 176         }                                                       \
 177 })
 178 
 179 #define __flush_cache_030()                                     \
 180 ({                                                              \
 181         if (CPU_IS_020_OR_030) {                                \
 182                 unsigned long _tmp;                             \
 183                 __asm__ __volatile__("movec %%cacr,%0\n\t"      \
 184                                      "orw %1,%0\n\t"            \
 185                                      "movec %0,%%cacr"          \
 186                                      : "=&d" (_tmp)             \
 187                                      : "di" (FLUSH_I_AND_D));   \
 188         }                                                       \
 189 })
 190 
 191 #define flush_cache_all() __flush_cache_all()
 192 
 193 #define flush_cache_vmap(start, end)            flush_cache_all()
 194 #define flush_cache_vunmap(start, end)          flush_cache_all()
 195 
 196 static inline void flush_cache_mm(struct mm_struct *mm)
 197 {
 198         if (mm == current->mm)
 199                 __flush_cache_030();
 200 }
 201 
 202 #define flush_cache_dup_mm(mm)                  flush_cache_mm(mm)
 203 
 204 /* flush_cache_range/flush_cache_page must be macros to avoid
 205    a dependency on linux/mm.h, which includes this file... */
 206 static inline void flush_cache_range(struct vm_area_struct *vma,
 207                                      unsigned long start,
 208                                      unsigned long end)
 209 {
 210         if (vma->vm_mm == current->mm)
 211                 __flush_cache_030();
 212 }
 213 
 214 static inline void flush_cache_page(struct vm_area_struct *vma, unsigned long vmaddr, unsigned long pfn)
 215 {
 216         if (vma->vm_mm == current->mm)
 217                 __flush_cache_030();
 218 }
 219 
 220 
 221 /* Push the page at kernel virtual address and clear the icache */
 222 /* RZ: use cpush %bc instead of cpush %dc, cinv %ic */
 223 static inline void __flush_page_to_ram(void *vaddr)
 224 {
 225         if (CPU_IS_COLDFIRE) {
 226                 unsigned long addr, start, end;
 227                 addr = ((unsigned long) vaddr) & ~(PAGE_SIZE - 1);
 228                 start = addr & ICACHE_SET_MASK;
 229                 end = (addr + PAGE_SIZE - 1) & ICACHE_SET_MASK;
 230                 if (start > end) {
 231                         flush_cf_bcache(0, end);
 232                         end = ICACHE_MAX_ADDR;
 233                 }
 234                 flush_cf_bcache(start, end);
 235         } else if (CPU_IS_040_OR_060) {
 236                 __asm__ __volatile__("nop\n\t"
 237                                      ".chip 68040\n\t"
 238                                      "cpushp %%bc,(%0)\n\t"
 239                                      ".chip 68k"
 240                                      : : "a" (__pa(vaddr)));
 241         } else {
 242                 unsigned long _tmp;
 243                 __asm__ __volatile__("movec %%cacr,%0\n\t"
 244                                      "orw %1,%0\n\t"
 245                                      "movec %0,%%cacr"
 246                                      : "=&d" (_tmp)
 247                                      : "di" (FLUSH_I));
 248         }
 249 }
 250 
 251 #define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE 1
 252 #define flush_dcache_page(page)         __flush_page_to_ram(page_address(page))
 253 #define flush_dcache_mmap_lock(mapping)         do { } while (0)
 254 #define flush_dcache_mmap_unlock(mapping)       do { } while (0)
 255 #define flush_icache_page(vma, page)    __flush_page_to_ram(page_address(page))
 256 
 257 extern void flush_icache_user_range(struct vm_area_struct *vma, struct page *page,
 258                                     unsigned long addr, int len);
 259 extern void flush_icache_range(unsigned long address, unsigned long endaddr);
 260 
 261 static inline void copy_to_user_page(struct vm_area_struct *vma,
 262                                      struct page *page, unsigned long vaddr,
 263                                      void *dst, void *src, int len)
 264 {
 265         flush_cache_page(vma, vaddr, page_to_pfn(page));
 266         memcpy(dst, src, len);
 267         flush_icache_user_range(vma, page, vaddr, len);
 268 }
 269 static inline void copy_from_user_page(struct vm_area_struct *vma,
 270                                        struct page *page, unsigned long vaddr,
 271                                        void *dst, void *src, int len)
 272 {
 273         flush_cache_page(vma, vaddr, page_to_pfn(page));
 274         memcpy(dst, src, len);
 275 }
 276 
 277 #endif /* _M68K_CACHEFLUSH_H */

/* [<][>][^][v][top][bottom][index][help] */