diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2011-07-26 07:59:39 +0200 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-07-26 07:59:39 +0200 |
commit | 184475029a724b6b900d88fc3a5f462a6107d5af (patch) | |
tree | 408320b46df221a2424bf94282b1b8e5b7aff7a1 /arch/powerpc/sysdev/ppc4xx_pci.c | |
parent | Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ger... (diff) | |
parent | drivers/virt: add missing linux/interrupt.h to fsl_hypervisor.c (diff) | |
download | linux-184475029a724b6b900d88fc3a5f462a6107d5af.tar.xz linux-184475029a724b6b900d88fc3a5f462a6107d5af.zip |
Merge branch 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc
* 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc: (99 commits)
drivers/virt: add missing linux/interrupt.h to fsl_hypervisor.c
powerpc/85xx: fix mpic configuration in CAMP mode
powerpc: Copy back TIF flags on return from softirq stack
powerpc/64: Make server perfmon only built on ppc64 server devices
powerpc/pseries: Fix hvc_vio.c build due to recent changes
powerpc: Exporting boot_cpuid_phys
powerpc: Add CFAR to oops output
hvc_console: Add kdb support
powerpc/pseries: Fix hvterm_raw_get_chars to accept < 16 chars, fixing xmon
powerpc/irq: Quieten irq mapping printks
powerpc: Enable lockup and hung task detectors in pseries and ppc64 defeconfigs
powerpc: Add mpt2sas driver to pseries and ppc64 defconfig
powerpc: Disable IRQs off tracer in ppc64 defconfig
powerpc: Sync pseries and ppc64 defconfigs
powerpc/pseries/hvconsole: Fix dropped console output
hvc_console: Improve tty/console put_chars handling
powerpc/kdump: Fix timeout in crash_kexec_wait_realmode
powerpc/mm: Fix output of total_ram.
powerpc/cpufreq: Add cpufreq driver for Momentum Maple boards
powerpc: Correct annotations of pmu registration functions
...
Fix up trivial Kconfig/Makefile conflicts in arch/powerpc, drivers, and
drivers/cpufreq
Diffstat (limited to 'arch/powerpc/sysdev/ppc4xx_pci.c')
-rw-r--r-- | arch/powerpc/sysdev/ppc4xx_pci.c | 147 |
1 files changed, 82 insertions, 65 deletions
diff --git a/arch/powerpc/sysdev/ppc4xx_pci.c b/arch/powerpc/sysdev/ppc4xx_pci.c index deda60a7f996..2ec4f3bb8160 100644 --- a/arch/powerpc/sysdev/ppc4xx_pci.c +++ b/arch/powerpc/sysdev/ppc4xx_pci.c @@ -650,12 +650,74 @@ struct ppc4xx_pciex_hwops int (*core_init)(struct device_node *np); int (*port_init_hw)(struct ppc4xx_pciex_port *port); int (*setup_utl)(struct ppc4xx_pciex_port *port); + void (*check_link)(struct ppc4xx_pciex_port *port); }; static struct ppc4xx_pciex_hwops *ppc4xx_pciex_hwops; #ifdef CONFIG_44x +static int __init ppc4xx_pciex_wait_on_sdr(struct ppc4xx_pciex_port *port, + unsigned int sdr_offset, + unsigned int mask, + unsigned int value, + int timeout_ms) +{ + u32 val; + + while(timeout_ms--) { + val = mfdcri(SDR0, port->sdr_base + sdr_offset); + if ((val & mask) == value) { + pr_debug("PCIE%d: Wait on SDR %x success with tm %d (%08x)\n", + port->index, sdr_offset, timeout_ms, val); + return 0; + } + msleep(1); + } + return -1; +} + +static int __init ppc4xx_pciex_port_reset_sdr(struct ppc4xx_pciex_port *port) +{ + /* Wait for reset to complete */ + if (ppc4xx_pciex_wait_on_sdr(port, PESDRn_RCSSTS, 1 << 20, 0, 10)) { + printk(KERN_WARNING "PCIE%d: PGRST failed\n", + port->index); + return -1; + } + return 0; +} + +static void __init ppc4xx_pciex_check_link_sdr(struct ppc4xx_pciex_port *port) +{ + printk(KERN_INFO "PCIE%d: Checking link...\n", port->index); + + /* Check for card presence detect if supported, if not, just wait for + * link unconditionally. + * + * note that we don't fail if there is no link, we just filter out + * config space accesses. That way, it will be easier to implement + * hotplug later on. + */ + if (!port->has_ibpre || + !ppc4xx_pciex_wait_on_sdr(port, PESDRn_LOOP, + 1 << 28, 1 << 28, 100)) { + printk(KERN_INFO + "PCIE%d: Device detected, waiting for link...\n", + port->index); + if (ppc4xx_pciex_wait_on_sdr(port, PESDRn_LOOP, + 0x1000, 0x1000, 2000)) + printk(KERN_WARNING + "PCIE%d: Link up failed\n", port->index); + else { + printk(KERN_INFO + "PCIE%d: link is up !\n", port->index); + port->link = 1; + } + } else + printk(KERN_INFO "PCIE%d: No device detected.\n", port->index); +} + /* Check various reset bits of the 440SPe PCIe core */ static int __init ppc440spe_pciex_check_reset(struct device_node *np) { @@ -806,7 +868,7 @@ static int ppc440spe_pciex_init_port_hw(struct ppc4xx_pciex_port *port) dcri_clrset(SDR0, port->sdr_base + PESDRn_RCSSET, (1 << 24) | (1 << 16), 1 << 12); - return 0; + return ppc4xx_pciex_port_reset_sdr(port); } static int ppc440speA_pciex_init_port_hw(struct ppc4xx_pciex_port *port) @@ -856,6 +918,7 @@ static struct ppc4xx_pciex_hwops ppc440speA_pcie_hwops __initdata = .core_init = ppc440spe_pciex_core_init, .port_init_hw = ppc440speA_pciex_init_port_hw, .setup_utl = ppc440speA_pciex_init_utl, + .check_link = ppc4xx_pciex_check_link_sdr, }; static struct ppc4xx_pciex_hwops ppc440speB_pcie_hwops __initdata = @@ -863,6 +926,7 @@ static struct ppc4xx_pciex_hwops ppc440speB_pcie_hwops __initdata = .core_init = ppc440spe_pciex_core_init, .port_init_hw = ppc440speB_pciex_init_port_hw, .setup_utl = ppc440speB_pciex_init_utl, + .check_link = ppc4xx_pciex_check_link_sdr, }; static int __init ppc460ex_pciex_core_init(struct device_node *np) @@ -944,7 +1008,7 @@ static int ppc460ex_pciex_init_port_hw(struct ppc4xx_pciex_port *port) port->has_ibpre = 1; - return 0; + return ppc4xx_pciex_port_reset_sdr(port); } static int ppc460ex_pciex_init_utl(struct ppc4xx_pciex_port *port) @@ -972,6 +1036,7 @@ static struct ppc4xx_pciex_hwops ppc460ex_pcie_hwops __initdata = .core_init = ppc460ex_pciex_core_init, .port_init_hw = ppc460ex_pciex_init_port_hw, .setup_utl = ppc460ex_pciex_init_utl, + .check_link = ppc4xx_pciex_check_link_sdr, }; static int __init ppc460sx_pciex_core_init(struct device_node *np) @@ -1075,7 +1140,7 @@ static int ppc460sx_pciex_init_port_hw(struct ppc4xx_pciex_port *port) port->has_ibpre = 1; - return 0; + return ppc4xx_pciex_port_reset_sdr(port); } static int ppc460sx_pciex_init_utl(struct ppc4xx_pciex_port *port) @@ -1089,6 +1154,7 @@ static struct ppc4xx_pciex_hwops ppc460sx_pcie_hwops __initdata = { .core_init = ppc460sx_pciex_core_init, .port_init_hw = ppc460sx_pciex_init_port_hw, .setup_utl = ppc460sx_pciex_init_utl, + .check_link = ppc4xx_pciex_check_link_sdr, }; #endif /* CONFIG_44x */ @@ -1154,7 +1220,7 @@ static int ppc405ex_pciex_init_port_hw(struct ppc4xx_pciex_port *port) port->has_ibpre = 1; - return 0; + return ppc4xx_pciex_port_reset_sdr(port); } static int ppc405ex_pciex_init_utl(struct ppc4xx_pciex_port *port) @@ -1183,11 +1249,11 @@ static struct ppc4xx_pciex_hwops ppc405ex_pcie_hwops __initdata = .core_init = ppc405ex_pciex_core_init, .port_init_hw = ppc405ex_pciex_init_port_hw, .setup_utl = ppc405ex_pciex_init_utl, + .check_link = ppc4xx_pciex_check_link_sdr, }; #endif /* CONFIG_40x */ - /* Check that the core has been initied and if not, do it */ static int __init ppc4xx_pciex_check_core_init(struct device_node *np) { @@ -1261,26 +1327,6 @@ static void __init ppc4xx_pciex_port_init_mapping(struct ppc4xx_pciex_port *port dcr_write(port->dcrs, DCRO_PEGPL_MSGMSK, 0); } -static int __init ppc4xx_pciex_wait_on_sdr(struct ppc4xx_pciex_port *port, - unsigned int sdr_offset, - unsigned int mask, - unsigned int value, - int timeout_ms) -{ - u32 val; - - while(timeout_ms--) { - val = mfdcri(SDR0, port->sdr_base + sdr_offset); - if ((val & mask) == value) { - pr_debug("PCIE%d: Wait on SDR %x success with tm %d (%08x)\n", - port->index, sdr_offset, timeout_ms, val); - return 0; - } - msleep(1); - } - return -1; -} - static int __init ppc4xx_pciex_port_init(struct ppc4xx_pciex_port *port) { int rc = 0; @@ -1291,40 +1337,8 @@ static int __init ppc4xx_pciex_port_init(struct ppc4xx_pciex_port *port) if (rc != 0) return rc; - printk(KERN_INFO "PCIE%d: Checking link...\n", - port->index); - - /* Wait for reset to complete */ - if (ppc4xx_pciex_wait_on_sdr(port, PESDRn_RCSSTS, 1 << 20, 0, 10)) { - printk(KERN_WARNING "PCIE%d: PGRST failed\n", - port->index); - return -1; - } - - /* Check for card presence detect if supported, if not, just wait for - * link unconditionally. - * - * note that we don't fail if there is no link, we just filter out - * config space accesses. That way, it will be easier to implement - * hotplug later on. - */ - if (!port->has_ibpre || - !ppc4xx_pciex_wait_on_sdr(port, PESDRn_LOOP, - 1 << 28, 1 << 28, 100)) { - printk(KERN_INFO - "PCIE%d: Device detected, waiting for link...\n", - port->index); - if (ppc4xx_pciex_wait_on_sdr(port, PESDRn_LOOP, - 0x1000, 0x1000, 2000)) - printk(KERN_WARNING - "PCIE%d: Link up failed\n", port->index); - else { - printk(KERN_INFO - "PCIE%d: link is up !\n", port->index); - port->link = 1; - } - } else - printk(KERN_INFO "PCIE%d: No device detected.\n", port->index); + if (ppc4xx_pciex_hwops->check_link) + ppc4xx_pciex_hwops->check_link(port); /* * Initialize mapping: disable all regions and configure @@ -1347,14 +1361,17 @@ static int __init ppc4xx_pciex_port_init(struct ppc4xx_pciex_port *port) /* * Check for VC0 active and assert RDY. */ - if (port->link && - ppc4xx_pciex_wait_on_sdr(port, PESDRn_RCSSTS, - 1 << 16, 1 << 16, 5000)) { - printk(KERN_INFO "PCIE%d: VC0 not active\n", port->index); - port->link = 0; + if (port->sdr_base) { + if (port->link && + ppc4xx_pciex_wait_on_sdr(port, PESDRn_RCSSTS, + 1 << 16, 1 << 16, 5000)) { + printk(KERN_INFO "PCIE%d: VC0 not active\n", port->index); + port->link = 0; + } + + dcri_clrset(SDR0, port->sdr_base + PESDRn_RCSSET, 0, 1 << 20); } - dcri_clrset(SDR0, port->sdr_base + PESDRn_RCSSET, 0, 1 << 20); msleep(100); return 0; |