aboutsummaryrefslogtreecommitdiff
path: root/arch/sh/kernel
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 15:20:36 -0700
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 15:20:36 -0700
commit1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch)
tree0bba044c4ce775e45a88a51686b5d9f90697ea9d /arch/sh/kernel
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history, even though we have it. We can create a separate "historical" git archive of that later if we want to, and in the meantime it's about 3.2GB when imported into git - space that would just make the early git days unnecessarily complicated, when we don't have a lot of good infrastructure for it. Let it rip!
Diffstat (limited to 'arch/sh/kernel')
-rw-r--r--arch/sh/kernel/Makefile22
-rw-r--r--arch/sh/kernel/asm-offsets.c32
-rw-r--r--arch/sh/kernel/cf-enabler.c158
-rw-r--r--arch/sh/kernel/cpu/Makefile16
-rw-r--r--arch/sh/kernel/cpu/adc.c36
-rw-r--r--arch/sh/kernel/cpu/bus.c195
-rw-r--r--arch/sh/kernel/cpu/init.c222
-rw-r--r--arch/sh/kernel/cpu/irq_imask.c116
-rw-r--r--arch/sh/kernel/cpu/irq_ipr.c339
-rw-r--r--arch/sh/kernel/cpu/rtc.c136
-rw-r--r--arch/sh/kernel/cpu/sh2/Makefile6
-rw-r--r--arch/sh/kernel/cpu/sh2/probe.c39
-rw-r--r--arch/sh/kernel/cpu/sh3/Makefile6
-rw-r--r--arch/sh/kernel/cpu/sh3/ex.S199
-rw-r--r--arch/sh/kernel/cpu/sh3/probe.c97
-rw-r--r--arch/sh/kernel/cpu/sh4/Makefile10
-rw-r--r--arch/sh/kernel/cpu/sh4/ex.S384
-rw-r--r--arch/sh/kernel/cpu/sh4/fpu.c335
-rw-r--r--arch/sh/kernel/cpu/sh4/irq_intc2.c222
-rw-r--r--arch/sh/kernel/cpu/sh4/probe.c138
-rw-r--r--arch/sh/kernel/cpu/sh4/sq.c453
-rw-r--r--arch/sh/kernel/cpu/ubc.S59
-rw-r--r--arch/sh/kernel/cpufreq.c218
-rw-r--r--arch/sh/kernel/early_printk.c137
-rw-r--r--arch/sh/kernel/entry.S1149
-rw-r--r--arch/sh/kernel/head.S76
-rw-r--r--arch/sh/kernel/init_task.c36
-rw-r--r--arch/sh/kernel/io.c59
-rw-r--r--arch/sh/kernel/io_generic.c243
-rw-r--r--arch/sh/kernel/irq.c106
-rw-r--r--arch/sh/kernel/kgdb_jmp.S33
-rw-r--r--arch/sh/kernel/kgdb_stub.c1491
-rw-r--r--arch/sh/kernel/module.c146
-rw-r--r--arch/sh/kernel/process.c531
-rw-r--r--arch/sh/kernel/ptrace.c320
-rw-r--r--arch/sh/kernel/semaphore.c139
-rw-r--r--arch/sh/kernel/setup.c649
-rw-r--r--arch/sh/kernel/sh_bios.c75
-rw-r--r--arch/sh/kernel/sh_ksyms.c126
-rw-r--r--arch/sh/kernel/signal.c607
-rw-r--r--arch/sh/kernel/smp.c199
-rw-r--r--arch/sh/kernel/sys_sh.c289
-rw-r--r--arch/sh/kernel/time.c657
-rw-r--r--arch/sh/kernel/traps.c712
-rw-r--r--arch/sh/kernel/vmlinux.lds.S155
45 files changed, 11373 insertions, 0 deletions
diff --git a/arch/sh/kernel/Makefile b/arch/sh/kernel/Makefile
new file mode 100644
index 00000000000..8b819698df1
--- /dev/null
+++ b/arch/sh/kernel/Makefile
@@ -0,0 +1,22 @@
+#
+# Makefile for the Linux/SuperH kernel.
+#
+
+extra-y := head.o init_task.o vmlinux.lds
+
+obj-y := process.o signal.o entry.o traps.o irq.o \
+ ptrace.o setup.o time.o sys_sh.o semaphore.o \
+ io.o io_generic.o sh_ksyms.o
+
+obj-y += cpu/
+
+obj-$(CONFIG_SMP) += smp.o
+obj-$(CONFIG_CF_ENABLER) += cf-enabler.o
+obj-$(CONFIG_SH_STANDARD_BIOS) += sh_bios.o
+obj-$(CONFIG_SH_KGDB) += kgdb_stub.o kgdb_jmp.o
+obj-$(CONFIG_SH_CPU_FREQ) += cpufreq.o
+obj-$(CONFIG_MODULES) += module.o
+obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
+
+USE_STANDARD_AS_RULE := true
+
diff --git a/arch/sh/kernel/asm-offsets.c b/arch/sh/kernel/asm-offsets.c
new file mode 100644
index 00000000000..dc6725c51a8
--- /dev/null
+++ b/arch/sh/kernel/asm-offsets.c
@@ -0,0 +1,32 @@
+/*
+ * This program is used to generate definitions needed by
+ * assembly language modules.
+ *
+ * We use the technique used in the OSF Mach kernel code:
+ * generate asm statements containing #defines,
+ * compile this file to assembler, and then extract the
+ * #defines from the assembly-language output.
+ */
+
+#include <linux/stddef.h>
+#include <linux/types.h>
+#include <linux/mm.h>
+#include <asm/thread_info.h>
+
+#define DEFINE(sym, val) \
+ asm volatile("\n->" #sym " %0 " #val : : "i" (val))
+
+#define BLANK() asm volatile("\n->" : : )
+
+int main(void)
+{
+ /* offsets into the thread_info struct */
+ DEFINE(TI_TASK, offsetof(struct thread_info, task));
+ DEFINE(TI_EXEC_DOMAIN, offsetof(struct thread_info, exec_domain));
+ DEFINE(TI_FLAGS, offsetof(struct thread_info, flags));
+ DEFINE(TI_CPU, offsetof(struct thread_info, cpu));
+ DEFINE(TI_PRE_COUNT, offsetof(struct thread_info, preempt_count));
+ DEFINE(TI_RESTART_BLOCK,offsetof(struct thread_info, restart_block));
+
+ return 0;
+}
diff --git a/arch/sh/kernel/cf-enabler.c b/arch/sh/kernel/cf-enabler.c
new file mode 100644
index 00000000000..7a3b18faa27
--- /dev/null
+++ b/arch/sh/kernel/cf-enabler.c
@@ -0,0 +1,158 @@
+/* $Id: cf-enabler.c,v 1.4 2004/02/22 22:44:36 kkojima Exp $
+ *
+ * linux/drivers/block/cf-enabler.c
+ *
+ * Copyright (C) 1999 Niibe Yutaka
+ * Copyright (C) 2000 Toshiharu Nozawa
+ * Copyright (C) 2001 A&D Co., Ltd.
+ *
+ * Enable the CF configuration.
+ */
+
+#include <linux/config.h>
+#include <linux/init.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+
+/*
+ * You can connect Compact Flash directly to the bus of SuperH.
+ * This is the enabler for that.
+ *
+ * SIM: How generic is this really? It looks pretty board, or at
+ * least SH sub-type, specific to me.
+ * I know it doesn't work on the Overdrive!
+ */
+
+/*
+ * 0xB8000000 : Attribute
+ * 0xB8001000 : Common Memory
+ * 0xBA000000 : I/O
+ */
+#if defined(CONFIG_IDE) && defined(CONFIG_CPU_SH4)
+/* SH4 can't access PCMCIA interface through P2 area.
+ * we must remap it with appropreate attribute bit of the page set.
+ * this part is based on Greg Banks' hd64465_ss.c implementation - Masahiro Abe */
+#include <linux/mm.h>
+#include <linux/vmalloc.h>
+
+#if defined(CONFIG_CF_AREA6)
+#define slot_no 0
+#else
+#define slot_no 1
+#endif
+
+/* defined in mm/ioremap.c */
+extern void * p3_ioremap(unsigned long phys_addr, unsigned long size, unsigned long flags);
+
+/* use this pointer to access to directly connected compact flash io area*/
+void *cf_io_base;
+
+static int __init allocate_cf_area(void)
+{
+ pgprot_t prot;
+ unsigned long paddrbase, psize;
+
+ /* open I/O area window */
+ paddrbase = virt_to_phys((void*)CONFIG_CF_BASE_ADDR);
+ psize = PAGE_SIZE;
+ prot = PAGE_KERNEL_PCC(slot_no, _PAGE_PCC_IO16);
+ cf_io_base = p3_ioremap(paddrbase, psize, prot.pgprot);
+ if (!cf_io_base) {
+ printk("allocate_cf_area : can't open CF I/O window!\n");
+ return -ENOMEM;
+ }
+/* printk("p3_ioremap(paddr=0x%08lx, psize=0x%08lx, prot=0x%08lx)=0x%08lx\n",
+ paddrbase, psize, prot.pgprot, cf_io_base);*/
+
+ /* XXX : do we need attribute and common-memory area also? */
+
+ return 0;
+}
+#endif
+
+static int __init cf_init_default(void)
+{
+/* You must have enabled the card, and set the level interrupt
+ * before reaching this point. Possibly in boot ROM or boot loader.
+ */
+#if defined(CONFIG_IDE) && defined(CONFIG_CPU_SH4)
+ allocate_cf_area();
+#endif
+#if defined(CONFIG_SH_UNKNOWN)
+ /* This should be done in each board's init_xxx_irq. */
+ make_imask_irq(14);
+ disable_irq(14);
+#endif
+ return 0;
+}
+
+#if defined(CONFIG_SH_SOLUTION_ENGINE)
+#include <asm/se/se.h>
+
+/*
+ * SolutionEngine
+ *
+ * 0xB8400000 : Common Memory
+ * 0xB8500000 : Attribute
+ * 0xB8600000 : I/O
+ */
+
+static int __init cf_init_se(void)
+{
+ if ((ctrl_inw(MRSHPC_CSR) & 0x000c) != 0)
+ return 0; /* Not detected */
+
+ if ((ctrl_inw(MRSHPC_CSR) & 0x0080) == 0) {
+ ctrl_outw(0x0674, MRSHPC_CPWCR); /* Card Vcc is 3.3v? */
+ } else {
+ ctrl_outw(0x0678, MRSHPC_CPWCR); /* Card Vcc is 5V */
+ }
+
+ /*
+ * PC-Card window open
+ * flag == COMMON/ATTRIBUTE/IO
+ */
+ /* common window open */
+ ctrl_outw(0x8a84, MRSHPC_MW0CR1);/* window 0xb8400000 */
+ if((ctrl_inw(MRSHPC_CSR) & 0x4000) != 0)
+ /* common mode & bus width 16bit SWAP = 1*/
+ ctrl_outw(0x0b00, MRSHPC_MW0CR2);
+ else
+ /* common mode & bus width 16bit SWAP = 0*/
+ ctrl_outw(0x0300, MRSHPC_MW0CR2);
+
+ /* attribute window open */
+ ctrl_outw(0x8a85, MRSHPC_MW1CR1);/* window 0xb8500000 */
+ if ((ctrl_inw(MRSHPC_CSR) & 0x4000) != 0)
+ /* attribute mode & bus width 16bit SWAP = 1*/
+ ctrl_outw(0x0a00, MRSHPC_MW1CR2);
+ else
+ /* attribute mode & bus width 16bit SWAP = 0*/
+ ctrl_outw(0x0200, MRSHPC_MW1CR2);
+
+ /* I/O window open */
+ ctrl_outw(0x8a86, MRSHPC_IOWCR1);/* I/O window 0xb8600000 */
+ ctrl_outw(0x0008, MRSHPC_CDCR); /* I/O card mode */
+ if ((ctrl_inw(MRSHPC_CSR) & 0x4000) != 0)
+ ctrl_outw(0x0a00, MRSHPC_IOWCR2); /* bus width 16bit SWAP = 1*/
+ else
+ ctrl_outw(0x0200, MRSHPC_IOWCR2); /* bus width 16bit SWAP = 0*/
+
+ ctrl_outw(0x2000, MRSHPC_ICR);
+ ctrl_outb(0x00, PA_MRSHPC_MW2 + 0x206);
+ ctrl_outb(0x42, PA_MRSHPC_MW2 + 0x200);
+ return 0;
+}
+#endif
+
+int __init cf_init(void)
+{
+#if defined(CONFIG_SH_SOLUTION_ENGINE)
+ if (MACH_SE)
+ return cf_init_se();
+#endif
+ return cf_init_default();
+}
+
+__initcall (cf_init);
diff --git a/arch/sh/kernel/cpu/Makefile b/arch/sh/kernel/cpu/Makefile
new file mode 100644
index 00000000000..cd43714df61
--- /dev/null
+++ b/arch/sh/kernel/cpu/Makefile
@@ -0,0 +1,16 @@
+#
+# Makefile for the Linux/SuperH CPU-specifc backends.
+#
+
+obj-y := irq_ipr.o irq_imask.o init.o bus.o
+
+obj-$(CONFIG_CPU_SH2) += sh2/
+obj-$(CONFIG_CPU_SH3) += sh3/
+obj-$(CONFIG_CPU_SH4) += sh4/
+
+obj-$(CONFIG_SH_RTC) += rtc.o
+obj-$(CONFIG_UBC_WAKEUP) += ubc.o
+obj-$(CONFIG_SH_ADC) += adc.o
+
+USE_STANDARD_AS_RULE := true
+
diff --git a/arch/sh/kernel/cpu/adc.c b/arch/sh/kernel/cpu/adc.c
new file mode 100644
index 00000000000..da3d6877f93
--- /dev/null
+++ b/arch/sh/kernel/cpu/adc.c
@@ -0,0 +1,36 @@
+/*
+ * linux/arch/sh/kernel/adc.c -- SH3 on-chip ADC support
+ *
+ * Copyright (C) 2004 Andriy Skulysh <askulysh@image.kiev.ua>
+ */
+
+#include <linux/module.h>
+#include <asm/adc.h>
+#include <asm/io.h>
+
+
+int adc_single(unsigned int channel)
+{
+ int off;
+ unsigned char csr;
+
+ if (channel >= 8) return -1;
+
+ off = (channel & 0x03) << 2;
+
+ csr = ctrl_inb(ADCSR);
+ csr = channel | ADCSR_ADST | ADCSR_CKS;
+ ctrl_outb(csr, ADCSR);
+
+ do {
+ csr = ctrl_inb(ADCSR);
+ } while ((csr & ADCSR_ADF) == 0);
+
+ csr &= ~(ADCSR_ADF | ADCSR_ADST);
+ ctrl_outb(csr, ADCSR);
+
+ return (((ctrl_inb(ADDRAH + off) << 8) |
+ ctrl_inb(ADDRAL + off)) >> 6);
+}
+
+EXPORT_SYMBOL(adc_single);
diff --git a/arch/sh/kernel/cpu/bus.c b/arch/sh/kernel/cpu/bus.c
new file mode 100644
index 00000000000..ace82f4b4a5
--- /dev/null
+++ b/arch/sh/kernel/cpu/bus.c
@@ -0,0 +1,195 @@
+/*
+ * arch/sh/kernel/cpu/bus.c
+ *
+ * Virtual bus for SuperH.
+ *
+ * Copyright (C) 2004 Paul Mundt
+ *
+ * Shamelessly cloned from arch/arm/mach-omap/bus.c, which was written
+ * by:
+ *
+ * Copyright (C) 2003 - 2004 Nokia Corporation
+ * Written by Tony Lindgren <tony@atomide.com>
+ * Portions of code based on sa1111.c.
+ *
+ * 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.
+ */
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <asm/bus-sh.h>
+
+static int sh_bus_match(struct device *dev, struct device_driver *drv)
+{
+ struct sh_driver *shdrv = to_sh_driver(drv);
+ struct sh_dev *shdev = to_sh_dev(dev);
+
+ return shdev->dev_id == shdrv->dev_id;
+}
+
+static int sh_bus_suspend(struct device *dev, u32 state)
+{
+ struct sh_dev *shdev = to_sh_dev(dev);
+ struct sh_driver *shdrv = to_sh_driver(dev->driver);
+
+ if (shdrv && shdrv->suspend)
+ return shdrv->suspend(shdev, state);
+
+ return 0;
+}
+
+static int sh_bus_resume(struct device *dev)
+{
+ struct sh_dev *shdev = to_sh_dev(dev);
+ struct sh_driver *shdrv = to_sh_driver(dev->driver);
+
+ if (shdrv && shdrv->resume)
+ return shdrv->resume(shdev);
+
+ return 0;
+}
+
+static struct device sh_bus_devices[SH_NR_BUSES] = {
+ {
+ .bus_id = SH_BUS_NAME_VIRT,
+ },
+};
+
+struct bus_type sh_bus_types[SH_NR_BUSES] = {
+ {
+ .name = SH_BUS_NAME_VIRT,
+ .match = sh_bus_match,
+ .suspend = sh_bus_suspend,
+ .resume = sh_bus_resume,
+ },
+};
+
+static int sh_device_probe(struct device *dev)
+{
+ struct sh_dev *shdev = to_sh_dev(dev);
+ struct sh_driver *shdrv = to_sh_driver(dev->driver);
+
+ if (shdrv && shdrv->probe)
+ return shdrv->probe(shdev);
+
+ return -ENODEV;
+}
+
+static int sh_device_remove(struct device *dev)
+{
+ struct sh_dev *shdev = to_sh_dev(dev);
+ struct sh_driver *shdrv = to_sh_driver(dev->driver);
+
+ if (shdrv && shdrv->remove)
+ return shdrv->remove(shdev);
+
+ return 0;
+}
+
+int sh_device_register(struct sh_dev *dev)
+{
+ if (!dev)
+ return -EINVAL;
+
+ if (dev->bus_id < 0 || dev->bus_id >= SH_NR_BUSES) {
+ printk(KERN_ERR "%s: bus_id invalid: %s bus: %d\n",
+ __FUNCTION__, dev->name, dev->bus_id);
+ return -EINVAL;
+ }
+
+ dev->dev.parent = &sh_bus_devices[dev->bus_id];
+ dev->dev.bus = &sh_bus_types[dev->bus_id];
+
+ /* This is needed for USB OHCI to work */
+ if (dev->dma_mask)
+ dev->dev.dma_mask = dev->dma_mask;
+
+ snprintf(dev->dev.bus_id, BUS_ID_SIZE, "%s%u",
+ dev->name, dev->dev_id);
+
+ printk(KERN_INFO "Registering SH device '%s'. Parent at %s\n",
+ dev->dev.bus_id, dev->dev.parent->bus_id);
+
+ return device_register(&dev->dev);
+}
+
+void sh_device_unregister(struct sh_dev *dev)
+{
+ device_unregister(&dev->dev);
+}
+
+int sh_driver_register(struct sh_driver *drv)
+{
+ if (!drv)
+ return -EINVAL;
+
+ if (drv->bus_id < 0 || drv->bus_id >= SH_NR_BUSES) {
+ printk(KERN_ERR "%s: bus_id invalid: bus: %d device %d\n",
+ __FUNCTION__, drv->bus_id, drv->dev_id);
+ return -EINVAL;
+ }
+
+ drv->drv.probe = sh_device_probe;
+ drv->drv.remove = sh_device_remove;
+ drv->drv.bus = &sh_bus_types[drv->bus_id];
+
+ return driver_register(&drv->drv);
+}
+
+void sh_driver_unregister(struct sh_driver *drv)
+{
+ driver_unregister(&drv->drv);
+}
+
+static int __init sh_bus_init(void)
+{
+ int i, ret = 0;
+
+ for (i = 0; i < SH_NR_BUSES; i++) {
+ ret = device_register(&sh_bus_devices[i]);
+ if (ret != 0) {
+ printk(KERN_ERR "Unable to register bus device %s\n",
+ sh_bus_devices[i].bus_id);
+ continue;
+ }
+
+ ret = bus_register(&sh_bus_types[i]);
+ if (ret != 0) {
+ printk(KERN_ERR "Unable to register bus %s\n",
+ sh_bus_types[i].name);
+ device_unregister(&sh_bus_devices[i]);
+ }
+ }
+
+ printk(KERN_INFO "SH Virtual Bus initialized\n");
+
+ return ret;
+}
+
+static void __exit sh_bus_exit(void)
+{
+ int i;
+
+ for (i = 0; i < SH_NR_BUSES; i++) {
+ bus_unregister(&sh_bus_types[i]);
+ device_unregister(&sh_bus_devices[i]);
+ }
+}
+
+module_init(sh_bus_init);
+module_exit(sh_bus_exit);
+
+MODULE_AUTHOR("Paul Mundt <lethal@linux-sh.org>");
+MODULE_DESCRIPTION("SH Virtual Bus");
+MODULE_LICENSE("GPL");
+
+EXPORT_SYMBOL(sh_bus_types);
+EXPORT_SYMBOL(sh_device_register);
+EXPORT_SYMBOL(sh_device_unregister);
+EXPORT_SYMBOL(sh_driver_register);
+EXPORT_SYMBOL(sh_driver_unregister);
+
diff --git a/arch/sh/kernel/cpu/init.c b/arch/sh/kernel/cpu/init.c
new file mode 100644
index 00000000000..cf94e8ef17c
--- /dev/null
+++ b/arch/sh/kernel/cpu/init.c
@@ -0,0 +1,222 @@
+/*
+ * arch/sh/kernel/cpu/init.c
+ *
+ * CPU init code
+ *
+ * Copyright (C) 2002, 2003 Paul Mundt
+ *
+ * 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
+ * for more details.
+ */
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <asm/processor.h>
+#include <asm/uaccess.h>
+#include <asm/system.h>
+#include <asm/cacheflush.h>
+#include <asm/cache.h>
+#include <asm/io.h>
+
+extern void detect_cpu_and_cache_system(void);
+
+/*
+ * 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; \
+ \
+static int __init x##_setup(char *opts) \
+{ \
+ x##_disabled = 1; \
+ return 0; \
+} \
+__setup("no" __stringify(x), x##_setup);
+
+onchip_setup(fpu);
+onchip_setup(dsp);
+
+/*
+ * Generic first-level cache init
+ */
+static void __init cache_init(void)
+{
+ unsigned long ccr, flags;
+
+ if (cpu_data->type == CPU_SH_NONE)
+ panic("Unknown CPU");
+
+ jump_to_P2();
+ ccr = ctrl_inl(CCR);
+
+ /*
+ * If the cache is already enabled .. flush it.
+ */
+ if (ccr & CCR_CACHE_ENABLE) {
+ unsigned long ways, waysize, addrstart;
+
+ waysize = cpu_data->dcache.sets;
+
+ /*
+ * If the OC is already in RAM mode, we only have
+ * half of the entries to flush..
+ */
+ if (ccr & CCR_CACHE_ORA)
+ waysize >>= 1;
+
+ waysize <<= cpu_data->dcache.entry_shift;
+
+#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;
+
+ addrstart = CACHE_OC_ADDRESS_ARRAY;
+ do {
+ unsigned long addr;
+
+ for (addr = addrstart;
+ addr < addrstart + waysize;
+ addr += cpu_data->dcache.linesz)
+ ctrl_outl(0, addr);
+
+ addrstart += cpu_data->dcache.way_incr;
+ } while (--ways);
+ }
+
+ /*
+ * Default CCR values .. enable the caches
+ * and invalidate them immediately..
+ */
+ flags = CCR_CACHE_ENABLE | CCR_CACHE_INVALIDATE;
+
+#ifdef CCR_CACHE_EMODE
+ /* Force EMODE if possible */
+ if (cpu_data->dcache.ways > 1)
+ flags |= CCR_CACHE_EMODE;
+#endif
+
+#ifdef CONFIG_SH_WRITETHROUGH
+ /* Turn on Write-through caching */
+ flags |= CCR_CACHE_WT;
+#else
+ /* .. or default to Write-back */
+ flags |= CCR_CACHE_CB;
+#endif
+
+#ifdef CONFIG_SH_OCRAM
+ /* Turn on OCRAM -- halve the OC */
+ flags |= CCR_CACHE_ORA;
+ cpu_data->dcache.sets >>= 1;
+#endif
+
+ ctrl_outl(flags, CCR);
+ back_to_P1();
+}
+
+#ifdef CONFIG_SH_DSP
+static void __init release_dsp(void)
+{
+ unsigned long sr;
+
+ /* Clear SR.DSP bit */
+ __asm__ __volatile__ (
+ "stc\tsr, %0\n\t"
+ "and\t%1, %0\n\t"
+ "ldc\t%0, sr\n\t"
+ : "=&r" (sr)
+ : "r" (~SR_DSP)
+ );
+}
+
+static void __init dsp_init(void)
+{
+ unsigned long sr;
+
+ /*
+ * Set the SR.DSP bit, wait for one instruction, and then read
+ * back the SR value.
+ */
+ __asm__ __volatile__ (
+ "stc\tsr, %0\n\t"
+ "or\t%1, %0\n\t"
+ "ldc\t%0, sr\n\t"
+ "nop\n\t"
+ "stc\tsr, %0\n\t"
+ : "=&r" (sr)
+ : "r" (SR_DSP)
+ );
+
+ /* If the DSP bit is still set, this CPU has a DSP */
+ if (sr & SR_DSP)
+ 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
+ * CPU prior to calling start_kernel(). For SMP, a combination of this and
+ * start_secondary() will bring up each processor to a ready state prior
+ * to hand forking the idle loop.
+ *
+ * We do all of the basic processor init here, including setting up the
+ * caches, FPU, DSP, kicking the UBC, etc. By the time start_kernel() is
+ * hit (and subsequently platform_setup()) things like determining the
+ * CPU subtype and initial configuration will all be done.
+ *
+ * Each processor family is still responsible for doing its own probing
+ * and cache configuration in detect_cpu_and_cache_system().
+ */
+asmlinkage void __init sh_cpu_init(void)
+{
+ /* First, probe the CPU */
+ detect_cpu_and_cache_system();
+
+ /* Init the cache */
+ cache_init();
+
+ /* Disable the FPU */
+ if (fpu_disabled) {
+ printk("FPU Disabled\n");
+ cpu_data->flags &= ~CPU_HAS_FPU;
+ disable_fpu();
+ }
+
+ /* FPU initialization */
+ if ((cpu_data->flags & CPU_HAS_FPU)) {
+ clear_thread_flag(TIF_USEDFPU);
+ clear_used_math();
+ }
+
+#ifdef CONFIG_SH_DSP
+ /* Probe for DSP */
+ dsp_init();
+
+ /* Disable the DSP */
+ if (dsp_disabled) {
+ printk("DSP Disabled\n");
+ cpu_data->flags &= ~CPU_HAS_DSP;
+ release_dsp();
+ }
+#endif
+
+#ifdef CONFIG_UBC_WAKEUP
+ /*
+ * Some brain-damaged loaders decided it would be a good idea to put
+ * the UBC to sleep. This causes some issues when it comes to things
+ * like PTRACE_SINGLESTEP or doing hardware watchpoints in GDB. So ..
+ * we wake it up and hope that all is well.
+ */
+ ubc_wakeup();
+#endif
+}
+
diff --git a/arch/sh/kernel/cpu/irq_imask.c b/arch/sh/kernel/cpu/irq_imask.c
new file mode 100644
index 00000000000..f76901e732f
--- /dev/null
+++ b/arch/sh/kernel/cpu/irq_imask.c
@@ -0,0 +1,116 @@
+/* $Id: irq_imask.c,v 1.1.2.1 2002/11/17 10:53:43 mrbrown Exp $
+ *
+ * linux/arch/sh/kernel/irq_imask.c
+ *
+ * Copyright (C) 1999, 2000 Niibe Yutaka
+ *
+ * Simple interrupt handling using IMASK of SR register.
+ *
+ */
+
+/* NOTE: Will not work on level 15 */
+
+
+#include <linux/ptrace.h>
+#include <linux/errno.h>
+#include <linux/kernel_stat.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+#include <linux/bitops.h>
+
+#include <asm/system.h>
+#include <asm/irq.h>
+
+#include <linux/spinlock.h>
+#include <linux/cache.h>
+#include <linux/irq.h>
+
+/* Bitmap of IRQ masked */
+static unsigned long imask_mask = 0x7fff;
+static int interrupt_priority = 0;
+
+static void enable_imask_irq(unsigned int irq);
+static void disable_imask_irq(unsigned int irq);
+static void shutdown_imask_irq(unsigned int irq);
+static void mask_and_ack_imask(unsigned int);
+static void end_imask_irq(unsigned int irq);
+
+#define IMASK_PRIORITY 15
+
+static unsigned int startup_imask_irq(unsigned int irq)
+{
+ /* Nothing to do */
+ return 0; /* never anything pending */
+}
+
+static struct hw_interrupt_type imask_irq_type = {
+ "SR.IMASK",
+ startup_imask_irq,
+ shutdown_imask_irq,
+ enable_imask_irq,
+ disable_imask_irq,
+ mask_and_ack_imask,
+ end_imask_irq
+};
+
+void static inline set_interrupt_registers(int ip)
+{
+ unsigned long __dummy;
+
+ asm volatile("ldc %2, r6_bank\n\t"
+ "stc sr, %0\n\t"
+ "and #0xf0, %0\n\t"
+ "shlr2 %0\n\t"
+ "cmp/eq #0x3c, %0\n\t"
+ "bt/s 1f ! CLI-ed\n\t"
+ " stc sr, %0\n\t"
+ "and %1, %0\n\t"
+ "or %2, %0\n\t"
+ "ldc %0, sr\n"
+ "1:"
+ : "=&z" (__dummy)
+ : "r" (~0xf0), "r" (ip << 4)
+ : "t");
+}
+
+static void disable_imask_irq(unsigned int irq)
+{
+ clear_bit(irq, &imask_mask);
+ if (interrupt_priority < IMASK_PRIORITY - irq)
+ interrupt_priority = IMASK_PRIORITY - irq;
+
+ set_interrupt_registers(interrupt_priority);
+}
+
+static void enable_imask_irq(unsigned int irq)
+{
+ set_bit(irq, &imask_mask);
+ interrupt_priority = IMASK_PRIORITY - ffz(imask_mask);
+
+ set_interrupt_registers(interrupt_priority);
+}
+
+static void mask_and_ack_imask(unsigned int irq)
+{
+ disable_imask_irq(irq);
+}
+
+static void end_imask_irq(unsigned int irq)
+{
+ if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
+ enable_imask_irq(irq);
+}
+
+static void shutdown_imask_irq(unsigned int irq)
+{
+ /* Nothing to do */
+}
+
+void make_imask_irq(unsigned int irq)
+{
+ disable_irq_nosync(irq);
+ irq_desc[irq].handler = &imask_irq_type;
+ enable_irq(irq);