^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) * sc-ip22.c: Indy cache management functions.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (C) 1997, 2001 Ralf Baechle (ralf@gnu.org),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * derived from r4xx0.c by David S. Miller (davem@davemloft.net).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/sched.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/mm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <asm/bcache.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <asm/page.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <asm/bootinfo.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <asm/sgi/ip22.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <asm/sgi/mc.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) /* Secondary cache size in bytes, if present. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) static unsigned long scache_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #undef DEBUG_CACHE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #define SC_SIZE 0x00080000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #define SC_LINE 32
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #define CI_MASK (SC_SIZE - SC_LINE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #define SC_INDEX(n) ((n) & CI_MASK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) static inline void indy_sc_wipe(unsigned long first, unsigned long last)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) unsigned long tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) __asm__ __volatile__(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) " .set push # indy_sc_wipe \n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) " .set noreorder \n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) " .set mips3 \n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) " .set noat \n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) " mfc0 %2, $12 \n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) " li $1, 0x80 # Go 64 bit \n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) " mtc0 $1, $12 \n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) " \n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) " # \n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) " # Open code a dli $1, 0x9000000080000000 \n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) " # \n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) " # Required because binutils 2.25 will happily accept \n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) " # 64 bit instructions in .set mips3 mode but puke on \n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) " # 64 bit constants when generating 32 bit ELF \n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) " # \n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) " lui $1,0x9000 \n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) " dsll $1,$1,0x10 \n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) " ori $1,$1,0x8000 \n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) " dsll $1,$1,0x10 \n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) " \n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) " or %0, $1 # first line to flush \n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) " or %1, $1 # last line to flush \n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) " .set at \n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) " \n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) "1: sw $0, 0(%0) \n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) " bne %0, %1, 1b \n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) " daddu %0, 32 \n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) " \n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) " mtc0 %2, $12 # Back to 32 bit \n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) " nop # pipeline hazard \n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) " nop \n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) " nop \n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) " nop \n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) " .set pop \n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) : "=r" (first), "=r" (last), "=&r" (tmp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) : "0" (first), "1" (last));
^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) static void indy_sc_wback_invalidate(unsigned long addr, unsigned long size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) unsigned long first_line, last_line;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) #ifdef DEBUG_CACHE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) printk("indy_sc_wback_invalidate[%08lx,%08lx]", addr, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) /* Catch bad driver code */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) BUG_ON(size == 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) /* Which lines to flush? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) first_line = SC_INDEX(addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) last_line = SC_INDEX(addr + size - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) local_irq_save(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) if (first_line <= last_line) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) indy_sc_wipe(first_line, last_line);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) indy_sc_wipe(first_line, SC_SIZE - SC_LINE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) indy_sc_wipe(0, last_line);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) local_irq_restore(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) static void indy_sc_enable(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) unsigned long addr, tmp1, tmp2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) /* This is really cool... */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) #ifdef DEBUG_CACHE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) printk("Enabling R4600 SCACHE\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) __asm__ __volatile__(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) ".set\tpush\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) ".set\tnoreorder\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) ".set\tmips3\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) "mfc0\t%2, $12\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) "nop; nop; nop; nop;\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) "li\t%1, 0x80\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) "mtc0\t%1, $12\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) "nop; nop; nop; nop;\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) "li\t%0, 0x1\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) "dsll\t%0, 31\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) "lui\t%1, 0x9000\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) "dsll32\t%1, 0\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) "or\t%0, %1, %0\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) "sb\t$0, 0(%0)\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) "mtc0\t$0, $12\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) "nop; nop; nop; nop;\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) "mtc0\t%2, $12\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) "nop; nop; nop; nop;\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) ".set\tpop"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) : "=r" (tmp1), "=r" (tmp2), "=r" (addr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) static void indy_sc_disable(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) unsigned long tmp1, tmp2, tmp3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) #ifdef DEBUG_CACHE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) printk("Disabling R4600 SCACHE\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) __asm__ __volatile__(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) ".set\tpush\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) ".set\tnoreorder\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) ".set\tmips3\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) "li\t%0, 0x1\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) "dsll\t%0, 31\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) "lui\t%1, 0x9000\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) "dsll32\t%1, 0\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) "or\t%0, %1, %0\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) "mfc0\t%2, $12\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) "nop; nop; nop; nop\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) "li\t%1, 0x80\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) "mtc0\t%1, $12\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) "nop; nop; nop; nop\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) "sh\t$0, 0(%0)\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) "mtc0\t$0, $12\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) "nop; nop; nop; nop\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) "mtc0\t%2, $12\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) "nop; nop; nop; nop\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) ".set\tpop"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) : "=r" (tmp1), "=r" (tmp2), "=r" (tmp3));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) static inline int __init indy_sc_probe(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) unsigned int size = ip22_eeprom_read(&sgimc->eeprom, 17);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) if (size == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) size <<= PAGE_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) printk(KERN_INFO "R4600/R5000 SCACHE size %dK, linesize 32 bytes.\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) size >> 10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) scache_size = size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) /* XXX Check with wje if the Indy caches can differentiate between
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) writeback + invalidate and just invalidate. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) static struct bcache_ops indy_sc_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) .bc_enable = indy_sc_enable,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) .bc_disable = indy_sc_disable,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) .bc_wback_inv = indy_sc_wback_invalidate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) .bc_inv = indy_sc_wback_invalidate
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) void indy_sc_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) if (indy_sc_probe()) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) indy_sc_enable();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) bcops = &indy_sc_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) }