Linux-2.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!
diff --git a/arch/sh/boards/mpc1211/Makefile b/arch/sh/boards/mpc1211/Makefile
new file mode 100644
index 0000000..1644ebe
--- /dev/null
+++ b/arch/sh/boards/mpc1211/Makefile
@@ -0,0 +1,8 @@
+#
+# Makefile for the Interface (CTP/PCI/MPC-SH02) specific parts of the kernel
+#
+
+obj-y	 := setup.o rtc.o led.o
+
+obj-$(CONFIG_PCI) += pci.o
+
diff --git a/arch/sh/boards/mpc1211/led.c b/arch/sh/boards/mpc1211/led.c
new file mode 100644
index 0000000..0a31bee
--- /dev/null
+++ b/arch/sh/boards/mpc1211/led.c
@@ -0,0 +1,64 @@
+/*
+ * linux/arch/sh/kernel/led_mpc1211.c
+ *
+ * Copyright (C) 2001  Saito.K & Jeanne
+ *
+ * This file contains Interface MPC-1211 specific LED code.
+ */
+
+#include <linux/config.h>
+
+static void mach_led(int position, int value)
+{
+	volatile unsigned char* p = (volatile unsigned char*)0xa2000000;
+
+	if (value) {
+		*p |= 1;
+	} else {
+		*p &= ~1;
+	}
+}
+
+#ifdef CONFIG_HEARTBEAT
+
+#include <linux/sched.h>
+
+/* Cycle the LED's in the clasic Knightrider/Sun pattern */
+void heartbeat_mpc1211(void)
+{
+	static unsigned int cnt = 0, period = 0;
+	volatile unsigned char* p = (volatile unsigned char*)0xa2000000;
+	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;
+
+}
+#endif /* CONFIG_HEARTBEAT */
diff --git a/arch/sh/boards/mpc1211/pci.c b/arch/sh/boards/mpc1211/pci.c
new file mode 100644
index 0000000..ba3a654
--- /dev/null
+++ b/arch/sh/boards/mpc1211/pci.c
@@ -0,0 +1,296 @@
+/*
+ *	Low-Level PCI Support for the MPC-1211(CTP/PCI/MPC-SH02)
+ *
+ *  (c) 2002-2003 Saito.K & Jeanne
+ *
+ *  Dustin McIntire (dustin@sensoria.com)
+ *	Derived from arch/i386/kernel/pci-*.c which bore the message:
+ *	(c) 1999--2000 Martin Mares <mj@ucw.cz>
+ *	
+ *  May be copied or modified under the terms of the GNU General Public
+ *  License.  See linux/COPYING for more information.
+ *
+ */
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/pci.h>
+#include <linux/sched.h>
+#include <linux/ioport.h>
+#include <linux/errno.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+
+#include <asm/machvec.h>
+#include <asm/io.h>
+#include <asm/mpc1211/pci.h>
+
+static struct resource mpcpci_io_resource = {
+	"MPCPCI IO",
+	0x00000000,
+	0xffffffff,
+	IORESOURCE_IO
+};
+
+static struct resource mpcpci_mem_resource = {
+	"MPCPCI mem",
+	0x00000000,
+	0xffffffff,
+	IORESOURCE_MEM
+};
+
+static struct pci_ops pci_direct_conf1;
+struct pci_channel board_pci_channels[] = {
+	{&pci_direct_conf1, &mpcpci_io_resource, &mpcpci_mem_resource, 0, 256},
+	{NULL, NULL, NULL, 0, 0},
+};
+
+/*
+ * Direct access to PCI hardware...
+ */
+
+
+#define CONFIG_CMD(bus, devfn, where) (0x80000000 | (bus->number << 16) | (devfn << 8) | (where & ~3))
+
+/*
+ * Functions for accessing PCI configuration space with type 1 accesses
+ */
+static int pci_conf1_read(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 *value)
+{
+	u32 word;
+	unsigned long flags;
+
+	/* 
+	 * PCIPDR may only be accessed as 32 bit words, 
+	 * so we must do byte alignment by hand 
+	 */
+	local_irq_save(flags);
+	writel(CONFIG_CMD(bus,devfn,where), PCIPAR);
+	word = readl(PCIPDR);
+	local_irq_restore(flags);
+
+	switch (size) {
+	case 1:
+		switch (where & 0x3) {
+		case 3:
+			*value = (u8)(word >> 24);
+			break;
+		case 2:
+			*value = (u8)(word >> 16);
+			break;
+		case 1:
+			*value = (u8)(word >> 8);
+			break;
+		default:
+			*value = (u8)word;
+			break;
+		}
+		break;
+	case 2:
+		switch (where & 0x3) {
+		case 3:
+			*value = (u16)(word >> 24);
+			local_irq_save(flags);
+			writel(CONFIG_CMD(bus,devfn,(where+1)), PCIPAR);
+			word = readl(PCIPDR);
+			local_irq_restore(flags);
+			*value |= ((word & 0xff) << 8);
+			break;
+		case 2:
+			*value = (u16)(word >> 16);
+			break;
+		case 1:
+			*value = (u16)(word >> 8);
+			break;
+		default:
+			*value = (u16)word;
+			break;
+		}
+		break;
+	case 4:
+		*value = word;
+		break;
+	}
+	PCIDBG(4,"pci_conf1_read@0x%08x=0x%x\n", CONFIG_CMD(bus,devfn,where),*value); 
+	return PCIBIOS_SUCCESSFUL;    
+}
+
+/* 
+ * Since MPC-1211 only does 32bit access we'll have to do a read,mask,write operation.  
+ * We'll allow an odd byte offset, though it should be illegal.
+ */ 
+static int pci_conf1_write(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 value)
+{
+	u32 word,mask = 0;
+	unsigned long flags;
+	u32 shift = (where & 3) * 8;
+
+	if(size == 1) {
+		mask = ((1 << 8) - 1) << shift;  // create the byte mask
+	} else if(size == 2){
+		if(shift == 24)
+			return PCIBIOS_BAD_REGISTER_NUMBER;           
+		mask = ((1 << 16) - 1) << shift;  // create the word mask
+	}
+	local_irq_save(flags);
+	writel(CONFIG_CMD(bus,devfn,where), PCIPAR);
+	if(size == 4){
+		writel(value, PCIPDR);
+		local_irq_restore(flags);
+		PCIDBG(4,"pci_conf1_write@0x%08x=0x%x\n", CONFIG_CMD(bus,devfn,where),value);
+		return PCIBIOS_SUCCESSFUL;
+	}
+	word = readl(PCIPDR);
+	word &= ~mask;
+	word |= ((value << shift) & mask);
+	writel(word, PCIPDR);
+	local_irq_restore(flags);
+	PCIDBG(4,"pci_conf1_write@0x%08x=0x%x\n", CONFIG_CMD(bus,devfn,where),word);
+	return PCIBIOS_SUCCESSFUL;
+}
+
+#undef CONFIG_CMD
+
+static struct pci_ops pci_direct_conf1 = {
+	.read =		pci_conf1_read,
+	.write = 	pci_conf1_write,
+};
+
+static void __devinit quirk_ali_ide_ports(struct pci_dev *dev)
+{
+        dev->resource[0].start = 0x1f0;
+	dev->resource[0].end   = 0x1f7;
+	dev->resource[0].flags = IORESOURCE_IO;
+        dev->resource[1].start = 0x3f6;
+	dev->resource[1].end   = 0x3f6;
+	dev->resource[1].flags = IORESOURCE_IO;
+        dev->resource[2].start = 0x170;
+	dev->resource[2].end   = 0x177;
+	dev->resource[2].flags = IORESOURCE_IO;
+        dev->resource[3].start = 0x376;
+	dev->resource[3].end   = 0x376;
+	dev->resource[3].flags = IORESOURCE_IO;
+        dev->resource[4].start = 0xf000;
+	dev->resource[4].end   = 0xf00f;
+	dev->resource[4].flags = IORESOURCE_IO;
+}
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M5229, quirk_ali_ide_ports);
+
+char * __devinit pcibios_setup(char *str)
+{
+	return str;
+}
+
+/*
+ *  Called after each bus is probed, but before its children
+ *  are examined.
+ */
+
+void __init pcibios_fixup_bus(struct pci_bus *b)
+{
+	pci_read_bridge_bases(b);
+}
+
+/* 
+ * 	IRQ functions 
+ */
+static inline u8 bridge_swizzle(u8 pin, u8 slot)
+{
+        return (((pin-1) + slot) % 4) + 1;
+}
+
+static inline u8 bridge_swizzle_pci_1(u8 pin, u8 slot)
+{
+        return (((pin-1) - slot) & 3) + 1;
+}
+
+static u8 __init mpc1211_swizzle(struct pci_dev *dev, u8 *pinp)
+{
+	unsigned long flags;
+        u8 pin = *pinp;
+	u32 word;
+
+	for ( ; dev->bus->self; dev = dev->bus->self) {
+		if (!pin)
+			continue;
+
+		if (dev->bus->number == 1) {
+			local_irq_save(flags);
+			writel(0x80000000 | 0x2c, PCIPAR);
+			word = readl(PCIPDR);
+			local_irq_restore(flags);
+			word >>= 16;
+
+			if (word == 0x0001)
+				pin = bridge_swizzle_pci_1(pin, PCI_SLOT(dev->devfn));
+			else
+				pin = bridge_swizzle(pin, PCI_SLOT(dev->devfn));
+		} else
+			pin = bridge_swizzle(pin, PCI_SLOT(dev->devfn));
+	}
+
+	*pinp = pin;
+
+	return PCI_SLOT(dev->devfn);
+}
+
+static int __init map_mpc1211_irq(struct pci_dev *dev, u8 slot, u8 pin)
+{
+	int irq = -1;
+
+	/* now lookup the actual IRQ on a platform specific basis (pci-'platform'.c) */
+	if (dev->bus->number == 0) {
+		switch (slot) {
+		case 13:   irq =  9; break;   /* USB */
+		case 22:   irq = 10; break;   /* LAN */
+		default:   irq =  0; break;
+	  	}
+	} else {
+		switch (pin) {
+		case 0:   irq =  0; break;
+		case 1:   irq =  7; break;
+		case 2:   irq =  9; break;
+		case 3:   irq = 10; break;
+		case 4:   irq = 11; break;
+		}
+	}
+
+	if( irq < 0 ) {
+		PCIDBG(3, "PCI: Error mapping IRQ on device %s\n", pci_name(dev));
+		return irq;
+	}
+	
+	PCIDBG(2, "Setting IRQ for slot %s to %d\n", pci_name(dev), irq);
+
+	return irq;
+}
+
+void __init pcibios_fixup_irqs(void)
+{
+	pci_fixup_irqs(mpc1211_swizzle, map_mpc1211_irq);
+}
+
+void pcibios_align_resource(void *data, struct resource *res,
+			    unsigned long size, unsigned long align)
+{
+	unsigned long start = res->start;
+
+	if (res->flags & IORESOURCE_IO) {
+		if (start >= 0x10000UL) {
+			if ((start & 0xffffUL) < 0x4000UL) {
+				start = (start & 0xffff0000UL) + 0x4000UL;
+			} else if ((start & 0xffffUL) >= 0xf000UL) {
+				start = (start & 0xffff0000UL) + 0x10000UL;
+			}
+			res->start = start;
+		} else {
+			if (start & 0x300) {
+				start = (start + 0x3ff) & ~0x3ff;
+				res->start = start;
+			}
+		}
+	}
+}
+
diff --git a/arch/sh/boards/mpc1211/rtc.c b/arch/sh/boards/mpc1211/rtc.c
new file mode 100644
index 0000000..4d100f0
--- /dev/null
+++ b/arch/sh/boards/mpc1211/rtc.c
@@ -0,0 +1,152 @@
+/*
+ * linux/arch/sh/kernel/rtc-mpc1211.c -- MPC-1211 on-chip RTC support
+ *
+ *  Copyright (C) 2002  Saito.K & Jeanne
+ *
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/time.h>
+#include <linux/mc146818rtc.h>
+
+#ifndef BCD_TO_BIN
+#define BCD_TO_BIN(val) ((val)=((val)&15) + ((val)>>4)*10)
+#endif
+
+#ifndef BIN_TO_BCD
+#define BIN_TO_BCD(val) ((val)=(((val)/10)<<4) + (val)%10)
+#endif
+
+/* arc/i386/kernel/time.c */
+unsigned long get_cmos_time(void)
+{
+	unsigned int year, mon, day, hour, min, sec;
+	int i;
+
+	spin_lock(&rtc_lock);
+	/* The Linux interpretation of the CMOS clock register contents:
+	 * When the Update-In-Progress (UIP) flag goes from 1 to 0, the
+	 * RTC registers show the second which has precisely just started.
+	 * Let's hope other operating systems interpret the RTC the same way.
+	 */
+	/* read RTC exactly on falling edge of update flag */
+	for (i = 0 ; i < 1000000 ; i++)	/* may take up to 1 second... */
+		if (CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP)
+			break;
+	for (i = 0 ; i < 1000000 ; i++)	/* must try at least 2.228 ms */
+		if (!(CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP))
+			break;
+	do { /* Isn't this overkill ? UIP above should guarantee consistency */
+		sec = CMOS_READ(RTC_SECONDS);
+		min = CMOS_READ(RTC_MINUTES);
+		hour = CMOS_READ(RTC_HOURS);
+		day = CMOS_READ(RTC_DAY_OF_MONTH);
+		mon = CMOS_READ(RTC_MONTH);
+		year = CMOS_READ(RTC_YEAR);
+	} while (sec != CMOS_READ(RTC_SECONDS));
+	if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY) || RTC_ALWAYS_BCD)
+	  {
+	    BCD_TO_BIN(sec);
+	    BCD_TO_BIN(min);
+	    BCD_TO_BIN(hour);
+	    BCD_TO_BIN(day);
+	    BCD_TO_BIN(mon);
+	    BCD_TO_BIN(year);
+	  }
+	spin_unlock(&rtc_lock);
+	if ((year += 1900) < 1970)
+		year += 100;
+	return mktime(year, mon, day, hour, min, sec);
+}
+
+void mpc1211_rtc_gettimeofday(struct timeval *tv)
+{
+
+	tv->tv_sec = get_cmos_time();
+	tv->tv_usec = 0;
+}
+
+/* arc/i386/kernel/time.c */
+/*
+ * In order to set the CMOS clock precisely, set_rtc_mmss has to be
+ * called 500 ms after the second nowtime has started, because when
+ * nowtime is written into the registers of the CMOS clock, it will
+ * jump to the next second precisely 500 ms later. Check the Motorola
+ * MC146818A or Dallas DS12887 data sheet for details.
+ *
+ * BUG: This routine does not handle hour overflow properly; it just
+ *      sets the minutes. Usually you'll only notice that after reboot!
+ */
+static int set_rtc_mmss(unsigned long nowtime)
+{
+	int retval = 0;
+	int real_seconds, real_minutes, cmos_minutes;
+	unsigned char save_control, save_freq_select;
+
+	/* gets recalled with irq locally disabled */
+	spin_lock(&rtc_lock);
+	save_control = CMOS_READ(RTC_CONTROL); /* tell the clock it's being set */
+	CMOS_WRITE((save_control|RTC_SET), RTC_CONTROL);
+
+	save_freq_select = CMOS_READ(RTC_FREQ_SELECT); /* stop and reset prescaler */
+	CMOS_WRITE((save_freq_select|RTC_DIV_RESET2), RTC_FREQ_SELECT);
+
+	cmos_minutes = CMOS_READ(RTC_MINUTES);
+	if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD)
+		BCD_TO_BIN(cmos_minutes);
+
+	/*
+	 * since we're only adjusting minutes and seconds,
+	 * don't interfere with hour overflow. This avoids
+	 * messing with unknown time zones but requires your
+	 * RTC not to be off by more than 15 minutes
+	 */
+	real_seconds = nowtime % 60;
+	real_minutes = nowtime / 60;
+	if (((abs(real_minutes - cmos_minutes) + 15)/30) & 1)
+		real_minutes += 30;		/* correct for half hour time zone */
+	real_minutes %= 60;
+
+	if (abs(real_minutes - cmos_minutes) < 30) {
+		if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) {
+			BIN_TO_BCD(real_seconds);
+			BIN_TO_BCD(real_minutes);
+		}
+		CMOS_WRITE(real_seconds,RTC_SECONDS);
+		CMOS_WRITE(real_minutes,RTC_MINUTES);
+	} else {
+		printk(KERN_WARNING
+		       "set_rtc_mmss: can't update from %d to %d\n",
+		       cmos_minutes, real_minutes);
+		retval = -1;
+	}
+
+	/* The following flags have to be released exactly in this order,
+	 * otherwise the DS12887 (popular MC146818A clone with integrated
+	 * battery and quartz) will not reset the oscillator and will not
+	 * update precisely 500 ms later. You won't find this mentioned in
+	 * the Dallas Semiconductor data sheets, but who believes data
+	 * sheets anyway ...                           -- Markus Kuhn
+	 */
+	CMOS_WRITE(save_control, RTC_CONTROL);
+	CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT);
+	spin_unlock(&rtc_lock);
+
+	return retval;
+}
+
+int mpc1211_rtc_settimeofday(const struct timeval *tv)
+{
+	unsigned long nowtime = tv->tv_sec;
+
+	return set_rtc_mmss(nowtime);
+}
+
+void mpc1211_time_init(void)
+{
+	rtc_get_time = mpc1211_rtc_gettimeofday;
+	rtc_set_time = mpc1211_rtc_settimeofday;
+}
+
diff --git a/arch/sh/boards/mpc1211/setup.c b/arch/sh/boards/mpc1211/setup.c
new file mode 100644
index 0000000..2bb581b
--- /dev/null
+++ b/arch/sh/boards/mpc1211/setup.c
@@ -0,0 +1,360 @@
+/*
+ * linux/arch/sh/board/mpc1211/setup.c
+ *
+ * Copyright (C) 2002  Saito.K & Jeanne,  Fujii.Y
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <linux/hdreg.h>
+#include <linux/ide.h>
+#include <linux/interrupt.h>
+
+#include <asm/io.h>
+#include <asm/machvec.h>
+#include <asm/mpc1211/mpc1211.h>
+#include <asm/mpc1211/pci.h>
+#include <asm/mpc1211/m1543c.h>
+
+
+/* ALI15X3 SMBus address offsets */
+#define SMBHSTSTS   (0 + 0x3100)
+#define SMBHSTCNT   (1 + 0x3100)
+#define SMBHSTSTART (2 + 0x3100)
+#define SMBHSTCMD   (7 + 0x3100)
+#define SMBHSTADD   (3 + 0x3100)
+#define SMBHSTDAT0  (4 + 0x3100)
+#define SMBHSTDAT1  (5 + 0x3100)
+#define SMBBLKDAT   (6 + 0x3100)
+
+/* Other settings */
+#define MAX_TIMEOUT 500		/* times 1/100 sec */
+
+/* ALI15X3 command constants */
+#define ALI15X3_ABORT      0x04
+#define ALI15X3_T_OUT      0x08
+#define ALI15X3_QUICK      0x00
+#define ALI15X3_BYTE       0x10
+#define ALI15X3_BYTE_DATA  0x20
+#define ALI15X3_WORD_DATA  0x30
+#define ALI15X3_BLOCK_DATA 0x40
+#define ALI15X3_BLOCK_CLR  0x80
+
+/* ALI15X3 status register bits */
+#define ALI15X3_STS_IDLE	0x04
+#define ALI15X3_STS_BUSY	0x08
+#define ALI15X3_STS_DONE	0x10
+#define ALI15X3_STS_DEV		0x20	/* device error */
+#define ALI15X3_STS_COLL	0x40	/* collision or no response */
+#define ALI15X3_STS_TERM	0x80	/* terminated by abort */
+#define ALI15X3_STS_ERR		0xE0	/* all the bad error bits */
+
+const char *get_system_type(void)
+{
+	return "Interface MPC-1211(CTP/PCI/MPC-SH02)";
+}
+
+static void __init pci_write_config(unsigned long busNo,
+				    unsigned long devNo,
+				    unsigned long fncNo,
+				    unsigned long cnfAdd,
+				    unsigned long cnfData)
+{
+	ctrl_outl((0x80000000 
+                + ((busNo & 0xff) << 16) 
+                + ((devNo & 0x1f) << 11) 
+                + ((fncNo & 0x07) <<  8) 
+		+ (cnfAdd & 0xfc)), PCIPAR);
+
+        ctrl_outl(cnfData, PCIPDR);
+}
+
+/*
+  Initialize IRQ setting
+*/
+
+static unsigned char m_irq_mask = 0xfb;
+static unsigned char s_irq_mask = 0xff;
+volatile unsigned long irq_err_count;
+
+static void disable_mpc1211_irq(unsigned int irq)
+{
+	unsigned long flags;
+
+	save_and_cli(flags);
+	if( irq < 8) {
+		m_irq_mask |= (1 << irq);
+		outb(m_irq_mask,I8259_M_MR);
+	} else {
+		s_irq_mask |= (1 << (irq - 8));
+		outb(s_irq_mask,I8259_S_MR);
+	}
+	restore_flags(flags);
+
+}
+
+static void enable_mpc1211_irq(unsigned int irq)
+{
+	unsigned long flags;
+
+	save_and_cli(flags);
+
+	if( irq < 8) {
+		m_irq_mask &= ~(1 << irq);
+		outb(m_irq_mask,I8259_M_MR);
+	} else {
+		s_irq_mask &= ~(1 << (irq - 8));
+		outb(s_irq_mask,I8259_S_MR);
+	}
+	restore_flags(flags);
+}
+
+static inline int mpc1211_irq_real(unsigned int irq)
+{
+	int value;
+	int irqmask;
+
+	if ( irq < 8) {
+		irqmask = 1<<irq;
+		outb(0x0b,I8259_M_CR);		/* ISR register */
+		value = inb(I8259_M_CR) & irqmask;
+		outb(0x0a,I8259_M_CR);		/* back ro the IPR reg */
+		return value;
+	}
+	irqmask = 1<<(irq - 8);
+	outb(0x0b,I8259_S_CR);		/* ISR register */
+	value = inb(I8259_S_CR) & irqmask;
+	outb(0x0a,I8259_S_CR);		/* back ro the IPR reg */
+	return value;
+}
+
+static void mask_and_ack_mpc1211(unsigned int irq)
+{
+	unsigned long flags;
+
+	save_and_cli(flags);
+
+	if(irq < 8) {
+		if(m_irq_mask & (1<<irq)){
+		  if(!mpc1211_irq_real(irq)){
+		    irq_err_count++;
+		    printk("spurious 8259A interrupt: IRQ %x\n",irq);
+		   }
+		} else {
+			m_irq_mask |= (1<<irq);
+		}
+		inb(I8259_M_MR);		/* DUMMY */
+		outb(m_irq_mask,I8259_M_MR);	/* disable */
+		outb(0x60+irq,I8259_M_CR);	/* EOI */
+		
+	} else {
+		if(s_irq_mask & (1<<(irq - 8))){
+		  if(!mpc1211_irq_real(irq)){
+		    irq_err_count++;
+		    printk("spurious 8259A interrupt: IRQ %x\n",irq);
+		  }
+		} else {
+			s_irq_mask |= (1<<(irq - 8));
+		}
+		inb(I8259_S_MR);		/* DUMMY */
+		outb(s_irq_mask,I8259_S_MR);	/* disable */
+		outb(0x60+(irq-8),I8259_S_CR); 	/* EOI */
+		outb(0x60+2,I8259_M_CR);
+	}
+	restore_flags(flags);
+}
+
+static void end_mpc1211_irq(unsigned int irq)
+{
+	enable_mpc1211_irq(irq);
+}
+
+static unsigned int startup_mpc1211_irq(unsigned int irq)
+{
+	enable_mpc1211_irq(irq);
+	return 0;
+}
+
+static void shutdown_mpc1211_irq(unsigned int irq)
+{
+	disable_mpc1211_irq(irq);
+}
+
+static struct hw_interrupt_type mpc1211_irq_type = {
+	.typename	= "MPC1211-IRQ",
+	.startup	= startup_mpc1211_irq,
+	.shutdown	= shutdown_mpc1211_irq,
+	.enable		= enable_mpc1211_irq,
+	.disable	= disable_mpc1211_irq,
+	.ack		= mask_and_ack_mpc1211,
+	.end		= end_mpc1211_irq
+};
+
+static void make_mpc1211_irq(unsigned int irq)
+{
+	irq_desc[irq].handler = &mpc1211_irq_type;
+	irq_desc[irq].status  = IRQ_DISABLED;
+	irq_desc[irq].action  = 0;
+	irq_desc[irq].depth   = 1;
+	disable_mpc1211_irq(irq);
+}
+
+int mpc1211_irq_demux(int irq)
+{
+	unsigned int poll;
+
+	if( irq == 2 ) {
+		outb(0x0c,I8259_M_CR);
+		poll = inb(I8259_M_CR);
+		if(poll & 0x80) {
+			irq = (poll & 0x07);
+		}
+		if( irq == 2) {
+			outb(0x0c,I8259_S_CR);
+			poll = inb(I8259_S_CR);
+			irq = (poll & 0x07) + 8;
+		}
+	}
+	return irq;
+}
+
+void __init init_mpc1211_IRQ(void)
+{
+	int i;
+	/*
+	 * Super I/O (Just mimic PC):
+	 *  1: keyboard
+	 *  3: serial 1
+	 *  4: serial 0
+	 *  5: printer
+	 *  6: floppy
+	 *  8: rtc
+	 * 10: lan
+	 * 12: mouse
+	 * 14: ide0
+	 * 15: ide1
+	 */
+
+	pci_write_config(0,0,0,0x54, 0xb0b0002d);
+	outb(0x11, I8259_M_CR); 	/* mater icw1 edge trigger  */
+	outb(0x11, I8259_S_CR);		/* slave icw1 edge trigger  */
+	outb(0x20, I8259_M_MR); 	/* m icw2 base vec 0x08	    */
+	outb(0x28, I8259_S_MR);		/* s icw2 base vec 0x70	    */
+	outb(0x04, I8259_M_MR);		/* m icw3 slave irq2	    */
+	outb(0x02, I8259_S_MR);		/* s icw3 slave id	    */
+	outb(0x01, I8259_M_MR);		/* m icw4 non buf normal eoi*/
+	outb(0x01, I8259_S_MR);		/* s icw4 non buf normal eo1*/
+	outb(0xfb, I8259_M_MR);		/* disable irq0--irq7  */
+	outb(0xff, I8259_S_MR);		/* disable irq8--irq15 */
+
+	for ( i=0; i < 16; i++) {
+		if(i != 2) {
+			make_mpc1211_irq(i);
+		}
+	}
+}
+
+/*
+  Initialize the board
+*/
+
+
+static void delay (void)
+{
+	volatile unsigned short tmp;
+	tmp = *(volatile unsigned short *) 0xa0000000;
+}
+
+static void delay1000 (void)
+{
+	int i;
+
+	for (i=0; i<1000; i++)
+		delay ();
+}
+
+static int put_smb_blk(unsigned char *p, int address, int command, int no)
+{
+	int temp;
+	int timeout;
+	int i;
+
+	outb(0xff, SMBHSTSTS);
+	temp = inb(SMBHSTSTS);
+	for (timeout = 0; (timeout < MAX_TIMEOUT) && !(temp & ALI15X3_STS_IDLE); timeout++) {
+		delay1000();
+		temp = inb(SMBHSTSTS);
+	}
+	if (timeout >= MAX_TIMEOUT){
+		return -1;
+	}
+
+	outb(((address & 0x7f) << 1), SMBHSTADD);
+	outb(0xc0, SMBHSTCNT);
+	outb(command & 0xff, SMBHSTCMD);
+	outb(no & 0x1f, SMBHSTDAT0);
+
+	for(i = 1; i <= no; i++) {
+		outb(*p++, SMBBLKDAT);
+	}
+	outb(0xff, SMBHSTSTART);
+
+	temp = inb(SMBHSTSTS);
+	for (timeout = 0; (timeout < MAX_TIMEOUT) && !(temp & (ALI15X3_STS_ERR | ALI15X3_STS_DONE)); timeout++) {
+		delay1000();
+		temp = inb(SMBHSTSTS);
+	}
+	if (timeout >= MAX_TIMEOUT) {
+		return -2;
+	}
+	if ( temp & ALI15X3_STS_ERR ){
+		return -3;
+	}
+	return 0;
+}
+
+/*
+ * The Machine Vector
+ */
+
+struct sh_machine_vector mv_mpc1211 __initmv = {
+	.mv_nr_irqs		= 48,
+	.mv_irq_demux		= mpc1211_irq_demux,
+	.mv_init_irq		= init_mpc1211_IRQ,
+
+#ifdef CONFIG_HEARTBEAT
+	.mv_heartbeat		= heartbeat_mpc1211,
+#endif
+};
+
+ALIAS_MV(mpc1211)
+
+/* arch/sh/boards/mpc1211/rtc.c */
+void mpc1211_time_init(void);
+
+int __init platform_setup(void)
+{
+	unsigned char spd_buf[128];
+
+	__set_io_port_base(PA_PCI_IO);
+
+	pci_write_config(0,0,0,0x54, 0xb0b00000);
+
+	do {
+		outb(ALI15X3_ABORT, SMBHSTCNT);
+		spd_buf[0] = 0x0c;
+		spd_buf[1] = 0x43;
+		spd_buf[2] = 0x7f;
+		spd_buf[3] = 0x03;
+		spd_buf[4] = 0x00;
+		spd_buf[5] = 0x03;
+		spd_buf[6] = 0x00;
+	} while (put_smb_blk(spd_buf, 0x69, 0, 7) < 0);
+
+	board_time_init = mpc1211_time_init;
+
+	return 0;
+}
+