linux/arch/metag/mm/l2cache.c
<<
>>
Prefs
   1#include <linux/init.h>
   2#include <linux/kernel.h>
   3#include <linux/delay.h>
   4
   5#include <asm/l2cache.h>
   6#include <asm/metag_isa.h>
   7
   8/* If non-0, then initialise the L2 cache */
   9static int l2cache_init = 1;
  10/* If non-0, then initialise the L2 cache prefetch */
  11static int l2cache_init_pf = 1;
  12
  13int l2c_pfenable;
  14
  15static volatile u32 l2c_testdata[16] __initdata __aligned(64);
  16
  17static int __init parse_l2cache(char *p)
  18{
  19        char *cp = p;
  20
  21        if (get_option(&cp, &l2cache_init) != 1) {
  22                pr_err("Bad l2cache parameter (%s)\n", p);
  23                return 1;
  24        }
  25        return 0;
  26}
  27early_param("l2cache", parse_l2cache);
  28
  29static int __init parse_l2cache_pf(char *p)
  30{
  31        char *cp = p;
  32
  33        if (get_option(&cp, &l2cache_init_pf) != 1) {
  34                pr_err("Bad l2cache_pf parameter (%s)\n", p);
  35                return 1;
  36        }
  37        return 0;
  38}
  39early_param("l2cache_pf", parse_l2cache_pf);
  40
  41static int __init meta_l2c_setup(void)
  42{
  43        /*
  44         * If the L2 cache isn't even present, don't do anything, but say so in
  45         * the log.
  46         */
  47        if (!meta_l2c_is_present()) {
  48                pr_info("L2 Cache: Not present\n");
  49                return 0;
  50        }
  51
  52        /*
  53         * Check whether the line size is recognised.
  54         */
  55        if (!meta_l2c_linesize()) {
  56                pr_warn_once("L2 Cache: unknown line size id (config=0x%08x)\n",
  57                             meta_l2c_config());
  58        }
  59
  60        /*
  61         * Initialise state.
  62         */
  63        l2c_pfenable = _meta_l2c_pf_is_enabled();
  64
  65        /*
  66         * Enable the L2 cache and print to log whether it was already enabled
  67         * by the bootloader.
  68         */
  69        if (l2cache_init) {
  70                pr_info("L2 Cache: Enabling... ");
  71                if (meta_l2c_enable())
  72                        pr_cont("already enabled\n");
  73                else
  74                        pr_cont("done\n");
  75        } else {
  76                pr_info("L2 Cache: Not enabling\n");
  77        }
  78
  79        /*
  80         * Enable L2 cache prefetch.
  81         */
  82        if (l2cache_init_pf) {
  83                pr_info("L2 Cache: Enabling prefetch... ");
  84                if (meta_l2c_pf_enable(1))
  85                        pr_cont("already enabled\n");
  86                else
  87                        pr_cont("done\n");
  88        } else {
  89                pr_info("L2 Cache: Not enabling prefetch\n");
  90        }
  91
  92        return 0;
  93}
  94core_initcall(meta_l2c_setup);
  95
  96int meta_l2c_disable(void)
  97{
  98        unsigned long flags;
  99        int en;
 100
 101        if (!meta_l2c_is_present())
 102                return 1;
 103
 104        /*
 105         * Prevent other threads writing during the writeback, otherwise the
 106         * writes will get "lost" when the L2 is disabled.
 107         */
 108        __global_lock2(flags);
 109        en = meta_l2c_is_enabled();
 110        if (likely(en)) {
 111                _meta_l2c_pf_enable(0);
 112                wr_fence();
 113                _meta_l2c_purge();
 114                _meta_l2c_enable(0);
 115        }
 116        __global_unlock2(flags);
 117
 118        return !en;
 119}
 120
 121int meta_l2c_enable(void)
 122{
 123        unsigned long flags;
 124        int en;
 125
 126        if (!meta_l2c_is_present())
 127                return 0;
 128
 129        /*
 130         * Init (clearing the L2) can happen while the L2 is disabled, so other
 131         * threads are safe to continue executing, however we must not init the
 132         * cache if it's already enabled (dirty lines would be discarded), so
 133         * this operation should still be atomic with other threads.
 134         */
 135        __global_lock1(flags);
 136        en = meta_l2c_is_enabled();
 137        if (likely(!en)) {
 138                _meta_l2c_init();
 139                _meta_l2c_enable(1);
 140                _meta_l2c_pf_enable(l2c_pfenable);
 141        }
 142        __global_unlock1(flags);
 143
 144        return en;
 145}
 146
 147int meta_l2c_pf_enable(int pfenable)
 148{
 149        unsigned long flags;
 150        int en = l2c_pfenable;
 151
 152        if (!meta_l2c_is_present())
 153                return 0;
 154
 155        /*
 156         * We read modify write the enable register, so this operation must be
 157         * atomic with other threads.
 158         */
 159        __global_lock1(flags);
 160        en = l2c_pfenable;
 161        l2c_pfenable = pfenable;
 162        if (meta_l2c_is_enabled())
 163                _meta_l2c_pf_enable(pfenable);
 164        __global_unlock1(flags);
 165
 166        return en;
 167}
 168
 169int meta_l2c_flush(void)
 170{
 171        unsigned long flags;
 172        int en;
 173
 174        /*
 175         * Prevent other threads writing during the writeback. This also
 176         * involves read modify writes.
 177         */
 178        __global_lock2(flags);
 179        en = meta_l2c_is_enabled();
 180        if (likely(en)) {
 181                _meta_l2c_pf_enable(0);
 182                wr_fence();
 183                _meta_l2c_purge();
 184                _meta_l2c_enable(0);
 185                _meta_l2c_init();
 186                _meta_l2c_enable(1);
 187                _meta_l2c_pf_enable(l2c_pfenable);
 188        }
 189        __global_unlock2(flags);
 190
 191        return !en;
 192}
 193