linux/arch/metag/include/asm/l2cache.h
<<
>>
Prefs
   1/* SPDX-License-Identifier: GPL-2.0 */
   2#ifndef _METAG_L2CACHE_H
   3#define _METAG_L2CACHE_H
   4
   5#ifdef CONFIG_METAG_L2C
   6
   7#include <asm/global_lock.h>
   8#include <asm/io.h>
   9
  10/*
  11 * Store the last known value of pfenable (we don't want prefetch enabled while
  12 * L2 is off).
  13 */
  14extern int l2c_pfenable;
  15
  16/* defined in arch/metag/drivers/core-sysfs.c */
  17extern struct sysdev_class cache_sysclass;
  18
  19static inline void wr_fence(void);
  20
  21/*
  22 * Functions for reading of L2 cache configuration.
  23 */
  24
  25/* Get raw L2 config register (CORE_CONFIG3) */
  26static inline unsigned int meta_l2c_config(void)
  27{
  28        const unsigned int *corecfg3 = (const unsigned int *)METAC_CORE_CONFIG3;
  29        return *corecfg3;
  30}
  31
  32/* Get whether the L2 is present */
  33static inline int meta_l2c_is_present(void)
  34{
  35        return meta_l2c_config() & METAC_CORECFG3_L2C_HAVE_L2C_BIT;
  36}
  37
  38/* Get whether the L2 is configured for write-back instead of write-through */
  39static inline int meta_l2c_is_writeback(void)
  40{
  41        return meta_l2c_config() & METAC_CORECFG3_L2C_MODE_BIT;
  42}
  43
  44/* Get whether the L2 is unified instead of separated code/data */
  45static inline int meta_l2c_is_unified(void)
  46{
  47        return meta_l2c_config() & METAC_CORECFG3_L2C_UNIFIED_BIT;
  48}
  49
  50/* Get the L2 cache size in bytes */
  51static inline unsigned int meta_l2c_size(void)
  52{
  53        unsigned int size_s;
  54        if (!meta_l2c_is_present())
  55                return 0;
  56        size_s = (meta_l2c_config() & METAC_CORECFG3_L2C_SIZE_BITS)
  57                        >> METAC_CORECFG3_L2C_SIZE_S;
  58        /* L2CSIZE is in KiB */
  59        return 1024 << size_s;
  60}
  61
  62/* Get the number of ways in the L2 cache */
  63static inline unsigned int meta_l2c_ways(void)
  64{
  65        unsigned int ways_s;
  66        if (!meta_l2c_is_present())
  67                return 0;
  68        ways_s = (meta_l2c_config() & METAC_CORECFG3_L2C_NUM_WAYS_BITS)
  69                        >> METAC_CORECFG3_L2C_NUM_WAYS_S;
  70        return 0x1 << ways_s;
  71}
  72
  73/* Get the line size of the L2 cache */
  74static inline unsigned int meta_l2c_linesize(void)
  75{
  76        unsigned int line_size;
  77        if (!meta_l2c_is_present())
  78                return 0;
  79        line_size = (meta_l2c_config() & METAC_CORECFG3_L2C_LINE_SIZE_BITS)
  80                        >> METAC_CORECFG3_L2C_LINE_SIZE_S;
  81        switch (line_size) {
  82        case METAC_CORECFG3_L2C_LINE_SIZE_64B:
  83                return 64;
  84        default:
  85                return 0;
  86        }
  87}
  88
  89/* Get the revision ID of the L2 cache */
  90static inline unsigned int meta_l2c_revision(void)
  91{
  92        return (meta_l2c_config() & METAC_CORECFG3_L2C_REV_ID_BITS)
  93                        >> METAC_CORECFG3_L2C_REV_ID_S;
  94}
  95
  96
  97/*
  98 * Start an initialisation of the L2 cachelines and wait for completion.
  99 * This should only be done in a LOCK1 or LOCK2 critical section while the L2
 100 * is disabled.
 101 */
 102static inline void _meta_l2c_init(void)
 103{
 104        metag_out32(SYSC_L2C_INIT_INIT, SYSC_L2C_INIT);
 105        while (metag_in32(SYSC_L2C_INIT) == SYSC_L2C_INIT_IN_PROGRESS)
 106                /* do nothing */;
 107}
 108
 109/*
 110 * Start a writeback of dirty L2 cachelines and wait for completion.
 111 * This should only be done in a LOCK1 or LOCK2 critical section.
 112 */
 113static inline void _meta_l2c_purge(void)
 114{
 115        metag_out32(SYSC_L2C_PURGE_PURGE, SYSC_L2C_PURGE);
 116        while (metag_in32(SYSC_L2C_PURGE) == SYSC_L2C_PURGE_IN_PROGRESS)
 117                /* do nothing */;
 118}
 119
 120/* Set whether the L2 cache is enabled. */
 121static inline void _meta_l2c_enable(int enabled)
 122{
 123        unsigned int enable;
 124
 125        enable = metag_in32(SYSC_L2C_ENABLE);
 126        if (enabled)
 127                enable |= SYSC_L2C_ENABLE_ENABLE_BIT;
 128        else
 129                enable &= ~SYSC_L2C_ENABLE_ENABLE_BIT;
 130        metag_out32(enable, SYSC_L2C_ENABLE);
 131}
 132
 133/* Set whether the L2 cache prefetch is enabled. */
 134static inline void _meta_l2c_pf_enable(int pfenabled)
 135{
 136        unsigned int enable;
 137
 138        enable = metag_in32(SYSC_L2C_ENABLE);
 139        if (pfenabled)
 140                enable |= SYSC_L2C_ENABLE_PFENABLE_BIT;
 141        else
 142                enable &= ~SYSC_L2C_ENABLE_PFENABLE_BIT;
 143        metag_out32(enable, SYSC_L2C_ENABLE);
 144}
 145
 146/* Return whether the L2 cache is enabled */
 147static inline int _meta_l2c_is_enabled(void)
 148{
 149        return metag_in32(SYSC_L2C_ENABLE) & SYSC_L2C_ENABLE_ENABLE_BIT;
 150}
 151
 152/* Return whether the L2 cache prefetch is enabled */
 153static inline int _meta_l2c_pf_is_enabled(void)
 154{
 155        return metag_in32(SYSC_L2C_ENABLE) & SYSC_L2C_ENABLE_PFENABLE_BIT;
 156}
 157
 158
 159/* Return whether the L2 cache is enabled */
 160static inline int meta_l2c_is_enabled(void)
 161{
 162        int en;
 163
 164        /*
 165         * There is no need to lock at the moment, as the enable bit is never
 166         * intermediately changed, so we will never see an intermediate result.
 167         */
 168        en = _meta_l2c_is_enabled();
 169
 170        return en;
 171}
 172
 173/*
 174 * Ensure the L2 cache is disabled.
 175 * Return whether the L2 was previously disabled.
 176 */
 177int meta_l2c_disable(void);
 178
 179/*
 180 * Ensure the L2 cache is enabled.
 181 * Return whether the L2 was previously enabled.
 182 */
 183int meta_l2c_enable(void);
 184
 185/* Return whether the L2 cache prefetch is enabled */
 186static inline int meta_l2c_pf_is_enabled(void)
 187{
 188        return l2c_pfenable;
 189}
 190
 191/*
 192 * Set whether the L2 cache prefetch is enabled.
 193 * Return whether the L2 prefetch was previously enabled.
 194 */
 195int meta_l2c_pf_enable(int pfenable);
 196
 197/*
 198 * Flush the L2 cache.
 199 * Return 1 if the L2 is disabled.
 200 */
 201int meta_l2c_flush(void);
 202
 203/*
 204 * Write back all dirty cache lines in the L2 cache.
 205 * Return 1 if the L2 is disabled or there isn't any writeback.
 206 */
 207static inline int meta_l2c_writeback(void)
 208{
 209        unsigned long flags;
 210        int en;
 211
 212        /* no need to purge if it's not a writeback cache */
 213        if (!meta_l2c_is_writeback())
 214                return 1;
 215
 216        /*
 217         * Purge only works if the L2 is enabled, and involves reading back to
 218         * detect completion, so keep this operation atomic with other threads.
 219         */
 220        __global_lock1(flags);
 221        en = meta_l2c_is_enabled();
 222        if (likely(en)) {
 223                wr_fence();
 224                _meta_l2c_purge();
 225        }
 226        __global_unlock1(flags);
 227
 228        return !en;
 229}
 230
 231#else /* CONFIG_METAG_L2C */
 232
 233#define meta_l2c_config()               0
 234#define meta_l2c_is_present()           0
 235#define meta_l2c_is_writeback()         0
 236#define meta_l2c_is_unified()           0
 237#define meta_l2c_size()                 0
 238#define meta_l2c_ways()                 0
 239#define meta_l2c_linesize()             0
 240#define meta_l2c_revision()             0
 241
 242#define meta_l2c_is_enabled()           0
 243#define _meta_l2c_pf_is_enabled()       0
 244#define meta_l2c_pf_is_enabled()        0
 245#define meta_l2c_disable()              1
 246#define meta_l2c_enable()               0
 247#define meta_l2c_pf_enable(X)           0
 248static inline int meta_l2c_flush(void)
 249{
 250        return 1;
 251}
 252static inline int meta_l2c_writeback(void)
 253{
 254        return 1;
 255}
 256
 257#endif /* CONFIG_METAG_L2C */
 258
 259#endif /* _METAG_L2CACHE_H */
 260