diff options
Diffstat (limited to 'drivers/pci/pci-uclass.c')
-rw-r--r-- | drivers/pci/pci-uclass.c | 140 |
1 files changed, 140 insertions, 0 deletions
diff --git a/drivers/pci/pci-uclass.c b/drivers/pci/pci-uclass.c index 6262f35..7d41d56 100644 --- a/drivers/pci/pci-uclass.c +++ b/drivers/pci/pci-uclass.c @@ -210,6 +210,17 @@ int pci_write_config(pci_dev_t bdf, int offset, unsigned long value, return pci_bus_write_config(bus, bdf, offset, value, size); } +int dm_pci_write_config(struct udevice *dev, int offset, unsigned long value, + enum pci_size_t size) +{ + struct udevice *bus; + + for (bus = dev; device_get_uclass_id(bus->parent) == UCLASS_PCI;) + bus = bus->parent; + return pci_bus_write_config(bus, pci_get_bdf(dev), offset, value, size); +} + + int pci_write_config32(pci_dev_t bdf, int offset, u32 value) { return pci_write_config(bdf, offset, value, PCI_SIZE_32); @@ -225,6 +236,21 @@ int pci_write_config8(pci_dev_t bdf, int offset, u8 value) return pci_write_config(bdf, offset, value, PCI_SIZE_8); } +int dm_pci_write_config8(struct udevice *dev, int offset, u8 value) +{ + return dm_pci_write_config(dev, offset, value, PCI_SIZE_8); +} + +int dm_pci_write_config16(struct udevice *dev, int offset, u16 value) +{ + return dm_pci_write_config(dev, offset, value, PCI_SIZE_16); +} + +int dm_pci_write_config32(struct udevice *dev, int offset, u32 value) +{ + return dm_pci_write_config(dev, offset, value, PCI_SIZE_32); +} + int pci_bus_read_config(struct udevice *bus, pci_dev_t bdf, int offset, unsigned long *valuep, enum pci_size_t size) { @@ -249,6 +275,17 @@ int pci_read_config(pci_dev_t bdf, int offset, unsigned long *valuep, return pci_bus_read_config(bus, bdf, offset, valuep, size); } +int dm_pci_read_config(struct udevice *dev, int offset, unsigned long *valuep, + enum pci_size_t size) +{ + struct udevice *bus; + + for (bus = dev; device_get_uclass_id(bus->parent) == UCLASS_PCI;) + bus = bus->parent; + return pci_bus_read_config(bus, pci_get_bdf(dev), offset, valuep, + size); +} + int pci_read_config32(pci_dev_t bdf, int offset, u32 *valuep) { unsigned long value; @@ -288,6 +325,45 @@ int pci_read_config8(pci_dev_t bdf, int offset, u8 *valuep) return 0; } +int dm_pci_read_config8(struct udevice *dev, int offset, u8 *valuep) +{ + unsigned long value; + int ret; + + ret = dm_pci_read_config(dev, offset, &value, PCI_SIZE_8); + if (ret) + return ret; + *valuep = value; + + return 0; +} + +int dm_pci_read_config16(struct udevice *dev, int offset, u16 *valuep) +{ + unsigned long value; + int ret; + + ret = dm_pci_read_config(dev, offset, &value, PCI_SIZE_16); + if (ret) + return ret; + *valuep = value; + + return 0; +} + +int dm_pci_read_config32(struct udevice *dev, int offset, u32 *valuep) +{ + unsigned long value; + int ret; + + ret = dm_pci_read_config(dev, offset, &value, PCI_SIZE_32); + if (ret) + return ret; + *valuep = value; + + return 0; +} + int pci_auto_config_devices(struct udevice *bus) { struct pci_controller *hose = bus->uclass_priv; @@ -641,6 +717,10 @@ static int pci_uclass_post_probe(struct udevice *bus) { int ret; + /* Don't scan buses before relocation */ + if (!(gd->flags & GD_FLG_RELOC)) + return 0; + debug("%s: probing bus %d\n", __func__, bus->seq); ret = pci_bind_bus_devices(bus); if (ret) @@ -699,6 +779,66 @@ static int pci_bridge_write_config(struct udevice *bus, pci_dev_t bdf, return pci_bus_write_config(hose->ctlr, bdf, offset, value, size); } +static int skip_to_next_device(struct udevice *bus, struct udevice **devp) +{ + struct udevice *dev; + int ret = 0; + + /* + * Scan through all the PCI controllers. On x86 there will only be one + * but that is not necessarily true on other hardware. + */ + do { + device_find_first_child(bus, &dev); + if (dev) { + *devp = dev; + return 0; + } + ret = uclass_next_device(&bus); + if (ret) + return ret; + } while (bus); + + return 0; +} + +int pci_find_next_device(struct udevice **devp) +{ + struct udevice *child = *devp; + struct udevice *bus = child->parent; + int ret; + + /* First try all the siblings */ + *devp = NULL; + while (child) { + device_find_next_child(&child); + if (child) { + *devp = child; + return 0; + } + } + + /* We ran out of siblings. Try the next bus */ + ret = uclass_next_device(&bus); + if (ret) + return ret; + + return bus ? skip_to_next_device(bus, devp) : 0; +} + +int pci_find_first_device(struct udevice **devp) +{ + struct udevice *bus; + int ret; + + *devp = NULL; + ret = uclass_first_device(UCLASS_PCI, &bus); + if (ret) + return ret; + + return skip_to_next_device(bus, devp); +} + UCLASS_DRIVER(pci) = { .id = UCLASS_PCI, .name = "pci", |