// SPDX-License-Identifier: GPL-2.01/*2* linux/arch/m68k/mm/memory.c3*4* Copyright (C) 1995 Hamish Macdonald5*/67#include <linux/module.h>8#include <linux/mm.h>9#include <linux/kernel.h>10#include <linux/string.h>11#include <linux/types.h>12#include <linux/init.h>13#include <linux/pagemap.h>14#include <linux/gfp.h>1516#include <asm/setup.h>17#include <asm/page.h>18#include <asm/traps.h>19#include <asm/machdep.h>202122/* invalidate page in both caches */23static inline void clear040(unsigned long paddr)24{25asm volatile (26"nop\n\t"27".chip 68040\n\t"28"cinvp %%bc,(%0)\n\t"29".chip 68k"30: : "a" (paddr));31}3233/* invalidate page in i-cache */34static inline void cleari040(unsigned long paddr)35{36asm volatile (37"nop\n\t"38".chip 68040\n\t"39"cinvp %%ic,(%0)\n\t"40".chip 68k"41: : "a" (paddr));42}4344/* push page in both caches */45/* RZ: cpush %bc DOES invalidate %ic, regardless of DPI */46static inline void push040(unsigned long paddr)47{48asm volatile (49"nop\n\t"50".chip 68040\n\t"51"cpushp %%bc,(%0)\n\t"52".chip 68k"53: : "a" (paddr));54}5556/* push and invalidate page in both caches, must disable ints57* to avoid invalidating valid data */58static inline void pushcl040(unsigned long paddr)59{60unsigned long flags;6162local_irq_save(flags);63push040(paddr);64if (CPU_IS_060)65clear040(paddr);66local_irq_restore(flags);67}6869/*70* 040: Hit every page containing an address in the range paddr..paddr+len-1.71* (Low order bits of the ea of a CINVP/CPUSHP are "don't care"s).72* Hit every page until there is a page or less to go. Hit the next page,73* and the one after that if the range hits it.74*/75/* ++roman: A little bit more care is required here: The CINVP instruction76* invalidates cache entries WITHOUT WRITING DIRTY DATA BACK! So the beginning77* and the end of the region must be treated differently if they are not78* exactly at the beginning or end of a page boundary. Else, maybe too much79* data becomes invalidated and thus lost forever. CPUSHP does what we need:80* it invalidates the page after pushing dirty data to memory. (Thanks to Jes81* for discovering the problem!)82*/83/* ... but on the '060, CPUSH doesn't invalidate (for us, since we have set84* the DPI bit in the CACR; would it cause problems with temporarily changing85* this?). So we have to push first and then additionally to invalidate.86*/878889/*90* cache_clear() semantics: Clear any cache entries for the area in question,91* without writing back dirty entries first. This is useful if the data will92* be overwritten anyway, e.g. by DMA to memory. The range is defined by a93* _physical_ address.94*/9596void cache_clear (unsigned long paddr, int len)97{98if (CPU_IS_COLDFIRE) {99clear_cf_bcache(0, DCACHE_MAX_ADDR);100} else if (CPU_IS_040_OR_060) {101int tmp;102103/*104* We need special treatment for the first page, in case it105* is not page-aligned. Page align the addresses to work106* around bug I17 in the 68060.107*/108if ((tmp = -paddr & (PAGE_SIZE - 1))) {109pushcl040(paddr & PAGE_MASK);110if ((len -= tmp) <= 0)111return;112paddr += tmp;113}114tmp = PAGE_SIZE;115paddr &= PAGE_MASK;116while ((len -= tmp) >= 0) {117clear040(paddr);118paddr += tmp;119}120if ((len += tmp))121/* a page boundary gets crossed at the end */122pushcl040(paddr);123}124else /* 68030 or 68020 */125asm volatile ("movec %/cacr,%/d0\n\t"126"oriw %0,%/d0\n\t"127"movec %/d0,%/cacr"128: : "i" (FLUSH_I_AND_D)129: "d0");130#ifdef CONFIG_M68K_L2_CACHE131if(mach_l2_flush)132mach_l2_flush(0);133#endif134}135EXPORT_SYMBOL(cache_clear);136137138/*139* cache_push() semantics: Write back any dirty cache data in the given area,140* and invalidate the range in the instruction cache. It needs not (but may)141* invalidate those entries also in the data cache. The range is defined by a142* _physical_ address.143*/144145void cache_push (unsigned long paddr, int len)146{147if (CPU_IS_COLDFIRE) {148flush_cf_bcache(0, DCACHE_MAX_ADDR);149} else if (CPU_IS_040_OR_060) {150int tmp = PAGE_SIZE;151152/*153* on 68040 or 68060, push cache lines for pages in the range;154* on the '040 this also invalidates the pushed lines, but not on155* the '060!156*/157len += paddr & (PAGE_SIZE - 1);158159/*160* Work around bug I17 in the 68060 affecting some instruction161* lines not being invalidated properly.162*/163paddr &= PAGE_MASK;164165do {166push040(paddr);167paddr += tmp;168} while ((len -= tmp) > 0);169}170/*171* 68030/68020 have no writeback cache. On the other hand,172* cache_push is actually a superset of cache_clear (the lines173* get written back and invalidated), so we should make sure174* to perform the corresponding actions. After all, this is getting175* called in places where we've just loaded code, or whatever, so176* flushing the icache is appropriate; flushing the dcache shouldn't177* be required.178*/179else /* 68030 or 68020 */180asm volatile ("movec %/cacr,%/d0\n\t"181"oriw %0,%/d0\n\t"182"movec %/d0,%/cacr"183: : "i" (FLUSH_I)184: "d0");185#ifdef CONFIG_M68K_L2_CACHE186if(mach_l2_flush)187mach_l2_flush(1);188#endif189}190EXPORT_SYMBOL(cache_push);191192193194