uboot/arch/nds32/lib/cache.c
<<
>>
Prefs
   1/*
   2 * Copyright (C) 2012 Andes Technology Corporation
   3 * Shawn Lin, Andes Technology Corporation <nobuhiro@andestech.com>
   4 * Macpaul Lin, Andes Technology Corporation <macpaul@andestech.com>
   5 *
   6 * SPDX-License-Identifier:     GPL-2.0+
   7 */
   8
   9#include <common.h>
  10#if (!defined(CONFIG_SYS_ICACHE_OFF) || !defined(CONFIG_SYS_DCACHE_OFF))
  11static inline unsigned long CACHE_SET(unsigned char cache)
  12{
  13        if (cache == ICACHE)
  14                return 64 << ((GET_ICM_CFG() & ICM_CFG_MSK_ISET) \
  15                        >> ICM_CFG_OFF_ISET);
  16        else
  17                return 64 << ((GET_DCM_CFG() & DCM_CFG_MSK_DSET) \
  18                        >> DCM_CFG_OFF_DSET);
  19}
  20
  21static inline unsigned long CACHE_WAY(unsigned char cache)
  22{
  23        if (cache == ICACHE)
  24                return 1 + ((GET_ICM_CFG() & ICM_CFG_MSK_IWAY) \
  25                        >> ICM_CFG_OFF_IWAY);
  26        else
  27                return 1 + ((GET_DCM_CFG() & DCM_CFG_MSK_DWAY) \
  28                        >> DCM_CFG_OFF_DWAY);
  29}
  30
  31static inline unsigned long CACHE_LINE_SIZE(enum cache_t cache)
  32{
  33        if (cache == ICACHE)
  34                return 8 << (((GET_ICM_CFG() & ICM_CFG_MSK_ISZ) \
  35                        >> ICM_CFG_OFF_ISZ) - 1);
  36        else
  37                return 8 << (((GET_DCM_CFG() & DCM_CFG_MSK_DSZ) \
  38                        >> DCM_CFG_OFF_DSZ) - 1);
  39}
  40#endif
  41
  42#ifndef CONFIG_SYS_ICACHE_OFF
  43void invalidate_icache_all(void)
  44{
  45        unsigned long end, line_size;
  46        line_size = CACHE_LINE_SIZE(ICACHE);
  47        end = line_size * CACHE_WAY(ICACHE) * CACHE_SET(ICACHE);
  48        do {
  49                end -= line_size;
  50                __asm__ volatile ("\n\tcctl %0, L1I_IX_INVAL" : : "r" (end));
  51
  52                end -= line_size;
  53                __asm__ volatile ("\n\tcctl %0, L1I_IX_INVAL" : : "r" (end));
  54
  55                end -= line_size;
  56                __asm__ volatile ("\n\tcctl %0, L1I_IX_INVAL" : : "r" (end));
  57                end -= line_size;
  58                __asm__ volatile ("\n\tcctl %0, L1I_IX_INVAL" : : "r" (end));
  59        } while (end > 0);
  60}
  61
  62void invalidate_icache_range(unsigned long start, unsigned long end)
  63{
  64        unsigned long line_size;
  65
  66        line_size = CACHE_LINE_SIZE(ICACHE);
  67        while (end > start) {
  68                asm volatile (
  69                        "\n\tcctl %0, L1I_VA_INVAL"
  70                        :
  71                        : "r"(start)
  72                );
  73                start += line_size;
  74        }
  75}
  76
  77void icache_enable(void)
  78{
  79        asm volatile (
  80                "mfsr   $p0, $mr8\n\t"
  81                "ori    $p0, $p0, 0x01\n\t"
  82                "mtsr   $p0, $mr8\n\t"
  83                "isb\n\t"
  84        );
  85}
  86
  87void icache_disable(void)
  88{
  89        asm volatile (
  90                "mfsr   $p0, $mr8\n\t"
  91                "li     $p1, ~0x01\n\t"
  92                "and    $p0, $p0, $p1\n\t"
  93                "mtsr   $p0, $mr8\n\t"
  94                "isb\n\t"
  95        );
  96}
  97
  98int icache_status(void)
  99{
 100        int ret;
 101
 102        asm volatile (
 103                "mfsr   $p0, $mr8\n\t"
 104                "andi   %0,  $p0, 0x01\n\t"
 105                : "=r" (ret)
 106                :
 107                : "memory"
 108        );
 109
 110        return ret;
 111}
 112
 113#else
 114void invalidate_icache_all(void)
 115{
 116}
 117
 118void invalidate_icache_range(unsigned long start, unsigned long end)
 119{
 120}
 121
 122void icache_enable(void)
 123{
 124}
 125
 126void icache_disable(void)
 127{
 128}
 129
 130int icache_status(void)
 131{
 132        return 0;
 133}
 134
 135#endif
 136
 137#ifndef CONFIG_SYS_DCACHE_OFF
 138void dcache_wbinval_all(void)
 139{
 140        unsigned long end, line_size;
 141        line_size = CACHE_LINE_SIZE(DCACHE);
 142        end = line_size * CACHE_WAY(DCACHE) * CACHE_SET(DCACHE);
 143        do {
 144                end -= line_size;
 145                __asm__ volatile ("\n\tcctl %0, L1D_IX_WB" : : "r" (end));
 146                __asm__ volatile ("\n\tcctl %0, L1D_IX_INVAL" : : "r" (end));
 147                end -= line_size;
 148                __asm__ volatile ("\n\tcctl %0, L1D_IX_WB" : : "r" (end));
 149                __asm__ volatile ("\n\tcctl %0, L1D_IX_INVAL" : : "r" (end));
 150                end -= line_size;
 151                __asm__ volatile ("\n\tcctl %0, L1D_IX_WB" : : "r" (end));
 152                __asm__ volatile ("\n\tcctl %0, L1D_IX_INVAL" : : "r" (end));
 153                end -= line_size;
 154                __asm__ volatile ("\n\tcctl %0, L1D_IX_WB" : : "r" (end));
 155                __asm__ volatile ("\n\tcctl %0, L1D_IX_INVAL" : : "r" (end));
 156
 157        } while (end > 0);
 158}
 159
 160void flush_dcache_range(unsigned long start, unsigned long end)
 161{
 162        unsigned long line_size;
 163
 164        line_size = CACHE_LINE_SIZE(DCACHE);
 165
 166        while (end > start) {
 167                asm volatile (
 168                        "\n\tcctl %0, L1D_VA_WB"
 169                        "\n\tcctl %0, L1D_VA_INVAL" : : "r" (start)
 170                );
 171                start += line_size;
 172        }
 173}
 174
 175void invalidate_dcache_range(unsigned long start, unsigned long end)
 176{
 177        unsigned long line_size;
 178
 179        line_size = CACHE_LINE_SIZE(DCACHE);
 180        while (end > start) {
 181                asm volatile (
 182                        "\n\tcctl %0, L1D_VA_INVAL" : : "r"(start)
 183                );
 184                start += line_size;
 185        }
 186}
 187
 188void dcache_enable(void)
 189{
 190        asm volatile (
 191                "mfsr   $p0, $mr8\n\t"
 192                "ori    $p0, $p0, 0x02\n\t"
 193                "mtsr   $p0, $mr8\n\t"
 194                "isb\n\t"
 195        );
 196}
 197
 198void dcache_disable(void)
 199{
 200        asm volatile (
 201                "mfsr   $p0, $mr8\n\t"
 202                "li     $p1, ~0x02\n\t"
 203                "and    $p0, $p0, $p1\n\t"
 204                "mtsr   $p0, $mr8\n\t"
 205                "isb\n\t"
 206        );
 207}
 208
 209int dcache_status(void)
 210{
 211        int ret;
 212        asm volatile (
 213                "mfsr   $p0, $mr8\n\t"
 214                "andi   %0, $p0, 0x02\n\t"
 215                : "=r" (ret)
 216                :
 217                : "memory"
 218        );
 219        return ret;
 220}
 221
 222#else
 223void dcache_wbinval_all(void)
 224{
 225}
 226
 227void flush_dcache_range(unsigned long start, unsigned long end)
 228{
 229}
 230
 231void invalidate_dcache_range(unsigned long start, unsigned long end)
 232{
 233}
 234
 235void dcache_enable(void)
 236{
 237}
 238
 239void dcache_disable(void)
 240{
 241}
 242
 243int dcache_status(void)
 244{
 245        return 0;
 246}
 247
 248#endif
 249
 250
 251void flush_dcache_all(void)
 252{
 253        dcache_wbinval_all();
 254}
 255
 256void cache_flush(void)
 257{
 258        flush_dcache_all();
 259        invalidate_icache_all();
 260}
 261
 262
 263void flush_cache(unsigned long addr, unsigned long size)
 264{
 265        flush_dcache_range(addr, addr + size);
 266        invalidate_icache_range(addr, addr + size);
 267}
 268