summaryrefslogtreecommitdiff
path: root/arch/sh/drivers/pci
diff options
context:
space:
mode:
authorArnd Bergmann <arnd@arndb.de>2009-06-12 09:53:47 +0200
committerArnd Bergmann <arnd@arndb.de>2009-06-12 11:32:58 +0200
commit5b02ee3d219f9e01b6e9146e25613822cfc2e5ce (patch)
tree7ce9126738c3cf4b37d67170d0e4b34818c057a9 /arch/sh/drivers/pci
parent26a28fa4fea5b8c65713aa50c124f76a88c7924d (diff)
parent8ebf975608aaebd7feb33d77f07ba21a6380e086 (diff)
asm-generic: merge branch 'master' of torvalds/linux-2.6
Fixes a merge conflict against the x86 tree caused by a fix to atomic.h which I renamed to atomic_long.h. Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Diffstat (limited to 'arch/sh/drivers/pci')
-rw-r--r--arch/sh/drivers/pci/Kconfig18
-rw-r--r--arch/sh/drivers/pci/Makefile28
-rw-r--r--arch/sh/drivers/pci/fixups-cayman.c (renamed from arch/sh/drivers/pci/ops-cayman.c)12
-rw-r--r--arch/sh/drivers/pci/fixups-dreamcast.c9
-rw-r--r--arch/sh/drivers/pci/fixups-landisk.c (renamed from arch/sh/drivers/pci/ops-landisk.c)33
-rw-r--r--arch/sh/drivers/pci/fixups-lboxre2.c41
-rw-r--r--arch/sh/drivers/pci/fixups-r7780rp.c41
-rw-r--r--arch/sh/drivers/pci/fixups-rts7751r2d.c48
-rw-r--r--arch/sh/drivers/pci/fixups-sdk7780.c63
-rw-r--r--arch/sh/drivers/pci/fixups-se7751.c111
-rw-r--r--arch/sh/drivers/pci/fixups-se7780.c60
-rw-r--r--arch/sh/drivers/pci/fixups-sh7785lcr.c46
-rw-r--r--arch/sh/drivers/pci/fixups-snapgear.c38
-rw-r--r--arch/sh/drivers/pci/fixups-titan.c (renamed from arch/sh/drivers/pci/ops-titan.c)39
-rw-r--r--arch/sh/drivers/pci/ops-dreamcast.c107
-rw-r--r--arch/sh/drivers/pci/ops-lboxre2.c63
-rw-r--r--arch/sh/drivers/pci/ops-r7780rp.c68
-rw-r--r--arch/sh/drivers/pci/ops-rts7751r2d.c74
-rw-r--r--arch/sh/drivers/pci/ops-sdk7780.c73
-rw-r--r--arch/sh/drivers/pci/ops-se7780.c96
-rw-r--r--arch/sh/drivers/pci/ops-sh03.c45
-rw-r--r--arch/sh/drivers/pci/ops-sh4.c79
-rw-r--r--arch/sh/drivers/pci/ops-sh5.c25
-rw-r--r--arch/sh/drivers/pci/ops-sh7785lcr.c66
-rw-r--r--arch/sh/drivers/pci/ops-snapgear.c94
-rw-r--r--arch/sh/drivers/pci/pci-auto.c545
-rw-r--r--arch/sh/drivers/pci/pci-dreamcast.c102
-rw-r--r--arch/sh/drivers/pci/pci-sh4.h19
-rw-r--r--arch/sh/drivers/pci/pci-sh5.c55
-rw-r--r--arch/sh/drivers/pci/pci-sh5.h3
-rw-r--r--arch/sh/drivers/pci/pci-sh7751.c215
-rw-r--r--arch/sh/drivers/pci/pci-sh7751.h12
-rw-r--r--arch/sh/drivers/pci/pci-sh7780.c224
-rw-r--r--arch/sh/drivers/pci/pci-sh7780.h16
-rw-r--r--arch/sh/drivers/pci/pci.c279
35 files changed, 864 insertions, 1983 deletions
diff --git a/arch/sh/drivers/pci/Kconfig b/arch/sh/drivers/pci/Kconfig
index 7e816ededed7..e8db585a6638 100644
--- a/arch/sh/drivers/pci/Kconfig
+++ b/arch/sh/drivers/pci/Kconfig
@@ -17,21 +17,3 @@ config SH_PCIDMA_NONCOHERENT
code will not have to flush the CPU's caches. If you have a PCI host
bridge integrated with your SH CPU, refer carefully to the chip specs
to see if you can say 'N' here. Otherwise, leave it as 'Y'.
-
-# This is also board-specific
-config PCI_AUTO
- bool
- depends on PCI
- default y
-
-config PCI_AUTO_UPDATE_RESOURCES
- bool
- depends on PCI_AUTO
- default y if !SH_DREAMCAST
- help
- Selecting this option will cause the PCI auto code to leave your
- BAR values alone. Otherwise they will be updated automatically. If
- for some reason, you have a board that simply refuses to work
- with its resources updated beyond what they are when the device
- is powered up, set this to N. Everyone else will want this as Y.
-
diff --git a/arch/sh/drivers/pci/Makefile b/arch/sh/drivers/pci/Makefile
index 847e90894d1b..d2ffc477549a 100644
--- a/arch/sh/drivers/pci/Makefile
+++ b/arch/sh/drivers/pci/Makefile
@@ -1,9 +1,7 @@
#
# Makefile for the PCI specific kernel interface routines under Linux.
#
-
obj-y += pci.o
-obj-$(CONFIG_PCI_AUTO) += pci-auto.o
obj-$(CONFIG_CPU_SUBTYPE_SH7751) += pci-sh7751.o ops-sh4.o
obj-$(CONFIG_CPU_SUBTYPE_SH7751R) += pci-sh7751.o ops-sh4.o
@@ -12,15 +10,17 @@ 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_SH5) += pci-sh5.o ops-sh5.o
-obj-$(CONFIG_SH_DREAMCAST) += ops-dreamcast.o fixups-dreamcast.o
-obj-$(CONFIG_SH_SECUREEDGE5410) += ops-snapgear.o
-obj-$(CONFIG_SH_RTS7751R2D) += ops-rts7751r2d.o fixups-rts7751r2d.o
-obj-$(CONFIG_SH_SH03) += ops-sh03.o fixups-sh03.o
-obj-$(CONFIG_SH_HIGHLANDER) += ops-r7780rp.o fixups-r7780rp.o
-obj-$(CONFIG_SH_SDK7780) += ops-sdk7780.o fixups-sdk7780.o
-obj-$(CONFIG_SH_TITAN) += ops-titan.o
-obj-$(CONFIG_SH_LANDISK) += ops-landisk.o
-obj-$(CONFIG_SH_LBOX_RE2) += ops-lboxre2.o fixups-lboxre2.o
-obj-$(CONFIG_SH_7780_SOLUTION_ENGINE) += ops-se7780.o fixups-se7780.o
-obj-$(CONFIG_SH_CAYMAN) += ops-cayman.o
-obj-$(CONFIG_SH_SH7785LCR) += ops-sh7785lcr.o fixups-sh7785lcr.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_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/ops-cayman.c b/arch/sh/drivers/pci/fixups-cayman.c
index 38ef76207af6..b68b61d22c6c 100644
--- a/arch/sh/drivers/pci/ops-cayman.c
+++ b/arch/sh/drivers/pci/fixups-cayman.c
@@ -75,15 +75,3 @@ int __init pcibios_map_platform_irq(struct pci_dev *dev, u8 slot, u8 pin)
return result;
}
-
-struct pci_channel board_pci_channels[] = {
- { &sh5_pci_ops, NULL, NULL, 0, 0xff },
- { NULL, NULL, NULL, 0, 0 },
-};
-EXPORT_SYMBOL(board_pci_channels);
-
-int __init pcibios_init_platform(void)
-{
- return sh5pci_init(__pa(memory_start),
- __pa(memory_end) - __pa(memory_start));
-}
diff --git a/arch/sh/drivers/pci/fixups-dreamcast.c b/arch/sh/drivers/pci/fixups-dreamcast.c
index 2bf85cf091e1..ed7f489936f1 100644
--- a/arch/sh/drivers/pci/fixups-dreamcast.c
+++ b/arch/sh/drivers/pci/fixups-dreamcast.c
@@ -30,7 +30,7 @@
static void __init gapspci_fixup_resources(struct pci_dev *dev)
{
- struct pci_channel *p = board_pci_channels;
+ struct pci_channel *p = dev->sysdata;
printk(KERN_NOTICE "PCI: Fixing up device %s\n", pci_name(dev));
@@ -41,6 +41,13 @@ static void __init gapspci_fixup_resources(struct pci_dev *dev)
*/
dev->resource[1].start = p->io_resource->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.
*/
diff --git a/arch/sh/drivers/pci/ops-landisk.c b/arch/sh/drivers/pci/fixups-landisk.c
index bff09ecf3419..bb1a6bb5149e 100644
--- a/arch/sh/drivers/pci/ops-landisk.c
+++ b/arch/sh/drivers/pci/fixups-landisk.c
@@ -15,39 +15,6 @@
#include <linux/pci.h>
#include "pci-sh4.h"
-static struct resource sh7751_io_resource = {
- .name = "SH7751 IO",
- .start = SH7751_PCI_IO_BASE,
- .end = SH7751_PCI_IO_BASE + SH7751_PCI_IO_SIZE - 1,
- .flags = IORESOURCE_IO
-};
-
-static struct resource sh7751_mem_resource = {
- .name = "SH7751 mem",
- .start = SH7751_PCI_MEMORY_BASE,
- .end = SH7751_PCI_MEMORY_BASE + SH7751_PCI_MEM_SIZE - 1,
- .flags = IORESOURCE_MEM
-};
-
-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)
{
/*
diff --git a/arch/sh/drivers/pci/fixups-lboxre2.c b/arch/sh/drivers/pci/fixups-lboxre2.c
deleted file mode 100644
index 1c1d41255ec0..000000000000
--- a/arch/sh/drivers/pci/fixups-lboxre2.c
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * arch/sh/drivers/pci/fixups-lboxre2.c
- *
- * L-BOX RE2 PCI fixups
- *
- * 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 "pci-sh4.h"
-
-#define PCIMCR_MRSET_OFF 0xBFFFFFFF
-#define PCIMCR_RFSH_OFF 0xFFFFFFFB
-
-int pci_fixup_pcic(void)
-{
- unsigned long bcr1, mcr;
-
- bcr1 = ctrl_inl(SH7751_BCR1);
- bcr1 |= 0x40080000; /* Enable Bit 19 BREQEN, set PCIC to slave */
- pci_write_reg(bcr1, SH4_PCIBCR1);
-
- /* Enable all interrupts, so we known what to fix */
- pci_write_reg(0x0000c3ff, SH4_PCIINTM);
- pci_write_reg(0x0000380f, SH4_PCIAINTM);
- pci_write_reg(0xfb900047, SH7751_PCICONF1);
- pci_write_reg(0xab000001, SH7751_PCICONF4);
-
- mcr = ctrl_inl(SH7751_MCR);
- mcr = (mcr & PCIMCR_MRSET_OFF) & PCIMCR_RFSH_OFF;
- 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);
-
- return 0;
-}
diff --git a/arch/sh/drivers/pci/fixups-r7780rp.c b/arch/sh/drivers/pci/fixups-r7780rp.c
index 3e321df65d22..15ca65cb667e 100644
--- a/arch/sh/drivers/pci/fixups-r7780rp.c
+++ b/arch/sh/drivers/pci/fixups-r7780rp.c
@@ -11,35 +11,26 @@
* for more details.
*/
#include <linux/pci.h>
+#include <linux/io.h>
#include "pci-sh4.h"
-#include <asm/io.h>
-int pci_fixup_pcic(void)
-{
- pci_write_reg(0x000043ff, SH4_PCIINTM);
- pci_write_reg(0x0000380f, SH4_PCIAINTM);
-
- pci_write_reg(0xfbb00047, SH7780_PCICMD);
- pci_write_reg(0x00000000, SH7780_PCIIBAR);
-
- 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);
-
- pci_write_reg(0xfd000000, SH7780_PCIMBR0);
- pci_write_reg(0x00fc0000, SH7780_PCIMBMR0);
+static char irq_tab[] __initdata = {
+ 65, 66, 67, 68,
+};
-#ifdef CONFIG_32BIT
- pci_write_reg(0xc0000000, SH7780_PCIMBR2);
- pci_write_reg(0x20000000 - SH7780_PCI_IO_SIZE, SH7780_PCIMBMR2);
-#endif
+int __init pcibios_map_platform_irq(struct pci_dev *pdev, u8 slot, u8 pin)
+{
+ return irq_tab[slot];
+}
- /* Set IOBR for windows containing area specified in pci.h */
- 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);
+int pci_fixup_pcic(struct pci_channel *chan)
+{
+ pci_write_reg(chan, 0x000043ff, SH4_PCIINTM);
+ pci_write_reg(chan, 0x00000000, SH7780_PCIIBAR);
+ pci_write_reg(chan, 0x08000000, SH7780_PCICSCR0);
+ pci_write_reg(chan, 0x0000001b, SH7780_PCICSAR0);
+ pci_write_reg(chan, 0xfd000000, SH7780_PCICSCR1);
+ pci_write_reg(chan, 0x0000000f, SH7780_PCICSAR1);
return 0;
}
diff --git a/arch/sh/drivers/pci/fixups-rts7751r2d.c b/arch/sh/drivers/pci/fixups-rts7751r2d.c
index 904bce8768d3..052b354236dc 100644
--- a/arch/sh/drivers/pci/fixups-rts7751r2d.c
+++ b/arch/sh/drivers/pci/fixups-rts7751r2d.c
@@ -1,43 +1,67 @@
/*
* arch/sh/drivers/pci/fixups-rts7751r2d.c
*
- * RTS7751R2D PCI fixups
+ * 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 <asm/machtypes.h>
#define PCIMCR_MRSET_OFF 0xBFFFFFFF
#define PCIMCR_RFSH_OFF 0xFFFFFFFB
-int pci_fixup_pcic(void)
+static u8 rts7751r2d_irq_tab[] __initdata = {
+ IRQ_PCI_INTA,
+ IRQ_PCI_INTB,
+ IRQ_PCI_INTC,
+ IRQ_PCI_INTD,
+};
+
+static char lboxre2_irq_tab[] __initdata = {
+ IRQ_ETH0, IRQ_ETH1, IRQ_INTA, IRQ_INTD,
+};
+
+int __init pcibios_map_platform_irq(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 = ctrl_inl(SH7751_BCR1);
bcr1 |= 0x40080000; /* Enable Bit 19 BREQEN, set PCIC to slave */
- pci_write_reg(bcr1, SH4_PCIBCR1);
+ pci_write_reg(chan, bcr1, SH4_PCIBCR1);
/* Enable all interrupts, so we known what to fix */
- pci_write_reg(0x0000c3ff, SH4_PCIINTM);
- pci_write_reg(0x0000380f, SH4_PCIAINTM);
+ pci_write_reg(chan, 0x0000c3ff, SH4_PCIINTM);
+ pci_write_reg(chan, 0x0000380f, SH4_PCIAINTM);
- pci_write_reg(0xfb900047, SH7751_PCICONF1);
- pci_write_reg(0xab000001, SH7751_PCICONF4);
+ pci_write_reg(chan, 0xfb900047, SH7751_PCICONF1);
+ pci_write_reg(chan, 0xab000001, SH7751_PCICONF4);
mcr = ctrl_inl(SH7751_MCR);
mcr = (mcr & PCIMCR_MRSET_OFF) & PCIMCR_RFSH_OFF;
- pci_write_reg(mcr, SH4_PCIMCR);
+ pci_write_reg(chan, 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);
+ 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
index 2f8863099dd1..250b0edd7365 100644
--- a/arch/sh/drivers/pci/fixups-sdk7780.c
+++ b/arch/sh/drivers/pci/fixups-sdk7780.c
@@ -5,55 +5,48 @@
*
* 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 "pci-sh4.h"
-#include <asm/io.h>
-int pci_fixup_pcic(void)
+/* IDSEL [16][17][18][19][20][21][22][23][24][25][26][27][28][29][30][31] */
+static char sdk7780_irq_tab[4][16] __initdata = {
+ /* INTA */
+ { 65, 68, 67, 68, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+ /* INTB */
+ { 66, 65, -1, 65, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+ /* INTC */
+ { 67, 66, -1, 66, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+ /* INTD */
+ { 68, 67, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+};
+
+int __init pcibios_map_platform_irq(struct pci_dev *pdev, u8 slot, u8 pin)
+{
+ return sdk7780_irq_tab[pin-1][slot];
+}
+int pci_fixup_pcic(struct pci_channel *chan)
{
- ctrl_outl(0x00000001, SH7780_PCI_VCR2);
-
/* Enable all interrupts, so we know what to fix */
- pci_write_reg(0x0000C3FF, SH7780_PCIIMR);
- pci_write_reg(0x0000380F, SH7780_PCIAINTM);
+ pci_write_reg(chan, 0x0000C3FF, SH7780_PCIIMR);
/* Set up standard PCI config registers */
- pci_write_reg(0xFB00, SH7780_PCISTATUS);
- pci_write_reg(0x0047, SH7780_PCICMD);
- pci_write_reg(0x00, SH7780_PCIPIF);
- pci_write_reg(0x00, SH7780_PCISUB);
- pci_write_reg(0x06, SH7780_PCIBCC);
- pci_write_reg(0x1912, SH7780_PCISVID);
- pci_write_reg(0x0001, SH7780_PCISID);
-
- pci_write_reg(0x08000000, SH7780_PCIMBAR0); /* PCI */
- pci_write_reg(0x08000000, SH7780_PCILAR0); /* SHwy */
- pci_write_reg(0x07F00001, SH7780_PCILSR); /* size 128M w/ MBAR */
-
- pci_write_reg(0x00000000, SH7780_PCIMBAR1);
- pci_write_reg(0x00000000, SH7780_PCILAR1);
- pci_write_reg(0x00000000, SH7780_PCILSR1);
-
- pci_write_reg(0xAB000801, SH7780_PCIIBAR);
-
- /*
- * Set the MBR so PCI address is one-to-one with window,
- * meaning all calls go straight through... use ifdef to
- * catch erroneous assumption.
- */
- pci_write_reg(0xFD000000 , SH7780_PCIMBR0);
- pci_write_reg(0x00FC0000 , SH7780_PCIMBMR0); /* 16M */
+ pci_write_reg(chan, 0x08000000, SH7780_PCIMBAR0); /* PCI */
+ pci_write_reg(chan, 0x08000000, SH4_PCILAR0); /* SHwy */
+ pci_write_reg(chan, 0x07F00001, SH4_PCILSR0); /* size 128M w/ MBAR */
- /* Set IOBR for window containing area specified in pci.h */
- 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);
+ pci_write_reg(chan, 0x00000000, SH7780_PCIMBAR1);
+ pci_write_reg(chan, 0x00000000, SH4_PCILAR1);
+ pci_write_reg(chan, 0x00000000, SH4_PCILSR1);
- pci_write_reg(0xA5000C01, SH7780_PCICR);
+ pci_write_reg(chan, 0xAB000801, SH7780_PCIIBAR);
+ pci_write_reg(chan, 0xA5000C01, SH4_PCICR);
return 0;
}
diff --git a/arch/sh/drivers/pci/fixups-se7751.c b/arch/sh/drivers/pci/fixups-se7751.c
new file mode 100644
index 000000000000..475fa9f0fe2c
--- /dev/null
+++ b/arch/sh/drivers/pci/fixups-se7751.c
@@ -0,0 +1,111 @@
+#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 "pci-sh4.h"
+
+int __init pcibios_map_platform_irq(u8 slot, u8 pin)
+{
+ switch (slot) {
+ case 0: return 13;
+ case 1: return 13; /* AMD Ethernet controller */
+ case 2: return -1;
+ case 3: return -1;
+ case 4: return -1;
+ default:
+ printk("PCI: Bad IRQ mapping request for slot %d\n", slot);
+ return -1;
+ }
+}
+
+#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->mem_resource->start != SH7751_PCI_MEMORY_BASE);
+
+ PCIC_WRITE(SH7751_PCIMBR, chan->mem_resource->start);
+
+ /* Set IOBR for window containing area specified in pci.h */
+ PCIC_WRITE(SH7751_PCIIOBR, (chan->io_resource->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-se7780.c b/arch/sh/drivers/pci/fixups-se7780.c
deleted file mode 100644
index 880cea1c0d89..000000000000
--- a/arch/sh/drivers/pci/fixups-se7780.c
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * arch/sh/drivers/pci/fixups-se7780.c
- *
- * HITACHI UL Solution Engine 7780 PCI fixups
- *
- * 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 "pci-sh4.h"
-#include <asm/io.h>
-
-int pci_fixup_pcic(void)
-{
- ctrl_outl(0x00000001, SH7780_PCI_VCR2);
-
- /* Enable all interrupts, so we know what to fix */
- pci_write_reg(0x0000C3FF, SH7780_PCIIMR);
- pci_write_reg(0x0000380F, SH7780_PCIAINTM);
-
- /* Set up standard PCI config registers */
- ctrl_outw(0xFB00, PCI_REG(SH7780_PCISTATUS));
- ctrl_outw(0x0047, PCI_REG(SH7780_PCICMD));
- ctrl_outb( 0x00, PCI_REG(SH7780_PCIPIF));
- ctrl_outb( 0x00, PCI_REG(SH7780_PCISUB));
- ctrl_outb( 0x06, PCI_REG(SH7780_PCIBCC));
- ctrl_outw(0x1912, PCI_REG(SH7780_PCISVID));
- ctrl_outw(0x0001, PCI_REG(SH7780_PCISID));
-
- pci_write_reg(0x08000000, SH7780_PCIMBAR0); /* PCI */
- pci_write_reg(0x08000000, SH7780_PCILAR0); /* SHwy */
- pci_write_reg(0x07F00001, SH7780_PCILSR); /* size 128M w/ MBAR */
-
- pci_write_reg(0x00000000, SH7780_PCIMBAR1);
- pci_write_reg(0x00000000, SH7780_PCILAR1);
- pci_write_reg(0x00000000, SH7780_PCILSR1);
-
- pci_write_reg(0xAB000801, SH7780_PCIIBAR);
-
- /*
- * Set the MBR so PCI address is one-to-one with window,
- * meaning all calls go straight through... use ifdef to
- * catch erroneous assumption.
- */
- pci_write_reg(0xFD000000 , SH7780_PCIMBR0);
- pci_write_reg(0x00FC0000 , SH7780_PCIMBMR0); /* 16M */
-
- /* Set IOBR for window containing area specified in pci.h */
- 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);
-
- pci_write_reg(0xA5000C01, SH7780_PCICR);
-
- return 0;
-}
diff --git a/arch/sh/drivers/pci/fixups-sh7785lcr.c b/arch/sh/drivers/pci/fixups-sh7785lcr.c
deleted file mode 100644
index 4949e601387a..000000000000
--- a/arch/sh/drivers/pci/fixups-sh7785lcr.c
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * arch/sh/drivers/pci/fixups-sh7785lcr.c
- *
- * R0P7785LC0011RL PCI fixups
- * Copyright (C) 2008 Yoshihiro Shimoda
- *
- * Based on arch/sh/drivers/pci/fixups-r7780rp.c
- * 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 "pci-sh4.h"
-
-int pci_fixup_pcic(void)
-{
- pci_write_reg(0x000043ff, SH4_PCIINTM);
- pci_write_reg(0x0000380f, SH4_PCIAINTM);
-
- pci_write_reg(0xfbb00047, SH7780_PCICMD);
- pci_write_reg(0x00000000, SH7780_PCIIBAR);
-
- 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);
-
- 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 */
- 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-snapgear.c b/arch/sh/drivers/pci/fixups-snapgear.c
new file mode 100644
index 000000000000..5a39ecc1adb8
--- /dev/null
+++ b/arch/sh/drivers/pci/fixups-snapgear.c
@@ -0,0 +1,38 @@
+/*
+ * 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 "pci-sh4.h"
+
+int __init pcibios_map_platform_irq(struct pci_dev *pdev, u8 slot, u8 pin)
+{
+ int irq = -1;
+
+ switch (slot) {
+ case 8: /* the PCI bridge */ break;
+ case 11: irq = 8; break; /* USB */
+ case 12: irq = 11; break; /* PCMCIA */
+ case 13: irq = 5; break; /* eth0 */
+ case 14: irq = 8; break; /* eth1 */
+ case 15: irq = 11; 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/ops-titan.c b/arch/sh/drivers/pci/fixups-titan.c
index a8f7801a34af..3a79fa8254a6 100644
--- a/arch/sh/drivers/pci/ops-titan.c
+++ b/arch/sh/drivers/pci/fixups-titan.c
@@ -36,42 +36,3 @@ int __init pcibios_map_platform_irq(struct pci_dev *pdev, u8 slot, u8 pin)
return irq;
}
-
-static struct resource sh7751_io_resource = {
- .name = "SH7751_IO",
- .start = SH7751_PCI_IO_BASE,
- .end = SH7751_PCI_IO_BASE + SH7751_PCI_IO_SIZE - 1,
- .flags = IORESOURCE_IO
-};
-
-static struct resource sh7751_mem_resource = {
- .name = "SH7751_mem",
- .start = SH7751_PCI_MEMORY_BASE,
- .end = SH7751_PCI_MEMORY_BASE + SH7751_PCI_MEM_SIZE - 1,
- .flags = IORESOURCE_MEM
-};
-
-struct pci_channel board_pci_channels[] = {
- { &sh4_pci_ops, &sh7751_io_resource, &sh7751_mem_resource, 0, 0xff },
- { NULL, NULL, NULL, 0, 0 },
-};
-EXPORT_SYMBOL(board_pci_channels);
-
-static struct sh4_pci_address_map sh7751_pci_map = {
- .window0 = {
- .base = SH7751_CS2_BASE_ADDR,
- .size = SH7751_MEM_REGION_SIZE*2, /* cs2 and cs3 */
- },
-
- .window1 = {
- .base = SH7751_CS2_BASE_ADDR,
- .size = SH7751_MEM_REGION_SIZE*2,
- },
-
- .flags = SH4_PCIC_NO_RESET,
-};
-
-int __init pcibios_init_platform(void)
-{
- return sh7751_pcic_init(&sh7751_pci_map);
-}
diff --git a/arch/sh/drivers/pci/ops-dreamcast.c b/arch/sh/drivers/pci/ops-dreamcast.c
index f5d2a2aa6f3f..e83d0d3aabe2 100644
--- a/arch/sh/drivers/pci/ops-dreamcast.c
+++ b/arch/sh/drivers/pci/ops-dreamcast.c
@@ -1,15 +1,9 @@
/*
- * arch/sh/drivers/pci/ops-dreamcast.c
- *
* PCI operations 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.
@@ -23,34 +17,10 @@
#include <linux/irq.h>
#include <linux/pci.h>
#include <linux/module.h>
-
-#include <asm/io.h>
-#include <asm/irq.h>
+#include <linux/io.h>
+#include <linux/irq.h>
#include <mach/pci.h>
-static struct resource gapspci_io_resource = {
- .name = "GAPSPCI IO",
- .start = GAPSPCI_BBA_CONFIG,
- .end = GAPSPCI_BBA_CONFIG + GAPSPCI_BBA_CONFIG_SIZE - 1,
- .flags = IORESOURCE_IO,
-};
-
-static struct resource gapspci_mem_resource = {
- .name = "GAPSPCI mem",
- .start = GAPSPCI_DMA_BASE,
- .end = GAPSPCI_DMA_BASE + GAPSPCI_DMA_SIZE - 1,
- .flags = IORESOURCE_MEM,
-};
-
-static struct pci_ops gapspci_pci_ops;
-
-struct pci_channel board_pci_channels[] = {
- { &gapspci_pci_ops, &gapspci_io_resource,
- &gapspci_mem_resource, 0, 1 },
- { 0, }
-};
-EXPORT_SYMBOL(board_pci_channels);
-
/*
* The !gapspci_config_access case really shouldn't happen, ever, unless
* someone implicitly messes around with the last devfn value.. otherwise we
@@ -85,10 +55,10 @@ static int gapspci_read(struct pci_bus *bus, unsigned int devfn, int where, int
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;
- }
+ 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;
}
@@ -99,72 +69,15 @@ static int gapspci_write(struct pci_bus *bus, unsigned int devfn, int where, int
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;
+ 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;
}
-static struct pci_ops gapspci_pci_ops = {
+struct pci_ops gapspci_pci_ops = {
.read = gapspci_read,
.write = gapspci_write,
};
-
-/*
- * gapspci init
- */
-
-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++)
- ;
-
- 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 0;
-}
-
-/* Haven't done anything here as yet */
-char * __devinit pcibios_setup(char *str)
-{
- return str;
-}
diff --git a/arch/sh/drivers/pci/ops-lboxre2.c b/arch/sh/drivers/pci/ops-lboxre2.c
deleted file mode 100644
index 86c0b6fb7375..000000000000
--- a/arch/sh/drivers/pci/ops-lboxre2.c
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * linux/arch/sh/drivers/pci/ops-lboxre2.c
- *
- * Copyright (C) 2007 Nobuhiro Iwamatsu
- *
- * PCI initialization for the NTT COMWARE L-BOX RE2
- */
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/init.h>
-#include <linux/pci.h>
-#include <linux/io.h>
-#include <mach/lboxre2.h>
-#include "pci-sh4.h"
-
-static char lboxre2_irq_tab[] __initdata = {
- IRQ_ETH0, IRQ_ETH1, IRQ_INTA, IRQ_INTD,
-};
-
-int __init pcibios_map_platform_irq(struct pci_dev *pdev, u8 slot, u8 pin)
-{
- return lboxre2_irq_tab[slot];
-}
-
-static struct resource sh7751_io_resource = {
- .name = "SH7751_IO",
- .start = SH7751_PCI_IO_BASE ,
- .end = SH7751_PCI_IO_BASE + SH7751_PCI_IO_SIZE - 1,
- .flags = IORESOURCE_IO
-};
-
-static struct resource sh7751_mem_resource = {
- .name = "SH7751_mem",
- .start = SH7751_PCI_MEMORY_BASE,
- .end = SH7751_PCI_MEMORY_BASE + SH7751_PCI_MEM_SIZE - 1,
- .flags = IORESOURCE_MEM
-};
-
-extern struct pci_ops sh7751_pci_ops;
-
-struct pci_channel board_pci_channels[] = {
- { &sh4_pci_ops, &sh7751_io_resource, &sh7751_mem_resource, 0, 0xff },
- { NULL, NULL, NULL, 0, 0 },
-};
-
-EXPORT_SYMBOL(board_pci_channels);
-
-static struct sh4_pci_address_map sh7751_pci_map = {
- .window0 = {
- .base = SH7751_CS3_BASE_ADDR,
- .size = 0x04000000,
- },
- .window1 = {
- .base = 0x00000000, /* Unused */
- .size = 0x00000000, /* Unused */
- },
- .flags = SH4_PCIC_NO_RESET,
-};
-
-int __init pcibios_init_platform(void)
-{
- return sh7751_pcic_init(&sh7751_pci_map);
-}
diff --git a/arch/sh/drivers/pci/ops-r7780rp.c b/arch/sh/drivers/pci/ops-r7780rp.c
deleted file mode 100644
index 8555238e63eb..000000000000
--- a/arch/sh/drivers/pci/ops-r7780rp.c
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Author: Ian DaSilva (idasilva@mvista.com)
- *
- * Highly leveraged from pci-bigsur.c, written by Dustin McIntire.
- *
- * May be copied or modified under the terms of the GNU General Public
- * License. See linux/COPYING for more information.
- *
- * PCI initialization for the Renesas SH7780 Highlander R7780RP-1 board
- */
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/pci.h>
-#include <mach/highlander.h>
-#include <asm/io.h>
-#include "pci-sh4.h"
-
-static char irq_tab[] __initdata = {
- 65, 66, 67, 68,
-};
-
-int __init pcibios_map_platform_irq(struct pci_dev *pdev, u8 slot, u8 pin)
-{
- return irq_tab[slot];
-}
-
-static struct resource sh7780_io_resource = {
- .name = "SH7780_IO",
- .start = SH7780_PCI_IO_BASE,
- .end = SH7780_PCI_IO_BASE + SH7780_PCI_IO_SIZE - 1,
- .flags = IORESOURCE_IO
-};
-
-static struct resource sh7780_mem_resource = {
- .name = "SH7780_mem",
- .start = SH7780_PCI_MEMORY_BASE,
- .end = SH7780_PCI_MEMORY_BASE + SH7780_PCI_MEM_SIZE - 1,
- .flags = IORESOURCE_MEM
-};
-
-extern struct pci_ops sh7780_pci_ops;
-
-struct pci_channel board_pci_channels[] = {
- { &sh4_pci_ops, &sh7780_io_resource, &sh7780_mem_resource, 0, 0xff },
- { NULL, NULL, NULL, 0, 0 },
-};
-EXPORT_SYMBOL(board_pci_channels);
-
-static struct sh4_pci_address_map sh7780_pci_map = {
- .window0 = {
- .base = SH7780_CS2_BASE_ADDR,
- .size = 0x04000000,
- },
-
- .window1 = {
- .base = SH7780_CS3_BASE_ADDR,
- .size = 0x04000000,
- },
-
- .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
deleted file mode 100644
index d6ca74b25d5f..000000000000
--- a/arch/sh/drivers/pci/ops-rts7751r2d.c
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * linux/arch/sh/drivers/pci/ops-rts7751r2d.c
- *
- * Author: Ian DaSilva (idasilva@mvista.com)
- *
- * Highly leveraged from pci-bigsur.c, written by Dustin McIntire.
- *
- * May be copied or modified under the terms of the GNU General Public
- * License. See linux/COPYING for more information.
- *
- * PCI initialization for the Renesas SH7751R RTS7751R2D board
- */
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/init.h>
-#include <linux/pci.h>
-#include <linux/io.h>
-#include <mach/r2d.h>
-#include "pci-sh4.h"
-
-static u8 rts7751r2d_irq_tab[] __initdata = {
- IRQ_PCI_INTA,
- IRQ_PCI_INTB,
- IRQ_PCI_INTC,
- IRQ_PCI_INTD,
-};
-
-int __init pcibios_map_platform_irq(struct pci_dev *pdev, u8 slot, u8 pin)
-{
- return rts7751r2d_irq_tab[slot];
-}
-
-static struct resource sh7751_io_resource = {
- .name = "SH7751_IO",
- .start = 0x4000,
- .end = SH7751_PCI_IO_SIZE - 1,
- .flags = IORESOURCE_IO
-};
-
-static struct resource sh7751_mem_resource = {
- .name = "SH7751_mem",
- .start = SH7751_PCI_MEMORY_BASE,
- .end = SH7751_PCI_MEMORY_BASE + SH7751_PCI_MEM_SIZE - 1,
- .flags = IORESOURCE_MEM
-};
-
-extern struct pci_ops sh7751_pci_ops;
-
-struct pci_channel board_pci_channels[] = {
- { &sh4_pci_ops, &sh7751_io_resource, &sh7751_mem_resource, 0, 0xff },
- { NULL, NULL, NULL, 0, 0 },
-};
-EXPORT_SYMBOL(board_pci_channels);
-
-static struct sh4_pci_address_map sh7751_pci_map = {
- .window0 = {
- .base = SH7751_CS3_BASE_ADDR,
- .size = 0x04000000,
- },
-
- .window1 = {
- .base = 0x00000000, /* Unused */
- .size = 0x00000000, /* Unused */
- },
-
- .flags = SH4_PCIC_NO_RESET,
-};
-
-int __init pcibios_init_platform(void)
-{
- __set_io_port_base(SH7751_PCI_IO_BASE);
- return sh7751_pcic_init(&sh7751_pci_map);
-}
-
diff --git a/arch/sh/drivers/pci/ops-sdk7780.c b/arch/sh/drivers/pci/ops-sdk7780.c
deleted file mode 100644
index 4dcc64184b23..000000000000
--- a/arch/sh/drivers/pci/ops-sdk7780.c
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * linux/arch/sh/drivers/pci/ops-sdk7780.c
- *
- * Copyright (C) 2006 Nobuhiro Iwamatsu
- *
- * PCI initialization for the SDK7780SE03
- *
- * 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 <mach/sdk7780.h>
-#include <asm/io.h>
-#include "pci-sh4.h"
-
-/* IDSEL [16][17][18][19][20][21][22][23][24][25][26][27][28][29][30][31] */
-static char sdk7780_irq_tab[4][16] __initdata = {
- /* INTA */
- { 65, 68, 67, 68, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
- /* INTB */
- { 66, 65, -1, 65, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
- /* INTC */
- { 67, 66, -1, 66, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
- /* INTD */
- { 68, 67, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
-};
-
-int __init pcibios_map_platform_irq(struct pci_dev *pdev, u8 slot, u8 pin)
-{
- return sdk7780_irq_tab[pin-1][slot];
-}
-
-static struct resource sdk7780_io_resource = {
- .name = "SH7780_IO",
- .start = SH7780_PCI_IO_BASE,
- .end = SH7780_PCI_IO_BASE + SH7780_PCI_IO_SIZE - 1,
- .flags = IORESOURCE_IO
-};
-
-static struct resource sdk7780_mem_resource = {
- .name = "SH7780_mem",
- .start = SH7780_PCI_MEMORY_BASE,
- .end = SH7780_PCI_MEMORY_BASE + SH7780_PCI_MEM_SIZE - 1,
- .flags = IORESOURCE_MEM
-};
-
-struct pci_channel board_pci_channels[] = {
- { &sh4_pci_ops, &sdk7780_io_resource, &sdk7780_mem_resource, 0, 0xff },
- { NULL, NULL, NULL, 0, 0 },
-};
-EXPORT_SYMBOL(board_pci_channels);
-
-static struct sh4_pci_address_map sdk7780_pci_map = {
- .window0 = {
- .base = SH7780_CS2_BASE_ADDR,
- .size = 0x04000000,
- },
- .window1 = {
- .base = SH7780_CS3_BASE_ADDR,
- .size = 0x04000000,
- },
- .flags = SH4_PCIC_NO_RESET,
-};
-
-int __init pcibios_init_platform(void)
-{
- printk(KERN_INFO "SH7780 PCI: Finished initializing PCI controller\n");
- return sh7780_pcic_init(&sdk7780_pci_map);
-}
diff --git a/arch/sh/drivers/pci/ops-se7780.c b/arch/sh/drivers/pci/ops-se7780.c
deleted file mode 100644
index 3145c62484d6..000000000000
--- a/arch/sh/drivers/pci/ops-se7780.c
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * linux/arch/sh/drivers/pci/ops-se7780.c
- *
- * Copyright (C) 2006 Nobuhiro Iwamatsu
- *
- * PCI initialization for the Hitachi UL Solution Engine 7780SE03
- *
- * 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 <mach-se/mach/se7780.h>
-#include <asm/io.h>
-#include "pci-sh4.h"
-
-/*
- * IDSEL = AD16 PCI slot
- * IDSEL = AD17 PCI slot
- * IDSEL = AD18 Serial ATA Controller (Silicon Image SiL3512A)
- * IDSEL = AD19 USB Host Controller (NEC uPD7210100A)
- */
-
-/* IDSEL [16][17][18][19][20][21][22][23][24][25][26][27][28][29][30][31] */
-static char se7780_irq_tab[4][16] __initdata = {
- /* INTA */
- { 65, 68, 67, 68, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
- /* INTB */
- { 66, 65, -1, 65, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
- /* INTC */
- { 67, 66, -1, 66, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
- /* INTD */
- { 68, 67, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
-};
-
-int __init pcibios_map_platform_irq(struct pci_dev *pdev, u8 slot, u8 pin)
-{
- return se7780_irq_tab[pin-1][slot];
-}
-
-static struct resource se7780_io_resource = {
- .name = "SH7780_IO",
- .start = SH7780_PCI_IO_BASE,
- .end = SH7780_PCI_IO_BASE + SH7780_PCI_IO_SIZE - 1,
- .flags = IORESOURCE_IO
-};
-
-static struct resource se7780_mem_resource = {
- .name = "SH7780_mem",
- .start = SH7780_PCI_MEMORY_BASE,
- .end = SH7780_PCI_MEMORY_BASE + SH7780_PCI_MEM_SIZE - 1,
- .flags = IORESOURCE_MEM
-};
-
-extern struct pci_ops se7780_pci_ops;
-
-struct pci_channel board_pci_channels[] = {
- { &sh4_pci_ops, &se7780_io_resource, &se7780_mem_resource, 0, 0xff },
- { NULL, NULL, NULL, 0, 0 },
-};
-EXPORT_SYMBOL(board_pci_channels);
-
-static struct sh4_pci_address_map se7780_pci_map = {
- .window0 = {
- .base = SH7780_CS2_BASE_ADDR,
- .size = 0x04000000,
- },
- .flags = SH4_PCIC_NO_RESET,
-};
-
-int __init pcibios_init_platform(void)
-{
- printk("SH7780 PCI: Finished initialization of the PCI controller\n");
-
- /*
- * FPGA PCISEL register initialize
- *
- * CPU || SLOT1 | SLOT2 | S-ATA | USB
- * -------------------------------------
- * INTA || INTA | INTD | -- | INTB
- * -------------------------------------
- * INTB || INTB | INTA | -- | INTC
- * -------------------------------------
- * INTC || INTC | INTB | INTA | --
- * -------------------------------------
- * INTD || INTD | INTC | -- | INTA
- * -------------------------------------
- */
- ctrl_outw(0x0013, FPGA_PCI_INTSEL1);
- ctrl_outw(0xE402, FPGA_PCI_INTSEL2);
-
- return sh7780_pcic_init(&se7780_pci_map);
-}
diff --git a/arch/sh/drivers/pci/ops-sh03.c b/arch/sh/drivers/pci/ops-sh03.c
deleted file mode 100644
index e1703ff5a4d2..000000000000
--- a/arch/sh/drivers/pci/ops-sh03.c
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * linux/arch/sh/drivers/pci/ops-sh03.c
- *
- * PCI initialization for the Interface CTP/PCI-SH03 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"
-
-/*
- * Description: This function sets up and initializes the pcic, sets
- * up the BARS, maps the DRAM into the address space etc, etc.
- */
-int __init pcibios_init_platform(void)
-{
- __set_io_port_base(SH7751_PCI_IO_BASE);
- return 1;
-}
-
-static struct resource sh7751_io_resource = {
- .name = "SH03 IO",
- .start = SH7751_PCI_IO_BASE,
- .end = SH7751_PCI_IO_BASE + SH7751_PCI_IO_SIZE - 1,
- .flags = IORESOURCE_IO
-};
-
-static struct resource sh7751_mem_resource = {
- .name = "SH03 mem",
- .start = SH7751_PCI_MEMORY_BASE,
- .end = SH7751_PCI_MEMORY_BASE + SH7751_PCI_MEM_SIZE - 1,
- .flags = IORESOURCE_MEM
-};
-
-extern struct pci_ops sh4_pci_ops;
-
-struct pci_channel board_pci_channels[] = {
- { &sh4_pci_ops, &sh7751_io_resource, &sh7751_mem_resource, 0, 0xff },
- { NULL, NULL, NULL, 0, 0 },
-};
-
diff --git a/arch/sh/drivers/pci/ops-sh4.c b/arch/sh/drivers/pci/ops-sh4.c
index 710a3b0306e5..78bebebdc99c 100644
--- a/arch/sh/drivers/pci/ops-sh4.c
+++ b/arch/sh/drivers/pci/ops-sh4.c
@@ -1,22 +1,22 @@
/*
* Generic SH-4 / SH-4A PCIC operations (SH7751, SH7780).
*
- * Copyright (C) 2002 - 2006 Paul Mundt
+ * 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 <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))
+ (P1SEG | (bus->number << 16) | (devfn << 8) | (where & ~3))
static DEFINE_SPINLOCK(sh4_pci_lock);
@@ -26,6 +26,7 @@ static DEFINE_SPINLOCK(sh4_pci_lock);
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;
@@ -34,8 +35,8 @@ static int sh4_pci_read(struct pci_bus *bus, unsigned int devfn,
* 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);
+ pci_write_reg(chan, CONFIG_CMD(bus, devfn, where), SH4_PCIPAR);
+ data = pci_read_reg(chan, SH4_PCIPDR);
spin_unlock_irqrestore(&sh4_pci_lock, flags);
switch (size) {
@@ -63,13 +64,14 @@ static int sh4_pci_read(struct pci_bus *bus, unsigned int devfn,
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;
spin_lock_irqsave(&sh4_pci_lock, flags);
- pci_write_reg(CONFIG_CMD(bus, devfn, where), SH4_PCIPAR);
- data = pci_read_reg(SH4_PCIPDR);
+ pci_write_reg(chan, CONFIG_CMD(bus, devfn, where), SH4_PCIPAR);
+ data = pci_read_reg(chan, SH4_PCIPDR);
spin_unlock_irqrestore(&sh4_pci_lock, flags);
switch (size) {
@@ -90,7 +92,7 @@ static int sh4_pci_write(struct pci_bus *bus, unsigned int devfn,
return PCIBIOS_FUNC_NOT_SUPPORTED;
}
- pci_write_reg(data, SH4_PCIPDR);
+ pci_write_reg(chan, data, SH4_PCIPDR);
return PCIBIOS_SUCCESSFUL;
}
@@ -104,66 +106,31 @@ struct pci_ops sh4_pci_ops = {
* 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)
+int __init sh4_pci_check_direct(struct pci_channel *chan)
{
/*
* Check if configuration works.
*/
- if (pci_probe & PCI_PROBE_CONF1) {
- unsigned int tmp = pci_read_reg(SH4_PCIPAR);
-
- pci_write_reg(P1SEG, SH4_PCIPAR);
+ unsigned int tmp = pci_read_reg(chan, 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");
+ pci_write_reg(chan, P1SEG, SH4_PCIPAR);
- return 0;
- }
-
- pci_write_reg(tmp, SH4_PCIPAR);
+ if (pci_read_reg(chan, SH4_PCIPAR) == P1SEG) {
+ pci_write_reg(chan, tmp, SH4_PCIPAR);
+ printk(KERN_INFO "PCI: Using configuration type 1\n");
+ request_region(chan->reg_base + SH4_PCIPAR, 8,
+ "PCI conf1");
+ return 0;
}
- pr_debug("PCI: pci_check_direct failed\n");
- return -EINVAL;
-}
+ pci_write_reg(chan, tmp, SH4_PCIPAR);
-/* Handle generic fixups */
-static void __init pci_fixup_ide_bases(struct pci_dev *d)
-{
- int i;
+ printk(KERN_ERR "PCI: %s failed\n", __func__);
- /*
- * 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 * __devinit pcibios_setup(char *str)
-{
- if (!strcmp(str, "off")) {
- pci_probe = 0;
- return NULL;
- }
-
- return str;
+ return -EINVAL;
}
-int __attribute__((weak)) pci_fixup_pcic(void)
+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
index 729e38a6fe07..4ce95a001b80 100644
--- a/arch/sh/drivers/pci/ops-sh5.c
+++ b/arch/sh/drivers/pci/ops-sh5.c
@@ -22,31 +22,6 @@
#include <asm/io.h>
#include "pci-sh5.h"
-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;
- printk("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 * __devinit pcibios_setup(char *str)
-{
- return str;
-}
-
static int sh5pci_read(struct pci_bus *bus, unsigned int devfn, int where,
int size, u32 *val)
{
diff --git a/arch/sh/drivers/pci/ops-sh7785lcr.c b/arch/sh/drivers/pci/ops-sh7785lcr.c
deleted file mode 100644
index fb0869f0bef8..000000000000
--- a/arch/sh/drivers/pci/ops-sh7785lcr.c
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Author: Ian DaSilva (idasilva@mvista.com)
- *
- * Highly leveraged from pci-bigsur.c, written by Dustin McIntire.
- *
- * May be copied or modified under the terms of the GNU General Public
- * License. See linux/COPYING for more information.
- *
- * PCI initialization for the Renesas R0P7785LC0011RL board
- * Based on arch/sh/drivers/pci/ops-r7780rp.c
- *
- */
-#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 char irq_tab[] __initdata = {
- 65, 66, 67, 68,
-};
-
-int __init pcibios_map_platform_irq(struct pci_dev *pdev, u8 slot, u8 pin)
-{
- return irq_tab[slot];
-}
-
-static struct resource sh7785_io_resource = {
- .name = "SH7785_IO",
- .start = SH7780_PCI_IO_BASE,
- .end = SH7780_PCI_IO_BASE + SH7780_PCI_IO_SIZE - 1,
- .flags = IORESOURCE_IO
-};
-
-static struct resource sh7785_mem_resource = {
- .name = "SH7785_mem",
- .start = SH7780_PCI_MEMORY_BASE,
- .end = SH7780_PCI_MEMORY_BASE + SH7780_PCI_MEM_SIZE - 1,
- .flags = IORESOURCE_MEM
-};
-
-struct pci_channel board_pci_channels[] = {
- { &sh4_pci_ops, &sh7785_io_resource, &sh7785_mem_resource, 0, 0xff },
- { NULL, NULL, NULL, 0, 0 },
-};
-EXPORT_SYMBOL(board_pci_channels);
-
-static struct sh4_pci_address_map sh7785_pci_map = {
- .window0 = {
-#if defined(CONFIG_32BIT)
- .base = SH7780_32BIT_DDR_BASE_ADDR,
- .size = 0x40000000,
-#else
- .base = SH7780_CS0_BASE_ADDR,
- .size = 0x20000000,
-#endif
- },
-
- .flags = SH4_PCIC_NO_RESET,
-};
-
-int __init pcibios_init_platform(void)
-{
- return sh7780_pcic_init(&sh7785_pci_map);
-}
diff --git a/arch/sh/drivers/pci/ops-snapgear.c b/arch/sh/drivers/pci/ops-snapgear.c
deleted file mode 100644
index 53dd893d4e54..000000000000
--- a/arch/sh/drivers/pci/ops-snapgear.c
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * 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 "pci-sh4.h"
-
-#define SNAPGEAR_PCI_IO 0x4000
-#define SNAPGEAR_PCI_MEM 0xfd000000
-
-/* PCI: default LOCAL memory window sizes (seen from PCI bus) */
-#define SNAPGEAR_LSR0_SIZE (64*(1<<20)) //64MB
-#define SNAPGEAR_LSR1_SIZE (64*(1<<20)) //64MB
-
-static struct resource sh7751_io_resource = {
- .name = "SH7751 IO",
- .start = SNAPGEAR_PCI_IO,
- .end = SNAPGEAR_PCI_IO + (64*1024) - 1, /* 64KiB I/O */
- .flags = IORESOURCE_IO,
-};
-
-static struct resource sh7751_mem_resource = {
- .name = "SH7751 mem",
- .start = SNAPGEAR_PCI_MEM,
- .end = SNAPGEAR_PCI_MEM + (64*1024*1024) - 1, /* 64MiB mem */
- .flags = IORESOURCE_MEM,
-};
-
-struct pci_channel board_pci_channels[] = {
- { &sh4_pci_ops, &sh7751_io_resource, &sh7751_mem_resource, 0, 0xff },
- { 0, }
-};
-
-static struct sh4_pci_address_map sh7751_pci_map = {
- .window0 = {
- .base = SH7751_CS2_BASE_ADDR,
- .size = SNAPGEAR_LSR0_SIZE,
- },
-
- .window1 = {
- .base = SH7751_CS2_BASE_ADDR,
- .size = SNAPGEAR_LSR1_SIZE,
- },
-
- .flags = SH4_PCIC_NO_RESET,
-};
-
-/*
- * 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
- */
-int __init pcibios_init_platform(void)
-{
- return sh7751_pcic_init(&sh7751_pci_map);
-}
-
-int __init pcibios_map_platform_irq(struct pci_dev *pdev, u8 slot, u8 pin)
-{
- int irq = -1;
-
- switch (slot) {
- case 8: /* the PCI bridge */ break;
- case 11: irq = 8; break; /* USB */
- case 12: irq = 11; break; /* PCMCIA */
- case 13: irq = 5; break; /* eth0 */
- case 14: irq = 8; break; /* eth1 */
- case 15: irq = 11; break; /* safenet (unused) */
- }
-
- printk("PCI: Mapping SnapGear IRQ for slot %d, pin %c to irq %d\n",
- slot, pin - 1 + 'A', irq);
-
- return irq;
-}
-
-void __init pcibios_fixup(void)
-{
- /* Nothing to fixup .. */
-}
diff --git a/arch/sh/drivers/pci/pci-auto.c b/arch/sh/drivers/pci/pci-auto.c
deleted file mode 100644
index cf48b12ee58c..000000000000
--- a/arch/sh/drivers/pci/pci-auto.c
+++ /dev/null
@@ -1,545 +0,0 @@
-/*
- * PCI autoconfiguration library
- *
- * Author: Matt Porter <mporter@mvista.com>
- *
- * Copyright 2000, 2001 MontaVista Software Inc.
- * Copyright 2001 Bradley D. LaRonde <brad@ltc.com>
- * Copyright 2003 Paul Mundt <lethal@linux-sh.org>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- */
-
-/*
- * Modified for MIPS by Jun Sun, jsun@mvista.com
- *
- * . Simplify the interface between pci_auto and the rest: a single function.
- * . Assign resources from low address to upper address.
- * . change most int to u32.
- *
- * Further modified to include it as mips generic code, ppopov@mvista.com.
- *
- * 2001-10-26 Bradley D. LaRonde <brad@ltc.com>
- * - Add a top_bus argument to the "early config" functions so that
- * they can set a fake parent bus pointer to convince the underlying
- * pci ops to use type 1 configuration for sub busses.
- * - Set bridge base and limit registers correctly.
- * - Align io and memory base properly before and after bridge setup.
- * - Don't fall through to pci_setup_bars for bridge.
- * - Reformat the debug output to look more like lspci's output.
- *
- * Cloned for SuperH by M. R. Brown, mrbrown@0xd6.org
- *
- * 2003-08-05 Paul Mundt <lethal@linux-sh.org>
- * - Don't update the BAR values on systems that already have valid addresses
- * and don't want these updated for whatever reason, by way of a new config
- * option check. However, we still read in the old BAR values so that they
- * can still be reported through the debug output.
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/types.h>
-#include <linux/pci.h>
-
-#define DEBUG
-#ifdef DEBUG
-#define DBG(x...) printk(x)
-#else
-#define DBG(x...)
-#endif
-
-/*
- * 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.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) \
-static int 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)
-
-static struct resource *io_resource_inuse;
-static struct resource *mem_resource_inuse;
-
-static u32 pciauto_lower_iospc;
-static u32 pciauto_upper_iospc;
-
-static u32 pciauto_lower_memspc;
-static u32 pciauto_upper_memspc;
-
-static void __init
-pciauto_setup_bars(struct pci_channel *hose,
- int top_bus,
- int current_bus,
- int pci_devfn,
- int bar_limit)
-{
- u32 bar_response, bar_size, bar_value;
- u32 bar, addr_mask, bar_nr = 0;
- u32 * upper_limit;
- u32 * lower_limit;
- int found_mem64 = 0;
-
- for (bar = PCI_BASE_ADDRESS_0; bar <= bar_limit; bar+=4) {
- u32 bar_addr;
-
- /* Read the old BAR value */
- early_read_config_dword(hose, top_bus,
- current_bus,
- pci_devfn,
- bar,
- &bar_addr);
-
- /* Tickle the BAR and get the response */
- early_write_config_dword(hose, top_bus,
- current_bus,
- pci_devfn,
- bar,
- 0xffffffff);
-
- early_read_config_dword(hose, top_bus,
- current_bus,
- pci_devfn,
- bar,
- &bar_response);
-
- /*
- * Write the old BAR value back out, only update the BAR
- * if we implicitly want resources to be updated, which
- * is done by the generic code further down. -- PFM.
- */
- early_write_config_dword(hose, top_bus,
- current_bus,
- pci_devfn,
- bar,
- bar_addr);
-
- /* If BAR is not implemented go to the next BAR */
- if (!bar_response)
- continue;
-
- /*
- * Workaround for a BAR that doesn't use its upper word,
- * like the ALi 1535D+ PCI DC-97 Controller Modem (M5457).
- * bdl <brad@ltc.com>
- */
- if (!(bar_response & 0xffff0000))
- bar_response |= 0xffff0000;
-
-retry:
- /* Check the BAR type and set our address mask */
- if (bar_response & PCI_BASE_ADDRESS_SPACE) {
- addr_mask = PCI_BASE_ADDRESS_IO_MASK;
- upper_limit = &pciauto_upper_iospc;
- lower_limit = &pciauto_lower_iospc;
- DBG(" I/O");
- } else {
- if ((bar_response & PCI_BASE_ADDRESS_MEM_TYPE_MASK) ==
- PCI_BASE_ADDRESS_MEM_TYPE_64)
- found_mem64 = 1;
-
- addr_mask = PCI_BASE_ADDRESS_MEM_MASK;
- upper_limit = &pciauto_upper_memspc;
- lower_limit = &pciauto_lower_memspc;
- DBG(" Mem");
- }
-
-
- /* Calculate requested size */
- bar_size = ~(bar_response & addr_mask) + 1;
-
- /* Allocate a base address */
- bar_value = ((*lower_limit - 1) & ~(bar_size - 1)) + bar_size;
-
- if ((bar_value + bar_size) > *upper_limit) {
- if (bar_response & PCI_BASE_ADDRESS_SPACE) {
- if (io_resource_inuse->child) {
- io_resource_inuse =
- io_resource_inuse->child;
- pciauto_lower_iospc =
- io_resource_inuse->start;
- pciauto_upper_iospc =
- io_resource_inuse->end + 1;
- goto retry;
- }
-
- } else {
- if (mem_resource_inuse->child) {
- mem_resource_inuse =
- mem_resource_inuse->child;
- pciauto_lower_memspc =
- mem_resource_inuse->start;
- pciauto_upper_memspc =
- mem_resource_inuse->end + 1;
- goto retry;
- }
- }
- DBG(" unavailable -- skipping, value %x size %x\n",
- bar_value, bar_size);
- continue;
- }
-
- if (bar_value < *lower_limit || (bar_value + bar_size) >= *upper_limit) {
- DBG(" unavailable -- skipping, value %x size %x\n",
- bar_value, bar_size);
- continue;
- }
-
-#ifdef CONFIG_PCI_AUTO_UPDATE_RESOURCES
- /* Write it out and update our limit */
- early_write_config_dword(hose, top_bus, current_bus, pci_devfn,
- bar, bar_value);
-#endif
-
- *lower_limit = bar_value + bar_size;
-
- /*
- * If we are a 64-bit decoder then increment to the
- * upper 32 bits of the bar and force it to locate
- * in the lower 4GB of memory.
- */
- if (found_mem64) {
- bar += 4;
- early_write_config_dword(hose, top_bus,
- current_bus,
- pci_devfn,
- bar,
- 0x00000000);
- }
-
- DBG(" at 0x%.8x [size=0x%x]\n", bar_value, bar_size);
-
- bar_nr++;
- }
-
-}
-
-static void __init
-pciauto_prescan_setup_bridge(struct pci_channel *hose,
- int top_bus,
- int current_bus,
- int pci_devfn,
- int sub_bus)
-{
- /* Configure bus number registers */
- early_write_config_byte(hose, top_bus, current_bus, pci_devfn,
- PCI_PRIMARY_BUS, current_bus);
- early_write_config_byte(hose, top_bus, current_bus, pci_devfn,
- PCI_SECONDARY_BUS, sub_bus + 1);
- early_write_config_byte(hose, top_bus, current_bus, pci_devfn,
- PCI_SUBORDINATE_BUS, 0xff);
-
- /* Align memory and I/O to 1MB and 4KB boundaries. */
- pciauto_lower_memspc = (pciauto_lower_memspc + (0x100000 - 1))
- & ~(0x100000 - 1);
- pciauto_lower_iospc = (pciauto_lower_iospc + (0x1000 - 1))
- & ~(0x1000 - 1);
-
- /* Set base (lower limit) of address range behind bridge. */
- early_write_config_word(hose, top_bus, current_bus, pci_devfn,
- PCI_MEMORY_BASE, pciauto_lower_memspc >> 16);
- early_write_config_byte(hose, top_bus, current_bus, pci_devfn,
- PCI_IO_BASE, (pciauto_lower_iospc & 0x0000f000) >> 8);
- early_write_config_word(hose, top_bus, current_bus, pci_devfn,
- PCI_IO_BASE_UPPER16, pciauto_lower_iospc >> 16);
-
- /* We don't support prefetchable memory for now, so disable */
- early_write_config_word(hose, top_bus, current_bus, pci_devfn,
- PCI_PREF_MEMORY_BASE, 0);
- early_write_config_word(hose, top_bus, current_bus, pci_devfn,
- PCI_PREF_MEMORY_LIMIT, 0);
-}
-
-static void __init
-pciauto_postscan_setup_bridge(struct pci_channel *hose,
- int top_bus,
- int current_bus,
- int pci_devfn,
- int sub_bus)
-{
- u32 temp;
-
- /*
- * [jsun] we always bump up baselines a little, so that if there
- * nothing behind P2P bridge, we don't wind up overlapping IO/MEM
- * spaces.
- */
- pciauto_lower_memspc += 1;
- pciauto_lower_iospc += 1;
-
- /* Configure bus number registers */
- early_write_config_byte(hose, top_bus, current_bus, pci_devfn,
- PCI_SUBORDINATE_BUS, sub_bus);
-
- /* Set upper limit of address range behind bridge. */
- early_write_config_word(hose, top_bus, current_bus, pci_devfn,
- PCI_MEMORY_LIMIT, pciauto_lower_memspc >> 16);
- early_write_config_byte(hose, top_bus, current_bus, pci_devfn,
- PCI_IO_LIMIT, (pciauto_lower_iospc & 0x0000f000) >> 8);
- early_write_config_word(hose, top_bus, current_bus, pci_devfn,
- PCI_IO_LIMIT_UPPER16, pciauto_lower_iospc >> 16);
-
- /* Align memory and I/O to 1MB and 4KB boundaries. */
- pciauto_lower_memspc = (pciauto_lower_memspc + (0x100000 - 1))
- & ~(0x100000 - 1);
- pciauto_lower_iospc = (pciauto_lower_iospc + (0x1000 - 1))
- & ~(0x1000 - 1);
-
- /* Enable memory and I/O accesses, enable bus master */
- early_read_config_dword(hose, top_bus, current_bus, pci_devfn,
- PCI_COMMAND, &temp);
- early_write_config_dword(hose, top_bus, current_bus, pci_devfn,
- PCI_COMMAND, temp | PCI_COMMAND_IO | PCI_COMMAND_MEMORY
- | PCI_COMMAND_MASTER);
-}
-
-static void __init
-pciauto_prescan_setup_cardbus_bridge(struct pci_channel *hose,
- int top_bus,
- int current_bus,
- int pci_devfn,
- int sub_bus)
-{
- /* Configure bus number registers */
- early_write_config_byte(hose, top_bus, current_bus, pci_devfn,
- PCI_PRIMARY_BUS, current_bus);
- early_write_config_byte(hose, top_bus, current_bus, pci_devfn,
- PCI_SECONDARY_BUS, sub_bus + 1);
- early_write_config_byte(hose, top_bus, current_bus, pci_devfn,
- PCI_SUBORDINATE_BUS, 0xff);
-
- /* Align memory and I/O to 4KB and 4 byte boundaries. */
- pciauto_lower_memspc = (pciauto_lower_memspc + (0x1000 - 1))
- & ~(0x1000 - 1);
- pciauto_lower_iospc = (pciauto_lower_iospc + (0x4 - 1))
- & ~(0x4 - 1);
-
- early_write_config_dword(hose, top_bus, current_bus, pci_devfn,
- PCI_CB_MEMORY_BASE_0, pciauto_lower_memspc);
- early_write_config_dword(hose, top_bus, current_bus, pci_devfn,
- PCI_CB_IO_BASE_0, pciauto_lower_iospc);
-}
-
-static void __init
-pciauto_postscan_setup_cardbus_bridge(struct pci_channel *hose,
- int top_bus,
- int current_bus,
- int pci_devfn,
- int sub_bus)
-{
- u32 temp;
-
- /*
- * [jsun] we always bump up baselines a little, so that if there
- * nothing behind P2P bridge, we don't wind up overlapping IO/MEM
- * spaces.
- */
- pciauto_lower_memspc += 1;
- pciauto_lower_iospc += 1;
-
- /*
- * Configure subordinate bus number. The PCI subsystem
- * bus scan will renumber buses (reserving three additional
- * for this PCI<->CardBus bridge for the case where a CardBus
- * adapter contains a P2P or CB2CB bridge.
- */
-
- early_write_config_byte(hose, top_bus, current_bus, pci_devfn,
- PCI_SUBORDINATE_BUS, sub_bus);
-
- /*
- * Reserve an additional 4MB for mem space and 16KB for
- * I/O space. This should cover any additional space
- * requirement of unusual CardBus devices with
- * additional bridges that can consume more address space.
- *
- * Although pcmcia-cs currently will reprogram bridge
- * windows, the goal is to add an option to leave them
- * alone and use the bridge window ranges as the regions
- * that are searched for free resources upon hot-insertion
- * of a device. This will allow a PCI<->CardBus bridge
- * configured by this routine to happily live behind a
- * P2P bridge in a system.
- */
- /* Align memory and I/O to 4KB and 4 byte boundaries. */
- pciauto_lower_memspc = (pciauto_lower_memspc + (0x1000 - 1))
- & ~(0x1000 - 1);
- pciauto_lower_iospc = (pciauto_lower_iospc + (0x4 - 1))
- & ~(0x4 - 1);
- /* Set up memory and I/O filter limits, assume 32-bit I/O space */
- early_write_config_dword(hose, top_bus, current_bus, pci_devfn,
- PCI_CB_MEMORY_LIMIT_0, pciauto_lower_memspc - 1);
- early_write_config_dword(hose, top_bus, current_bus, pci_devfn,
- PCI_CB_IO_LIMIT_0, pciauto_lower_iospc - 1);
-
- /* Enable memory and I/O accesses, enable bus master */
- early_read_config_dword(hose, top_bus, current_bus, pci_devfn,
- PCI_COMMAND, &temp);
- early_write_config_dword(hose, top_bus, current_bus, pci_devfn,
- PCI_COMMAND, temp | PCI_COMMAND_IO | PCI_COMMAND_MEMORY |
- PCI_COMMAND_MASTER);
-}
-
-#define PCIAUTO_IDE_MODE_MASK 0x05
-
-static int __init
-pciauto_bus_scan(struct pci_channel *hose, int top_bus, int current_bus)
-{
- int sub_bus;
- u32 pci_devfn, pci_class, cmdstat, found_multi=0;
- unsigned short vid, did;
- unsigned char header_type;
- int devfn_start = 0;
- int devfn_stop = 0xff;
-
- sub_bus = current_bus;
-
- if (hose->first_devfn)
- devfn_start = hose->first_devfn;
- if (hose->last_devfn)
- devfn_stop = hose->last_devfn;
-
- for (pci_devfn=devfn_start; pci_devfn<devfn_stop; pci_devfn++) {
-
- if (PCI_FUNC(pci_devfn) && !found_multi)
- continue;
-
- early_read_config_word(hose, top_bus, current_bus, pci_devfn,
- PCI_VENDOR_ID, &vid);
-
- if (vid == 0xffff) continue;
-
- early_read_config_byte(hose, top_bus, current_bus, pci_devfn,
- PCI_HEADER_TYPE, &header_type);
-
- if (!PCI_FUNC(pci_devfn))
- found_multi = header_type & 0x80;
-
- early_read_config_word(hose, top_bus, current_bus, pci_devfn,
- PCI_DEVICE_ID, &did);
-
- early_read_config_dword(hose, top_bus, current_bus, pci_devfn,
- PCI_CLASS_REVISION, &pci_class);
-
- DBG("%.2x:%.2x.%x Class %.4x: %.4x:%.4x",
- current_bus, PCI_SLOT(pci_devfn), PCI_FUNC(pci_devfn),
- pci_class >> 16, vid, did);
- if (pci_class & 0xff)
- DBG(" (rev %.2x)", pci_class & 0xff);
- DBG("\n");
-
- if ((pci_class >> 16) == PCI_CLASS_BRIDGE_PCI) {
- DBG(" Bridge: primary=%.2x, secondary=%.2x\n",
- current_bus, sub_bus + 1);
- 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",
- sub_bus + 1,
- pciauto_lower_iospc, pciauto_lower_memspc);
- sub_bus = pciauto_bus_scan(hose, top_bus, sub_bus+1);
- DBG("Back to bus %.2x\n", current_bus);
- pciauto_postscan_setup_bridge(hose, top_bus, current_bus,
- pci_devfn, sub_bus);
- continue;
- } else if ((pci_class >> 16) == PCI_CLASS_BRIDGE_CARDBUS) {
- DBG(" CARDBUS Bridge: primary=%.2x, secondary=%.2x\n",
- current_bus, sub_bus + 1);
- DBG("PCI Autoconfig: Found CardBus bridge, device %d function %d\n", PCI_SLOT(pci_devfn), PCI_FUNC(pci_devfn));
- /* Place CardBus Socket/ExCA registers */
- pciauto_setup_bars(hose, top_bus, current_bus, pci_devfn, PCI_BASE_ADDRESS_0);
-
- pciauto_prescan_setup_cardbus_bridge(hose, top_bus,
- current_bus, pci_devfn, sub_bus);
-
- DBG("Scanning sub bus %.2x, I/O 0x%.8x, Mem 0x%.8x\n",
- sub_bus + 1,
- pciauto_lower_iospc, pciauto_lower_memspc);
- sub_bus = pciauto_bus_scan(hose, top_bus, sub_bus+1);
- DBG("Back to bus %.2x, sub_bus is %x\n", current_bus, sub_bus);
- pciauto_postscan_setup_cardbus_bridge(hose, top_bus,
- current_bus, pci_devfn, sub_bus);
- continue;
- } else if ((pci_class >> 16) == PCI_CLASS_STORAGE_IDE) {
-
- unsigned char prg_iface;
-
- early_read_config_byte(hose, top_bus, current_bus,
- pci_devfn, PCI_CLASS_PROG, &prg_iface);
- if (!(prg_iface & PCIAUTO_IDE_MODE_MASK)) {
- DBG("Skipping legacy mode IDE controller\n");
- continue;
- }
- }
-
- /*
- * Found a peripheral, enable some standard
- * settings
- */
- early_read_config_dword(hose, top_bus, current_bus, pci_devfn,
- PCI_COMMAND, &cmdstat);
- early_write_config_dword(hose, top_bus, current_bus, pci_devfn,
- PCI_COMMAND, cmdstat | PCI_COMMAND_IO |
- PCI_COMMAND_MEMORY |
- PCI_COMMAND_MASTER);
- early_write_config_byte(hose, top_bus, current_bus, pci_devfn,
- PCI_LATENCY_TIMER, 0x80);
-
- /* Allocate PCI I/O and/or memory space */
- pciauto_setup_bars(hose, top_bus, current_bus, pci_devfn, PCI_BASE_ADDRESS_5);
- }
- return sub_bus;
-}
-
-int __init
-pciauto_assign_resources(int busno, struct pci_channel *hose)
-{
- /* setup resource limits */
- io_resource_inuse = hose->io_resource;
- mem_resource_inuse = hose->mem_resource;
-
- pciauto_lower_iospc = io_resource_inuse->start;
- pciauto_upper_iospc = io_resource_inuse->end + 1;
- pciauto_lower_memspc = mem_resource_inuse->start;
- pciauto_upper_memspc = mem_resource_inuse->end + 1;
- DBG("Autoconfig PCI channel 0x%p\n", hose);
- DBG("Scanning bus %.2x, I/O 0x%.8x:0x%.8x, Mem 0x%.8x:0x%.8x\n",
- busno, pciauto_lower_iospc, pciauto_upper_iospc,
- pciauto_lower_memspc, pciauto_upper_memspc);
-
- return pciauto_bus_scan(hose, busno, busno);
-}
diff --git a/arch/sh/drivers/pci/pci-dreamcast.c b/arch/sh/drivers/pci/pci-dreamcast.c
new file mode 100644
index 000000000000..210f9d4af141
--- /dev/null
+++ b/arch/sh/drivers/pci/pci-dreamcast.c
@@ -0,0 +1,102 @@
+/*
+ * 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_io_resource = {
+ .name = "GAPSPCI IO",
+ .start = GAPSPCI_BBA_CONFIG,
+ .end = GAPSPCI_BBA_CONFIG + GAPSPCI_BBA_CONFIG_SIZE - 1,
+ .flags = IORESOURCE_IO,
+};
+
+static struct resource gapspci_mem_resource = {
+ .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,
+ .io_resource = &gapspci_io_resource,
+ .io_offset = 0x00000000,
+ .mem_resource = &gapspci_mem_resource,
+ .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);
+
+ register_pci_controller(&dreamcast_pci_controller);
+
+ return 0;
+}
+arch_initcall(gapspci_init);
diff --git a/arch/sh/drivers/pci/pci-sh4.h b/arch/sh/drivers/pci/pci-sh4.h
index a83dcf70c13b..3d5296cde622 100644
--- a/arch/sh/drivers/pci/pci-sh4.h
+++ b/arch/sh/drivers/pci/pci-sh4.h
@@ -149,13 +149,10 @@
#define SH4_PCIPDTR_PB0 0x000000001 /* Port 0 Enable */
#define SH4_PCIPDR 0x220 /* Port IO Data Register */
-/* Flags */
-#define SH4_PCIC_NO_RESET 0x0001
-
/* arch/sh/kernel/drivers/pci/ops-sh4.c */
extern struct pci_ops sh4_pci_ops;
-int sh4_pci_check_direct(void);
-int pci_fixup_pcic(void);
+int sh4_pci_check_direct(struct pci_channel *chan);
+int pci_fixup_pcic(struct pci_channel *chan);
struct sh4_pci_address_space {
unsigned long base;
@@ -165,16 +162,18 @@ struct sh4_pci_address_space {
struct sh4_pci_address_map {
struct sh4_pci_address_space window0;
struct sh4_pci_address_space window1;
- unsigned long flags;
};
-static inline void pci_write_reg(unsigned long val, unsigned long reg)
+static inline void pci_write_reg(struct pci_channel *chan,
+ unsigned long val, unsigned long reg)
{
- ctrl_outl(val, PCI_REG(reg));
+ ctrl_outl(val, chan->reg_base + reg);
}
-static inline unsigned long pci_read_reg(unsigned long reg)
+static inline unsigned long pci_read_reg(struct pci_channel *chan,
+ unsigned long reg)
{
- return ctrl_inl(PCI_REG(reg));
+ return ctrl_inl(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
index 7a97438762c8..873ed2b44055 100644
--- a/arch/sh/drivers/pci/pci-sh5.c
+++ b/arch/sh/drivers/pci/pci-sh5.c
@@ -89,8 +89,21 @@ static irqreturn_t pcish5_serr_irq(int irq, void *dev_id)
return IRQ_NONE;
}
-int __init sh5pci_init(unsigned long memStart, unsigned long memSize)
+static struct resource sh5_io_resource = { /* place holder */ };
+static struct resource sh5_mem_resource = { /* place holder */ };
+
+static struct pci_channel sh5pci_controller = {
+ .pci_ops = &sh5_pci_ops,
+ .mem_resource = &sh5_mem_resource,
+ .mem_offset = 0x00000000,
+ .io_resource = &sh5_io_resource,
+ .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;
@@ -106,12 +119,12 @@ int __init sh5pci_init(unsigned long memStart, unsigned long memSize)
return -EINVAL;
}
- pcicr_virt = onchip_remap(SH5PCI_ICR_BASE, 1024, "PCICR");
+ pcicr_virt = (unsigned long)ioremap_nocache(SH5PCI_ICR_BASE, 1024);
if (!pcicr_virt) {
panic("Unable to remap PCICR\n");
}
- PCI_IO_AREA = onchip_remap(SH5PCI_IO_BASE, 0x10000, "PCIIO");
+ PCI_IO_AREA = (unsigned long)ioremap_nocache(SH5PCI_IO_BASE, 0x10000);
if (!PCI_IO_AREA) {
panic("Unable to remap PCIIO\n");
}
@@ -197,32 +210,14 @@ int __init sh5pci_init(unsigned long memStart, unsigned long memSize)
SH5PCI_WRITE(AINTM, ~0);
SH5PCI_WRITE(PINTM, ~0);
- return 0;
-}
+ sh5_io_resource.start = PCI_IO_AREA;
+ sh5_io_resource.end = PCI_IO_AREA + 0x10000;
-void __devinit pcibios_fixup_bus(struct pci_bus *bus)
-{
- struct pci_dev *dev = bus->self;
- int i;
-
- if (dev) {
- for (i= 0; i < 3; i++) {
- bus->resource[i] =
- &dev->resource[PCI_BRIDGE_RESOURCES+i];
- bus->resource[i]->name = bus->name;
- }
- bus->resource[0]->flags |= IORESOURCE_IO;
- bus->resource[1]->flags |= IORESOURCE_MEM;
-
- /* For now, propagate host limits to the bus;
- * we'll adjust them later. */
- bus->resource[0]->end = 64*1024 - 1 ;
- bus->resource[1]->end = PCIBIOS_MIN_MEM+(256*1024*1024)-1;
- bus->resource[0]->start = PCIBIOS_MIN_IO;
- bus->resource[1]->start = PCIBIOS_MIN_MEM;
-
- /* Turn off downstream PF memory address range by default */
- bus->resource[2]->start = 1024*1024;
- bus->resource[2]->end = bus->resource[2]->start - 1;
- }
+ sh5_mem_resource.start = memStart;
+ sh5_mem_resource.end = memStart + memSize;
+
+ register_pci_controller(&sh5pci_controller);
+
+ return 0;
}
+arch_initcall(sh5pci_init);
diff --git a/arch/sh/drivers/pci/pci-sh5.h b/arch/sh/drivers/pci/pci-sh5.h
index 7cff3fc04d30..f277628221f3 100644
--- a/arch/sh/drivers/pci/pci-sh5.h
+++ b/arch/sh/drivers/pci/pci-sh5.h
@@ -107,7 +107,4 @@ extern unsigned long pcicr_virt;
extern struct pci_ops sh5_pci_ops;
-/* arch/sh/drivers/pci/pci-sh5.c */
-int sh5pci_init(unsigned long memStart, unsigned long memSize);
-
#endif /* __PCI_SH5_H */
diff --git a/arch/sh/drivers/pci/pci-sh7751.c b/arch/sh/drivers/pci/pci-sh7751.c
index 3065eb184f01..70c1999a0ec4 100644
--- a/arch/sh/drivers/pci/pci-sh7751.c
+++ b/arch/sh/drivers/pci/pci-sh7751.c
@@ -1,88 +1,100 @@
/*
- * Low-Level PCI Support for the SH7751
+ * Low-Level PCI Support for the SH7751
*
- * Dustin McIntire (dustin@sensoria.com)
- * Derived from arch/i386/kernel/pci-*.c which bore the message:
- * (c) 1999--2000 Martin Mares <mj@ucw.cz>
+ * Copyright (C) 2003 - 2009 Paul Mundt
+ * Copyright (C) 2001 Dustin McIntire
*
- * Ported to the new API by Paul Mundt <lethal@linux-sh.org>
- * With cleanup by Paul van Gool <pvangool@mimotech.com>
- *
- * May be copied or modified under the terms of the GNU General Public
- * License. See linux/COPYING for more information.
+ * 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.
*/
-#undef DEBUG
-
#include <linux/init.h>
#include <linux/pci.h>
#include <linux/types.h>
#include <linux/errno.h>
-#include <linux/delay.h>
+#include <linux/io.h>
#include "pci-sh4.h"
#include <asm/addrspace.h>
-#include <asm/io.h>
-/*
- * Initialization. Try all known PCI access methods. Note that we support
- * using both PCI BIOS and direct access: in such cases, we use I/O ports
- * to access config space.
- *
- * Note that the platform specific initialization (BSC registers, and memory
- * space mapping) will be called via the platform defined function
- * pcibios_init_platform().
- */
-static int __init sh7751_pci_init(void)
+static int __init __area_sdram_check(struct pci_channel *chan,
+ unsigned int area)
{
- unsigned int id;
- int ret;
-
- pr_debug("PCI: Starting intialization.\n");
+ unsigned long word;
- /* check for SH7751/SH7751R hardware */
- id = pci_read_reg(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;
- }
-
- if ((ret = sh4_pci_check_direct()) != 0)
- return ret;
-
- return pcibios_init_platform();
-}
-subsys_initcall(sh7751_pci_init);
-
-static int __init __area_sdram_check(unsigned int area)
-{
- u32 word;
-
- word = ctrl_inl(SH7751_BCR1);
+ 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%x\n",
+ printk("PCI: Area %d is not configured for SDRAM. BCR1=0x%lx\n",
area, word);
return 0;
}
- pci_write_reg(word, SH4_PCIBCR1);
+ pci_write_reg(chan, word, SH4_PCIBCR1);
- word = (u16)ctrl_inw(SH7751_BCR2);
+ 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%x\n",
+ printk("PCI: Area %d is not 32 bit SDRAM. BCR2=0x%lx\n",
area, word);
return 0;
}
- pci_write_reg(word, SH4_PCIBCR2);
+ pci_write_reg(chan, word, SH4_PCIBCR2);
return 1;
}
-int __init sh7751_pcic_init(struct sh4_pci_address_map *map)
+static struct resource sh7751_io_resource = {
+ .name = "SH7751_IO",
+ .start = SH7751_PCI_IO_BASE,
+ .end = SH7751_PCI_IO_BASE + SH7751_PCI_IO_SIZE - 1,
+ .flags = IORESOURCE_IO
+};
+
+static struct resource sh7751_mem_resource = {
+ .name = "SH7751_mem",
+ .start = SH7751_PCI_MEMORY_BASE,
+ .end = SH7751_PCI_MEMORY_BASE + SH7751_PCI_MEM_SIZE - 1,
+ .flags = IORESOURCE_MEM
+};
+
+static struct pci_channel sh7751_pci_controller = {
+ .pci_ops = &sh4_pci_ops,
+ .mem_resource = &sh7751_mem_resource,
+ .mem_offset = 0x00000000,
+ .io_resource = &sh7751_io_resource,
+ .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)
{
- u32 reg;
- u32 word;
+ struct pci_channel *chan = &sh7751_pci_controller;
+ unsigned int id;
+ u32 word, reg;
+ int ret;
+
+ printk(KERN_NOTICE "PCI: Starting intialization.\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;
+ }
+
+ if ((ret = sh4_pci_check_direct(chan)) != 0)
+ return ret;
/* Set the BCR's to enable PCI access */
reg = ctrl_inl(SH7751_BCR1);
@@ -90,25 +102,10 @@ int __init sh7751_pcic_init(struct sh4_pci_address_map *map)
ctrl_outl(reg, SH7751_BCR1);
/* Turn the clocks back on (not done in reset)*/
- pci_write_reg(0, SH4_PCICLKR);
+ 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(word, SH4_PCIPINT);
-
- /*
- * This code is unused for some boards as it is done in the
- * bootloader and doing it here means the MAC addresses loaded
- * by the bootloader get lost.
- */
- if (!(map->flags & SH4_PCIC_NO_RESET)) {
- /* toggle PCI reset pin */
- word = SH4_PCICR_PREFIX | SH4_PCICR_PRST;
- pci_write_reg(word, SH4_PCICR);
- /* Wait for a long time... not 1 sec. but long enough */
- mdelay(100);
- word = SH4_PCICR_PREFIX;
- pci_write_reg(word, SH4_PCICR);
- }
+ pci_write_reg(chan, word, SH4_PCIPINT);
/* set the command/status bits to:
* Wait Cycle Control + Parity Enable + Bus Master +
@@ -116,89 +113,75 @@ int __init sh7751_pcic_init(struct sh4_pci_address_map *map)
*/
word = SH7751_PCICONF1_WCC | SH7751_PCICONF1_PER |
SH7751_PCICONF1_BUM | SH7751_PCICONF1_MES;
- pci_write_reg(word, SH7751_PCICONF1);
+ pci_write_reg(chan, word, SH7751_PCICONF1);
/* define this host as the host bridge */
word = PCI_BASE_CLASS_BRIDGE << 24;
- pci_write_reg(word, SH7751_PCICONF2);
+ 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
- * Window0 = map->window0.size @ non-cached area base = SDRAM
- * Window1 = map->window1.size @ cached area base = SDRAM
*/
- word = map->window0.size - 1;
- pci_write_reg(word, SH4_PCILSR0);
- word = map->window1.size - 1;
- pci_write_reg(word, SH4_PCILSR1);
+ 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(map->window0.base);
- pci_write_reg(word, SH4_PCILAR0);
- pci_write_reg(word, SH7751_PCICONF5);
- /* Set the values on window 1 PCI config registers */
- word = PHYSADDR(map->window1.base);
- pci_write_reg(word, SH4_PCILAR1);
- pci_write_reg(word, SH7751_PCICONF6);
+ 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 = PCIBIOS_MIN_MEM & SH4_PCIMBR_MASK;
+ word = chan->mem_resource->start & SH4_PCIMBR_MASK;
pr_debug("PCI: Setting upper bits of Memory window to 0x%x\n", word);
- pci_write_reg(word , SH4_PCIMBR);
-
- /* Map IO space into PCI IO window
- * The IO window is 64K-PCIBIOS_MIN_IO in size
- * IO addresses will be translated to the
- * PCI IO window base address
- */
- pr_debug("PCI: Mapping IO address 0x%x - 0x%x to base 0x%x\n",
- PCIBIOS_MIN_IO, (64 << 10),
- SH7751_PCI_IO_BASE + PCIBIOS_MIN_IO);
+ pci_write_reg(chan, word , SH4_PCIMBR);
/* Make sure the MSB's of IO window are set to access PCI space
* correctly */
- word = PCIBIOS_MIN_IO & SH4_PCIIOBR_MASK;
+ word = chan->io_resource->start & SH4_PCIIOBR_MASK;
pr_debug("PCI: Setting upper bits of IO window to 0x%x\n", word);
- pci_write_reg(word, SH4_PCIIOBR);
+ pci_write_reg(chan, word, SH4_PCIIOBR);
/* Set PCI WCRx, BCRx's, copy from BSC locations */
/* check BCR for SDRAM in specified area */
- switch (map->window0.base) {
- case SH7751_CS0_BASE_ADDR: word = __area_sdram_check(0); break;
- case SH7751_CS1_BASE_ADDR: word = __area_sdram_check(1); break;
- case SH7751_CS2_BASE_ADDR: word = __area_sdram_check(2); break;
- case SH7751_CS3_BASE_ADDR: word = __area_sdram_check(3); break;
- case SH7751_CS4_BASE_ADDR: word = __area_sdram_check(4); break;
- case SH7751_CS5_BASE_ADDR: word = __area_sdram_check(5); break;
- case SH7751_CS6_BASE_ADDR: word = __area_sdram_check(6); break;
+ 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 0;
+ return -1;
/* configure the wait control registers */
word = ctrl_inl(SH7751_WCR1);
- pci_write_reg(word, SH4_PCIWCR1);
+ pci_write_reg(chan, word, SH4_PCIWCR1);
word = ctrl_inl(SH7751_WCR2);
- pci_write_reg(word, SH4_PCIWCR2);
+ pci_write_reg(chan, word, SH4_PCIWCR2);
word = ctrl_inl(SH7751_WCR3);
- pci_write_reg(word, SH4_PCIWCR3);
+ pci_write_reg(chan, word, SH4_PCIWCR3);
word = ctrl_inl(SH7751_MCR);
- pci_write_reg(word, SH4_PCIMCR);
+ 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();
+ 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(word, SH4_PCICR);
+ pci_write_reg(chan, word, SH4_PCICR);
- return 1;
+ register_pci_controller(chan);
+
+ return 0;
}
+arch_initcall(sh7751_pci_init);
diff --git a/arch/sh/drivers/pci/pci-sh7751.h b/arch/sh/drivers/pci/pci-sh7751.h
index 68e3cb5e6bec..4983a4d20355 100644
--- a/arch/sh/drivers/pci/pci-sh7751.h
+++ b/arch/sh/drivers/pci/pci-sh7751.h
@@ -26,7 +26,6 @@
#define SH7751_PCI_IO_SIZE 0x40000 /* Size of IO window */
#define SH7751_PCIREG_BASE 0xFE200000 /* PCI regs base address */
-#define PCI_REG(n) (SH7751_PCIREG_BASE+ n)
#define SH7751_PCICONF0 0x0 /* PCI Config Reg 0 */
#define SH7751_PCICONF0_DEVID 0xFFFF0000 /* Device ID */
@@ -58,7 +57,7 @@
#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 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 */
@@ -73,12 +72,12 @@
#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_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 */
+ #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 */
@@ -127,9 +126,4 @@
#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)
-struct sh4_pci_address_map;
-
-/* arch/sh/drivers/pci/pci-sh7751.c */
-int sh7751_pcic_init(struct sh4_pci_address_map *map);
-
#endif /* _PCI_SH7751_H_ */
diff --git a/arch/sh/drivers/pci/pci-sh7780.c b/arch/sh/drivers/pci/pci-sh7780.c
index bae6a2cf047d..323b92d565fe 100644
--- a/arch/sh/drivers/pci/pci-sh7780.c
+++ b/arch/sh/drivers/pci/pci-sh7780.c
@@ -1,19 +1,12 @@
/*
- * Low-Level PCI Support for the SH7780
+ * Low-Level PCI Support for the SH7780
*
- * Dustin McIntire (dustin@sensoria.com)
- * Derived from arch/i386/kernel/pci-*.c which bore the message:
- * (c) 1999--2000 Martin Mares <mj@ucw.cz>
- *
- * Ported to the new API by Paul Mundt <lethal@linux-sh.org>
- * With cleanup by Paul van Gool <pvangool@mimotech.com>
- *
- * May be copied or modified under the terms of the GNU General Public
- * License. See linux/COPYING for more information.
+ * Copyright (C) 2005 - 2009 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.
*/
-#undef DEBUG
-
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/init.h>
@@ -22,135 +15,132 @@
#include <linux/delay.h>
#include "pci-sh4.h"
-#define INTC_BASE 0xffd00000
-#define INTC_ICR0 (INTC_BASE+0x0)
-#define INTC_ICR1 (INTC_BASE+0x1c)
-#define INTC_INTPRI (INTC_BASE+0x10)
-#define INTC_INTREQ (INTC_BASE+0x24)
-#define INTC_INTMSK0 (INTC_BASE+0x44)
-#define INTC_INTMSK1 (INTC_BASE+0x48)
-#define INTC_INTMSK2 (INTC_BASE+0x40080)
-#define INTC_INTMSKCLR0 (INTC_BASE+0x64)
-#define INTC_INTMSKCLR1 (INTC_BASE+0x68)
-#define INTC_INTMSKCLR2 (INTC_BASE+0x40084)
-#define INTC_INT2MSKR (INTC_BASE+0x40038)
-#define INTC_INT2MSKCR (INTC_BASE+0x4003c)
+static struct resource sh7785_io_resource = {
+ .name = "SH7785_IO",
+ .start = SH7780_PCI_IO_BASE,
+ .end = SH7780_PCI_IO_BASE + SH7780_PCI_IO_SIZE - 1,
+ .flags = IORESOURCE_IO
+};
+
+static struct resource sh7785_mem_resource = {
+ .name = "SH7785_mem",
+ .start = SH7780_PCI_MEMORY_BASE,
+ .end = SH7780_PCI_MEMORY_BASE + SH7780_PCI_MEM_SIZE - 1,
+ .flags = IORESOURCE_MEM
+};
+
+static struct pci_channel sh7780_pci_controller = {
+ .pci_ops = &sh4_pci_ops,
+ .mem_resource = &sh7785_mem_resource,
+ .mem_offset = 0x00000000,
+ .io_resource = &sh7785_io_resource,
+ .io_offset = 0x00000000,
+ .io_map_base = SH7780_PCI_IO_BASE,
+};
+
+static struct sh4_pci_address_map sh7780_pci_map = {
+ .window0 = {
+#if defined(CONFIG_32BIT)
+ .base = SH7780_32BIT_DDR_BASE_ADDR,
+ .size = 0x40000000,
+#else
+ .base = SH7780_CS0_BASE_ADDR,
+ .size = 0x20000000,
+#endif
+ },
+};
-/*
- * Initialization. Try all known PCI access methods. Note that we support
- * using both PCI BIOS and direct access: in such cases, we use I/O ports
- * to access config space.
- *
- * Note that the platform specific initialization (BSC registers, and memory
- * space mapping) will be called via the platform defined function
- * pcibios_init_platform().
- */
static int __init sh7780_pci_init(void)
{
+ struct pci_channel *chan = &sh7780_pci_controller;
unsigned int id;
- int ret, match = 0;
-
- pr_debug("PCI: Starting intialization.\n");
-
- ctrl_outl(0x00000001, SH7780_PCI_VCR2); /* Enable PCIC */
-
- /* check for SH7780/SH7780R hardware */
- id = pci_read_reg(SH7780_PCIVID);
- if ((id & 0xffff) == SH7780_VENDOR_ID) {
- switch ((id >> 16) & 0xffff) {
- case SH7763_DEVICE_ID:
- case SH7780_DEVICE_ID:
- case SH7781_DEVICE_ID:
- case SH7785_DEVICE_ID:
- match = 1;
- break;
- }
- }
+ const char *type = NULL;
+ int ret;
+ u32 word;
- if (unlikely(!match)) {
- printk(KERN_ERR "PCI: This is not an SH7780 (%x)\n", id);
+ printk(KERN_NOTICE "PCI: Starting intialization.\n");
+
+ chan->reg_base = 0xfe040000;
+
+ /* Enable CPU access to the PCIC registers. */
+ __raw_writel(PCIECR_ENBL, PCIECR);
+
+ id = __raw_readw(chan->reg_base + SH7780_PCIVID);
+ if (id != SH7780_VENDOR_ID) {
+ printk(KERN_ERR "PCI: Unknown vendor ID 0x%04x.\n", id);
return -ENODEV;
}
- /* Setup the INTC */
- if (mach_is_7780se()) {
- /* ICR0: IRL=use separately */
- ctrl_outl(0x00C00020, INTC_ICR0);
- /* ICR1: detect low level(for 2ndcut) */
- ctrl_outl(0xAAAA0000, INTC_ICR1);
- /* INTPRI: priority=3(all) */
- ctrl_outl(0x33333333, INTC_INTPRI);
+ id = __raw_readw(chan->reg_base + SH7780_PCIDID);
+ type = (id == SH7763_DEVICE_ID) ? "SH7763" :
+ (id == SH7780_DEVICE_ID) ? "SH7780" :
+ (id == SH7781_DEVICE_ID) ? "SH7781" :
+ (id == SH7785_DEVICE_ID) ? "SH7785" :
+ NULL;
+ if (unlikely(!type)) {
+ printk(KERN_ERR "PCI: Found an unsupported Renesas host "
+ "controller, device id 0x%04x.\n", id);
+ return -EINVAL;
}
- if ((ret = sh4_pci_check_direct()) != 0)
- return ret;
+ printk(KERN_NOTICE "PCI: Found a Renesas %s host "
+ "controller, revision %d.\n", type,
+ __raw_readb(chan->reg_base + SH7780_PCIRID));
- return pcibios_init_platform();
-}
-core_initcall(sh7780_pci_init);
-
-int __init sh7780_pcic_init(struct sh4_pci_address_map *map)
-{
- u32 word;
+ if ((ret = sh4_pci_check_direct(chan)) != 0)
+ return ret;
/*
- * This code is unused for some boards as it is done in the
- * bootloader and doing it here means the MAC addresses loaded
- * by the bootloader get lost.
- */
- if (!(map->flags & SH4_PCIC_NO_RESET)) {
- /* toggle PCI reset pin */
- word = SH4_PCICR_PREFIX | SH4_PCICR_PRST;
- pci_write_reg(word, SH4_PCICR);
- /* Wait for a long time... not 1 sec. but long enough */
- mdelay(100);
- word = SH4_PCICR_PREFIX;
- pci_write_reg(word, SH4_PCICR);
- }
-
- /* set the command/status bits to:
- * Wait Cycle Control + Parity Enable + Bus Master +
- * Mem space enable
+ * Set the class and sub-class codes.
*/
- pci_write_reg(0x00000046, SH7780_PCICMD);
-
- /* define this host as the host bridge */
- word = PCI_BASE_CLASS_BRIDGE << 24;
- pci_write_reg(word, SH7780_PCIRID);
+ __raw_writeb(PCI_CLASS_BRIDGE_HOST >> 8,
+ chan->reg_base + SH7780_PCIBCC);
+ __raw_writeb(PCI_CLASS_BRIDGE_HOST & 0xff,
+ chan->reg_base + SH7780_PCISUB);
- /* Set IO and Mem windows to local address
+ /*
+ * Set IO and Mem windows to local address
* Make PCI and local address the same for easy 1 to 1 mapping
*/
- pci_write_reg(map->window0.size - 0xfffff, SH4_PCILSR0);
- pci_write_reg(map->window1.size - 0xfffff, SH4_PCILSR1);
+ pci_write_reg(chan, sh7780_pci_map.window0.size - 0xfffff, SH4_PCILSR0);
/* Set the values on window 0 PCI config registers */
- pci_write_reg(map->window0.base, SH4_PCILAR0);
- pci_write_reg(map->window0.base, SH7780_PCIMBAR0);
- /* Set the values on window 1 PCI config registers */
- pci_write_reg(map->window1.base, SH4_PCILAR1);
- pci_write_reg(map->window1.base, SH7780_PCIMBAR1);
-
- /* Map IO space into PCI IO window
- * The IO window is 64K-PCIBIOS_MIN_IO in size
- * IO addresses will be translated to the
- * PCI IO window base address
- */
- pr_debug("PCI: Mapping IO address 0x%x - 0x%x to base 0x%x\n",
- PCIBIOS_MIN_IO, (64 << 10),
- SH7780_PCI_IO_BASE + PCIBIOS_MIN_IO);
+ pci_write_reg(chan, sh7780_pci_map.window0.base, SH4_PCILAR0);
+ pci_write_reg(chan, sh7780_pci_map.window0.base, SH7780_PCIMBAR0);
- /* NOTE: I'm ignoring the PCI error IRQs for now..
- * TODO: add support for the internal error interrupts and
- * DMA interrupts...
- */
+ pci_write_reg(chan, 0x0000380f, SH4_PCIAINTM);
+
+ /* Set up standard PCI config registers */
+ __raw_writew(0xFB00, chan->reg_base + SH7780_PCISTATUS);
+ __raw_writew(0x0047, chan->reg_base + SH7780_PCICMD);
+ __raw_writew(0x1912, chan->reg_base + SH7780_PCISVID);
+ __raw_writew(0x0001, chan->reg_base + SH7780_PCISID);
+
+ __raw_writeb(0x00, chan->reg_base + SH7780_PCIPIF);
/* Apply any last-minute PCIC fixups */
- pci_fixup_pcic();
+ pci_fixup_pcic(chan);
+
+ pci_write_reg(chan, 0xfd000000, SH7780_PCIMBR0);
+ pci_write_reg(chan, 0x00fc0000, SH7780_PCIMBMR0);
+
+#ifdef CONFIG_32BIT
+ pci_write_reg(chan, 0xc0000000, SH7780_PCIMBR2);
+ pci_write_reg(chan, 0x20000000 - SH7780_PCI_IO_SIZE, SH7780_PCIMBMR2);
+#endif
+
+ /* Set IOBR for windows containing area specified in pci.h */
+ pci_write_reg(chan, chan->io_resource->start & ~(SH7780_PCI_IO_SIZE-1),
+ SH7780_PCIIOBR);
+ pci_write_reg(chan, ((SH7780_PCI_IO_SIZE-1) & (7<<18)),
+ SH7780_PCIIOBMR);
/* SH7780 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_FTO;
- pci_write_reg(word, SH4_PCICR);
+ pci_write_reg(chan, word, SH4_PCICR);
+
+ register_pci_controller(chan);
- return 1;
+ return 0;
}
+arch_initcall(sh7780_pci_init);
diff --git a/arch/sh/drivers/pci/pci-sh7780.h b/arch/sh/drivers/pci/pci-sh7780.h
index 93adc7119b79..4a52478c97cf 100644
--- a/arch/sh/drivers/pci/pci-sh7780.h
+++ b/arch/sh/drivers/pci/pci-sh7780.h
@@ -20,9 +20,8 @@
#define SH7785_DEVICE_ID 0x0007
/* SH7780 Control Registers */
-#define SH7780_PCI_VCR0 0xFE000000
-#define SH7780_PCI_VCR1 0xFE000004
-#define SH7780_PCI_VCR2 0xFE000008
+#define PCIECR 0xFE000008
+#define PCIECR_ENBL 0x01
/* SH7780 Specific Values */
#define SH7780_PCI_CONFIG_BASE 0xFD000000 /* Config space base addr */
@@ -35,7 +34,6 @@
#define SH7780_PCI_IO_SIZE 0x00400000 /* Size of IO window */
#define SH7780_PCIREG_BASE 0xFE040000 /* PCI regs base address */
-#define PCI_REG(n) (SH7780_PCIREG_BASE+n)
/* SH7780 PCI Config Registers */
#define SH7780_PCIVID 0x000 /* Vendor ID */
@@ -67,11 +65,6 @@
#define SH7780_PCIPMCSR_BSE 0x046
#define SH7780_PCICDD 0x047
-#define SH7780_PCICR 0x100 /* PCI Control Register */
-#define SH7780_PCILSR 0x104 /* PCI Local Space Register0 */
-#define SH7780_PCILSR1 0x108 /* PCI Local Space Register1 */
-#define SH7780_PCILAR0 0x10C /* PCI Local Address Register1 */
-#define SH7780_PCILAR1 0x110 /* PCI Local Address Register1 */
#define SH7780_PCIIR 0x114 /* PCI Interrupt Register */
#define SH7780_PCIIMR 0x118 /* PCI Interrupt Mask Register */
#define SH7780_PCIAIR 0x11C /* Error Address Register */
@@ -106,9 +99,4 @@
#define SH7780_32BIT_DDR_BASE_ADDR 0x40000000
-struct sh4_pci_address_map;
-
-/* arch/sh/drivers/pci/pci-sh7780.c */
-int sh7780_pcic_init(struct sh4_pci_address_map *map);
-
#endif /* _PCI_SH7780_H_ */
diff --git a/arch/sh/drivers/pci/pci.c b/arch/sh/drivers/pci/pci.c
index 0d6ac7a1db49..54d77cbb8b39 100644
--- a/arch/sh/drivers/pci/pci.c
+++ b/arch/sh/drivers/pci/pci.c
@@ -1,67 +1,156 @@
/*
- * arch/sh/drivers/pci/pci.c
+ * New-style PCI core.
*
- * Copyright (c) 2002 M. R. Brown <mrbrown@linux-sh.org>
- * Copyright (c) 2004 - 2006 Paul Mundt <lethal@linux-sh.org>
+ * Copyright (c) 2004 - 2009 Paul Mundt
+ * Copyright (c) 2002 M. R. Brown
*
- * These functions are collected here to reduce duplication of common
- * code amongst the many platform-specific PCI support code files.
- *
- * These routines require the following board-specific routines:
- * void pcibios_fixup_irqs();
- *
- * See include/asm-sh/pci.h for more information.
+ * 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 <asm/io.h>
+#include <linux/io.h>
+#include <linux/mutex.h>
-static int __init pcibios_init(void)
+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 __devinit pcibios_scanbus(struct pci_channel *hose)
{
- struct pci_channel *p;
+ static int next_busno;
struct pci_bus *bus;
- int busno;
-#ifdef CONFIG_PCI_AUTO
- /* assign resources */
- busno = 0;
- for (p = board_pci_channels; p->pci_ops != NULL; p++)
- busno = pciauto_assign_resources(busno, p) + 1;
-#endif
+ bus = pci_scan_bus(next_busno, hose->pci_ops, hose);
+ if (bus) {
+ next_busno = bus->subordinate + 1;
+ /* Don't allow 8-bit bus number overflow inside the hose -
+ reserve some space for bridges. */
+ if (next_busno > 224)
+ next_busno = 0;
+
+ pci_bus_size_bridges(bus);
+ pci_bus_assign_resources(bus);
+ pci_enable_bridges(bus);
+ }
+}
+
+static DEFINE_MUTEX(pci_scan_mutex);
- /* scan the buses */
- busno = 0;
- for (p = board_pci_channels; p->pci_ops != NULL; p++) {
- bus = pci_scan_bus(busno, p->pci_ops, p);
- busno = bus->subordinate + 1;
+void __devinit register_pci_controller(struct pci_channel *hose)
+{
+ if (request_resource(&iomem_resource, hose->mem_resource) < 0)
+ goto out;
+ if (request_resource(&ioport_resource, hose->io_resource) < 0) {
+ release_resource(hose->mem_resource);
+ goto out;
}
+ *hose_tail = hose;
+ hose_tail = &hose->next;
+
+ /*
+ * Do not panic here but later - this might hapen before console init.
+ */
+ if (!hose->io_map_base) {
+ printk(KERN_WARNING
+ "registering PCI controller with io_map_base unset\n");
+ }
+
+ /*
+ * 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;
+
+out:
+ printk(KERN_WARNING
+ "Skipping PCI bus scan due to resource conflict\n");
+}
+
+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_fixup_irqs(pci_common_swizzle, pcibios_map_platform_irq);
dma_debug_add_bus(&pci_bus_type);
+ pci_initialized = 1;
+
return 0;
}
subsys_initcall(pcibios_init);
+static void pcibios_fixup_device_resources(struct pci_dev *dev,
+ struct pci_bus *bus)
+{
+ /* Update device resources. */
+ struct pci_channel *hose = bus->sysdata;
+ unsigned long offset = 0;
+ int i;
+
+ for (i = 0; i < PCI_NUM_RESOURCES; i++) {
+ if (!dev->resource[i].start)
+ continue;
+ if (dev->resource[i].flags & IORESOURCE_PCI_FIXED)
+ continue;
+ if (dev->resource[i].flags & IORESOURCE_IO)
+ offset = hose->io_offset;
+ else if (dev->resource[i].flags & IORESOURCE_MEM)
+ offset = hose->mem_offset;
+
+ dev->resource[i].start += offset;
+ dev->resource[i].end += offset;
+ }
+}
+
/*
* Called after each bus is probed, but before its children
* are examined.
*/
-void __devinit __weak pcibios_fixup_bus(struct pci_bus *bus)
+void __devinit pcibios_fixup_bus(struct pci_bus *bus)
{
- pci_read_bridge_bases(bus);
-}
+ struct pci_dev *dev = bus->self;
+ struct list_head *ln;
+ struct pci_channel *chan = bus->sysdata;
-void pcibios_align_resource(void *data, struct resource *res,
- resource_size_t size, resource_size_t align)
- __attribute__ ((weak));
+ if (!dev) {
+ bus->resource[0] = chan->io_resource;
+ bus->resource[1] = chan->mem_resource;
+ }
+
+ for (ln = bus->devices.next; ln != &bus->devices; ln = ln->next) {
+ dev = pci_dev_b(ln);
+
+ if ((dev->class >> 8) != PCI_CLASS_BRIDGE_PCI)
+ pcibios_fixup_device_resources(dev, bus);
+ }
+}
/*
* We need to avoid collisions with `mirrored' VGA ports
@@ -72,14 +161,58 @@ void pcibios_align_resource(void *data, struct resource *res,
void pcibios_align_resource(void *data, struct resource *res,
resource_size_t size, resource_size_t align)
{
+ struct pci_dev *dev = data;
+ struct pci_channel *chan = dev->sysdata;
+ resource_size_t start = res->start;
+
if (res->flags & IORESOURCE_IO) {
- resource_size_t start = res->start;
+ if (start < PCIBIOS_MIN_IO + chan->io_resource->start)
+ start = PCIBIOS_MIN_IO + chan->io_resource->start;
+ /*
+ * Put everything into 0x00-0xff region modulo 0x400.
+ */
if (start & 0x300) {
start = (start + 0x3ff) & ~0x3ff;
res->start = start;
}
+ } else if (res->flags & IORESOURCE_MEM) {
+ if (start < PCIBIOS_MIN_MEM + chan->mem_resource->start)
+ start = PCIBIOS_MIN_MEM + chan->mem_resource->start;
}
+
+ res->start = start;
+}
+
+void pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region,
+ struct resource *res)
+{
+ struct pci_channel *hose = dev->sysdata;
+ unsigned long offset = 0;
+
+ if (res->flags & IORESOURCE_IO)
+ offset = hose->io_offset;
+ else if (res->flags & IORESOURCE_MEM)
+ offset = hose->mem_offset;
+
+ region->start = res->start - offset;
+ region->end = res->end - offset;
+}
+
+void __devinit
+pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res,
+ struct pci_bus_region *region)
+{
+ struct pci_channel *hose = dev->sysdata;
+ unsigned long offset = 0;
+
+ if (res->flags & IORESOURCE_IO)
+ offset = hose->io_offset;
+ else if (res->flags & IORESOURCE_MEM)
+ offset = hose->mem_offset;
+
+ res->start = region->start + offset;
+ res->end = region->end + offset;
}
int pcibios_enable_device(struct pci_dev *dev, int mask)
@@ -90,13 +223,21 @@ int pcibios_enable_device(struct pci_dev *dev, int mask)
pci_read_config_word(dev, PCI_COMMAND, &cmd);
old_cmd = cmd;
- for(idx=0; idx<6; idx++) {
- if (!(mask & (1 << idx)))
+ for (idx=0; idx < PCI_NUM_RESOURCES; idx++) {
+ /* Only set up the requested stuff */
+ if (!(mask & (1<<idx)))
continue;
+
r = &dev->resource[idx];
+ if (!(r->flags & (IORESOURCE_IO | IORESOURCE_MEM)))
+ continue;
+ if ((idx == PCI_ROM_RESOURCE) &&
+ (!(r->flags & IORESOURCE_ROM_ENABLE)))
+ continue;
if (!r->start && r->end) {
- printk(KERN_ERR "PCI: Device %s not available because "
- "of resource collisions\n", pci_name(dev));
+ printk(KERN_ERR "PCI: Device %s not available "
+ "because of resource collisions\n",
+ pci_name(dev));
return -EINVAL;
}
if (r->flags & IORESOURCE_IO)
@@ -104,10 +245,8 @@ int pcibios_enable_device(struct pci_dev *dev, int mask)
if (r->flags & IORESOURCE_MEM)
cmd |= PCI_COMMAND_MEMORY;
}
- if (dev->resource[PCI_ROM_RESOURCE].start)
- cmd |= PCI_COMMAND_MEMORY;
if (cmd != old_cmd) {
- printk(KERN_INFO "PCI: Enabling device %s (%04x -> %04x)\n",
+ printk("PCI: Enabling device %s (%04x -> %04x)\n",
pci_name(dev), old_cmd, cmd);
pci_write_config_word(dev, PCI_COMMAND, cmd);
}
@@ -140,6 +279,43 @@ void __init pcibios_update_irq(struct pci_dev *dev, int irq)
pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq);
}
+char * __devinit pcibios_setup(char *str)
+{
+ return str;
+}
+
+int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
+ enum pci_mmap_state mmap_state, int write_combine)
+{
+ /*
+ * I/O space can be accessed via normal processor loads and stores on
+ * this platform but for now we elect not to do this and portable
+ * drivers should not do this anyway.
+ */
+ if (mmap_state == pci_mmap_io)
+ return -EINVAL;
+
+ /*
+ * Ignore write-combine; for now only return uncached mappings.
+ */
+ vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+
+ return remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,
+ vma->vm_end - vma->vm_start,
+ vma->vm_page_prot);
+}
+
+static void __iomem *ioport_map_pci(struct pci_dev *dev,
+ unsigned long port, unsigned int nr)
+{
+ struct pci_channel *chan = dev->sysdata;
+
+ if (!chan->io_map_base)
+ chan->io_map_base = generic_io_base;
+
+ return (void __iomem *)(chan->io_map_base + port);
+}
+
void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long maxlen)
{
resource_size_t start = pci_resource_start(dev, bar);
@@ -151,20 +327,24 @@ void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long maxlen)
if (maxlen && len > maxlen)
len = maxlen;
+ if (flags & IORESOURCE_IO)
+ return ioport_map_pci(dev, start, len);
+
/*
* Presently the IORESOURCE_MEM case is a bit special, most
* SH7751 style PCI controllers have PCI memory at a fixed
- * location in the address space where no remapping is desired
- * (typically at 0xfd000000, but is_pci_memaddr() will know
- * best). With the IORESOURCE_MEM case more care has to be taken
+ * location in the address space where no remapping is desired.
+ * With the IORESOURCE_MEM case more care has to be taken
* to inhibit page table mapping for legacy cores, but this is
* punted off to __ioremap().
* -- PFM.
*/
- if (flags & IORESOURCE_IO)
- return ioport_map(start, len);
- if (flags & IORESOURCE_MEM)
- return ioremap(start, len);
+ if (flags & IORESOURCE_MEM) {
+ if (flags & IORESOURCE_CACHEABLE)
+ return ioremap(start, len);
+
+ return ioremap_nocache(start, len);
+ }
return NULL;
}
@@ -175,3 +355,10 @@ void pci_iounmap(struct pci_dev *dev, void __iomem *addr)
iounmap(addr);
}
EXPORT_SYMBOL(pci_iounmap);
+
+#ifdef CONFIG_HOTPLUG
+EXPORT_SYMBOL(pcibios_resource_to_bus);
+EXPORT_SYMBOL(pcibios_bus_to_resource);
+EXPORT_SYMBOL(PCIBIOS_MIN_IO);
+EXPORT_SYMBOL(PCIBIOS_MIN_MEM);
+#endif