uboot/arch/arc/lib/cache.c
<<
>>
Prefs
   1/*
   2 * Copyright (C) 2013-2014 Synopsys, Inc. All rights reserved.
   3 *
   4 * SPDX-License-Identifier:     GPL-2.0+
   5 */
   6
   7#include <config.h>
   8#include <asm/arcregs.h>
   9#include <asm/cache.h>
  10
  11/* Bit values in IC_CTRL */
  12#define IC_CTRL_CACHE_DISABLE   (1 << 0)
  13
  14/* Bit values in DC_CTRL */
  15#define DC_CTRL_CACHE_DISABLE   (1 << 0)
  16#define DC_CTRL_INV_MODE_FLUSH  (1 << 6)
  17#define DC_CTRL_FLUSH_STATUS    (1 << 8)
  18#define CACHE_VER_NUM_MASK      0xF
  19#define SLC_CTRL_SB             (1 << 2)
  20
  21int icache_status(void)
  22{
  23        /* If no cache in CPU exit immediately */
  24        if (!(read_aux_reg(ARC_BCR_IC_BUILD) & CACHE_VER_NUM_MASK))
  25                return 0;
  26
  27        return (read_aux_reg(ARC_AUX_IC_CTRL) & IC_CTRL_CACHE_DISABLE) !=
  28               IC_CTRL_CACHE_DISABLE;
  29}
  30
  31void icache_enable(void)
  32{
  33        /* If no cache in CPU exit immediately */
  34        if (!(read_aux_reg(ARC_BCR_IC_BUILD) & CACHE_VER_NUM_MASK))
  35                return;
  36
  37        write_aux_reg(ARC_AUX_IC_CTRL, read_aux_reg(ARC_AUX_IC_CTRL) &
  38                      ~IC_CTRL_CACHE_DISABLE);
  39}
  40
  41void icache_disable(void)
  42{
  43        /* If no cache in CPU exit immediately */
  44        if (!(read_aux_reg(ARC_BCR_IC_BUILD) & CACHE_VER_NUM_MASK))
  45                return;
  46
  47        write_aux_reg(ARC_AUX_IC_CTRL, read_aux_reg(ARC_AUX_IC_CTRL) |
  48                      IC_CTRL_CACHE_DISABLE);
  49}
  50
  51void invalidate_icache_all(void)
  52{
  53        /* If no cache in CPU exit immediately */
  54        if (!(read_aux_reg(ARC_BCR_IC_BUILD) & CACHE_VER_NUM_MASK))
  55                return;
  56
  57        /* Any write to IC_IVIC register triggers invalidation of entire I$ */
  58        write_aux_reg(ARC_AUX_IC_IVIC, 1);
  59}
  60
  61int dcache_status(void)
  62{
  63        /* If no cache in CPU exit immediately */
  64        if (!(read_aux_reg(ARC_BCR_DC_BUILD) & CACHE_VER_NUM_MASK))
  65                return 0;
  66
  67        return (read_aux_reg(ARC_AUX_DC_CTRL) & DC_CTRL_CACHE_DISABLE) !=
  68                DC_CTRL_CACHE_DISABLE;
  69}
  70
  71void dcache_enable(void)
  72{
  73        /* If no cache in CPU exit immediately */
  74        if (!(read_aux_reg(ARC_BCR_DC_BUILD) & CACHE_VER_NUM_MASK))
  75                return;
  76
  77        write_aux_reg(ARC_AUX_DC_CTRL, read_aux_reg(ARC_AUX_DC_CTRL) &
  78                      ~(DC_CTRL_INV_MODE_FLUSH | DC_CTRL_CACHE_DISABLE));
  79}
  80
  81void dcache_disable(void)
  82{
  83        /* If no cache in CPU exit immediately */
  84        if (!(read_aux_reg(ARC_BCR_DC_BUILD) & CACHE_VER_NUM_MASK))
  85                return;
  86
  87        write_aux_reg(ARC_AUX_DC_CTRL, read_aux_reg(ARC_AUX_DC_CTRL) |
  88                      DC_CTRL_CACHE_DISABLE);
  89}
  90
  91void flush_dcache_all(void)
  92{
  93        /* If no cache in CPU exit immediately */
  94        if (!(read_aux_reg(ARC_BCR_DC_BUILD) & CACHE_VER_NUM_MASK))
  95                return;
  96
  97        /* Do flush of entire cache */
  98        write_aux_reg(ARC_AUX_DC_FLSH, 1);
  99
 100        /* Wait flush end */
 101        while (read_aux_reg(ARC_AUX_DC_CTRL) & DC_CTRL_FLUSH_STATUS)
 102                ;
 103}
 104
 105#ifndef CONFIG_SYS_DCACHE_OFF
 106static void dcache_flush_line(unsigned addr)
 107{
 108#if (CONFIG_ARC_MMU_VER == 3)
 109        write_aux_reg(ARC_AUX_DC_PTAG, addr);
 110#endif
 111        write_aux_reg(ARC_AUX_DC_FLDL, addr);
 112
 113        /* Wait flush end */
 114        while (read_aux_reg(ARC_AUX_DC_CTRL) & DC_CTRL_FLUSH_STATUS)
 115                ;
 116
 117#ifndef CONFIG_SYS_ICACHE_OFF
 118        /*
 119         * Invalidate I$ for addresses range just flushed from D$.
 120         * If we try to execute data flushed above it will be valid/correct
 121         */
 122#if (CONFIG_ARC_MMU_VER == 3)
 123        write_aux_reg(ARC_AUX_IC_PTAG, addr);
 124#endif
 125        write_aux_reg(ARC_AUX_IC_IVIL, addr);
 126#endif /* CONFIG_SYS_ICACHE_OFF */
 127}
 128#endif /* CONFIG_SYS_DCACHE_OFF */
 129
 130void flush_dcache_range(unsigned long start, unsigned long end)
 131{
 132#ifndef CONFIG_SYS_DCACHE_OFF
 133        unsigned int addr;
 134
 135        start = start & (~(CONFIG_SYS_CACHELINE_SIZE - 1));
 136        end = end & (~(CONFIG_SYS_CACHELINE_SIZE - 1));
 137
 138        for (addr = start; addr <= end; addr += CONFIG_SYS_CACHELINE_SIZE)
 139                dcache_flush_line(addr);
 140#endif /* CONFIG_SYS_DCACHE_OFF */
 141}
 142
 143void invalidate_dcache_range(unsigned long start, unsigned long end)
 144{
 145#ifndef CONFIG_SYS_DCACHE_OFF
 146        unsigned int addr;
 147
 148        start = start & (~(CONFIG_SYS_CACHELINE_SIZE - 1));
 149        end = end & (~(CONFIG_SYS_CACHELINE_SIZE - 1));
 150
 151        for (addr = start; addr <= end; addr += CONFIG_SYS_CACHELINE_SIZE) {
 152#if (CONFIG_ARC_MMU_VER == 3)
 153                write_aux_reg(ARC_AUX_DC_PTAG, addr);
 154#endif
 155                write_aux_reg(ARC_AUX_DC_IVDL, addr);
 156        }
 157#endif /* CONFIG_SYS_DCACHE_OFF */
 158}
 159
 160void invalidate_dcache_all(void)
 161{
 162        /* If no cache in CPU exit immediately */
 163        if (!(read_aux_reg(ARC_BCR_DC_BUILD) & CACHE_VER_NUM_MASK))
 164                return;
 165
 166        /* Write 1 to DC_IVDC register triggers invalidation of entire D$ */
 167        write_aux_reg(ARC_AUX_DC_IVDC, 1);
 168}
 169
 170void flush_cache(unsigned long start, unsigned long size)
 171{
 172        flush_dcache_range(start, start + size);
 173}
 174
 175#ifdef CONFIG_ISA_ARCV2
 176void slc_enable(void)
 177{
 178        /* If SLC ver = 0, no SLC present in CPU */
 179        if (!(read_aux_reg(ARC_BCR_SLC) & 0xff))
 180                return;
 181
 182        write_aux_reg(ARC_AUX_SLC_CONTROL,
 183                      read_aux_reg(ARC_AUX_SLC_CONTROL) & ~1);
 184}
 185
 186void slc_disable(void)
 187{
 188        /* If SLC ver = 0, no SLC present in CPU */
 189        if (!(read_aux_reg(ARC_BCR_SLC) & 0xff))
 190                return;
 191
 192        write_aux_reg(ARC_AUX_SLC_CONTROL,
 193                      read_aux_reg(ARC_AUX_SLC_CONTROL) | 1);
 194}
 195
 196void slc_flush(void)
 197{
 198        /* If SLC ver = 0, no SLC present in CPU */
 199        if (!(read_aux_reg(ARC_BCR_SLC) & 0xff))
 200                return;
 201
 202        write_aux_reg(ARC_AUX_SLC_FLUSH, 1);
 203
 204        /* Wait flush end */
 205        while (read_aux_reg(ARC_AUX_SLC_CONTROL) & SLC_CTRL_SB)
 206                ;
 207}
 208
 209void slc_invalidate(void)
 210{
 211        /* If SLC ver = 0, no SLC present in CPU */
 212        if (!(read_aux_reg(ARC_BCR_SLC) & 0xff))
 213                return;
 214
 215        write_aux_reg(ARC_AUX_SLC_INVALIDATE, 1);
 216}
 217
 218#endif /* CONFIG_ISA_ARCV2 */
 219