aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/sysdev
diff options
context:
space:
mode:
authorRojhalat Ibrahim <imr@rtschenk.de>2013-04-08 04:15:28 -0400
committerKumar Gala <galak@kernel.crashing.org>2013-04-10 11:15:28 -0400
commit50d8f87d2b39313dae9d0a2d9b23d377328f2f7b (patch)
tree10d88cde5443443f400c596a60fd0c5c406da8c3 /arch/powerpc/sysdev
parent34642bbb3d12121333efcf4ea7dfe66685e403a1 (diff)
powerpc/fsl-pci Make PCIe hotplug work with Freescale PCIe controllers
Up to now the PCIe link status on Freescale PCIe controllers was only checked once at boot time. So hotplug did not work. With this patch the link status is checked on every config read. PCIe devices not present at boot time are found after doing 'echo 1 >/sys/bus/pci/rescan'. Signed-off-by: Rojhalat Ibrahim <imr@rtschenk.de> Signed-off-by: Kumar Gala <galak@kernel.crashing.org>
Diffstat (limited to 'arch/powerpc/sysdev')
-rw-r--r--arch/powerpc/sysdev/fsl_pci.c51
-rw-r--r--arch/powerpc/sysdev/indirect_pci.c10
2 files changed, 48 insertions, 13 deletions
diff --git a/arch/powerpc/sysdev/fsl_pci.c b/arch/powerpc/sysdev/fsl_pci.c
index 83918c3e665a..40ffe29b7594 100644
--- a/arch/powerpc/sysdev/fsl_pci.c
+++ b/arch/powerpc/sysdev/fsl_pci.c
@@ -54,12 +54,22 @@ static void quirk_fsl_pcie_header(struct pci_dev *dev)
54 return; 54 return;
55} 55}
56 56
57static int __init fsl_pcie_check_link(struct pci_controller *hose) 57static int fsl_indirect_read_config(struct pci_bus *, unsigned int,
58 int, int, u32 *);
59
60static int fsl_pcie_check_link(struct pci_controller *hose)
58{ 61{
59 u32 val; 62 u32 val = 0;
60 63
61 if (hose->indirect_type & PPC_INDIRECT_TYPE_FSL_CFG_REG_LINK) { 64 if (hose->indirect_type & PPC_INDIRECT_TYPE_FSL_CFG_REG_LINK) {
62 early_read_config_dword(hose, 0, 0, PCIE_LTSSM, &val); 65 if (hose->ops->read == fsl_indirect_read_config) {
66 struct pci_bus bus;
67 bus.number = 0;
68 bus.sysdata = hose;
69 bus.ops = hose->ops;
70 indirect_read_config(&bus, 0, PCIE_LTSSM, 4, &val);
71 } else
72 early_read_config_dword(hose, 0, 0, PCIE_LTSSM, &val);
63 if (val < PCIE_LTSSM_L0) 73 if (val < PCIE_LTSSM_L0)
64 return 1; 74 return 1;
65 } else { 75 } else {
@@ -74,6 +84,33 @@ static int __init fsl_pcie_check_link(struct pci_controller *hose)
74 return 0; 84 return 0;
75} 85}
76 86
87static int fsl_indirect_read_config(struct pci_bus *bus, unsigned int devfn,
88 int offset, int len, u32 *val)
89{
90 struct pci_controller *hose = pci_bus_to_host(bus);
91
92 if (fsl_pcie_check_link(hose))
93 hose->indirect_type |= PPC_INDIRECT_TYPE_NO_PCIE_LINK;
94 else
95 hose->indirect_type &= ~PPC_INDIRECT_TYPE_NO_PCIE_LINK;
96
97 return indirect_read_config(bus, devfn, offset, len, val);
98}
99
100static struct pci_ops fsl_indirect_pci_ops =
101{
102 .read = fsl_indirect_read_config,
103 .write = indirect_write_config,
104};
105
106static void __init fsl_setup_indirect_pci(struct pci_controller* hose,
107 resource_size_t cfg_addr,
108 resource_size_t cfg_data, u32 flags)
109{
110 setup_indirect_pci(hose, cfg_addr, cfg_data, flags);
111 hose->ops = &fsl_indirect_pci_ops;
112}
113
77#if defined(CONFIG_FSL_SOC_BOOKE) || defined(CONFIG_PPC_86xx) 114#if defined(CONFIG_FSL_SOC_BOOKE) || defined(CONFIG_PPC_86xx)
78 115
79#define MAX_PHYS_ADDR_BITS 40 116#define MAX_PHYS_ADDR_BITS 40
@@ -469,8 +506,8 @@ int __init fsl_add_bridge(struct platform_device *pdev, int is_primary)
469 if (!hose->private_data) 506 if (!hose->private_data)
470 goto no_bridge; 507 goto no_bridge;
471 508
472 setup_indirect_pci(hose, rsrc.start, rsrc.start + 0x4, 509 fsl_setup_indirect_pci(hose, rsrc.start, rsrc.start + 0x4,
473 PPC_INDIRECT_TYPE_BIG_ENDIAN); 510 PPC_INDIRECT_TYPE_BIG_ENDIAN);
474 511
475 if (in_be32(&pci->block_rev1) < PCIE_IP_REV_3_0) 512 if (in_be32(&pci->block_rev1) < PCIE_IP_REV_3_0)
476 hose->indirect_type |= PPC_INDIRECT_TYPE_FSL_CFG_REG_LINK; 513 hose->indirect_type |= PPC_INDIRECT_TYPE_FSL_CFG_REG_LINK;
@@ -779,8 +816,8 @@ int __init mpc83xx_add_bridge(struct device_node *dev)
779 if (ret) 816 if (ret)
780 goto err0; 817 goto err0;
781 } else { 818 } else {
782 setup_indirect_pci(hose, rsrc_cfg.start, 819 fsl_setup_indirect_pci(hose, rsrc_cfg.start,
783 rsrc_cfg.start + 4, 0); 820 rsrc_cfg.start + 4, 0);
784 } 821 }
785 822
786 printk(KERN_INFO "Found FSL PCI host bridge at 0x%016llx. " 823 printk(KERN_INFO "Found FSL PCI host bridge at 0x%016llx. "
diff --git a/arch/powerpc/sysdev/indirect_pci.c b/arch/powerpc/sysdev/indirect_pci.c
index 82fdad885d20..c6c8b526a4f6 100644
--- a/arch/powerpc/sysdev/indirect_pci.c
+++ b/arch/powerpc/sysdev/indirect_pci.c
@@ -20,9 +20,8 @@
20#include <asm/pci-bridge.h> 20#include <asm/pci-bridge.h>
21#include <asm/machdep.h> 21#include <asm/machdep.h>
22 22
23static int 23int indirect_read_config(struct pci_bus *bus, unsigned int devfn,
24indirect_read_config(struct pci_bus *bus, unsigned int devfn, int offset, 24 int offset, int len, u32 *val)
25 int len, u32 *val)
26{ 25{
27 struct pci_controller *hose = pci_bus_to_host(bus); 26 struct pci_controller *hose = pci_bus_to_host(bus);
28 volatile void __iomem *cfg_data; 27 volatile void __iomem *cfg_data;
@@ -78,9 +77,8 @@ indirect_read_config(struct pci_bus *bus, unsigned int devfn, int offset,
78 return PCIBIOS_SUCCESSFUL; 77 return PCIBIOS_SUCCESSFUL;
79} 78}
80 79
81static int 80int indirect_write_config(struct pci_bus *bus, unsigned int devfn,
82indirect_write_config(struct pci_bus *bus, unsigned int devfn, int offset, 81 int offset, int len, u32 val)
83 int len, u32 val)
84{ 82{
85 struct pci_controller *hose = pci_bus_to_host(bus); 83 struct pci_controller *hose = pci_bus_to_host(bus);
86 volatile void __iomem *cfg_data; 84 volatile void __iomem *cfg_data;