uboot/arch/arm/lib/cache-cp15.c
<<
>>
Prefs
   1/*
   2 * (C) Copyright 2002
   3 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
   4 *
   5 * See file CREDITS for list of people who contributed to this
   6 * project.
   7 *
   8 * This program is free software; you can redistribute it and/or
   9 * modify it under the terms of the GNU General Public License as
  10 * published by the Free Software Foundation; either version 2 of
  11 * the License, or (at your option) any later version.
  12 *
  13 * This program is distributed in the hope that it will be useful,
  14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16 * GNU General Public License for more details.
  17 *
  18 * You should have received a copy of the GNU General Public License
  19 * along with this program; if not, write to the Free Software
  20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  21 * MA 02111-1307 USA
  22 */
  23
  24#include <common.h>
  25#include <asm/system.h>
  26
  27#if !(defined(CONFIG_SYS_ICACHE_OFF) && defined(CONFIG_SYS_DCACHE_OFF))
  28
  29#if defined(CONFIG_SYS_ARM_CACHE_WRITETHROUGH)
  30#define CACHE_SETUP     0x1a
  31#else
  32#define CACHE_SETUP     0x1e
  33#endif
  34
  35DECLARE_GLOBAL_DATA_PTR;
  36
  37void __arm_init_before_mmu(void)
  38{
  39}
  40void arm_init_before_mmu(void)
  41        __attribute__((weak, alias("__arm_init_before_mmu")));
  42
  43static void cp_delay (void)
  44{
  45        volatile int i;
  46
  47        /* copro seems to need some delay between reading and writing */
  48        for (i = 0; i < 100; i++)
  49                nop();
  50        asm volatile("" : : : "memory");
  51}
  52
  53static inline void dram_bank_mmu_setup(int bank)
  54{
  55        u32 *page_table = (u32 *)gd->tlb_addr;
  56        bd_t *bd = gd->bd;
  57        int     i;
  58
  59        debug("%s: bank: %d\n", __func__, bank);
  60        for (i = bd->bi_dram[bank].start >> 20;
  61             i < (bd->bi_dram[bank].start + bd->bi_dram[bank].size) >> 20;
  62             i++) {
  63                page_table[i] = i << 20 | (3 << 10) | CACHE_SETUP;
  64        }
  65}
  66
  67/* to activate the MMU we need to set up virtual memory: use 1M areas */
  68static inline void mmu_setup(void)
  69{
  70        u32 *page_table = (u32 *)gd->tlb_addr;
  71        int i;
  72        u32 reg;
  73
  74        arm_init_before_mmu();
  75        /* Set up an identity-mapping for all 4GB, rw for everyone */
  76        for (i = 0; i < 4096; i++)
  77                page_table[i] = i << 20 | (3 << 10) | 0x12;
  78
  79        for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) {
  80                dram_bank_mmu_setup(i);
  81        }
  82
  83        /* Copy the page table address to cp15 */
  84        asm volatile("mcr p15, 0, %0, c2, c0, 0"
  85                     : : "r" (page_table) : "memory");
  86        /* Set the access control to all-supervisor */
  87        asm volatile("mcr p15, 0, %0, c3, c0, 0"
  88                     : : "r" (~0));
  89        /* and enable the mmu */
  90        reg = get_cr(); /* get control reg. */
  91        cp_delay();
  92        set_cr(reg | CR_M);
  93}
  94
  95static int mmu_enabled(void)
  96{
  97        return get_cr() & CR_M;
  98}
  99
 100/* cache_bit must be either CR_I or CR_C */
 101static void cache_enable(uint32_t cache_bit)
 102{
 103        uint32_t reg;
 104
 105        /* The data cache is not active unless the mmu is enabled too */
 106        if ((cache_bit == CR_C) && !mmu_enabled())
 107                mmu_setup();
 108        reg = get_cr(); /* get control reg. */
 109        cp_delay();
 110        set_cr(reg | cache_bit);
 111}
 112
 113/* cache_bit must be either CR_I or CR_C */
 114static void cache_disable(uint32_t cache_bit)
 115{
 116        uint32_t reg;
 117
 118        if (cache_bit == CR_C) {
 119                /* if cache isn;t enabled no need to disable */
 120                reg = get_cr();
 121                if ((reg & CR_C) != CR_C)
 122                        return;
 123                /* if disabling data cache, disable mmu too */
 124                cache_bit |= CR_M;
 125                flush_dcache_all();
 126        }
 127        reg = get_cr();
 128        cp_delay();
 129        set_cr(reg & ~cache_bit);
 130}
 131#endif
 132
 133#ifdef CONFIG_SYS_ICACHE_OFF
 134void icache_enable (void)
 135{
 136        return;
 137}
 138
 139void icache_disable (void)
 140{
 141        return;
 142}
 143
 144int icache_status (void)
 145{
 146        return 0;                                       /* always off */
 147}
 148#else
 149void icache_enable(void)
 150{
 151        cache_enable(CR_I);
 152}
 153
 154void icache_disable(void)
 155{
 156        cache_disable(CR_I);
 157}
 158
 159int icache_status(void)
 160{
 161        return (get_cr() & CR_I) != 0;
 162}
 163#endif
 164
 165#ifdef CONFIG_SYS_DCACHE_OFF
 166void dcache_enable (void)
 167{
 168        return;
 169}
 170
 171void dcache_disable (void)
 172{
 173        return;
 174}
 175
 176int dcache_status (void)
 177{
 178        return 0;                                       /* always off */
 179}
 180#else
 181void dcache_enable(void)
 182{
 183        cache_enable(CR_C);
 184}
 185
 186void dcache_disable(void)
 187{
 188        cache_disable(CR_C);
 189}
 190
 191int dcache_status(void)
 192{
 193        return (get_cr() & CR_C) != 0;
 194}
 195#endif
 196