linux/arch/mips/mm/sc-mips.c
<<
>>
Prefs
   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 */
  25static void mips_sc_wback_inv(unsigned long addr, unsigned long size)
  26{
  27        blast_scache_range(addr, addr + size);
  28}
  29
  30/*
  31 * Invalidate the secondary cache before DMA.
  32 */
  33static void mips_sc_inv(unsigned long addr, unsigned long size)
  34{
  35        unsigned long lsize = cpu_scache_line_size();
  36        unsigned long almask = ~(lsize - 1);
  37
  38        cache_op(Hit_Writeback_Inv_SD, addr & almask);
  39        cache_op(Hit_Writeback_Inv_SD, (addr + size - 1) & almask);
  40        blast_inv_scache_range(addr, addr + size);
  41}
  42
  43static void mips_sc_enable(void)
  44{
  45        /* L2 cache is permanently enabled */
  46}
  47
  48static void mips_sc_disable(void)
  49{
  50        /* L2 cache is permanently enabled */
  51}
  52
  53static struct bcache_ops mips_sc_ops = {
  54        .bc_enable = mips_sc_enable,
  55        .bc_disable = mips_sc_disable,
  56        .bc_wback_inv = mips_sc_wback_inv,
  57        .bc_inv = mips_sc_inv
  58};
  59
  60/*
  61 * Check if the L2 cache controller is activated on a particular platform.
  62 * MTI's L2 controller and the L2 cache controller of Broadcom's BMIPS
  63 * cores both use c0_config2's bit 12 as "L2 Bypass" bit, that is the
  64 * cache being disabled.  However there is no guarantee for this to be
  65 * true on all platforms.  In an act of stupidity the spec defined bits
  66 * 12..15 as implementation defined so below function will eventually have
  67 * to be replaced by a platform specific probe.
  68 */
  69static inline int mips_sc_is_activated(struct cpuinfo_mips *c)
  70{
  71        unsigned int config2 = read_c0_config2();
  72        unsigned int tmp;
  73
  74        /* Check the bypass bit (L2B) */
  75        switch (c->cputype) {
  76        case CPU_34K:
  77        case CPU_74K:
  78        case CPU_1004K:
  79        case CPU_BMIPS5000:
  80                if (config2 & (1 << 12))
  81                        return 0;
  82        }
  83
  84        tmp = (config2 >> 4) & 0x0f;
  85        if (0 < tmp && tmp <= 7)
  86                c->scache.linesz = 2 << tmp;
  87        else
  88                return 0;
  89        return 1;
  90}
  91
  92static inline int __init mips_sc_probe(void)
  93{
  94        struct cpuinfo_mips *c = &current_cpu_data;
  95        unsigned int config1, config2;
  96        unsigned int tmp;
  97
  98        /* Mark as not present until probe completed */
  99        c->scache.flags |= MIPS_CACHE_NOT_PRESENT;
 100
 101        /* Ignore anything but MIPSxx processors */
 102        if (c->isa_level != MIPS_CPU_ISA_M32R1 &&
 103            c->isa_level != MIPS_CPU_ISA_M32R2 &&
 104            c->isa_level != MIPS_CPU_ISA_M64R1 &&
 105            c->isa_level != MIPS_CPU_ISA_M64R2)
 106                return 0;
 107
 108        /* Does this MIPS32/MIPS64 CPU have a config2 register? */
 109        config1 = read_c0_config1();
 110        if (!(config1 & MIPS_CONF_M))
 111                return 0;
 112
 113        config2 = read_c0_config2();
 114
 115        if (!mips_sc_is_activated(c))
 116                return 0;
 117
 118        tmp = (config2 >> 8) & 0x0f;
 119        if (0 <= tmp && tmp <= 7)
 120                c->scache.sets = 64 << tmp;
 121        else
 122                return 0;
 123
 124        tmp = (config2 >> 0) & 0x0f;
 125        if (0 <= tmp && tmp <= 7)
 126                c->scache.ways = tmp + 1;
 127        else
 128                return 0;
 129
 130        c->scache.waysize = c->scache.sets * c->scache.linesz;
 131        c->scache.waybit = __ffs(c->scache.waysize);
 132
 133        c->scache.flags &= ~MIPS_CACHE_NOT_PRESENT;
 134
 135        return 1;
 136}
 137
 138int __cpuinit mips_sc_init(void)
 139{
 140        int found = mips_sc_probe();
 141        if (found) {
 142                mips_sc_enable();
 143                bcops = &mips_sc_ops;
 144        }
 145        return found;
 146}
 147