aboutsummaryrefslogtreecommitdiff
path: root/arch/sh/boards/se/7751
diff options
context:
space:
mode:
Diffstat (limited to 'arch/sh/boards/se/7751')
-rw-r--r--arch/sh/boards/se/7751/Makefile8
-rw-r--r--arch/sh/boards/se/7751/io.c244
-rw-r--r--arch/sh/boards/se/7751/irq.c67
-rw-r--r--arch/sh/boards/se/7751/led.c68
-rw-r--r--arch/sh/boards/se/7751/mach.c55
-rw-r--r--arch/sh/boards/se/7751/pci.c148
-rw-r--r--arch/sh/boards/se/7751/setup.c228
7 files changed, 818 insertions, 0 deletions
diff --git a/arch/sh/boards/se/7751/Makefile b/arch/sh/boards/se/7751/Makefile
new file mode 100644
index 00000000000..ce7ca247f84
--- /dev/null
+++ b/arch/sh/boards/se/7751/Makefile
@@ -0,0 +1,8 @@
+#
+# Makefile for the 7751 SolutionEngine specific parts of the kernel
+#
+
+obj-y := mach.o setup.o io.o irq.o led.o
+
+obj-$(CONFIG_PCI) += pci.o
+
diff --git a/arch/sh/boards/se/7751/io.c b/arch/sh/boards/se/7751/io.c
new file mode 100644
index 00000000000..99041b26926
--- /dev/null
+++ b/arch/sh/boards/se/7751/io.c
@@ -0,0 +1,244 @@
+/*
+ * linux/arch/sh/kernel/io_7751se.c
+ *
+ * Copyright (C) 2001 Ian da Silva, Jeremy Siegel
+ * Based largely on io_se.c.
+ *
+ * I/O routine for Hitachi 7751 SolutionEngine.
+ *
+ * Initial version only to support LAN access; some
+ * placeholder code from io_se.c left in with the
+ * expectation of later SuperIO and PCMCIA access.
+ */
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <asm/io.h>
+#include <asm/se7751/se7751.h>
+#include <asm/addrspace.h>
+
+#include <linux/pci.h>
+#include "../../../drivers/pci/pci-sh7751.h"
+
+#if 0
+/******************************************************************
+ * Variables from io_se.c, related to PCMCIA (not PCI); we're not
+ * compiling them in, and have removed references from functions
+ * which follow. [Many checked for IO ports in the range bounded
+ * by sh_pcic_io_start/stop, and used sh_pcic_io_wbase as offset.
+ * As start/stop are uninitialized, only port 0x0 would match?]
+ * When used, remember to adjust names to avoid clash with io_se?
+ *****************************************************************/
+/* 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;
+/*************************************************************/
+#endif
+
+/*
+ * The 7751 Solution Engine uses the built-in PCI controller (PCIC)
+ * of the 7751 processor, and has a SuperIO accessible via the PCI.
+ * The board also includes a PCMCIA controller on its memory bus,
+ * like the other Solution Engine boards.
+ */
+
+#define PCIIOBR (volatile long *)PCI_REG(SH7751_PCIIOBR)
+#define PCIMBR (volatile long *)PCI_REG(SH7751_PCIMBR)
+#define PCI_IO_AREA SH7751_PCI_IO_BASE
+#define PCI_MEM_AREA SH7751_PCI_CONFIG_BASE
+
+#define PCI_IOMAP(adr) (PCI_IO_AREA + (adr & ~SH7751_PCIIOBR_MASK))
+
+#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))
+
+static inline void delay(void)
+{
+ ctrl_inw(0xa0000000);
+}
+
+static inline volatile __u16 *
+port2adr(unsigned int port)
+{
+ if (port >= 0x2000)
+ return (volatile __u16 *) (PA_MRSHPC + (port - 0x2000));
+#if 0
+ else
+ return (volatile __u16 *) (PA_SUPERIO + (port << 1));
+#endif
+ maybebadio(name,(unsigned long)port);
+ return (volatile __u16*)port;
+}
+
+#if 0
+/* The 7751 Solution Engine seems to have everything hooked */
+/* up pretty normally (nothing on high-bytes only...) so this */
+/* shouldn't be needed */
+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;
+}
+#endif
+
+/* In case someone configures the kernel w/o PCI support: in that */
+/* scenario, don't ever bother to check for PCI-window addresses */
+
+/* NOTE: WINDOW CHECK MAY BE A BIT OFF, HIGH PCIBIOS_MIN_IO WRAPS? */
+#if defined(CONFIG_PCI)
+#define CHECK_SH7751_PCIIO(port) \
+ ((port >= PCIBIOS_MIN_IO) && (port < (PCIBIOS_MIN_IO + SH7751_PCI_IO_SIZE)))
+#else
+#define CHECK_SH7751_PCIIO(port) (0)
+#endif
+
+/*
+ * General outline: remap really low stuff [eventually] to SuperIO,
+ * stuff in PCI IO space (at or above window at pci.h:PCIBIOS_MIN_IO)
+ * is mapped through the PCI IO window. Stuff with high bits (PXSEG)
+ * should be way beyond the window, and is used w/o translation for
+ * compatibility.
+ */
+unsigned char sh7751se_inb(unsigned long port)
+{
+ if (PXSEG(port))
+ return *(volatile unsigned char *)port;
+ else if (CHECK_SH7751_PCIIO(port))
+ return *(volatile unsigned char *)PCI_IOMAP(port);
+ else
+ return (*port2adr(port))&0xff;
+}
+
+unsigned char sh7751se_inb_p(unsigned long port)
+{
+ unsigned char v;
+
+ if (PXSEG(port))
+ v = *(volatile unsigned char *)port;
+ else if (CHECK_SH7751_PCIIO(port))
+ v = *(volatile unsigned char *)PCI_IOMAP(port);
+ else
+ v = (*port2adr(port))&0xff;
+ delay();
+ return v;
+}
+
+unsigned short sh7751se_inw(unsigned long port)
+{
+ if (PXSEG(port))
+ return *(volatile unsigned short *)port;
+ else if (CHECK_SH7751_PCIIO(port))
+ return *(volatile unsigned short *)PCI_IOMAP(port);
+ else if (port >= 0x2000)
+ return *port2adr(port);
+ else
+ maybebadio(inw, port);
+ return 0;
+}
+
+unsigned int sh7751se_inl(unsigned long port)
+{
+ if (PXSEG(port))
+ return *(volatile unsigned long *)port;
+ else if (CHECK_SH7751_PCIIO(port))
+ return *(volatile unsigned int *)PCI_IOMAP(port);
+ else if (port >= 0x2000)
+ return *port2adr(port);
+ else
+ maybebadio(inl, port);
+ return 0;
+}
+
+void sh7751se_outb(unsigned char value, unsigned long port)
+{
+
+ if (PXSEG(port))
+ *(volatile unsigned char *)port = value;
+ else if (CHECK_SH7751_PCIIO(port))
+ *((unsigned char*)PCI_IOMAP(port)) = value;
+ else
+ *(port2adr(port)) = value;
+}
+
+void sh7751se_outb_p(unsigned char value, unsigned long port)
+{
+ if (PXSEG(port))
+ *(volatile unsigned char *)port = value;
+ else if (CHECK_SH7751_PCIIO(port))
+ *((unsigned char*)PCI_IOMAP(port)) = value;
+ else
+ *(port2adr(port)) = value;
+ delay();
+}
+
+void sh7751se_outw(unsigned short value, unsigned long port)
+{
+ if (PXSEG(port))
+ *(volatile unsigned short *)port = value;
+ else if (CHECK_SH7751_PCIIO(port))
+ *((unsigned short *)PCI_IOMAP(port)) = value;
+ else if (port >= 0x2000)
+ *port2adr(port) = value;
+ else
+ maybebadio(outw, port);
+}
+
+void sh7751se_outl(unsigned int value, unsigned long port)
+{
+ if (PXSEG(port))
+ *(volatile unsigned long *)port = value;
+ else if (CHECK_SH7751_PCIIO(port))
+ *((unsigned long*)PCI_IOMAP(port)) = value;
+ else
+ maybebadio(outl, port);
+}
+
+void sh7751se_insl(unsigned long port, void *addr, unsigned long count)
+{
+ maybebadio(insl, port);
+}
+
+void sh7751se_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];
+
+#if 0
+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);
+ printk("sh_isa_mmap: start %x len %x offset %x (idx %x paddr %x)\n",
+ start, length, offset, idx, sh_isa_memmap[idx]);
+ return 0;
+}
+#endif
+
+unsigned long
+sh7751se_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/7751/irq.c b/arch/sh/boards/se/7751/irq.c
new file mode 100644
index 00000000000..ad71f3e66c1
--- /dev/null
+++ b/arch/sh/boards/se/7751/irq.c
@@ -0,0 +1,67 @@
+/*
+ * linux/arch/sh/boards/se/7751/irq.c
+ *
+ * Copyright (C) 2000 Kazumoto Kojima
+ *
+ * Hitachi SolutionEngine Support.
+ *
+ * Modified for 7751 Solution Engine by
+ * Ian da Silva and Jeremy Siegel, 2001.
+ */
+
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <asm/irq.h>
+#include <asm/se7751/se7751.h>
+
+/*
+ * Initialize IRQ setting
+ */
+void __init init_7751se_IRQ(void)
+{
+
+ /* Leave old Solution Engine code in for reference. */
+#if defined(CONFIG_SH_SOLUTION_ENGINE)
+ /*
+ * Super I/O (Just mimic PC):
+ * 1: keyboard
+ * 3: serial 0
+ * 4: serial 1
+ * 5: printer
+ * 6: floppy
+ * 8: rtc
+ * 12: mouse
+ * 14: ide0
+ */
+ 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 */
+
+#elif defined(CONFIG_SH_7751_SOLUTION_ENGINE)
+
+ make_ipr_irq(13, BCR_ILCRD, 3, 2);
+
+ /* Add additional calls to make_ipr_irq() as drivers are added
+ * and tested.
+ */
+#endif
+
+}
diff --git a/arch/sh/boards/se/7751/led.c b/arch/sh/boards/se/7751/led.c
new file mode 100644
index 00000000000..0c788230cf8
--- /dev/null
+++ b/arch/sh/boards/se/7751/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/se7751/se7751.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_7751se(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/7751/mach.c b/arch/sh/boards/se/7751/mach.c
new file mode 100644
index 00000000000..16d386b7e3b
--- /dev/null
+++ b/arch/sh/boards/se/7751/mach.c
@@ -0,0 +1,55 @@
+/*
+ * linux/arch/sh/kernel/mach_7751se.c
+ *
+ * Minor tweak of mach_se.c file to reference 7751se-specific items.
+ *
+ * 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 7751 SolutionEngine
+ */
+
+#include <linux/config.h>
+#include <linux/init.h>
+
+#include <asm/machvec.h>
+#include <asm/rtc.h>
+#include <asm/machvec_init.h>
+
+#include <asm/se7751/io.h>
+
+void heartbeat_7751se(void);
+void init_7751se_IRQ(void);
+
+/*
+ * The Machine Vector
+ */
+
+struct sh_machine_vector mv_7751se __initmv = {
+ .mv_nr_irqs = 72,
+
+ .mv_inb = sh7751se_inb,
+ .mv_inw = sh7751se_inw,
+ .mv_inl = sh7751se_inl,
+ .mv_outb = sh7751se_outb,
+ .mv_outw = sh7751se_outw,
+ .mv_outl = sh7751se_outl,
+
+ .mv_inb_p = sh7751se_inb_p,
+ .mv_inw_p = sh7751se_inw,
+ .mv_inl_p = sh7751se_inl,
+ .mv_outb_p = sh7751se_outb_p,
+ .mv_outw_p = sh7751se_outw,
+ .mv_outl_p = sh7751se_outl,
+
+ .mv_insl = sh7751se_insl,
+ .mv_outsl = sh7751se_outsl,
+
+ .mv_isa_port2addr = sh7751se_isa_port2addr,
+
+ .mv_init_irq = init_7751se_IRQ,
+#ifdef CONFIG_HEARTBEAT
+ .mv_heartbeat = heartbeat_7751se,
+#endif
+};
+ALIAS_MV(7751se)
diff --git a/arch/sh/boards/se/7751/pci.c b/arch/sh/boards/se/7751/pci.c
new file mode 100644
index 00000000000..1f273efd2cf
--- /dev/null
+++ b/arch/sh/boards/se/7751/pci.c
@@ -0,0 +1,148 @@
+/*
+ * linux/arch/sh/kernel/pci-7751se.c
+ *
+ * Author: Ian DaSilva (idasilva@mvista.com)
+ *
+ * Highly leveraged from pci-bigsur.c, written by Dustin McIntire.
+ *
+ * May be copied or modified under the terms of the GNU General Public
+ * License. See linux/COPYING for more information.
+ *
+ * PCI initialization for the Hitachi SH7751 Solution Engine board (MS7751SE01)
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/pci.h>
+
+#include <asm/io.h>
+#include "../../../drivers/pci/pci-sh7751.h"
+
+#define PCIMCR_MRSET_OFF 0xBFFFFFFF
+#define PCIMCR_RFSH_OFF 0xFFFFFFFB
+
+/*
+ * Only long word accesses of the PCIC's internal local registers and the
+ * configuration registers from the CPU is supported.
+ */
+#define PCIC_WRITE(x,v) writel((v), PCI_REG(x))
+#define PCIC_READ(x) readl(PCI_REG(x))
+
+/*
+ * Description: This function sets up and initializes the pcic, sets
+ * up the BARS, maps the DRAM into the address space etc, etc.
+ */
+int __init pcibios_init_platform(void)
+{
+ unsigned long bcr1, wcr1, wcr2, wcr3, mcr;
+ unsigned short bcr2;
+
+ /*
+ * Initialize the slave bus controller on the pcic. The values used
+ * here should not be hardcoded, but they should be taken from the bsc
+ * on the processor, to make this function as generic as possible.
+ * (i.e. Another sbc may usr different SDRAM timing settings -- in order
+ * for the pcic to work, its settings need to be exactly the same.)
+ */
+ bcr1 = (*(volatile unsigned long*)(SH7751_BCR1));
+ bcr2 = (*(volatile unsigned short*)(SH7751_BCR2));
+ wcr1 = (*(volatile unsigned long*)(SH7751_WCR1));
+ wcr2 = (*(volatile unsigned long*)(SH7751_WCR2));
+ wcr3 = (*(volatile unsigned long*)(SH7751_WCR3));
+ mcr = (*(volatile unsigned long*)(SH7751_MCR));
+
+ bcr1 = bcr1 | 0x00080000; /* Enable Bit 19, BREQEN */
+ (*(volatile unsigned long*)(SH7751_BCR1)) = bcr1;
+
+ bcr1 = bcr1 | 0x40080000; /* Enable Bit 19 BREQEN, set PCIC to slave */
+ PCIC_WRITE(SH7751_PCIBCR1, bcr1); /* PCIC BCR1 */
+ PCIC_WRITE(SH7751_PCIBCR2, bcr2); /* PCIC BCR2 */
+ PCIC_WRITE(SH7751_PCIWCR1, wcr1); /* PCIC WCR1 */
+ PCIC_WRITE(SH7751_PCIWCR2, wcr2); /* PCIC WCR2 */
+ PCIC_WRITE(SH7751_PCIWCR3, wcr3); /* PCIC WCR3 */
+ mcr = (mcr & PCIMCR_MRSET_OFF) & PCIMCR_RFSH_OFF;
+ PCIC_WRITE(SH7751_PCIMCR, mcr); /* PCIC MCR */
+
+
+ /* Enable all interrupts, so we know what to fix */
+ PCIC_WRITE(SH7751_PCIINTM, 0x0000c3ff);
+ PCIC_WRITE(SH7751_PCIAINTM, 0x0000380f);
+
+ /* Set up standard PCI config registers */
+ PCIC_WRITE(SH7751_PCICONF1, 0xF39000C7); /* Bus Master, Mem & I/O access */
+ PCIC_WRITE(SH7751_PCICONF2, 0x00000000); /* PCI Class code & Revision ID */
+ PCIC_WRITE(SH7751_PCICONF4, 0xab000001); /* PCI I/O address (local regs) */
+ PCIC_WRITE(SH7751_PCICONF5, 0x0c000000); /* PCI MEM address (local RAM) */
+ PCIC_WRITE(SH7751_PCICONF6, 0xd0000000); /* PCI MEM address (unused) */
+ PCIC_WRITE(SH7751_PCICONF11, 0x35051054); /* PCI Subsystem ID & Vendor ID */
+ PCIC_WRITE(SH7751_PCILSR0, 0x03f00000); /* MEM (full 64M exposed) */
+ PCIC_WRITE(SH7751_PCILSR1, 0x00000000); /* MEM (unused) */
+ PCIC_WRITE(SH7751_PCILAR0, 0x0c000000); /* MEM (direct map from PCI) */
+ PCIC_WRITE(SH7751_PCILAR1, 0x00000000); /* MEM (unused) */
+
+ /* Now turn it on... */
+ PCIC_WRITE(SH7751_PCICR, 0xa5000001);
+
+ /*
+ * Set PCIMBR and PCIIOBR here, assuming a single window
+ * (16M MEM, 256K IO) is enough. If a larger space is
+ * needed, the readx/writex and inx/outx functions will
+ * have to do more (e.g. setting registers for each call).
+ */
+
+ /*
+ * Set the MBR so PCI address is one-to-one with window,
+ * meaning all calls go straight through... use BUG_ON to
+ * catch erroneous assumption.
+ */
+ BUG_ON(PCIBIOS_MIN_MEM != SH7751_PCI_MEMORY_BASE);
+
+ PCIC_WRITE(SH7751_PCIMBR, PCIBIOS_MIN_MEM);
+
+ /* Set IOBR for window containing area specified in pci.h */
+ PCIC_WRITE(SH7751_PCIIOBR, (PCIBIOS_MIN_IO & SH7751_PCIIOBR_MASK));
+
+ /* All done, may as well say so... */
+ printk("SH7751 PCI: Finished initialization of the PCI controller\n");
+
+ return 1;
+}
+
+int __init pcibios_map_platform_irq(u8 slot, u8 pin)
+{
+ switch (slot) {
+ case 0: return 13;
+ case 1: return 13; /* AMD Ethernet controller */
+ case 2: return -1;
+ case 3: return -1;
+ case 4: return -1;
+ default:
+ printk("PCI: Bad IRQ mapping request for slot %d\n", slot);
+ return -1;
+ }
+}
+
+static struct resource sh7751_io_resource = {
+ .name = "SH7751 IO",
+ .start = SH7751_PCI_IO_BASE,
+ .end = SH7751_PCI_IO_BASE + SH7751_PCI_IO_SIZE - 1,
+ .flags = IORESOURCE_IO
+};
+
+static struct resource sh7751_mem_resource = {
+ .name = "SH7751 mem",
+ .start = SH7751_PCI_MEMORY_BASE,
+ .end = SH7751_PCI_MEMORY_BASE + SH7751_PCI_MEM_SIZE - 1,
+ .flags = IORESOURCE_MEM
+};
+
+extern struct pci_ops sh7751_pci_ops;
+
+struct pci_channel board_pci_channels[] = {
+ { &sh7751_pci_ops, &sh7751_io_resource, &sh7751_mem_resource, 0, 0xff },
+ { NULL, NULL, NULL, 0, 0 },
+};
+
diff --git a/arch/sh/boards/se/7751/setup.c b/arch/sh/boards/se/7751/setup.c
new file mode 100644
index 00000000000..9d111bb884f
--- /dev/null
+++ b/arch/sh/boards/se/7751/setup.c
@@ -0,0 +1,228 @@
+/*
+ * linux/arch/sh/kernel/setup_7751se.c
+ *
+ * Copyright (C) 2000 Kazumoto Kojima
+ *
+ * Hitachi SolutionEngine Support.
+ *
+ * Modified for 7751 Solution Engine by
+ * Ian da Silva and Jeremy Siegel, 2001.
+ */
+
+#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/se7751/se7751.h>
+
+#ifdef CONFIG_SH_KGDB
+#include <asm/kgdb.h>
+#endif
+
+/*
+ * Configure the Super I/O chip
+ */
+#if 0
+/* Leftover code from regular Solution Engine, for reference. */
+/* The SH7751 Solution Engine has a different SuperIO. */
+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);
+}
+#endif
+
+const char *get_system_type(void)
+{
+ return "7751 SolutionEngine";
+}
+
+#ifdef CONFIG_SH_KGDB
+static int kgdb_uart_setup(void);
+static struct kgdb_sermap kgdb_uart_sermap =
+{ "ttyS", 0, kgdb_uart_setup, NULL };
+#endif
+
+/*
+ * Initialize the board
+ */
+void __init platform_setup(void)
+{
+ /* Call init_smsc() replacement to set up SuperIO. */
+ /* XXX: RTC setting comes here */
+#ifdef CONFIG_SH_KGDB
+ kgdb_register_sermap(&kgdb_uart_sermap);
+#endif
+}
+
+/*********************************************************************
+ * Currently a hack (e.g. does not interact well w/serial.c, lots of *
+ * hardcoded stuff) but may be useful if SCI/F needs debugging. *
+ * Mostly copied from x86 code (see files asm-i386/kgdb_local.h and *
+ * arch/i386/lib/kgdb_serial.c). *
+ *********************************************************************/
+
+#ifdef CONFIG_SH_KGDB
+#include <linux/types.h>
+#include <linux/serial.h>
+#include <linux/serialP.h>
+#include <linux/serial_reg.h>
+
+#define COM1_PORT 0x3f8 /* Base I/O address */
+#define COM1_IRQ 4 /* IRQ not used yet */
+#define COM2_PORT 0x2f8 /* Base I/O address */
+#define COM2_IRQ 3 /* IRQ not used yet */
+
+#define SB_CLOCK 1843200 /* Serial baud clock */
+#define SB_BASE (SB_CLOCK/16)
+#define SB_MCR UART_MCR_OUT2 | UART_MCR_DTR | UART_MCR_RTS
+
+struct uart_port {
+ int base;
+};
+#define UART_NPORTS 2
+struct uart_port uart_ports[] = {
+ { COM1_PORT },
+ { COM2_PORT },
+};
+struct uart_port *kgdb_uart_port;
+
+#define UART_IN(reg) inb_p(kgdb_uart_port->base + reg)
+#define UART_OUT(reg,v) outb_p((v), kgdb_uart_port->base + reg)
+
+/* Basic read/write functions for the UART */
+#define UART_LSR_RXCERR (UART_LSR_BI | UART_LSR_FE | UART_LSR_PE)
+static int kgdb_uart_getchar(void)
+{
+ int lsr;
+ int c = -1;
+
+ while (c == -1) {
+ lsr = UART_IN(UART_LSR);
+ if (lsr & UART_LSR_DR)
+ c = UART_IN(UART_RX);
+ if ((lsr & UART_LSR_RXCERR))
+ c = -1;
+ }
+ return c;
+}
+
+static void kgdb_uart_putchar(int c)
+{
+ while ((UART_IN(UART_LSR) & UART_LSR_THRE) == 0)
+ ;
+ UART_OUT(UART_TX, c);
+}
+
+/*
+ * Initialize UART to configured/requested values.
+ * (But we don't interrupts yet, or interact w/serial.c)
+ */
+static int kgdb_uart_setup(void)
+{
+ int port;
+ int lcr = 0;
+ int bdiv = 0;
+
+ if (kgdb_portnum >= UART_NPORTS) {
+ KGDB_PRINTK("uart port %d invalid.\n", kgdb_portnum);
+ return -1;
+ }
+
+ kgdb_uart_port = &uart_ports[kgdb_portnum];
+
+ /* Init sequence from gdb_hook_interrupt */
+ UART_IN(UART_RX);
+ UART_OUT(UART_IER, 0);
+
+ UART_IN(UART_RX); /* Serial driver comments say */
+ UART_IN(UART_IIR); /* this clears interrupt regs */
+ UART_IN(UART_MSR);
+
+ /* Figure basic LCR values */
+ switch (kgdb_bits) {
+ case '7':
+ lcr |= UART_LCR_WLEN7;
+ break;
+ default: case '8':
+ lcr |= UART_LCR_WLEN8;
+ break;
+ }
+ switch (kgdb_parity) {
+ case 'O':
+ lcr |= UART_LCR_PARITY;
+ break;
+ case 'E':
+ lcr |= (UART_LCR_PARITY | UART_LCR_EPAR);
+ break;
+ default: break;
+ }
+
+ /* Figure the baud rate divisor */
+ bdiv = (SB_BASE/kgdb_baud);
+
+ /* Set the baud rate and LCR values */
+ UART_OUT(UART_LCR, (lcr | UART_LCR_DLAB));
+ UART_OUT(UART_DLL, (bdiv & 0xff));
+ UART_OUT(UART_DLM, ((bdiv >> 8) & 0xff));
+ UART_OUT(UART_LCR, lcr);
+
+ /* Set the MCR */
+ UART_OUT(UART_MCR, SB_MCR);
+
+ /* Turn off FIFOs for now */
+ UART_OUT(UART_FCR, 0);
+
+ /* Setup complete: initialize function pointers */
+ kgdb_getchar = kgdb_uart_getchar;
+ kgdb_putchar = kgdb_uart_putchar;
+
+ return 0;
+}
+#endif /* CONFIG_SH_KGDB */