summaryrefslogtreecommitdiff
path: root/drivers/pci/pci-uclass.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/pci/pci-uclass.c')
-rw-r--r--drivers/pci/pci-uclass.c128
1 files changed, 68 insertions, 60 deletions
diff --git a/drivers/pci/pci-uclass.c b/drivers/pci/pci-uclass.c
index eb07d25301..914217d0c9 100644
--- a/drivers/pci/pci-uclass.c
+++ b/drivers/pci/pci-uclass.c
@@ -14,6 +14,7 @@
#include <asm/io.h>
#include <dm/device-internal.h>
#include <dm/lists.h>
+#include <dm/uclass-internal.h>
#if defined(CONFIG_X86) && defined(CONFIG_HAVE_FSP)
#include <asm/fsp/fsp_support.h>
#endif
@@ -49,7 +50,7 @@ struct udevice *pci_get_controller(struct udevice *dev)
pci_dev_t dm_pci_get_bdf(const struct udevice *dev)
{
- struct pci_child_platdata *pplat = dev_get_parent_platdata(dev);
+ struct pci_child_plat *pplat = dev_get_parent_plat(dev);
struct udevice *bus = dev->parent;
/*
@@ -58,14 +59,14 @@ pci_dev_t dm_pci_get_bdf(const struct udevice *dev)
* will produce a bad BDF>
*
* A common cause of this problem is that this function is called in the
- * ofdata_to_platdata() method of @dev. Accessing the PCI bus in that
+ * of_to_plat() method of @dev. Accessing the PCI bus in that
* method is not allowed, since it has not yet been probed. To fix this,
* move that access to the probe() method of @dev instead.
*/
if (!device_active(bus))
log_err("PCI: Device '%s' on unprobed bus '%s'\n", dev->name,
bus->name);
- return PCI_ADD_BUS(bus->seq, pplat->devfn);
+ return PCI_ADD_BUS(dev_seq(bus), pplat->devfn);
}
/**
@@ -81,8 +82,8 @@ static int pci_get_bus_max(void)
ret = uclass_get(UCLASS_PCI, &uc);
uclass_foreach_dev(bus, uc) {
- if (bus->seq > ret)
- ret = bus->seq;
+ if (dev_seq(bus) > ret)
+ ret = dev_seq(bus);
}
debug("%s: ret=%d\n", __func__, ret);
@@ -136,9 +137,9 @@ int pci_bus_find_devfn(const struct udevice *bus, pci_dev_t find_devfn,
for (device_find_first_child(bus, &dev);
dev;
device_find_next_child(&dev)) {
- struct pci_child_platdata *pplat;
+ struct pci_child_plat *pplat;
- pplat = dev_get_parent_platdata(dev);
+ pplat = dev_get_parent_plat(dev);
if (pplat && pplat->devfn == find_devfn) {
*devp = dev;
return 0;
@@ -162,10 +163,10 @@ int dm_pci_bus_find_bdf(pci_dev_t bdf, struct udevice **devp)
static int pci_device_matches_ids(struct udevice *dev,
struct pci_device_id *ids)
{
- struct pci_child_platdata *pplat;
+ struct pci_child_plat *pplat;
int i;
- pplat = dev_get_parent_platdata(dev);
+ pplat = dev_get_parent_plat(dev);
if (!pplat)
return -EINVAL;
for (i = 0; ids[i].vendor != 0; i++) {
@@ -218,13 +219,13 @@ static int dm_pci_bus_find_device(struct udevice *bus, unsigned int vendor,
unsigned int device, int *indexp,
struct udevice **devp)
{
- struct pci_child_platdata *pplat;
+ struct pci_child_plat *pplat;
struct udevice *dev;
for (device_find_first_child(bus, &dev);
dev;
device_find_next_child(&dev)) {
- pplat = dev_get_parent_platdata(dev);
+ pplat = dev_get_parent_plat(dev);
if (pplat->vendor == vendor && pplat->device == device) {
if (!(*indexp)--) {
*devp = dev;
@@ -261,7 +262,7 @@ int dm_pci_find_class(uint find_class, int index, struct udevice **devp)
for (pci_find_first_device(&dev);
dev;
pci_find_next_device(&dev)) {
- struct pci_child_platdata *pplat = dev_get_parent_platdata(dev);
+ struct pci_child_plat *pplat = dev_get_parent_plat(dev);
if (pplat->class == find_class && !index--) {
*devp = dev;
@@ -513,7 +514,7 @@ static void set_vga_bridge_bits(struct udevice *dev)
struct udevice *parent = dev->parent;
u16 bc;
- while (parent->seq != 0) {
+ while (dev_seq(parent) != 0) {
dm_pci_read_config16(parent, PCI_BRIDGE_CONTROL, &bc);
bc |= PCI_BRIDGE_CTL_VGA;
dm_pci_write_config16(parent, PCI_BRIDGE_CONTROL, bc);
@@ -524,12 +525,12 @@ static void set_vga_bridge_bits(struct udevice *dev)
int pci_auto_config_devices(struct udevice *bus)
{
struct pci_controller *hose = bus->uclass_priv;
- struct pci_child_platdata *pplat;
+ struct pci_child_plat *pplat;
unsigned int sub_bus;
struct udevice *dev;
int ret;
- sub_bus = bus->seq;
+ sub_bus = dev_seq(bus);
debug("%s: start\n", __func__);
pciauto_config_init(hose);
for (ret = device_find_first_child(bus, &dev);
@@ -544,17 +545,17 @@ int pci_auto_config_devices(struct udevice *bus)
continue;
ret = dm_pciauto_config_device(dev);
if (ret < 0)
- return ret;
+ return log_msg_ret("auto", ret);
max_bus = ret;
sub_bus = max(sub_bus, max_bus);
- pplat = dev_get_parent_platdata(dev);
+ pplat = dev_get_parent_plat(dev);
if (pplat->class == (PCI_CLASS_DISPLAY_VGA << 8))
set_vga_bridge_bits(dev);
}
debug("%s: done\n", __func__);
- return sub_bus;
+ return log_msg_ret("sub", sub_bus);
}
int pci_generic_mmap_write_config(
@@ -641,17 +642,9 @@ int dm_pci_hose_probe_bus(struct udevice *bus)
if (ret) {
debug("%s: Cannot probe bus %s: %d\n", __func__, bus->name,
ret);
- return ret;
+ return log_msg_ret("probe", ret);
}
- if (!ea_pos) {
- if (sub_bus != bus->seq) {
- debug("%s: Internal error, bus '%s' got seq %d, expected %d\n",
- __func__, bus->name, bus->seq, sub_bus);
- return -EPIPE;
- }
- sub_bus = pci_get_bus_max();
- }
dm_pciauto_postscan_setup_bridge(bus, sub_bus);
return sub_bus;
@@ -714,7 +707,7 @@ static int pci_find_and_bind_driver(struct udevice *parent,
if (ofnode_valid(node) && !ofnode_is_available(node)) {
debug("%s: Ignoring disabled device\n", __func__);
- return -EPERM;
+ return log_msg_ret("dis", -EPERM);
}
start = ll_entry_start(struct pci_driver_entry, pci_driver_entry);
@@ -740,18 +733,18 @@ static int pci_find_and_bind_driver(struct udevice *parent,
*/
if (!(gd->flags & GD_FLG_RELOC) &&
!(drv->flags & DM_FLAG_PRE_RELOC))
- return -EPERM;
+ return log_msg_ret("pre", -EPERM);
/*
* We could pass the descriptor to the driver as
- * platdata (instead of NULL) and allow its bind()
+ * plat (instead of NULL) and allow its bind()
* method to return -ENOENT if it doesn't support this
* device. That way we could continue the search to
* find another driver. For now this doesn't seem
* necesssary, so just bind the first match.
*/
- ret = device_bind_ofnode(parent, drv, drv->name, NULL,
- node, &dev);
+ ret = device_bind(parent, drv, drv->name, NULL, node,
+ &dev);
if (ret)
goto error;
debug("%s: Match found: %s\n", __func__, drv->name);
@@ -768,10 +761,10 @@ static int pci_find_and_bind_driver(struct udevice *parent,
* limited (ie: using Cache As RAM).
*/
if (!(gd->flags & GD_FLG_RELOC) && !bridge)
- return -EPERM;
+ return log_msg_ret("notbr", -EPERM);
/* Bind a generic driver so that the device can be used */
- sprintf(name, "pci_%x:%x.%x", parent->seq, PCI_DEV(bdf),
+ sprintf(name, "pci_%x:%x.%x", dev_seq(parent), PCI_DEV(bdf),
PCI_FUNC(bdf));
str = strdup(name);
if (!str)
@@ -803,11 +796,11 @@ int pci_bind_bus_devices(struct udevice *bus)
int ret;
found_multi = false;
- end = PCI_BDF(bus->seq, PCI_MAX_PCI_DEVICES - 1,
+ end = PCI_BDF(dev_seq(bus), PCI_MAX_PCI_DEVICES - 1,
PCI_MAX_PCI_FUNCTIONS - 1);
- for (bdf = PCI_BDF(bus->seq, 0, 0); bdf <= end;
+ for (bdf = PCI_BDF(dev_seq(bus), 0, 0); bdf <= end;
bdf += PCI_BDF(0, 0, 1)) {
- struct pci_child_platdata *pplat;
+ struct pci_child_plat *pplat;
struct udevice *dev;
ulong class;
@@ -832,7 +825,7 @@ int pci_bind_bus_devices(struct udevice *bus)
found_multi = header_type & 0x80;
debug("%s: bus %d/%s: found device %x, function %d", __func__,
- bus->seq, bus->name, PCI_DEV(bdf), PCI_FUNC(bdf));
+ dev_seq(bus), bus->name, PCI_DEV(bdf), PCI_FUNC(bdf));
pci_bus_read_config(bus, bdf, PCI_DEVICE_ID, &device,
PCI_SIZE_16);
pci_bus_read_config(bus, bdf, PCI_CLASS_REVISION, &class,
@@ -868,7 +861,7 @@ int pci_bind_bus_devices(struct udevice *bus)
return ret;
/* Update the platform data */
- pplat = dev_get_parent_platdata(dev);
+ pplat = dev_get_parent_plat(dev);
pplat->devfn = PCI_MASK_BUS(bdf);
pplat->vendor = vendor;
pplat->device = device;
@@ -1009,11 +1002,26 @@ static void decode_regions(struct pci_controller *hose, ofnode parent_node,
static int pci_uclass_pre_probe(struct udevice *bus)
{
struct pci_controller *hose;
+ struct uclass *uc;
+ int ret;
- debug("%s, bus=%d/%s, parent=%s\n", __func__, bus->seq, bus->name,
+ debug("%s, bus=%d/%s, parent=%s\n", __func__, dev_seq(bus), bus->name,
bus->parent->name);
hose = bus->uclass_priv;
+ /*
+ * Set the sequence number, if device_bind() doesn't. We want control
+ * of this so that numbers are allocated as devices are probed. That
+ * ensures that sub-bus numbered is correct (sub-buses must get numbers
+ * higher than their parents)
+ */
+ if (dev_seq(bus) == -1) {
+ ret = uclass_get(UCLASS_PCI, &uc);
+ if (ret)
+ return ret;
+ bus->sqq = uclass_find_next_free_seq(uc);
+ }
+
/* For bridges, use the top-level PCI controller */
if (!device_is_on_pci_bus(bus)) {
hose->ctlr = bus;
@@ -1024,9 +1032,10 @@ static int pci_uclass_pre_probe(struct udevice *bus)
parent_hose = dev_get_uclass_priv(bus->parent);
hose->ctlr = parent_hose->bus;
}
+
hose->bus = bus;
- hose->first_busno = bus->seq;
- hose->last_busno = bus->seq;
+ hose->first_busno = dev_seq(bus);
+ hose->last_busno = dev_seq(bus);
if (dev_of_valid(bus)) {
hose->skip_auto_config_until_reloc =
dev_read_bool(bus,
@@ -1041,17 +1050,17 @@ static int pci_uclass_post_probe(struct udevice *bus)
struct pci_controller *hose = dev_get_uclass_priv(bus);
int ret;
- debug("%s: probing bus %d\n", __func__, bus->seq);
+ debug("%s: probing bus %d\n", __func__, dev_seq(bus));
ret = pci_bind_bus_devices(bus);
if (ret)
- return ret;
+ return log_msg_ret("bind", ret);
if (CONFIG_IS_ENABLED(PCI_PNP) && ll_boot_init() &&
(!hose->skip_auto_config_until_reloc ||
(gd->flags & GD_FLG_RELOC))) {
ret = pci_auto_config_devices(bus);
if (ret < 0)
- return log_msg_ret("pci auto-config", ret);
+ return log_msg_ret("cfg", ret);
}
#if defined(CONFIG_X86) && defined(CONFIG_HAVE_FSP)
@@ -1068,10 +1077,10 @@ static int pci_uclass_post_probe(struct udevice *bus)
* Note we only call this 1) after U-Boot is relocated, and 2)
* root bus has finished probing.
*/
- if ((gd->flags & GD_FLG_RELOC) && bus->seq == 0 && ll_boot_init()) {
+ if ((gd->flags & GD_FLG_RELOC) && dev_seq(bus) == 0 && ll_boot_init()) {
ret = fsp_init_phase_pci();
if (ret)
- return ret;
+ return log_msg_ret("fsp", ret);
}
#endif
@@ -1080,12 +1089,12 @@ static int pci_uclass_post_probe(struct udevice *bus)
static int pci_uclass_child_post_bind(struct udevice *dev)
{
- struct pci_child_platdata *pplat;
+ struct pci_child_plat *pplat;
if (!dev_of_valid(dev))
return 0;
- pplat = dev_get_parent_platdata(dev);
+ pplat = dev_get_parent_plat(dev);
/* Extract vendor id and device id if available */
ofnode_read_pci_vendev(dev_ofnode(dev), &pplat->vendor, &pplat->device);
@@ -1441,7 +1450,7 @@ pci_addr_t dm_pci_phys_to_bus(struct udevice *dev, phys_addr_t phys_addr,
}
static phys_addr_t dm_pci_map_ea_virt(struct udevice *dev, int ea_off,
- struct pci_child_platdata *pdata)
+ struct pci_child_plat *pdata)
{
phys_addr_t addr = 0;
@@ -1472,7 +1481,7 @@ static phys_addr_t dm_pci_map_ea_virt(struct udevice *dev, int ea_off,
}
static void *dm_pci_map_ea_bar(struct udevice *dev, int bar, int flags,
- int ea_off, struct pci_child_platdata *pdata)
+ int ea_off, struct pci_child_plat *pdata)
{
int ea_cnt, i, entry_size;
int bar_id = (bar - PCI_BASE_ADDRESS_0) >> 2;
@@ -1523,7 +1532,7 @@ static void *dm_pci_map_ea_bar(struct udevice *dev, int bar, int flags,
void *dm_pci_map_bar(struct udevice *dev, int bar, int flags)
{
- struct pci_child_platdata *pdata = dev_get_parent_platdata(dev);
+ struct pci_child_plat *pdata = dev_get_parent_plat(dev);
struct udevice *udev = dev;
pci_addr_t pci_bus_addr;
u32 bar_response;
@@ -1725,14 +1734,14 @@ int pci_sriov_init(struct udevice *pdev, int vf_en)
bdf += PCI_BDF(0, 0, vf_offset);
for (vf = 0; vf < num_vfs; vf++) {
- struct pci_child_platdata *pplat;
+ struct pci_child_plat *pplat;
ulong class;
pci_bus_read_config(bus, bdf, PCI_CLASS_DEVICE,
&class, PCI_SIZE_16);
debug("%s: bus %d/%s: found VF %x:%x\n", __func__,
- bus->seq, bus->name, PCI_DEV(bdf), PCI_FUNC(bdf));
+ dev_seq(bus), bus->name, PCI_DEV(bdf), PCI_FUNC(bdf));
/* Find this device in the device tree */
ret = pci_bus_find_devfn(bus, PCI_MASK_BUS(bdf), &dev);
@@ -1753,7 +1762,7 @@ int pci_sriov_init(struct udevice *pdev, int vf_en)
}
/* Update the platform data */
- pplat = dev_get_parent_platdata(dev);
+ pplat = dev_get_parent_plat(dev);
pplat->devfn = PCI_MASK_BUS(bdf);
pplat->vendor = vendor;
pplat->device = device;
@@ -1763,7 +1772,7 @@ int pci_sriov_init(struct udevice *pdev, int vf_en)
pplat->virtid = vf * vf_stride + vf_offset;
debug("%s: bus %d/%s: found VF %x:%x %x:%x class %lx id %x\n",
- __func__, dev->seq, dev->name, PCI_DEV(bdf),
+ __func__, dev_seq(dev), dev->name, PCI_DEV(bdf),
PCI_FUNC(bdf), vendor, device, class, pplat->virtid);
bdf += PCI_BDF(0, 0, vf_stride);
}
@@ -1791,14 +1800,13 @@ int pci_sriov_get_totalvfs(struct udevice *pdev)
UCLASS_DRIVER(pci) = {
.id = UCLASS_PCI,
.name = "pci",
- .flags = DM_UC_FLAG_SEQ_ALIAS,
+ .flags = DM_UC_FLAG_SEQ_ALIAS | DM_UC_FLAG_NO_AUTO_SEQ,
.post_bind = dm_scan_fdt_dev,
.pre_probe = pci_uclass_pre_probe,
.post_probe = pci_uclass_post_probe,
.child_post_bind = pci_uclass_child_post_bind,
- .per_device_auto_alloc_size = sizeof(struct pci_controller),
- .per_child_platdata_auto_alloc_size =
- sizeof(struct pci_child_platdata),
+ .per_device_auto = sizeof(struct pci_controller),
+ .per_child_plat_auto = sizeof(struct pci_child_plat),
};
static const struct dm_pci_ops pci_bridge_ops = {