* CPU init code
*
* Copyright (C) 2002, 2003 Paul Mundt
+ * Copyright (C) 2003 Richard Curnow
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
#include <linux/kernel.h>
#include <asm/processor.h>
#include <asm/uaccess.h>
+#include <asm/page.h>
#include <asm/system.h>
#include <asm/cacheflush.h>
#include <asm/cache.h>
* Generic wrapper for command line arguments to disable on-chip
* peripherals (nofpu, nodsp, and so forth).
*/
-#define onchip_setup(x) \
-static int x##_disabled __initdata = 0; \
+#define onchip_setup(x) \
+static int x##_disabled __initdata = 0; \
\
static int __init x##_setup(char *opts) \
{ \
x##_disabled = 1; \
- return 0; \
+ return 1; \
} \
__setup("no" __stringify(x), x##_setup);
*/
static void __init cache_init(void)
{
- unsigned long ccr, flags = 0;
+ unsigned long ccr, flags;
if (cpu_data->type == CPU_SH_NONE)
panic("Unknown CPU");
ccr = ctrl_inl(CCR);
/*
- * If the cache is already enabled .. flush it.
+ * At this point we don't know whether the cache is enabled or not - a
+ * bootloader may have enabled it. There are at least 2 things that
+ * could be dirty in the cache at this point:
+ * 1. kernel command line set up by boot loader
+ * 2. spilled registers from the prolog of this function
+ * => before re-initialising the cache, we must do a purge of the whole
+ * cache out to memory for safety. As long as nothing is spilled
+ * during the loop to lines that have already been done, this is safe.
+ * - RPC
*/
if (ccr & CCR_CACHE_ENABLE) {
- unsigned long entries, i, j;
+ unsigned long ways, waysize, addrstart;
- entries = cpu_data->dcache.sets;
+ waysize = cpu_data->dcache.sets;
+#ifdef CCR_CACHE_ORA
/*
* If the OC is already in RAM mode, we only have
* half of the entries to flush..
*/
if (ccr & CCR_CACHE_ORA)
- entries >>= 1;
+ waysize >>= 1;
+#endif
+
+ waysize <<= cpu_data->dcache.entry_shift;
- for (i = 0; i < entries; i++) {
- for (j = 0; j < cpu_data->dcache.ways; j++) {
- unsigned long data, addr;
+#ifdef CCR_CACHE_EMODE
+ /* If EMODE is not set, we only have 1 way to flush. */
+ if (!(ccr & CCR_CACHE_EMODE))
+ ways = 1;
+ else
+#endif
+ ways = cpu_data->dcache.ways;
- addr = CACHE_OC_ADDRESS_ARRAY |
- (j << cpu_data->dcache.way_shift) |
- (i << cpu_data->dcache.entry_shift);
+ addrstart = CACHE_OC_ADDRESS_ARRAY;
+ do {
+ unsigned long addr;
- data = ctrl_inl(addr);
+ for (addr = addrstart;
+ addr < addrstart + waysize;
+ addr += cpu_data->dcache.linesz)
+ ctrl_outl(0, addr);
- if ((data & (SH_CACHE_UPDATED | SH_CACHE_VALID))
- == (SH_CACHE_UPDATED | SH_CACHE_VALID))
- ctrl_outl(data & ~SH_CACHE_UPDATED, addr);
- }
- }
+ addrstart += cpu_data->dcache.way_incr;
+ } while (--ways);
}
- /*
+ /*
* Default CCR values .. enable the caches
- * and flush them immediately..
+ * and invalidate them immediately..
*/
- flags |= CCR_CACHE_ENABLE | CCR_CACHE_INVALIDATE;
-
+ flags = CCR_CACHE_ENABLE | CCR_CACHE_INVALIDATE;
+
#ifdef CCR_CACHE_EMODE
- flags |= (ccr & CCR_CACHE_EMODE);
+ /* Force EMODE if possible */
+ if (cpu_data->dcache.ways > 1)
+ flags |= CCR_CACHE_EMODE;
+ else
+ flags &= ~CCR_CACHE_EMODE;
#endif
#ifdef CONFIG_SH_WRITETHROUGH
/* Turn on OCRAM -- halve the OC */
flags |= CCR_CACHE_ORA;
cpu_data->dcache.sets >>= 1;
+
+ cpu_data->dcache.way_size = cpu_data->dcache.sets *
+ cpu_data->dcache.linesz;
#endif
ctrl_outl(flags, CCR);
/* If the DSP bit is still set, this CPU has a DSP */
if (sr & SR_DSP)
- set_bit(CPU_HAS_DSP, &(cpu_data->flags));
-
+ cpu_data->flags |= CPU_HAS_DSP;
+
/* Now that we've determined the DSP status, clear the DSP bit. */
release_dsp();
}
#endif /* CONFIG_SH_DSP */
-/*
+/**
* sh_cpu_init
*
* This is our initial entry point for each CPU, and is invoked on the boot
/* Init the cache */
cache_init();
+ shm_align_mask = max_t(unsigned long,
+ cpu_data->dcache.way_size - 1,
+ PAGE_SIZE - 1);
+
/* Disable the FPU */
if (fpu_disabled) {
printk("FPU Disabled\n");
}
/* FPU initialization */
- if (test_bit(CPU_HAS_FPU, &(cpu_data->flags))) {
+ if ((cpu_data->flags & CPU_HAS_FPU)) {
clear_thread_flag(TIF_USEDFPU);
- current->used_math = 0;
+ clear_used_math();
}
#ifdef CONFIG_SH_DSP
/* Probe for DSP */
dsp_init();
-
+
/* Disable the DSP */
if (dsp_disabled) {
printk("DSP Disabled\n");