v4.19.13 snapshot.
diff --git a/arch/sh/drivers/pci/Makefile b/arch/sh/drivers/pci/Makefile
new file mode 100644
index 0000000..947bfe8
--- /dev/null
+++ b/arch/sh/drivers/pci/Makefile
@@ -0,0 +1,29 @@
+# SPDX-License-Identifier: GPL-2.0
+#
+# Makefile for the PCI specific kernel interface routines under Linux.
+#
+obj-y					+= common.o pci.o
+
+obj-$(CONFIG_CPU_SUBTYPE_SH7751)	+= pci-sh7751.o ops-sh4.o
+obj-$(CONFIG_CPU_SUBTYPE_SH7751R)	+= pci-sh7751.o ops-sh4.o
+obj-$(CONFIG_CPU_SUBTYPE_SH7763)	+= pci-sh7780.o ops-sh4.o
+obj-$(CONFIG_CPU_SUBTYPE_SH7780)	+= pci-sh7780.o ops-sh4.o
+obj-$(CONFIG_CPU_SUBTYPE_SH7785)	+= pci-sh7780.o ops-sh4.o
+obj-$(CONFIG_CPU_SUBTYPE_SH7786)	+= pcie-sh7786.o ops-sh7786.o
+obj-$(CONFIG_CPU_SH5)			+= pci-sh5.o ops-sh5.o
+
+obj-$(CONFIG_SH_DREAMCAST)		+= ops-dreamcast.o fixups-dreamcast.o \
+					   pci-dreamcast.o
+obj-$(CONFIG_SH_SECUREEDGE5410)		+= fixups-snapgear.o
+obj-$(CONFIG_SH_7751_SOLUTION_ENGINE)	+= fixups-se7751.o
+obj-$(CONFIG_SH_RTS7751R2D)		+= fixups-rts7751r2d.o
+obj-$(CONFIG_SH_SH03)			+= fixups-sh03.o
+obj-$(CONFIG_SH_HIGHLANDER)		+= fixups-r7780rp.o
+obj-$(CONFIG_SH_SH7785LCR)		+= fixups-r7780rp.o
+obj-$(CONFIG_SH_SDK7786)		+= fixups-sdk7786.o
+obj-$(CONFIG_SH_SDK7780)		+= fixups-sdk7780.o
+obj-$(CONFIG_SH_7780_SOLUTION_ENGINE)	+= fixups-sdk7780.o
+obj-$(CONFIG_SH_TITAN)			+= fixups-titan.o
+obj-$(CONFIG_SH_LANDISK)		+= fixups-landisk.o
+obj-$(CONFIG_SH_LBOX_RE2)		+= fixups-rts7751r2d.o
+obj-$(CONFIG_SH_CAYMAN)			+= fixups-cayman.o
diff --git a/arch/sh/drivers/pci/common.c b/arch/sh/drivers/pci/common.c
new file mode 100644
index 0000000..fe163ec
--- /dev/null
+++ b/arch/sh/drivers/pci/common.c
@@ -0,0 +1,159 @@
+// SPDX-License-Identifier: GPL-2.0
+#include <linux/pci.h>
+#include <linux/interrupt.h>
+#include <linux/timer.h>
+#include <linux/kernel.h>
+
+/*
+ * These functions are used early on before PCI scanning is done
+ * and all of the pci_dev and pci_bus structures have been created.
+ */
+static struct pci_dev *fake_pci_dev(struct pci_channel *hose,
+	int top_bus, int busnr, int devfn)
+{
+	static struct pci_dev dev;
+	static struct pci_bus bus;
+
+	dev.bus = &bus;
+	dev.sysdata = hose;
+	dev.devfn = devfn;
+	bus.number = busnr;
+	bus.sysdata = hose;
+	bus.ops = hose->pci_ops;
+
+	if(busnr != top_bus)
+		/* Fake a parent bus structure. */
+		bus.parent = &bus;
+	else
+		bus.parent = NULL;
+
+	return &dev;
+}
+
+#define EARLY_PCI_OP(rw, size, type)					\
+int __init early_##rw##_config_##size(struct pci_channel *hose,		\
+	int top_bus, int bus, int devfn, int offset, type value)	\
+{									\
+	return pci_##rw##_config_##size(				\
+		fake_pci_dev(hose, top_bus, bus, devfn),		\
+		offset, value);						\
+}
+
+EARLY_PCI_OP(read, byte, u8 *)
+EARLY_PCI_OP(read, word, u16 *)
+EARLY_PCI_OP(read, dword, u32 *)
+EARLY_PCI_OP(write, byte, u8)
+EARLY_PCI_OP(write, word, u16)
+EARLY_PCI_OP(write, dword, u32)
+
+int __init pci_is_66mhz_capable(struct pci_channel *hose,
+				int top_bus, int current_bus)
+{
+	u32 pci_devfn;
+	unsigned short vid;
+	int cap66 = -1;
+	u16 stat;
+
+	printk(KERN_INFO "PCI: Checking 66MHz capabilities...\n");
+
+	for (pci_devfn = 0; pci_devfn < 0xff; pci_devfn++) {
+		if (PCI_FUNC(pci_devfn))
+			continue;
+		if (early_read_config_word(hose, top_bus, current_bus,
+					   pci_devfn, PCI_VENDOR_ID, &vid) !=
+		    PCIBIOS_SUCCESSFUL)
+			continue;
+		if (vid == 0xffff)
+			continue;
+
+		/* check 66MHz capability */
+		if (cap66 < 0)
+			cap66 = 1;
+		if (cap66) {
+			early_read_config_word(hose, top_bus, current_bus,
+					       pci_devfn, PCI_STATUS, &stat);
+			if (!(stat & PCI_STATUS_66MHZ)) {
+				printk(KERN_DEBUG
+				       "PCI: %02x:%02x not 66MHz capable.\n",
+				       current_bus, pci_devfn);
+				cap66 = 0;
+				break;
+			}
+		}
+	}
+
+	return cap66 > 0;
+}
+
+static void pcibios_enable_err(struct timer_list *t)
+{
+	struct pci_channel *hose = from_timer(hose, t, err_timer);
+
+	del_timer(&hose->err_timer);
+	printk(KERN_DEBUG "PCI: re-enabling error IRQ.\n");
+	enable_irq(hose->err_irq);
+}
+
+static void pcibios_enable_serr(struct timer_list *t)
+{
+	struct pci_channel *hose = from_timer(hose, t, serr_timer);
+
+	del_timer(&hose->serr_timer);
+	printk(KERN_DEBUG "PCI: re-enabling system error IRQ.\n");
+	enable_irq(hose->serr_irq);
+}
+
+void pcibios_enable_timers(struct pci_channel *hose)
+{
+	if (hose->err_irq) {
+		timer_setup(&hose->err_timer, pcibios_enable_err, 0);
+	}
+
+	if (hose->serr_irq) {
+		timer_setup(&hose->serr_timer, pcibios_enable_serr, 0);
+	}
+}
+
+/*
+ * A simple handler for the regular PCI status errors, called from IRQ
+ * context.
+ */
+unsigned int pcibios_handle_status_errors(unsigned long addr,
+					  unsigned int status,
+					  struct pci_channel *hose)
+{
+	unsigned int cmd = 0;
+
+	if (status & PCI_STATUS_REC_MASTER_ABORT) {
+		printk(KERN_DEBUG "PCI: master abort, pc=0x%08lx\n", addr);
+		cmd |= PCI_STATUS_REC_MASTER_ABORT;
+	}
+
+	if (status & PCI_STATUS_REC_TARGET_ABORT) {
+		printk(KERN_DEBUG "PCI: target abort: ");
+		pcibios_report_status(PCI_STATUS_REC_TARGET_ABORT |
+				      PCI_STATUS_SIG_TARGET_ABORT |
+				      PCI_STATUS_REC_MASTER_ABORT, 1);
+		printk("\n");
+
+		cmd |= PCI_STATUS_REC_TARGET_ABORT;
+	}
+
+	if (status & (PCI_STATUS_PARITY | PCI_STATUS_DETECTED_PARITY)) {
+		printk(KERN_DEBUG "PCI: parity error detected: ");
+		pcibios_report_status(PCI_STATUS_PARITY |
+				      PCI_STATUS_DETECTED_PARITY, 1);
+		printk("\n");
+
+		cmd |= PCI_STATUS_PARITY | PCI_STATUS_DETECTED_PARITY;
+
+		/* Now back off of the IRQ for awhile */
+		if (hose->err_irq) {
+			disable_irq_nosync(hose->err_irq);
+			hose->err_timer.expires = jiffies + HZ;
+			add_timer(&hose->err_timer);
+		}
+	}
+
+	return cmd;
+}
diff --git a/arch/sh/drivers/pci/fixups-cayman.c b/arch/sh/drivers/pci/fixups-cayman.c
new file mode 100644
index 0000000..c797bfb
--- /dev/null
+++ b/arch/sh/drivers/pci/fixups-cayman.c
@@ -0,0 +1,78 @@
+// SPDX-License-Identifier: GPL-2.0
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/types.h>
+#include <cpu/irq.h>
+#include "pci-sh5.h"
+
+int pcibios_map_platform_irq(const struct pci_dev *dev, u8 slot, u8 pin)
+{
+	int result = -1;
+
+	/* The complication here is that the PCI IRQ lines from the Cayman's 2
+	   5V slots get into the CPU via a different path from the IRQ lines
+	   from the 3 3.3V slots.  Thus, we have to detect whether the card's
+	   interrupts go via the 5V or 3.3V path, i.e. the 'bridge swizzling'
+	   at the point where we cross from 5V to 3.3V is not the normal case.
+
+	   The added complication is that we don't know that the 5V slots are
+	   always bus 2, because a card containing a PCI-PCI bridge may be
+	   plugged into a 3.3V slot, and this changes the bus numbering.
+
+	   Also, the Cayman has an intermediate PCI bus that goes a custom
+	   expansion board header (and to the secondary bridge).  This bus has
+	   never been used in practice.
+
+	   The 1ary onboard PCI-PCI bridge is device 3 on bus 0
+	   The 2ary onboard PCI-PCI bridge is device 0 on the 2ary bus of
+	   the 1ary bridge.
+	   */
+
+	struct slot_pin {
+		int slot;
+		int pin;
+	} path[4];
+	int i=0;
+
+	while (dev->bus->number > 0) {
+
+		slot = path[i].slot = PCI_SLOT(dev->devfn);
+		pin = path[i].pin = pci_swizzle_interrupt_pin(dev, pin);
+		dev = dev->bus->self;
+		i++;
+		if (i > 3) panic("PCI path to root bus too long!\n");
+	}
+
+	slot = PCI_SLOT(dev->devfn);
+	/* This is the slot on bus 0 through which the device is eventually
+	   reachable. */
+
+	/* Now work back up. */
+	if ((slot < 3) || (i == 0)) {
+		/* Bus 0 (incl. PCI-PCI bridge itself) : perform the final
+		   swizzle now. */
+		result = IRQ_INTA + pci_swizzle_interrupt_pin(dev, pin) - 1;
+	} else {
+		i--;
+		slot = path[i].slot;
+		pin  = path[i].pin;
+		if (slot > 0) {
+			panic("PCI expansion bus device found - not handled!\n");
+		} else {
+			if (i > 0) {
+				/* 5V slots */
+				i--;
+				slot = path[i].slot;
+				pin  = path[i].pin;
+				/* 'pin' was swizzled earlier wrt slot, don't do it again. */
+				result = IRQ_P2INTA + (pin - 1);
+			} else {
+				/* IRQ for 2ary PCI-PCI bridge : unused */
+				result = -1;
+			}
+		}
+	}
+
+	return result;
+}
diff --git a/arch/sh/drivers/pci/fixups-dreamcast.c b/arch/sh/drivers/pci/fixups-dreamcast.c
new file mode 100644
index 0000000..48aaefd
--- /dev/null
+++ b/arch/sh/drivers/pci/fixups-dreamcast.c
@@ -0,0 +1,88 @@
+/*
+ * arch/sh/drivers/pci/fixups-dreamcast.c
+ *
+ * PCI fixups for the Sega Dreamcast
+ *
+ * Copyright (C) 2001, 2002  M. R. Brown
+ * Copyright (C) 2002, 2003, 2006  Paul Mundt
+ *
+ * This file originally bore the message (with enclosed-$):
+ *	Id: pci.c,v 1.3 2003/05/04 19:29:46 lethal Exp
+ *	Dreamcast PCI: Supports SEGA Broadband Adaptor only.
+ *
+ * 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/sched.h>
+#include <linux/kernel.h>
+#include <linux/param.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <linux/pci.h>
+#include <linux/dma-mapping.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <mach/pci.h>
+
+static void gapspci_fixup_resources(struct pci_dev *dev)
+{
+	struct pci_channel *p = dev->sysdata;
+	struct resource res;
+	struct pci_bus_region region;
+
+	printk(KERN_NOTICE "PCI: Fixing up device %s\n", pci_name(dev));
+
+	switch (dev->device) {
+	case PCI_DEVICE_ID_SEGA_BBA:
+		/*
+		 * We also assume that dev->devfn == 0
+		 */
+		dev->resource[1].start	= p->resources[0].start  + 0x100;
+		dev->resource[1].end	= dev->resource[1].start + 0x200 - 1;
+
+		/*
+		 * This is not a normal BAR, prevent any attempts to move
+		 * the BAR, as this will result in a bus lock.
+		 */
+		dev->resource[1].flags |= IORESOURCE_PCI_FIXED;
+
+		/*
+		 * Redirect dma memory allocations to special memory window.
+		 *
+		 * If this GAPSPCI region were mapped by a BAR, the CPU
+		 * phys_addr_t would be pci_resource_start(), and the bus
+		 * address would be pci_bus_address(pci_resource_start()).
+		 * But apparently there's no BAR mapping it, so we just
+		 * "know" its CPU address is GAPSPCI_DMA_BASE.
+		 */
+		res.start = GAPSPCI_DMA_BASE;
+		res.end = GAPSPCI_DMA_BASE + GAPSPCI_DMA_SIZE - 1;
+		res.flags = IORESOURCE_MEM;
+		pcibios_resource_to_bus(dev->bus, &region, &res);
+		BUG_ON(dma_declare_coherent_memory(&dev->dev,
+						res.start,
+						region.start,
+						resource_size(&res),
+						DMA_MEMORY_EXCLUSIVE));
+		break;
+	default:
+		printk("PCI: Failed resource fixup\n");
+	}
+}
+DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, gapspci_fixup_resources);
+
+int pcibios_map_platform_irq(const struct pci_dev *dev, u8 slot, u8 pin)
+{
+	/*
+	 * The interrupt routing semantics here are quite trivial.
+	 *
+	 * We basically only support one interrupt, so we only bother
+	 * updating a device's interrupt line with this single shared
+	 * interrupt. Keeps routing quite simple, doesn't it?
+	 */
+	return GAPSPCI_IRQ;
+}
diff --git a/arch/sh/drivers/pci/fixups-landisk.c b/arch/sh/drivers/pci/fixups-landisk.c
new file mode 100644
index 0000000..db5b40a
--- /dev/null
+++ b/arch/sh/drivers/pci/fixups-landisk.c
@@ -0,0 +1,59 @@
+/*
+ * arch/sh/drivers/pci/fixups-landisk.c
+ *
+ * PCI initialization for the I-O DATA Device, Inc. LANDISK board
+ *
+ * Copyright (C) 2006 kogiidena
+ * Copyright (C) 2010 Nobuhiro Iwamatsu
+ *
+ * May be copied or modified under the terms of the GNU General Public
+ * License.  See linux/COPYING for more information.
+ */
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/pci.h>
+#include <linux/sh_intc.h>
+#include "pci-sh4.h"
+
+#define PCIMCR_MRSET_OFF	0xBFFFFFFF
+#define PCIMCR_RFSH_OFF		0xFFFFFFFB
+
+int pcibios_map_platform_irq(const struct pci_dev *pdev, u8 slot, u8 pin)
+{
+	/*
+	 * slot0: pin1-4 = irq5,6,7,8
+	 * slot1: pin1-4 = irq6,7,8,5
+	 * slot2: pin1-4 = irq7,8,5,6
+	 * slot3: pin1-4 = irq8,5,6,7
+	 */
+	int irq = ((slot + pin - 1) & 0x3) + evt2irq(0x2a0);
+
+	if ((slot | (pin - 1)) > 0x3) {
+		printk(KERN_WARNING "PCI: Bad IRQ mapping request for slot %d pin %c\n",
+		       slot, pin - 1 + 'A');
+		return -1;
+	}
+	return irq;
+}
+
+int pci_fixup_pcic(struct pci_channel *chan)
+{
+	unsigned long bcr1, mcr;
+
+	bcr1 = __raw_readl(SH7751_BCR1);
+	bcr1 |= 0x40080000;	/* Enable Bit 19 BREQEN, set PCIC to slave */
+	pci_write_reg(chan, bcr1, SH4_PCIBCR1);
+
+	mcr = __raw_readl(SH7751_MCR);
+	mcr = (mcr & PCIMCR_MRSET_OFF) & PCIMCR_RFSH_OFF;
+	pci_write_reg(chan, mcr, SH4_PCIMCR);
+
+	pci_write_reg(chan, 0x0c000000, SH7751_PCICONF5);
+	pci_write_reg(chan, 0xd0000000, SH7751_PCICONF6);
+	pci_write_reg(chan, 0x0c000000, SH4_PCILAR0);
+	pci_write_reg(chan, 0x00000000, SH4_PCILAR1);
+
+	return 0;
+}
diff --git a/arch/sh/drivers/pci/fixups-r7780rp.c b/arch/sh/drivers/pci/fixups-r7780rp.c
new file mode 100644
index 0000000..2c9b58f
--- /dev/null
+++ b/arch/sh/drivers/pci/fixups-r7780rp.c
@@ -0,0 +1,21 @@
+/*
+ * arch/sh/drivers/pci/fixups-r7780rp.c
+ *
+ * Highlander R7780RP-1 PCI fixups
+ *
+ * Copyright (C) 2003  Lineo uSolutions, Inc.
+ * Copyright (C) 2004 - 2006  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/pci.h>
+#include <linux/io.h>
+#include <linux/sh_intc.h>
+#include "pci-sh4.h"
+
+int pcibios_map_platform_irq(const struct pci_dev *pdev, u8 slot, u8 pin)
+{
+	return evt2irq(0xa20) + slot;
+}
diff --git a/arch/sh/drivers/pci/fixups-rts7751r2d.c b/arch/sh/drivers/pci/fixups-rts7751r2d.c
new file mode 100644
index 0000000..358ac10
--- /dev/null
+++ b/arch/sh/drivers/pci/fixups-rts7751r2d.c
@@ -0,0 +1,67 @@
+/*
+ * arch/sh/drivers/pci/fixups-rts7751r2d.c
+ *
+ * RTS7751R2D / LBOXRE2 PCI fixups
+ *
+ * Copyright (C) 2003  Lineo uSolutions, Inc.
+ * Copyright (C) 2004  Paul Mundt
+ * Copyright (C) 2007  Nobuhiro Iwamatsu
+ *
+ * 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/pci.h>
+#include <mach/lboxre2.h>
+#include <mach/r2d.h>
+#include "pci-sh4.h"
+#include <generated/machtypes.h>
+
+#define PCIMCR_MRSET_OFF	0xBFFFFFFF
+#define PCIMCR_RFSH_OFF		0xFFFFFFFB
+
+static u8 rts7751r2d_irq_tab[] = {
+	IRQ_PCI_INTA,
+	IRQ_PCI_INTB,
+	IRQ_PCI_INTC,
+	IRQ_PCI_INTD,
+};
+
+static char lboxre2_irq_tab[] = {
+	IRQ_ETH0, IRQ_ETH1, IRQ_INTA, IRQ_INTD,
+};
+
+int pcibios_map_platform_irq(const struct pci_dev *pdev, u8 slot, u8 pin)
+{
+	if (mach_is_lboxre2())
+		return lboxre2_irq_tab[slot];
+	else
+		return rts7751r2d_irq_tab[slot];
+}
+
+int pci_fixup_pcic(struct pci_channel *chan)
+{
+	unsigned long bcr1, mcr;
+
+	bcr1 = __raw_readl(SH7751_BCR1);
+	bcr1 |= 0x40080000;	/* Enable Bit 19 BREQEN, set PCIC to slave */
+	pci_write_reg(chan, bcr1, SH4_PCIBCR1);
+
+	/* Enable all interrupts, so we known what to fix */
+	pci_write_reg(chan, 0x0000c3ff, SH4_PCIINTM);
+	pci_write_reg(chan, 0x0000380f, SH4_PCIAINTM);
+
+	pci_write_reg(chan, 0xfb900047, SH7751_PCICONF1);
+	pci_write_reg(chan, 0xab000001, SH7751_PCICONF4);
+
+	mcr = __raw_readl(SH7751_MCR);
+	mcr = (mcr & PCIMCR_MRSET_OFF) & PCIMCR_RFSH_OFF;
+	pci_write_reg(chan, mcr, SH4_PCIMCR);
+
+	pci_write_reg(chan, 0x0c000000, SH7751_PCICONF5);
+	pci_write_reg(chan, 0xd0000000, SH7751_PCICONF6);
+	pci_write_reg(chan, 0x0c000000, SH4_PCILAR0);
+	pci_write_reg(chan, 0x00000000, SH4_PCILAR1);
+
+	return 0;
+}
diff --git a/arch/sh/drivers/pci/fixups-sdk7780.c b/arch/sh/drivers/pci/fixups-sdk7780.c
new file mode 100644
index 0000000..24e96df
--- /dev/null
+++ b/arch/sh/drivers/pci/fixups-sdk7780.c
@@ -0,0 +1,43 @@
+/*
+ * arch/sh/drivers/pci/fixups-sdk7780.c
+ *
+ * PCI fixups for the SDK7780SE03
+ *
+ * Copyright (C) 2003  Lineo uSolutions, Inc.
+ * Copyright (C) 2004 - 2006  Paul Mundt
+ * Copyright (C) 2006  Nobuhiro Iwamatsu
+ *
+ * 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/pci.h>
+#include <linux/io.h>
+#include <linux/sh_intc.h>
+#include "pci-sh4.h"
+
+#define IRQ_INTA	evt2irq(0xa20)
+#define IRQ_INTB	evt2irq(0xa40)
+#define IRQ_INTC	evt2irq(0xa60)
+#define IRQ_INTD	evt2irq(0xa80)
+
+/* IDSEL [16][17][18][19][20][21][22][23][24][25][26][27][28][29][30][31] */
+static char sdk7780_irq_tab[4][16] = {
+	/* INTA */
+	{ IRQ_INTA, IRQ_INTD, IRQ_INTC, IRQ_INTD, -1, -1, -1, -1, -1, -1,
+	  -1, -1, -1, -1, -1, -1 },
+	/* INTB */
+	{ IRQ_INTB, IRQ_INTA, -1, IRQ_INTA, -1, -1, -1, -1, -1, -1, -1, -1,
+	  -1, -1, -1, -1 },
+	/* INTC */
+	{ IRQ_INTC, IRQ_INTB, -1, IRQ_INTB, -1, -1, -1, -1, -1, -1, -1, -1,
+	  -1, -1, -1, -1 },
+	/* INTD */
+	{ IRQ_INTD, IRQ_INTC, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+	  -1, -1, -1 },
+};
+
+int pcibios_map_platform_irq(const struct pci_dev *pdev, u8 slot, u8 pin)
+{
+       return sdk7780_irq_tab[pin-1][slot];
+}
diff --git a/arch/sh/drivers/pci/fixups-sdk7786.c b/arch/sh/drivers/pci/fixups-sdk7786.c
new file mode 100644
index 0000000..36eb6fc
--- /dev/null
+++ b/arch/sh/drivers/pci/fixups-sdk7786.c
@@ -0,0 +1,67 @@
+/*
+ * SDK7786 FPGA PCIe mux handling
+ *
+ * Copyright (C) 2010  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.
+ */
+#define pr_fmt(fmt) "PCI: " fmt
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <mach/fpga.h>
+
+/*
+ * The SDK7786 FPGA supports mangling of most of the slots in some way or
+ * another. Slots 3/4 are special in that only one can be supported at a
+ * time, and both appear on port 3 to the PCI bus scan. Enabling slot 4
+ * (the horizontal edge connector) will disable slot 3 entirely.
+ *
+ * Misconfigurations can be detected through the FPGA via the slot
+ * resistors to determine card presence. Hotplug remains unsupported.
+ */
+static unsigned int slot4en __initdata;
+
+char *__init pcibios_setup(char *str)
+{
+	if (strcmp(str, "slot4en") == 0) {
+		slot4en = 1;
+		return NULL;
+	}
+
+	return str;
+}
+
+static int __init sdk7786_pci_init(void)
+{
+	u16 data = fpga_read_reg(PCIECR);
+
+	/*
+	 * Enable slot #4 if it's been specified on the command line.
+	 *
+	 * Optionally reroute if slot #4 has a card present while slot #3
+	 * does not, regardless of command line value.
+	 *
+	 * Card presence is logically inverted.
+	 */
+	slot4en ?: (!(data & PCIECR_PRST4) && (data & PCIECR_PRST3));
+	if (slot4en) {
+		pr_info("Activating PCIe slot#4 (disabling slot#3)\n");
+
+		data &= ~PCIECR_PCIEMUX1;
+		fpga_write_reg(data, PCIECR);
+
+		/* Warn about forced rerouting if slot#3 is occupied */
+		if ((data & PCIECR_PRST3) == 0) {
+			pr_warning("Unreachable card detected in slot#3\n");
+			return -EBUSY;
+		}
+	} else
+		pr_info("PCIe slot#4 disabled\n");
+
+	return 0;
+}
+postcore_initcall(sdk7786_pci_init);
diff --git a/arch/sh/drivers/pci/fixups-se7751.c b/arch/sh/drivers/pci/fixups-se7751.c
new file mode 100644
index 0000000..608f652
--- /dev/null
+++ b/arch/sh/drivers/pci/fixups-se7751.c
@@ -0,0 +1,113 @@
+// SPDX-License-Identifier: GPL-2.0
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/pci.h>
+#include <linux/io.h>
+#include <linux/sh_intc.h>
+#include "pci-sh4.h"
+
+int pcibios_map_platform_irq(const struct pci_dev *, u8 slot, u8 pin)
+{
+        switch (slot) {
+        case 0: return evt2irq(0x3a0);
+        case 1: return evt2irq(0x3a0);	/* 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;
+        }
+}
+
+#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 pci_fixup_pcic(struct pci_channel *chan)
+{
+	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(chan->resources[1].start != SH7751_PCI_MEMORY_BASE);
+
+	PCIC_WRITE(SH7751_PCIMBR, chan->resources[1].start);
+
+	/* Set IOBR for window containing area specified in pci.h */
+	PCIC_WRITE(SH7751_PCIIOBR, (chan->resources[0].start & SH7751_PCIIOBR_MASK));
+
+	/* All done, may as well say so... */
+	printk("SH7751 PCI: Finished initialization of the PCI controller\n");
+
+	return 1;
+}
diff --git a/arch/sh/drivers/pci/fixups-sh03.c b/arch/sh/drivers/pci/fixups-sh03.c
new file mode 100644
index 0000000..7ec4a74
--- /dev/null
+++ b/arch/sh/drivers/pci/fixups-sh03.c
@@ -0,0 +1,33 @@
+// SPDX-License-Identifier: GPL-2.0
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/sh_intc.h>
+
+int pcibios_map_platform_irq(const struct pci_dev *dev, u8 slot, u8 pin)
+{
+	int irq;
+
+	if (dev->bus->number == 0) {
+		switch (slot) {
+		case 4: return evt2irq(0x2a0);	/* eth0       */
+		case 8: return evt2irq(0x2a0);	/* eth1       */
+		case 6: return evt2irq(0x240);	/* PCI bridge */
+		default:
+			printk(KERN_ERR "PCI: Bad IRQ mapping request "
+					"for slot %d\n", slot);
+			return evt2irq(0x240);
+		}
+	} else {
+		switch (pin) {
+		case 0:   irq =  evt2irq(0x240); break;
+		case 1:   irq =  evt2irq(0x240); break;
+		case 2:   irq =  evt2irq(0x240); break;
+		case 3:   irq =  evt2irq(0x240); break;
+		case 4:   irq =  evt2irq(0x240); break;
+		default:  irq = -1; break;
+		}
+	}
+	return irq;
+}
diff --git a/arch/sh/drivers/pci/fixups-snapgear.c b/arch/sh/drivers/pci/fixups-snapgear.c
new file mode 100644
index 0000000..a931e59
--- /dev/null
+++ b/arch/sh/drivers/pci/fixups-snapgear.c
@@ -0,0 +1,39 @@
+/*
+ * arch/sh/drivers/pci/ops-snapgear.c
+ *
+ * Author:  David McCullough <davidm@snapgear.com>
+ *
+ * Ported to new API by Paul Mundt <lethal@linux-sh.org>
+ *
+ * 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 SnapGear boards
+ */
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/sh_intc.h>
+#include "pci-sh4.h"
+
+int pcibios_map_platform_irq(const struct pci_dev *pdev, u8 slot, u8 pin)
+{
+	int irq = -1;
+
+	switch (slot) {
+	case 8:  /* the PCI bridge */ break;
+	case 11: irq = evt2irq(0x300); break; /* USB    */
+	case 12: irq = evt2irq(0x360); break; /* PCMCIA */
+	case 13: irq = evt2irq(0x2a0); break; /* eth0   */
+	case 14: irq = evt2irq(0x300); break; /* eth1   */
+	case 15: irq = evt2irq(0x360); break; /* safenet (unused) */
+	}
+
+	printk("PCI: Mapping SnapGear IRQ for slot %d, pin %c to irq %d\n",
+	       slot, pin - 1 + 'A', irq);
+
+	return irq;
+}
diff --git a/arch/sh/drivers/pci/fixups-titan.c b/arch/sh/drivers/pci/fixups-titan.c
new file mode 100644
index 0000000..a9d563e
--- /dev/null
+++ b/arch/sh/drivers/pci/fixups-titan.c
@@ -0,0 +1,38 @@
+/*
+ * arch/sh/drivers/pci/ops-titan.c
+ *
+ * Ported to new API by Paul Mundt <lethal@linux-sh.org>
+ *
+ * Modified from ops-snapgear.c written by  David McCullough
+ * 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 Titan boards
+ */
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/io.h>
+#include <mach/titan.h>
+#include "pci-sh4.h"
+
+static char titan_irq_tab[] = {
+	TITAN_IRQ_WAN,
+	TITAN_IRQ_LAN,
+	TITAN_IRQ_MPCIA,
+	TITAN_IRQ_MPCIB,
+	TITAN_IRQ_USB,
+};
+
+int pcibios_map_platform_irq(const struct pci_dev *pdev, u8 slot, u8 pin)
+{
+	int irq = titan_irq_tab[slot];
+
+	printk("PCI: Mapping TITAN IRQ for slot %d, pin %c to irq %d\n",
+		slot, pin - 1 + 'A', irq);
+
+	return irq;
+}
diff --git a/arch/sh/drivers/pci/ops-dreamcast.c b/arch/sh/drivers/pci/ops-dreamcast.c
new file mode 100644
index 0000000..16e0a1b
--- /dev/null
+++ b/arch/sh/drivers/pci/ops-dreamcast.c
@@ -0,0 +1,82 @@
+/*
+ * PCI operations for the Sega Dreamcast
+ *
+ * Copyright (C) 2001, 2002  M. R. Brown
+ * 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/sched.h>
+#include <linux/kernel.h>
+#include <linux/param.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <linux/pci.h>
+#include <linux/module.h>
+#include <linux/io.h>
+#include <mach/pci.h>
+
+/*
+ * The !gapspci_config_access case really shouldn't happen, ever, unless
+ * someone implicitly messes around with the last devfn value.. otherwise we
+ * only support a single device anyways, and if we didn't have a BBA, we
+ * wouldn't make it terribly far through the PCI setup anyways.
+ *
+ * Also, we could very easily support both Type 0 and Type 1 configurations
+ * here, but since it doesn't seem that there is any such implementation in
+ * existence, we don't bother.
+ *
+ * I suppose if someone actually gets around to ripping the chip out of
+ * the BBA and hanging some more devices off of it, then this might be
+ * something to take into consideration. However, due to the cost of the BBA,
+ * and the general lack of activity by DC hardware hackers, this doesn't seem
+ * likely to happen anytime soon.
+ */
+static int gapspci_config_access(unsigned char bus, unsigned int devfn)
+{
+	return (bus == 0) && (devfn == 0);
+}
+
+/*
+ * We can also actually read and write in b/w/l sizes! Thankfully this part
+ * was at least done right, and we don't have to do the stupid masking and
+ * shifting that we do on the 7751! Small wonders never cease to amaze.
+ */
+static int gapspci_read(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 *val)
+{
+	*val = 0xffffffff;
+
+	if (!gapspci_config_access(bus->number, devfn))
+		return PCIBIOS_DEVICE_NOT_FOUND;
+
+	switch (size) {
+	case 1: *val = inb(GAPSPCI_BBA_CONFIG+where); break;
+	case 2: *val = inw(GAPSPCI_BBA_CONFIG+where); break;
+	case 4: *val = inl(GAPSPCI_BBA_CONFIG+where); break;
+	}
+
+        return PCIBIOS_SUCCESSFUL;
+}
+
+static int gapspci_write(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 val)
+{
+	if (!gapspci_config_access(bus->number, devfn))
+		return PCIBIOS_DEVICE_NOT_FOUND;
+
+	switch (size) {
+	case 1: outb(( u8)val, GAPSPCI_BBA_CONFIG+where); break;
+	case 2: outw((u16)val, GAPSPCI_BBA_CONFIG+where); break;
+	case 4: outl((u32)val, GAPSPCI_BBA_CONFIG+where); break;
+	}
+
+        return PCIBIOS_SUCCESSFUL;
+}
+
+struct pci_ops gapspci_pci_ops = {
+	.read	= gapspci_read,
+	.write	= gapspci_write,
+};
diff --git a/arch/sh/drivers/pci/ops-sh4.c b/arch/sh/drivers/pci/ops-sh4.c
new file mode 100644
index 0000000..b623420
--- /dev/null
+++ b/arch/sh/drivers/pci/ops-sh4.c
@@ -0,0 +1,108 @@
+/*
+ * Generic SH-4 / SH-4A PCIC operations (SH7751, SH7780).
+ *
+ * Copyright (C) 2002 - 2009  Paul Mundt
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License v2. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#include <linux/pci.h>
+#include <linux/io.h>
+#include <linux/spinlock.h>
+#include <asm/addrspace.h>
+#include "pci-sh4.h"
+
+/*
+ * 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 sh4_pci_read(struct pci_bus *bus, unsigned int devfn,
+			   int where, int size, u32 *val)
+{
+	struct pci_channel *chan = bus->sysdata;
+	unsigned long flags;
+	u32 data;
+
+	/*
+	 * PCIPDR may only be accessed as 32 bit words,
+	 * so we must do byte alignment by hand
+	 */
+	raw_spin_lock_irqsave(&pci_config_lock, flags);
+	pci_write_reg(chan, CONFIG_CMD(bus, devfn, where), SH4_PCIPAR);
+	data = pci_read_reg(chan, SH4_PCIPDR);
+	raw_spin_unlock_irqrestore(&pci_config_lock, flags);
+
+	switch (size) {
+	case 1:
+		*val = (data >> ((where & 3) << 3)) & 0xff;
+		break;
+	case 2:
+		*val = (data >> ((where & 2) << 3)) & 0xffff;
+		break;
+	case 4:
+		*val = data;
+		break;
+	default:
+		return PCIBIOS_FUNC_NOT_SUPPORTED;
+	}
+
+	return PCIBIOS_SUCCESSFUL;
+}
+
+/*
+ * Since SH4 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 sh4_pci_write(struct pci_bus *bus, unsigned int devfn,
+			 int where, int size, u32 val)
+{
+	struct pci_channel *chan = bus->sysdata;
+	unsigned long flags;
+	int shift;
+	u32 data;
+
+	raw_spin_lock_irqsave(&pci_config_lock, flags);
+	pci_write_reg(chan, CONFIG_CMD(bus, devfn, where), SH4_PCIPAR);
+	data = pci_read_reg(chan, SH4_PCIPDR);
+	raw_spin_unlock_irqrestore(&pci_config_lock, flags);
+
+	switch (size) {
+	case 1:
+		shift = (where & 3) << 3;
+		data &= ~(0xff << shift);
+		data |= ((val & 0xff) << shift);
+		break;
+	case 2:
+		shift = (where & 2) << 3;
+		data &= ~(0xffff << shift);
+		data |= ((val & 0xffff) << shift);
+		break;
+	case 4:
+		data = val;
+		break;
+	default:
+		return PCIBIOS_FUNC_NOT_SUPPORTED;
+	}
+
+	pci_write_reg(chan, data, SH4_PCIPDR);
+
+	return PCIBIOS_SUCCESSFUL;
+}
+
+struct pci_ops sh4_pci_ops = {
+	.read		= sh4_pci_read,
+	.write		= sh4_pci_write,
+};
+
+int __attribute__((weak)) pci_fixup_pcic(struct pci_channel *chan)
+{
+	/* Nothing to do. */
+	return 0;
+}
diff --git a/arch/sh/drivers/pci/ops-sh5.c b/arch/sh/drivers/pci/ops-sh5.c
new file mode 100644
index 0000000..4536194
--- /dev/null
+++ b/arch/sh/drivers/pci/ops-sh5.c
@@ -0,0 +1,67 @@
+/*
+ * Support functions for the SH5 PCI hardware.
+ *
+ * Copyright (C) 2001 David J. Mckay (david.mckay@st.com)
+ * Copyright (C) 2003, 2004 Paul Mundt
+ * Copyright (C) 2004 Richard Curnow
+ *
+ * May be copied or modified under the terms of the GNU General Public
+ * License.  See linux/COPYING for more information.
+ */
+#include <linux/kernel.h>
+#include <linux/rwsem.h>
+#include <linux/smp.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <linux/types.h>
+#include <linux/irq.h>
+#include <asm/io.h>
+#include "pci-sh5.h"
+
+static int sh5pci_read(struct pci_bus *bus, unsigned int devfn, int where,
+			int size, u32 *val)
+{
+	SH5PCI_WRITE(PAR, CONFIG_CMD(bus, devfn, where));
+
+	switch (size) {
+		case 1:
+			*val = (u8)SH5PCI_READ_BYTE(PDR + (where & 3));
+			break;
+		case 2:
+			*val = (u16)SH5PCI_READ_SHORT(PDR + (where & 2));
+			break;
+		case 4:
+			*val = SH5PCI_READ(PDR);
+			break;
+	}
+
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static int sh5pci_write(struct pci_bus *bus, unsigned int devfn, int where,
+			 int size, u32 val)
+{
+	SH5PCI_WRITE(PAR, CONFIG_CMD(bus, devfn, where));
+
+	switch (size) {
+		case 1:
+			SH5PCI_WRITE_BYTE(PDR + (where & 3), (u8)val);
+			break;
+		case 2:
+			SH5PCI_WRITE_SHORT(PDR + (where & 2), (u16)val);
+			break;
+		case 4:
+			SH5PCI_WRITE(PDR, val);
+			break;
+	}
+
+	return PCIBIOS_SUCCESSFUL;
+}
+
+struct pci_ops sh5_pci_ops = {
+	.read		= sh5pci_read,
+	.write		= sh5pci_write,
+};
diff --git a/arch/sh/drivers/pci/ops-sh7786.c b/arch/sh/drivers/pci/ops-sh7786.c
new file mode 100644
index 0000000..1284210
--- /dev/null
+++ b/arch/sh/drivers/pci/ops-sh7786.c
@@ -0,0 +1,171 @@
+/*
+ * Generic SH7786 PCI-Express operations.
+ *
+ *  Copyright (C) 2009 - 2010  Paul Mundt
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License v2. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/io.h>
+#include <linux/spinlock.h>
+#include "pcie-sh7786.h"
+
+enum {
+	PCI_ACCESS_READ,
+	PCI_ACCESS_WRITE,
+};
+
+static int sh7786_pcie_config_access(unsigned char access_type,
+		struct pci_bus *bus, unsigned int devfn, int where, u32 *data)
+{
+	struct pci_channel *chan = bus->sysdata;
+	int dev, func, type, reg;
+
+	dev = PCI_SLOT(devfn);
+	func = PCI_FUNC(devfn);
+	type = !!bus->parent;
+	reg = where & ~3;
+
+	if (bus->number > 255 || dev > 31 || func > 7)
+		return PCIBIOS_FUNC_NOT_SUPPORTED;
+
+	/*
+	 * While each channel has its own memory-mapped extended config
+	 * space, it's generally only accessible when in endpoint mode.
+	 * When in root complex mode, the controller is unable to target
+	 * itself with either type 0 or type 1 accesses, and indeed, any
+	 * controller initiated target transfer to its own config space
+	 * result in a completer abort.
+	 *
+	 * Each channel effectively only supports a single device, but as
+	 * the same channel <-> device access works for any PCI_SLOT()
+	 * value, we cheat a bit here and bind the controller's config
+	 * space to devfn 0 in order to enable self-enumeration. In this
+	 * case the regular PAR/PDR path is sidelined and the mangled
+	 * config access itself is initiated as a SuperHyway transaction.
+	 */
+	if (pci_is_root_bus(bus)) {
+		if (dev == 0) {
+			if (access_type == PCI_ACCESS_READ)
+				*data = pci_read_reg(chan, PCI_REG(reg));
+			else
+				pci_write_reg(chan, *data, PCI_REG(reg));
+
+			return PCIBIOS_SUCCESSFUL;
+		} else if (dev > 1)
+			return PCIBIOS_DEVICE_NOT_FOUND;
+	}
+
+	/* Clear errors */
+	pci_write_reg(chan, pci_read_reg(chan, SH4A_PCIEERRFR), SH4A_PCIEERRFR);
+
+	/* Set the PIO address */
+	pci_write_reg(chan, (bus->number << 24) | (dev << 19) |
+				(func << 16) | reg, SH4A_PCIEPAR);
+
+	/* Enable the configuration access */
+	pci_write_reg(chan, (1 << 31) | (type << 8), SH4A_PCIEPCTLR);
+
+	/* Check for errors */
+	if (pci_read_reg(chan, SH4A_PCIEERRFR) & 0x10)
+		return PCIBIOS_DEVICE_NOT_FOUND;
+
+	/* Check for master and target aborts */
+	if (pci_read_reg(chan, SH4A_PCIEPCICONF1) & ((1 << 29) | (1 << 28)))
+		return PCIBIOS_DEVICE_NOT_FOUND;
+
+	if (access_type == PCI_ACCESS_READ)
+		*data = pci_read_reg(chan, SH4A_PCIEPDR);
+	else
+		pci_write_reg(chan, *data, SH4A_PCIEPDR);
+
+	/* Disable the configuration access */
+	pci_write_reg(chan, 0, SH4A_PCIEPCTLR);
+
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static int sh7786_pcie_read(struct pci_bus *bus, unsigned int devfn,
+			    int where, int size, u32 *val)
+{
+	unsigned long flags;
+	int ret;
+	u32 data;
+
+        if ((size == 2) && (where & 1))
+		return PCIBIOS_BAD_REGISTER_NUMBER;
+	else if ((size == 4) && (where & 3))
+		return PCIBIOS_BAD_REGISTER_NUMBER;
+
+	raw_spin_lock_irqsave(&pci_config_lock, flags);
+	ret = sh7786_pcie_config_access(PCI_ACCESS_READ, bus,
+					devfn, where, &data);
+	if (ret != PCIBIOS_SUCCESSFUL) {
+		*val = 0xffffffff;
+		goto out;
+	}
+
+	if (size == 1)
+		*val = (data >> ((where & 3) << 3)) & 0xff;
+	else if (size == 2)
+		*val = (data >> ((where & 2) << 3)) & 0xffff;
+	else
+		*val = data;
+
+	dev_dbg(&bus->dev, "pcie-config-read: bus=%3d devfn=0x%04x "
+		"where=0x%04x size=%d val=0x%08lx\n", bus->number,
+		devfn, where, size, (unsigned long)*val);
+
+out:
+	raw_spin_unlock_irqrestore(&pci_config_lock, flags);
+	return ret;
+}
+
+static int sh7786_pcie_write(struct pci_bus *bus, unsigned int devfn,
+			     int where, int size, u32 val)
+{
+	unsigned long flags;
+	int shift, ret;
+	u32 data;
+
+        if ((size == 2) && (where & 1))
+		return PCIBIOS_BAD_REGISTER_NUMBER;
+	else if ((size == 4) && (where & 3))
+		return PCIBIOS_BAD_REGISTER_NUMBER;
+
+	raw_spin_lock_irqsave(&pci_config_lock, flags);
+	ret = sh7786_pcie_config_access(PCI_ACCESS_READ, bus,
+					devfn, where, &data);
+	if (ret != PCIBIOS_SUCCESSFUL)
+		goto out;
+
+	dev_dbg(&bus->dev, "pcie-config-write: bus=%3d devfn=0x%04x "
+		"where=0x%04x size=%d val=%08lx\n", bus->number,
+		devfn, where, size, (unsigned long)val);
+
+	if (size == 1) {
+		shift = (where & 3) << 3;
+		data &= ~(0xff << shift);
+		data |= ((val & 0xff) << shift);
+	} else if (size == 2) {
+		shift = (where & 2) << 3;
+		data &= ~(0xffff << shift);
+		data |= ((val & 0xffff) << shift);
+	} else
+		data = val;
+
+	ret = sh7786_pcie_config_access(PCI_ACCESS_WRITE, bus,
+					devfn, where, &data);
+out:
+	raw_spin_unlock_irqrestore(&pci_config_lock, flags);
+	return ret;
+}
+
+struct pci_ops sh7786_pci_ops = {
+	.read	= sh7786_pcie_read,
+	.write	= sh7786_pcie_write,
+};
diff --git a/arch/sh/drivers/pci/pci-dreamcast.c b/arch/sh/drivers/pci/pci-dreamcast.c
new file mode 100644
index 0000000..6336941
--- /dev/null
+++ b/arch/sh/drivers/pci/pci-dreamcast.c
@@ -0,0 +1,100 @@
+/*
+ * PCI support for the Sega Dreamcast
+ *
+ * Copyright (C) 2001, 2002  M. R. Brown
+ * Copyright (C) 2002, 2003  Paul Mundt
+ *
+ * This file originally bore the message (with enclosed-$):
+ *	Id: pci.c,v 1.3 2003/05/04 19:29:46 lethal Exp
+ *	Dreamcast PCI: Supports SEGA Broadband Adaptor only.
+ *
+ * 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/sched.h>
+#include <linux/kernel.h>
+#include <linux/param.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <linux/pci.h>
+#include <linux/module.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <mach/pci.h>
+
+static struct resource gapspci_resources[] = {
+	{
+		.name	= "GAPSPCI IO",
+		.start	= GAPSPCI_BBA_CONFIG,
+		.end	= GAPSPCI_BBA_CONFIG + GAPSPCI_BBA_CONFIG_SIZE - 1,
+		.flags	= IORESOURCE_IO,
+	},  {
+		.name	= "GAPSPCI mem",
+		.start	= GAPSPCI_DMA_BASE,
+		.end	= GAPSPCI_DMA_BASE + GAPSPCI_DMA_SIZE - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+};
+
+static struct pci_channel dreamcast_pci_controller = {
+	.pci_ops	= &gapspci_pci_ops,
+	.resources	= gapspci_resources,
+	.nr_resources	= ARRAY_SIZE(gapspci_resources),
+	.io_offset	= 0x00000000,
+	.mem_offset	= 0x00000000,
+};
+
+/*
+ * gapspci init
+ */
+
+static int __init gapspci_init(void)
+{
+	char idbuf[16];
+	int i;
+
+	/*
+	 * FIXME: All of this wants documenting to some degree,
+	 * even some basic register definitions would be nice.
+	 *
+	 * I haven't seen anything this ugly since.. maple.
+	 */
+
+	for (i=0; i<16; i++)
+		idbuf[i] = inb(GAPSPCI_REGS+i);
+
+	if (strncmp(idbuf, "GAPSPCI_BRIDGE_2", 16))
+		return -ENODEV;
+
+	outl(0x5a14a501, GAPSPCI_REGS+0x18);
+
+	for (i=0; i<1000000; i++)
+		cpu_relax();
+
+	if (inl(GAPSPCI_REGS+0x18) != 1)
+		return -EINVAL;
+
+	outl(0x01000000, GAPSPCI_REGS+0x20);
+	outl(0x01000000, GAPSPCI_REGS+0x24);
+
+	outl(GAPSPCI_DMA_BASE, GAPSPCI_REGS+0x28);
+	outl(GAPSPCI_DMA_BASE+GAPSPCI_DMA_SIZE, GAPSPCI_REGS+0x2c);
+
+	outl(1, GAPSPCI_REGS+0x14);
+	outl(1, GAPSPCI_REGS+0x34);
+
+	/* Setting Broadband Adapter */
+	outw(0xf900, GAPSPCI_BBA_CONFIG+0x06);
+	outl(0x00000000, GAPSPCI_BBA_CONFIG+0x30);
+	outb(0x00, GAPSPCI_BBA_CONFIG+0x3c);
+	outb(0xf0, GAPSPCI_BBA_CONFIG+0x0d);
+	outw(0x0006, GAPSPCI_BBA_CONFIG+0x04);
+	outl(0x00002001, GAPSPCI_BBA_CONFIG+0x10);
+	outl(0x01000000, GAPSPCI_BBA_CONFIG+0x14);
+
+	return register_pci_controller(&dreamcast_pci_controller);
+}
+arch_initcall(gapspci_init);
diff --git a/arch/sh/drivers/pci/pci-sh4.h b/arch/sh/drivers/pci/pci-sh4.h
new file mode 100644
index 0000000..1543c50
--- /dev/null
+++ b/arch/sh/drivers/pci/pci-sh4.h
@@ -0,0 +1,182 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __PCI_SH4_H
+#define __PCI_SH4_H
+
+#if defined(CONFIG_CPU_SUBTYPE_SH7780) || \
+    defined(CONFIG_CPU_SUBTYPE_SH7785) || \
+    defined(CONFIG_CPU_SUBTYPE_SH7763)
+#include "pci-sh7780.h"
+#else
+#include "pci-sh7751.h"
+#endif
+
+#include <asm/io.h>
+
+#define SH4_PCICR		0x100		/* PCI Control Register */
+  #define SH4_PCICR_PREFIX	  0xA5000000	/* CR prefix for write */
+  #define SH4_PCICR_FTO		  0x00000400	/* TRDY/IRDY Enable */
+  #define SH4_PCICR_TRSB	  0x00000200	/* Target Read Single */
+  #define SH4_PCICR_BSWP	  0x00000100	/* Target Byte Swap */
+  #define SH4_PCICR_PLUP	  0x00000080	/* Enable PCI Pullup */
+  #define SH4_PCICR_ARBM	  0x00000040	/* PCI Arbitration Mode */
+  #define SH4_PCICR_MD		  0x00000030	/* MD9 and MD10 status */
+  #define SH4_PCICR_SERR	  0x00000008	/* SERR output assert */
+  #define SH4_PCICR_INTA	  0x00000004	/* INTA output assert */
+  #define SH4_PCICR_PRST	  0x00000002	/* PCI Reset Assert */
+  #define SH4_PCICR_CFIN	  0x00000001	/* Central Fun. Init Done */
+#define SH4_PCILSR0		0x104		/* PCI Local Space Register0 */
+#define SH4_PCILSR1		0x108		/* PCI Local Space Register1 */
+#define SH4_PCILAR0		0x10C		/* PCI Local Addr Register1 */
+#define SH4_PCILAR1		0x110		/* PCI Local Addr Register1 */
+#define SH4_PCIINT		0x114		/* PCI Interrupt Register */
+  #define SH4_PCIINT_MLCK	  0x00008000	/* Master Lock Error */
+  #define SH4_PCIINT_TABT	  0x00004000	/* Target Abort Error */
+  #define SH4_PCIINT_TRET	  0x00000200	/* Target Retry Error */
+  #define SH4_PCIINT_MFDE	  0x00000100	/* Master Func. Disable Error */
+  #define SH4_PCIINT_PRTY	  0x00000080	/* Address Parity Error */
+  #define SH4_PCIINT_SERR	  0x00000040	/* SERR Detection Error */
+  #define SH4_PCIINT_TWDP	  0x00000020	/* Tgt. Write Parity Error */
+  #define SH4_PCIINT_TRDP	  0x00000010	/* Tgt. Read Parity Err Det. */
+  #define SH4_PCIINT_MTABT	  0x00000008	/* Master-Tgt. Abort Error */
+  #define SH4_PCIINT_MMABT	  0x00000004	/* Master-Master Abort Error */
+  #define SH4_PCIINT_MWPD	  0x00000002	/* Master Write PERR Detect */
+  #define SH4_PCIINT_MRPD	  0x00000001	/* Master Read PERR Detect */
+#define SH4_PCIINTM		0x118		/* PCI Interrupt Mask */
+  #define SH4_PCIINTM_TTADIM	  BIT(14)	/* Target-target abort interrupt */
+  #define SH4_PCIINTM_TMTOIM	  BIT(9)	/* Target retry timeout */
+  #define SH4_PCIINTM_MDEIM	  BIT(8)	/* Master function disable error */
+  #define SH4_PCIINTM_APEDIM	  BIT(7)	/* Address parity error detection */
+  #define SH4_PCIINTM_SDIM	  BIT(6)	/* SERR detection */
+  #define SH4_PCIINTM_DPEITWM	  BIT(5)	/* Data parity error for target write */
+  #define SH4_PCIINTM_PEDITRM	  BIT(4)	/* PERR detection for target read */
+  #define SH4_PCIINTM_TADIMM	  BIT(3)	/* Target abort for master */
+  #define SH4_PCIINTM_MADIMM	  BIT(2)	/* Master abort for master */
+  #define SH4_PCIINTM_MWPDIM	  BIT(1)	/* Master write data parity error */
+  #define SH4_PCIINTM_MRDPEIM	  BIT(0)	/* Master read data parity error */
+#define SH4_PCIALR		0x11C		/* Error Address Register */
+#define SH4_PCICLR		0x120		/* Error Command/Data */
+  #define SH4_PCICLR_MPIO	  0x80000000
+  #define SH4_PCICLR_MDMA0	  0x40000000	/* DMA0 Transfer Error */
+  #define SH4_PCICLR_MDMA1	  0x20000000	/* DMA1 Transfer Error */
+  #define SH4_PCICLR_MDMA2	  0x10000000	/* DMA2 Transfer Error */
+  #define SH4_PCICLR_MDMA3	  0x08000000	/* DMA3 Transfer Error */
+  #define SH4_PCICLR_TGT	  0x04000000	/* Target Transfer Error */
+  #define SH4_PCICLR_CMDL	  0x0000000F	/* PCI Command at Error */
+#define SH4_PCIAINT		0x130		/* Arbiter Interrupt Register */
+  #define SH4_PCIAINT_MBKN	  0x00002000	/* Master Broken Interrupt */
+  #define SH4_PCIAINT_TBTO	  0x00001000	/* Target Bus Time Out */
+  #define SH4_PCIAINT_MBTO	  0x00000800	/* Master Bus Time Out */
+  #define SH4_PCIAINT_TABT	  0x00000008	/* Target Abort */
+  #define SH4_PCIAINT_MABT	  0x00000004	/* Master Abort */
+  #define SH4_PCIAINT_RDPE	  0x00000002	/* Read Data Parity Error */
+  #define SH4_PCIAINT_WDPE	  0x00000001	/* Write Data Parity Error */
+#define SH4_PCIAINTM            0x134		/* Arbiter Int. Mask Register */
+#define SH4_PCIBMLR		0x138		/* Error Bus Master Register */
+  #define SH4_PCIBMLR_REQ4	  0x00000010	/* REQ4 bus master at error */
+  #define SH4_PCIBMLR_REQ3	  0x00000008	/* REQ3 bus master at error */
+  #define SH4_PCIBMLR_REQ2	  0x00000004	/* REQ2 bus master at error */
+  #define SH4_PCIBMLR_REQ1	  0x00000002	/* REQ1 bus master at error */
+  #define SH4_PCIBMLR_REQ0	  0x00000001	/* REQ0 bus master at error */
+#define SH4_PCIDMABT		0x140		/* DMA Transfer Arb. Register */
+  #define SH4_PCIDMABT_RRBN	  0x00000001	/* DMA Arbitor Round-Robin */
+#define SH4_PCIDPA0		0x180		/* DMA0 Transfer Addr. */
+#define SH4_PCIDLA0		0x184		/* DMA0 Local Addr. */
+#define SH4_PCIDTC0		0x188		/* DMA0 Transfer Cnt. */
+#define SH4_PCIDCR0		0x18C		/* DMA0 Control Register */
+  #define SH4_PCIDCR_ALGN	  0x00000600	/* DMA Alignment Mode */
+  #define SH4_PCIDCR_MAST	  0x00000100	/* DMA Termination Type */
+  #define SH4_PCIDCR_INTM	  0x00000080	/* DMA Interrupt Done Mask*/
+  #define SH4_PCIDCR_INTS	  0x00000040	/* DMA Interrupt Done Status */
+  #define SH4_PCIDCR_LHLD	  0x00000020	/* Local Address Control */
+  #define SH4_PCIDCR_PHLD	  0x00000010	/* PCI Address Control*/
+  #define SH4_PCIDCR_IOSEL	  0x00000008	/* PCI Address Space Type */
+  #define SH4_PCIDCR_DIR	  0x00000004	/* DMA Transfer Direction */
+  #define SH4_PCIDCR_STOP	  0x00000002	/* Force DMA Stop */
+  #define SH4_PCIDCR_STRT	  0x00000001	/* DMA Start */
+#define SH4_PCIDPA1		0x190		/* DMA1 Transfer Addr. */
+#define SH4_PCIDLA1		0x194		/* DMA1 Local Addr. */
+#define SH4_PCIDTC1		0x198		/* DMA1 Transfer Cnt. */
+#define SH4_PCIDCR1		0x19C		/* DMA1 Control Register */
+#define SH4_PCIDPA2		0x1A0		/* DMA2 Transfer Addr. */
+#define SH4_PCIDLA2		0x1A4		/* DMA2 Local Addr. */
+#define SH4_PCIDTC2		0x1A8		/* DMA2 Transfer Cnt. */
+#define SH4_PCIDCR2		0x1AC		/* DMA2 Control Register */
+#define SH4_PCIDPA3		0x1B0		/* DMA3 Transfer Addr. */
+#define SH4_PCIDLA3		0x1B4		/* DMA3 Local Addr. */
+#define SH4_PCIDTC3		0x1B8		/* DMA3 Transfer Cnt. */
+#define SH4_PCIDCR3		0x1BC		/* DMA3 Control Register */
+#define SH4_PCIPAR		0x1C0		/* PIO Address Register */
+  #define SH4_PCIPAR_CFGEN	  0x80000000	/* Configuration Enable */
+  #define SH4_PCIPAR_BUSNO	  0x00FF0000	/* Config. Bus Number */
+  #define SH4_PCIPAR_DEVNO	  0x0000FF00	/* Config. Device Number */
+  #define SH4_PCIPAR_REGAD	  0x000000FC	/* Register Address Number */
+#define SH4_PCIMBR		0x1C4		/* Memory Base Address */
+  #define SH4_PCIMBR_MASK	  0xFF000000	/* Memory Space Mask */
+  #define SH4_PCIMBR_LOCK	  0x00000001	/* Lock Memory Space */
+#define SH4_PCIIOBR		0x1C8		/* I/O Base Address Register */
+  #define SH4_PCIIOBR_MASK	  0xFFFC0000	/* IO Space Mask */
+  #define SH4_PCIIOBR_LOCK	  0x00000001	/* Lock IO Space */
+#define SH4_PCIPINT		0x1CC		/* Power Mgmnt Int. Register */
+  #define SH4_PCIPINT_D3	  0x00000002	/* D3 Pwr Mgmt. Interrupt */
+  #define SH4_PCIPINT_D0	  0x00000001	/* D0 Pwr Mgmt. Interrupt */
+#define SH4_PCIPINTM		0x1D0		/* Power Mgmnt Mask Register */
+#define SH4_PCICLKR		0x1D4		/* Clock Ctrl. Register */
+  #define SH4_PCICLKR_PCSTP	  0x00000002	/* PCI Clock Stop */
+  #define SH4_PCICLKR_BCSTP	  0x00000001	/* BCLK Clock Stop */
+/* For definitions of BCR, MCR see ... */
+#define SH4_PCIBCR1		0x1E0		/* Memory BCR1 Register */
+  #define SH4_PCIMBR0		SH4_PCIBCR1
+#define SH4_PCIBCR2		0x1E4		/* Memory BCR2 Register */
+  #define SH4_PCIMBMR0		SH4_PCIBCR2
+#define SH4_PCIWCR1		0x1E8		/* Wait Control 1 Register */
+#define SH4_PCIWCR2		0x1EC		/* Wait Control 2 Register */
+#define SH4_PCIWCR3		0x1F0		/* Wait Control 3 Register */
+  #define SH4_PCIMBR2		SH4_PCIWCR3
+#define SH4_PCIMCR		0x1F4		/* Memory Control Register */
+#define SH4_PCIBCR3		0x1f8		/* Memory BCR3 Register */
+#define SH4_PCIPCTR             0x200		/* Port Control Register */
+  #define SH4_PCIPCTR_P2EN	  0x000400000	/* Port 2 Enable */
+  #define SH4_PCIPCTR_P1EN	  0x000200000	/* Port 1 Enable */
+  #define SH4_PCIPCTR_P0EN	  0x000100000	/* Port 0 Enable */
+  #define SH4_PCIPCTR_P2UP	  0x000000020	/* Port2 Pull Up Enable */
+  #define SH4_PCIPCTR_P2IO	  0x000000010	/* Port2 Output Enable */
+  #define SH4_PCIPCTR_P1UP	  0x000000008	/* Port1 Pull Up Enable */
+  #define SH4_PCIPCTR_P1IO	  0x000000004	/* Port1 Output Enable */
+  #define SH4_PCIPCTR_P0UP	  0x000000002	/* Port0 Pull Up Enable */
+  #define SH4_PCIPCTR_P0IO	  0x000000001	/* Port0 Output Enable */
+#define SH4_PCIPDTR		0x204		/* Port Data Register */
+  #define SH4_PCIPDTR_PB5	  0x000000020	/* Port 5 Enable */
+  #define SH4_PCIPDTR_PB4	  0x000000010	/* Port 4 Enable */
+  #define SH4_PCIPDTR_PB3	  0x000000008	/* Port 3 Enable */
+  #define SH4_PCIPDTR_PB2	  0x000000004	/* Port 2 Enable */
+  #define SH4_PCIPDTR_PB1	  0x000000002	/* Port 1 Enable */
+  #define SH4_PCIPDTR_PB0	  0x000000001	/* Port 0 Enable */
+#define SH4_PCIPDR		0x220		/* Port IO Data Register */
+
+/* arch/sh/kernel/drivers/pci/ops-sh4.c */
+extern struct pci_ops sh4_pci_ops;
+int pci_fixup_pcic(struct pci_channel *chan);
+
+struct sh4_pci_address_space {
+	unsigned long base;
+	unsigned long size;
+};
+
+struct sh4_pci_address_map {
+	struct sh4_pci_address_space window0;
+	struct sh4_pci_address_space window1;
+};
+
+static inline void pci_write_reg(struct pci_channel *chan,
+				 unsigned long val, unsigned long reg)
+{
+	__raw_writel(val, chan->reg_base + reg);
+}
+
+static inline unsigned long pci_read_reg(struct pci_channel *chan,
+					 unsigned long reg)
+{
+	return __raw_readl(chan->reg_base + reg);
+}
+
+#endif /* __PCI_SH4_H */
diff --git a/arch/sh/drivers/pci/pci-sh5.c b/arch/sh/drivers/pci/pci-sh5.c
new file mode 100644
index 0000000..8229114
--- /dev/null
+++ b/arch/sh/drivers/pci/pci-sh5.c
@@ -0,0 +1,219 @@
+/*
+ * Copyright (C) 2001 David J. Mckay (david.mckay@st.com)
+ * Copyright (C) 2003, 2004 Paul Mundt
+ * Copyright (C) 2004 Richard Curnow
+ *
+ * May be copied or modified under the terms of the GNU General Public
+ * License.  See linux/COPYING for more information.
+ *
+ * Support functions for the SH5 PCI hardware.
+ */
+
+#include <linux/kernel.h>
+#include <linux/rwsem.h>
+#include <linux/smp.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <linux/types.h>
+#include <linux/irq.h>
+#include <cpu/irq.h>
+#include <asm/io.h>
+#include "pci-sh5.h"
+
+unsigned long pcicr_virt;
+unsigned long PCI_IO_AREA;
+
+/* Rounds a number UP to the nearest power of two. Used for
+ * sizing the PCI window.
+ */
+static u32 __init r2p2(u32 num)
+{
+	int i = 31;
+	u32 tmp = num;
+
+	if (num == 0)
+		return 0;
+
+	do {
+		if (tmp & (1 << 31))
+			break;
+		i--;
+		tmp <<= 1;
+	} while (i >= 0);
+
+	tmp = 1 << i;
+	/* If the original number isn't a power of 2, round it up */
+	if (tmp != num)
+		tmp <<= 1;
+
+	return tmp;
+}
+
+static irqreturn_t pcish5_err_irq(int irq, void *dev_id)
+{
+	struct pt_regs *regs = get_irq_regs();
+	unsigned pci_int, pci_air, pci_cir, pci_aint;
+
+	pci_int = SH5PCI_READ(INT);
+	pci_cir = SH5PCI_READ(CIR);
+	pci_air = SH5PCI_READ(AIR);
+
+	if (pci_int) {
+		printk("PCI INTERRUPT (at %08llx)!\n", regs->pc);
+		printk("PCI INT -> 0x%x\n", pci_int & 0xffff);
+		printk("PCI AIR -> 0x%x\n", pci_air);
+		printk("PCI CIR -> 0x%x\n", pci_cir);
+		SH5PCI_WRITE(INT, ~0);
+	}
+
+	pci_aint = SH5PCI_READ(AINT);
+	if (pci_aint) {
+		printk("PCI ARB INTERRUPT!\n");
+		printk("PCI AINT -> 0x%x\n", pci_aint);
+		printk("PCI AIR -> 0x%x\n", pci_air);
+		printk("PCI CIR -> 0x%x\n", pci_cir);
+		SH5PCI_WRITE(AINT, ~0);
+	}
+
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t pcish5_serr_irq(int irq, void *dev_id)
+{
+	printk("SERR IRQ\n");
+
+	return IRQ_NONE;
+}
+
+static struct resource sh5_pci_resources[2];
+
+static struct pci_channel sh5pci_controller = {
+	.pci_ops		= &sh5_pci_ops,
+	.resources		= sh5_pci_resources,
+	.nr_resources		= ARRAY_SIZE(sh5_pci_resources),
+	.mem_offset		= 0x00000000,
+	.io_offset		= 0x00000000,
+};
+
+static int __init sh5pci_init(void)
+{
+	unsigned long memStart = __pa(memory_start);
+	unsigned long memSize = __pa(memory_end) - memStart;
+	u32 lsr0;
+	u32 uval;
+
+        if (request_irq(IRQ_ERR, pcish5_err_irq,
+                        0, "PCI Error",NULL) < 0) {
+                printk(KERN_ERR "PCISH5: Cannot hook PCI_PERR interrupt\n");
+                return -EINVAL;
+        }
+
+        if (request_irq(IRQ_SERR, pcish5_serr_irq,
+                        0, "PCI SERR interrupt", NULL) < 0) {
+                printk(KERN_ERR "PCISH5: Cannot hook PCI_SERR interrupt\n");
+                return -EINVAL;
+        }
+
+	pcicr_virt = (unsigned long)ioremap_nocache(SH5PCI_ICR_BASE, 1024);
+	if (!pcicr_virt) {
+		panic("Unable to remap PCICR\n");
+	}
+
+	PCI_IO_AREA = (unsigned long)ioremap_nocache(SH5PCI_IO_BASE, 0x10000);
+	if (!PCI_IO_AREA) {
+		panic("Unable to remap PCIIO\n");
+	}
+
+	/* Clear snoop registers */
+        SH5PCI_WRITE(CSCR0, 0);
+        SH5PCI_WRITE(CSCR1, 0);
+
+        /* Switch off interrupts */
+        SH5PCI_WRITE(INTM,  0);
+        SH5PCI_WRITE(AINTM, 0);
+        SH5PCI_WRITE(PINTM, 0);
+
+        /* Set bus active, take it out of reset */
+        uval = SH5PCI_READ(CR);
+
+	/* Set command Register */
+        SH5PCI_WRITE(CR, uval | CR_LOCK_MASK | CR_CFINT| CR_FTO | CR_PFE |
+		     CR_PFCS | CR_BMAM);
+
+	uval=SH5PCI_READ(CR);
+
+        /* Allow it to be a master */
+	/* NB - WE DISABLE I/O ACCESS to stop overlap */
+        /* set WAIT bit to enable stepping, an attempt to improve stability */
+	SH5PCI_WRITE_SHORT(CSR_CMD,
+			    PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER |
+			    PCI_COMMAND_WAIT);
+
+        /*
+        ** Set translation mapping memory in order to convert the address
+        ** used for the main bus, to the PCI internal address.
+        */
+        SH5PCI_WRITE(MBR,0x40000000);
+
+        /* Always set the max size 512M */
+        SH5PCI_WRITE(MBMR, PCISH5_MEM_SIZCONV(512*1024*1024));
+
+        /*
+        ** I/O addresses are mapped at internal PCI specific address
+        ** as is described into the configuration bridge table.
+        ** These are changed to 0, to allow cards that have legacy
+        ** io such as vga to function correctly. We set the SH5 IOBAR to
+        ** 256K, which is a bit big as we can only have 64K of address space
+        */
+
+        SH5PCI_WRITE(IOBR,0x0);
+
+        /* Set up a 256K window. Totally pointless waste  of address space */
+        SH5PCI_WRITE(IOBMR,0);
+
+	/* The SH5 has a HUGE 256K I/O region, which breaks the PCI spec.
+	 * Ideally, we would want to map the I/O region somewhere, but it
+	 * is so big this is not that easy!
+         */
+	SH5PCI_WRITE(CSR_IBAR0,~0);
+	/* Set memory size value */
+        memSize = memory_end - memory_start;
+
+	/* Now we set up the mbars so the PCI bus can see the memory of
+	 * the machine */
+	if (memSize < (1024 * 1024)) {
+                printk(KERN_ERR "PCISH5: Ridiculous memory size of 0x%lx?\n",
+		       memSize);
+                return -EINVAL;
+        }
+
+        /* Set LSR 0 */
+        lsr0 = (memSize > (512 * 1024 * 1024)) ? 0x1ff00001 :
+		((r2p2(memSize) - 0x100000) | 0x1);
+        SH5PCI_WRITE(LSR0, lsr0);
+
+        /* Set MBAR 0 */
+        SH5PCI_WRITE(CSR_MBAR0, memory_start);
+        SH5PCI_WRITE(LAR0, memory_start);
+
+        SH5PCI_WRITE(CSR_MBAR1,0);
+        SH5PCI_WRITE(LAR1,0);
+        SH5PCI_WRITE(LSR1,0);
+
+        /* Enable the PCI interrupts on the device */
+        SH5PCI_WRITE(INTM,  ~0);
+        SH5PCI_WRITE(AINTM, ~0);
+        SH5PCI_WRITE(PINTM, ~0);
+
+	sh5_pci_resources[0].start = PCI_IO_AREA;
+	sh5_pci_resources[0].end = PCI_IO_AREA + 0x10000;
+
+	sh5_pci_resources[1].start = memStart;
+	sh5_pci_resources[1].end = memStart + memSize;
+
+	return register_pci_controller(&sh5pci_controller);
+}
+arch_initcall(sh5pci_init);
diff --git a/arch/sh/drivers/pci/pci-sh5.h b/arch/sh/drivers/pci/pci-sh5.h
new file mode 100644
index 0000000..3f01dec
--- /dev/null
+++ b/arch/sh/drivers/pci/pci-sh5.h
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2001 David J. Mckay (david.mckay@st.com)
+ *
+ * May be copied or modified under the terms of the GNU General Public
+ * License.  See linux/COPYING for more information.
+ *
+ * Definitions for the SH5 PCI hardware.
+ */
+#ifndef __PCI_SH5_H
+#define __PCI_SH5_H
+
+/* Product ID */
+#define PCISH5_PID		0x350d
+
+/* vendor ID */
+#define PCISH5_VID		0x1054
+
+/* Configuration types */
+#define ST_TYPE0                0x00    /* Configuration cycle type 0 */
+#define ST_TYPE1                0x01    /* Configuration cycle type 1 */
+
+/* VCR data */
+#define PCISH5_VCR_STATUS      0x00
+#define PCISH5_VCR_VERSION     0x08
+
+/*
+** ICR register offsets and bits
+*/
+#define PCISH5_ICR_CR          0x100   /* PCI control register values */
+#define CR_PBAM                 (1<<12)
+#define CR_PFCS                 (1<<11)
+#define CR_FTO                  (1<<10)
+#define CR_PFE                  (1<<9)
+#define CR_TBS                  (1<<8)
+#define CR_SPUE                 (1<<7)
+#define CR_BMAM                 (1<<6)
+#define CR_HOST                 (1<<5)
+#define CR_CLKEN                (1<<4)
+#define CR_SOCS                 (1<<3)
+#define CR_IOCS                 (1<<2)
+#define CR_RSTCTL               (1<<1)
+#define CR_CFINT                (1<<0)
+#define CR_LOCK_MASK            0xa5000000
+
+#define PCISH5_ICR_INT         0x114   /* Interrupt registert values     */
+#define INT_MADIM               (1<<2)
+
+#define PCISH5_ICR_LSR0        0X104   /* Local space register values    */
+#define PCISH5_ICR_LSR1        0X108   /* Local space register values    */
+#define PCISH5_ICR_LAR0        0x10c   /* Local address register values  */
+#define PCISH5_ICR_LAR1        0x110   /* Local address register values  */
+#define PCISH5_ICR_INTM        0x118   /* Interrupt mask register values                         */
+#define PCISH5_ICR_AIR         0x11c   /* Interrupt error address information register values    */
+#define PCISH5_ICR_CIR         0x120   /* Interrupt error command information register values    */
+#define PCISH5_ICR_AINT        0x130   /* Interrupt error arbiter interrupt register values      */
+#define PCISH5_ICR_AINTM       0x134   /* Interrupt error arbiter interrupt mask register values */
+#define PCISH5_ICR_BMIR        0x138   /* Interrupt error info register of bus master values     */
+#define PCISH5_ICR_PAR         0x1c0   /* Pio address register values                            */
+#define PCISH5_ICR_MBR         0x1c4   /* Memory space bank register values                      */
+#define PCISH5_ICR_IOBR        0x1c8   /* I/O space bank register values                         */
+#define PCISH5_ICR_PINT        0x1cc   /* power management interrupt register values             */
+#define PCISH5_ICR_PINTM       0x1d0   /* power management interrupt mask register values        */
+#define PCISH5_ICR_MBMR        0x1d8   /* memory space bank mask register values                 */
+#define PCISH5_ICR_IOBMR       0x1dc   /* I/O space bank mask register values                    */
+#define PCISH5_ICR_CSCR0       0x210   /* PCI cache snoop control register 0                     */
+#define PCISH5_ICR_CSCR1       0x214   /* PCI cache snoop control register 1                     */
+#define PCISH5_ICR_PDR         0x220   /* Pio data register values                               */
+
+/* These are configs space registers */
+#define PCISH5_ICR_CSR_VID     0x000	/* Vendor id                           */
+#define PCISH5_ICR_CSR_DID     0x002   /* Device id                           */
+#define PCISH5_ICR_CSR_CMD     0x004   /* Command register                    */
+#define PCISH5_ICR_CSR_STATUS  0x006   /* Stautus                             */
+#define PCISH5_ICR_CSR_IBAR0   0x010   /* I/O base address register           */
+#define PCISH5_ICR_CSR_MBAR0   0x014   /* First  Memory base address register */
+#define PCISH5_ICR_CSR_MBAR1   0x018   /* Second Memory base address register */
+
+/* Base address of registers */
+#define SH5PCI_ICR_BASE (PHYS_PCI_BLOCK + 0x00040000)
+#define SH5PCI_IO_BASE  (PHYS_PCI_BLOCK + 0x00800000)
+/* #define SH5PCI_VCR_BASE (P2SEG_PCICB_BLOCK + P2SEG)    */
+
+extern unsigned long pcicr_virt;
+/* Register selection macro */
+#define PCISH5_ICR_REG(x)                ( pcicr_virt + (PCISH5_ICR_##x))
+/* #define PCISH5_VCR_REG(x)                ( SH5PCI_VCR_BASE (PCISH5_VCR_##x)) */
+
+/* Write I/O functions */
+#define SH5PCI_WRITE(reg,val)        __raw_writel((u32)(val),PCISH5_ICR_REG(reg))
+#define SH5PCI_WRITE_SHORT(reg,val)  __raw_writew((u16)(val),PCISH5_ICR_REG(reg))
+#define SH5PCI_WRITE_BYTE(reg,val)   __raw_writeb((u8)(val),PCISH5_ICR_REG(reg))
+
+/* Read I/O functions */
+#define SH5PCI_READ(reg)             __raw_readl(PCISH5_ICR_REG(reg))
+#define SH5PCI_READ_SHORT(reg)       __raw_readw(PCISH5_ICR_REG(reg))
+#define SH5PCI_READ_BYTE(reg)        __raw_readb(PCISH5_ICR_REG(reg))
+
+/* Set PCI config bits */
+#define SET_CONFIG_BITS(bus,devfn,where)  ((((bus) << 16) | ((devfn) << 8) | ((where) & ~3)) | 0x80000000)
+
+/* Set PCI command register */
+#define CONFIG_CMD(bus, devfn, where)            SET_CONFIG_BITS(bus->number,devfn,where)
+
+/* Size converters */
+#define PCISH5_MEM_SIZCONV(x)		  (((x / 0x40000) - 1) << 18)
+#define PCISH5_IO_SIZCONV(x)		  (((x / 0x40000) - 1) << 18)
+
+extern struct pci_ops sh5_pci_ops;
+
+#endif /* __PCI_SH5_H */
diff --git a/arch/sh/drivers/pci/pci-sh7751.c b/arch/sh/drivers/pci/pci-sh7751.c
new file mode 100644
index 0000000..86adb1e
--- /dev/null
+++ b/arch/sh/drivers/pci/pci-sh7751.c
@@ -0,0 +1,182 @@
+/*
+ * Low-Level PCI Support for the SH7751
+ *
+ *  Copyright (C) 2003 - 2009  Paul Mundt
+ *  Copyright (C) 2001  Dustin McIntire
+ *
+ *  With cleanup by Paul van Gool <pvangool@mimotech.com>, 2003.
+ *
+ * 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/pci.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/io.h>
+#include "pci-sh4.h"
+#include <asm/addrspace.h>
+#include <asm/sizes.h>
+
+static int __init __area_sdram_check(struct pci_channel *chan,
+				     unsigned int area)
+{
+	unsigned long word;
+
+	word = __raw_readl(SH7751_BCR1);
+	/* check BCR for SDRAM in area */
+	if (((word >> area) & 1) == 0) {
+		printk("PCI: Area %d is not configured for SDRAM. BCR1=0x%lx\n",
+		       area, word);
+		return 0;
+	}
+	pci_write_reg(chan, word, SH4_PCIBCR1);
+
+	word = __raw_readw(SH7751_BCR2);
+	/* check BCR2 for 32bit SDRAM interface*/
+	if (((word >> (area << 1)) & 0x3) != 0x3) {
+		printk("PCI: Area %d is not 32 bit SDRAM. BCR2=0x%lx\n",
+		       area, word);
+		return 0;
+	}
+	pci_write_reg(chan, word, SH4_PCIBCR2);
+
+	return 1;
+}
+
+static struct resource sh7751_pci_resources[] = {
+	{
+		.name	= "SH7751_IO",
+		.start	= 0x1000,
+		.end	= SZ_4M - 1,
+		.flags	= IORESOURCE_IO
+	}, {
+		.name	= "SH7751_mem",
+		.start	= SH7751_PCI_MEMORY_BASE,
+		.end	= SH7751_PCI_MEMORY_BASE + SH7751_PCI_MEM_SIZE - 1,
+		.flags	= IORESOURCE_MEM
+	},
+};
+
+static struct pci_channel sh7751_pci_controller = {
+	.pci_ops	= &sh4_pci_ops,
+	.resources	= sh7751_pci_resources,
+	.nr_resources	= ARRAY_SIZE(sh7751_pci_resources),
+	.mem_offset	= 0x00000000,
+	.io_offset	= 0x00000000,
+	.io_map_base	= SH7751_PCI_IO_BASE,
+};
+
+static struct sh4_pci_address_map sh7751_pci_map = {
+	.window0	= {
+		.base	= SH7751_CS3_BASE_ADDR,
+		.size	= 0x04000000,
+	},
+};
+
+static int __init sh7751_pci_init(void)
+{
+	struct pci_channel *chan = &sh7751_pci_controller;
+	unsigned int id;
+	u32 word, reg;
+
+	printk(KERN_NOTICE "PCI: Starting initialization.\n");
+
+	chan->reg_base = 0xfe200000;
+
+	/* check for SH7751/SH7751R hardware */
+	id = pci_read_reg(chan, SH7751_PCICONF0);
+	if (id != ((SH7751_DEVICE_ID << 16) | SH7751_VENDOR_ID) &&
+	    id != ((SH7751R_DEVICE_ID << 16) | SH7751_VENDOR_ID)) {
+		pr_debug("PCI: This is not an SH7751(R) (%x)\n", id);
+		return -ENODEV;
+	}
+
+	/* Set the BCR's to enable PCI access */
+	reg = __raw_readl(SH7751_BCR1);
+	reg |= 0x80000;
+	__raw_writel(reg, SH7751_BCR1);
+
+	/* Turn the clocks back on (not done in reset)*/
+	pci_write_reg(chan, 0, SH4_PCICLKR);
+	/* Clear Powerdown IRQ's (not done in reset) */
+	word = SH4_PCIPINT_D3 | SH4_PCIPINT_D0;
+	pci_write_reg(chan, word, SH4_PCIPINT);
+
+	/* set the command/status bits to:
+	 * Wait Cycle Control + Parity Enable + Bus Master +
+	 * Mem space enable
+	 */
+	word = SH7751_PCICONF1_WCC | SH7751_PCICONF1_PER |
+	       SH7751_PCICONF1_BUM | SH7751_PCICONF1_MES;
+	pci_write_reg(chan, word, SH7751_PCICONF1);
+
+	/* define this host as the host bridge */
+	word = PCI_BASE_CLASS_BRIDGE << 24;
+	pci_write_reg(chan, word, SH7751_PCICONF2);
+
+	/* Set IO and Mem windows to local address
+	 * Make PCI and local address the same for easy 1 to 1 mapping
+	 */
+	word = sh7751_pci_map.window0.size - 1;
+	pci_write_reg(chan, word, SH4_PCILSR0);
+	/* Set the values on window 0 PCI config registers */
+	word = P2SEGADDR(sh7751_pci_map.window0.base);
+	pci_write_reg(chan, word, SH4_PCILAR0);
+	pci_write_reg(chan, word, SH7751_PCICONF5);
+
+	/* Set the local 16MB PCI memory space window to
+	 * the lowest PCI mapped address
+	 */
+	word = chan->resources[1].start & SH4_PCIMBR_MASK;
+	pr_debug("PCI: Setting upper bits of Memory window to 0x%x\n", word);
+	pci_write_reg(chan, word , SH4_PCIMBR);
+
+	/* Make sure the MSB's of IO window are set to access PCI space
+	 * correctly */
+	word = chan->resources[0].start & SH4_PCIIOBR_MASK;
+	pr_debug("PCI: Setting upper bits of IO window to 0x%x\n", word);
+	pci_write_reg(chan, word, SH4_PCIIOBR);
+
+	/* Set PCI WCRx, BCRx's, copy from BSC locations */
+
+	/* check BCR for SDRAM in specified area */
+	switch (sh7751_pci_map.window0.base) {
+	case SH7751_CS0_BASE_ADDR: word = __area_sdram_check(chan, 0); break;
+	case SH7751_CS1_BASE_ADDR: word = __area_sdram_check(chan, 1); break;
+	case SH7751_CS2_BASE_ADDR: word = __area_sdram_check(chan, 2); break;
+	case SH7751_CS3_BASE_ADDR: word = __area_sdram_check(chan, 3); break;
+	case SH7751_CS4_BASE_ADDR: word = __area_sdram_check(chan, 4); break;
+	case SH7751_CS5_BASE_ADDR: word = __area_sdram_check(chan, 5); break;
+	case SH7751_CS6_BASE_ADDR: word = __area_sdram_check(chan, 6); break;
+	}
+
+	if (!word)
+		return -1;
+
+	/* configure the wait control registers */
+	word = __raw_readl(SH7751_WCR1);
+	pci_write_reg(chan, word, SH4_PCIWCR1);
+	word = __raw_readl(SH7751_WCR2);
+	pci_write_reg(chan, word, SH4_PCIWCR2);
+	word = __raw_readl(SH7751_WCR3);
+	pci_write_reg(chan, word, SH4_PCIWCR3);
+	word = __raw_readl(SH7751_MCR);
+	pci_write_reg(chan, word, SH4_PCIMCR);
+
+	/* NOTE: I'm ignoring the PCI error IRQs for now..
+	 * TODO: add support for the internal error interrupts and
+	 * DMA interrupts...
+	 */
+
+	pci_fixup_pcic(chan);
+
+	/* SH7751 init done, set central function init complete */
+	/* use round robin mode to stop a device starving/overruning */
+	word = SH4_PCICR_PREFIX | SH4_PCICR_CFIN | SH4_PCICR_ARBM;
+	pci_write_reg(chan, word, SH4_PCICR);
+
+	return register_pci_controller(chan);
+}
+arch_initcall(sh7751_pci_init);
diff --git a/arch/sh/drivers/pci/pci-sh7751.h b/arch/sh/drivers/pci/pci-sh7751.h
new file mode 100644
index 0000000..5ede38c
--- /dev/null
+++ b/arch/sh/drivers/pci/pci-sh7751.h
@@ -0,0 +1,129 @@
+/*
+ *	Low-Level PCI Support for SH7751 targets
+ *
+ *  Dustin McIntire (dustin@sensoria.com) (c) 2001
+ *  Paul Mundt (lethal@linux-sh.org) (c) 2003
+ *
+ *  May be copied or modified under the terms of the GNU General Public
+ *  License.  See linux/COPYING for more information.
+ *
+ */
+
+#ifndef _PCI_SH7751_H_
+#define _PCI_SH7751_H_
+
+/* Platform Specific Values */
+#define SH7751_VENDOR_ID             0x1054
+#define SH7751_DEVICE_ID             0x3505
+#define SH7751R_DEVICE_ID            0x350e
+
+/* SH7751 Specific Values */
+#define SH7751_PCI_CONFIG_BASE	     0xFD000000  /* Config space base addr */
+#define SH7751_PCI_CONFIG_SIZE       0x1000000   /* Config space size */
+#define SH7751_PCI_MEMORY_BASE	     0xFD000000  /* Memory space base addr */
+#define SH7751_PCI_MEM_SIZE          0x01000000  /* Size of Memory window */
+#define SH7751_PCI_IO_BASE           0xFE240000  /* IO space base address */
+#define SH7751_PCI_IO_SIZE           0x40000     /* Size of IO window */
+
+#define SH7751_PCIREG_BASE           0xFE200000  /* PCI regs base address */
+
+#define SH7751_PCICONF0            0x0           /* PCI Config Reg 0 */
+  #define SH7751_PCICONF0_DEVID      0xFFFF0000  /* Device ID */
+  #define SH7751_PCICONF0_VNDID      0x0000FFFF  /* Vendor ID */
+#define SH7751_PCICONF1            0x4           /* PCI Config Reg 1 */
+  #define SH7751_PCICONF1_DPE        0x80000000  /* Data Parity Error */
+  #define SH7751_PCICONF1_SSE        0x40000000  /* System Error Status */
+  #define SH7751_PCICONF1_RMA        0x20000000  /* Master Abort */
+  #define SH7751_PCICONF1_RTA        0x10000000  /* Target Abort Rx Status */
+  #define SH7751_PCICONF1_STA        0x08000000  /* Target Abort Exec Status */
+  #define SH7751_PCICONF1_DEV        0x06000000  /* Timing Status */
+  #define SH7751_PCICONF1_DPD        0x01000000  /* Data Parity Status */
+  #define SH7751_PCICONF1_FBBC       0x00800000  /* Back 2 Back Status */
+  #define SH7751_PCICONF1_UDF        0x00400000  /* User Defined Status */
+  #define SH7751_PCICONF1_66M        0x00200000  /* 66Mhz Operation Status */
+  #define SH7751_PCICONF1_PM         0x00100000  /* Power Management Status */
+  #define SH7751_PCICONF1_PBBE       0x00000200  /* Back 2 Back Control */
+  #define SH7751_PCICONF1_SER        0x00000100  /* SERR Output Control */
+  #define SH7751_PCICONF1_WCC        0x00000080  /* Wait Cycle Control */
+  #define SH7751_PCICONF1_PER        0x00000040  /* Parity Error Response */
+  #define SH7751_PCICONF1_VPS        0x00000020  /* VGA Pallet Snoop */
+  #define SH7751_PCICONF1_MWIE       0x00000010  /* Memory Write+Invalidate */
+  #define SH7751_PCICONF1_SPC        0x00000008  /* Special Cycle Control */
+  #define SH7751_PCICONF1_BUM        0x00000004  /* Bus Master Control */
+  #define SH7751_PCICONF1_MES        0x00000002  /* Memory Space Control */
+  #define SH7751_PCICONF1_IOS        0x00000001  /* I/O Space Control */
+#define SH7751_PCICONF2            0x8           /* PCI Config Reg 2 */
+  #define SH7751_PCICONF2_BCC        0xFF000000  /* Base Class Code */
+  #define SH7751_PCICONF2_SCC        0x00FF0000  /* Sub-Class Code */
+  #define SH7751_PCICONF2_RLPI       0x0000FF00  /* Programming Interface */
+  #define SH7751_PCICONF2_REV        0x000000FF  /* Revision ID */
+#define SH7751_PCICONF3            0xC           /* PCI Config Reg 3 */
+  #define SH7751_PCICONF3_BIST7      0x80000000  /* Bist Supported */
+  #define SH7751_PCICONF3_BIST6      0x40000000  /* Bist Executing */
+  #define SH7751_PCICONF3_BIST3_0    0x0F000000  /* Bist Passed */
+  #define SH7751_PCICONF3_HD7        0x00800000  /* Single Function device */
+  #define SH7751_PCICONF3_HD6_0      0x007F0000  /* Configuration Layout */
+  #define SH7751_PCICONF3_LAT        0x0000FF00  /* Latency Timer */
+  #define SH7751_PCICONF3_CLS        0x000000FF  /* Cache Line Size */
+#define SH7751_PCICONF4            0x10          /* PCI Config Reg 4 */
+  #define SH7751_PCICONF4_BASE       0xFFFFFFFC  /* I/O Space Base Addr */
+  #define SH7751_PCICONF4_ASI        0x00000001  /* Address Space Type */
+#define SH7751_PCICONF5            0x14          /* PCI Config Reg 5 */
+  #define SH7751_PCICONF5_BASE       0xFFFFFFF0  /* Mem Space Base Addr */
+  #define SH7751_PCICONF5_LAP        0x00000008  /* Prefetch Enabled */
+  #define SH7751_PCICONF5_LAT        0x00000006  /* Local Memory type */
+  #define SH7751_PCICONF5_ASI        0x00000001  /* Address Space Type */
+#define SH7751_PCICONF6            0x18          /* PCI Config Reg 6 */
+  #define SH7751_PCICONF6_BASE       0xFFFFFFF0  /* Mem Space Base Addr */
+  #define SH7751_PCICONF6_LAP        0x00000008  /* Prefetch Enabled */
+  #define SH7751_PCICONF6_LAT        0x00000006  /* Local Memory type */
+  #define SH7751_PCICONF6_ASI        0x00000001  /* Address Space Type */
+/* PCICONF7 - PCICONF10 are undefined */
+#define SH7751_PCICONF11           0x2C          /* PCI Config Reg 11 */
+  #define SH7751_PCICONF11_SSID      0xFFFF0000  /* Subsystem ID */
+  #define SH7751_PCICONF11_SVID      0x0000FFFF  /* Subsystem Vendor ID */
+/* PCICONF12 is undefined */
+#define SH7751_PCICONF13           0x34          /* PCI Config Reg 13 */
+  #define SH7751_PCICONF13_CPTR      0x000000FF  /* PM function pointer */
+/* PCICONF14 is undefined */
+#define SH7751_PCICONF15           0x3C          /* PCI Config Reg 15 */
+  #define SH7751_PCICONF15_IPIN      0x000000FF  /* Interrupt Pin */
+#define SH7751_PCICONF16           0x40          /* PCI Config Reg 16 */
+  #define SH7751_PCICONF16_PMES      0xF8000000  /* PME Support */
+  #define SH7751_PCICONF16_D2S       0x04000000  /* D2 Support */
+  #define SH7751_PCICONF16_D1S       0x02000000  /* D1 Support */
+  #define SH7751_PCICONF16_DSI       0x00200000  /* Bit Device Init. */
+  #define SH7751_PCICONF16_PMCK      0x00080000  /* Clock for PME req. */
+  #define SH7751_PCICONF16_VER       0x00070000  /* PM Version */
+  #define SH7751_PCICONF16_NIP       0x0000FF00  /* Next Item Pointer */
+  #define SH7751_PCICONF16_CID       0x000000FF  /* Capability Identifier */
+#define SH7751_PCICONF17           0x44          /* PCI Config Reg 17 */
+  #define SH7751_PCICONF17_DATA      0xFF000000  /* Data field for PM */
+  #define SH7751_PCICONF17_PMES      0x00800000  /* PME Status */
+  #define SH7751_PCICONF17_DSCL      0x00600000  /* Data Scaling Value */
+  #define SH7751_PCICONF17_DSEL      0x001E0000  /* Data Select */
+  #define SH7751_PCICONF17_PMEN      0x00010000  /* PME Enable */
+  #define SH7751_PCICONF17_PWST      0x00000003  /* Power State */
+/* SH7715 Internal PCI Registers */
+
+/* Memory Control Registers */
+#define SH7751_BCR1                0xFF800000    /* Memory BCR1 Register */
+#define SH7751_BCR2                0xFF800004    /* Memory BCR2 Register */
+#define SH7751_BCR3                0xFF800050    /* Memory BCR3 Register */
+#define SH7751_BCR4                0xFE0A00F0    /* Memory BCR4 Register */
+#define SH7751_WCR1                0xFF800008    /* Wait Control 1 Register */
+#define SH7751_WCR2                0xFF80000C    /* Wait Control 2 Register */
+#define SH7751_WCR3                0xFF800010    /* Wait Control 3 Register */
+#define SH7751_MCR                 0xFF800014    /* Memory Control Register */
+
+/* General Memory Config Addresses */
+#define SH7751_CS0_BASE_ADDR       0x0
+#define SH7751_MEM_REGION_SIZE     0x04000000
+#define SH7751_CS1_BASE_ADDR       (SH7751_CS0_BASE_ADDR + SH7751_MEM_REGION_SIZE)
+#define SH7751_CS2_BASE_ADDR       (SH7751_CS1_BASE_ADDR + SH7751_MEM_REGION_SIZE)
+#define SH7751_CS3_BASE_ADDR       (SH7751_CS2_BASE_ADDR + SH7751_MEM_REGION_SIZE)
+#define SH7751_CS4_BASE_ADDR       (SH7751_CS3_BASE_ADDR + SH7751_MEM_REGION_SIZE)
+#define SH7751_CS5_BASE_ADDR       (SH7751_CS4_BASE_ADDR + SH7751_MEM_REGION_SIZE)
+#define SH7751_CS6_BASE_ADDR       (SH7751_CS5_BASE_ADDR + SH7751_MEM_REGION_SIZE)
+
+#endif /* _PCI_SH7751_H_ */
diff --git a/arch/sh/drivers/pci/pci-sh7780.c b/arch/sh/drivers/pci/pci-sh7780.c
new file mode 100644
index 0000000..5a6dab6
--- /dev/null
+++ b/arch/sh/drivers/pci/pci-sh7780.c
@@ -0,0 +1,411 @@
+/*
+ * Low-Level PCI Support for the SH7780
+ *
+ *  Copyright (C) 2005 - 2010  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/types.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/interrupt.h>
+#include <linux/timer.h>
+#include <linux/irq.h>
+#include <linux/errno.h>
+#include <linux/delay.h>
+#include <linux/log2.h>
+#include "pci-sh4.h"
+#include <asm/mmu.h>
+#include <asm/sizes.h>
+
+#if defined(CONFIG_CPU_BIG_ENDIAN)
+# define PCICR_ENDIANNESS SH4_PCICR_BSWP
+#else
+# define PCICR_ENDIANNESS 0
+#endif
+
+
+static struct resource sh7785_pci_resources[] = {
+	{
+		.name	= "PCI IO",
+		.start	= 0x1000,
+		.end	= SZ_4M - 1,
+		.flags	= IORESOURCE_IO,
+	}, {
+		.name	= "PCI MEM 0",
+		.start	= 0xfd000000,
+		.end	= 0xfd000000 + SZ_16M - 1,
+		.flags	= IORESOURCE_MEM,
+	}, {
+		.name	= "PCI MEM 1",
+		.start	= 0x10000000,
+		.end	= 0x10000000 + SZ_64M - 1,
+		.flags	= IORESOURCE_MEM,
+	}, {
+		/*
+		 * 32-bit only resources must be last.
+		 */
+		.name	= "PCI MEM 2",
+		.start	= 0xc0000000,
+		.end	= 0xc0000000 + SZ_512M - 1,
+		.flags	= IORESOURCE_MEM | IORESOURCE_MEM_32BIT,
+	},
+};
+
+static struct pci_channel sh7780_pci_controller = {
+	.pci_ops	= &sh4_pci_ops,
+	.resources	= sh7785_pci_resources,
+	.nr_resources	= ARRAY_SIZE(sh7785_pci_resources),
+	.io_offset	= 0,
+	.mem_offset	= 0,
+	.io_map_base	= 0xfe200000,
+	.serr_irq	= evt2irq(0xa00),
+	.err_irq	= evt2irq(0xaa0),
+};
+
+struct pci_errors {
+	unsigned int	mask;
+	const char	*str;
+} pci_arbiter_errors[] = {
+	{ SH4_PCIAINT_MBKN,	"master broken" },
+	{ SH4_PCIAINT_TBTO,	"target bus time out" },
+	{ SH4_PCIAINT_MBTO,	"master bus time out" },
+	{ SH4_PCIAINT_TABT,	"target abort" },
+	{ SH4_PCIAINT_MABT,	"master abort" },
+	{ SH4_PCIAINT_RDPE,	"read data parity error" },
+	{ SH4_PCIAINT_WDPE,	"write data parity error" },
+}, pci_interrupt_errors[] = {
+	{ SH4_PCIINT_MLCK,	"master lock error" },
+	{ SH4_PCIINT_TABT,	"target-target abort" },
+	{ SH4_PCIINT_TRET,	"target retry time out" },
+	{ SH4_PCIINT_MFDE,	"master function disable error" },
+	{ SH4_PCIINT_PRTY,	"address parity error" },
+	{ SH4_PCIINT_SERR,	"SERR" },
+	{ SH4_PCIINT_TWDP,	"data parity error for target write" },
+	{ SH4_PCIINT_TRDP,	"PERR detected for target read" },
+	{ SH4_PCIINT_MTABT,	"target abort for master" },
+	{ SH4_PCIINT_MMABT,	"master abort for master" },
+	{ SH4_PCIINT_MWPD,	"master write data parity error" },
+	{ SH4_PCIINT_MRPD,	"master read data parity error" },
+};
+
+static irqreturn_t sh7780_pci_err_irq(int irq, void *dev_id)
+{
+	struct pci_channel *hose = dev_id;
+	unsigned long addr;
+	unsigned int status;
+	unsigned int cmd;
+	int i;
+
+	addr = __raw_readl(hose->reg_base + SH4_PCIALR);
+
+	/*
+	 * Handle status errors.
+	 */
+	status = __raw_readw(hose->reg_base + PCI_STATUS);
+	if (status & (PCI_STATUS_PARITY |
+		      PCI_STATUS_DETECTED_PARITY |
+		      PCI_STATUS_SIG_TARGET_ABORT |
+		      PCI_STATUS_REC_TARGET_ABORT |
+		      PCI_STATUS_REC_MASTER_ABORT)) {
+		cmd = pcibios_handle_status_errors(addr, status, hose);
+		if (likely(cmd))
+			__raw_writew(cmd, hose->reg_base + PCI_STATUS);
+	}
+
+	/*
+	 * Handle arbiter errors.
+	 */
+	status = __raw_readl(hose->reg_base + SH4_PCIAINT);
+	for (i = cmd = 0; i < ARRAY_SIZE(pci_arbiter_errors); i++) {
+		if (status & pci_arbiter_errors[i].mask) {
+			printk(KERN_DEBUG "PCI: %s, addr=%08lx\n",
+			       pci_arbiter_errors[i].str, addr);
+			cmd |= pci_arbiter_errors[i].mask;
+		}
+	}
+	__raw_writel(cmd, hose->reg_base + SH4_PCIAINT);
+
+	/*
+	 * Handle the remaining PCI errors.
+	 */
+	status = __raw_readl(hose->reg_base + SH4_PCIINT);
+	for (i = cmd = 0; i < ARRAY_SIZE(pci_interrupt_errors); i++) {
+		if (status & pci_interrupt_errors[i].mask) {
+			printk(KERN_DEBUG "PCI: %s, addr=%08lx\n",
+			       pci_interrupt_errors[i].str, addr);
+			cmd |= pci_interrupt_errors[i].mask;
+		}
+	}
+	__raw_writel(cmd, hose->reg_base + SH4_PCIINT);
+
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t sh7780_pci_serr_irq(int irq, void *dev_id)
+{
+	struct pci_channel *hose = dev_id;
+
+	printk(KERN_DEBUG "PCI: system error received: ");
+	pcibios_report_status(PCI_STATUS_SIG_SYSTEM_ERROR, 1);
+	printk("\n");
+
+	/* Deassert SERR */
+	__raw_writel(SH4_PCIINTM_SDIM, hose->reg_base + SH4_PCIINTM);
+
+	/* Back off the IRQ for awhile */
+	disable_irq_nosync(irq);
+	hose->serr_timer.expires = jiffies + HZ;
+	add_timer(&hose->serr_timer);
+
+	return IRQ_HANDLED;
+}
+
+static int __init sh7780_pci_setup_irqs(struct pci_channel *hose)
+{
+	int ret;
+
+	/* Clear out PCI arbiter IRQs */
+	__raw_writel(0, hose->reg_base + SH4_PCIAINT);
+
+	/* Clear all error conditions */
+	__raw_writew(PCI_STATUS_DETECTED_PARITY  | \
+		     PCI_STATUS_SIG_SYSTEM_ERROR | \
+		     PCI_STATUS_REC_MASTER_ABORT | \
+		     PCI_STATUS_REC_TARGET_ABORT | \
+		     PCI_STATUS_SIG_TARGET_ABORT | \
+		     PCI_STATUS_PARITY, hose->reg_base + PCI_STATUS);
+
+	ret = request_irq(hose->serr_irq, sh7780_pci_serr_irq, 0,
+			  "PCI SERR interrupt", hose);
+	if (unlikely(ret)) {
+		printk(KERN_ERR "PCI: Failed hooking SERR IRQ\n");
+		return ret;
+	}
+
+	/*
+	 * The PCI ERR IRQ needs to be IRQF_SHARED since all of the power
+	 * down IRQ vectors are routed through the ERR IRQ vector. We
+	 * only request_irq() once as there is only a single masking
+	 * source for multiple events.
+	 */
+	ret = request_irq(hose->err_irq, sh7780_pci_err_irq, IRQF_SHARED,
+			  "PCI ERR interrupt", hose);
+	if (unlikely(ret)) {
+		free_irq(hose->serr_irq, hose);
+		return ret;
+	}
+
+	/* Unmask all of the arbiter IRQs. */
+	__raw_writel(SH4_PCIAINT_MBKN | SH4_PCIAINT_TBTO | SH4_PCIAINT_MBTO | \
+		     SH4_PCIAINT_TABT | SH4_PCIAINT_MABT | SH4_PCIAINT_RDPE | \
+		     SH4_PCIAINT_WDPE, hose->reg_base + SH4_PCIAINTM);
+
+	/* Unmask all of the PCI IRQs */
+	__raw_writel(SH4_PCIINTM_TTADIM  | SH4_PCIINTM_TMTOIM  | \
+		     SH4_PCIINTM_MDEIM   | SH4_PCIINTM_APEDIM  | \
+		     SH4_PCIINTM_SDIM    | SH4_PCIINTM_DPEITWM | \
+		     SH4_PCIINTM_PEDITRM | SH4_PCIINTM_TADIMM  | \
+		     SH4_PCIINTM_MADIMM  | SH4_PCIINTM_MWPDIM  | \
+		     SH4_PCIINTM_MRDPEIM, hose->reg_base + SH4_PCIINTM);
+
+	return ret;
+}
+
+static inline void __init sh7780_pci_teardown_irqs(struct pci_channel *hose)
+{
+	free_irq(hose->err_irq, hose);
+	free_irq(hose->serr_irq, hose);
+}
+
+static void __init sh7780_pci66_init(struct pci_channel *hose)
+{
+	unsigned int tmp;
+
+	if (!pci_is_66mhz_capable(hose, 0, 0))
+		return;
+
+	/* Enable register access */
+	tmp = __raw_readl(hose->reg_base + SH4_PCICR);
+	tmp |= SH4_PCICR_PREFIX;
+	__raw_writel(tmp, hose->reg_base + SH4_PCICR);
+
+	/* Enable 66MHz operation */
+	tmp = __raw_readw(hose->reg_base + PCI_STATUS);
+	tmp |= PCI_STATUS_66MHZ;
+	__raw_writew(tmp, hose->reg_base + PCI_STATUS);
+
+	/* Done */
+	tmp = __raw_readl(hose->reg_base + SH4_PCICR);
+	tmp |= SH4_PCICR_PREFIX | SH4_PCICR_CFIN;
+	__raw_writel(tmp, hose->reg_base + SH4_PCICR);
+}
+
+static int __init sh7780_pci_init(void)
+{
+	struct pci_channel *chan = &sh7780_pci_controller;
+	phys_addr_t memphys;
+	size_t memsize;
+	unsigned int id;
+	const char *type;
+	int ret, i;
+
+	printk(KERN_NOTICE "PCI: Starting initialization.\n");
+
+	chan->reg_base = 0xfe040000;
+
+	/* Enable CPU access to the PCIC registers. */
+	__raw_writel(PCIECR_ENBL, PCIECR);
+
+	/* Reset */
+	__raw_writel(SH4_PCICR_PREFIX | SH4_PCICR_PRST | PCICR_ENDIANNESS,
+		     chan->reg_base + SH4_PCICR);
+
+	/*
+	 * Wait for it to come back up. The spec says to allow for up to
+	 * 1 second after toggling the reset pin, but in practice 100ms
+	 * is more than enough.
+	 */
+	mdelay(100);
+
+	id = __raw_readw(chan->reg_base + PCI_VENDOR_ID);
+	if (id != PCI_VENDOR_ID_RENESAS) {
+		printk(KERN_ERR "PCI: Unknown vendor ID 0x%04x.\n", id);
+		return -ENODEV;
+	}
+
+	id = __raw_readw(chan->reg_base + PCI_DEVICE_ID);
+	type = (id == PCI_DEVICE_ID_RENESAS_SH7763) ? "SH7763" :
+	       (id == PCI_DEVICE_ID_RENESAS_SH7780) ? "SH7780" :
+	       (id == PCI_DEVICE_ID_RENESAS_SH7781) ? "SH7781" :
+	       (id == PCI_DEVICE_ID_RENESAS_SH7785) ? "SH7785" :
+					  NULL;
+	if (unlikely(!type)) {
+		printk(KERN_ERR "PCI: Found an unsupported Renesas host "
+		       "controller, device id 0x%04x.\n", id);
+		return -EINVAL;
+	}
+
+	printk(KERN_NOTICE "PCI: Found a Renesas %s host "
+	       "controller, revision %d.\n", type,
+	       __raw_readb(chan->reg_base + PCI_REVISION_ID));
+
+	/*
+	 * Now throw it in to register initialization mode and
+	 * start the real work.
+	 */
+	__raw_writel(SH4_PCICR_PREFIX | PCICR_ENDIANNESS,
+		     chan->reg_base + SH4_PCICR);
+
+	memphys = __pa(memory_start);
+	memsize = roundup_pow_of_two(memory_end - memory_start);
+
+	/*
+	 * If there's more than 512MB of memory, we need to roll over to
+	 * LAR1/LSR1.
+	 */
+	if (memsize > SZ_512M) {
+		__raw_writel(memphys + SZ_512M, chan->reg_base + SH4_PCILAR1);
+		__raw_writel((((memsize - SZ_512M) - SZ_1M) & 0x1ff00000) | 1,
+			     chan->reg_base + SH4_PCILSR1);
+		memsize = SZ_512M;
+	} else {
+		/*
+		 * Otherwise just zero it out and disable it.
+		 */
+		__raw_writel(0, chan->reg_base + SH4_PCILAR1);
+		__raw_writel(0, chan->reg_base + SH4_PCILSR1);
+	}
+
+	/*
+	 * LAR0/LSR0 covers up to the first 512MB, which is enough to
+	 * cover all of lowmem on most platforms.
+	 */
+	__raw_writel(memphys, chan->reg_base + SH4_PCILAR0);
+	__raw_writel(((memsize - SZ_1M) & 0x1ff00000) | 1,
+		     chan->reg_base + SH4_PCILSR0);
+
+	/*
+	 * Hook up the ERR and SERR IRQs.
+	 */
+	ret = sh7780_pci_setup_irqs(chan);
+	if (unlikely(ret))
+		return ret;
+
+	/*
+	 * Disable the cache snoop controller for non-coherent DMA.
+	 */
+	__raw_writel(0, chan->reg_base + SH7780_PCICSCR0);
+	__raw_writel(0, chan->reg_base + SH7780_PCICSAR0);
+	__raw_writel(0, chan->reg_base + SH7780_PCICSCR1);
+	__raw_writel(0, chan->reg_base + SH7780_PCICSAR1);
+
+	/*
+	 * Setup the memory BARs
+	 */
+	for (i = 1; i < chan->nr_resources; i++) {
+		struct resource *res = chan->resources + i;
+		resource_size_t size;
+
+		if (unlikely(res->flags & IORESOURCE_IO))
+			continue;
+
+		/*
+		 * Make sure we're in the right physical addressing mode
+		 * for dealing with the resource.
+		 */
+		if ((res->flags & IORESOURCE_MEM_32BIT) && __in_29bit_mode()) {
+			chan->nr_resources--;
+			continue;
+		}
+
+		size = resource_size(res);
+
+		/*
+		 * The MBMR mask is calculated in units of 256kB, which
+		 * keeps things pretty simple.
+		 */
+		__raw_writel(((roundup_pow_of_two(size) / SZ_256K) - 1) << 18,
+			     chan->reg_base + SH7780_PCIMBMR(i - 1));
+		__raw_writel(res->start, chan->reg_base + SH7780_PCIMBR(i - 1));
+	}
+
+	/*
+	 * And I/O.
+	 */
+	__raw_writel(0, chan->reg_base + PCI_BASE_ADDRESS_0);
+	__raw_writel(0, chan->reg_base + SH7780_PCIIOBR);
+	__raw_writel(0, chan->reg_base + SH7780_PCIIOBMR);
+
+	__raw_writew(PCI_COMMAND_SERR   | PCI_COMMAND_WAIT   | \
+		     PCI_COMMAND_PARITY | PCI_COMMAND_MASTER | \
+		     PCI_COMMAND_MEMORY, chan->reg_base + PCI_COMMAND);
+
+	/*
+	 * Initialization mode complete, release the control register and
+	 * enable round robin mode to stop device overruns/starvation.
+	 */
+	__raw_writel(SH4_PCICR_PREFIX | SH4_PCICR_CFIN | SH4_PCICR_FTO |
+		     PCICR_ENDIANNESS,
+		     chan->reg_base + SH4_PCICR);
+
+	ret = register_pci_controller(chan);
+	if (unlikely(ret))
+		goto err;
+
+	sh7780_pci66_init(chan);
+
+	printk(KERN_NOTICE "PCI: Running at %dMHz.\n",
+	       (__raw_readw(chan->reg_base + PCI_STATUS) & PCI_STATUS_66MHZ) ?
+	       66 : 33);
+
+	return 0;
+
+err:
+	sh7780_pci_teardown_irqs(chan);
+	return ret;
+}
+arch_initcall(sh7780_pci_init);
diff --git a/arch/sh/drivers/pci/pci-sh7780.h b/arch/sh/drivers/pci/pci-sh7780.h
new file mode 100644
index 0000000..1742e2c
--- /dev/null
+++ b/arch/sh/drivers/pci/pci-sh7780.h
@@ -0,0 +1,46 @@
+/*
+ *	Low-Level PCI Support for SH7780 targets
+ *
+ *  Dustin McIntire (dustin@sensoria.com) (c) 2001
+ *  Paul Mundt (lethal@linux-sh.org) (c) 2003
+ *
+ *  May be copied or modified under the terms of the GNU General Public
+ *  License.  See linux/COPYING for more information.
+ *
+ */
+
+#ifndef _PCI_SH7780_H_
+#define _PCI_SH7780_H_
+
+/* SH7780 Control Registers */
+#define	PCIECR			0xFE000008
+#define PCIECR_ENBL		0x01
+
+/* SH7780 Specific Values */
+#define SH7780_PCI_CONFIG_BASE	0xFD000000	/* Config space base addr */
+#define SH7780_PCI_CONFIG_SIZE	0x01000000	/* Config space size */
+
+#define SH7780_PCIREG_BASE	0xFE040000	/* PCI regs base address */
+
+/* SH7780 PCI Config Registers */
+#define SH7780_PCIIR		0x114		/* PCI Interrupt Register */
+#define SH7780_PCIIMR		0x118		/* PCI Interrupt Mask Register */
+#define SH7780_PCIAIR		0x11C		/* Error Address Register */
+#define SH7780_PCICIR		0x120		/* Error Command/Data Register */
+#define SH7780_PCIAINT		0x130		/* Arbiter Interrupt Register */
+#define SH7780_PCIAINTM		0x134		/* Arbiter Int. Mask Register */
+#define SH7780_PCIBMIR		0x138		/* Error Bus Master Register */
+#define SH7780_PCIPAR		0x1C0		/* PIO Address Register */
+#define SH7780_PCIPINT		0x1CC		/* Power Mgmnt Int. Register */
+#define SH7780_PCIPINTM		0x1D0		/* Power Mgmnt Mask Register */
+
+#define SH7780_PCIMBR(x)	(0x1E0 + ((x) * 8))
+#define SH7780_PCIMBMR(x)	(0x1E4 + ((x) * 8))
+#define SH7780_PCIIOBR		0x1F8
+#define SH7780_PCIIOBMR		0x1FC
+#define SH7780_PCICSCR0		0x210		/* Cache Snoop1 Cnt. Register */
+#define SH7780_PCICSCR1		0x214		/* Cache Snoop2 Cnt. Register */
+#define SH7780_PCICSAR0		0x218	/* Cache Snoop1 Addr. Register */
+#define SH7780_PCICSAR1		0x21C	/* Cache Snoop2 Addr. Register */
+
+#endif /* _PCI_SH7780_H_ */
diff --git a/arch/sh/drivers/pci/pci.c b/arch/sh/drivers/pci/pci.c
new file mode 100644
index 0000000..8256626
--- /dev/null
+++ b/arch/sh/drivers/pci/pci.c
@@ -0,0 +1,303 @@
+/*
+ * New-style PCI core.
+ *
+ * Copyright (c) 2004 - 2009  Paul Mundt
+ * Copyright (c) 2002  M. R. Brown
+ *
+ * Modelled after arch/mips/pci/pci.c:
+ *  Copyright (C) 2003, 04 Ralf Baechle (ralf@linux-mips.org)
+ *
+ * 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/kernel.h>
+#include <linux/mm.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/dma-debug.h>
+#include <linux/io.h>
+#include <linux/mutex.h>
+#include <linux/spinlock.h>
+#include <linux/export.h>
+
+unsigned long PCIBIOS_MIN_IO = 0x0000;
+unsigned long PCIBIOS_MIN_MEM = 0;
+
+/*
+ * The PCI controller list.
+ */
+static struct pci_channel *hose_head, **hose_tail = &hose_head;
+
+static int pci_initialized;
+
+static void pcibios_scanbus(struct pci_channel *hose)
+{
+	static int next_busno;
+	static int need_domain_info;
+	LIST_HEAD(resources);
+	struct resource *res;
+	resource_size_t offset;
+	int i, ret;
+	struct pci_host_bridge *bridge;
+
+	bridge = pci_alloc_host_bridge(0);
+	if (!bridge)
+		return;
+
+	for (i = 0; i < hose->nr_resources; i++) {
+		res = hose->resources + i;
+		offset = 0;
+		if (res->flags & IORESOURCE_DISABLED)
+			continue;
+		if (res->flags & IORESOURCE_IO)
+			offset = hose->io_offset;
+		else if (res->flags & IORESOURCE_MEM)
+			offset = hose->mem_offset;
+		pci_add_resource_offset(&resources, res, offset);
+	}
+
+	list_splice_init(&resources, &bridge->windows);
+	bridge->dev.parent = NULL;
+	bridge->sysdata = hose;
+	bridge->busnr = next_busno;
+	bridge->ops = hose->pci_ops;
+	bridge->swizzle_irq = pci_common_swizzle;
+	bridge->map_irq = pcibios_map_platform_irq;
+
+	ret = pci_scan_root_bus_bridge(bridge);
+	if (ret) {
+		pci_free_host_bridge(bridge);
+		return;
+	}
+
+	hose->bus = bridge->bus;
+
+	need_domain_info = need_domain_info || hose->index;
+	hose->need_domain_info = need_domain_info;
+
+	next_busno = hose->bus->busn_res.end + 1;
+	/* Don't allow 8-bit bus number overflow inside the hose -
+	   reserve some space for bridges. */
+	if (next_busno > 224) {
+		next_busno = 0;
+		need_domain_info = 1;
+	}
+
+	pci_bus_size_bridges(hose->bus);
+	pci_bus_assign_resources(hose->bus);
+	pci_bus_add_devices(hose->bus);
+}
+
+/*
+ * This interrupt-safe spinlock protects all accesses to PCI
+ * configuration space.
+ */
+DEFINE_RAW_SPINLOCK(pci_config_lock);
+static DEFINE_MUTEX(pci_scan_mutex);
+
+int register_pci_controller(struct pci_channel *hose)
+{
+	int i;
+
+	for (i = 0; i < hose->nr_resources; i++) {
+		struct resource *res = hose->resources + i;
+
+		if (res->flags & IORESOURCE_DISABLED)
+			continue;
+
+		if (res->flags & IORESOURCE_IO) {
+			if (request_resource(&ioport_resource, res) < 0)
+				goto out;
+		} else {
+			if (request_resource(&iomem_resource, res) < 0)
+				goto out;
+		}
+	}
+
+	*hose_tail = hose;
+	hose_tail = &hose->next;
+
+	/*
+	 * Do not panic here but later - this might happen before console init.
+	 */
+	if (!hose->io_map_base) {
+		printk(KERN_WARNING
+		       "registering PCI controller with io_map_base unset\n");
+	}
+
+	/*
+	 * Setup the ERR/PERR and SERR timers, if available.
+	 */
+	pcibios_enable_timers(hose);
+
+	/*
+	 * Scan the bus if it is register after the PCI subsystem
+	 * initialization.
+	 */
+	if (pci_initialized) {
+		mutex_lock(&pci_scan_mutex);
+		pcibios_scanbus(hose);
+		mutex_unlock(&pci_scan_mutex);
+	}
+
+	return 0;
+
+out:
+	for (--i; i >= 0; i--)
+		release_resource(&hose->resources[i]);
+
+	printk(KERN_WARNING "Skipping PCI bus scan due to resource conflict\n");
+	return -1;
+}
+
+static int __init pcibios_init(void)
+{
+	struct pci_channel *hose;
+
+	/* Scan all of the recorded PCI controllers.  */
+	for (hose = hose_head; hose; hose = hose->next)
+		pcibios_scanbus(hose);
+
+	pci_initialized = 1;
+
+	return 0;
+}
+subsys_initcall(pcibios_init);
+
+/*
+ * We need to avoid collisions with `mirrored' VGA ports
+ * and other strange ISA hardware, so we always want the
+ * addresses to be allocated in the 0x000-0x0ff region
+ * modulo 0x400.
+ */
+resource_size_t pcibios_align_resource(void *data, const struct resource *res,
+				resource_size_t size, resource_size_t align)
+{
+	struct pci_dev *dev = data;
+	struct pci_channel *hose = dev->sysdata;
+	resource_size_t start = res->start;
+
+	if (res->flags & IORESOURCE_IO) {
+		if (start < PCIBIOS_MIN_IO + hose->resources[0].start)
+			start = PCIBIOS_MIN_IO + hose->resources[0].start;
+
+		/*
+                 * Put everything into 0x00-0xff region modulo 0x400.
+		 */
+		if (start & 0x300)
+			start = (start + 0x3ff) & ~0x3ff;
+	}
+
+	return start;
+}
+
+static void __init
+pcibios_bus_report_status_early(struct pci_channel *hose,
+				int top_bus, int current_bus,
+				unsigned int status_mask, int warn)
+{
+	unsigned int pci_devfn;
+	u16 status;
+	int ret;
+
+	for (pci_devfn = 0; pci_devfn < 0xff; pci_devfn++) {
+		if (PCI_FUNC(pci_devfn))
+			continue;
+		ret = early_read_config_word(hose, top_bus, current_bus,
+					     pci_devfn, PCI_STATUS, &status);
+		if (ret != PCIBIOS_SUCCESSFUL)
+			continue;
+		if (status == 0xffff)
+			continue;
+
+		early_write_config_word(hose, top_bus, current_bus,
+					pci_devfn, PCI_STATUS,
+					status & status_mask);
+		if (warn)
+			printk("(%02x:%02x: %04X) ", current_bus,
+			       pci_devfn, status);
+	}
+}
+
+/*
+ * We can't use pci_find_device() here since we are
+ * called from interrupt context.
+ */
+static void __ref
+pcibios_bus_report_status(struct pci_bus *bus, unsigned int status_mask,
+			  int warn)
+{
+	struct pci_dev *dev;
+
+	list_for_each_entry(dev, &bus->devices, bus_list) {
+		u16 status;
+
+		/*
+		 * ignore host bridge - we handle
+		 * that separately
+		 */
+		if (dev->bus->number == 0 && dev->devfn == 0)
+			continue;
+
+		pci_read_config_word(dev, PCI_STATUS, &status);
+		if (status == 0xffff)
+			continue;
+
+		if ((status & status_mask) == 0)
+			continue;
+
+		/* clear the status errors */
+		pci_write_config_word(dev, PCI_STATUS, status & status_mask);
+
+		if (warn)
+			printk("(%s: %04X) ", pci_name(dev), status);
+	}
+
+	list_for_each_entry(dev, &bus->devices, bus_list)
+		if (dev->subordinate)
+			pcibios_bus_report_status(dev->subordinate, status_mask, warn);
+}
+
+void __ref pcibios_report_status(unsigned int status_mask, int warn)
+{
+	struct pci_channel *hose;
+
+	for (hose = hose_head; hose; hose = hose->next) {
+		if (unlikely(!hose->bus))
+			pcibios_bus_report_status_early(hose, hose_head->index,
+					hose->index, status_mask, warn);
+		else
+			pcibios_bus_report_status(hose->bus, status_mask, warn);
+	}
+}
+
+#ifndef CONFIG_GENERIC_IOMAP
+
+void __iomem *__pci_ioport_map(struct pci_dev *dev,
+			       unsigned long port, unsigned int nr)
+{
+	struct pci_channel *chan = dev->sysdata;
+
+	if (unlikely(!chan->io_map_base)) {
+		chan->io_map_base = sh_io_port_base;
+
+		if (pci_domains_supported)
+			panic("To avoid data corruption io_map_base MUST be "
+			      "set with multiple PCI domains.");
+	}
+
+	return (void __iomem *)(chan->io_map_base + port);
+}
+
+void pci_iounmap(struct pci_dev *dev, void __iomem *addr)
+{
+	iounmap(addr);
+}
+EXPORT_SYMBOL(pci_iounmap);
+
+#endif /* CONFIG_GENERIC_IOMAP */
+
+EXPORT_SYMBOL(PCIBIOS_MIN_IO);
+EXPORT_SYMBOL(PCIBIOS_MIN_MEM);
diff --git a/arch/sh/drivers/pci/pcie-sh7786.c b/arch/sh/drivers/pci/pcie-sh7786.c
new file mode 100644
index 0000000..3d81a8b
--- /dev/null
+++ b/arch/sh/drivers/pci/pcie-sh7786.c
@@ -0,0 +1,611 @@
+/*
+ * Low-Level PCI Express Support for the SH7786
+ *
+ *  Copyright (C) 2009 - 2011  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.
+ */
+#define pr_fmt(fmt) "PCI: " fmt
+
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/io.h>
+#include <linux/async.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/clk.h>
+#include <linux/sh_clk.h>
+#include <linux/sh_intc.h>
+#include <cpu/sh7786.h>
+#include "pcie-sh7786.h"
+#include <asm/sizes.h>
+
+struct sh7786_pcie_port {
+	struct pci_channel	*hose;
+	struct clk		*fclk, phy_clk;
+	unsigned int		index;
+	int			endpoint;
+	int			link;
+};
+
+static struct sh7786_pcie_port *sh7786_pcie_ports;
+static unsigned int nr_ports;
+static unsigned long dma_pfn_offset;
+
+static struct sh7786_pcie_hwops {
+	int (*core_init)(void);
+	async_func_t port_init_hw;
+} *sh7786_pcie_hwops;
+
+static struct resource sh7786_pci0_resources[] = {
+	{
+		.name	= "PCIe0 MEM 0",
+		.start	= 0xfd000000,
+		.end	= 0xfd000000 + SZ_8M - 1,
+		.flags	= IORESOURCE_MEM,
+	}, {
+		.name	= "PCIe0 MEM 1",
+		.start	= 0xc0000000,
+		.end	= 0xc0000000 + SZ_512M - 1,
+		.flags	= IORESOURCE_MEM | IORESOURCE_MEM_32BIT,
+	}, {
+		.name	= "PCIe0 MEM 2",
+		.start	= 0x10000000,
+		.end	= 0x10000000 + SZ_64M - 1,
+		.flags	= IORESOURCE_MEM,
+	}, {
+		.name	= "PCIe0 IO",
+		.start	= 0xfe100000,
+		.end	= 0xfe100000 + SZ_1M - 1,
+		.flags	= IORESOURCE_IO,
+	},
+};
+
+static struct resource sh7786_pci1_resources[] = {
+	{
+		.name	= "PCIe1 MEM 0",
+		.start	= 0xfd800000,
+		.end	= 0xfd800000 + SZ_8M - 1,
+		.flags	= IORESOURCE_MEM,
+	}, {
+		.name	= "PCIe1 MEM 1",
+		.start	= 0xa0000000,
+		.end	= 0xa0000000 + SZ_512M - 1,
+		.flags	= IORESOURCE_MEM | IORESOURCE_MEM_32BIT,
+	}, {
+		.name	= "PCIe1 MEM 2",
+		.start	= 0x30000000,
+		.end	= 0x30000000 + SZ_256M - 1,
+		.flags	= IORESOURCE_MEM | IORESOURCE_MEM_32BIT,
+	}, {
+		.name	= "PCIe1 IO",
+		.start	= 0xfe300000,
+		.end	= 0xfe300000 + SZ_1M - 1,
+		.flags	= IORESOURCE_IO,
+	},
+};
+
+static struct resource sh7786_pci2_resources[] = {
+	{
+		.name	= "PCIe2 MEM 0",
+		.start	= 0xfc800000,
+		.end	= 0xfc800000 + SZ_4M - 1,
+		.flags	= IORESOURCE_MEM,
+	}, {
+		.name	= "PCIe2 MEM 1",
+		.start	= 0x80000000,
+		.end	= 0x80000000 + SZ_512M - 1,
+		.flags	= IORESOURCE_MEM | IORESOURCE_MEM_32BIT,
+	}, {
+		.name	= "PCIe2 MEM 2",
+		.start	= 0x20000000,
+		.end	= 0x20000000 + SZ_256M - 1,
+		.flags	= IORESOURCE_MEM | IORESOURCE_MEM_32BIT,
+	}, {
+		.name	= "PCIe2 IO",
+		.start	= 0xfcd00000,
+		.end	= 0xfcd00000 + SZ_1M - 1,
+		.flags	= IORESOURCE_IO,
+	},
+};
+
+extern struct pci_ops sh7786_pci_ops;
+
+#define DEFINE_CONTROLLER(start, idx)					\
+{									\
+	.pci_ops	= &sh7786_pci_ops,				\
+	.resources	= sh7786_pci##idx##_resources,			\
+	.nr_resources	= ARRAY_SIZE(sh7786_pci##idx##_resources),	\
+	.reg_base	= start,					\
+	.mem_offset	= 0,						\
+	.io_offset	= 0,						\
+}
+
+static struct pci_channel sh7786_pci_channels[] = {
+	DEFINE_CONTROLLER(0xfe000000, 0),
+	DEFINE_CONTROLLER(0xfe200000, 1),
+	DEFINE_CONTROLLER(0xfcc00000, 2),
+};
+
+static struct clk fixed_pciexclkp = {
+	.rate = 100000000,	/* 100 MHz reference clock */
+};
+
+static void sh7786_pci_fixup(struct pci_dev *dev)
+{
+	/*
+	 * Prevent enumeration of root complex resources.
+	 */
+	if (pci_is_root_bus(dev->bus) && dev->devfn == 0) {
+		int i;
+
+		for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
+			dev->resource[i].start	= 0;
+			dev->resource[i].end	= 0;
+			dev->resource[i].flags	= 0;
+		}
+	}
+}
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_RENESAS, PCI_DEVICE_ID_RENESAS_SH7786,
+			 sh7786_pci_fixup);
+
+static int __init phy_wait_for_ack(struct pci_channel *chan)
+{
+	unsigned int timeout = 100;
+
+	while (timeout--) {
+		if (pci_read_reg(chan, SH4A_PCIEPHYADRR) & (1 << BITS_ACK))
+			return 0;
+
+		udelay(100);
+	}
+
+	return -ETIMEDOUT;
+}
+
+static int __init pci_wait_for_irq(struct pci_channel *chan, unsigned int mask)
+{
+	unsigned int timeout = 100;
+
+	while (timeout--) {
+		if ((pci_read_reg(chan, SH4A_PCIEINTR) & mask) == mask)
+			return 0;
+
+		udelay(100);
+	}
+
+	return -ETIMEDOUT;
+}
+
+static void __init phy_write_reg(struct pci_channel *chan, unsigned int addr,
+				 unsigned int lane, unsigned int data)
+{
+	unsigned long phyaddr;
+
+	phyaddr = (1 << BITS_CMD) + ((lane & 0xf) << BITS_LANE) +
+			((addr & 0xff) << BITS_ADR);
+
+	/* Set write data */
+	pci_write_reg(chan, data, SH4A_PCIEPHYDOUTR);
+	pci_write_reg(chan, phyaddr, SH4A_PCIEPHYADRR);
+
+	phy_wait_for_ack(chan);
+
+	/* Clear command */
+	pci_write_reg(chan, 0, SH4A_PCIEPHYDOUTR);
+	pci_write_reg(chan, 0, SH4A_PCIEPHYADRR);
+
+	phy_wait_for_ack(chan);
+}
+
+static int __init pcie_clk_init(struct sh7786_pcie_port *port)
+{
+	struct pci_channel *chan = port->hose;
+	struct clk *clk;
+	char fclk_name[16];
+	int ret;
+
+	/*
+	 * First register the fixed clock
+	 */
+	ret = clk_register(&fixed_pciexclkp);
+	if (unlikely(ret != 0))
+		return ret;
+
+	/*
+	 * Grab the port's function clock, which the PHY clock depends
+	 * on. clock lookups don't help us much at this point, since no
+	 * dev_id is available this early. Lame.
+	 */
+	snprintf(fclk_name, sizeof(fclk_name), "pcie%d_fck", port->index);
+
+	port->fclk = clk_get(NULL, fclk_name);
+	if (IS_ERR(port->fclk)) {
+		ret = PTR_ERR(port->fclk);
+		goto err_fclk;
+	}
+
+	clk_enable(port->fclk);
+
+	/*
+	 * And now, set up the PHY clock
+	 */
+	clk = &port->phy_clk;
+
+	memset(clk, 0, sizeof(struct clk));
+
+	clk->parent = &fixed_pciexclkp;
+	clk->enable_reg = (void __iomem *)(chan->reg_base + SH4A_PCIEPHYCTLR);
+	clk->enable_bit = BITS_CKE;
+
+	ret = sh_clk_mstp_register(clk, 1);
+	if (unlikely(ret < 0))
+		goto err_phy;
+
+	return 0;
+
+err_phy:
+	clk_disable(port->fclk);
+	clk_put(port->fclk);
+err_fclk:
+	clk_unregister(&fixed_pciexclkp);
+
+	return ret;
+}
+
+static int __init phy_init(struct sh7786_pcie_port *port)
+{
+	struct pci_channel *chan = port->hose;
+	unsigned int timeout = 100;
+
+	clk_enable(&port->phy_clk);
+
+	/* Initialize the phy */
+	phy_write_reg(chan, 0x60, 0xf, 0x004b008b);
+	phy_write_reg(chan, 0x61, 0xf, 0x00007b41);
+	phy_write_reg(chan, 0x64, 0xf, 0x00ff4f00);
+	phy_write_reg(chan, 0x65, 0xf, 0x09070907);
+	phy_write_reg(chan, 0x66, 0xf, 0x00000010);
+	phy_write_reg(chan, 0x74, 0xf, 0x0007001c);
+	phy_write_reg(chan, 0x79, 0xf, 0x01fc000d);
+	phy_write_reg(chan, 0xb0, 0xf, 0x00000610);
+
+	/* Deassert Standby */
+	phy_write_reg(chan, 0x67, 0x1, 0x00000400);
+
+	/* Disable clock */
+	clk_disable(&port->phy_clk);
+
+	while (timeout--) {
+		if (pci_read_reg(chan, SH4A_PCIEPHYSR))
+			return 0;
+
+		udelay(100);
+	}
+
+	return -ETIMEDOUT;
+}
+
+static void __init pcie_reset(struct sh7786_pcie_port *port)
+{
+	struct pci_channel *chan = port->hose;
+
+	pci_write_reg(chan, 1, SH4A_PCIESRSTR);
+	pci_write_reg(chan, 0, SH4A_PCIETCTLR);
+	pci_write_reg(chan, 0, SH4A_PCIESRSTR);
+	pci_write_reg(chan, 0, SH4A_PCIETXVC0SR);
+}
+
+static int __init pcie_init(struct sh7786_pcie_port *port)
+{
+	struct pci_channel *chan = port->hose;
+	unsigned int data;
+	phys_addr_t memstart, memend;
+	size_t memsize;
+	int ret, i, win;
+
+	/* Begin initialization */
+	pcie_reset(port);
+
+	/*
+	 * Initial header for port config space is type 1, set the device
+	 * class to match. Hardware takes care of propagating the IDSETR
+	 * settings, so there is no need to bother with a quirk.
+	 */
+	pci_write_reg(chan, PCI_CLASS_BRIDGE_PCI << 16, SH4A_PCIEIDSETR1);
+
+	/* Initialize default capabilities. */
+	data = pci_read_reg(chan, SH4A_PCIEEXPCAP0);
+	data &= ~(PCI_EXP_FLAGS_TYPE << 16);
+
+	if (port->endpoint)
+		data |= PCI_EXP_TYPE_ENDPOINT << 20;
+	else
+		data |= PCI_EXP_TYPE_ROOT_PORT << 20;
+
+	data |= PCI_CAP_ID_EXP;
+	pci_write_reg(chan, data, SH4A_PCIEEXPCAP0);
+
+	/* Enable data link layer active state reporting */
+	pci_write_reg(chan, PCI_EXP_LNKCAP_DLLLARC, SH4A_PCIEEXPCAP3);
+
+	/* Enable extended sync and ASPM L0s support */
+	data = pci_read_reg(chan, SH4A_PCIEEXPCAP4);
+	data &= ~PCI_EXP_LNKCTL_ASPMC;
+	data |= PCI_EXP_LNKCTL_ES | 1;
+	pci_write_reg(chan, data, SH4A_PCIEEXPCAP4);
+
+	/* Write out the physical slot number */
+	data = pci_read_reg(chan, SH4A_PCIEEXPCAP5);
+	data &= ~PCI_EXP_SLTCAP_PSN;
+	data |= (port->index + 1) << 19;
+	pci_write_reg(chan, data, SH4A_PCIEEXPCAP5);
+
+	/* Set the completion timer timeout to the maximum 32ms. */
+	data = pci_read_reg(chan, SH4A_PCIETLCTLR);
+	data &= ~0x3f00;
+	data |= 0x32 << 8;
+	pci_write_reg(chan, data, SH4A_PCIETLCTLR);
+
+	/*
+	 * Set fast training sequences to the maximum 255,
+	 * and enable MAC data scrambling.
+	 */
+	data = pci_read_reg(chan, SH4A_PCIEMACCTLR);
+	data &= ~PCIEMACCTLR_SCR_DIS;
+	data |= (0xff << 16);
+	pci_write_reg(chan, data, SH4A_PCIEMACCTLR);
+
+	memstart = __pa(memory_start);
+	memend   = __pa(memory_end);
+	memsize = roundup_pow_of_two(memend - memstart);
+
+	/*
+	 * The start address must be aligned on its size. So we round
+	 * it down, and then recalculate the size so that it covers
+	 * the entire memory.
+	 */
+	memstart = ALIGN_DOWN(memstart, memsize);
+	memsize = roundup_pow_of_two(memend - memstart);
+
+	dma_pfn_offset = memstart >> PAGE_SHIFT;
+
+	/*
+	 * If there's more than 512MB of memory, we need to roll over to
+	 * LAR1/LAMR1.
+	 */
+	if (memsize > SZ_512M) {
+		pci_write_reg(chan, memstart + SZ_512M, SH4A_PCIELAR1);
+		pci_write_reg(chan, ((memsize - SZ_512M) - SZ_256) | 1,
+			      SH4A_PCIELAMR1);
+		memsize = SZ_512M;
+	} else {
+		/*
+		 * Otherwise just zero it out and disable it.
+		 */
+		pci_write_reg(chan, 0, SH4A_PCIELAR1);
+		pci_write_reg(chan, 0, SH4A_PCIELAMR1);
+	}
+
+	/*
+	 * LAR0/LAMR0 covers up to the first 512MB, which is enough to
+	 * cover all of lowmem on most platforms.
+	 */
+	pci_write_reg(chan, memstart, SH4A_PCIELAR0);
+	pci_write_reg(chan, (memsize - SZ_256) | 1, SH4A_PCIELAMR0);
+
+	/* Finish initialization */
+	data = pci_read_reg(chan, SH4A_PCIETCTLR);
+	data |= 0x1;
+	pci_write_reg(chan, data, SH4A_PCIETCTLR);
+
+	/* Let things settle down a bit.. */
+	mdelay(100);
+
+	/* Enable DL_Active Interrupt generation */
+	data = pci_read_reg(chan, SH4A_PCIEDLINTENR);
+	data |= PCIEDLINTENR_DLL_ACT_ENABLE;
+	pci_write_reg(chan, data, SH4A_PCIEDLINTENR);
+
+	/* Disable MAC data scrambling. */
+	data = pci_read_reg(chan, SH4A_PCIEMACCTLR);
+	data |= PCIEMACCTLR_SCR_DIS | (0xff << 16);
+	pci_write_reg(chan, data, SH4A_PCIEMACCTLR);
+
+	/*
+	 * This will timeout if we don't have a link, but we permit the
+	 * port to register anyways in order to support hotplug on future
+	 * hardware.
+	 */
+	ret = pci_wait_for_irq(chan, MASK_INT_TX_CTRL);
+
+	data = pci_read_reg(chan, SH4A_PCIEPCICONF1);
+	data &= ~(PCI_STATUS_DEVSEL_MASK << 16);
+	data |= PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER |
+		(PCI_STATUS_CAP_LIST | PCI_STATUS_DEVSEL_FAST) << 16;
+	pci_write_reg(chan, data, SH4A_PCIEPCICONF1);
+
+	pci_write_reg(chan, 0x80888000, SH4A_PCIETXVC0DCTLR);
+	pci_write_reg(chan, 0x00222000, SH4A_PCIERXVC0DCTLR);
+
+	wmb();
+
+	if (ret == 0) {
+		data = pci_read_reg(chan, SH4A_PCIEMACSR);
+		printk(KERN_NOTICE "PCI: PCIe#%d x%d link detected\n",
+		       port->index, (data >> 20) & 0x3f);
+	} else
+		printk(KERN_NOTICE "PCI: PCIe#%d link down\n",
+		       port->index);
+
+	for (i = win = 0; i < chan->nr_resources; i++) {
+		struct resource *res = chan->resources + i;
+		resource_size_t size;
+		u32 mask;
+
+		/*
+		 * We can't use the 32-bit mode windows in legacy 29-bit
+		 * mode, so just skip them entirely.
+		 */
+		if ((res->flags & IORESOURCE_MEM_32BIT) && __in_29bit_mode())
+			res->flags |= IORESOURCE_DISABLED;
+
+		if (res->flags & IORESOURCE_DISABLED)
+			continue;
+
+		pci_write_reg(chan, 0x00000000, SH4A_PCIEPTCTLR(win));
+
+		/*
+		 * The PAMR mask is calculated in units of 256kB, which
+		 * keeps things pretty simple.
+		 */
+		size = resource_size(res);
+		mask = (roundup_pow_of_two(size) / SZ_256K) - 1;
+		pci_write_reg(chan, mask << 18, SH4A_PCIEPAMR(win));
+
+		pci_write_reg(chan, upper_32_bits(res->start),
+			      SH4A_PCIEPARH(win));
+		pci_write_reg(chan, lower_32_bits(res->start),
+			      SH4A_PCIEPARL(win));
+
+		mask = MASK_PARE;
+		if (res->flags & IORESOURCE_IO)
+			mask |= MASK_SPC;
+
+		pci_write_reg(chan, mask, SH4A_PCIEPTCTLR(win));
+
+		win++;
+	}
+
+	return 0;
+}
+
+int pcibios_map_platform_irq(const struct pci_dev *pdev, u8 slot, u8 pin)
+{
+        return evt2irq(0xae0);
+}
+
+void pcibios_bus_add_device(struct pci_dev *pdev)
+{
+	pdev->dev.dma_pfn_offset = dma_pfn_offset;
+}
+
+static int __init sh7786_pcie_core_init(void)
+{
+	/* Return the number of ports */
+	return test_mode_pin(MODE_PIN12) ? 3 : 2;
+}
+
+static void __init sh7786_pcie_init_hw(void *data, async_cookie_t cookie)
+{
+	struct sh7786_pcie_port *port = data;
+	int ret;
+
+	/*
+	 * Check if we are configured in endpoint or root complex mode,
+	 * this is a fixed pin setting that applies to all PCIe ports.
+	 */
+	port->endpoint = test_mode_pin(MODE_PIN11);
+
+	/*
+	 * Setup clocks, needed both for PHY and PCIe registers.
+	 */
+	ret = pcie_clk_init(port);
+	if (unlikely(ret < 0)) {
+		pr_err("clock initialization failed for port#%d\n",
+		       port->index);
+		return;
+	}
+
+	ret = phy_init(port);
+	if (unlikely(ret < 0)) {
+		pr_err("phy initialization failed for port#%d\n",
+		       port->index);
+		return;
+	}
+
+	ret = pcie_init(port);
+	if (unlikely(ret < 0)) {
+		pr_err("core initialization failed for port#%d\n",
+			       port->index);
+		return;
+	}
+
+	/* In the interest of preserving device ordering, synchronize */
+	async_synchronize_cookie(cookie);
+
+	register_pci_controller(port->hose);
+}
+
+static struct sh7786_pcie_hwops sh7786_65nm_pcie_hwops __initdata = {
+	.core_init	= sh7786_pcie_core_init,
+	.port_init_hw	= sh7786_pcie_init_hw,
+};
+
+static int __init sh7786_pcie_init(void)
+{
+	struct clk *platclk;
+	u32 mm_sel;
+	int i;
+
+	printk(KERN_NOTICE "PCI: Starting initialization.\n");
+
+	sh7786_pcie_hwops = &sh7786_65nm_pcie_hwops;
+
+	nr_ports = sh7786_pcie_hwops->core_init();
+	BUG_ON(nr_ports > ARRAY_SIZE(sh7786_pci_channels));
+
+	if (unlikely(nr_ports == 0))
+		return -ENODEV;
+
+	sh7786_pcie_ports = kcalloc(nr_ports, sizeof(struct sh7786_pcie_port),
+				    GFP_KERNEL);
+	if (unlikely(!sh7786_pcie_ports))
+		return -ENOMEM;
+
+	/*
+	 * Fetch any optional platform clock associated with this block.
+	 *
+	 * This is a rather nasty hack for boards with spec-mocking FPGAs
+	 * that have a secondary set of clocks outside of the on-chip
+	 * ones that need to be accounted for before there is any chance
+	 * of touching the existing MSTP bits or CPG clocks.
+	 */
+	platclk = clk_get(NULL, "pcie_plat_clk");
+	if (IS_ERR(platclk)) {
+		/* Sane hardware should probably get a WARN_ON.. */
+		platclk = NULL;
+	}
+
+	clk_enable(platclk);
+
+	mm_sel = sh7786_mm_sel();
+
+	/*
+	 * Depending on the MMSELR register value, the PCIe0 MEM 1
+	 * area may not be available. See Table 13.11 of the SH7786
+	 * datasheet.
+	 */
+	if (mm_sel != 1 && mm_sel != 2 && mm_sel != 5 && mm_sel != 6)
+		sh7786_pci0_resources[2].flags |= IORESOURCE_DISABLED;
+
+	printk(KERN_NOTICE "PCI: probing %d ports.\n", nr_ports);
+
+	for (i = 0; i < nr_ports; i++) {
+		struct sh7786_pcie_port *port = sh7786_pcie_ports + i;
+
+		port->index		= i;
+		port->hose		= sh7786_pci_channels + i;
+		port->hose->io_map_base	= port->hose->resources[0].start;
+
+		async_schedule(sh7786_pcie_hwops->port_init_hw, port);
+	}
+
+	async_synchronize_full();
+
+	return 0;
+}
+arch_initcall(sh7786_pcie_init);
diff --git a/arch/sh/drivers/pci/pcie-sh7786.h b/arch/sh/drivers/pci/pcie-sh7786.h
new file mode 100644
index 0000000..4a6ff55
--- /dev/null
+++ b/arch/sh/drivers/pci/pcie-sh7786.h
@@ -0,0 +1,580 @@
+/*
+ * SH7786 PCI-Express controller definitions.
+ *
+ * Copyright (C) 2008, 2009 Renesas Technology Corp.
+ * All rights reserved.
+ *
+ * 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.
+ */
+#ifndef __PCI_SH7786_H
+#define __PCI_SH7786_H
+
+/* PCIe bus-0(x4) on SH7786 */			// Rev1.171
+#define SH4A_PCIE_SPW_BASE	0xFE000000	/* spw config address for controller 0 */
+#define SH4A_PCIE_SPW_BASE1	0xFE200000	/* spw config address for controller 1 (Rev1.14)*/
+#define SH4A_PCIE_SPW_BASE2	0xFCC00000	/* spw config address for controller 2 (Rev1.171)*/
+#define SH4A_PCIE_SPW_BASE_LEN	0x00080000
+
+#define SH4A_PCI_CNFG_BASE	0xFE040000	/* pci config address for controller 0 */
+#define SH4A_PCI_CNFG_BASE1	0xFE240000	/* pci config address for controller 1 (Rev1.14)*/
+#define SH4A_PCI_CNFG_BASE2	0xFCC40000	/* pci config address for controller 2 (Rev1.171)*/
+#define SH4A_PCI_CNFG_BASE_LEN	0x00040000
+
+#define SH4A_PCIPIO_ADDR_OFFSET	0x000001c0	/* offset to pci config_address */
+#define SH4A_PCIPIO_DATA_OFFSET	0x00000220	/* offset to pci config_data */
+
+/*
+ * for PEX8111(Max Payload Size=128B,PCIIO_SIZE=64K),
+ * for other(Max Payload Size=4096B,PCIIO_SIZE=8M)
+ */
+
+/* PCI0: PCI memory target transfer 32-bit address translation value(Rev1.11T)*/
+#define SH4A_PCIBMSTR_TRANSLATION	0x20000000
+
+/*	SPVCR0		*/
+#define	SH4A_PCIEVCR0		(0x000000)	/* R - 0x0000 0000 32 */
+#define		BITS_TOP_MB	(24)
+#define		MASK_TOP_MB	(0xff<<BITS_TOP_MB)
+#define		BITS_BOT_MB	(16)
+#define		MASK_BOT_MB	(0xff<<BITS_BOT_MB)
+#define		BITS_VC_ID	(0)
+#define		MASK_VC_ID	(0xffff<<BITS_VC_ID)
+
+/*	SPVCR1		*/
+#define	SH4A_PCIEVCR1		(0x000004)	/* R - 0x0000 0000 32*/
+#define		BITS_BADOPC	(5)		/* 5 BADOPC 0 R/W */
+#define		MASK_BADOPC	(1<<BITS_BADOPC)
+#define		BITS_BADDEST	(4)		/*4 BADDEST 0 R/W  */
+#define		MASK_BADDEST	(1<<BITS_BADDEST)
+#define		BITS_UNSOLRESP	(3)		/* 3 UNSOLRESP 0 R/W  */
+#define		MASK_UNSOLRESP	(1<<BITS_UNSOLRESP)
+#define		BITS_ERRSNT	(1)		/* 1 ERRSNT 0 */
+#define		MASK_ERRSNT	(1<<BITS_ERRSNT)
+#define		BITS_ERRRCV	(0)		/* 0 ERRRCV 0 */
+#define		MASK_ERRRCV	(1<<BITS_ERRRCV)
+
+/*	PCIEENBLR	 */
+#define	SH4A_PCIEENBLR		(0x000008)	/* R/W - 0x0000 0001 32 */
+
+/*	PCIEECR		*/
+#define	SH4A_PCIEECR		(0x00000C)	/* R/W - 0x0000 0000 32 */
+#define		BITS_ENBL	(0)	/* 0 ENBL 0 R/W */
+#define		MASK_ENBL	(1<<BITS_ENBL)
+
+/*	PCIEPAR		*/
+#define	SH4A_PCIEPAR		(0x000010)	/* R/W - 0x0000 0000 32 */
+#define		BITS_BN		(24)
+#define		MASK_BN		(0xff<<BITS_BN)
+#define		BITS_DN		(19)
+#define		MASK_DN		(0x1f<<BITS_DN)
+#define		BITS_FN		(16)
+#define		MASK_FN		(0x7<<BITS_FN)
+#define		BITS_EREGNO	(8)
+#define		MASK_EREGNO	(0xff<<BITS_EREGNO)
+#define		BITS_REGNO	(2)
+#define		MASK_REGNO	(0x3f<<BITS_REGNO)
+
+/*	PCIEPCTLR	*/
+#define	SH4A_PCIEPCTLR		(0x000018)	/* R/W - 0x0000 0000 32 */
+#define		BITS_CCIE	(31)	/*  31 CCIE */
+#define		MASK_CCIE	(1<<BITS_CCIE)
+#define		BITS_TYPE	(8)
+#define		MASK_TYPE	(1<<BITS_TYPE)
+#define		BITS_C_VC	(0)
+#define		MASK_C_VC	(1<<BITS_C_VC)
+
+/*	PCIEPDR		*/
+#define	SH4A_PCIEPDR		(0x000020)	/* R/W - 0x0000 0000 32 */
+#define		BITS_PDR	(0)
+#define		MASK_PDR	(0xffffffff<<BITS_PDR)
+
+/*	PCIEMSGALR	*/
+#define	SH4A_PCIEMSGALR		(0x000030)	/* R/W - 0x0000 0000 32 */
+#define		BITS_MSGADRL	(0)
+#define		MASK_MSGADRL	(0xffffffff<<BITS_MSGADRL)
+
+/*	PCIEMSGAHR	*/
+#define	SH4A_PCIEMSGAHR		(0x000034)	/* R/W - 0x0000 0000 32 */
+#define		BITS_MSGADRH	(0)
+#define		MASK_MSGADRH	(0xffffffff<<BITS_MSGADRH)
+
+/*	PCIEMSGCTLR	*/
+#define	SH4A_PCIEMSGCTLR	(0x000038)	/* R/W - 0x0000 0000 32 */
+#define		BITS_MSGIE	(31)
+#define		MASK_MSGIE	(1<<BITS_MSGIE)
+#define		BITS_MROUTE	(16)
+#define		MASK_MROUTE	(0x7<<BITS_MROUTE)
+#define		BITS_MCODE	(8)
+#define		MASK_MCODE	(0xff<<BITS_MCODE)
+#define		BITS_M_VC	(0)
+#define		MASK_M_VC	(1<<BITS_M_VC)
+
+/*	PCIEMSG		*/
+#define	SH4A_PCIEMSG		(0x000040)	/* W - - 32	*/
+#define		BITS_MDATA	(0)
+#define		MASK_MDATA	(0xffffffff<<BITS_MDATA)
+
+/*	PCIEUNLOCKCR	*/
+#define	SH4A_PCIEUNLOCKCR	(0x000048)	/* R/W - 0x0000 0000 32 */
+
+/*	PCIEIDR		*/
+#define	SH4A_PCIEIDR		(0x000060)	/* R/W - 0x0101 1101 32 */
+
+/*	PCIEDBGCTLR	*/
+#define	SH4A_PCIEDBGCTLR	(0x000100)	/* R/W - 0x0000 0000 32 */
+
+/*	PCIEINTXR	*/
+#define	SH4A_PCIEINTXR		(0x004000)	/* R/W - 0x0000 0000 32 */
+
+/*	PCIERMSGR	*/
+#define	SH4A_PCIERMSGR		(0x004010)	/* R/W - 0x0000 0000 32 */
+
+/*	PCIERSTR	*/
+#define SH4A_PCIERSTR(x)	(0x008000 + ((x) * 0x4)) /* R/W - 0x0000 0000 32 */
+
+/*	PCIESRSTR	 */
+#define SH4A_PCIESRSTR		(0x008040)	/* R/W - 0x0000 0000 32 */
+
+/*	PCIEPHYCTLR	*/
+#define	SH4A_PCIEPHYCTLR	(0x010000)	/* R/W - 0x0000 0000 32 */
+#define		BITS_CKE	(0)
+#define		MASK_CKE	(1<<BITS_CKE)
+
+/*	PCIERMSGIER	*/
+#define	SH4A_PCIERMSGIER	(0x004040)	/* R/W - 0x0000 0000 32 */
+
+/*	PCIEPHYADRR	*/
+#define	SH4A_PCIEPHYADRR	(0x010004)	/* R/W - 0x0000 0000 32 */
+#define		BITS_ACK	(24)			// Rev1.171
+#define		MASK_ACK	(1<<BITS_ACK)		// Rev1.171
+#define		BITS_CMD	(16)			// Rev1.171
+#define		MASK_CMD	(0x03<<BITS_CMD)	// Rev1.171
+#define		BITS_LANE	(8)
+#define		MASK_LANE	(0x0f<<BITS_LANE)
+#define		BITS_ADR	(0)
+#define		MASK_ADR	(0xff<<BITS_ADR)
+
+/*	PCIEPHYDINR	*/							// Rev1.171 start.
+#define	SH4A_PCIEPHYDINR	(0x010008)	/* R/W - 0x0000 0000 32 */
+
+/*	PCIEPHYDOUTR	*/
+#define	SH4A_PCIEPHYDOUTR	(0x01000C)	/* R/W - 0x0000 0000 32 */
+
+/*	PCIEPHYSR	*/
+#define	SH4A_PCIEPHYSR		(0x010010)	/* R/W - 0x0000 0000 32 */	// Rev1.171 end.
+
+/*	PCIEPHYDATAR	*/
+#define	SH4A_PCIEPHYDATAR	(0x00008)	/* R/W - 0xxxxx xxxx 32 */
+#define		BITS_DATA	(0)
+#define		MASK_DATA	(0xffffffff<<BITS_DATA)
+
+/*	PCIETCTLR	*/
+#define	SH4A_PCIETCTLR		(0x020000)	/* R/W R/W 0x0000 0000 32 */
+#define		BITS_CFINT	(0)
+#define		MASK_CFINT	(1<<BITS_CFINT)
+
+/*	PCIETSTR	*/
+#define	SH4A_PCIETSTR		(0x020004)	/* R 0x0000 0000 32  */
+
+/*	PCIEINTR	*/
+#define	SH4A_PCIEINTR		(0x020008)	/* R/W R/W 0x0000 0000 32  */
+#define		BITS_INT_RX_ERP			(31)
+#define		MASK_INT_RX_ERP			(1<<BITS_INT_RX_ERP)
+#define		BITS_INT_RX_VCX_Posted		(30)
+#define		MASK_INT_RX_VCX_Posted		(1<<BITS_INT_RX_VCX_Posted)
+#define		BITS_INT_RX_VCX_NonPosted	(29)
+#define		MASK_INT_RX_VCX_NonPosted	(1<<BITS_INT_RX_VCX_NonPosted)
+#define		BITS_INT_RX_VCX_CPL		(28)
+#define		MASK_INT_RX_VCX_CPL		(1<<BITS_INT_RX_VCX_CPL)
+#define		BITS_INT_TX_VCX_Posted		(26)
+#define		MASK_INT_TX_VCX_Posted		(1<<BITS_INT_TX_VCX_Posted)
+#define		BITS_INT_TX_VCX_NonPosted	(25)
+#define		MASK_INT_TX_VCX_NonPosted	(1<<BITS_INT_TX_VCX_NonPosted)
+#define		BITS_INT_TX_VCX_CPL		(24)
+#define		MASK_INT_TX_VCX_CPL		(1<<BITS_INT_TX_VCX_CPL)
+#define		BITS_INT_RX_VC0_Posted		(22)
+#define		MASK_INT_RX_VC0_Posted		(1<<BITS_INT_RX_VC0_Posted)
+#define		BITS_INT_RX_VC0_NonPosted	(21)
+#define		MASK_INT_RX_VC0_NonPosted	(1<<BITS_INT_RX_VC0_NonPosted)
+#define		BITS_INT_RX_VC0_CPL		(20)
+#define		MASK_INT_RX_VC0_CPL		(1<<BITS_INT_RX_VC0_CPL)
+#define		BITS_INT_TX_VC0_Posted		(18)
+#define		MASK_INT_TX_VC0_Posted		(1<<BITS_INT_TX_VC0_Posted)
+#define		BITS_INT_TX_VC0_NonPosted	(17)
+#define		MASK_INT_TX_VC0_NonPosted	(1<<BITS_INT_TX_VC0_NonPosted)
+#define		BITS_INT_TX_VC0_CPL		(16)
+#define		MASK_INT_TX_VC0_CPL		(1<<BITS_INT_TX_VC0_CPL)
+#define		BITS_INT_RX_CTRL		(15)
+#define		MASK_INT_RX_CTRL		(1<<BITS_INT_RX_CTRL)
+#define		BITS_INT_TX_CTRL		(14)
+#define		MASK_INT_TX_CTRL		(1<<BITS_INT_TX_CTRL)
+#define		BITS_INTTL			(11)
+#define		MASK_INTTL			(1<<BITS_INTTL)
+#define		BITS_INTDL			(10)
+#define		MASK_INTDL			(1<<BITS_INTDL)
+#define		BITS_INTMAC			(9)
+#define		MASK_INTMAC			(1<<BITS_INTMAC)
+#define		BITS_INTPM			(8)
+#define		MASK_INTPM			(1<<BITS_INTPM)
+
+/*	PCIEINTER	*/
+#define	SH4A_PCIEINTER		(0x02000C)	/* R/W R/W 0x0000 0000 32 */
+#define		BITS_INT_RX_ERP			(31)
+#define		MASK_INT_RX_ERP			(1<<BITS_INT_RX_ERP)
+#define		BITS_INT_RX_VCX_Posted		(30)
+#define		MASK_INT_RX_VCX_Posted		(1<<BITS_INT_RX_VCX_Posted)
+#define		BITS_INT_RX_VCX_NonPosted	(29)
+#define		MASK_INT_RX_VCX_NonPosted	(1<<BITS_INT_RX_VCX_NonPosted)
+#define		BITS_INT_RX_VCX_CPL		(28)
+#define		MASK_INT_RX_VCX_CPL		(1<<BITS_INT_RX_VCX_CPL)
+#define		BITS_INT_TX_VCX_Posted		(26)
+#define		MASK_INT_TX_VCX_Posted		(1<<BITS_INT_TX_VCX_Posted)
+#define		BITS_INT_TX_VCX_NonPosted	(25)
+#define		MASK_INT_TX_VCX_NonPosted	(1<<BITS_INT_TX_VCX_NonPosted)
+#define		BITS_INT_TX_VCX_CPL		(24)
+#define		MASK_INT_TX_VCX_CPL		(1<<BITS_INT_TX_VCX_CPL)
+#define		BITS_INT_RX_VC0_Posted		(22)
+#define		MASK_INT_RX_VC0_Posted		(1<<BITS_INT_RX_VC0_Posted)
+#define		BITS_INT_RX_VC0_NonPosted	(21)
+#define		MASK_INT_RX_VC0_NonPosted	(1<<BITS_INT_RX_VC0_NonPosted)
+#define		BITS_INT_RX_VC0_CPL		(20)
+#define		MASK_INT_RX_VC0_CPL		(1<<BITS_INT_RX_VC0_CPL)
+#define		BITS_INT_TX_VC0_Posted		(18)
+#define		MASK_INT_TX_VC0_Posted		(1<<BITS_INT_TX_VC0_Posted)
+#define		BITS_INT_TX_VC0_NonPosted	(17)
+#define		MASK_INT_TX_VC0_NonPosted	(1<<BITS_INT_TX_VC0_NonPosted)
+#define		BITS_INT_TX_VC0_CPL		(16)
+#define		MASK_INT_TX_VC0_CPL		(1<<BITS_INT_TX_VC0_CPL)
+#define		BITS_INT_RX_CTRL		(15)
+#define		MASK_INT_RX_CTRL		(1<<BITS_INT_RX_CTRL)
+#define		BITS_INT_TX_CTRL		(14)
+#define		MASK_INT_TX_CTRL		(1<<BITS_INT_TX_CTRL)
+#define		BITS_INTTL			(11)
+#define		MASK_INTTL			(1<<BITS_INTTL)
+#define		BITS_INTDL			(10)
+#define		MASK_INTDL			(1<<BITS_INTDL)
+#define		BITS_INTMAC			(9)
+#define		MASK_INTMAC			(1<<BITS_INTMAC)
+#define		BITS_INTPM			(8)
+#define		MASK_INTPM			(1<<BITS_INTPM)
+
+/*	PCIEEH0R	*/
+#define SH4A_PCIEEHR(x)		(0x020010 + ((x) * 0x4)) /* R - 0x0000 0000 32 */
+
+/*	PCIEAIR	 */
+#define	SH4A_PCIEAIR		(SH4A_PCIE_BASE + 0x020010)	/* R/W R/W 0xxxxx xxxx 32 */
+
+/*	 PCIECIR	 */
+#define	SH4A_PCIECIR		(SH4A_PCIE_BASE)	/* R/W R/W 0xxxxx xxxx 32 */
+
+/*	 PCIEERRFR	 */								// Rev1.18
+#define	SH4A_PCIEERRFR		(0x020020)		/* R/W R/W 0xxxxx xxxx 32 */	// Rev1.18
+
+/*	PCIEERRFER	*/
+#define SH4A_PCIEERRFER		(0x020024)		/* R/W R/W 0x0000 0000 32 */
+
+/*	PCIEERRFR2	*/
+#define SH4A_PCIEERRFR2		(0x020028)		/* R/W R/W 0x0000 0000 32 */
+
+/*	PCIEMSIR	*/
+#define SH4A_PCIEMSIR		(0x020040)		/* R/W - 0x0000 0000 32 */
+
+/*	PCIEMSIFR	*/
+#define SH4A_PCIEMSIFR		(0x020044)		/* R/W R/W 0x0000 0000 32 */
+
+/*	PCIEPWRCTLR	*/
+#define SH4A_PCIEPWRCTLR	(0x020100)		/* R/W - 0x0000 0000 32 */
+
+/*	PCIEPCCTLR	*/
+#define SH4A_PCIEPCCTLR		(0x020180)		/* R/W - 0x0000 0000 32 */
+
+											// Rev1.18
+/*	PCIELAR0	*/
+#define	SH4A_PCIELAR0		(0x020200)	/* R/W R/W 0x0000 0000 32 */
+#define		BITS_LARn	(20)
+#define		MASK_LARn	(0xfff<<BITS_LARn)
+
+#define	SH4A_PCIE_020204	(0x020204)	/* R/W R/W 0x0000 0000 32 */
+
+/*	PCIELAMR0	*/
+#define	SH4A_PCIELAMR0		(0x020208)	/* R/W R/W 0x0000 0000 32 */
+#define		BITS_LAMRn	(20)
+#define		MASK_LAMRn	(0x1ff<<BITS_LAMRn)
+#define		BITS_LAREn	(0)
+#define		MASK_LAREn	(0x1<<BITS_LAREn)
+
+/*	PCIECSCR0	*/
+#define	SH4A_PCIECSCR0		(0x020210)	/* R/W R/W 0x0000 0000 32 */
+#define		BITS_RANGE	(2)
+#define		MASK_RANGE	(0x7<<BITS_RANGE)
+#define		BITS_SNPMD	(0)
+#define		MASK_SNPMD	(0x3<<BITS_SNPMD)
+
+/*	PCIECSAR0	*/
+#define	SH4A_PCIECSAR0		(0x020214)	/* R/W R/W 0x0000 0000 32 */
+#define		BITS_CSADR	(0)
+#define		MASK_CSADR	(0xffffffff<<BITS_CSADR)
+
+/*	PCIESTCTLR0	*/
+#define	SH4A_PCIESTCTLR0	(0x020218)	/* R/W R/W 0x0000 0000 32 */
+#define		BITS_SHPRI	(8)
+#define		MASK_SHPRI	(0x0f<<BITS_SHPRI)
+
+#define	SH4A_PCIE_020224	(0x020224)	/* R/W R/W 0x0000 0000 32 */
+
+#define	SH4A_PCIELAR1		(0x020220)	/* R/W R/W 0x0000 0000 32 */
+#define	SH4A_PCIELAMR1		(0x020228)	/* R/W R/W 0x0000 0000 32 */
+#define	SH4A_PCIECSCR1		(0x020230)	/* R/W R/W 0x0000 0000 32 */
+#define	SH4A_PCIECSAR1		(0x020234)	/* R/W R/W 0x0000 0000 32 */
+#define	SH4A_PCIESTCTLR1	(0x020238)	/* R/W R/W 0x0000 0000 32 */
+
+#define	SH4A_PCIELAR2		(0x020240)	/* R/W R/W 0x0000 0000 32 */
+#define	SH4A_PCIE_020244	(0x020244)	/* R/W R/W 0x0000 0000 32 */
+#define	SH4A_PCIELAMR2		(0x020248)	/* R/W R/W 0x0000 0000 32 */
+#define	SH4A_PCIECSCR2		(0x020250)	/* R/W R/W 0x0000 0000 32 */
+#define	SH4A_PCIECSAR2		(0x020254)	/* R/W R/W 0x0000 0000 32 */
+#define	SH4A_PCIESTCTLR2	(0x020258)	/* R/W R/W 0x0000 0000 32 */
+
+#define	SH4A_PCIELAR3		(0x020260)	/* R/W R/W 0x0000 0000 32 */
+#define	SH4A_PCIE_020264	(0x020264)	/* R/W R/W 0x0000 0000 32 */
+#define	SH4A_PCIELAMR3		(0x020268)	/* R/W R/W 0x0000 0000 32 */
+#define	SH4A_PCIECSCR3		(0x020270)	/* R/W R/W 0x0000 0000 32 */
+#define	SH4A_PCIECSAR3		(0x020274)	/* R/W R/W 0x0000 0000 32 */
+#define	SH4A_PCIESTCTLR3	(0x020278)	/* R/W R/W 0x0000 0000 32 */
+
+#define	SH4A_PCIELAR4		(0x020280)	/* R/W R/W 0x0000 0000 32 */
+#define	SH4A_PCIE_020284	(0x020284)	/* R/W R/W 0x0000 0000 32 */
+#define	SH4A_PCIELAMR4		(0x020288)	/* R/W R/W 0x0000 0000 32 */
+#define	SH4A_PCIECSCR4		(0x020290)	/* R/W R/W 0x0000 0000 32 */
+#define	SH4A_PCIECSAR4		(0x020294)	/* R/W R/W 0x0000 0000 32 */
+#define	SH4A_PCIESTCTLR4	(0x020298)	/* R/W R/W 0x0000 0000 32 */
+
+#define	SH4A_PCIELAR5		(0x0202A0)	/* R/W R/W 0x0000 0000 32 */
+#define	SH4A_PCIE_0202A4	(0x0202A4)	/* R/W R/W 0x0000 0000 32 */
+#define	SH4A_PCIELAMR5		(0x0202A8)	/* R/W R/W 0x0000 0000 32 */
+#define	SH4A_PCIECSCR5		(0x0202B0)	/* R/W R/W 0x0000 0000 32 */
+#define	SH4A_PCIECSAR5		(0x0202B4)	/* R/W R/W 0x0000 0000 32 */
+#define	SH4A_PCIESTCTLR5	(0x0202B8)	/* R/W R/W 0x0000 0000 32 */
+
+/*	PCIEPARL	*/
+#define	SH4A_PCIEPARL(x)	(0x020400 + ((x) * 0x20)) /* R/W R/W 0x0000 0000 32 */
+#define		BITS_PAL	(18)
+#define		MASK_PAL	(0x3fff<<BITS_PAL)
+
+/*	PCIEPARH	*/
+#define	SH4A_PCIEPARH(x)	(0x020404 + ((x) * 0x20)) /* R/W R/W 0x0000 0000 32 */
+#define		BITS_PAH	(0)
+#define		MASK_PAH	(0xffffffff<<BITS_PAH)
+
+/*	PCIEPAMR	 */
+#define	SH4A_PCIEPAMR(x)	(0x020408 + ((x) * 0x20)) /* R/W R/W 0x0000 0000 32 */
+#define		BITS_PAM	(18)
+#define		MASK_PAM	(0x3fff<<BITS_PAM)
+
+/*	PCIEPTCTLR	*/
+#define SH4A_PCIEPTCTLR(x)	(0x02040C + ((x) * 0x20))
+#define		BITS_PARE	(31)
+#define		MASK_PARE	(0x1<<BITS_PARE)
+#define		BITS_TC		(20)
+#define		MASK_TC		(0x7<<BITS_TC)
+#define		BITS_T_VC	(16)
+#define		MASK_T_VC	(0x1<<BITS_T_VC)
+#define		BITS_LOCK	(12)
+#define		MASK_LOCK	(0x1<<BITS_LOCK)
+#define		BITS_SPC	(8)
+#define		MASK_SPC	(0x1<<BITS_SPC)
+
+#define	SH4A_PCIEDMAOR		(0x021000)	/* R/W R/W 0x0000 0000 32 */
+#define	SH4A_PCIEDMSAR0		(0x021100)	/* R/W R/W 0x0000 0000 32 */
+#define	SH4A_PCIEDMSAHR0	(0x021104)	/* R/W R/W 0x0000 0000 32 */
+#define	SH4A_PCIEDMDAR0		(0x021108)	/* R/W R/W 0x0000 0000 32 */
+#define	SH4A_PCIEDMDAHR0	(0x02110C)	/* R/W R/W 0x0000 0000 32 */
+#define	SH4A_PCIEDMBCNTR0	(0x021110)	/* R/W R/W 0x0000 0000 32 */
+#define	SH4A_PCIEDMSBCNTR0	(0x021114)	/* R/W R/W 0x0000 0000 32 */
+#define	SH4A_PCIEDMSTRR0	(0x021118)	/* R/W R/W 0x0000 0000 32 */
+#define	SH4A_PCIEDMCCAR0	(0x02111C)	/* R/W R/W 0x0000 0000 32 */
+#define	SH4A_PCIEDMCCR0		(0x021120)	/* R/W R/W 0x0000 0000 32 */
+#define	SH4A_PCIEDMCC2R0	(0x021124)	/* R/W R/W 0x0000 0000 - */
+#define	SH4A_PCIEDMCCCR0	(0x021128)	/* R/W R/W 0x0000 0000 32 */
+#define SH4A_PCIEDMCHSR0	(0x02112C)	/* R/W - 0x0000 0000 32 */
+#define	SH4A_PCIEDMSAR1		(0x021140)	/* R/W R/W 0x0000 0000 32 */
+#define	SH4A_PCIEDMSAHR1	(0x021144)	/* R/W R/W 0x0000 0000 32 */
+#define	SH4A_PCIEDMDAR1		(0x021148)	/* R/W R/W 0x0000 0000 32 */
+#define	SH4A_PCIEDMDAHR1	(0x02114C)	/* R/W R/W 0x0000 0000 32 */
+#define	SH4A_PCIEDMBCNTR1	(0x021150)	/* R/W R/W 0x0000 0000 32 */
+#define	SH4A_PCIEDMSBCNTR1	(0x021154)	/* R/W R/W 0x0000 0000 32 */
+#define	SH4A_PCIEDMSTRR1	(0x021158)	/* R/W R/W 0x0000 0000 32 */
+#define	SH4A_PCIEDMCCAR1	(0x02115C)	/* R/W R/W 0x0000 0000 32 */
+#define	SH4A_PCIEDMCCR1		(0x021160)	/* R/W R/W 0x0000 0000 32 */
+#define	SH4A_PCIEDMCC2R1	(0x021164)	/* R/W R/W 0x0000 0000 - */
+#define	SH4A_PCIEDMCCCR1	(0x021168)	/* R/W R/W 0x0000 0000 32 */
+#define SH4A_PCIEDMCHSR1	(0x02116C)	/* R/W - 0x0000 0000 32 */
+#define	SH4A_PCIEDMSAR2		(0x021180)	/* R/W R/W 0x0000 0000 32 */
+#define	SH4A_PCIEDMSAHR2	(0x021184)	/* R/W R/W 0x0000 0000 32 */
+#define	SH4A_PCIEDMDAR2		(0x021188)	/* R/W R/W 0x0000 0000 32 */
+#define	SH4A_PCIEDMDAHR2	(0x02118C)	/* R/W R/W 0x0000 0000 32 */
+#define	SH4A_PCIEDMBCNTR2	(0x021190)	/* R/W R/W 0x0000 0000 32 */
+#define	SH4A_PCIEDMSBCNTR2	(0x021194)	/* R/W R/W 0x0000 0000 32 */
+#define	SH4A_PCIEDMSTRR2	(0x021198)	/* R/W R/W 0x0000 0000 32 */
+#define	SH4A_PCIEDMCCAR2	(0x02119C)	/* R/W R/W 0x0000 0000 32 */
+#define	SH4A_PCIEDMCCR2		(0x0211A0)	/* R/W R/W 0x0000 0000 32 */
+#define	SH4A_PCIEDMCC2R2	(0x0211A4)	/* R/W R/W 0x0000 0000 -  */
+#define	SH4A_PCIEDMCCCR2	(0x0211A8)	/* R/W R/W 0x0000 0000 32 */
+#define	SH4A_PCIEDMSAR3		(0x0211C0)	/* R/W R/W 0x0000 0000 32 */
+#define	SH4A_PCIEDMSAHR3	(0x0211C4)	/* R/W R/W 0x0000 0000 32 */
+#define	SH4A_PCIEDMDAR3		(0x0211C8)	/* R/W R/W 0x0000 0000 32 */
+#define	SH4A_PCIEDMDAHR3	(0x0211CC)	/* R/W R/W 0x0000 0000 32 */
+#define	SH4A_PCIEDMBCNTR3	(0x0211D0)	/* R/W R/W 0x0000 0000 32 */
+#define	SH4A_PCIEDMSBCNTR3	(0x0211D4)	/* R/W R/W 0x0000 0000 32 */
+#define	SH4A_PCIEDMSTRR3	(0x0211D8)	/* R/W R/W 0x0000 0000 32 */
+#define	SH4A_PCIEDMCCAR3	(0x0211DC)	/* R/W R/W 0x0000 0000 32 */
+#define	SH4A_PCIEDMCCR3		(0x0211E0)	/* R/W R/W 0x0000 0000 32 */
+#define	SH4A_PCIEDMCC2R3	(0x0211E4)	/* R/W R/W 0x0000 0000 -  */
+#define	SH4A_PCIEDMCCCR3	(0x0211E8)	/* R/W R/W 0x0000 0000 32 */
+#define SH4A_PCIEDMCHSR3	(0x0211EC)	/* R/W R/W 0x0000 0000 32 */
+#define	SH4A_PCIEPCICONF0	(0x040000)	/* R R - 8/16/32 */
+#define	SH4A_PCIEPCICONF1	(0x040004)	/* R/W R/W 0x0008 0000 8/16/32 */
+#define	SH4A_PCIEPCICONF2	(0x040008)	/* R/W R/W 0xFF00 0000 8/16/32 */
+#define	SH4A_PCIEPCICONF3	(0x04000C)	/* R/W R/W 0x0000 0000 8/16/32 */
+#define	SH4A_PCIEPCICONF4	(0x040010)	/* - R/W - 8/16/32 */
+#define	SH4A_PCIEPCICONF5	(0x040014)	/* - R/W - 8/16/32 */
+#define	SH4A_PCIEPCICONF6	(0x040018)	/* - R/W - 8/16/32 */
+#define	SH4A_PCIEPCICONF7	(0x04001C)	/* - R/W - 8/16/32 */
+#define	SH4A_PCIEPCICONF8	(0x040020)	/* - R/W - 8/16/32 */
+#define	SH4A_PCIEPCICONF9	(0x040024)	/* - R/W - 8/16/32 */
+#define	SH4A_PCIEPCICONF10	(0x040028)	/* R/W R/W 0x0000 0000 8/16/32 */
+#define	SH4A_PCIEPCICONF11	(0x04002C)	/* R/W R/W 0x0000 0000 8/16/32 */
+#define	SH4A_PCIEPCICONF12	(0x040030)	/* R/W R/W 0x0000 0000 8/16/32 */
+#define	SH4A_PCIEPCICONF13	(0x040034)	/* R/W R/W 0x0000 0040 8/16/32 */
+#define	SH4A_PCIEPCICONF14	(0x040038)	/* R/W R/W 0x0000 0000 8/16/32 */
+#define	SH4A_PCIEPCICONF15	(0x04003C)	/* R/W R/W 0x0000 00FF 8/16/32 */
+#define	SH4A_PCIEPMCAP0		(0x040040)	/* R/W R 0x0003 5001 8/16/32 */
+#define	SH4A_PCIEPMCAP1		(0x040044)	/* R/W R/W 0x0000 0000 8/16/32 */
+#define	SH4A_PCIEMSICAP0	(0x040050)	/* R/W R/W 0x0180 7005 8/16/32 */
+#define	SH4A_PCIEMSICAP1	(0x040054)	/* R/W R/W 0x0000 0000 8/16/32 */
+#define	SH4A_PCIEMSICAP2	(0x040058)	/* R/W R/W 0x0000 0000 8/16/32 */
+#define	SH4A_PCIEMSICAP3	(0x04005C)	/* R/W R/W 0x0000 0000 8/16/32 */
+#define	SH4A_PCIEMSICAP4	(0x040060)	/* R/W R/W 0x0000 0000 8/16/32 */
+#define	SH4A_PCIEMSICAP5	(0x040064)	/* R/W R/W 0x0000 0000 8/16/32 */
+#define	SH4A_PCIEEXPCAP0	(0x040070)	/* R/W R/W 0x0001 0010 8/16/32 */
+#define	SH4A_PCIEEXPCAP1	(0x040074)	/* R/W R 0x0000 0005 8/16/32 */
+#define	SH4A_PCIEEXPCAP2	(0x040078)	/* R/W R/W 0x0000 0801 8/16/32 */
+#define	SH4A_PCIEEXPCAP3	(0x04007C)	/* R/W R 0x0003 F421 8/16/32 */
+#define	SH4A_PCIEEXPCAP4	(0x040080)	/* R/W R/W 0x0041 0000 8/16/32 */
+#define	SH4A_PCIEEXPCAP5	(0x040084)	/* R/W R/W 0x0000 0000 8/16/32 */
+#define	SH4A_PCIEEXPCAP6	(0x040088)	/* R/W R/W 0x0000 03C0 8/16/32 */
+#define	SH4A_PCIEEXPCAP7	(0x04008C)	/* R/W R/W 0x0000 0000 8/16/32 */
+#define	SH4A_PCIEEXPCAP8	(0x040090)	/* R/W R/W 0x0000 0000 8/16/32 */
+#define	SH4A_PCIEVCCAP0		(0x040100)	/* R/W R 0x1B01 0002 8/16/32 */
+#define	SH4A_PCIEVCCAP1		(0x040104)	/* R R 0x0000 0001 8/16/32 */
+#define	SH4A_PCIEVCCAP2		(0x040108)	/* R R 0x0000 0000 8/16/32 */
+#define	SH4A_PCIEVCCAP3		(0x04010C)	/* R R/W 0x0000 0000 8/16/32 */
+#define	SH4A_PCIEVCCAP4		(0x040110)	/* R/W R/W 0x0000 0000 8/16/32 */
+#define	SH4A_PCIEVCCAP5		(0x040114)	/* R/W R/W 0x8000 00FF 8/16/32 */
+#define	SH4A_PCIEVCCAP6		(0x040118)	/* R/W R 0x0002 0000 8/16/32 */
+#define	SH4A_PCIEVCCAP7		(0x04011C)	/* R/W R/W 0x0000 0000 8/16/32 */
+#define	SH4A_PCIEVCCAP8		(0x040120)	/* R/W R/W 0x0000 0000 8/16/32 */
+#define	SH4A_PCIEVCCAP9		(0x040124)	/* R/W R 0x0002 0000 8/16/32 */
+#define	SH4A_PCIENUMCAP0	(0x0001B0)	/* RW R 0x0001 0003 8/16/32 */
+#define	SH4A_PCIENUMCAP1	(0x0001B4)	/* R R 0x0000 0000 8/16/32 */
+#define	SH4A_PCIENUMCAP2	(0x0001B8)	/* R R 0x0000 0000 8/16/32 */
+#define	SH4A_PCIEIDSETR0	(0x041000)	/* R/W R 0x0000 FFFF 16/32 */
+#define	SH4A_PCIEIDSETR1	(0x041004)	/* R/W R 0xFF00 0000 16/32 */
+#define	SH4A_PCIEBAR0SETR	(0x041008)	/* R/W R 0x0000 0000 16/32 */
+#define	SH4A_PCIEBAR1SETR	(0x04100C)	/* R/W R 0x0000 0000 16/32 */
+#define	SH4A_PCIEBAR2SETR	(0x041010)	/* R/W R 0x0000 0000 16/32 */
+#define	SH4A_PCIEBAR3SETR	(0x041014)	/* R/W R 0x0000 0000 16/32 */
+#define	SH4A_PCIEBAR4SETR	(0x041018)	/* R/W R 0x0000 0000 16/32 */
+#define	SH4A_PCIEBAR5SETR	(0x04101C)	/* R/W R 0x0000 0000 16/32 */
+#define	SH4A_PCIECISSETR	(0x041020)	/* R/W R 0x0000 0000 16/32 */
+#define	SH4A_PCIEIDSETR2	(0x041024)	/* R/W R 0x0000 0000 16/32 */
+#define	SH4A_PCIEEROMSETR	(0x041028)	/* R/W R 0x0000 0000 16/32 */
+#define	SH4A_PCIEDSERSETR0	(0x04102C)	/* R/W R 0x0000 0000 16/32 */
+#define	SH4A_PCIEDSERSETR1	(0x041030)	/* R/W R 0x0000 0000 16/32 */
+#define	SH4A_PCIECTLR		(0x041040)	/* R/W R 0x0000 0000 16/32 */
+#define	SH4A_PCIETLSR		(0x041044)	/* R/W1C R 0x0000 0000 16/32 */
+#define	SH4A_PCIETLCTLR		(0x041048)	/* R/W R 0x0000 0000 16/32 */
+#define	SH4A_PCIEDLSR		(0x04104C)	/* R/W1C R 0x4003 0000 16/32 */
+#define	SH4A_PCIEDLCTLR		(0x041050)	/* R R 0x0000 0000 16/32 */
+#define	SH4A_PCIEMACSR		(0x041054)	/* R/W1C R 0x0041 0000 16/32 */
+#define	SH4A_PCIEMACCTLR	(0x041058)	/* R/W R 0x0000 0000 16/32 */
+#define		PCIEMACCTLR_SCR_DIS	(1 << 27)	/* scramble disable */
+#define	SH4A_PCIEPMSTR		(0x04105C)	/* R/W1C R 0x0000 0000 16/32 */
+#define	SH4A_PCIEPMCTLR		(0x041060)	/* R/W R 0x0000 0000 16/32 */
+#define	SH4A_PCIETLINTENR	(0x041064)	/* R/W R 0x0000 0000 16/32 */
+#define	SH4A_PCIEDLINTENR	(0x041068)	/* R/W R 0x0000 0000 16/32 */
+#define		PCIEDLINTENR_DLL_ACT_ENABLE	(1 << 31) /* DL active irq */
+#define	SH4A_PCIEMACINTENR	(0x04106C)	/* R/W R 0x0000 0000 16/32 */
+#define	SH4A_PCIEPMINTENR	(0x041070)	/* R/W R 0x0000 0000 16/32 */
+#define	SH4A_PCIETXDCTLR	(0x044000)	/* R/W - H'00000000_00000000 32/64 */
+#define	SH4A_PCIETXCTLR		(0x044020)	/* R/W - H'00000000_00000000 32/64 */
+#define	SH4A_PCIETXSR		(0x044028)	/* R - H'00000000_00000000 32/64 */
+#define	SH4A_PCIETXVC0DCTLR	(0x044100)	/* R/W - H'00000000_00000000 32/64 */
+#define	SH4A_PCIETXVC0SR	(0x044108)	/* R/W - H'00888000_00000000 32/64 */
+#define	SH4A_PCIEVC0PDTXR	(0x044110)	/* W - H'00000000_00000000 32/64 */
+#define	SH4A_PCIEVC0PHTXR	(0x044118)	/* W - H'00000000_00000000 32/64 */
+#define	SH4A_PCIEVC0NPDTXR	(0x044120)	/* W - H'00000000_00000000 32/64 */
+#define	SH4A_PCIEVC0NPHTXR	(0x044128)	/* W - H'00000000_00000000 32/64 */
+#define	SH4A_PCIEVC0CDTXR	(0x044130)	/* W - H'00000000_00000000 32/64 */
+#define	SH4A_PCIEVC0CHTXR	(0x044138)	/* W - H'00000000_00000000 32/64 */
+#define	SH4A_PCIETXVCXDCTLR	(0x044200)	/* R/W - H'00000000_00000000 32/64 */
+#define	SH4A_PCIETXVCXSR	(0x044208)	/* R/W - H'00000000_00000000 32/64 */
+#define	SH4A_PCIEVCXPDTXR	(0x044210)	/* W - H'00000000_00000000 32/64 */
+#define	SH4A_PCIEVCXPHTXR	(0x044218)	/* W - H'00000000_00000000 32/64 */
+#define	SH4A_PCIEVCXNPDTXR	(0x044220)	/* W - H'00000000_00000000 32/64 */
+#define	SH4A_PCIEVCXNPHTXR	(0x044228)	/* W - H'00000000_00000000 32/64 */
+#define	SH4A_PCIEVCXCDTXR	(0x044230)	/* W - H'00000000_00000000 32/64 */
+#define	SH4A_PCIEVCXCHTXR	(0x044238)	/* W - H'00000000_00000000 32/64 */
+#define	SH4A_PCIERDCTLR		(0x046000)	/* RW - H'00000000_00000000 32/64 */
+#define	SH4A_PCIEERPCTLR	(0x046008)	/* RW - H'00000000_00000000 32/64 */
+#define	SH4A_PCIEERPHR		(0x046010)	/* R - H'00000000_00000000 32/64 */
+#define	SH4A_PCIEERPERR		(0x046018)	/* R - H'00000000_00000000 32/64 */
+#define	SH4A_PCIERXVC0DCTLR	(0x046100)	/* RW - H'00000000_00000000 32/64 */
+#define	SH4A_PCIERXVC0SR	(0x046108)	/* RW - H'00000000_00000000 32/64 */
+#define	SH4A_PCIEVC0PDRXR	(0x046140)	/* R - H'00000000_00000000 32/64 */
+#define	SH4A_PCIEVC0PHRXR	(0x046148)	/* R - H'00000000_00000000 32/64 */
+#define	SH4A_PCIEVC0PERR	(0x046150)	/* R - H'00000000_00000000 32/64 */
+#define	SH4A_PCIEVC0NPDRXR	(0x046158)	/* R - H'00000000_00000000 32/64 */
+#define	SH4A_PCIEVC0NPHRXR	(0x046160)	/* R - H'00000000_00000000 32/64 */
+#define	SH4A_PCIEVC0NPERR	(0x046168)	/* R - H'00000000_00000000 32/64 */
+#define	SH4A_PCIEVC0CDRXR	(0x046170)	/* R - H'00000000_00000000 32/64 */
+#define	SH4A_PCIEVC0CHRXR	(0x046178)	/* R - H'00000000_00000000 32/64 */
+#define	SH4A_PCIEVC0CERR	(0x046180)	/* R - H'00000000_00000000 32/64 */
+#define	SH4A_PCIERXVCXDCTLR	(0x046200)	/* RW - H'00000000_00000000 32/64 */
+#define	SH4A_PCIERXVCXSR	(0x046208)	/* RW - H'00000000_00000000 32/64 */
+#define	SH4A_PCIEVCXPDRXR	(0x046240)	/* R - H'00000000_00000000 32/64 */
+#define	SH4A_PCIEVCXPHRXR	(0x046248)	/* R H'00000000_00000000 32/64 */
+#define	SH4A_PCIEVCXPERR	(0x046250)	/* R H'00000000_00000000 32/64 */
+#define	SH4A_PCIEVCXNPDRXR	(0x046258)	/* R H'00000000_00000000 32/64 */
+#define	SH4A_PCIEVCXNPHRXR	(0x046260)	/* R H'00000000_00000000 32/64 */
+#define	SH4A_PCIEVCXNPERR	(0x046268)	/* R H'00000000_00000000 32/64 */
+#define	SH4A_PCIEVCXCDRXR	(0x046270)	/* R H'00000000_00000000 32/64 */
+#define	SH4A_PCIEVCXCHRXR	(0x046278)	/* R H'00000000_00000000 32/64 */
+#define	SH4A_PCIEVCXCERR	(0x046280)	/* R H'00000000_00000000 32/64 */
+
+/* SSI Register Definition for MSI WORK AROUND --hamada */
+#define SH4A_PCI_SSI_BASE	0xFFE00000	/* spw config address	*/
+#define SH4A_PCI_SSI_BASE_LEN	0x00100000	/* 1MB			*/
+
+#define	SH4A_SSICR0		(0x000000)
+#define	SH4A_SSICR1		(0x010000)
+#define	SH4A_SSICR2		(0x020000)
+#define	SH4A_SSICR3		(0x030000)
+
+#define PCI_REG(x)		((x) + 0x40000)
+
+static inline void
+pci_write_reg(struct pci_channel *chan, unsigned long val, unsigned long reg)
+{
+	__raw_writel(val, chan->reg_base + reg);
+}
+
+static inline unsigned long
+pci_read_reg(struct pci_channel *chan, unsigned long reg)
+{
+	return __raw_readl(chan->reg_base + reg);
+}
+
+#endif /* __PCI_SH7786_H */