Commit 9318c51acd9689505850152cc98277a6d6f2d752

Authored by Chris Dearman
Committed by Ralf Baechle
1 parent f7a849153b

[MIPS] MIPS32/MIPS64 secondary cache management

Signed-off-by: Chris Dearman <chris@mips.com>
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>

Showing 5 changed files with 168 additions and 7 deletions Side-by-side Diff

... ... @@ -325,6 +325,7 @@
325 325 select I8259
326 326 select MIPS_BOARDS_GEN
327 327 select MIPS_BONITO64
  328 + select MIPS_CPU_SCACHE
328 329 select MIPS_GT64120
329 330 select MIPS_MSC
330 331 select SWAP_IO_SPACE
... ... @@ -1475,6 +1476,13 @@
1475 1476 bool
1476 1477  
1477 1478 config IP22_CPU_SCACHE
  1479 + bool
  1480 + select BOARD_SCACHE
  1481 +
  1482 +#
  1483 +# Support for a MIPS32 / MIPS64 style S-caches
  1484 +#
  1485 +config MIPS_CPU_SCACHE
1478 1486 bool
1479 1487 select BOARD_SCACHE
1480 1488  
arch/mips/kernel/cpu-probe.c
... ... @@ -597,8 +597,6 @@
597 597 break;
598 598 case PRID_IMP_25KF:
599 599 c->cputype = CPU_25KF;
600   - /* Probe for L2 cache */
601   - c->scache.flags &= ~MIPS_CACHE_NOT_PRESENT;
602 600 break;
603 601 case PRID_IMP_34K:
604 602 c->cputype = CPU_34K;
arch/mips/mm/Makefile
... ... @@ -30,6 +30,7 @@
30 30 obj-$(CONFIG_IP22_CPU_SCACHE) += sc-ip22.o
31 31 obj-$(CONFIG_R5000_CPU_SCACHE) += sc-r5k.o
32 32 obj-$(CONFIG_RM7000_CPU_SCACHE) += sc-rm7k.o
  33 +obj-$(CONFIG_MIPS_CPU_SCACHE) += sc-mips.o
33 34  
34 35 #
35 36 # Choose one DMA coherency model
arch/mips/mm/c-r4k.c
... ... @@ -1092,6 +1092,7 @@
1092 1092  
1093 1093 extern int r5k_sc_init(void);
1094 1094 extern int rm7k_sc_init(void);
  1095 +extern int mips_sc_init(void);
