diff options
Diffstat (limited to 'arch/sh/drivers/pci')
-rw-r--r-- | arch/sh/drivers/pci/fixups-landisk.c | 28 | ||||
-rw-r--r-- | arch/sh/drivers/pci/pci.c | 3 | ||||
-rw-r--r-- | arch/sh/drivers/pci/pcie-sh7786.c | 46 |
3 files changed, 56 insertions, 21 deletions
diff --git a/arch/sh/drivers/pci/fixups-landisk.c b/arch/sh/drivers/pci/fixups-landisk.c index bb1a6bb5149e..95c6e2d94a0a 100644 --- a/arch/sh/drivers/pci/fixups-landisk.c +++ b/arch/sh/drivers/pci/fixups-landisk.c @@ -1,9 +1,10 @@ /* - * arch/sh/drivers/pci/ops-landisk.c + * arch/sh/drivers/pci/fixups-landisk.c * * PCI initialization for the I-O DATA Device, Inc. LANDISK board * * Copyright (C) 2006 kogiidena + * Copyright (C) 2010 Nobuhiro Iwamatsu * * May be copied or modified under the terms of the GNU General Public * License. See linux/COPYING for more information. @@ -15,6 +16,9 @@ #include <linux/pci.h> #include "pci-sh4.h" +#define PCIMCR_MRSET_OFF 0xBFFFFFFF +#define PCIMCR_RFSH_OFF 0xFFFFFFFB + int pcibios_map_platform_irq(struct pci_dev *pdev, u8 slot, u8 pin) { /* @@ -26,9 +30,29 @@ int pcibios_map_platform_irq(struct pci_dev *pdev, u8 slot, u8 pin) int irq = ((slot + pin - 1) & 0x3) + 5; if ((slot | (pin - 1)) > 0x3) { - printk("PCI: Bad IRQ mapping request for slot %d pin %c\n", + printk(KERN_WARNING "PCI: Bad IRQ mapping request for slot %d pin %c\n", slot, pin - 1 + 'A'); return -1; } return irq; } + +int pci_fixup_pcic(struct pci_channel *chan) +{ + unsigned long bcr1, mcr; + + bcr1 = __raw_readl(SH7751_BCR1); + bcr1 |= 0x40080000; /* Enable Bit 19 BREQEN, set PCIC to slave */ + pci_write_reg(chan, bcr1, SH4_PCIBCR1); + + mcr = __raw_readl(SH7751_MCR); + mcr = (mcr & PCIMCR_MRSET_OFF) & PCIMCR_RFSH_OFF; + pci_write_reg(chan, mcr, SH4_PCIMCR); + + pci_write_reg(chan, 0x0c000000, SH7751_PCICONF5); + pci_write_reg(chan, 0xd0000000, SH7751_PCICONF6); + pci_write_reg(chan, 0x0c000000, SH4_PCILAR0); + pci_write_reg(chan, 0x00000000, SH4_PCILAR1); + + return 0; +} diff --git a/arch/sh/drivers/pci/pci.c b/arch/sh/drivers/pci/pci.c index 60ee09a4e121..a09c77dd09db 100644 --- a/arch/sh/drivers/pci/pci.c +++ b/arch/sh/drivers/pci/pci.c @@ -382,14 +382,13 @@ static void __iomem *ioport_map_pci(struct pci_dev *dev, struct pci_channel *chan = dev->sysdata; if (unlikely(!chan->io_map_base)) { - chan->io_map_base = generic_io_base; + chan->io_map_base = sh_io_port_base; if (pci_domains_supported) panic("To avoid data corruption io_map_base MUST be " "set with multiple PCI domains."); } - return (void __iomem *)(chan->io_map_base + port); } diff --git a/arch/sh/drivers/pci/pcie-sh7786.c b/arch/sh/drivers/pci/pcie-sh7786.c index 96e9b058aa1d..4418f9070ed1 100644 --- a/arch/sh/drivers/pci/pcie-sh7786.c +++ b/arch/sh/drivers/pci/pcie-sh7786.c @@ -1,16 +1,19 @@ /* * Low-Level PCI Express Support for the SH7786 * - * Copyright (C) 2009 - 2010 Paul Mundt + * Copyright (C) 2009 - 2011 Paul Mundt * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive * for more details. */ +#define pr_fmt(fmt) "PCI: " fmt + #include <linux/pci.h> #include <linux/init.h> #include <linux/kernel.h> #include <linux/io.h> +#include <linux/async.h> #include <linux/delay.h> #include <linux/slab.h> #include <linux/clk.h> @@ -31,7 +34,7 @@ static unsigned int nr_ports; static struct sh7786_pcie_hwops { int (*core_init)(void); - int (*port_init_hw)(struct sh7786_pcie_port *port); + async_func_ptr *port_init_hw; } *sh7786_pcie_hwops; static struct resource sh7786_pci0_resources[] = { @@ -474,8 +477,9 @@ static int __init sh7786_pcie_core_init(void) return test_mode_pin(MODE_PIN12) ? 3 : 2; } -static int __init sh7786_pcie_init_hw(struct sh7786_pcie_port *port) +static void __init sh7786_pcie_init_hw(void *data, async_cookie_t cookie) { + struct sh7786_pcie_port *port = data; int ret; /* @@ -488,18 +492,30 @@ static int __init sh7786_pcie_init_hw(struct sh7786_pcie_port *port) * Setup clocks, needed both for PHY and PCIe registers. */ ret = pcie_clk_init(port); - if (unlikely(ret < 0)) - return ret; + if (unlikely(ret < 0)) { + pr_err("clock initialization failed for port#%d\n", + port->index); + return; + } ret = phy_init(port); - if (unlikely(ret < 0)) - return ret; + if (unlikely(ret < 0)) { + pr_err("phy initialization failed for port#%d\n", + port->index); + return; + } ret = pcie_init(port); - if (unlikely(ret < 0)) - return ret; + if (unlikely(ret < 0)) { + pr_err("core initialization failed for port#%d\n", + port->index); + return; + } - return register_pci_controller(port->hose); + /* In the interest of preserving device ordering, synchronize */ + async_synchronize_cookie(cookie); + + register_pci_controller(port->hose); } static struct sh7786_pcie_hwops sh7786_65nm_pcie_hwops __initdata = { @@ -510,7 +526,7 @@ static struct sh7786_pcie_hwops sh7786_65nm_pcie_hwops __initdata = { static int __init sh7786_pcie_init(void) { struct clk *platclk; - int ret = 0, i; + int i; printk(KERN_NOTICE "PCI: Starting initialization.\n"); @@ -552,14 +568,10 @@ static int __init sh7786_pcie_init(void) port->hose = sh7786_pci_channels + i; port->hose->io_map_base = port->hose->resources[0].start; - ret |= sh7786_pcie_hwops->port_init_hw(port); + async_schedule(sh7786_pcie_hwops->port_init_hw, port); } - if (unlikely(ret)) { - clk_disable(platclk); - clk_put(platclk); - return ret; - } + async_synchronize_full(); return 0; } |