linux/arch/mips/mm/sc-mips.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * Copyright (C) 2006 Chris Dearman (chris@mips.com),
   4 */
   5#include <linux/init.h>
   6#include <linux/kernel.h>
   7#include <linux/sched.h>
   8#include <linux/mm.h>
   9
  10#include <asm/cpu-type.h>
  11#include <asm/mipsregs.h>
  12#include <asm/bcache.h>
  13#include <asm/cacheops.h>
  14#include <asm/page.h>
  15#include <asm/pgtable.h>
  16#include <asm/mmu_context.h>
  17#include <asm/r4kcache.h>
  18#include <asm/mips-cps.h>
  19#include <asm/bootinfo.h>
  20
  21/*
  22 * MIPS32/MIPS64 L2 cache handling
  23 */
  24
  25/*
  26 * Writeback and invalidate the secondary cache before DMA.
  27 */
  28static void mips_sc_wback_inv(unsigned long addr, unsigned long size)
  29{
  30        blast_scache_range(addr, addr + size);
  31}
  32
  33/*
  34 * Invalidate the secondary cache before DMA.
  35 */
  36static void mips_sc_inv(unsigned long addr, unsigned long size)
  37{
  38        unsigned long lsize = cpu_scache_line_size();
  39        unsigned long almask = ~(lsize - 1);
  40
  41        cache_op(Hit_Writeback_Inv_SD, addr & almask);
  42        cache_op(Hit_Writeback_Inv_SD, (addr + size - 1) & almask);
  43        blast_inv_scache_range(addr, addr + size);
  44}
  45
  46static void mips_sc_enable(void)
  47{
  48        /* L2 cache is permanently enabled */
  49}
  50
  51static void mips_sc_disable(void)
  52{
  53        /* L2 cache is permanently enabled */
  54}
  55
  56static void mips_sc_prefetch_enable(void)
  57{
  58        unsigned long pftctl;
  59
  60        if (mips_cm_revision() < CM_REV_CM2_5)
  61                return;
  62
  63        /*
  64         * If there is one or more L2 prefetch unit present then enable
  65         * prefetching for both code & data, for all ports.
  66         */
  67        pftctl = read_gcr_l2_pft_control();
  68        if (pftctl & CM_GCR_L2_PFT_CONTROL_NPFT) {
  69                pftctl &= ~CM_GCR_L2_PFT_CONTROL_PAGEMASK;
  70                pftctl |= PAGE_MASK & CM_GCR_L2_PFT_CONTROL_PAGEMASK;
  71                pftctl |= CM_GCR_L2_PFT_CONTROL_PFTEN;
  72                write_gcr_l2_pft_control(pftctl);
  73
  74                set_gcr_l2_pft_control_b(CM_GCR_L2_PFT_CONTROL_B_PORTID |
  75                                         CM_GCR_L2_PFT_CONTROL_B_CEN);
  76        }
  77}
  78
  79static void mips_sc_prefetch_disable(void)
  80{
  81        if (mips_cm_revision() < CM_REV_CM2_5)
  82                return;
  83
  84        clear_gcr_l2_pft_control(CM_GCR_L2_PFT_CONTROL_PFTEN);
  85        clear_gcr_l2_pft_control_b(CM_GCR_L2_PFT_CONTROL_B_PORTID |
  86                                   CM_GCR_L2_PFT_CONTROL_B_CEN);
  87}
  88
  89static bool mips_sc_prefetch_is_enabled(void)
  90{
  91        unsigned long pftctl;
  92
  93        if (mips_cm_revision() < CM_REV_CM2_5)
  94                return false;
  95
  96        pftctl = read_gcr_l2_pft_control();
  97        if (!(pftctl & CM_GCR_L2_PFT_CONTROL_NPFT))
  98                return false;
  99        return !!(pftctl & CM_GCR_L2_PFT_CONTROL_PFTEN);
 100}
 101
 102static struct bcache_ops mips_sc_ops = {
 103        .bc_enable = mips_sc_enable,
 104        .bc_disable = mips_sc_disable,
 105        .bc_wback_inv = mips_sc_wback_inv,
 106        .bc_inv = mips_sc_inv,
 107        .bc_prefetch_enable = mips_sc_prefetch_enable,
 108        .bc_prefetch_disable = mips_sc_prefetch_disable,
 109        .bc_prefetch_is_enabled = mips_sc_prefetch_is_enabled,
 110};
 111
 112/*
 113 * Check if the L2 cache controller is activated on a particular platform.
 114 * MTI's L2 controller and the L2 cache controller of Broadcom's BMIPS
 115 * cores both use c0_config2's bit 12 as "L2 Bypass" bit, that is the
 116 * cache being disabled.  However there is no guarantee for this to be
 117 * true on all platforms.  In an act of stupidity the spec defined bits
 118 * 12..15 as implementation defined so below function will eventually have
 119 * to be replaced by a platform specific probe.
 120 */
 121static inline int mips_sc_is_activated(struct cpuinfo_mips *c)
 122{
 123        unsigned int config2 = read_c0_config2();
 124        unsigned int tmp;
 125
 126        /* Check the bypass bit (L2B) */
 127        switch (current_cpu_type()) {
 128        case CPU_34K:
 129        case CPU_74K:
 130        case CPU_1004K:
 131        case CPU_1074K:
 132        case CPU_INTERAPTIV:
 133        case CPU_PROAPTIV:
 134        case CPU_P5600:
 135        case CPU_BMIPS5000:
 136        case CPU_QEMU_GENERIC:
 137        case CPU_P6600:
 138                if (config2 & (1 << 12))
 139                        return 0;
 140        }
 141
 142        tmp = (config2 >> 4) & 0x0f;
 143        if (0 < tmp && tmp <= 7)
 144                c->scache.linesz = 2 << tmp;
 145        else
 146                return 0;
 147        return 1;
 148}
 149
 150static int __init mips_sc_probe_cm3(void)
 151{
 152        struct cpuinfo_mips *c = &current_cpu_data;
 153        unsigned long cfg = read_gcr_l2_config();
 154        unsigned long sets, line_sz, assoc;
 155
 156        if (cfg & CM_GCR_L2_CONFIG_BYPASS)
 157                return 0;
 158
 159        sets = cfg & CM_GCR_L2_CONFIG_SET_SIZE;
 160        sets >>= __ffs(CM_GCR_L2_CONFIG_SET_SIZE);
 161        if (sets)
 162                c->scache.sets = 64 << sets;
 163
 164        line_sz = cfg & CM_GCR_L2_CONFIG_LINE_SIZE;
 165        line_sz >>= __ffs(CM_GCR_L2_CONFIG_LINE_SIZE);
 166        if (line_sz)
 167                c->scache.linesz = 2 << line_sz;
 168
 169        assoc = cfg & CM_GCR_L2_CONFIG_ASSOC;
 170        assoc >>= __ffs(CM_GCR_L2_CONFIG_ASSOC);
 171        c->scache.ways = assoc + 1;
 172        c->scache.waysize = c->scache.sets * c->scache.linesz;
 173        c->scache.waybit = __ffs(c->scache.waysize);
 174
 175        if (c->scache.linesz) {
 176                c->scache.flags &= ~MIPS_CACHE_NOT_PRESENT;
 177                c->options |= MIPS_CPU_INCLUSIVE_CACHES;
 178                return 1;
 179        }
 180
 181        return 0;
 182}
 183
 184static inline int __init mips_sc_probe(void)
 185{
 186        struct cpuinfo_mips *c = &current_cpu_data;
 187        unsigned int config1, config2;
 188        unsigned int tmp;
 189
 190        /* Mark as not present until probe completed */
 191        c->scache.flags |= MIPS_CACHE_NOT_PRESENT;
 192
 193        if (mips_cm_revision() >= CM_REV_CM3)
 194                return mips_sc_probe_cm3();
 195
 196        /* Ignore anything but MIPSxx processors */
 197        if (!(c->isa_level & (MIPS_CPU_ISA_M32R1 | MIPS_CPU_ISA_M32R2 |
 198                              MIPS_CPU_ISA_M32R6 | MIPS_CPU_ISA_M64R1 |
 199                              MIPS_CPU_ISA_M64R2 | MIPS_CPU_ISA_M64R6)))
 200                return 0;
 201
 202        /* Does this MIPS32/MIPS64 CPU have a config2 register? */
 203        config1 = read_c0_config1();
 204        if (!(config1 & MIPS_CONF_M))
 205                return 0;
 206
 207        config2 = read_c0_config2();
 208
 209        if (!mips_sc_is_activated(c))
 210                return 0;
 211
 212        tmp = (config2 >> 8) & 0x0f;
 213        if (tmp <= 7)
 214                c->scache.sets = 64 << tmp;
 215        else
 216                return 0;
 217
 218        tmp = (config2 >> 0) & 0x0f;
 219        if (tmp <= 7)
 220                c->scache.ways = tmp + 1;
 221        else
 222                return 0;
 223
 224        /*
 225         * According to config2 it would be 5-ways, but that is contradicted
 226         * by all documentation.
 227         */
 228        if (current_cpu_type() == CPU_JZRISC &&
 229                                mips_machtype == MACH_INGENIC_JZ4770)
 230                c->scache.ways = 4;
 231
 232        c->scache.waysize = c->scache.sets * c->scache.linesz;
 233        c->scache.waybit = __ffs(c->scache.waysize);
 234
 235        c->scache.flags &= ~MIPS_CACHE_NOT_PRESENT;
 236
 237        return 1;
 238}
 239
 240int mips_sc_init(void)
 241{
 242        int found = mips_sc_probe();
 243        if (found) {
 244                mips_sc_enable();
 245                mips_sc_prefetch_enable();
 246                bcops = &mips_sc_ops;
 247        }
 248        return found;
 249}
 250