aboutsummaryrefslogtreecommitdiff
path: root/arch/sh/boards/se/770x
diff options
context:
space:
mode:
Diffstat (limited to 'arch/sh/boards/se/770x')
-rw-r--r--arch/sh/boards/se/770x/Makefile6
-rw-r--r--arch/sh/boards/se/770x/io.c226
-rw-r--r--arch/sh/boards/se/770x/irq.c80
-rw-r--r--arch/sh/boards/se/770x/led.c68
-rw-r--r--arch/sh/boards/se/770x/mach.c68
-rw-r--r--arch/sh/boards/se/770x/setup.c85
6 files changed, 533 insertions, 0 deletions
diff --git a/arch/sh/boards/se/770x/Makefile b/arch/sh/boards/se/770x/Makefile
new file mode 100644
index 00000000000..be89a73cc41
--- /dev/null
+++ b/arch/sh/boards/se/770x/Makefile
@@ -0,0 +1,6 @@
+#
+# Makefile for the 770x SolutionEngine specific parts of the kernel
+#
+
+obj-y := mach.o setup.o io.o irq.o led.o
+
diff --git a/arch/sh/boards/se/770x/io.c b/arch/sh/boards/se/770x/io.c
new file mode 100644
index 00000000000..9a39ee96314
--- /dev/null
+++ b/arch/sh/boards/se/770x/io.c
@@ -0,0 +1,226 @@
+/* $Id: io.c,v 1.5 2004/02/22 23:08:43 kkojima Exp $
+ *
+ * linux/arch/sh/kernel/io_se.c
+ *
+ * Copyright (C) 2000 Kazumoto Kojima
+ *
+ * I/O routine for Hitachi SolutionEngine.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <asm/io.h>
+#include <asm/se/se.h>
+
+/* SH pcmcia io window base, start and end. */
+int sh_pcic_io_wbase = 0xb8400000;
+int sh_pcic_io_start;
+int sh_pcic_io_stop;
+int sh_pcic_io_type;
+int sh_pcic_io_dummy;
+
+static inline void delay(void)
+{
+ ctrl_inw(0xa0000000);
+}
+
+/* MS7750 requires special versions of in*, out* routines, since
+ PC-like io ports are located at upper half byte of 16-bit word which
+ can be accessed only with 16-bit wide. */
+
+static inline volatile __u16 *
+port2adr(unsigned int port)
+{
+ if (port >= 0x2000)
+ return (volatile __u16 *) (PA_MRSHPC + (port - 0x2000));
+ else if (port >= 0x1000)
+ return (volatile __u16 *) (PA_83902 + (port << 1));
+ else if (sh_pcic_io_start <= port && port <= sh_pcic_io_stop)
+ return (volatile __u16 *) (sh_pcic_io_wbase + (port &~ 1));
+ else
+ return (volatile __u16 *) (PA_SUPERIO + (port << 1));
+}
+
+static inline int
+shifted_port(unsigned long port)
+{
+ /* For IDE registers, value is not shifted */
+ if ((0x1f0 <= port && port < 0x1f8) || port == 0x3f6)
+ return 0;
+ else
+ return 1;
+}
+
+#define maybebadio(name,port) \
+ printk("bad PC-like io %s for port 0x%lx at 0x%08x\n", \
+ #name, (port), (__u32) __builtin_return_address(0))
+
+unsigned char se_inb(unsigned long port)
+{
+ if (sh_pcic_io_start <= port && port <= sh_pcic_io_stop)
+ return *(__u8 *) (sh_pcic_io_wbase + 0x40000 + port);
+ else if (shifted_port(port))
+ return (*port2adr(port) >> 8);
+ else
+ return (*port2adr(port))&0xff;
+}
+
+unsigned char se_inb_p(unsigned long port)
+{
+ unsigned long v;
+
+ if (sh_pcic_io_start <= port && port <= sh_pcic_io_stop)
+ v = *(__u8 *) (sh_pcic_io_wbase + 0x40000 + port);
+ else if (shifted_port(port))
+ v = (*port2adr(port) >> 8);
+ else
+ v = (*port2adr(port))&0xff;
+ delay();
+ return v;
+}
+
+unsigned short se_inw(unsigned long port)
+{
+ if (port >= 0x2000 ||
+ (sh_pcic_io_start <= port && port <= sh_pcic_io_stop))
+ return *port2adr(port);
+ else
+ maybebadio(inw, port);
+ return 0;
+}
+
+unsigned int se_inl(unsigned long port)
+{
+ maybebadio(inl, port);
+ return 0;
+}
+
+void se_outb(unsigned char value, unsigned long port)
+{
+ if (sh_pcic_io_start <= port && port <= sh_pcic_io_stop)
+ *(__u8 *)(sh_pcic_io_wbase + port) = value;
+ else if (shifted_port(port))
+ *(port2adr(port)) = value << 8;
+ else
+ *(port2adr(port)) = value;
+}
+
+void se_outb_p(unsigned char value, unsigned long port)
+{
+ if (sh_pcic_io_start <= port && port <= sh_pcic_io_stop)
+ *(__u8 *)(sh_pcic_io_wbase + port) = value;
+ else if (shifted_port(port))
+ *(port2adr(port)) = value << 8;
+ else
+ *(port2adr(port)) = value;
+ delay();
+}
+
+void se_outw(unsigned short value, unsigned long port)
+{
+ if (port >= 0x2000 ||
+ (sh_pcic_io_start <= port && port <= sh_pcic_io_stop))
+ *port2adr(port) = value;
+ else
+ maybebadio(outw, port);
+}
+
+void se_outl(unsigned int value, unsigned long port)
+{
+ maybebadio(outl, port);
+}
+
+void se_insb(unsigned long port, void *addr, unsigned long count)
+{
+ volatile __u16 *p = port2adr(port);
+ __u8 *ap = addr;
+
+ if (sh_pcic_io_start <= port && port <= sh_pcic_io_stop) {
+ volatile __u8 *bp = (__u8 *) (sh_pcic_io_wbase + 0x40000 + port);
+ while (count--)
+ *ap++ = *bp;
+ } else if (shifted_port(port)) {
+ while (count--)
+ *ap++ = *p >> 8;
+ } else {
+ while (count--)
+ *ap++ = *p;
+ }
+}
+
+void se_insw(unsigned long port, void *addr, unsigned long count)
+{
+ volatile __u16 *p = port2adr(port);
+ __u16 *ap = addr;
+ while (count--)
+ *ap++ = *p;
+}
+
+void se_insl(unsigned long port, void *addr, unsigned long count)
+{
+ maybebadio(insl, port);
+}
+
+void se_outsb(unsigned long port, const void *addr, unsigned long count)
+{
+ volatile __u16 *p = port2adr(port);
+ const __u8 *ap = addr;
+
+ if (sh_pcic_io_start <= port && port <= sh_pcic_io_stop) {
+ volatile __u8 *bp = (__u8 *) (sh_pcic_io_wbase + port);
+ while (count--)
+ *bp = *ap++;
+ } else if (shifted_port(port)) {
+ while (count--)
+ *p = *ap++ << 8;
+ } else {
+ while (count--)
+ *p = *ap++;
+ }
+}
+
+void se_outsw(unsigned long port, const void *addr, unsigned long count)
+{
+ volatile __u16 *p = port2adr(port);
+ const __u16 *ap = addr;
+ while (count--)
+ *p = *ap++;
+}
+
+void se_outsl(unsigned long port, const void *addr, unsigned long count)
+{
+ maybebadio(outsw, port);
+}
+
+/* Map ISA bus address to the real address. Only for PCMCIA. */
+
+/* ISA page descriptor. */
+static __u32 sh_isa_memmap[256];
+
+static int
+sh_isa_mmap(__u32 start, __u32 length, __u32 offset)
+{
+ int idx;
+
+ if (start >= 0x100000 || (start & 0xfff) || (length != 0x1000))
+ return -1;
+
+ idx = start >> 12;
+ sh_isa_memmap[idx] = 0xb8000000 + (offset &~ 0xfff);
+#if 0
+ printk("sh_isa_mmap: start %x len %x offset %x (idx %x paddr %x)\n",
+ start, length, offset, idx, sh_isa_memmap[idx]);
+#endif
+ return 0;
+}
+
+unsigned long
+se_isa_port2addr(unsigned long offset)
+{
+ int idx;
+
+ idx = (offset >> 12) & 0xff;
+ offset &= 0xfff;
+ return sh_isa_memmap[idx] + offset;
+}
diff --git a/arch/sh/boards/se/770x/irq.c b/arch/sh/boards/se/770x/irq.c
new file mode 100644
index 00000000000..210897b315f
--- /dev/null
+++ b/arch/sh/boards/se/770x/irq.c
@@ -0,0 +1,80 @@
+/*
+ * linux/arch/sh/boards/se/770x/irq.c
+ *
+ * Copyright (C) 2000 Kazumoto Kojima
+ *
+ * Hitachi SolutionEngine Support.
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <asm/irq.h>
+#include <asm/io.h>
+#include <asm/se/se.h>
+
+/*
+ * Initialize IRQ setting
+ */
+void __init init_se_IRQ(void)
+{
+ /*
+ * Super I/O (Just mimic PC):
+ * 1: keyboard
+ * 3: serial 0
+ * 4: serial 1
+ * 5: printer
+ * 6: floppy
+ * 8: rtc
+ * 12: mouse
+ * 14: ide0
+ */
+#if defined(CONFIG_CPU_SUBTYPE_SH7705)
+ /* Disable all interrupts */
+ ctrl_outw(0, BCR_ILCRA);
+ ctrl_outw(0, BCR_ILCRB);
+ ctrl_outw(0, BCR_ILCRC);
+ ctrl_outw(0, BCR_ILCRD);
+ ctrl_outw(0, BCR_ILCRE);
+ ctrl_outw(0, BCR_ILCRF);
+ ctrl_outw(0, BCR_ILCRG);
+ /* This is default value */
+ make_ipr_irq(0xf-0x2, BCR_ILCRA, 2, 0x2);
+ make_ipr_irq(0xf-0xa, BCR_ILCRA, 1, 0xa);
+ make_ipr_irq(0xf-0x5, BCR_ILCRB, 0, 0x5);
+ make_ipr_irq(0xf-0x8, BCR_ILCRC, 1, 0x8);
+ make_ipr_irq(0xf-0xc, BCR_ILCRC, 0, 0xc);
+ make_ipr_irq(0xf-0xe, BCR_ILCRD, 3, 0xe);
+ make_ipr_irq(0xf-0x3, BCR_ILCRD, 1, 0x3); /* LAN */
+ make_ipr_irq(0xf-0xd, BCR_ILCRE, 2, 0xd);
+ make_ipr_irq(0xf-0x9, BCR_ILCRE, 1, 0x9);
+ make_ipr_irq(0xf-0x1, BCR_ILCRE, 0, 0x1);
+ make_ipr_irq(0xf-0xf, BCR_ILCRF, 3, 0xf);
+ make_ipr_irq(0xf-0xb, BCR_ILCRF, 1, 0xb);
+ make_ipr_irq(0xf-0x7, BCR_ILCRG, 3, 0x7);
+ make_ipr_irq(0xf-0x6, BCR_ILCRG, 2, 0x6);
+ make_ipr_irq(0xf-0x4, BCR_ILCRG, 1, 0x4);
+#else
+ make_ipr_irq(14, BCR_ILCRA, 2, 0x0f-14);
+ make_ipr_irq(12, BCR_ILCRA, 1, 0x0f-12);
+ make_ipr_irq( 8, BCR_ILCRB, 1, 0x0f- 8);
+ make_ipr_irq( 6, BCR_ILCRC, 3, 0x0f- 6);
+ make_ipr_irq( 5, BCR_ILCRC, 2, 0x0f- 5);
+ make_ipr_irq( 4, BCR_ILCRC, 1, 0x0f- 4);
+ make_ipr_irq( 3, BCR_ILCRC, 0, 0x0f- 3);
+ make_ipr_irq( 1, BCR_ILCRD, 3, 0x0f- 1);
+
+ make_ipr_irq(10, BCR_ILCRD, 1, 0x0f-10); /* LAN */
+
+ make_ipr_irq( 0, BCR_ILCRE, 3, 0x0f- 0); /* PCIRQ3 */
+ make_ipr_irq(11, BCR_ILCRE, 2, 0x0f-11); /* PCIRQ2 */
+ make_ipr_irq( 9, BCR_ILCRE, 1, 0x0f- 9); /* PCIRQ1 */
+ make_ipr_irq( 7, BCR_ILCRE, 0, 0x0f- 7); /* PCIRQ0 */
+
+ /* #2, #13 are allocated for SLOT IRQ #1 and #2 (for now) */
+ /* NOTE: #2 and #13 are not used on PC */
+ make_ipr_irq(13, BCR_ILCRG, 1, 0x0f-13); /* SLOTIRQ2 */
+ make_ipr_irq( 2, BCR_ILCRG, 0, 0x0f- 2); /* SLOTIRQ1 */
+#endif
+}
diff --git a/arch/sh/boards/se/770x/led.c b/arch/sh/boards/se/770x/led.c
new file mode 100644
index 00000000000..5c64e8ab2cf
--- /dev/null
+++ b/arch/sh/boards/se/770x/led.c
@@ -0,0 +1,68 @@
+/*
+ * linux/arch/sh/kernel/led_se.c
+ *
+ * Copyright (C) 2000 Stuart Menefy <stuart.menefy@st.com>
+ *
+ * May be copied or modified under the terms of the GNU General Public
+ * License. See linux/COPYING for more information.
+ *
+ * This file contains Solution Engine specific LED code.
+ */
+
+#include <linux/config.h>
+#include <asm/se/se.h>
+
+static void mach_led(int position, int value)
+{
+ volatile unsigned short* p = (volatile unsigned short*)PA_LED;
+
+ if (value) {
+ *p |= (1<<8);
+ } else {
+ *p &= ~(1<<8);
+ }
+}
+
+#ifdef CONFIG_HEARTBEAT
+
+#include <linux/sched.h>
+
+/* Cycle the LED's in the clasic Knightrider/Sun pattern */
+void heartbeat_se(void)
+{
+ static unsigned int cnt = 0, period = 0;
+ volatile unsigned short* p = (volatile unsigned short*)PA_LED;
+ static unsigned bit = 0, up = 1;
+
+ cnt += 1;
+ if (cnt < period) {
+ return;
+ }
+
+ cnt = 0;
+
+ /* Go through the points (roughly!):
+ * f(0)=10, f(1)=16, f(2)=20, f(5)=35,f(inf)->110
+ */
+ period = 110 - ( (300<<FSHIFT)/
+ ((avenrun[0]/5) + (3<<FSHIFT)) );
+
+ if (up) {
+ if (bit == 7) {
+ bit--;
+ up=0;
+ } else {
+ bit ++;
+ }
+ } else {
+ if (bit == 0) {
+ bit++;
+ up=1;
+ } else {
+ bit--;
+ }
+ }
+ *p = 1<<(bit+8);
+
+}
+#endif /* CONFIG_HEARTBEAT */
diff --git a/arch/sh/boards/se/770x/mach.c b/arch/sh/boards/se/770x/mach.c
new file mode 100644
index 00000000000..f9b4c56cc47
--- /dev/null
+++ b/arch/sh/boards/se/770x/mach.c
@@ -0,0 +1,68 @@
+/*
+ * linux/arch/sh/kernel/mach_se.c
+ *
+ * Copyright (C) 2000 Stuart Menefy (stuart.menefy@st.com)
+ *
+ * May be copied or modified under the terms of the GNU General Public
+ * License. See linux/COPYING for more information.
+ *
+ * Machine vector for the Hitachi SolutionEngine
+ */
+
+#include <linux/config.h>
+#include <linux/init.h>
+
+#include <asm/machvec.h>
+#include <asm/rtc.h>
+#include <asm/machvec_init.h>
+
+#include <asm/se/io.h>
+
+void heartbeat_se(void);
+void setup_se(void);
+void init_se_IRQ(void);
+
+/*
+ * The Machine Vector
+ */
+
+struct sh_machine_vector mv_se __initmv = {
+#if defined(CONFIG_CPU_SH4)
+ .mv_nr_irqs = 48,
+#elif defined(CONFIG_CPU_SUBTYPE_SH7708)
+ .mv_nr_irqs = 32,
+#elif defined(CONFIG_CPU_SUBTYPE_SH7709)
+ .mv_nr_irqs = 61,
+#elif defined(CONFIG_CPU_SUBTYPE_SH7705)
+ .mv_nr_irqs = 86,
+#endif
+
+ .mv_inb = se_inb,
+ .mv_inw = se_inw,
+ .mv_inl = se_inl,
+ .mv_outb = se_outb,
+ .mv_outw = se_outw,
+ .mv_outl = se_outl,
+
+ .mv_inb_p = se_inb_p,
+ .mv_inw_p = se_inw,
+ .mv_inl_p = se_inl,
+ .mv_outb_p = se_outb_p,
+ .mv_outw_p = se_outw,
+ .mv_outl_p = se_outl,
+
+ .mv_insb = se_insb,
+ .mv_insw = se_insw,
+ .mv_insl = se_insl,
+ .mv_outsb = se_outsb,
+ .mv_outsw = se_outsw,
+ .mv_outsl = se_outsl,
+
+ .mv_isa_port2addr = se_isa_port2addr,
+
+ .mv_init_irq = init_se_IRQ,
+#ifdef CONFIG_HEARTBEAT
+ .mv_heartbeat = heartbeat_se,
+#endif
+};
+ALIAS_MV(se)
diff --git a/arch/sh/boards/se/770x/setup.c b/arch/sh/boards/se/770x/setup.c
new file mode 100644
index 00000000000..2bed46fb607
--- /dev/null
+++ b/arch/sh/boards/se/770x/setup.c
@@ -0,0 +1,85 @@
+/* $Id: setup.c,v 1.1.2.4 2002/03/02 21:57:07 lethal Exp $
+ *
+ * linux/arch/sh/boards/se/770x/setup.c
+ *
+ * Copyright (C) 2000 Kazumoto Kojima
+ *
+ * Hitachi SolutionEngine Support.
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+
+#include <linux/hdreg.h>
+#include <linux/ide.h>
+#include <asm/io.h>
+#include <asm/se/se.h>
+#include <asm/se/smc37c93x.h>
+
+/*
+ * Configure the Super I/O chip
+ */
+static void __init smsc_config(int index, int data)
+{
+ outb_p(index, INDEX_PORT);
+ outb_p(data, DATA_PORT);
+}
+
+static void __init init_smsc(void)
+{
+ outb_p(CONFIG_ENTER, CONFIG_PORT);
+ outb_p(CONFIG_ENTER, CONFIG_PORT);
+
+ /* FDC */
+ smsc_config(CURRENT_LDN_INDEX, LDN_FDC);
+ smsc_config(ACTIVATE_INDEX, 0x01);
+ smsc_config(IRQ_SELECT_INDEX, 6); /* IRQ6 */
+
+ /* IDE1 */
+ smsc_config(CURRENT_LDN_INDEX, LDN_IDE1);
+ smsc_config(ACTIVATE_INDEX, 0x01);
+ smsc_config(IRQ_SELECT_INDEX, 14); /* IRQ14 */
+
+ /* AUXIO (GPIO): to use IDE1 */
+ smsc_config(CURRENT_LDN_INDEX, LDN_AUXIO);
+ smsc_config(GPIO46_INDEX, 0x00); /* nIOROP */
+ smsc_config(GPIO47_INDEX, 0x00); /* nIOWOP */
+
+ /* COM1 */
+ smsc_config(CURRENT_LDN_INDEX, LDN_COM1);
+ smsc_config(ACTIVATE_INDEX, 0x01);
+ smsc_config(IO_BASE_HI_INDEX, 0x03);
+ smsc_config(IO_BASE_LO_INDEX, 0xf8);
+ smsc_config(IRQ_SELECT_INDEX, 4); /* IRQ4 */
+
+ /* COM2 */
+ smsc_config(CURRENT_LDN_INDEX, LDN_COM2);
+ smsc_config(ACTIVATE_INDEX, 0x01);
+ smsc_config(IO_BASE_HI_INDEX, 0x02);
+ smsc_config(IO_BASE_LO_INDEX, 0xf8);
+ smsc_config(IRQ_SELECT_INDEX, 3); /* IRQ3 */
+
+ /* RTC */
+ smsc_config(CURRENT_LDN_INDEX, LDN_RTC);
+ smsc_config(ACTIVATE_INDEX, 0x01);
+ smsc_config(IRQ_SELECT_INDEX, 8); /* IRQ8 */
+
+ /* XXX: PARPORT, KBD, and MOUSE will come here... */
+ outb_p(CONFIG_EXIT, CONFIG_PORT);
+}
+
+const char *get_system_type(void)
+{
+ return "SolutionEngine";
+}
+
+/*
+ * Initialize the board
+ */
+void __init platform_setup(void)
+{
+ init_smsc();
+ /* XXX: RTC setting comes here */
+}