mirror of
https://github.com/FEX-Emu/linux.git
synced 2025-01-02 15:21:03 +00:00
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: Kleber Sacilotto de Souza <klebers@linux.vnet.ibm.com> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
This commit is contained in:
parent
e61133dda4
commit
d82fb31abc
@ -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 {
|
|||||||
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)
|
|||||||
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)
|
|||||||
}
|
}
|
||||||
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 *);
|
|||||||
/* 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)
|
|||||||
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) {
|
||||||
|
Loading…
Reference in New Issue
Block a user