^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) * Copyright (C) 1997, 2001 Ralf Baechle (ralf@gnu.org),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * derived from r4xx0.c by David S. Miller (davem@davemloft.net).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <linux/sched.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)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <asm/mipsregs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <asm/bcache.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <asm/cacheops.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/mmu_context.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <asm/r4kcache.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) /* Secondary cache size in bytes, if present. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) static unsigned long scache_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #define SC_LINE 32
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #define SC_PAGE (128*SC_LINE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) static inline void blast_r5000_scache(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) unsigned long start = INDEX_BASE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) unsigned long end = start + scache_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) while(start < end) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) cache_op(R5K_Page_Invalidate_S, start);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) start += SC_PAGE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) }
^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) static void r5k_dma_cache_inv_sc(unsigned long addr, unsigned long size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) unsigned long end, a;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) /* Catch bad driver code */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) BUG_ON(size == 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) if (size >= scache_size) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) blast_r5000_scache();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) /* On the R5000 secondary cache we cannot
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) * invalidate less than a page at a time.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) * The secondary cache is physically indexed, write-through.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) a = addr & ~(SC_PAGE - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) end = (addr + size - 1) & ~(SC_PAGE - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) while (a <= end) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) cache_op(R5K_Page_Invalidate_S, a);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) a += SC_PAGE;
^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)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) static void r5k_sc_enable(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) local_irq_save(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) set_c0_config(R5K_CONF_SE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) blast_r5000_scache();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) local_irq_restore(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) static void r5k_sc_disable(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) local_irq_save(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) blast_r5000_scache();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) clear_c0_config(R5K_CONF_SE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) local_irq_restore(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) static inline int __init r5k_sc_probe(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) unsigned long config = read_c0_config();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) if (config & CONF_SC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) scache_size = (512 * 1024) << ((config & R5K_CONF_SS) >> 20);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) printk("R5000 SCACHE size %ldkB, linesize 32 bytes.\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) scache_size >> 10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) return 1;
^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) static struct bcache_ops r5k_sc_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) .bc_enable = r5k_sc_enable,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) .bc_disable = r5k_sc_disable,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) .bc_wback_inv = r5k_dma_cache_inv_sc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) .bc_inv = r5k_dma_cache_inv_sc
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) void r5k_sc_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) if (r5k_sc_probe()) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) r5k_sc_enable();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) bcops = &r5k_sc_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) }