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