aboutsummaryrefslogtreecommitdiff
path: root/arch/sh/boards/saturn
diff options
context:
space:
mode:
Diffstat (limited to 'arch/sh/boards/saturn')
-rw-r--r--arch/sh/boards/saturn/Makefile8
-rw-r--r--arch/sh/boards/saturn/io.c26
-rw-r--r--arch/sh/boards/saturn/irq.c118
-rw-r--r--arch/sh/boards/saturn/setup.c43
-rw-r--r--arch/sh/boards/saturn/smp.c68
5 files changed, 263 insertions, 0 deletions
diff --git a/arch/sh/boards/saturn/Makefile b/arch/sh/boards/saturn/Makefile
new file mode 100644
index 00000000000..75a3042e252
--- /dev/null
+++ b/arch/sh/boards/saturn/Makefile
@@ -0,0 +1,8 @@
+#
+# Makefile for the Sega Saturn specific parts of the kernel
+#
+
+obj-y := setup.o io.o irq.o
+
+obj-$(CONFIG_SMP) += smp.o
+
diff --git a/arch/sh/boards/saturn/io.c b/arch/sh/boards/saturn/io.c
new file mode 100644
index 00000000000..c6e4f7f2e68
--- /dev/null
+++ b/arch/sh/boards/saturn/io.c
@@ -0,0 +1,26 @@
+/*
+ * arch/sh/boards/saturn/io.c
+ *
+ * I/O routines for the Sega Saturn.
+ *
+ * Copyright (C) 2002 Paul Mundt
+ *
+ * Released under the terms of the GNU GPL v2.0.
+ */
+#include <asm/saturn/io.h>
+#include <asm/machvec.h>
+
+unsigned long saturn_isa_port2addr(unsigned long offset)
+{
+ return offset;
+}
+
+void *saturn_ioremap(unsigned long offset, unsigned long size)
+{
+ return (void *)offset;
+}
+
+void saturn_iounmap(void *addr)
+{
+}
+
diff --git a/arch/sh/boards/saturn/irq.c b/arch/sh/boards/saturn/irq.c
new file mode 100644
index 00000000000..15d1d3f0f78
--- /dev/null
+++ b/arch/sh/boards/saturn/irq.c
@@ -0,0 +1,118 @@
+/*
+ * arch/sh/boards/saturn/irq.c
+ *
+ * Copyright (C) 2002 Paul Mundt
+ *
+ * Released under the terms of the GNU GPL v2.0.
+ */
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <asm/irq.h>
+#include <asm/io.h>
+
+/*
+ * Interrupts map out as follows:
+ *
+ * Vector Name Mask
+ *
+ * 64 VBLANKIN 0x0001
+ * 65 VBLANKOUT 0x0002
+ * 66 HBLANKIN 0x0004
+ * 67 TIMER0 0x0008
+ * 68 TIMER1 0x0010
+ * 69 DSPEND 0x0020
+ * 70 SOUNDREQUEST 0x0040
+ * 71 SYSTEMMANAGER 0x0080
+ * 72 PAD 0x0100
+ * 73 LEVEL2DMAEND 0x0200
+ * 74 LEVEL1DMAEND 0x0400
+ * 75 LEVEL0DMAEND 0x0800
+ * 76 DMAILLEGAL 0x1000
+ * 77 SRITEDRAWEND 0x2000
+ * 78 ABUS 0x8000
+ *
+ */
+#define SATURN_IRQ_MIN 64 /* VBLANKIN */
+#define SATURN_IRQ_MAX 78 /* ABUS */
+
+#define SATURN_IRQ_MASK 0xbfff
+
+static inline u32 saturn_irq_mask(unsigned int irq_nr)
+{
+ u32 mask;
+
+ mask = (1 << (irq_nr - SATURN_IRQ_MIN));
+ mask <<= (irq_nr == SATURN_IRQ_MAX);
+ mask &= SATURN_IRQ_MASK;
+
+ return mask;
+}
+
+static inline void mask_saturn_irq(unsigned int irq_nr)
+{
+ u32 mask;
+
+ mask = ctrl_inl(SATURN_IMR);
+ mask |= saturn_irq_mask(irq_nr);
+ ctrl_outl(mask, SATURN_IMR);
+}
+
+static inline void unmask_saturn_irq(unsigned int irq_nr)
+{
+ u32 mask;
+
+ mask = ctrl_inl(SATURN_IMR);
+ mask &= ~saturn_irq_mask(irq_nr);
+ ctrl_outl(mask, SATURN_IMR);
+}
+
+static void disable_saturn_irq(unsigned int irq_nr)
+{
+ mask_saturn_irq(irq_nr);
+}
+
+static void enable_saturn_irq(unsigned int irq_nr)
+{
+ unmask_saturn_irq(irq_nr);
+}
+
+static void mask_and_ack_saturn_irq(unsigned int irq_nr)
+{
+ mask_saturn_irq(irq_nr);
+}
+
+static void end_saturn_irq(unsigned int irq_nr)
+{
+ if (!(irq_desc[irq_nr].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
+ unmask_saturn_irq(irq_nr);
+}
+
+static unsigned int startup_saturn_irq(unsigned int irq_nr)
+{
+ unmask_saturn_irq(irq_nr);
+
+ return 0;
+}
+
+static void shutdown_saturn_irq(unsigned int irq_nr)
+{
+ mask_saturn_irq(irq_nr);
+}
+
+static struct hw_interrupt_type saturn_int = {
+ .typename = "Saturn",
+ .enable = enable_saturn_irq,
+ .disable = disable_saturn_irq,
+ .ack = mask_and_ack_saturn_irq,
+ .end = end_saturn_irq,
+ .startup = startup_saturn_irq,
+ .shutdown = shutdown_saturn_irq,
+};
+
+int saturn_irq_demux(int irq_nr)
+{
+ /* FIXME */
+ return irq_nr;
+}
+
diff --git a/arch/sh/boards/saturn/setup.c b/arch/sh/boards/saturn/setup.c
new file mode 100644
index 00000000000..bea6c572ad8
--- /dev/null
+++ b/arch/sh/boards/saturn/setup.c
@@ -0,0 +1,43 @@
+/*
+ * arch/sh/boards/saturn/setup.c
+ *
+ * Hardware support for the Sega Saturn.
+ *
+ * Copyright (c) 2002 Paul Mundt
+ *
+ * Released under the terms of the GNU GPL v2.0.
+ */
+#include <linux/kernel.h>
+#include <linux/init.h>
+
+#include <asm/io.h>
+#include <asm/machvec.h>
+#include <asm/mach/io.h>
+
+extern int saturn_irq_demux(int irq_nr);
+
+const char *get_system_type(void)
+{
+ return "Sega Saturn";
+}
+
+/*
+ * The Machine Vector
+ */
+struct sh_machine_vector mv_saturn __initmv = {
+ .mv_nr_irqs = 80, /* Fix this later */
+
+ .mv_isa_port2addr = saturn_isa_port2addr,
+ .mv_irq_demux = saturn_irq_demux,
+
+ .mv_ioremap = saturn_ioremap,
+ .mv_iounmap = saturn_iounmap,
+};
+
+ALIAS_MV(saturn)
+
+int __init platform_setup(void)
+{
+ return 0;
+}
+
diff --git a/arch/sh/boards/saturn/smp.c b/arch/sh/boards/saturn/smp.c
new file mode 100644
index 00000000000..76460918c9c
--- /dev/null
+++ b/arch/sh/boards/saturn/smp.c
@@ -0,0 +1,68 @@
+/*
+ * arch/sh/boards/saturn/smp.c
+ *
+ * SMP support for the Sega Saturn.
+ *
+ * Copyright (c) 2002 Paul Mundt
+ *
+ * Released under the terms of the GNU GPL v2.0.
+ */
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/smp.h>
+
+#include <asm/saturn/smpc.h>
+
+extern void start_secondary(void);
+
+void __smp_send_ipi(unsigned int cpu, unsigned int action)
+{
+ /* Nothing here yet .. */
+}
+
+unsigned int __smp_probe_cpus(void)
+{
+ /*
+ * This is just a straightforward master/slave configuration,
+ * and probing isn't really supported..
+ */
+ return 2;
+}
+
+/*
+ * We're only allowed to do byte-access to SMPC registers. In
+ * addition to which, we treat them as write-only, since
+ * reading from them will return undefined data.
+ */
+static inline void smpc_slave_stop(unsigned int cpu)
+{
+ smpc_barrier();
+ ctrl_outb(1, SMPC_STATUS);
+
+ ctrl_outb(SMPC_CMD_SSHOFF, SMPC_COMMAND);
+ smpc_barrier();
+}
+
+static inline void smpc_slave_start(unsigned int cpu)
+{
+ ctrl_outb(1, SMPC_STATUS);
+ ctrl_outb(SMPC_CMD_SSHON, SMPC_COMMAND);
+
+ smpc_barrier();
+}
+
+void __smp_slave_init(unsigned int cpu)
+{
+ register unsigned long vbr;
+ void **entry;
+
+ __asm__ __volatile__ ("stc vbr, %0\n\t" : "=r" (vbr));
+ entry = (void **)(vbr + 0x310 + 0x94);
+
+ smpc_slave_stop(cpu);
+
+ *(void **)entry = (void *)start_secondary;
+
+ smpc_slave_start(cpu);
+}
+