^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * linux/arch/m68k/mm/memory.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (C) 1995 Hamish Macdonald
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/mm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/string.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/types.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/pagemap.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/gfp.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <asm/setup.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <asm/segment.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <asm/page.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <asm/traps.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <asm/machdep.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) /* invalidate page in both caches */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) static inline void clear040(unsigned long paddr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) asm volatile (
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) "nop\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) ".chip 68040\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) "cinvp %%bc,(%0)\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) ".chip 68k"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) : : "a" (paddr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) /* invalidate page in i-cache */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) static inline void cleari040(unsigned long paddr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) asm volatile (
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) "nop\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) ".chip 68040\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) "cinvp %%ic,(%0)\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) ".chip 68k"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) : : "a" (paddr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) /* push page in both caches */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) /* RZ: cpush %bc DOES invalidate %ic, regardless of DPI */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) static inline void push040(unsigned long paddr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) asm volatile (
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) "nop\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) ".chip 68040\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) "cpushp %%bc,(%0)\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) ".chip 68k"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) : : "a" (paddr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) /* push and invalidate page in both caches, must disable ints
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) * to avoid invalidating valid data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) static inline void pushcl040(unsigned long paddr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) local_irq_save(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) push040(paddr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) if (CPU_IS_060)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) clear040(paddr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) local_irq_restore(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) * 040: Hit every page containing an address in the range paddr..paddr+len-1.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) * (Low order bits of the ea of a CINVP/CPUSHP are "don't care"s).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) * Hit every page until there is a page or less to go. Hit the next page,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) * and the one after that if the range hits it.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) /* ++roman: A little bit more care is required here: The CINVP instruction
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) * invalidates cache entries WITHOUT WRITING DIRTY DATA BACK! So the beginning
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) * and the end of the region must be treated differently if they are not
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) * exactly at the beginning or end of a page boundary. Else, maybe too much
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) * data becomes invalidated and thus lost forever. CPUSHP does what we need:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) * it invalidates the page after pushing dirty data to memory. (Thanks to Jes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) * for discovering the problem!)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) /* ... but on the '060, CPUSH doesn't invalidate (for us, since we have set
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) * the DPI bit in the CACR; would it cause problems with temporarily changing
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) * this?). So we have to push first and then additionally to invalidate.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) * cache_clear() semantics: Clear any cache entries for the area in question,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) * without writing back dirty entries first. This is useful if the data will
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) * be overwritten anyway, e.g. by DMA to memory. The range is defined by a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) * _physical_ address.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) void cache_clear (unsigned long paddr, int len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) if (CPU_IS_COLDFIRE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) clear_cf_bcache(0, DCACHE_MAX_ADDR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) } else if (CPU_IS_040_OR_060) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) int tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) * We need special treatment for the first page, in case it
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) * is not page-aligned. Page align the addresses to work
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) * around bug I17 in the 68060.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) if ((tmp = -paddr & (PAGE_SIZE - 1))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) pushcl040(paddr & PAGE_MASK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) if ((len -= tmp) <= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) paddr += tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) tmp = PAGE_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) paddr &= PAGE_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) while ((len -= tmp) >= 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) clear040(paddr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) paddr += tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) if ((len += tmp))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) /* a page boundary gets crossed at the end */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) pushcl040(paddr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) else /* 68030 or 68020 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) asm volatile ("movec %/cacr,%/d0\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) "oriw %0,%/d0\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) "movec %/d0,%/cacr"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) : : "i" (FLUSH_I_AND_D)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) : "d0");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) #ifdef CONFIG_M68K_L2_CACHE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) if(mach_l2_flush)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) mach_l2_flush(0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) EXPORT_SYMBOL(cache_clear);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) * cache_push() semantics: Write back any dirty cache data in the given area,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) * and invalidate the range in the instruction cache. It needs not (but may)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) * invalidate those entries also in the data cache. The range is defined by a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) * _physical_ address.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) void cache_push (unsigned long paddr, int len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) if (CPU_IS_COLDFIRE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) flush_cf_bcache(0, DCACHE_MAX_ADDR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) } else if (CPU_IS_040_OR_060) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) int tmp = PAGE_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) * on 68040 or 68060, push cache lines for pages in the range;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) * on the '040 this also invalidates the pushed lines, but not on
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) * the '060!
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) len += paddr & (PAGE_SIZE - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) * Work around bug I17 in the 68060 affecting some instruction
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) * lines not being invalidated properly.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) paddr &= PAGE_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) push040(paddr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) paddr += tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) } while ((len -= tmp) > 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) * 68030/68020 have no writeback cache. On the other hand,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) * cache_push is actually a superset of cache_clear (the lines
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) * get written back and invalidated), so we should make sure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) * to perform the corresponding actions. After all, this is getting
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) * called in places where we've just loaded code, or whatever, so
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) * flushing the icache is appropriate; flushing the dcache shouldn't
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) * be required.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) else /* 68030 or 68020 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) asm volatile ("movec %/cacr,%/d0\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) "oriw %0,%/d0\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) "movec %/d0,%/cacr"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) : : "i" (FLUSH_I)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) : "d0");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) #ifdef CONFIG_M68K_L2_CACHE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) if(mach_l2_flush)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) mach_l2_flush(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) EXPORT_SYMBOL(cache_push);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193)