Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^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)