diff options
author | Paul Mundt <lethal@linux-sh.org> | 2006-09-27 16:43:28 +0900 |
---|---|---|
committer | Paul Mundt <lethal@linux-sh.org> | 2006-09-27 16:43:28 +0900 |
commit | 959f85f8a3223c116bbe95dd8a9b207790b5d4d3 (patch) | |
tree | e7da9ccf292f860bfa0ff9cc8b2682cd1d6bad4d /arch/sh/drivers | |
parent | e108b2ca2349f510ce7d7f910eda89f71d710d84 (diff) |
sh: Consolidated SH7751/SH7780 PCI support.
This cleans up quite a lot of the PCI mess that we
currently have, and attempts to consolidate the
duplication in the SH7780 and SH7751 PCI controllers.
Signed-off-by: Paul Mundt <lethal@linux-sh.org>
Diffstat (limited to 'arch/sh/drivers')
-rw-r--r-- | arch/sh/drivers/pci/Makefile | 5 | ||||
-rw-r--r-- | arch/sh/drivers/pci/fixups-dreamcast.c | 38 | ||||
-rw-r--r-- | arch/sh/drivers/pci/fixups-r7780rp.c | 38 | ||||
-rw-r--r-- | arch/sh/drivers/pci/fixups-rts7751r2d.c | 24 | ||||
-rw-r--r-- | arch/sh/drivers/pci/fixups-sh03.c | 38 | ||||
-rw-r--r-- | arch/sh/drivers/pci/ops-bigsur.c | 18 | ||||
-rw-r--r-- | arch/sh/drivers/pci/ops-landisk.c | 68 | ||||
-rw-r--r-- | arch/sh/drivers/pci/ops-r7780rp.c | 18 | ||||
-rw-r--r-- | arch/sh/drivers/pci/ops-rts7751r2d.c | 13 | ||||
-rw-r--r-- | arch/sh/drivers/pci/ops-sh4.c | 164 | ||||
-rw-r--r-- | arch/sh/drivers/pci/ops-snapgear.c | 21 | ||||
-rw-r--r-- | arch/sh/drivers/pci/ops-titan.c | 16 | ||||
-rw-r--r-- | arch/sh/drivers/pci/pci-auto.c | 10 | ||||
-rw-r--r-- | arch/sh/drivers/pci/pci-sh4.h | 180 | ||||
-rw-r--r-- | arch/sh/drivers/pci/pci-sh7751.c | 322 | ||||
-rw-r--r-- | arch/sh/drivers/pci/pci-sh7751.h | 174 | ||||
-rw-r--r-- | arch/sh/drivers/pci/pci-sh7780.c | 270 | ||||
-rw-r--r-- | arch/sh/drivers/pci/pci-sh7780.h | 94 | ||||
-rw-r--r-- | arch/sh/drivers/pci/pci-st40.c | 19 | ||||
-rw-r--r-- | arch/sh/drivers/pci/pci.c | 40 |
20 files changed, 638 insertions, 932 deletions
diff --git a/arch/sh/drivers/pci/Makefile b/arch/sh/drivers/pci/Makefile index 3d8078f1c05..9e00cb8a39e 100644 --- a/arch/sh/drivers/pci/Makefile +++ b/arch/sh/drivers/pci/Makefile @@ -6,8 +6,8 @@ obj-y += pci.o obj-$(CONFIG_PCI_AUTO) += pci-auto.o obj-$(CONFIG_CPU_SUBTYPE_ST40STB1) += pci-st40.o -obj-$(CONFIG_CPU_SUBTYPE_SH7751) += pci-sh7751.o -obj-$(CONFIG_CPU_SUBTYPE_SH7780) += pci-sh7780.o +obj-$(CONFIG_CPU_SUBTYPE_SH7751) += pci-sh7751.o ops-sh4.o +obj-$(CONFIG_CPU_SUBTYPE_SH7780) += pci-sh7780.o ops-sh4.o obj-$(CONFIG_SH_DREAMCAST) += ops-dreamcast.o fixups-dreamcast.o \ dma-dreamcast.o @@ -17,3 +17,4 @@ obj-$(CONFIG_SH_RTS7751R2D) += ops-rts7751r2d.o fixups-rts7751r2d.o obj-$(CONFIG_SH_SH03) += ops-sh03.o fixups-sh03.o obj-$(CONFIG_SH_R7780RP) += ops-r7780rp.o fixups-r7780rp.o obj-$(CONFIG_SH_TITAN) += ops-titan.o +obj-$(CONFIG_SH_LANDISK) += ops-landisk.o diff --git a/arch/sh/drivers/pci/fixups-dreamcast.c b/arch/sh/drivers/pci/fixups-dreamcast.c index 63b1c6f4b8d..c0af5f7ef41 100644 --- a/arch/sh/drivers/pci/fixups-dreamcast.c +++ b/arch/sh/drivers/pci/fixups-dreamcast.c @@ -4,7 +4,7 @@ * PCI fixups for the Sega Dreamcast * * Copyright (C) 2001, 2002 M. R. Brown - * Copyright (C) 2002, 2003 Paul Mundt + * Copyright (C) 2002, 2003, 2006 Paul Mundt * * This file originally bore the message (with enclosed-$): * Id: pci.c,v 1.3 2003/05/04 19:29:46 lethal Exp @@ -45,36 +45,16 @@ static void __init gapspci_fixup_resources(struct pci_dev *dev) printk("PCI: Failed resource fixup\n"); } } - DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, gapspci_fixup_resources); -void __init pcibios_fixup_bus(struct pci_bus *bus) +int __init pcibios_map_platform_irq(struct pci_dev *dev, u8 slot, u8 pin) { - /* - * We don't have any sub bus to fix up, and this is a rather - * stupid place to put general device fixups. Don't do it. - * Use the pcibios_fixups table or suffer the consequences. + /* + * The interrupt routing semantics here are quite trivial. + * + * We basically only support one interrupt, so we only bother + * updating a device's interrupt line with this single shared + * interrupt. Keeps routing quite simple, doesn't it? */ + return GAPSPCI_IRQ; } - -void __init pcibios_fixup_irqs(void) -{ - struct pci_dev *dev = 0; - - for_each_pci_dev(dev) { - /* - * The interrupt routing semantics here are quite trivial. - * - * We basically only support one interrupt, so we only bother - * updating a device's interrupt line with this single shared - * interrupt. Keeps routing quite simple, doesn't it? - */ - printk(KERN_NOTICE "PCI: Fixing up IRQ routing for device %s\n", - pci_name(dev)); - - dev->irq = GAPSPCI_IRQ; - - pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq); - } -} - diff --git a/arch/sh/drivers/pci/fixups-r7780rp.c b/arch/sh/drivers/pci/fixups-r7780rp.c index b656b562ec9..3e321df65d2 100644 --- a/arch/sh/drivers/pci/fixups-r7780rp.c +++ b/arch/sh/drivers/pci/fixups-r7780rp.c @@ -4,36 +4,42 @@ * Highlander R7780RP-1 PCI fixups * * Copyright (C) 2003 Lineo uSolutions, Inc. - * Copyright (C) 2004 Paul Mundt + * Copyright (C) 2004 - 2006 Paul Mundt * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive * for more details. */ -#include "pci-sh7780.h" +#include <linux/pci.h> +#include "pci-sh4.h" #include <asm/io.h> int pci_fixup_pcic(void) { - outl(0x000043ff, PCI_REG(SH7780_PCIIMR)); - outl(0x0000380f, PCI_REG(SH7780_PCIAINTM)); + pci_write_reg(0x000043ff, SH4_PCIINTM); + pci_write_reg(0x0000380f, SH4_PCIAINTM); - outl(0xfbb00047, PCI_REG(SH7780_PCICMD)); - outl(0x00000000, PCI_REG(SH7780_PCIIBAR)); + pci_write_reg(0xfbb00047, SH7780_PCICMD); + pci_write_reg(0x00000000, SH7780_PCIIBAR); - outl(0x00011912, PCI_REG(SH7780_PCISVID)); - outl(0x08000000, PCI_REG(SH7780_PCICSCR0)); - outl(0x0000001b, PCI_REG(SH7780_PCICSAR0)); - outl(0xfd000000, PCI_REG(SH7780_PCICSCR1)); - outl(0x0000000f, PCI_REG(SH7780_PCICSAR1)); + pci_write_reg(0x00011912, SH7780_PCISVID); + pci_write_reg(0x08000000, SH7780_PCICSCR0); + pci_write_reg(0x0000001b, SH7780_PCICSAR0); + pci_write_reg(0xfd000000, SH7780_PCICSCR1); + pci_write_reg(0x0000000f, SH7780_PCICSAR1); - outl(0xfd000000, PCI_REG(SH7780_PCIMBR0)); - outl(0x00fc0000, PCI_REG(SH7780_PCIMBMR0)); + pci_write_reg(0xfd000000, SH7780_PCIMBR0); + pci_write_reg(0x00fc0000, SH7780_PCIMBMR0); + +#ifdef CONFIG_32BIT + pci_write_reg(0xc0000000, SH7780_PCIMBR2); + pci_write_reg(0x20000000 - SH7780_PCI_IO_SIZE, SH7780_PCIMBMR2); +#endif /* Set IOBR for windows containing area specified in pci.h */ - outl((PCIBIOS_MIN_IO & ~(SH7780_PCI_IO_SIZE-1)), PCI_REG(SH7780_PCIIOBR)); - outl(((SH7780_PCI_IO_SIZE-1) & (7<<18)), PCI_REG(SH7780_PCIIOBMR)); + pci_write_reg((PCIBIOS_MIN_IO & ~(SH7780_PCI_IO_SIZE - 1)), + SH7780_PCIIOBR); + pci_write_reg(((SH7780_PCI_IO_SIZE-1) & (7<<18)), SH7780_PCIIOBMR); return 0; } - diff --git a/arch/sh/drivers/pci/fixups-rts7751r2d.c b/arch/sh/drivers/pci/fixups-rts7751r2d.c index 0c590fc7a08..e72ceb560d5 100644 --- a/arch/sh/drivers/pci/fixups-rts7751r2d.c +++ b/arch/sh/drivers/pci/fixups-rts7751r2d.c @@ -10,8 +10,7 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. */ -#include "pci-sh7751.h" -#include <asm/io.h> +#include "pci-sh4.h" #define PCIMCR_MRSET_OFF 0xBFFFFFFF #define PCIMCR_RFSH_OFF 0xFFFFFFFB @@ -22,22 +21,23 @@ int pci_fixup_pcic(void) bcr1 = inl(SH7751_BCR1); bcr1 |= 0x40080000; /* Enable Bit 19 BREQEN, set PCIC to slave */ - outl(bcr1, PCI_REG(SH7751_PCIBCR1)); + pci_write_reg(bcr1, SH4_PCIBCR1); /* Enable all interrupts, so we known what to fix */ - outl(0x0000c3ff, PCI_REG(SH7751_PCIINTM)); - outl(0x0000380f, PCI_REG(SH7751_PCIAINTM)); + pci_write_reg(0x0000c3ff, SH4_PCIINTM); + pci_write_reg(0x0000380f, SH4_PCIAINTM); - outl(0xfb900047, PCI_REG(SH7751_PCICONF1)); - outl(0xab000001, PCI_REG(SH7751_PCICONF4)); + pci_write_reg(0xfb900047, SH7751_PCICONF1); + pci_write_reg(0xab000001, SH7751_PCICONF4); mcr = inl(SH7751_MCR); mcr = (mcr & PCIMCR_MRSET_OFF) & PCIMCR_RFSH_OFF; - outl(mcr, PCI_REG(SH7751_PCIMCR)); + pci_write_reg(mcr, SH4_PCIMCR); + + pci_write_reg(0x0c000000, SH7751_PCICONF5); + pci_write_reg(0xd0000000, SH7751_PCICONF6); + pci_write_reg(0x0c000000, SH4_PCILAR0); + pci_write_reg(0x00000000, SH4_PCILAR1); - outl(0x0c000000, PCI_REG(SH7751_PCICONF5)); - outl(0xd0000000, PCI_REG(SH7751_PCICONF6)); - outl(0x0c000000, PCI_REG(SH7751_PCILAR0)); - outl(0x00000000, PCI_REG(SH7751_PCILAR1)); return 0; } diff --git a/arch/sh/drivers/pci/fixups-sh03.c b/arch/sh/drivers/pci/fixups-sh03.c index 57ac26c2171..2e8a18b7ee5 100644 --- a/arch/sh/drivers/pci/fixups-sh03.c +++ b/arch/sh/drivers/pci/fixups-sh03.c @@ -3,11 +3,7 @@ #include <linux/types.h> #include <linux/pci.h> -/* - * IRQ functions - */ - -int __init pcibios_map_platform_irq(u8 slot, u8 pin, struct pci_dev *dev) +int __init pcibios_map_platform_irq(struct pci_dev *dev, u8 slot, u8 pin) { int irq; @@ -17,8 +13,9 @@ int __init pcibios_map_platform_irq(u8 slot, u8 pin, struct pci_dev *dev) case 8: return 5; /* eth1 */ case 6: return 2; /* PCI bridge */ default: - printk("PCI: Bad IRQ mapping request for slot %d\n", slot); - return 2; + printk(KERN_ERR "PCI: Bad IRQ mapping request " + "for slot %d\n", slot); + return 2; } } else { switch (pin) { @@ -32,30 +29,3 @@ int __init pcibios_map_platform_irq(u8 slot, u8 pin, struct pci_dev *dev) } return irq; } - -static u8 __init sh03_no_swizzle(struct pci_dev *dev, u8 *pin) -{ - /* no swizzling */ - return PCI_SLOT(dev->devfn); -} - -static int sh03_pci_lookup_irq(struct pci_dev *dev, u8 slot, u8 pin) -{ - int irq = -1; - - /* now lookup the actual IRQ on a platform specific basis (pci-'platform'.c) */ - irq = pcibios_map_platform_irq(slot, pin, dev); - if( irq < 0 ) { - pr_debug("PCI: Error mapping IRQ on device %s\n", pci_name(dev)); - return irq; - } - - pr_debug("Setting IRQ for slot %s to %d\n", pci_name(dev), irq); - - return irq; -} - -void __init pcibios_fixup_irqs(void) -{ - pci_fixup_irqs(sh03_no_swizzle, sh03_pci_lookup_irq); -} diff --git a/arch/sh/drivers/pci/ops-bigsur.c b/arch/sh/drivers/pci/ops-bigsur.c index ae82c6ca05e..5da501bd77b 100644 --- a/arch/sh/drivers/pci/ops-bigsur.c +++ b/arch/sh/drivers/pci/ops-bigsur.c @@ -10,15 +10,12 @@ * * PCI initialization for the Hitachi Big Sur Evaluation Board */ - #include <linux/kernel.h> #include <linux/types.h> #include <linux/init.h> -#include <linux/delay.h> #include <linux/pci.h> - #include <asm/io.h> -#include "pci-sh7751.h" +#include "pci-sh4.h" #include <asm/bigsur/bigsur.h> #define BIGSUR_PCI_IO 0x4000 @@ -41,11 +38,11 @@ static struct resource sh7751_mem_resource = { extern struct pci_ops sh7751_pci_ops; struct pci_channel board_pci_channels[] = { - { &sh7751_pci_ops, &sh7751_io_resource, &sh7751_mem_resource, 0, 0xff }, + { &sh4_pci_ops, &sh7751_io_resource, &sh7751_mem_resource, 0, 0xff }, { 0, } }; -static struct sh7751_pci_address_map sh7751_pci_map = { +static struct sh4_pci_address_map sh7751_pci_map = { .window0 = { .base = SH7751_CS3_BASE_ADDR, .size = BIGSUR_LSR0_SIZE, @@ -58,7 +55,7 @@ static struct sh7751_pci_address_map sh7751_pci_map = { }; /* - * Initialize the Big Sur PCI interface + * Initialize the Big Sur PCI interface * Setup hardware to be Central Funtion * Copy the BSR regs to the PCI interface * Setup PCI windows into local RAM @@ -68,15 +65,15 @@ int __init pcibios_init_platform(void) return sh7751_pcic_init(&sh7751_pci_map); } -int pcibios_map_platform_irq(u8 slot, u8 pin) +int __init pcibios_map_platform_irq(struct pci_dev *pdev, u8 slot, u8 pin) { - /* + /* * The Big Sur can be used in a CPCI chassis, but the SH7751 PCI * interface is on the wrong end of the board so that it can also * support a V320 CPI interface chip... Therefor the IRQ mapping is * somewhat use dependent... I'l assume a linear map for now, i.e. * INTA=slot0,pin0... INTD=slot3,pin0... - */ + */ int irq = (slot + pin-1) % 4 + BIGSUR_SH7751_PCI_IRQ_BASE; PCIDBG(2, "PCI: Mapping Big Sur IRQ for slot %d, pin %c to irq %d\n", @@ -84,4 +81,3 @@ int pcibios_map_platform_irq(u8 slot, u8 pin) return irq; } - diff --git a/arch/sh/drivers/pci/ops-landisk.c b/arch/sh/drivers/pci/ops-landisk.c new file mode 100644 index 00000000000..ada301c21fe --- /dev/null +++ b/arch/sh/drivers/pci/ops-landisk.c @@ -0,0 +1,68 @@ +/* + * arch/sh/drivers/pci/ops-landisk.c + * + * PCI initialization for the I-O DATA Device, Inc. LANDISK board + * + * Copyright (C) 2006 kogiidena + * + * May be copied or modified under the terms of the GNU General Public + * License. See linux/COPYING for more information. + */ +#include <linux/config.h> +#include <linux/kernel.h> +#include <linux/types.h> +#include <linux/init.h> +#include <linux/delay.h> +#include <linux/pci.h> +#include "pci-sh4.h" + +static struct resource sh7751_io_resource = { + .name = "SH7751 IO", + .start = 0x4000, + .end = 0x4000 + SH7751_PCI_IO_SIZE - 1, + .flags = IORESOURCE_IO +}; + +static struct resource sh7751_mem_resource = { + .name = "SH7751 mem", + .start = SH7751_PCI_MEMORY_BASE, + .end = SH7751_PCI_MEMORY_BASE + SH7751_PCI_MEM_SIZE - 1, + .flags = IORESOURCE_MEM +}; + +struct pci_channel board_pci_channels[] = { + {&sh4_pci_ops, &sh7751_io_resource, &sh7751_mem_resource, 0, 0x3ff}, + {NULL, NULL, NULL, 0, 0}, +}; + +static struct sh4_pci_address_map sh7751_pci_map = { + .window0 = { + .base = SH7751_CS3_BASE_ADDR, + .size = (64 << 20), /* 64MB */ + }, + + .flags = SH4_PCIC_NO_RESET, +}; + +int __init pcibios_init_platform(void) +{ + return sh7751_pcic_init(&sh7751_pci_map); +} + +int pcibios_map_platform_irq(struct pci_dev *pdev, u8 slot, u8 pin) +{ + /* + * slot0: pin1-4 = irq5,6,7,8 + * slot1: pin1-4 = irq6,7,8,5 + * slot2: pin1-4 = irq7,8,5,6 + * slot3: pin1-4 = irq8,5,6,7 + */ + int irq = ((slot + pin - 1) & 0x3) + 5; + + if ((slot | (pin - 1)) > 0x3) { + printk("PCI: Bad IRQ mapping request for slot %d pin %c\n", + slot, pin - 1 + 'A'); + return -1; + } + return irq; +} diff --git a/arch/sh/drivers/pci/ops-r7780rp.c b/arch/sh/drivers/pci/ops-r7780rp.c index 3254c4e917a..554d5ed2c58 100644 --- a/arch/sh/drivers/pci/ops-r7780rp.c +++ b/arch/sh/drivers/pci/ops-r7780rp.c @@ -15,13 +15,11 @@ #include <linux/init.h> #include <linux/delay.h> #include <linux/pci.h> -#include <linux/module.h> - -#include <asm/io.h> -#include "pci-sh7780.h" #include <asm/r7780rp/r7780rp.h> +#include <asm/io.h> +#include "pci-sh4.h" -int __init pcibios_map_platform_irq(u8 slot, u8 pin) +int __init pcibios_map_platform_irq(struct pci_dev *pdev, u8 slot, u8 pin) { switch (slot) { case 0: return IRQ_PCISLOT1; /* PCI Interrupt #1 */ @@ -29,7 +27,8 @@ int __init pcibios_map_platform_irq(u8 slot, u8 pin) case 2: return IRQ_PCISLOT3; /* PCI Interrupt #3 */ case 3: return IRQ_PCISLOT4; /* PCI Interrupt E4 */ default: - printk("PCI: Bad IRQ mapping request for slot %d, func %d\n", slot, pin-1); + printk(KERN_ERR "PCI: Bad IRQ mapping " + "request for slot %d, func %d\n", slot, pin-1); return -1; } } @@ -51,12 +50,12 @@ static struct resource sh7780_mem_resource = { extern struct pci_ops sh7780_pci_ops; struct pci_channel board_pci_channels[] = { - { &sh7780_pci_ops, &sh7780_io_resource, &sh7780_mem_resource, 0, 0xff }, + { &sh4_pci_ops, &sh7780_io_resource, &sh7780_mem_resource, 0, 0xff }, { NULL, NULL, NULL, 0, 0 }, }; EXPORT_SYMBOL(board_pci_channels); -static struct sh7780_pci_address_map sh7780_pci_map = { +static struct sh4_pci_address_map sh7780_pci_map = { .window0 = { .base = SH7780_CS2_BASE_ADDR, .size = 0x04000000, @@ -67,11 +66,10 @@ static struct sh7780_pci_address_map sh7780_pci_map = { .size = 0x04000000, }, - .flags = SH7780_PCIC_NO_RESET, + .flags = SH4_PCIC_NO_RESET, }; int __init pcibios_init_platform(void) { return sh7780_pcic_init(&sh7780_pci_map); } - diff --git a/arch/sh/drivers/pci/ops-rts7751r2d.c b/arch/sh/drivers/pci/ops-rts7751r2d.c index 83171d10141..88f44e24542 100644 --- a/arch/sh/drivers/pci/ops-rts7751r2d.c +++ b/arch/sh/drivers/pci/ops-rts7751r2d.c @@ -17,12 +17,11 @@ #include <linux/delay.h> #include <linux/pci.h> #include <linux/module.h> - -#include <asm/io.h> -#include "pci-sh7751.h" #include <asm/rts7751r2d/rts7751r2d.h> +#include <asm/io.h> +#include "pci-sh4.h" -int __init pcibios_map_platform_irq(u8 slot, u8 pin) +int __init pcibios_map_platform_irq(struct pci_dev *pdev, u8 slot, u8 pin) { switch (slot) { case 0: return IRQ_PCISLOT1; /* PCI Extend slot #1 */ @@ -52,12 +51,12 @@ static struct resource sh7751_mem_resource = { extern struct pci_ops sh7751_pci_ops; struct pci_channel board_pci_channels[] = { - { &sh7751_pci_ops, &sh7751_io_resource, &sh7751_mem_resource, 0, 0xff }, + { &sh4_pci_ops, &sh7751_io_resource, &sh7751_mem_resource, 0, 0xff }, { NULL, NULL, NULL, 0, 0 }, }; EXPORT_SYMBOL(board_pci_channels); -static struct sh7751_pci_address_map sh7751_pci_map = { +static struct sh4_pci_address_map sh7751_pci_map = { .window0 = { .base = SH7751_CS3_BASE_ADDR, .size = 0x04000000, @@ -68,7 +67,7 @@ static struct sh7751_pci_address_map sh7751_pci_map = { .size = 0x00000000, /* Unused */ }, - .flags = SH7751_PCIC_NO_RESET, + .flags = SH4_PCIC_NO_RESET, }; int __init pcibios_init_platform(void) diff --git a/arch/sh/drivers/pci/ops-sh4.c b/arch/sh/drivers/pci/ops-sh4.c new file mode 100644 index 00000000000..2d4371009a5 --- /dev/null +++ b/arch/sh/drivers/pci/ops-sh4.c @@ -0,0 +1,164 @@ +/* + * Generic SH-4 / SH-4A PCIC operations (SH7751, SH7780). + * + * Copyright (C) 2002 - 2006 Paul Mundt + * + * This file is subject to the terms and conditions of the GNU General Public + * License v2. See the file "COPYING" in the main directory of this archive + * for more details. + */ +#include <linux/pci.h> +#include <asm/addrspace.h> +#include <asm/io.h> +#include "pci-sh4.h" + +/* + * Direct access to PCI hardware... + */ +#define CONFIG_CMD(bus, devfn, where) \ + P1SEGADDR((bus->number << 16) | (devfn << 8) | (where & ~3)) + +static DEFINE_SPINLOCK(sh4_pci_lock); + +/* + * Functions for accessing PCI configuration space with type 1 accesses + */ +static int sh4_pci_read(struct pci_bus *bus, unsigned int devfn, + int where, int size, u32 *val) +{ + unsigned long flags; + u32 data; + + /* + * PCIPDR may only be accessed as 32 bit words, + * so we must do byte alignment by hand + */ + spin_lock_irqsave(&sh4_pci_lock, flags); + pci_write_reg(CONFIG_CMD(bus, devfn, where), SH4_PCIPAR); + data = pci_read_reg(SH4_PCIPDR); + spin_unlock_irqrestore(&sh4_pci_lock, flags); + + switch (size) { + case 1: + *val = (data >> ((where & 3) << 3)) & 0xff; + break; + case 2: + *val = (data >> ((where & 2) << 3)) & 0xffff; + break; + case 4: + *val = data; + break; + default: + return PCIBIOS_FUNC_NOT_SUPPORTED; + } + + return PCIBIOS_SUCCESSFUL; +} + +/* + * Since SH4 only does 32bit access we'll have to do a read, + * mask,write operation. + * We'll allow an odd byte offset, though it should be illegal. + */ +static int sh4_pci_write(struct pci_bus *bus, unsigned int devfn, + int where, int size, u32 val) +{ + unsigned long flags; + int shift; + u32 data; + + spin_lock_irqsave(&sh4_pci_lock, flags); + pci_write_reg(CONFIG_CMD(bus, devfn, where), SH4_PCIPAR); + data = pci_read_reg(SH4_PCIPDR); + spin_unlock_irqrestore(&sh4_pci_lock, flags); + + switch (size) { + case 1: + shift = (where & 3) << 3; + data &= ~(0xff << shift); + data |= ((val & 0xff) << shift); + break; + case 2: + shift = (where & 2) << 3; + data &= ~(0xffff << shift); + data |= ((val & 0xffff) << shift); + break; + case 4: + data = val; + break; + default: + return PCIBIOS_FUNC_NOT_SUPPORTED; + } + + pci_write_reg(data, SH4_PCIPDR); + + return PCIBIOS_SUCCESSFUL; +} + +struct pci_ops sh4_pci_ops = { + .read = sh4_pci_read, + .write = sh4_pci_write, +}; + +/* + * Not really related to pci_ops, but it's common and not worth shoving + * somewhere else for now.. + */ +static unsigned int pci_probe = PCI_PROBE_CONF1; + +int __init sh4_pci_check_direct(void) +{ + /* + * Check if configuration works. + */ + if (pci_probe & PCI_PROBE_CONF1) { + unsigned int tmp = pci_read_reg(SH4_PCIPAR); + + pci_write_reg(P1SEG, SH4_PCIPAR); + + if (pci_read_reg(SH4_PCIPAR) == P1SEG) { + pci_write_reg(tmp, SH4_PCIPAR); + printk(KERN_INFO "PCI: Using configuration type 1\n"); + request_region(PCI_REG(SH4_PCIPAR), 8, "PCI conf1"); + + return 0; + } + + pci_write_reg(tmp, SH4_PCIPAR); + } + + pr_debug("PCI: pci_check_direct failed\n"); + return -EINVAL; +} + +/* Handle generic fixups */ +static void __init pci_fixup_ide_bases(struct pci_dev *d) +{ + int i; + + /* + * PCI IDE controllers use non-standard I/O port decoding, respect it. + */ + if ((d->class >> 8) != PCI_CLASS_STORAGE_IDE) + return; + pr_debug("PCI: IDE base address fixup for %s\n", pci_name(d)); + for(i = 0; i < 4; i++) { + struct resource *r = &d->resource[i]; + + if ((r->start & ~0x80) == 0x374) { + r->start |= 2; + r->end = r->start; + } + } +} +DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, pci_fixup_ide_bases); + +char * __init pcibios_setup(char *str) +{ + if (!strcmp(str, "off")) { + pci_probe = 0; + return NULL; + } + + return str; +} diff --git a/arch/sh/drivers/pci/ops-snapgear.c b/arch/sh/drivers/pci/ops-snapgear.c index 3cbd14dd28f..53dd893d4e5 100644 --- a/arch/sh/drivers/pci/ops-snapgear.c +++ b/arch/sh/drivers/pci/ops-snapgear.c @@ -2,7 +2,7 @@ * arch/sh/drivers/pci/ops-snapgear.c * * Author: David McCullough <davidm@snapgear.com> - * + * * Ported to new API by Paul Mundt <lethal@linux-sh.org> * * Highly leveraged from pci-bigsur.c, written by Dustin McIntire. @@ -12,15 +12,11 @@ * * PCI initialization for the SnapGear boards */ - #include <linux/kernel.h> #include <linux/types.h> #include <linux/init.h> -#include <linux/delay.h> #include <linux/pci.h> - -#include <asm/io.h> -#include "pci-sh7751.h" +#include "pci-sh4.h" #define SNAPGEAR_PCI_IO 0x4000 #define SNAPGEAR_PCI_MEM 0xfd000000 @@ -43,14 +39,12 @@ static struct resource sh7751_mem_resource = { .flags = IORESOURCE_MEM, }; -extern struct pci_ops sh7751_pci_ops; - struct pci_channel board_pci_channels[] = { - { &sh7751_pci_ops, &sh7751_io_resource, &sh7751_mem_resource, 0, 0xff }, + { &sh4_pci_ops, &sh7751_io_resource, &sh7751_mem_resource, 0, 0xff }, { 0, } }; -static struct sh7751_pci_address_map sh7751_pci_map = { +static struct sh4_pci_address_map sh7751_pci_map = { .window0 = { .base = SH7751_CS2_BASE_ADDR, .size = SNAPGEAR_LSR0_SIZE, @@ -61,11 +55,11 @@ static struct sh7751_pci_address_map sh7751_pci_map = { .size = SNAPGEAR_LSR1_SIZE, }, - .flags = SH7751_PCIC_NO_RESET, + .flags = SH4_PCIC_NO_RESET, }; /* - * Initialize the SnapGear PCI interface + * Initialize the SnapGear PCI interface * Setup hardware to be Central Funtion * Copy the BSR regs to the PCI interface * Setup PCI windows into local RAM @@ -75,7 +69,7 @@ int __init pcibios_init_platform(void) return sh7751_pcic_init(&sh7751_pci_map); } -int __init pcibios_map_platform_irq(u8 slot, u8 pin) +int __init pcibios_map_platform_irq(struct pci_dev *pdev, u8 slot, u8 pin) { int irq = -1; @@ -98,4 +92,3 @@ void __init pcibios_fixup(void) { /* Nothing to fixup .. */ } - diff --git a/arch/sh/drivers/pci/ops-titan.c b/arch/sh/drivers/pci/ops-titan.c index f76e4e963ac..9c8b2027c35 100644 --- a/arch/sh/drivers/pci/ops-titan.c +++ b/arch/sh/drivers/pci/ops-titan.c @@ -16,12 +16,11 @@ #include <linux/kernel.h> #include <linux/types.h> #include <linux/init.h> -#include <linux/delay.h> #include <asm/io.h> #include <asm/titan.h> -#include "pci-sh7751.h" +#include "pci-sh4.h" -int __init pcibios_map_platform_irq(u8 slot, u8 pin) +int __init pcibios_map_platform_irq(struct pci_dev *pdev, u8 slot, u8 pin) { int irq = -1; @@ -32,7 +31,8 @@ int __init pcibios_map_platform_irq(u8 slot, u8 pin) case 3: irq = TITAN_IRQ_MPCIB; break; /* mPCI B */ case 4: irq = TITAN_IRQ_USB; break; /* USB */ default: - printk(KERN_INFO "PCI: Bad IRQ mapping request for slot %d\n", slot); + printk(KERN_INFO "PCI: Bad IRQ mapping " + "request for slot %d\n", slot); return -1; } @@ -56,15 +56,13 @@ static struct resource sh7751_mem_resource = { .flags = IORESOURCE_MEM }; -extern struct pci_ops sh7751_pci_ops; - struct pci_channel board_pci_channels[] = { - { &sh7751_pci_ops, &sh7751_io_resource, &sh7751_mem_resource, 0, 0xff }, + { &sh4_pci_ops, &sh7751_io_resource, &sh7751_mem_resource, 0, 0xff }, { NULL, NULL, NULL, 0, 0 }, }; EXPORT_SYMBOL(board_pci_channels); -static struct sh7751_pci_address_map sh7751_pci_map = { +static struct sh4_pci_address_map sh7751_pci_map = { .window0 = { .base = SH7751_CS2_BASE_ADDR, .size = SH7751_MEM_REGION_SIZE*2, /* cs2 and cs3 */ @@ -75,7 +73,7 @@ static struct sh7751_pci_address_map sh7751_pci_map = { .size = SH7751_MEM_REGION_SIZE*2, }, - .flags = SH7751_PCIC_NO_RESET, + .flags = SH4_PCIC_NO_RESET, }; int __init pcibios_init_platform(void) diff --git a/arch/sh/drivers/pci/pci-auto.c b/arch/sh/drivers/pci/pci-auto.c index d55e4661854..ecf16344f94 100644 --- a/arch/sh/drivers/pci/pci-auto.c +++ b/arch/sh/drivers/pci/pci-auto.c @@ -358,7 +358,6 @@ pciauto_postscan_setup_cardbus_bridge(struct pci_channel *hose, { u32 temp; -#if !defined(CONFIG_SH_HS7751RVOIP) && !defined(CONFIG_SH_RTS7751R2D) && !defined(CONFIG_SH_R7780RP) /* * [jsun] we always bump up baselines a little, so that if there * nothing behind P2P bridge, we don't wind up overlapping IO/MEM @@ -366,7 +365,6 @@ pciauto_postscan_setup_cardbus_bridge(struct pci_channel *hose, */ pciauto_lower_memspc += 1; pciauto_lower_iospc += 1; -#endif /* * Configure subordinate bus number. The PCI subsystem @@ -392,11 +390,6 @@ pciauto_postscan_setup_cardbus_bridge(struct pci_channel *hose, * configured by this routine to happily live behind a * P2P bridge in a system. */ -#if defined(CONFIG_SH_HS7751RVOIP) || defined(CONFIG_SH_RTS7751R2D) || defined(CONFIG_SH_R7780RP) - pciauto_lower_memspc += 0x00400000; - pciauto_lower_iospc += 0x00004000; -#endif - /* Align memory and I/O to 4KB and 4 byte boundaries. */ pciauto_lower_memspc = (pciauto_lower_memspc + (0x1000 - 1)) & ~(0x1000 - 1); @@ -467,9 +460,6 @@ pciauto_bus_scan(struct pci_channel *hose, int top_bus, int current_bus) if ((pci_class >> 16) == PCI_CLASS_BRIDGE_PCI) { DBG(" Bridge: primary=%.2x, secondary=%.2x\n", current_bus, sub_bus + 1); -#if defined(CONFIG_SH_HS7751RVOIP) || defined(CONFIG_SH_RTS7751R2D) || defined(CONFIG_SH_R7780RP) - pciauto_setup_bars(hose, top_bus, current_bus, pci_devfn, PCI_BASE_ADDRESS_1); -#endif pciauto_prescan_setup_bridge(hose, top_bus, current_bus, pci_devfn, sub_bus); DBG("Scanning sub bus %.2x, I/O 0x%.8x, Mem 0x%.8x\n", diff --git a/arch/sh/drivers/pci/pci-sh4.h b/arch/sh/drivers/pci/pci-sh4.h new file mode 100644 index 00000000000..5a61d6041f2 --- /dev/null +++ b/arch/sh/drivers/pci/pci-sh4.h @@ -0,0 +1,180 @@ +#ifndef __PCI_SH4_H +#define __PCI_SH4_H + +#ifdef CONFIG_CPU_SUBTYPE_SH7780 +#include "pci-sh7780.h" +#else +#include "pci-sh7751.h" +#endif + +#include <asm/io.h> + +/* startup values */ +#define PCI_PROBE_BIOS 1 +#define PCI_PROBE_CONF1 2 +#define PCI_PROBE_CONF2 4 +#define PCI_NO_SORT 0x100 +#define PCI_BIOS_SORT 0x200 +#define PCI_NO_CHECKS 0x400 +#define PCI_ASSIGN_ROMS 0x1000 +#define PCI_BIOS_IRQ_SCAN 0x2000 + +#define SH4_PCICR 0x100 /* PCI Control Register */ + #define SH4_PCICR_PREFIX 0xA5000000 /* CR prefix for write */ + #define SH4_PCICR_FTO 0x00000400 /* TRDY/IRDY Enable */ + #define SH4_PCICR_TRSB 0x00000200 /* Target Read Single */ + #define SH4_PCICR_BSWP 0x00000100 /* Target Byte Swap */ + #define SH4_PCICR_PLUP 0x00000080 /* Enable PCI Pullup */ + #define SH4_PCICR_ARBM 0x00000040 /* PCI Arbitration Mode */ + #define SH4_PCICR_MD 0x00000030 /* MD9 and MD10 status */ + #define SH4_PCICR_SERR 0x00000008 /* SERR output assert */ + #define SH4_PCICR_INTA 0x00000004 /* INTA output assert */ + #define SH4_PCICR_PRST 0x00000002 /* PCI Reset Assert */ + #define SH4_PCICR_CFIN 0x00000001 /* Central Fun. Init Done */ +#define SH4_PCILSR0 0x104 /* PCI Local Space Register0 */ +#define SH4_PCILSR1 0x108 /* PCI Local Space Register1 */ +#define SH4_PCILAR0 0x10C /* PCI Local Addr Register1 */ +#define SH4_PCILAR1 0x110 /* PCI Local Addr Register1 */ +#define SH4_PCIINT 0x114 /* PCI Interrupt Register */ + #define SH4_PCIINT_MLCK 0x00008000 /* Master Lock Error */ + #define SH4_PCIINT_TABT 0x00004000 /* Target Abort Error */ + #define SH4_PCIINT_TRET 0x00000200 /* Target Retry Error */ + #define SH4_PCIINT_MFDE 0x00000100 /* Master Func. Disable Error */ + #define SH4_PCIINT_PRTY 0x00000080 /* Address Parity Error */ + #define SH4_PCIINT_SERR 0x00000040 /* SERR Detection Error */ + #define SH4_PCIINT_TWDP 0x00000020 /* Tgt. Write Parity Error */ + #define SH4_PCIINT_TRDP 0x00000010 /* Tgt. Read Parity Err Det. */ + #define SH4_PCIINT_MTABT 0x00000008 /* Master-Tgt. Abort Error */ + #define SH4_PCIINT_MMABT 0x00000004 /* Master-Master Abort Error */ + #define SH4_PCIINT_MWPD 0x00000002 /* Master Write PERR Detect */ + #define SH4_PCIINT_MRPD |