2005-01-09 23:16:25 +00:00
|
|
|
/*
|
|
|
|
* (C) Copyright 2004 Texas Insturments
|
|
|
|
*
|
|
|
|
* (C) Copyright 2002
|
|
|
|
* Sysgo Real-Time Solutions, GmbH <www.elinos.com>
|
|
|
|
* Marius Groeger <mgroeger@sysgo.de>
|
|
|
|
*
|
|
|
|
* (C) Copyright 2002
|
2009-05-13 08:54:10 +00:00
|
|
|
* Gary Jennejohn, DENX Software Engineering, <garyj@denx.de>
|
2005-01-09 23:16:25 +00:00
|
|
|
*
|
|
|
|
* See file CREDITS for list of people who contributed to this
|
|
|
|
* project.
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU General Public License as
|
|
|
|
* published by the Free Software Foundation; either version 2 of
|
|
|
|
* the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
|
|
|
* MA 02111-1307 USA
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
* CPU specific code
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <common.h>
|
|
|
|
#include <command.h>
|
2009-04-05 11:02:43 +00:00
|
|
|
#include <asm/system.h>
|
2005-01-09 23:16:25 +00:00
|
|
|
|
2009-04-05 11:06:31 +00:00
|
|
|
static void cache_flush(void);
|
2005-01-09 23:16:25 +00:00
|
|
|
|
|
|
|
int cleanup_before_linux (void)
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* this function is called just before we call linux
|
|
|
|
* it prepares the processor for linux
|
|
|
|
*
|
|
|
|
* we turn off caches etc ...
|
|
|
|
*/
|
|
|
|
|
|
|
|
disable_interrupts ();
|
|
|
|
|
|
|
|
#ifdef CONFIG_LCD
|
|
|
|
{
|
|
|
|
extern void lcd_disable(void);
|
|
|
|
extern void lcd_panel_disable(void);
|
|
|
|
|
|
|
|
lcd_disable(); /* proper disable of lcd & panel */
|
|
|
|
lcd_panel_disable();
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/* turn off I/D-cache */
|
2009-04-05 11:06:31 +00:00
|
|
|
icache_disable();
|
|
|
|
dcache_disable();
|
2005-01-09 23:16:25 +00:00
|
|
|
/* flush I/D-cache */
|
2009-04-05 11:06:31 +00:00
|
|
|
cache_flush();
|
|
|
|
|
|
|
|
return 0;
|
2005-01-09 23:16:25 +00:00
|
|
|
}
|
|
|
|
|
2009-04-05 11:06:31 +00:00
|
|
|
static void cache_flush(void)
|
2005-01-09 23:16:25 +00:00
|
|
|
{
|
2009-04-05 11:06:31 +00:00
|
|
|
unsigned long i = 0;
|
2005-01-09 23:16:25 +00:00
|
|
|
|
ARM1136: Fix cache_flush() error and correct cpu_init_crit() comments
The ARM1136 cache_flush() function uses the "mcr p15, 0, rn, c7, c7, 0"
instruction which means "Invalidate Both Caches" when in fact the intent
is to clean and invalidate all caches. So add an "mcr p15, 0, %0, c7,
c10, 0" instruction to "Clean Entire Data Cache" prior to the "Invalidate
Both Caches" instruction to insure that memory is consistent with any
dirty cache lines.
Also fix a couple of "flush v*" comments in ARM1136 cpu_init_crit() so
that they correctly describe the actual ARM1136 CP15 C7 Cache Operations
used.
Signed-off-by: George G. Davis <gdavis@mvista.com>
2010-05-11 14:15:36 +00:00
|
|
|
asm ("mcr p15, 0, %0, c7, c10, 0": :"r" (i)); /* clean entire data cache */
|
2009-04-05 11:06:31 +00:00
|
|
|
asm ("mcr p15, 0, %0, c7, c7, 0": :"r" (i)); /* invalidate both caches and flush btb */
|
|
|
|
asm ("mcr p15, 0, %0, c7, c10, 4": :"r" (i)); /* mem barrier to sync things */
|
2005-01-09 23:16:25 +00:00
|
|
|
}
|
2012-04-02 06:18:00 +00:00
|
|
|
|
|
|
|
#ifndef CONFIG_SYS_DCACHE_OFF
|
|
|
|
|
|
|
|
#ifndef CONFIG_SYS_CACHELINE_SIZE
|
|
|
|
#define CONFIG_SYS_CACHELINE_SIZE 32
|
|
|
|
#endif
|
|
|
|
|
|
|
|
void invalidate_dcache_all(void)
|
|
|
|
{
|
|
|
|
asm ("mcr p15, 0, %0, c7, c6, 0" : : "r" (0));
|
|
|
|
}
|
|
|
|
|
|
|
|
void flush_dcache_all(void)
|
|
|
|
{
|
|
|
|
asm ("mcr p15, 0, %0, c7, c10, 0" : : "r" (0));
|
|
|
|
asm ("mcr p15, 0, %0, c7, c10, 4" : : "r" (0));
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline int bad_cache_range(unsigned long start, unsigned long stop)
|
|
|
|
{
|
|
|
|
int ok = 1;
|
|
|
|
|
|
|
|
if (start & (CONFIG_SYS_CACHELINE_SIZE - 1))
|
|
|
|
ok = 0;
|
|
|
|
|
|
|
|
if (stop & (CONFIG_SYS_CACHELINE_SIZE - 1))
|
|
|
|
ok = 0;
|
|
|
|
|
|
|
|
if (!ok)
|
|
|
|
debug("CACHE: Misaligned operation at range [%08lx, %08lx]\n",
|
|
|
|
start, stop);
|
|
|
|
|
|
|
|
return ok;
|
|
|
|
}
|
|
|
|
|
|
|
|
void invalidate_dcache_range(unsigned long start, unsigned long stop)
|
|
|
|
{
|
|
|
|
if (bad_cache_range(start, stop))
|
|
|
|
return;
|
|
|
|
|
|
|
|
while (start < stop) {
|
|
|
|
asm ("mcr p15, 0, %0, c7, c6, 1" : : "r" (start));
|
|
|
|
start += CONFIG_SYS_CACHELINE_SIZE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void flush_dcache_range(unsigned long start, unsigned long stop)
|
|
|
|
{
|
|
|
|
if (bad_cache_range(start, stop))
|
|
|
|
return;
|
|
|
|
|
|
|
|
while (start < stop) {
|
|
|
|
asm ("mcr p15, 0, %0, c7, c14, 1" : : "r" (start));
|
|
|
|
start += CONFIG_SYS_CACHELINE_SIZE;
|
|
|
|
}
|
|
|
|
|
|
|
|
asm ("mcr p15, 0, %0, c7, c10, 4" : : "r" (0));
|
|
|
|
}
|
|
|
|
|
|
|
|
void flush_cache(unsigned long start, unsigned long size)
|
|
|
|
{
|
|
|
|
flush_dcache_range(start, start + size);
|
|
|
|
}
|
|
|
|
|
|
|
|
void enable_caches(void)
|
|
|
|
{
|
|
|
|
#ifndef CONFIG_SYS_ICACHE_OFF
|
|
|
|
icache_enable();
|
|
|
|
#endif
|
|
|
|
#ifndef CONFIG_SYS_DCACHE_OFF
|
|
|
|
dcache_enable();
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
#else /* #ifndef CONFIG_SYS_DCACHE_OFF */
|
|
|
|
void invalidate_dcache_all(void)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
void flush_dcache_all(void)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
void invalidate_dcache_range(unsigned long start, unsigned long stop)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
void flush_dcache_range(unsigned long start, unsigned long stop)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
void flush_cache(unsigned long start, unsigned long size)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
#endif /* #ifndef CONFIG_SYS_DCACHE_OFF */
|