Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * Copyright (C) 1997, 2001 Ralf Baechle (ralf@gnu.org),
0004  * derived from r4xx0.c by David S. Miller (davem@davemloft.net).
0005  */
0006 #include <linux/init.h>
0007 #include <linux/kernel.h>
0008 #include <linux/sched.h>
0009 #include <linux/mm.h>
0010 
0011 #include <asm/mipsregs.h>
0012 #include <asm/bcache.h>
0013 #include <asm/cacheops.h>
0014 #include <asm/page.h>
0015 #include <asm/mmu_context.h>
0016 #include <asm/r4kcache.h>
0017 
0018 /* Secondary cache size in bytes, if present.  */
0019 static unsigned long scache_size;
0020 
0021 #define SC_LINE 32
0022 #define SC_PAGE (128*SC_LINE)
0023 
0024 static inline void blast_r5000_scache(void)
0025 {
0026     unsigned long start = INDEX_BASE;
0027     unsigned long end = start + scache_size;
0028 
0029     while(start < end) {
0030         cache_op(R5K_Page_Invalidate_S, start);
0031         start += SC_PAGE;
0032     }
0033 }
0034 
0035 static void r5k_dma_cache_inv_sc(unsigned long addr, unsigned long size)
0036 {
0037     unsigned long end, a;
0038 
0039     /* Catch bad driver code */
0040     BUG_ON(size == 0);
0041 
0042     if (size >= scache_size) {
0043         blast_r5000_scache();
0044         return;
0045     }
0046 
0047     /* On the R5000 secondary cache we cannot
0048      * invalidate less than a page at a time.
0049      * The secondary cache is physically indexed, write-through.
0050      */
0051     a = addr & ~(SC_PAGE - 1);
0052     end = (addr + size - 1) & ~(SC_PAGE - 1);
0053     while (a <= end) {
0054         cache_op(R5K_Page_Invalidate_S, a);
0055         a += SC_PAGE;
0056     }
0057 }
0058 
0059 static void r5k_sc_enable(void)
0060 {
0061     unsigned long flags;
0062 
0063     local_irq_save(flags);
0064     set_c0_config(R5K_CONF_SE);
0065     blast_r5000_scache();
0066     local_irq_restore(flags);
0067 }
0068 
0069 static void r5k_sc_disable(void)
0070 {
0071     unsigned long flags;
0072 
0073     local_irq_save(flags);
0074     blast_r5000_scache();
0075     clear_c0_config(R5K_CONF_SE);
0076     local_irq_restore(flags);
0077 }
0078 
0079 static inline int __init r5k_sc_probe(void)
0080 {
0081     unsigned long config = read_c0_config();
0082 
0083     if (config & CONF_SC)
0084         return 0;
0085 
0086     scache_size = (512 * 1024) << ((config & R5K_CONF_SS) >> 20);
0087 
0088     printk("R5000 SCACHE size %ldkB, linesize 32 bytes.\n",
0089             scache_size >> 10);
0090 
0091     return 1;
0092 }
0093 
0094 static struct bcache_ops r5k_sc_ops = {
0095     .bc_enable = r5k_sc_enable,
0096     .bc_disable = r5k_sc_disable,
0097     .bc_wback_inv = r5k_dma_cache_inv_sc,
0098     .bc_inv = r5k_dma_cache_inv_sc
0099 };
0100 
0101 void r5k_sc_init(void)
0102 {
0103     if (r5k_sc_probe()) {
0104         r5k_sc_enable();
0105         bcops = &r5k_sc_ops;
0106     }
0107 }