1095 1096  
1096 1097 static void __init setup_scache(void)
1097 1098 {
1098 1099  
... ... @@ -1139,16 +1140,28 @@
1139 1140 return;
1140 1141  
1141 1142 default:
  1143 + if (c->isa_level == MIPS_CPU_ISA_M32R1 ||
  1144 + c->isa_level == MIPS_CPU_ISA_M32R2 ||
  1145 + c->isa_level == MIPS_CPU_ISA_M64R1 ||
  1146 + c->isa_level == MIPS_CPU_ISA_M64R2) {
  1147 +#ifdef CONFIG_MIPS_CPU_SCACHE
  1148 + if (mips_sc_init ()) {
  1149 + scache_size = c->scache.ways * c->scache.sets * c->scache.linesz;
  1150 + printk("MIPS secondary cache %ldkB, %s, linesize %d bytes.\n",
  1151 + scache_size >> 10,
  1152 + way_string[c->scache.ways], c->scache.linesz);
  1153 + }
  1154 +#else
  1155 + if (!(c->scache.flags & MIPS_CACHE_NOT_PRESENT))
  1156 + panic("Dunno how to handle MIPS32 / MIPS64 second level cache");
  1157 +#endif
  1158 + return;
  1159 + }
1142 1160 sc_present = 0;
1143 1161 }
1144 1162  
1145 1163 if (!sc_present)
1146 1164 return;
1147   -
1148   - if ((c->isa_level == MIPS_CPU_ISA_M32R1 ||
1149   - c->isa_level == MIPS_CPU_ISA_M64R1) &&
1150   - !(c->scache.flags & MIPS_CACHE_NOT_PRESENT))
1151   - panic("Dunno how to handle MIPS32 / MIPS64 second level cache");
1152 1165  
1153 1166 /* compute a couple of other cache variables */
1154 1167 c->scache.waysize = scache_size / c->scache.ways;
arch/mips/mm/sc-mips.c
  1 +/*
  2 + * Copyright (C) 2006 Chris Dearman (chris@mips.com),
  3 + */
  4 +#include <linux/init.h>
  5 +#include <linux/kernel.h>
  6 +#include <linux/sched.h>
  7 +#include <linux/mm.h>
  8 +
  9 +#include <asm/mipsregs.h>
  10 +#include <asm/bcache.h>
  11 +#include <asm/cacheops.h>
  12 +#include <asm/page.h>
  13 +#include <asm/pgtable.h>
  14 +#include <asm/system.h>
  15 +#include <asm/mmu_context.h>
  16 +#include <asm/r4kcache.h>
  17 +
  18 +/*
  19 + * MIPS32/MIPS64 L2 cache handling
  20 + */
  21 +
  22 +/*
  23 + * Writeback and invalidate the secondary cache before DMA.
  24 + */
  25 +static void mips_sc_wback_inv(unsigned long addr, unsigned long size)
  26 +{
  27 + unsigned long sc_lsize = cpu_scache_line_size();
  28 + unsigned long end, a;
  29 +
  30 + pr_debug("mips_sc_wback_inv[%08lx,%08lx]", addr, size);
  31 +
  32 + /* Catch bad driver code */
  33 + BUG_ON(size == 0);
  34 +
  35 + a = addr & ~(sc_lsize - 1);
  36 + end = (addr + size - 1) & ~(sc_lsize - 1);
  37 + while (1) {
  38 + flush_scache_line(a); /* Hit_Writeback_Inv_SD */
  39 + if (a == end)
  40 + break;
  41 + a += sc_lsize;
  42 + }
  43 +}
  44 +
  45 +/*
  46 + * Invalidate the secondary cache before DMA.
  47 + */
  48 +static void mips_sc_inv(unsigned long addr, unsigned long size)
  49 +{
  50 + unsigned long sc_lsize = cpu_scache_line_size();
  51 + unsigned long end, a;
  52 +
  53 + pr_debug("mips_sc_inv[%08lx,%08lx]", addr, size);
  54 +
  55 + /* Catch bad driver code */
  56 + BUG_ON(size == 0);
  57 +
  58 + a = addr & ~(sc_lsize - 1);
  59 + end = (addr + size - 1) & ~(sc_lsize - 1);
  60 + while (1) {
  61 + invalidate_scache_line(a); /* Hit_Invalidate_SD */
  62 + if (a == end)
  63 + break;
  64 + a += sc_lsize;
  65 + }
  66 +}
  67 +
  68 +static void mips_sc_enable(void)
  69 +{
  70 + /* L2 cache is permanently enabled */
  71 +}
  72 +
  73 +static void mips_sc_disable(void)
  74 +{
  75 + /* L2 cache is permanently enabled */
  76 +}
  77 +
  78 +static struct bcache_ops mips_sc_ops = {
  79 + .bc_enable = mips_sc_enable,
  80 + .bc_disable = mips_sc_disable,
  81 + .bc_wback_inv = mips_sc_wback_inv,
  82 + .bc_inv = mips_sc_inv
  83 +};
  84 +
  85 +static inline int __init mips_sc_probe(void)
  86 +{
  87 + struct cpuinfo_mips *c = &current_cpu_data;
  88 + unsigned int config1, config2;
  89 + unsigned int tmp;
  90 +
  91 + /* Mark as not present until probe completed */
  92 + c->scache.flags |= MIPS_CACHE_NOT_PRESENT;
  93 +
  94 + /* Ignore anything but MIPSxx processors */
  95 + if (c->isa_level != MIPS_CPU_ISA_M32R1 &&
  96 + c->isa_level != MIPS_CPU_ISA_M32R2 &&
  97 + c->isa_level != MIPS_CPU_ISA_M64R1 &&
  98 + c->isa_level != MIPS_CPU_ISA_M64R2)
  99 + return 0;
  100 +
  101 + /* Does this MIPS32/MIPS64 CPU have a config2 register? */
  102 + config1 = read_c0_config1();
  103 + if (!(config1 & MIPS_CONF_M))
  104 + return 0;
  105 +
  106 + config2 = read_c0_config2();
  107 + tmp = (config2 >> 4) & 0x0f;
  108 + if (0 < tmp && tmp <= 7)
  109 + c->scache.linesz = 2 << tmp;
  110 + else
  111 + return 0;
  112 +
  113 + tmp = (config2 >> 8) & 0x0f;
  114 + if (0 <= tmp && tmp <= 7)
  115 + c->scache.sets = 64 << tmp;
  116 + else
  117 + return 0;
  118 +
  119 + tmp = (config2 >> 0) & 0x0f;
  120 + if (0 <= tmp && tmp <= 7)
  121 + c->scache.ways = tmp + 1;
  122 + else
  123 + return 0;
  124 +
  125 + c->scache.waysize = c->scache.sets * c->scache.linesz;
  126 +
  127 + c->scache.flags &= ~MIPS_CACHE_NOT_PRESENT;
  128 +
  129 + return 1;
  130 +}
  131 +
  132 +int __init mips_sc_init(void)
  133 +{
  134 + int found = mips_sc_probe ();
  135 + if (found) {
  136 + mips_sc_enable();
  137 + bcops = &mips_sc_ops;
  138 + }
  139 + return found;
  140 +}