uboot/arch/blackfin/lib/cache.c
<<
>>
Prefs
   1/*
   2 * U-boot - cache.c
   3 *
   4 * Copyright (c) 2005-2008 Analog Devices Inc.
   5 *
   6 * (C) Copyright 2000-2004
   7 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
   8 *
   9 * Licensed under the GPL-2 or later.
  10 */
  11
  12#include <common.h>
  13#include <asm/blackfin.h>
  14#include <asm/mach-common/bits/mpu.h>
  15
  16void flush_cache(unsigned long addr, unsigned long size)
  17{
  18        void *start_addr, *end_addr;
  19        int istatus, dstatus;
  20
  21        /* no need to flush stuff in on chip memory (L1/L2/etc...) */
  22        if (addr >= 0xE0000000)
  23                return;
  24
  25        start_addr = (void *)addr;
  26        end_addr = (void *)(addr + size);
  27        istatus = icache_status();
  28        dstatus = dcache_status();
  29
  30        if (istatus) {
  31                if (dstatus)
  32                        blackfin_icache_dcache_flush_range(start_addr, end_addr);
  33                else
  34                        blackfin_icache_flush_range(start_addr, end_addr);
  35        } else if (dstatus)
  36                blackfin_dcache_flush_range(start_addr, end_addr);
  37}
  38
  39#ifdef CONFIG_DCACHE_WB
  40static void flushinv_all_dcache(void)
  41{
  42        u32 way, bank, subbank, set;
  43        u32 status, addr;
  44        u32 dmem_ctl = bfin_read_DMEM_CONTROL();
  45
  46        for (bank = 0; bank < 2; ++bank) {
  47                if (!(dmem_ctl & (1 << (DMC1_P - bank))))
  48                        continue;
  49
  50                for (way = 0; way < 2; ++way)
  51                        for (subbank = 0; subbank < 4; ++subbank)
  52                                for (set = 0; set < 64; ++set) {
  53
  54                                        bfin_write_DTEST_COMMAND(
  55                                                way << 26 |
  56                                                bank << 23 |
  57                                                subbank << 16 |
  58                                                set << 5
  59                                        );
  60                                        CSYNC();
  61                                        status = bfin_read_DTEST_DATA0();
  62
  63                                        /* only worry about valid/dirty entries */
  64                                        if ((status & 0x3) != 0x3)
  65                                                continue;
  66
  67                                        /* construct the address using the tag */
  68                                        addr = (status & 0xFFFFC800) | (subbank << 12) | (set << 5);
  69
  70                                        /* flush it */
  71                                        __asm__ __volatile__("FLUSHINV[%0];" : : "a"(addr));
  72                                }
  73        }
  74}
  75#endif
  76
  77void icache_enable(void)
  78{
  79        bfin_write_IMEM_CONTROL(IMC | ENICPLB);
  80        SSYNC();
  81}
  82
  83void icache_disable(void)
  84{
  85        bfin_write_IMEM_CONTROL(0);
  86        SSYNC();
  87}
  88
  89int icache_status(void)
  90{
  91        return bfin_read_IMEM_CONTROL() & IMC;
  92}
  93
  94void dcache_enable(void)
  95{
  96        bfin_write_DMEM_CONTROL(ACACHE_BCACHE | ENDCPLB | PORT_PREF0);
  97        SSYNC();
  98}
  99
 100void dcache_disable(void)
 101{
 102#ifdef CONFIG_DCACHE_WB
 103        bfin_write_DMEM_CONTROL(bfin_read_DMEM_CONTROL() & ~(ENDCPLB));
 104        flushinv_all_dcache();
 105#endif
 106        bfin_write_DMEM_CONTROL(0);
 107        SSYNC();
 108}
 109
 110int dcache_status(void)
 111{
 112        return bfin_read_DMEM_CONTROL() & ACACHE_BCACHE;
 113}
 114