aboutsummaryrefslogtreecommitdiff
path: root/arch/sh/drivers
diff options
context:
space:
mode:
authorPaul Mundt <lethal@linux-sh.org>2006-09-27 16:43:28 +0900
committerPaul Mundt <lethal@linux-sh.org>2006-09-27 16:43:28 +0900
commit959f85f8a3223c116bbe95dd8a9b207790b5d4d3 (patch)
treee7da9ccf292f860bfa0ff9cc8b2682cd1d6bad4d /arch/sh/drivers
parente108b2ca2349f510ce7d7f910eda89f71d710d84 (diff)
sh: Consolidated SH7751/SH7780 PCI support.
This cleans up quite a lot of the PCI mess that we currently have, and attempts to consolidate the duplication in the SH7780 and SH7751 PCI controllers. Signed-off-by: Paul Mundt <lethal@linux-sh.org>
Diffstat (limited to 'arch/sh/drivers')
-rw-r--r--arch/sh/drivers/pci/Makefile5
-rw-r--r--arch/sh/drivers/pci/fixups-dreamcast.c38
-rw-r--r--arch/sh/drivers/pci/fixups-r7780rp.c38
-rw-r--r--arch/sh/drivers/pci/fixups-rts7751r2d.c24
-rw-r--r--arch/sh/drivers/pci/fixups-sh03.c38
-rw-r--r--arch/sh/drivers/pci/ops-bigsur.c18
-rw-r--r--arch/sh/drivers/pci/ops-landisk.c68
-rw-r--r--arch/sh/drivers/pci/ops-r7780rp.c18
-rw-r--r--arch/sh/drivers/pci/ops-rts7751r2d.c13
-rw-r--r--arch/sh/drivers/pci/ops-sh4.c164
-rw-r--r--arch/sh/drivers/pci/ops-snapgear.c21
-rw-r--r--arch/sh/drivers/pci/ops-titan.c16
-rw-r--r--arch/sh/drivers/pci/pci-auto.c10
-rw-r--r--arch/sh/drivers/pci/pci-sh4.h180
-rw-r--r--arch/sh/drivers/pci/pci-sh7751.c322
-rw-r--r--arch/sh/drivers/pci/pci-sh7751.h174
-rw-r--r--arch/sh/drivers/pci/pci-sh7780.c270
-rw-r--r--arch/sh/drivers/pci/pci-sh7780.h94
-rw-r--r--arch/sh/drivers/pci/pci-st40.c19
-rw-r--r--arch/sh/drivers/pci/pci.c40
20 files changed, 638 insertions, 932 deletions
diff --git a/arch/sh/drivers/pci/Makefile b/arch/sh/drivers/pci/Makefile
index 3d8078f1c05..9e00cb8a39e 100644
--- a/arch/sh/drivers/pci/Makefile
+++ b/arch/sh/drivers/pci/Makefile
@@ -6,8 +6,8 @@ obj-y += pci.o
obj-$(CONFIG_PCI_AUTO) += pci-auto.o
obj-$(CONFIG_CPU_SUBTYPE_ST40STB1) += pci-st40.o
-obj-$(CONFIG_CPU_SUBTYPE_SH7751) += pci-sh7751.o
-obj-$(CONFIG_CPU_SUBTYPE_SH7780) += pci-sh7780.o
+obj-$(CONFIG_CPU_SUBTYPE_SH7751) += pci-sh7751.o ops-sh4.o
+obj-$(CONFIG_CPU_SUBTYPE_SH7780) += pci-sh7780.o ops-sh4.o
obj-$(CONFIG_SH_DREAMCAST) += ops-dreamcast.o fixups-dreamcast.o \
dma-dreamcast.o
@@ -17,3 +17,4 @@ obj-$(CONFIG_SH_RTS7751R2D) += ops-rts7751r2d.o fixups-rts7751r2d.o
obj-$(CONFIG_SH_SH03) += ops-sh03.o fixups-sh03.o
obj-$(CONFIG_SH_R7780RP) += ops-r7780rp.o fixups-r7780rp.o
obj-$(CONFIG_SH_TITAN) += ops-titan.o
+obj-$(CONFIG_SH_LANDISK) += ops-landisk.o
diff --git a/arch/sh/drivers/pci/fixups-dreamcast.c b/arch/sh/drivers/pci/fixups-dreamcast.c
index 63b1c6f4b8d..c0af5f7ef41 100644
--- a/arch/sh/drivers/pci/fixups-dreamcast.c
+++ b/arch/sh/drivers/pci/fixups-dreamcast.c
@@ -4,7 +4,7 @@
* PCI fixups for the Sega Dreamcast
*
* Copyright (C) 2001, 2002 M. R. Brown
- * Copyright (C) 2002, 2003 Paul Mundt
+ * 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
@@ -45,36 +45,16 @@ static void __init gapspci_fixup_resources(struct pci_dev *dev)
printk("PCI: Failed resource fixup\n");
}
}
-
DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, gapspci_fixup_resources);
-void __init pcibios_fixup_bus(struct pci_bus *bus)
+int __init pcibios_map_platform_irq(struct pci_dev *dev, u8 slot, u8 pin)
{
- /*
- * We don't have any sub bus to fix up, and this is a rather
- * stupid place to put general device fixups. Don't do it.
- * Use the pcibios_fixups table or suffer the consequences.
+ /*
+ * 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;
}
-
-void __init pcibios_fixup_irqs(void)
-{
- struct pci_dev *dev = 0;
-
- for_each_pci_dev(dev) {
- /*
- * 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?
- */
- printk(KERN_NOTICE "PCI: Fixing up IRQ routing for device %s\n",
- pci_name(dev));
-
- dev->irq = GAPSPCI_IRQ;
-
- pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq);
- }
-}
-
diff --git a/arch/sh/drivers/pci/fixups-r7780rp.c b/arch/sh/drivers/pci/fixups-r7780rp.c
index b656b562ec9..3e321df65d2 100644
--- a/arch/sh/drivers/pci/fixups-r7780rp.c
+++ b/arch/sh/drivers/pci/fixups-r7780rp.c
@@ -4,36 +4,42 @@
* Highlander R7780RP-1 PCI fixups
*
* Copyright (C) 2003 Lineo uSolutions, Inc.
- * Copyright (C) 2004 Paul Mundt
+ * 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 "pci-sh7780.h"
+#include <linux/pci.h>
+#include "pci-sh4.h"
#include <asm/io.h>
int pci_fixup_pcic(void)
{
- outl(0x000043ff, PCI_REG(SH7780_PCIIMR));
- outl(0x0000380f, PCI_REG(SH7780_PCIAINTM));
+ pci_write_reg(0x000043ff, SH4_PCIINTM);
+ pci_write_reg(0x0000380f, SH4_PCIAINTM);
- outl(0xfbb00047, PCI_REG(SH7780_PCICMD));
- outl(0x00000000, PCI_REG(SH7780_PCIIBAR));
+ pci_write_reg(0xfbb00047, SH7780_PCICMD);
+ pci_write_reg(0x00000000, SH7780_PCIIBAR);
- outl(0x00011912, PCI_REG(SH7780_PCISVID));
- outl(0x08000000, PCI_REG(SH7780_PCICSCR0));
- outl(0x0000001b, PCI_REG(SH7780_PCICSAR0));
- outl(0xfd000000, PCI_REG(SH7780_PCICSCR1));
- outl(0x0000000f, PCI_REG(SH7780_PCICSAR1));
+ pci_write_reg(0x00011912, SH7780_PCISVID);
+ pci_write_reg(0x08000000, SH7780_PCICSCR0);
+ pci_write_reg(0x0000001b, SH7780_PCICSAR0);
+ pci_write_reg(0xfd000000, SH7780_PCICSCR1);
+ pci_write_reg(0x0000000f, SH7780_PCICSAR1);
- outl(0xfd000000, PCI_REG(SH7780_PCIMBR0));
- outl(0x00fc0000, PCI_REG(SH7780_PCIMBMR0));
+ pci_write_reg(0xfd000000, SH7780_PCIMBR0);
+ pci_write_reg(0x00fc0000, SH7780_PCIMBMR0);
+
+#ifdef CONFIG_32BIT
+ pci_write_reg(0xc0000000, SH7780_PCIMBR2);
+ pci_write_reg(0x20000000 - SH7780_PCI_IO_SIZE, SH7780_PCIMBMR2);
+#endif
/* Set IOBR for windows containing area specified in pci.h */
- outl((PCIBIOS_MIN_IO & ~(SH7780_PCI_IO_SIZE-1)), PCI_REG(SH7780_PCIIOBR));
- outl(((SH7780_PCI_IO_SIZE-1) & (7<<18)), PCI_REG(SH7780_PCIIOBMR));
+ pci_write_reg((PCIBIOS_MIN_IO & ~(SH7780_PCI_IO_SIZE - 1)),
+ SH7780_PCIIOBR);
+ pci_write_reg(((SH7780_PCI_IO_SIZE-1) & (7<<18)), SH7780_PCIIOBMR);
return 0;
}
-
diff --git a/arch/sh/drivers/pci/fixups-rts7751r2d.c b/arch/sh/drivers/pci/fixups-rts7751r2d.c
index 0c590fc7a08..e72ceb560d5 100644
--- a/arch/sh/drivers/pci/fixups-rts7751r2d.c
+++ b/arch/sh/drivers/pci/fixups-rts7751r2d.c
@@ -10,8 +10,7 @@
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*/
-#include "pci-sh7751.h"
-#include <asm/io.h>
+#include "pci-sh4.h"
#define PCIMCR_MRSET_OFF 0xBFFFFFFF
#define PCIMCR_RFSH_OFF 0xFFFFFFFB
@@ -22,22 +21,23 @@ int pci_fixup_pcic(void)
bcr1 = inl(SH7751_BCR1);
bcr1 |= 0x40080000; /* Enable Bit 19 BREQEN, set PCIC to slave */
- outl(bcr1, PCI_REG(SH7751_PCIBCR1));
+ pci_write_reg(bcr1, SH4_PCIBCR1);
/* Enable all interrupts, so we known what to fix */
- outl(0x0000c3ff, PCI_REG(SH7751_PCIINTM));
- outl(0x0000380f, PCI_REG(SH7751_PCIAINTM));
+ pci_write_reg(0x0000c3ff, SH4_PCIINTM);
+ pci_write_reg(0x0000380f, SH4_PCIAINTM);
- outl(0xfb900047, PCI_REG(SH7751_PCICONF1));
- outl(0xab000001, PCI_REG(SH7751_PCICONF4));
+ pci_write_reg(0xfb900047, SH7751_PCICONF1);
+ pci_write_reg(0xab000001, SH7751_PCICONF4);
mcr = inl(SH7751_MCR);
mcr = (mcr & PCIMCR_MRSET_OFF) & PCIMCR_RFSH_OFF;
- outl(mcr, PCI_REG(SH7751_PCIMCR));
+ pci_write_reg(mcr, SH4_PCIMCR);
+
+ pci_write_reg(0x0c000000, SH7751_PCICONF5);
+ pci_write_reg(0xd0000000, SH7751_PCICONF6);
+ pci_write_reg(0x0c000000, SH4_PCILAR0);
+ pci_write_reg(0x00000000, SH4_PCILAR1);
- outl(0x0c000000, PCI_REG(SH7751_PCICONF5));
- outl(0xd0000000, PCI_REG(SH7751_PCICONF6));
- outl(0x0c000000, PCI_REG(SH7751_PCILAR0));
- outl(0x00000000, PCI_REG(SH7751_PCILAR1));
return 0;
}
diff --git a/arch/sh/drivers/pci/fixups-sh03.c b/arch/sh/drivers/pci/fixups-sh03.c
index 57ac26c2171..2e8a18b7ee5 100644
--- a/arch/sh/drivers/pci/fixups-sh03.c
+++ b/arch/sh/drivers/pci/fixups-sh03.c
@@ -3,11 +3,7 @@
#include <linux/types.h>
#include <linux/pci.h>
-/*
- * IRQ functions
- */
-
-int __init pcibios_map_platform_irq(u8 slot, u8 pin, struct pci_dev *dev)
+int __init pcibios_map_platform_irq(struct pci_dev *dev, u8 slot, u8 pin)
{
int irq;
@@ -17,8 +13,9 @@ int __init pcibios_map_platform_irq(u8 slot, u8 pin, struct pci_dev *dev)
case 8: return 5; /* eth1 */
case 6: return 2; /* PCI bridge */
default:
- printk("PCI: Bad IRQ mapping request for slot %d\n", slot);
- return 2;
+ printk(KERN_ERR "PCI: Bad IRQ mapping request "
+ "for slot %d\n", slot);
+ return 2;
}
} else {
switch (pin) {
@@ -32,30 +29,3 @@ int __init pcibios_map_platform_irq(u8 slot, u8 pin, struct pci_dev *dev)
}
return irq;
}
-
-static u8 __init sh03_no_swizzle(struct pci_dev *dev, u8 *pin)
-{
- /* no swizzling */
- return PCI_SLOT(dev->devfn);
-}
-
-static int sh03_pci_lookup_irq(struct pci_dev *dev, u8 slot, u8 pin)
-{
- int irq = -1;
-
- /* now lookup the actual IRQ on a platform specific basis (pci-'platform'.c) */
- irq = pcibios_map_platform_irq(slot, pin, dev);
- if( irq < 0 ) {
- pr_debug("PCI: Error mapping IRQ on device %s\n", pci_name(dev));
- return irq;
- }
-
- pr_debug("Setting IRQ for slot %s to %d\n", pci_name(dev), irq);
-
- return irq;
-}
-
-void __init pcibios_fixup_irqs(void)
-{
- pci_fixup_irqs(sh03_no_swizzle, sh03_pci_lookup_irq);
-}
diff --git a/arch/sh/drivers/pci/ops-bigsur.c b/arch/sh/drivers/pci/ops-bigsur.c
index ae82c6ca05e..5da501bd77b 100644
--- a/arch/sh/drivers/pci/ops-bigsur.c
+++ b/arch/sh/drivers/pci/ops-bigsur.c
@@ -10,15 +10,12 @@
*
* PCI initialization for the Hitachi Big Sur Evaluation Board
*/
-
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/init.h>
-#include <linux/delay.h>
#include <linux/pci.h>
-
#include <asm/io.h>
-#include "pci-sh7751.h"
+#include "pci-sh4.h"
#include <asm/bigsur/bigsur.h>
#define BIGSUR_PCI_IO 0x4000
@@ -41,11 +38,11 @@ static struct resource sh7751_mem_resource = {
extern struct pci_ops sh7751_pci_ops;
struct pci_channel board_pci_channels[] = {
- { &sh7751_pci_ops, &sh7751_io_resource, &sh7751_mem_resource, 0, 0xff },
+ { &sh4_pci_ops, &sh7751_io_resource, &sh7751_mem_resource, 0, 0xff },
{ 0, }
};
-static struct sh7751_pci_address_map sh7751_pci_map = {
+static struct sh4_pci_address_map sh7751_pci_map = {
.window0 = {
.base = SH7751_CS3_BASE_ADDR,
.size = BIGSUR_LSR0_SIZE,
@@ -58,7 +55,7 @@ static struct sh7751_pci_address_map sh7751_pci_map = {
};
/*
- * Initialize the Big Sur PCI interface
+ * Initialize the Big Sur PCI interface
* Setup hardware to be Central Funtion
* Copy the BSR regs to the PCI interface
* Setup PCI windows into local RAM
@@ -68,15 +65,15 @@ int __init pcibios_init_platform(void)
return sh7751_pcic_init(&sh7751_pci_map);
}
-int pcibios_map_platform_irq(u8 slot, u8 pin)
+int __init pcibios_map_platform_irq(struct pci_dev *pdev, u8 slot, u8 pin)
{
- /*
+ /*
* The Big Sur can be used in a CPCI chassis, but the SH7751 PCI
* interface is on the wrong end of the board so that it can also
* support a V320 CPI interface chip... Therefor the IRQ mapping is
* somewhat use dependent... I'l assume a linear map for now, i.e.
* INTA=slot0,pin0... INTD=slot3,pin0...
- */
+ */
int irq = (slot + pin-1) % 4 + BIGSUR_SH7751_PCI_IRQ_BASE;
PCIDBG(2, "PCI: Mapping Big Sur IRQ for slot %d, pin %c to irq %d\n",
@@ -84,4 +81,3 @@ int pcibios_map_platform_irq(u8 slot, u8 pin)
return irq;
}
-
diff --git a/arch/sh/drivers/pci/ops-landisk.c b/arch/sh/drivers/pci/ops-landisk.c
new file mode 100644
index 00000000000..ada301c21fe
--- /dev/null
+++ b/arch/sh/drivers/pci/ops-landisk.c
@@ -0,0 +1,68 @@
+/*
+ * arch/sh/drivers/pci/ops-landisk.c
+ *
+ * PCI initialization for the I-O DATA Device, Inc. LANDISK board
+ *
+ * Copyright (C) 2006 kogiidena
+ *
+ * May be copied or modified under the terms of the GNU General Public
+ * License. See linux/COPYING for more information.
+ */
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/pci.h>
+#include "pci-sh4.h"
+
+static struct resource sh7751_io_resource = {
+ .name = "SH7751 IO",
+ .start = 0x4000,
+ .end = 0x4000 + SH7751_PCI_IO_SIZE - 1,
+ .flags = IORESOURCE_IO
+};
+
+static struct resource sh7751_mem_resource = {
+ .name = "SH7751 mem",
+ .start = SH7751_PCI_MEMORY_BASE,
+ .end = SH7751_PCI_MEMORY_BASE + SH7751_PCI_MEM_SIZE - 1,
+ .flags = IORESOURCE_MEM
+};
+
+struct pci_channel board_pci_channels[] = {
+ {&sh4_pci_ops, &sh7751_io_resource, &sh7751_mem_resource, 0, 0x3ff},
+ {NULL, NULL, NULL, 0, 0},
+};
+
+static struct sh4_pci_address_map sh7751_pci_map = {
+ .window0 = {
+ .base = SH7751_CS3_BASE_ADDR,
+ .size = (64 << 20), /* 64MB */
+ },
+
+ .flags = SH4_PCIC_NO_RESET,
+};
+
+int __init pcibios_init_platform(void)
+{
+ return sh7751_pcic_init(&sh7751_pci_map);
+}
+
+int pcibios_map_platform_irq(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) + 5;
+
+ if ((slot | (pin - 1)) > 0x3) {
+ printk("PCI: Bad IRQ mapping request for slot %d pin %c\n",
+ slot, pin - 1 + 'A');
+ return -1;
+ }
+ return irq;
+}
diff --git a/arch/sh/drivers/pci/ops-r7780rp.c b/arch/sh/drivers/pci/ops-r7780rp.c
index 3254c4e917a..554d5ed2c58 100644
--- a/arch/sh/drivers/pci/ops-r7780rp.c
+++ b/arch/sh/drivers/pci/ops-r7780rp.c
@@ -15,13 +15,11 @@
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/pci.h>
-#include <linux/module.h>
-
-#include <asm/io.h>
-#include "pci-sh7780.h"
#include <asm/r7780rp/r7780rp.h>
+#include <asm/io.h>
+#include "pci-sh4.h"
-int __init pcibios_map_platform_irq(u8 slot, u8 pin)
+int __init pcibios_map_platform_irq(struct pci_dev *pdev, u8 slot, u8 pin)
{
switch (slot) {
case 0: return IRQ_PCISLOT1; /* PCI Interrupt #1 */
@@ -29,7 +27,8 @@ int __init pcibios_map_platform_irq(u8 slot, u8 pin)
case 2: return IRQ_PCISLOT3; /* PCI Interrupt #3 */
case 3: return IRQ_PCISLOT4; /* PCI Interrupt E4 */
default:
- printk("PCI: Bad IRQ mapping request for slot %d, func %d\n", slot, pin-1);
+ printk(KERN_ERR "PCI: Bad IRQ mapping "
+ "request for slot %d, func %d\n", slot, pin-1);
return -1;
}
}
@@ -51,12 +50,12 @@ static struct resource sh7780_mem_resource = {
extern struct pci_ops sh7780_pci_ops;
struct pci_channel board_pci_channels[] = {
- { &sh7780_pci_ops, &sh7780_io_resource, &sh7780_mem_resource, 0, 0xff },
+ { &sh4_pci_ops, &sh7780_io_resource, &sh7780_mem_resource, 0, 0xff },
{ NULL, NULL, NULL, 0, 0 },
};
EXPORT_SYMBOL(board_pci_channels);
-static struct sh7780_pci_address_map sh7780_pci_map = {
+static struct sh4_pci_address_map sh7780_pci_map = {
.window0 = {
.base = SH7780_CS2_BASE_ADDR,
.size = 0x04000000,
@@ -67,11 +66,10 @@ static struct sh7780_pci_address_map sh7780_pci_map = {
.size = 0x04000000,
},
- .flags = SH7780_PCIC_NO_RESET,
+ .flags = SH4_PCIC_NO_RESET,
};
int __init pcibios_init_platform(void)
{
return sh7780_pcic_init(&sh7780_pci_map);
}
-
diff --git a/arch/sh/drivers/pci/ops-rts7751r2d.c b/arch/sh/drivers/pci/ops-rts7751r2d.c
index 83171d10141..88f44e24542 100644
--- a/arch/sh/drivers/pci/ops-rts7751r2d.c
+++ b/arch/sh/drivers/pci/ops-rts7751r2d.c
@@ -17,12 +17,11 @@
#include <linux/delay.h>
#include <linux/pci.h>
#include <linux/module.h>
-
-#include <asm/io.h>
-#include "pci-sh7751.h"
#include <asm/rts7751r2d/rts7751r2d.h>
+#include <asm/io.h>
+#include "pci-sh4.h"
-int __init pcibios_map_platform_irq(u8 slot, u8 pin)
+int __init pcibios_map_platform_irq(struct pci_dev *pdev, u8 slot, u8 pin)
{
switch (slot) {
case 0: return IRQ_PCISLOT1; /* PCI Extend slot #1 */
@@ -52,12 +51,12 @@ static struct resource sh7751_mem_resource = {
extern struct pci_ops sh7751_pci_ops;
struct pci_channel board_pci_channels[] = {
- { &sh7751_pci_ops, &sh7751_io_resource, &sh7751_mem_resource, 0, 0xff },
+ { &sh4_pci_ops, &sh7751_io_resource, &sh7751_mem_resource, 0, 0xff },
{ NULL, NULL, NULL, 0, 0 },
};
EXPORT_SYMBOL(board_pci_channels);
-static struct sh7751_pci_address_map sh7751_pci_map = {
+static struct sh4_pci_address_map sh7751_pci_map = {
.window0 = {
.base = SH7751_CS3_BASE_ADDR,
.size = 0x04000000,
@@ -68,7 +67,7 @@ static struct sh7751_pci_address_map sh7751_pci_map = {
.size = 0x00000000, /* Unused */
},
- .flags = SH7751_PCIC_NO_RESET,
+ .flags = SH4_PCIC_NO_RESET,
};
int __init pcibios_init_platform(void)
diff --git a/arch/sh/drivers/pci/ops-sh4.c b/arch/sh/drivers/pci/ops-sh4.c
new file mode 100644
index 00000000000..2d4371009a5
--- /dev/null
+++ b/arch/sh/drivers/pci/ops-sh4.c
@@ -0,0 +1,164 @@
+/*
+ * Generic SH-4 / SH-4A PCIC operations (SH7751, SH7780).
+ *
+ * Copyright (C) 2002 - 2006 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 <asm/addrspace.h>
+#include <asm/io.h>
+#include "pci-sh4.h"
+
+/*
+ * Direct access to PCI hardware...
+ */
+#define CONFIG_CMD(bus, devfn, where) \
+ P1SEGADDR((bus->number << 16) | (devfn << 8) | (where & ~3))
+
+static DEFINE_SPINLOCK(sh4_pci_lock);
+
+/*
+ * 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)
+{
+ unsigned long flags;
+ u32 data;
+
+ /*
+ * PCIPDR may only be accessed as 32 bit words,
+ * so we must do byte alignment by hand
+ */
+ spin_lock_irqsave(&sh4_pci_lock, flags);
+ pci_write_reg(CONFIG_CMD(bus, devfn, where), SH4_PCIPAR);
+ data = pci_read_reg(SH4_PCIPDR);
+ spin_unlock_irqrestore(&sh4_pci_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)
+{
+ unsigned long flags;
+ int shift;
+ u32 data;
+
+ spin_lock_irqsave(&sh4_pci_lock, flags);
+ pci_write_reg(CONFIG_CMD(bus, devfn, where), SH4_PCIPAR);
+ data = pci_read_reg(SH4_PCIPDR);
+ spin_unlock_irqrestore(&sh4_pci_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(data, SH4_PCIPDR);
+
+ return PCIBIOS_SUCCESSFUL;
+}
+
+struct pci_ops sh4_pci_ops = {
+ .read = sh4_pci_read,
+ .write = sh4_pci_write,
+};
+
+/*
+ * Not really related to pci_ops, but it's common and not worth shoving
+ * somewhere else for now..
+ */
+static unsigned int pci_probe = PCI_PROBE_CONF1;
+
+int __init sh4_pci_check_direct(void)
+{
+ /*
+ * Check if configuration works.
+ */
+ if (pci_probe & PCI_PROBE_CONF1) {
+ unsigned int tmp = pci_read_reg(SH4_PCIPAR);
+
+ pci_write_reg(P1SEG, SH4_PCIPAR);
+
+ if (pci_read_reg(SH4_PCIPAR) == P1SEG) {
+ pci_write_reg(tmp, SH4_PCIPAR);
+ printk(KERN_INFO "PCI: Using configuration type 1\n");
+ request_region(PCI_REG(SH4_PCIPAR), 8, "PCI conf1");
+
+ return 0;
+ }
+
+ pci_write_reg(tmp, SH4_PCIPAR);
+ }
+
+ pr_debug("PCI: pci_check_direct failed\n");
+ return -EINVAL;
+}
+
+/* Handle generic fixups */
+static void __init pci_fixup_ide_bases(struct pci_dev *d)
+{
+ int i;
+
+ /*
+ * PCI IDE controllers use non-standard I/O port decoding, respect it.
+ */
+ if ((d->class >> 8) != PCI_CLASS_STORAGE_IDE)
+ return;
+ pr_debug("PCI: IDE base address fixup for %s\n", pci_name(d));
+ for(i = 0; i < 4; i++) {
+ struct resource *r = &d->resource[i];
+
+ if ((r->start & ~0x80) == 0x374) {
+ r->start |= 2;
+ r->end = r->start;
+ }
+ }
+}
+DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, pci_fixup_ide_bases);
+
+char * __init pcibios_setup(char *str)
+{
+ if (!strcmp(str, "off")) {
+ pci_probe = 0;
+ return NULL;
+ }
+
+ return str;
+}
diff --git a/arch/sh/drivers/pci/ops-snapgear.c b/arch/sh/drivers/pci/ops-snapgear.c
index 3cbd14dd28f..53dd893d4e5 100644
--- a/arch/sh/drivers/pci/ops-snapgear.c
+++ b/arch/sh/drivers/pci/ops-snapgear.c
@@ -2,7 +2,7 @@
* 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.
@@ -12,15 +12,11 @@
*
* PCI initialization for the SnapGear boards
*/
-
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/init.h>
-#include <linux/delay.h>
#include <linux/pci.h>
-
-#include <asm/io.h>
-#include "pci-sh7751.h"
+#include "pci-sh4.h"
#define SNAPGEAR_PCI_IO 0x4000
#define SNAPGEAR_PCI_MEM 0xfd000000
@@ -43,14 +39,12 @@ static struct resource sh7751_mem_resource = {
.flags = IORESOURCE_MEM,
};
-extern struct pci_ops sh7751_pci_ops;
-
struct pci_channel board_pci_channels[] = {
- { &sh7751_pci_ops, &sh7751_io_resource, &sh7751_mem_resource, 0, 0xff },
+ { &sh4_pci_ops, &sh7751_io_resource, &sh7751_mem_resource, 0, 0xff },
{ 0, }
};
-static struct sh7751_pci_address_map sh7751_pci_map = {
+static struct sh4_pci_address_map sh7751_pci_map = {
.window0 = {
.base = SH7751_CS2_BASE_ADDR,
.size = SNAPGEAR_LSR0_SIZE,
@@ -61,11 +55,11 @@ static struct sh7751_pci_address_map sh7751_pci_map = {
.size = SNAPGEAR_LSR1_SIZE,
},
- .flags = SH7751_PCIC_NO_RESET,
+ .flags = SH4_PCIC_NO_RESET,
};
/*
- * Initialize the SnapGear PCI interface
+ * Initialize the SnapGear PCI interface
* Setup hardware to be Central Funtion
* Copy the BSR regs to the PCI interface
* Setup PCI windows into local RAM
@@ -75,7 +69,7 @@ int __init pcibios_init_platform(void)
return sh7751_pcic_init(&sh7751_pci_map);
}
-int __init pcibios_map_platform_irq(u8 slot, u8 pin)
+int __init pcibios_map_platform_irq(struct pci_dev *pdev, u8 slot, u8 pin)
{
int irq = -1;
@@ -98,4 +92,3 @@ void __init pcibios_fixup(void)
{
/* Nothing to fixup .. */
}
-
diff --git a/arch/sh/drivers/pci/ops-titan.c b/arch/sh/drivers/pci/ops-titan.c
index f76e4e963ac..9c8b2027c35 100644
--- a/arch/sh/drivers/pci/ops-titan.c
+++ b/arch/sh/drivers/pci/ops-titan.c
@@ -16,12 +16,11 @@
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/init.h>
-#include <linux/delay.h>
#include <asm/io.h>
#include <asm/titan.h>
-#include "pci-sh7751.h"
+#include "pci-sh4.h"
-int __init pcibios_map_platform_irq(u8 slot, u8 pin)
+int __init pcibios_map_platform_irq(struct pci_dev *pdev, u8 slot, u8 pin)
{
int irq = -1;
@@ -32,7 +31,8 @@ int __init pcibios_map_platform_irq(u8 slot, u8 pin)
case 3: irq = TITAN_IRQ_MPCIB; break; /* mPCI B */
case 4: irq = TITAN_IRQ_USB; break; /* USB */
default:
- printk(KERN_INFO "PCI: Bad IRQ mapping request for slot %d\n", slot);
+ printk(KERN_INFO "PCI: Bad IRQ mapping "
+ "request for slot %d\n", slot);
return -1;
}
@@ -56,15 +56,13 @@ static struct resource sh7751_mem_resource = {
.flags = IORESOURCE_MEM
};
-extern struct pci_ops sh7751_pci_ops;
-
struct pci_channel board_pci_channels[] = {
- { &sh7751_pci_ops, &sh7751_io_resource, &sh7751_mem_resource, 0, 0xff },
+ { &sh4_pci_ops, &sh7751_io_resource, &sh7751_mem_resource, 0, 0xff },
{ NULL, NULL, NULL, 0, 0 },
};
EXPORT_SYMBOL(board_pci_channels);
-static struct sh7751_pci_address_map sh7751_pci_map = {
+static struct sh4_pci_address_map sh7751_pci_map = {
.window0 = {
.base = SH7751_CS2_BASE_ADDR,
.size = SH7751_MEM_REGION_SIZE*2, /* cs2 and cs3 */
@@ -75,7 +73,7 @@ static struct sh7751_pci_address_map sh7751_pci_map = {
.size = SH7751_MEM_REGION_SIZE*2,
},
- .flags = SH7751_PCIC_NO_RESET,
+ .flags = SH4_PCIC_NO_RESET,
};
int __init pcibios_init_platform(void)
diff --git a/arch/sh/drivers/pci/pci-auto.c b/arch/sh/drivers/pci/pci-auto.c
index d55e4661854..ecf16344f94 100644
--- a/arch/sh/drivers/pci/pci-auto.c
+++ b/arch/sh/drivers/pci/pci-auto.c
@@ -358,7 +358,6 @@ pciauto_postscan_setup_cardbus_bridge(struct pci_channel *hose,
{
u32 temp;
-#if !defined(CONFIG_SH_HS7751RVOIP) && !defined(CONFIG_SH_RTS7751R2D) && !defined(CONFIG_SH_R7780RP)
/*
* [jsun] we always bump up baselines a little, so that if there
* nothing behind P2P bridge, we don't wind up overlapping IO/MEM
@@ -366,7 +365,6 @@ pciauto_postscan_setup_cardbus_bridge(struct pci_channel *hose,
*/
pciauto_lower_memspc += 1;
pciauto_lower_iospc += 1;
-#endif
/*
* Configure subordinate bus number. The PCI subsystem
@@ -392,11 +390,6 @@ pciauto_postscan_setup_cardbus_bridge(struct pci_channel *hose,
* configured by this routine to happily live behind a
* P2P bridge in a system.
*/
-#if defined(CONFIG_SH_HS7751RVOIP) || defined(CONFIG_SH_RTS7751R2D) || defined(CONFIG_SH_R7780RP)
- pciauto_lower_memspc += 0x00400000;
- pciauto_lower_iospc += 0x00004000;
-#endif
-
/* Align memory and I/O to 4KB and 4 byte boundaries. */
pciauto_lower_memspc = (pciauto_lower_memspc + (0x1000 - 1))
& ~(0x1000 - 1);
@@ -467,9 +460,6 @@ pciauto_bus_scan(struct pci_channel *hose, int top_bus, int current_bus)
if ((pci_class >> 16) == PCI_CLASS_BRIDGE_PCI) {
DBG(" Bridge: primary=%.2x, secondary=%.2x\n",
current_bus, sub_bus + 1);
-#if defined(CONFIG_SH_HS7751RVOIP) || defined(CONFIG_SH_RTS7751R2D) || defined(CONFIG_SH_R7780RP)
- pciauto_setup_bars(hose, top_bus, current_bus, pci_devfn, PCI_BASE_ADDRESS_1);
-#endif
pciauto_prescan_setup_bridge(hose, top_bus, current_bus,
pci_devfn, sub_bus);
DBG("Scanning sub bus %.2x, I/O 0x%.8x, Mem 0x%.8x\n",
diff --git a/arch/sh/drivers/pci/pci-sh4.h b/arch/sh/drivers/pci/pci-sh4.h
new file mode 100644
index 00000000000..5a61d6041f2
--- /dev/null
+++ b/arch/sh/drivers/pci/pci-sh4.h
@@ -0,0 +1,180 @@
+#ifndef __PCI_SH4_H
+#define __PCI_SH4_H
+
+#ifdef CONFIG_CPU_SUBTYPE_SH7780
+#include "pci-sh7780.h"
+#else
+#include "pci-sh7751.h"
+#endif
+
+#include <asm/io.h>
+
+/* startup values */
+#define PCI_PROBE_BIOS 1
+#define PCI_PROBE_CONF1 2
+#define PCI_PROBE_CONF2 4
+#define PCI_NO_SORT 0x100
+#define PCI_BIOS_SORT 0x200
+#define PCI_NO_CHECKS 0x400
+#define PCI_ASSIGN_ROMS 0x1000
+#define PCI_BIOS_IRQ_SCAN 0x2000
+
+#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