Commit d82fb31a authored by Kleber Sacilotto de Souza's avatar Kleber Sacilotto de Souza Committed by Benjamin Herrenschmidt
Browse files

powerpc/pseries: Perform proper max_bus_speed detection



On pseries machines the detection for max_bus_speed should be done
through an OpenFirmware property. This patch adds a function to perform
this detection and a hook to perform dynamic adding of the function only
for pseries. This is done by overwriting the weak
pcibios_root_bridge_prepare function which is called by
pci_create_root_bus().

From: Lucas Kannebley Tavares <lucaskt@linux.vnet.ibm.com>
Signed-off-by: default avatarKleber Sacilotto de Souza <klebers@linux.vnet.ibm.com>
Signed-off-by: default avatarBenjamin Herrenschmidt <benh@kernel.crashing.org>
parent e61133dd
...@@ -29,6 +29,7 @@ struct rtc_time; ...@@ -29,6 +29,7 @@ struct rtc_time;
struct file; struct file;
struct pci_controller; struct pci_controller;
struct kimage; struct kimage;
struct pci_host_bridge;
struct machdep_calls { struct machdep_calls {
char *name; char *name;
...@@ -108,6 +109,8 @@ struct machdep_calls { ...@@ -108,6 +109,8 @@ struct machdep_calls {
void (*pcibios_fixup)(void); void (*pcibios_fixup)(void);
int (*pci_probe_mode)(struct pci_bus *); int (*pci_probe_mode)(struct pci_bus *);
void (*pci_irq_fixup)(struct pci_dev *dev); void (*pci_irq_fixup)(struct pci_dev *dev);
int (*pcibios_root_bridge_prepare)(struct pci_host_bridge
*bridge);
/* To setup PHBs when using automatic OF platform driver for PCI */ /* To setup PHBs when using automatic OF platform driver for PCI */
int (*pci_setup_phb)(struct pci_controller *host); int (*pci_setup_phb)(struct pci_controller *host);
......
...@@ -845,6 +845,14 @@ int pci_proc_domain(struct pci_bus *bus) ...@@ -845,6 +845,14 @@ int pci_proc_domain(struct pci_bus *bus)
return 1; return 1;
} }
int pcibios_root_bridge_prepare(struct pci_host_bridge *bridge)
{
if (ppc_md.pcibios_root_bridge_prepare)
return ppc_md.pcibios_root_bridge_prepare(bridge);
return 0;
}
/* This header fixup will do the resource fixup for all devices as they are /* This header fixup will do the resource fixup for all devices as they are
* probed, but not for bridge ranges * probed, but not for bridge ranges
*/ */
......
...@@ -108,3 +108,56 @@ static void fixup_winbond_82c105(struct pci_dev* dev) ...@@ -108,3 +108,56 @@ static void fixup_winbond_82c105(struct pci_dev* dev)
} }
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_WINBOND, PCI_DEVICE_ID_WINBOND_82C105, DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_WINBOND, PCI_DEVICE_ID_WINBOND_82C105,
fixup_winbond_82c105); fixup_winbond_82c105);
int pseries_root_bridge_prepare(struct pci_host_bridge *bridge)
{
struct device_node *dn, *pdn;
struct pci_bus *bus;
const uint32_t *pcie_link_speed_stats;
bus = bridge->bus;
dn = pcibios_get_phb_of_node(bus);
if (!dn)
return 0;
for (pdn = dn; pdn != NULL; pdn = of_get_next_parent(pdn)) {
pcie_link_speed_stats = (const uint32_t *) of_get_property(pdn,
"ibm,pcie-link-speed-stats", NULL);
if (pcie_link_speed_stats)
break;
}
of_node_put(pdn);
if (!pcie_link_speed_stats) {
pr_err("no ibm,pcie-link-speed-stats property\n");
return 0;
}
switch (pcie_link_speed_stats[0]) {
case 0x01:
bus->max_bus_speed = PCIE_SPEED_2_5GT;
break;
case 0x02:
bus->max_bus_speed = PCIE_SPEED_5_0GT;
break;
default:
bus->max_bus_speed = PCI_SPEED_UNKNOWN;
break;
}
switch (pcie_link_speed_stats[1]) {
case 0x01:
bus->cur_bus_speed = PCIE_SPEED_2_5GT;
break;
case 0x02:
bus->cur_bus_speed = PCIE_SPEED_5_0GT;
break;
default:
bus->cur_bus_speed = PCI_SPEED_UNKNOWN;
break;
}
return 0;
}
...@@ -63,4 +63,8 @@ extern int dlpar_detach_node(struct device_node *); ...@@ -63,4 +63,8 @@ extern int dlpar_detach_node(struct device_node *);
/* Snooze Delay, pseries_idle */ /* Snooze Delay, pseries_idle */
DECLARE_PER_CPU(long, smt_snooze_delay); DECLARE_PER_CPU(long, smt_snooze_delay);
/* PCI root bridge prepare function override for pseries */
struct pci_host_bridge;
int pseries_root_bridge_prepare(struct pci_host_bridge *bridge);
#endif /* _PSERIES_PSERIES_H */ #endif /* _PSERIES_PSERIES_H */
...@@ -466,6 +466,8 @@ static void __init pSeries_setup_arch(void) ...@@ -466,6 +466,8 @@ static void __init pSeries_setup_arch(void)
else else
ppc_md.enable_pmcs = power4_enable_pmcs; ppc_md.enable_pmcs = power4_enable_pmcs;
ppc_md.pcibios_root_bridge_prepare = pseries_root_bridge_prepare;
if (firmware_has_feature(FW_FEATURE_SET_MODE)) { if (firmware_has_feature(FW_FEATURE_SET_MODE)) {
long rc; long rc;
if ((rc = pSeries_enable_reloc_on_exc()) != H_SUCCESS) { if ((rc = pSeries_enable_reloc_on_exc()) != H_SUCCESS) {
......
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