Commit 50d8f87d authored by Rojhalat Ibrahim's avatar Rojhalat Ibrahim Committed by Kumar Gala

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: default avatarRojhalat Ibrahim <imr@rtschenk.de>
Signed-off-by: default avatarKumar Gala <galak@kernel.crashing.org>
parent 34642bbb
...@@ -120,6 +120,12 @@ extern void setup_indirect_pci(struct pci_controller* hose, ...@@ -120,6 +120,12 @@ extern void setup_indirect_pci(struct pci_controller* hose,
resource_size_t cfg_addr, resource_size_t cfg_addr,
resource_size_t cfg_data, u32 flags); resource_size_t cfg_data, u32 flags);
extern int indirect_read_config(struct pci_bus *bus, unsigned int devfn,
int offset, int len, u32 *val);
extern int indirect_write_config(struct pci_bus *bus, unsigned int devfn,
int offset, int len, u32 val);
static inline struct pci_controller *pci_bus_to_host(const struct pci_bus *bus) static inline struct pci_controller *pci_bus_to_host(const struct pci_bus *bus)
{ {
return bus->sysdata; return bus->sysdata;
......
...@@ -54,12 +54,22 @@ static void quirk_fsl_pcie_header(struct pci_dev *dev) ...@@ -54,12 +54,22 @@ static void quirk_fsl_pcie_header(struct pci_dev *dev)
return; return;
} }
static int __init fsl_pcie_check_link(struct pci_controller *hose) static int fsl_indirect_read_config(struct pci_bus *, unsigned int,
int, int, u32 *);
static int fsl_pcie_check_link(struct pci_controller *hose)
{ {
u32 val; u32 val = 0;
if (hose->indirect_type & PPC_INDIRECT_TYPE_FSL_CFG_REG_LINK) { if (hose->indirect_type & PPC_INDIRECT_TYPE_FSL_CFG_REG_LINK) {
early_read_config_dword(hose, 0, 0, PCIE_LTSSM, &val); if (hose->ops->read == fsl_indirect_read_config) {
struct pci_bus bus;
bus.number = 0;
bus.sysdata = hose;
bus.ops = hose->ops;
indirect_read_config(&bus, 0, PCIE_LTSSM, 4, &val);
} else
early_read_config_dword(hose, 0, 0, PCIE_LTSSM, &val);
if (val < PCIE_LTSSM_L0) if (val < PCIE_LTSSM_L0)
return 1; return 1;
} else { } else {
...@@ -74,6 +84,33 @@ static int __init fsl_pcie_check_link(struct pci_controller *hose) ...@@ -74,6 +84,33 @@ static int __init fsl_pcie_check_link(struct pci_controller *hose)
return 0; return 0;
} }
static int fsl_indirect_read_config(struct pci_bus *bus, unsigned int devfn,
int offset, int len, u32 *val)
{
struct pci_controller *hose = pci_bus_to_host(bus);
if (fsl_pcie_check_link(hose))
hose->indirect_type |= PPC_INDIRECT_TYPE_NO_PCIE_LINK;
else
hose->indirect_type &= ~PPC_INDIRECT_TYPE_NO_PCIE_LINK;
return indirect_read_config(bus, devfn, offset, len, val);
}
static struct pci_ops fsl_indirect_pci_ops =
{
.read = fsl_indirect_read_config,
.write = indirect_write_config,
};
static void __init fsl_setup_indirect_pci(struct pci_controller* hose,
resource_size_t cfg_addr,
resource_size_t cfg_data, u32 flags)
{
setup_indirect_pci(hose, cfg_addr, cfg_data, flags);
hose->ops = &fsl_indirect_pci_ops;
}
#if defined(CONFIG_FSL_SOC_BOOKE) || defined(CONFIG_PPC_86xx) #if defined(CONFIG_FSL_SOC_BOOKE) || defined(CONFIG_PPC_86xx)
#define MAX_PHYS_ADDR_BITS 40 #define MAX_PHYS_ADDR_BITS 40
...@@ -469,8 +506,8 @@ int __init fsl_add_bridge(struct platform_device *pdev, int is_primary) ...@@ -469,8 +506,8 @@ int __init fsl_add_bridge(struct platform_device *pdev, int is_primary)
if (!hose->private_data) if (!hose->private_data)
goto no_bridge; goto no_bridge;
setup_indirect_pci(hose, rsrc.start, rsrc.start + 0x4, fsl_setup_indirect_pci(hose, rsrc.start, rsrc.start + 0x4,
PPC_INDIRECT_TYPE_BIG_ENDIAN); PPC_INDIRECT_TYPE_BIG_ENDIAN);
if (in_be32(&pci->block_rev1) < PCIE_IP_REV_3_0) if (in_be32(&pci->block_rev1) < PCIE_IP_REV_3_0)
hose->indirect_type |= PPC_INDIRECT_TYPE_FSL_CFG_REG_LINK; hose->indirect_type |= PPC_INDIRECT_TYPE_FSL_CFG_REG_LINK;
...@@ -779,8 +816,8 @@ int __init mpc83xx_add_bridge(struct device_node *dev) ...@@ -779,8 +816,8 @@ int __init mpc83xx_add_bridge(struct device_node *dev)
if (ret) if (ret)
goto err0; goto err0;
} else { } else {
setup_indirect_pci(hose, rsrc_cfg.start, fsl_setup_indirect_pci(hose, rsrc_cfg.start,
rsrc_cfg.start + 4, 0); rsrc_cfg.start + 4, 0);
} }
printk(KERN_INFO "Found FSL PCI host bridge at 0x%016llx. " printk(KERN_INFO "Found FSL PCI host bridge at 0x%016llx. "
......
...@@ -20,9 +20,8 @@ ...@@ -20,9 +20,8 @@
#include <asm/pci-bridge.h> #include <asm/pci-bridge.h>
#include <asm/machdep.h> #include <asm/machdep.h>
static int int indirect_read_config(struct pci_bus *bus, unsigned int devfn,
indirect_read_config(struct pci_bus *bus, unsigned int devfn, int offset, int offset, int len, u32 *val)
int len, u32 *val)
{ {
struct pci_controller *hose = pci_bus_to_host(bus); struct pci_controller *hose = pci_bus_to_host(bus);
volatile void __iomem *cfg_data; volatile void __iomem *cfg_data;
...@@ -78,9 +77,8 @@ indirect_read_config(struct pci_bus *bus, unsigned int devfn, int offset, ...@@ -78,9 +77,8 @@ indirect_read_config(struct pci_bus *bus, unsigned int devfn, int offset,
return PCIBIOS_SUCCESSFUL; return PCIBIOS_SUCCESSFUL;
} }
static int int indirect_write_config(struct pci_bus *bus, unsigned int devfn,
indirect_write_config(struct pci_bus *bus, unsigned int devfn, int offset, int offset, int len, u32 val)
int len, u32 val)
{ {
struct pci_controller *hose = pci_bus_to_host(bus); struct pci_controller *hose = pci_bus_to_host(bus);
volatile void __iomem *cfg_data; volatile void __iomem *cfg_data;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment