1ff3e077bSSimon Glass /* 2ff3e077bSSimon Glass * Copyright (c) 2014 Google, Inc 3ff3e077bSSimon Glass * Written by Simon Glass <sjg@chromium.org> 4ff3e077bSSimon Glass * 5ff3e077bSSimon Glass * SPDX-License-Identifier: GPL-2.0+ 6ff3e077bSSimon Glass */ 7ff3e077bSSimon Glass 8ff3e077bSSimon Glass #include <common.h> 9ff3e077bSSimon Glass #include <dm.h> 10ff3e077bSSimon Glass #include <errno.h> 11ff3e077bSSimon Glass #include <fdtdec.h> 12ff3e077bSSimon Glass #include <inttypes.h> 13ff3e077bSSimon Glass #include <pci.h> 14*21d1fe7eSSimon Glass #include <asm/io.h> 15ff3e077bSSimon Glass #include <dm/lists.h> 16ff3e077bSSimon Glass #include <dm/root.h> 17ff3e077bSSimon Glass #include <dm/device-internal.h> 18348b744bSBin Meng #if defined(CONFIG_X86) && defined(CONFIG_HAVE_FSP) 19348b744bSBin Meng #include <asm/fsp/fsp_support.h> 20348b744bSBin Meng #endif 215e23b8b4SSimon Glass #include "pci_internal.h" 22ff3e077bSSimon Glass 23ff3e077bSSimon Glass DECLARE_GLOBAL_DATA_PTR; 24ff3e077bSSimon Glass 25983c6ba2SSimon Glass static int pci_get_bus(int busnum, struct udevice **busp) 26983c6ba2SSimon Glass { 27983c6ba2SSimon Glass int ret; 28983c6ba2SSimon Glass 29983c6ba2SSimon Glass ret = uclass_get_device_by_seq(UCLASS_PCI, busnum, busp); 30983c6ba2SSimon Glass 31983c6ba2SSimon Glass /* Since buses may not be numbered yet try a little harder with bus 0 */ 32983c6ba2SSimon Glass if (ret == -ENODEV) { 33983c6ba2SSimon Glass ret = uclass_first_device(UCLASS_PCI, busp); 34983c6ba2SSimon Glass if (ret) 35983c6ba2SSimon Glass return ret; 36983c6ba2SSimon Glass else if (!*busp) 37983c6ba2SSimon Glass return -ENODEV; 38983c6ba2SSimon Glass ret = uclass_get_device_by_seq(UCLASS_PCI, busnum, busp); 39983c6ba2SSimon Glass } 40983c6ba2SSimon Glass 41983c6ba2SSimon Glass return ret; 42983c6ba2SSimon Glass } 43983c6ba2SSimon Glass 44ff3e077bSSimon Glass struct pci_controller *pci_bus_to_hose(int busnum) 45ff3e077bSSimon Glass { 46ff3e077bSSimon Glass struct udevice *bus; 47ff3e077bSSimon Glass int ret; 48ff3e077bSSimon Glass 49983c6ba2SSimon Glass ret = pci_get_bus(busnum, &bus); 50ff3e077bSSimon Glass if (ret) { 51ff3e077bSSimon Glass debug("%s: Cannot get bus %d: ret=%d\n", __func__, busnum, ret); 52ff3e077bSSimon Glass return NULL; 53ff3e077bSSimon Glass } 54983c6ba2SSimon Glass 55ff3e077bSSimon Glass return dev_get_uclass_priv(bus); 56ff3e077bSSimon Glass } 57ff3e077bSSimon Glass 589f60fb0dSSimon Glass struct udevice *pci_get_controller(struct udevice *dev) 599f60fb0dSSimon Glass { 609f60fb0dSSimon Glass while (device_is_on_pci_bus(dev)) 619f60fb0dSSimon Glass dev = dev->parent; 629f60fb0dSSimon Glass 639f60fb0dSSimon Glass return dev; 649f60fb0dSSimon Glass } 659f60fb0dSSimon Glass 6621ccce1bSSimon Glass pci_dev_t dm_pci_get_bdf(struct udevice *dev) 674b515e4fSSimon Glass { 684b515e4fSSimon Glass struct pci_child_platdata *pplat = dev_get_parent_platdata(dev); 694b515e4fSSimon Glass struct udevice *bus = dev->parent; 704b515e4fSSimon Glass 714b515e4fSSimon Glass return PCI_ADD_BUS(bus->seq, pplat->devfn); 724b515e4fSSimon Glass } 734b515e4fSSimon Glass 74ff3e077bSSimon Glass /** 75ff3e077bSSimon Glass * pci_get_bus_max() - returns the bus number of the last active bus 76ff3e077bSSimon Glass * 77ff3e077bSSimon Glass * @return last bus number, or -1 if no active buses 78ff3e077bSSimon Glass */ 79ff3e077bSSimon Glass static int pci_get_bus_max(void) 80ff3e077bSSimon Glass { 81ff3e077bSSimon Glass struct udevice *bus; 82ff3e077bSSimon Glass struct uclass *uc; 83ff3e077bSSimon Glass int ret = -1; 84ff3e077bSSimon Glass 85ff3e077bSSimon Glass ret = uclass_get(UCLASS_PCI, &uc); 86ff3e077bSSimon Glass uclass_foreach_dev(bus, uc) { 87ff3e077bSSimon Glass if (bus->seq > ret) 88ff3e077bSSimon Glass ret = bus->seq; 89ff3e077bSSimon Glass } 90ff3e077bSSimon Glass 91ff3e077bSSimon Glass debug("%s: ret=%d\n", __func__, ret); 92ff3e077bSSimon Glass 93ff3e077bSSimon Glass return ret; 94ff3e077bSSimon Glass } 95ff3e077bSSimon Glass 96ff3e077bSSimon Glass int pci_last_busno(void) 97ff3e077bSSimon Glass { 98069155cbSBin Meng return pci_get_bus_max(); 99ff3e077bSSimon Glass } 100ff3e077bSSimon Glass 101ff3e077bSSimon Glass int pci_get_ff(enum pci_size_t size) 102ff3e077bSSimon Glass { 103ff3e077bSSimon Glass switch (size) { 104ff3e077bSSimon Glass case PCI_SIZE_8: 105ff3e077bSSimon Glass return 0xff; 106ff3e077bSSimon Glass case PCI_SIZE_16: 107ff3e077bSSimon Glass return 0xffff; 108ff3e077bSSimon Glass default: 109ff3e077bSSimon Glass return 0xffffffff; 110ff3e077bSSimon Glass } 111ff3e077bSSimon Glass } 112ff3e077bSSimon Glass 113ff3e077bSSimon Glass int pci_bus_find_devfn(struct udevice *bus, pci_dev_t find_devfn, 114ff3e077bSSimon Glass struct udevice **devp) 115ff3e077bSSimon Glass { 116ff3e077bSSimon Glass struct udevice *dev; 117ff3e077bSSimon Glass 118ff3e077bSSimon Glass for (device_find_first_child(bus, &dev); 119ff3e077bSSimon Glass dev; 120ff3e077bSSimon Glass device_find_next_child(&dev)) { 121ff3e077bSSimon Glass struct pci_child_platdata *pplat; 122ff3e077bSSimon Glass 123ff3e077bSSimon Glass pplat = dev_get_parent_platdata(dev); 124ff3e077bSSimon Glass if (pplat && pplat->devfn == find_devfn) { 125ff3e077bSSimon Glass *devp = dev; 126ff3e077bSSimon Glass return 0; 127ff3e077bSSimon Glass } 128ff3e077bSSimon Glass } 129ff3e077bSSimon Glass 130ff3e077bSSimon Glass return -ENODEV; 131ff3e077bSSimon Glass } 132ff3e077bSSimon Glass 133f3f1faefSSimon Glass int dm_pci_bus_find_bdf(pci_dev_t bdf, struct udevice **devp) 134ff3e077bSSimon Glass { 135ff3e077bSSimon Glass struct udevice *bus; 136ff3e077bSSimon Glass int ret; 137ff3e077bSSimon Glass 138983c6ba2SSimon Glass ret = pci_get_bus(PCI_BUS(bdf), &bus); 139ff3e077bSSimon Glass if (ret) 140ff3e077bSSimon Glass return ret; 141ff3e077bSSimon Glass return pci_bus_find_devfn(bus, PCI_MASK_BUS(bdf), devp); 142ff3e077bSSimon Glass } 143ff3e077bSSimon Glass 144ff3e077bSSimon Glass static int pci_device_matches_ids(struct udevice *dev, 145ff3e077bSSimon Glass struct pci_device_id *ids) 146ff3e077bSSimon Glass { 147ff3e077bSSimon Glass struct pci_child_platdata *pplat; 148ff3e077bSSimon Glass int i; 149ff3e077bSSimon Glass 150ff3e077bSSimon Glass pplat = dev_get_parent_platdata(dev); 151ff3e077bSSimon Glass if (!pplat) 152ff3e077bSSimon Glass return -EINVAL; 153ff3e077bSSimon Glass for (i = 0; ids[i].vendor != 0; i++) { 154ff3e077bSSimon Glass if (pplat->vendor == ids[i].vendor && 155ff3e077bSSimon Glass pplat->device == ids[i].device) 156ff3e077bSSimon Glass return i; 157ff3e077bSSimon Glass } 158ff3e077bSSimon Glass 159ff3e077bSSimon Glass return -EINVAL; 160ff3e077bSSimon Glass } 161ff3e077bSSimon Glass 162ff3e077bSSimon Glass int pci_bus_find_devices(struct udevice *bus, struct pci_device_id *ids, 163ff3e077bSSimon Glass int *indexp, struct udevice **devp) 164ff3e077bSSimon Glass { 165ff3e077bSSimon Glass struct udevice *dev; 166ff3e077bSSimon Glass 167ff3e077bSSimon Glass /* Scan all devices on this bus */ 168ff3e077bSSimon Glass for (device_find_first_child(bus, &dev); 169ff3e077bSSimon Glass dev; 170ff3e077bSSimon Glass device_find_next_child(&dev)) { 171ff3e077bSSimon Glass if (pci_device_matches_ids(dev, ids) >= 0) { 172ff3e077bSSimon Glass if ((*indexp)-- <= 0) { 173ff3e077bSSimon Glass *devp = dev; 174ff3e077bSSimon Glass return 0; 175ff3e077bSSimon Glass } 176ff3e077bSSimon Glass } 177ff3e077bSSimon Glass } 178ff3e077bSSimon Glass 179ff3e077bSSimon Glass return -ENODEV; 180ff3e077bSSimon Glass } 181ff3e077bSSimon Glass 182ff3e077bSSimon Glass int pci_find_device_id(struct pci_device_id *ids, int index, 183ff3e077bSSimon Glass struct udevice **devp) 184ff3e077bSSimon Glass { 185ff3e077bSSimon Glass struct udevice *bus; 186ff3e077bSSimon Glass 187ff3e077bSSimon Glass /* Scan all known buses */ 188ff3e077bSSimon Glass for (uclass_first_device(UCLASS_PCI, &bus); 189ff3e077bSSimon Glass bus; 190ff3e077bSSimon Glass uclass_next_device(&bus)) { 191ff3e077bSSimon Glass if (!pci_bus_find_devices(bus, ids, &index, devp)) 192ff3e077bSSimon Glass return 0; 193ff3e077bSSimon Glass } 194ff3e077bSSimon Glass *devp = NULL; 195ff3e077bSSimon Glass 196ff3e077bSSimon Glass return -ENODEV; 197ff3e077bSSimon Glass } 198ff3e077bSSimon Glass 1995c0bf647SSimon Glass static int dm_pci_bus_find_device(struct udevice *bus, unsigned int vendor, 2005c0bf647SSimon Glass unsigned int device, int *indexp, 2015c0bf647SSimon Glass struct udevice **devp) 2025c0bf647SSimon Glass { 2035c0bf647SSimon Glass struct pci_child_platdata *pplat; 2045c0bf647SSimon Glass struct udevice *dev; 2055c0bf647SSimon Glass 2065c0bf647SSimon Glass for (device_find_first_child(bus, &dev); 2075c0bf647SSimon Glass dev; 2085c0bf647SSimon Glass device_find_next_child(&dev)) { 2095c0bf647SSimon Glass pplat = dev_get_parent_platdata(dev); 2105c0bf647SSimon Glass if (pplat->vendor == vendor && pplat->device == device) { 2115c0bf647SSimon Glass if (!(*indexp)--) { 2125c0bf647SSimon Glass *devp = dev; 2135c0bf647SSimon Glass return 0; 2145c0bf647SSimon Glass } 2155c0bf647SSimon Glass } 2165c0bf647SSimon Glass } 2175c0bf647SSimon Glass 2185c0bf647SSimon Glass return -ENODEV; 2195c0bf647SSimon Glass } 2205c0bf647SSimon Glass 2215c0bf647SSimon Glass int dm_pci_find_device(unsigned int vendor, unsigned int device, int index, 2225c0bf647SSimon Glass struct udevice **devp) 2235c0bf647SSimon Glass { 2245c0bf647SSimon Glass struct udevice *bus; 2255c0bf647SSimon Glass 2265c0bf647SSimon Glass /* Scan all known buses */ 2275c0bf647SSimon Glass for (uclass_first_device(UCLASS_PCI, &bus); 2285c0bf647SSimon Glass bus; 2295c0bf647SSimon Glass uclass_next_device(&bus)) { 2305c0bf647SSimon Glass if (!dm_pci_bus_find_device(bus, vendor, device, &index, devp)) 2315c0bf647SSimon Glass return device_probe(*devp); 2325c0bf647SSimon Glass } 2335c0bf647SSimon Glass *devp = NULL; 2345c0bf647SSimon Glass 2355c0bf647SSimon Glass return -ENODEV; 2365c0bf647SSimon Glass } 2375c0bf647SSimon Glass 238a0eb8356SSimon Glass int dm_pci_find_class(uint find_class, int index, struct udevice **devp) 239a0eb8356SSimon Glass { 240a0eb8356SSimon Glass struct udevice *dev; 241a0eb8356SSimon Glass 242a0eb8356SSimon Glass /* Scan all known buses */ 243a0eb8356SSimon Glass for (pci_find_first_device(&dev); 244a0eb8356SSimon Glass dev; 245a0eb8356SSimon Glass pci_find_next_device(&dev)) { 246a0eb8356SSimon Glass struct pci_child_platdata *pplat = dev_get_parent_platdata(dev); 247a0eb8356SSimon Glass 248a0eb8356SSimon Glass if (pplat->class == find_class && !index--) { 249a0eb8356SSimon Glass *devp = dev; 250a0eb8356SSimon Glass return device_probe(*devp); 251a0eb8356SSimon Glass } 252a0eb8356SSimon Glass } 253a0eb8356SSimon Glass *devp = NULL; 254a0eb8356SSimon Glass 255a0eb8356SSimon Glass return -ENODEV; 256a0eb8356SSimon Glass } 257a0eb8356SSimon Glass 258ff3e077bSSimon Glass int pci_bus_write_config(struct udevice *bus, pci_dev_t bdf, int offset, 259ff3e077bSSimon Glass unsigned long value, enum pci_size_t size) 260ff3e077bSSimon Glass { 261ff3e077bSSimon Glass struct dm_pci_ops *ops; 262ff3e077bSSimon Glass 263ff3e077bSSimon Glass ops = pci_get_ops(bus); 264ff3e077bSSimon Glass if (!ops->write_config) 265ff3e077bSSimon Glass return -ENOSYS; 266ff3e077bSSimon Glass return ops->write_config(bus, bdf, offset, value, size); 267ff3e077bSSimon Glass } 268ff3e077bSSimon Glass 269ff3e077bSSimon Glass int pci_write_config(pci_dev_t bdf, int offset, unsigned long value, 270ff3e077bSSimon Glass enum pci_size_t size) 271ff3e077bSSimon Glass { 272ff3e077bSSimon Glass struct udevice *bus; 273ff3e077bSSimon Glass int ret; 274ff3e077bSSimon Glass 275983c6ba2SSimon Glass ret = pci_get_bus(PCI_BUS(bdf), &bus); 276ff3e077bSSimon Glass if (ret) 277ff3e077bSSimon Glass return ret; 278ff3e077bSSimon Glass 2794d8615cbSBin Meng return pci_bus_write_config(bus, bdf, offset, value, size); 280ff3e077bSSimon Glass } 281ff3e077bSSimon Glass 28266afb4edSSimon Glass int dm_pci_write_config(struct udevice *dev, int offset, unsigned long value, 28366afb4edSSimon Glass enum pci_size_t size) 28466afb4edSSimon Glass { 28566afb4edSSimon Glass struct udevice *bus; 28666afb4edSSimon Glass 2871e0f2263SBin Meng for (bus = dev; device_is_on_pci_bus(bus);) 28866afb4edSSimon Glass bus = bus->parent; 28921ccce1bSSimon Glass return pci_bus_write_config(bus, dm_pci_get_bdf(dev), offset, value, 29021ccce1bSSimon Glass size); 29166afb4edSSimon Glass } 29266afb4edSSimon Glass 29366afb4edSSimon Glass 294ff3e077bSSimon Glass int pci_write_config32(pci_dev_t bdf, int offset, u32 value) 295ff3e077bSSimon Glass { 296ff3e077bSSimon Glass return pci_write_config(bdf, offset, value, PCI_SIZE_32); 297ff3e077bSSimon Glass } 298ff3e077bSSimon Glass 299ff3e077bSSimon Glass int pci_write_config16(pci_dev_t bdf, int offset, u16 value) 300ff3e077bSSimon Glass { 301ff3e077bSSimon Glass return pci_write_config(bdf, offset, value, PCI_SIZE_16); 302ff3e077bSSimon Glass } 303ff3e077bSSimon Glass 304ff3e077bSSimon Glass int pci_write_config8(pci_dev_t bdf, int offset, u8 value) 305ff3e077bSSimon Glass { 306ff3e077bSSimon Glass return pci_write_config(bdf, offset, value, PCI_SIZE_8); 307ff3e077bSSimon Glass } 308ff3e077bSSimon Glass 30966afb4edSSimon Glass int dm_pci_write_config8(struct udevice *dev, int offset, u8 value) 31066afb4edSSimon Glass { 31166afb4edSSimon Glass return dm_pci_write_config(dev, offset, value, PCI_SIZE_8); 31266afb4edSSimon Glass } 31366afb4edSSimon Glass 31466afb4edSSimon Glass int dm_pci_write_config16(struct udevice *dev, int offset, u16 value) 31566afb4edSSimon Glass { 31666afb4edSSimon Glass return dm_pci_write_config(dev, offset, value, PCI_SIZE_16); 31766afb4edSSimon Glass } 31866afb4edSSimon Glass 31966afb4edSSimon Glass int dm_pci_write_config32(struct udevice *dev, int offset, u32 value) 32066afb4edSSimon Glass { 32166afb4edSSimon Glass return dm_pci_write_config(dev, offset, value, PCI_SIZE_32); 32266afb4edSSimon Glass } 32366afb4edSSimon Glass 324ff3e077bSSimon Glass int pci_bus_read_config(struct udevice *bus, pci_dev_t bdf, int offset, 325ff3e077bSSimon Glass unsigned long *valuep, enum pci_size_t size) 326ff3e077bSSimon Glass { 327ff3e077bSSimon Glass struct dm_pci_ops *ops; 328ff3e077bSSimon Glass 329ff3e077bSSimon Glass ops = pci_get_ops(bus); 330ff3e077bSSimon Glass if (!ops->read_config) 331ff3e077bSSimon Glass return -ENOSYS; 332ff3e077bSSimon Glass return ops->read_config(bus, bdf, offset, valuep, size); 333ff3e077bSSimon Glass } 334ff3e077bSSimon Glass 335ff3e077bSSimon Glass int pci_read_config(pci_dev_t bdf, int offset, unsigned long *valuep, 336ff3e077bSSimon Glass enum pci_size_t size) 337ff3e077bSSimon Glass { 338ff3e077bSSimon Glass struct udevice *bus; 339ff3e077bSSimon Glass int ret; 340ff3e077bSSimon Glass 341983c6ba2SSimon Glass ret = pci_get_bus(PCI_BUS(bdf), &bus); 342ff3e077bSSimon Glass if (ret) 343ff3e077bSSimon Glass return ret; 344ff3e077bSSimon Glass 3454d8615cbSBin Meng return pci_bus_read_config(bus, bdf, offset, valuep, size); 346ff3e077bSSimon Glass } 347ff3e077bSSimon Glass 34866afb4edSSimon Glass int dm_pci_read_config(struct udevice *dev, int offset, unsigned long *valuep, 34966afb4edSSimon Glass enum pci_size_t size) 35066afb4edSSimon Glass { 35166afb4edSSimon Glass struct udevice *bus; 35266afb4edSSimon Glass 3531e0f2263SBin Meng for (bus = dev; device_is_on_pci_bus(bus);) 35466afb4edSSimon Glass bus = bus->parent; 35521ccce1bSSimon Glass return pci_bus_read_config(bus, dm_pci_get_bdf(dev), offset, valuep, 35666afb4edSSimon Glass size); 35766afb4edSSimon Glass } 35866afb4edSSimon Glass 359ff3e077bSSimon Glass int pci_read_config32(pci_dev_t bdf, int offset, u32 *valuep) 360ff3e077bSSimon Glass { 361ff3e077bSSimon Glass unsigned long value; 362ff3e077bSSimon Glass int ret; 363ff3e077bSSimon Glass 364ff3e077bSSimon Glass ret = pci_read_config(bdf, offset, &value, PCI_SIZE_32); 365ff3e077bSSimon Glass if (ret) 366ff3e077bSSimon Glass return ret; 367ff3e077bSSimon Glass *valuep = value; 368ff3e077bSSimon Glass 369ff3e077bSSimon Glass return 0; 370ff3e077bSSimon Glass } 371ff3e077bSSimon Glass 372ff3e077bSSimon Glass int pci_read_config16(pci_dev_t bdf, int offset, u16 *valuep) 373ff3e077bSSimon Glass { 374ff3e077bSSimon Glass unsigned long value; 375ff3e077bSSimon Glass int ret; 376ff3e077bSSimon Glass 377ff3e077bSSimon Glass ret = pci_read_config(bdf, offset, &value, PCI_SIZE_16); 378ff3e077bSSimon Glass if (ret) 379ff3e077bSSimon Glass return ret; 380ff3e077bSSimon Glass *valuep = value; 381ff3e077bSSimon Glass 382ff3e077bSSimon Glass return 0; 383ff3e077bSSimon Glass } 384ff3e077bSSimon Glass 385ff3e077bSSimon Glass int pci_read_config8(pci_dev_t bdf, int offset, u8 *valuep) 386ff3e077bSSimon Glass { 387ff3e077bSSimon Glass unsigned long value; 388ff3e077bSSimon Glass int ret; 389ff3e077bSSimon Glass 390ff3e077bSSimon Glass ret = pci_read_config(bdf, offset, &value, PCI_SIZE_8); 391ff3e077bSSimon Glass if (ret) 392ff3e077bSSimon Glass return ret; 393ff3e077bSSimon Glass *valuep = value; 394ff3e077bSSimon Glass 395ff3e077bSSimon Glass return 0; 396ff3e077bSSimon Glass } 397ff3e077bSSimon Glass 39866afb4edSSimon Glass int dm_pci_read_config8(struct udevice *dev, int offset, u8 *valuep) 39966afb4edSSimon Glass { 40066afb4edSSimon Glass unsigned long value; 40166afb4edSSimon Glass int ret; 40266afb4edSSimon Glass 40366afb4edSSimon Glass ret = dm_pci_read_config(dev, offset, &value, PCI_SIZE_8); 40466afb4edSSimon Glass if (ret) 40566afb4edSSimon Glass return ret; 40666afb4edSSimon Glass *valuep = value; 40766afb4edSSimon Glass 40866afb4edSSimon Glass return 0; 40966afb4edSSimon Glass } 41066afb4edSSimon Glass 41166afb4edSSimon Glass int dm_pci_read_config16(struct udevice *dev, int offset, u16 *valuep) 41266afb4edSSimon Glass { 41366afb4edSSimon Glass unsigned long value; 41466afb4edSSimon Glass int ret; 41566afb4edSSimon Glass 41666afb4edSSimon Glass ret = dm_pci_read_config(dev, offset, &value, PCI_SIZE_16); 41766afb4edSSimon Glass if (ret) 41866afb4edSSimon Glass return ret; 41966afb4edSSimon Glass *valuep = value; 42066afb4edSSimon Glass 42166afb4edSSimon Glass return 0; 42266afb4edSSimon Glass } 42366afb4edSSimon Glass 42466afb4edSSimon Glass int dm_pci_read_config32(struct udevice *dev, int offset, u32 *valuep) 42566afb4edSSimon Glass { 42666afb4edSSimon Glass unsigned long value; 42766afb4edSSimon Glass int ret; 42866afb4edSSimon Glass 42966afb4edSSimon Glass ret = dm_pci_read_config(dev, offset, &value, PCI_SIZE_32); 43066afb4edSSimon Glass if (ret) 43166afb4edSSimon Glass return ret; 43266afb4edSSimon Glass *valuep = value; 43366afb4edSSimon Glass 43466afb4edSSimon Glass return 0; 43566afb4edSSimon Glass } 43666afb4edSSimon Glass 437bbbcb526SBin Meng static void set_vga_bridge_bits(struct udevice *dev) 438bbbcb526SBin Meng { 439bbbcb526SBin Meng struct udevice *parent = dev->parent; 440bbbcb526SBin Meng u16 bc; 441bbbcb526SBin Meng 442bbbcb526SBin Meng while (parent->seq != 0) { 443bbbcb526SBin Meng dm_pci_read_config16(parent, PCI_BRIDGE_CONTROL, &bc); 444bbbcb526SBin Meng bc |= PCI_BRIDGE_CTL_VGA; 445bbbcb526SBin Meng dm_pci_write_config16(parent, PCI_BRIDGE_CONTROL, bc); 446bbbcb526SBin Meng parent = parent->parent; 447bbbcb526SBin Meng } 448bbbcb526SBin Meng } 449bbbcb526SBin Meng 450ff3e077bSSimon Glass int pci_auto_config_devices(struct udevice *bus) 451ff3e077bSSimon Glass { 452ff3e077bSSimon Glass struct pci_controller *hose = bus->uclass_priv; 453bbbcb526SBin Meng struct pci_child_platdata *pplat; 454ff3e077bSSimon Glass unsigned int sub_bus; 455ff3e077bSSimon Glass struct udevice *dev; 456ff3e077bSSimon Glass int ret; 457ff3e077bSSimon Glass 458ff3e077bSSimon Glass sub_bus = bus->seq; 459ff3e077bSSimon Glass debug("%s: start\n", __func__); 460ff3e077bSSimon Glass pciauto_config_init(hose); 461ff3e077bSSimon Glass for (ret = device_find_first_child(bus, &dev); 462ff3e077bSSimon Glass !ret && dev; 463ff3e077bSSimon Glass ret = device_find_next_child(&dev)) { 464ff3e077bSSimon Glass unsigned int max_bus; 4654d21455eSSimon Glass int ret; 466ff3e077bSSimon Glass 467ff3e077bSSimon Glass debug("%s: device %s\n", __func__, dev->name); 4685e23b8b4SSimon Glass ret = dm_pciauto_config_device(dev); 4694d21455eSSimon Glass if (ret < 0) 4704d21455eSSimon Glass return ret; 4714d21455eSSimon Glass max_bus = ret; 472ff3e077bSSimon Glass sub_bus = max(sub_bus, max_bus); 473bbbcb526SBin Meng 474bbbcb526SBin Meng pplat = dev_get_parent_platdata(dev); 475bbbcb526SBin Meng if (pplat->class == (PCI_CLASS_DISPLAY_VGA << 8)) 476bbbcb526SBin Meng set_vga_bridge_bits(dev); 477ff3e077bSSimon Glass } 478ff3e077bSSimon Glass debug("%s: done\n", __func__); 479ff3e077bSSimon Glass 480ff3e077bSSimon Glass return sub_bus; 481ff3e077bSSimon Glass } 482ff3e077bSSimon Glass 4835e23b8b4SSimon Glass int dm_pci_hose_probe_bus(struct udevice *bus) 484ff3e077bSSimon Glass { 485ff3e077bSSimon Glass int sub_bus; 486ff3e077bSSimon Glass int ret; 487ff3e077bSSimon Glass 488ff3e077bSSimon Glass debug("%s\n", __func__); 489ff3e077bSSimon Glass 490ff3e077bSSimon Glass sub_bus = pci_get_bus_max() + 1; 491ff3e077bSSimon Glass debug("%s: bus = %d/%s\n", __func__, sub_bus, bus->name); 4925e23b8b4SSimon Glass dm_pciauto_prescan_setup_bridge(bus, sub_bus); 493ff3e077bSSimon Glass 494ff3e077bSSimon Glass ret = device_probe(bus); 495ff3e077bSSimon Glass if (ret) { 4963129ace4SSimon Glass debug("%s: Cannot probe bus %s: %d\n", __func__, bus->name, 497ff3e077bSSimon Glass ret); 498ff3e077bSSimon Glass return ret; 499ff3e077bSSimon Glass } 500ff3e077bSSimon Glass if (sub_bus != bus->seq) { 501ff3e077bSSimon Glass printf("%s: Internal error, bus '%s' got seq %d, expected %d\n", 502ff3e077bSSimon Glass __func__, bus->name, bus->seq, sub_bus); 503ff3e077bSSimon Glass return -EPIPE; 504ff3e077bSSimon Glass } 505ff3e077bSSimon Glass sub_bus = pci_get_bus_max(); 5065e23b8b4SSimon Glass dm_pciauto_postscan_setup_bridge(bus, sub_bus); 507ff3e077bSSimon Glass 508ff3e077bSSimon Glass return sub_bus; 509ff3e077bSSimon Glass } 510ff3e077bSSimon Glass 511aba92962SSimon Glass /** 512aba92962SSimon Glass * pci_match_one_device - Tell if a PCI device structure has a matching 513aba92962SSimon Glass * PCI device id structure 514aba92962SSimon Glass * @id: single PCI device id structure to match 515aba92962SSimon Glass * @dev: the PCI device structure to match against 516aba92962SSimon Glass * 517aba92962SSimon Glass * Returns the matching pci_device_id structure or %NULL if there is no match. 518aba92962SSimon Glass */ 519aba92962SSimon Glass static bool pci_match_one_id(const struct pci_device_id *id, 520aba92962SSimon Glass const struct pci_device_id *find) 521aba92962SSimon Glass { 522aba92962SSimon Glass if ((id->vendor == PCI_ANY_ID || id->vendor == find->vendor) && 523aba92962SSimon Glass (id->device == PCI_ANY_ID || id->device == find->device) && 524aba92962SSimon Glass (id->subvendor == PCI_ANY_ID || id->subvendor == find->subvendor) && 525aba92962SSimon Glass (id->subdevice == PCI_ANY_ID || id->subdevice == find->subdevice) && 526aba92962SSimon Glass !((id->class ^ find->class) & id->class_mask)) 527aba92962SSimon Glass return true; 528aba92962SSimon Glass 529aba92962SSimon Glass return false; 530aba92962SSimon Glass } 531aba92962SSimon Glass 532aba92962SSimon Glass /** 533aba92962SSimon Glass * pci_find_and_bind_driver() - Find and bind the right PCI driver 534aba92962SSimon Glass * 535aba92962SSimon Glass * This only looks at certain fields in the descriptor. 5365dbcf3a0SSimon Glass * 5375dbcf3a0SSimon Glass * @parent: Parent bus 5385dbcf3a0SSimon Glass * @find_id: Specification of the driver to find 5395dbcf3a0SSimon Glass * @bdf: Bus/device/function addreess - see PCI_BDF() 5405dbcf3a0SSimon Glass * @devp: Returns a pointer to the device created 5415dbcf3a0SSimon Glass * @return 0 if OK, -EPERM if the device is not needed before relocation and 5425dbcf3a0SSimon Glass * therefore was not created, other -ve value on error 543aba92962SSimon Glass */ 544aba92962SSimon Glass static int pci_find_and_bind_driver(struct udevice *parent, 5455dbcf3a0SSimon Glass struct pci_device_id *find_id, 5465dbcf3a0SSimon Glass pci_dev_t bdf, struct udevice **devp) 547aba92962SSimon Glass { 548aba92962SSimon Glass struct pci_driver_entry *start, *entry; 549aba92962SSimon Glass const char *drv; 550aba92962SSimon Glass int n_ents; 551aba92962SSimon Glass int ret; 552aba92962SSimon Glass char name[30], *str; 55308fc7b8fSBin Meng bool bridge; 554aba92962SSimon Glass 555aba92962SSimon Glass *devp = NULL; 556aba92962SSimon Glass 557aba92962SSimon Glass debug("%s: Searching for driver: vendor=%x, device=%x\n", __func__, 558aba92962SSimon Glass find_id->vendor, find_id->device); 559aba92962SSimon Glass start = ll_entry_start(struct pci_driver_entry, pci_driver_entry); 560aba92962SSimon Glass n_ents = ll_entry_count(struct pci_driver_entry, pci_driver_entry); 561aba92962SSimon Glass for (entry = start; entry != start + n_ents; entry++) { 562aba92962SSimon Glass const struct pci_device_id *id; 563aba92962SSimon Glass struct udevice *dev; 564aba92962SSimon Glass const struct driver *drv; 565aba92962SSimon Glass 566aba92962SSimon Glass for (id = entry->match; 567aba92962SSimon Glass id->vendor || id->subvendor || id->class_mask; 568aba92962SSimon Glass id++) { 569aba92962SSimon Glass if (!pci_match_one_id(id, find_id)) 570aba92962SSimon Glass continue; 571aba92962SSimon Glass 572aba92962SSimon Glass drv = entry->driver; 57308fc7b8fSBin Meng 57408fc7b8fSBin Meng /* 57508fc7b8fSBin Meng * In the pre-relocation phase, we only bind devices 57608fc7b8fSBin Meng * whose driver has the DM_FLAG_PRE_RELOC set, to save 57708fc7b8fSBin Meng * precious memory space as on some platforms as that 57808fc7b8fSBin Meng * space is pretty limited (ie: using Cache As RAM). 57908fc7b8fSBin Meng */ 58008fc7b8fSBin Meng if (!(gd->flags & GD_FLG_RELOC) && 58108fc7b8fSBin Meng !(drv->flags & DM_FLAG_PRE_RELOC)) 5825dbcf3a0SSimon Glass return -EPERM; 58308fc7b8fSBin Meng 584aba92962SSimon Glass /* 585aba92962SSimon Glass * We could pass the descriptor to the driver as 586aba92962SSimon Glass * platdata (instead of NULL) and allow its bind() 587aba92962SSimon Glass * method to return -ENOENT if it doesn't support this 588aba92962SSimon Glass * device. That way we could continue the search to 589aba92962SSimon Glass * find another driver. For now this doesn't seem 590aba92962SSimon Glass * necesssary, so just bind the first match. 591aba92962SSimon Glass */ 592aba92962SSimon Glass ret = device_bind(parent, drv, drv->name, NULL, -1, 593aba92962SSimon Glass &dev); 594aba92962SSimon Glass if (ret) 595aba92962SSimon Glass goto error; 596aba92962SSimon Glass debug("%s: Match found: %s\n", __func__, drv->name); 597aba92962SSimon Glass dev->driver_data = find_id->driver_data; 598aba92962SSimon Glass *devp = dev; 599aba92962SSimon Glass return 0; 600aba92962SSimon Glass } 601aba92962SSimon Glass } 602aba92962SSimon Glass 60308fc7b8fSBin Meng bridge = (find_id->class >> 8) == PCI_CLASS_BRIDGE_PCI; 60408fc7b8fSBin Meng /* 60508fc7b8fSBin Meng * In the pre-relocation phase, we only bind bridge devices to save 60608fc7b8fSBin Meng * precious memory space as on some platforms as that space is pretty 60708fc7b8fSBin Meng * limited (ie: using Cache As RAM). 60808fc7b8fSBin Meng */ 60908fc7b8fSBin Meng if (!(gd->flags & GD_FLG_RELOC) && !bridge) 6105dbcf3a0SSimon Glass return -EPERM; 61108fc7b8fSBin Meng 612aba92962SSimon Glass /* Bind a generic driver so that the device can be used */ 6134d8615cbSBin Meng sprintf(name, "pci_%x:%x.%x", parent->seq, PCI_DEV(bdf), 6144d8615cbSBin Meng PCI_FUNC(bdf)); 615aba92962SSimon Glass str = strdup(name); 616aba92962SSimon Glass if (!str) 617aba92962SSimon Glass return -ENOMEM; 61808fc7b8fSBin Meng drv = bridge ? "pci_bridge_drv" : "pci_generic_drv"; 61908fc7b8fSBin Meng 620aba92962SSimon Glass ret = device_bind_driver(parent, drv, str, devp); 621aba92962SSimon Glass if (ret) { 6223129ace4SSimon Glass debug("%s: Failed to bind generic driver: %d\n", __func__, ret); 623aba92962SSimon Glass return ret; 624aba92962SSimon Glass } 625aba92962SSimon Glass debug("%s: No match found: bound generic driver instead\n", __func__); 626aba92962SSimon Glass 627aba92962SSimon Glass return 0; 628aba92962SSimon Glass 629aba92962SSimon Glass error: 630aba92962SSimon Glass debug("%s: No match found: error %d\n", __func__, ret); 631aba92962SSimon Glass return ret; 632aba92962SSimon Glass } 633aba92962SSimon Glass 634ff3e077bSSimon Glass int pci_bind_bus_devices(struct udevice *bus) 635ff3e077bSSimon Glass { 636ff3e077bSSimon Glass ulong vendor, device; 637ff3e077bSSimon Glass ulong header_type; 6384d8615cbSBin Meng pci_dev_t bdf, end; 639ff3e077bSSimon Glass bool found_multi; 640ff3e077bSSimon Glass int ret; 641ff3e077bSSimon Glass 642ff3e077bSSimon Glass found_multi = false; 6434d8615cbSBin Meng end = PCI_BDF(bus->seq, PCI_MAX_PCI_DEVICES - 1, 6444d8615cbSBin Meng PCI_MAX_PCI_FUNCTIONS - 1); 6454d8615cbSBin Meng for (bdf = PCI_BDF(bus->seq, 0, 0); bdf < end; 6464d8615cbSBin Meng bdf += PCI_BDF(0, 0, 1)) { 647ff3e077bSSimon Glass struct pci_child_platdata *pplat; 648ff3e077bSSimon Glass struct udevice *dev; 649ff3e077bSSimon Glass ulong class; 650ff3e077bSSimon Glass 6514d8615cbSBin Meng if (PCI_FUNC(bdf) && !found_multi) 652ff3e077bSSimon Glass continue; 653ff3e077bSSimon Glass /* Check only the first access, we don't expect problems */ 6544d8615cbSBin Meng ret = pci_bus_read_config(bus, bdf, PCI_HEADER_TYPE, 655ff3e077bSSimon Glass &header_type, PCI_SIZE_8); 656ff3e077bSSimon Glass if (ret) 657ff3e077bSSimon Glass goto error; 6584d8615cbSBin Meng pci_bus_read_config(bus, bdf, PCI_VENDOR_ID, &vendor, 659ff3e077bSSimon Glass PCI_SIZE_16); 660ff3e077bSSimon Glass if (vendor == 0xffff || vendor == 0x0000) 661ff3e077bSSimon Glass continue; 662ff3e077bSSimon Glass 6634d8615cbSBin Meng if (!PCI_FUNC(bdf)) 664ff3e077bSSimon Glass found_multi = header_type & 0x80; 665ff3e077bSSimon Glass 666ff3e077bSSimon Glass debug("%s: bus %d/%s: found device %x, function %d\n", __func__, 6674d8615cbSBin Meng bus->seq, bus->name, PCI_DEV(bdf), PCI_FUNC(bdf)); 6684d8615cbSBin Meng pci_bus_read_config(bus, bdf, PCI_DEVICE_ID, &device, 669ff3e077bSSimon Glass PCI_SIZE_16); 6704d8615cbSBin Meng pci_bus_read_config(bus, bdf, PCI_CLASS_REVISION, &class, 671aba92962SSimon Glass PCI_SIZE_32); 672aba92962SSimon Glass class >>= 8; 673ff3e077bSSimon Glass 674ff3e077bSSimon Glass /* Find this device in the device tree */ 6754d8615cbSBin Meng ret = pci_bus_find_devfn(bus, PCI_MASK_BUS(bdf), &dev); 676ff3e077bSSimon Glass 677aba92962SSimon Glass /* Search for a driver */ 678aba92962SSimon Glass 679ff3e077bSSimon Glass /* If nothing in the device tree, bind a generic device */ 680ff3e077bSSimon Glass if (ret == -ENODEV) { 681aba92962SSimon Glass struct pci_device_id find_id; 682aba92962SSimon Glass ulong val; 683ff3e077bSSimon Glass 684aba92962SSimon Glass memset(&find_id, '\0', sizeof(find_id)); 685aba92962SSimon Glass find_id.vendor = vendor; 686aba92962SSimon Glass find_id.device = device; 687aba92962SSimon Glass find_id.class = class; 688aba92962SSimon Glass if ((header_type & 0x7f) == PCI_HEADER_TYPE_NORMAL) { 6894d8615cbSBin Meng pci_bus_read_config(bus, bdf, 690aba92962SSimon Glass PCI_SUBSYSTEM_VENDOR_ID, 691aba92962SSimon Glass &val, PCI_SIZE_32); 692aba92962SSimon Glass find_id.subvendor = val & 0xffff; 693aba92962SSimon Glass find_id.subdevice = val >> 16; 694aba92962SSimon Glass } 6954d8615cbSBin Meng ret = pci_find_and_bind_driver(bus, &find_id, bdf, 696aba92962SSimon Glass &dev); 697ff3e077bSSimon Glass } 6985dbcf3a0SSimon Glass if (ret == -EPERM) 6995dbcf3a0SSimon Glass continue; 7005dbcf3a0SSimon Glass else if (ret) 701ff3e077bSSimon Glass return ret; 702ff3e077bSSimon Glass 703ff3e077bSSimon Glass /* Update the platform data */ 704ff3e077bSSimon Glass pplat = dev_get_parent_platdata(dev); 7054d8615cbSBin Meng pplat->devfn = PCI_MASK_BUS(bdf); 706ff3e077bSSimon Glass pplat->vendor = vendor; 707ff3e077bSSimon Glass pplat->device = device; 708ff3e077bSSimon Glass pplat->class = class; 709ff3e077bSSimon Glass } 710ff3e077bSSimon Glass 711ff3e077bSSimon Glass return 0; 712ff3e077bSSimon Glass error: 713ff3e077bSSimon Glass printf("Cannot read bus configuration: %d\n", ret); 714ff3e077bSSimon Glass 715ff3e077bSSimon Glass return ret; 716ff3e077bSSimon Glass } 717ff3e077bSSimon Glass 718ff3e077bSSimon Glass static int pci_uclass_post_bind(struct udevice *bus) 719ff3e077bSSimon Glass { 720ff3e077bSSimon Glass /* 7211887ed3aSBin Meng * If there is no pci device listed in the device tree, 7221887ed3aSBin Meng * don't bother scanning the device tree. 7231887ed3aSBin Meng */ 7241887ed3aSBin Meng if (bus->of_offset == -1) 7251887ed3aSBin Meng return 0; 7261887ed3aSBin Meng 7271887ed3aSBin Meng /* 728ff3e077bSSimon Glass * Scan the device tree for devices. This does not probe the PCI bus, 729ff3e077bSSimon Glass * as this is not permitted while binding. It just finds devices 730ff3e077bSSimon Glass * mentioned in the device tree. 731ff3e077bSSimon Glass * 732ff3e077bSSimon Glass * Before relocation, only bind devices marked for pre-relocation 733ff3e077bSSimon Glass * use. 734ff3e077bSSimon Glass */ 735ff3e077bSSimon Glass return dm_scan_fdt_node(bus, gd->fdt_blob, bus->of_offset, 736ff3e077bSSimon Glass gd->flags & GD_FLG_RELOC ? false : true); 737ff3e077bSSimon Glass } 738ff3e077bSSimon Glass 739ff3e077bSSimon Glass static int decode_regions(struct pci_controller *hose, const void *blob, 740ff3e077bSSimon Glass int parent_node, int node) 741ff3e077bSSimon Glass { 742ff3e077bSSimon Glass int pci_addr_cells, addr_cells, size_cells; 7432084c5afSSimon Glass phys_addr_t base = 0, size; 744ff3e077bSSimon Glass int cells_per_record; 745ff3e077bSSimon Glass const u32 *prop; 746ff3e077bSSimon Glass int len; 747ff3e077bSSimon Glass int i; 748ff3e077bSSimon Glass 749ff3e077bSSimon Glass prop = fdt_getprop(blob, node, "ranges", &len); 750ff3e077bSSimon Glass if (!prop) 751ff3e077bSSimon Glass return -EINVAL; 752ff3e077bSSimon Glass pci_addr_cells = fdt_address_cells(blob, node); 753ff3e077bSSimon Glass addr_cells = fdt_address_cells(blob, parent_node); 754ff3e077bSSimon Glass size_cells = fdt_size_cells(blob, node); 755ff3e077bSSimon Glass 756ff3e077bSSimon Glass /* PCI addresses are always 3-cells */ 757ff3e077bSSimon Glass len /= sizeof(u32); 758ff3e077bSSimon Glass cells_per_record = pci_addr_cells + addr_cells + size_cells; 759ff3e077bSSimon Glass hose->region_count = 0; 760ff3e077bSSimon Glass debug("%s: len=%d, cells_per_record=%d\n", __func__, len, 761ff3e077bSSimon Glass cells_per_record); 762ff3e077bSSimon Glass for (i = 0; i < MAX_PCI_REGIONS; i++, len -= cells_per_record) { 763ff3e077bSSimon Glass u64 pci_addr, addr, size; 764ff3e077bSSimon Glass int space_code; 765ff3e077bSSimon Glass u32 flags; 766ff3e077bSSimon Glass int type; 7679526d83aSSimon Glass int pos; 768ff3e077bSSimon Glass 769ff3e077bSSimon Glass if (len < cells_per_record) 770ff3e077bSSimon Glass break; 771ff3e077bSSimon Glass flags = fdt32_to_cpu(prop[0]); 772ff3e077bSSimon Glass space_code = (flags >> 24) & 3; 773ff3e077bSSimon Glass pci_addr = fdtdec_get_number(prop + 1, 2); 774ff3e077bSSimon Glass prop += pci_addr_cells; 775ff3e077bSSimon Glass addr = fdtdec_get_number(prop, addr_cells); 776ff3e077bSSimon Glass prop += addr_cells; 777ff3e077bSSimon Glass size = fdtdec_get_number(prop, size_cells); 778ff3e077bSSimon Glass prop += size_cells; 779ff3e077bSSimon Glass debug("%s: region %d, pci_addr=%" PRIx64 ", addr=%" PRIx64 780ff3e077bSSimon Glass ", size=%" PRIx64 ", space_code=%d\n", __func__, 781ff3e077bSSimon Glass hose->region_count, pci_addr, addr, size, space_code); 782ff3e077bSSimon Glass if (space_code & 2) { 783ff3e077bSSimon Glass type = flags & (1U << 30) ? PCI_REGION_PREFETCH : 784ff3e077bSSimon Glass PCI_REGION_MEM; 785ff3e077bSSimon Glass } else if (space_code & 1) { 786ff3e077bSSimon Glass type = PCI_REGION_IO; 787ff3e077bSSimon Glass } else { 788ff3e077bSSimon Glass continue; 789ff3e077bSSimon Glass } 7909526d83aSSimon Glass pos = -1; 7919526d83aSSimon Glass for (i = 0; i < hose->region_count; i++) { 7929526d83aSSimon Glass if (hose->regions[i].flags == type) 7939526d83aSSimon Glass pos = i; 7949526d83aSSimon Glass } 7959526d83aSSimon Glass if (pos == -1) 7969526d83aSSimon Glass pos = hose->region_count++; 7979526d83aSSimon Glass debug(" - type=%d, pos=%d\n", type, pos); 7989526d83aSSimon Glass pci_set_region(hose->regions + pos, pci_addr, addr, size, type); 799ff3e077bSSimon Glass } 800ff3e077bSSimon Glass 801ff3e077bSSimon Glass /* Add a region for our local memory */ 8022084c5afSSimon Glass size = gd->ram_size; 8032084c5afSSimon Glass #ifdef CONFIG_SYS_SDRAM_BASE 8042084c5afSSimon Glass base = CONFIG_SYS_SDRAM_BASE; 8052084c5afSSimon Glass #endif 8062084c5afSSimon Glass if (gd->pci_ram_top && gd->pci_ram_top < base + size) 8072084c5afSSimon Glass size = gd->pci_ram_top - base; 8082084c5afSSimon Glass pci_set_region(hose->regions + hose->region_count++, base, base, 8092084c5afSSimon Glass size, PCI_REGION_MEM | PCI_REGION_SYS_MEMORY); 810ff3e077bSSimon Glass 811ff3e077bSSimon Glass return 0; 812ff3e077bSSimon Glass } 813ff3e077bSSimon Glass 814ff3e077bSSimon Glass static int pci_uclass_pre_probe(struct udevice *bus) 815ff3e077bSSimon Glass { 816ff3e077bSSimon Glass struct pci_controller *hose; 817ff3e077bSSimon Glass int ret; 818ff3e077bSSimon Glass 819ff3e077bSSimon Glass debug("%s, bus=%d/%s, parent=%s\n", __func__, bus->seq, bus->name, 820ff3e077bSSimon Glass bus->parent->name); 821ff3e077bSSimon Glass hose = bus->uclass_priv; 822ff3e077bSSimon Glass 823ff3e077bSSimon Glass /* For bridges, use the top-level PCI controller */ 824ff3e077bSSimon Glass if (device_get_uclass_id(bus->parent) == UCLASS_ROOT) { 825ff3e077bSSimon Glass hose->ctlr = bus; 826ff3e077bSSimon Glass ret = decode_regions(hose, gd->fdt_blob, bus->parent->of_offset, 827ff3e077bSSimon Glass bus->of_offset); 828ff3e077bSSimon Glass if (ret) { 829ff3e077bSSimon Glass debug("%s: Cannot decode regions\n", __func__); 830ff3e077bSSimon Glass return ret; 831ff3e077bSSimon Glass } 832ff3e077bSSimon Glass } else { 833ff3e077bSSimon Glass struct pci_controller *parent_hose; 834ff3e077bSSimon Glass 835ff3e077bSSimon Glass parent_hose = dev_get_uclass_priv(bus->parent); 836ff3e077bSSimon Glass hose->ctlr = parent_hose->bus; 837ff3e077bSSimon Glass } 838ff3e077bSSimon Glass hose->bus = bus; 839ff3e077bSSimon Glass hose->first_busno = bus->seq; 840ff3e077bSSimon Glass hose->last_busno = bus->seq; 841ff3e077bSSimon Glass 842ff3e077bSSimon Glass return 0; 843ff3e077bSSimon Glass } 844ff3e077bSSimon Glass 845ff3e077bSSimon Glass static int pci_uclass_post_probe(struct udevice *bus) 846ff3e077bSSimon Glass { 847ff3e077bSSimon Glass int ret; 848ff3e077bSSimon Glass 849ff3e077bSSimon Glass debug("%s: probing bus %d\n", __func__, bus->seq); 850ff3e077bSSimon Glass ret = pci_bind_bus_devices(bus); 851ff3e077bSSimon Glass if (ret) 852ff3e077bSSimon Glass return ret; 853ff3e077bSSimon Glass 854ff3e077bSSimon Glass #ifdef CONFIG_PCI_PNP 855ff3e077bSSimon Glass ret = pci_auto_config_devices(bus); 8564d21455eSSimon Glass if (ret < 0) 8574d21455eSSimon Glass return ret; 858ff3e077bSSimon Glass #endif 859ff3e077bSSimon Glass 860348b744bSBin Meng #if defined(CONFIG_X86) && defined(CONFIG_HAVE_FSP) 861348b744bSBin Meng /* 862348b744bSBin Meng * Per Intel FSP specification, we should call FSP notify API to 863348b744bSBin Meng * inform FSP that PCI enumeration has been done so that FSP will 864348b744bSBin Meng * do any necessary initialization as required by the chipset's 865348b744bSBin Meng * BIOS Writer's Guide (BWG). 866348b744bSBin Meng * 867348b744bSBin Meng * Unfortunately we have to put this call here as with driver model, 868348b744bSBin Meng * the enumeration is all done on a lazy basis as needed, so until 869348b744bSBin Meng * something is touched on PCI it won't happen. 870348b744bSBin Meng * 871348b744bSBin Meng * Note we only call this 1) after U-Boot is relocated, and 2) 872348b744bSBin Meng * root bus has finished probing. 873348b744bSBin Meng */ 8744d21455eSSimon Glass if ((gd->flags & GD_FLG_RELOC) && (bus->seq == 0)) { 875348b744bSBin Meng ret = fsp_init_phase_pci(); 8764d21455eSSimon Glass if (ret) 8774d21455eSSimon Glass return ret; 8784d21455eSSimon Glass } 879348b744bSBin Meng #endif 880348b744bSBin Meng 8814d21455eSSimon Glass return 0; 882ff3e077bSSimon Glass } 883ff3e077bSSimon Glass 884ff3e077bSSimon Glass static int pci_uclass_child_post_bind(struct udevice *dev) 885ff3e077bSSimon Glass { 886ff3e077bSSimon Glass struct pci_child_platdata *pplat; 887ff3e077bSSimon Glass struct fdt_pci_addr addr; 888ff3e077bSSimon Glass int ret; 889ff3e077bSSimon Glass 890ff3e077bSSimon Glass if (dev->of_offset == -1) 891ff3e077bSSimon Glass return 0; 892ff3e077bSSimon Glass 893ff3e077bSSimon Glass /* 894ff3e077bSSimon Glass * We could read vendor, device, class if available. But for now we 895ff3e077bSSimon Glass * just check the address. 896ff3e077bSSimon Glass */ 897ff3e077bSSimon Glass pplat = dev_get_parent_platdata(dev); 898ff3e077bSSimon Glass ret = fdtdec_get_pci_addr(gd->fdt_blob, dev->of_offset, 899ff3e077bSSimon Glass FDT_PCI_SPACE_CONFIG, "reg", &addr); 900ff3e077bSSimon Glass 901ff3e077bSSimon Glass if (ret) { 902ff3e077bSSimon Glass if (ret != -ENOENT) 903ff3e077bSSimon Glass return -EINVAL; 904ff3e077bSSimon Glass } else { 905dce54dd6SBin Meng /* extract the devfn from fdt_pci_addr */ 906dce54dd6SBin Meng pplat->devfn = addr.phys_hi & 0xff00; 907ff3e077bSSimon Glass } 908ff3e077bSSimon Glass 909ff3e077bSSimon Glass return 0; 910ff3e077bSSimon Glass } 911ff3e077bSSimon Glass 9124d8615cbSBin Meng static int pci_bridge_read_config(struct udevice *bus, pci_dev_t bdf, 9134d8615cbSBin Meng uint offset, ulong *valuep, 9144d8615cbSBin Meng enum pci_size_t size) 915ff3e077bSSimon Glass { 916ff3e077bSSimon Glass struct pci_controller *hose = bus->uclass_priv; 917ff3e077bSSimon Glass 918ff3e077bSSimon Glass return pci_bus_read_config(hose->ctlr, bdf, offset, valuep, size); 919ff3e077bSSimon Glass } 920ff3e077bSSimon Glass 9214d8615cbSBin Meng static int pci_bridge_write_config(struct udevice *bus, pci_dev_t bdf, 9224d8615cbSBin Meng uint offset, ulong value, 9234d8615cbSBin Meng enum pci_size_t size) 924ff3e077bSSimon Glass { 925ff3e077bSSimon Glass struct pci_controller *hose = bus->uclass_priv; 926ff3e077bSSimon Glass 927ff3e077bSSimon Glass return pci_bus_write_config(hose->ctlr, bdf, offset, value, size); 928ff3e077bSSimon Glass } 929ff3e077bSSimon Glass 93076c3fbcdSSimon Glass static int skip_to_next_device(struct udevice *bus, struct udevice **devp) 93176c3fbcdSSimon Glass { 93276c3fbcdSSimon Glass struct udevice *dev; 93376c3fbcdSSimon Glass int ret = 0; 93476c3fbcdSSimon Glass 93576c3fbcdSSimon Glass /* 93676c3fbcdSSimon Glass * Scan through all the PCI controllers. On x86 there will only be one 93776c3fbcdSSimon Glass * but that is not necessarily true on other hardware. 93876c3fbcdSSimon Glass */ 93976c3fbcdSSimon Glass do { 94076c3fbcdSSimon Glass device_find_first_child(bus, &dev); 94176c3fbcdSSimon Glass if (dev) { 94276c3fbcdSSimon Glass *devp = dev; 94376c3fbcdSSimon Glass return 0; 94476c3fbcdSSimon Glass } 94576c3fbcdSSimon Glass ret = uclass_next_device(&bus); 94676c3fbcdSSimon Glass if (ret) 94776c3fbcdSSimon Glass return ret; 94876c3fbcdSSimon Glass } while (bus); 94976c3fbcdSSimon Glass 95076c3fbcdSSimon Glass return 0; 95176c3fbcdSSimon Glass } 95276c3fbcdSSimon Glass 95376c3fbcdSSimon Glass int pci_find_next_device(struct udevice **devp) 95476c3fbcdSSimon Glass { 95576c3fbcdSSimon Glass struct udevice *child = *devp; 95676c3fbcdSSimon Glass struct udevice *bus = child->parent; 95776c3fbcdSSimon Glass int ret; 95876c3fbcdSSimon Glass 95976c3fbcdSSimon Glass /* First try all the siblings */ 96076c3fbcdSSimon Glass *devp = NULL; 96176c3fbcdSSimon Glass while (child) { 96276c3fbcdSSimon Glass device_find_next_child(&child); 96376c3fbcdSSimon Glass if (child) { 96476c3fbcdSSimon Glass *devp = child; 96576c3fbcdSSimon Glass return 0; 96676c3fbcdSSimon Glass } 96776c3fbcdSSimon Glass } 96876c3fbcdSSimon Glass 96976c3fbcdSSimon Glass /* We ran out of siblings. Try the next bus */ 97076c3fbcdSSimon Glass ret = uclass_next_device(&bus); 97176c3fbcdSSimon Glass if (ret) 97276c3fbcdSSimon Glass return ret; 97376c3fbcdSSimon Glass 97476c3fbcdSSimon Glass return bus ? skip_to_next_device(bus, devp) : 0; 97576c3fbcdSSimon Glass } 97676c3fbcdSSimon Glass 97776c3fbcdSSimon Glass int pci_find_first_device(struct udevice **devp) 97876c3fbcdSSimon Glass { 97976c3fbcdSSimon Glass struct udevice *bus; 98076c3fbcdSSimon Glass int ret; 98176c3fbcdSSimon Glass 98276c3fbcdSSimon Glass *devp = NULL; 98376c3fbcdSSimon Glass ret = uclass_first_device(UCLASS_PCI, &bus); 98476c3fbcdSSimon Glass if (ret) 98576c3fbcdSSimon Glass return ret; 98676c3fbcdSSimon Glass 98776c3fbcdSSimon Glass return skip_to_next_device(bus, devp); 98876c3fbcdSSimon Glass } 98976c3fbcdSSimon Glass 9909289db6cSSimon Glass ulong pci_conv_32_to_size(ulong value, uint offset, enum pci_size_t size) 9919289db6cSSimon Glass { 9929289db6cSSimon Glass switch (size) { 9939289db6cSSimon Glass case PCI_SIZE_8: 9949289db6cSSimon Glass return (value >> ((offset & 3) * 8)) & 0xff; 9959289db6cSSimon Glass case PCI_SIZE_16: 9969289db6cSSimon Glass return (value >> ((offset & 2) * 8)) & 0xffff; 9979289db6cSSimon Glass default: 9989289db6cSSimon Glass return value; 9999289db6cSSimon Glass } 10009289db6cSSimon Glass } 10019289db6cSSimon Glass 10029289db6cSSimon Glass ulong pci_conv_size_to_32(ulong old, ulong value, uint offset, 10039289db6cSSimon Glass enum pci_size_t size) 10049289db6cSSimon Glass { 10059289db6cSSimon Glass uint off_mask; 10069289db6cSSimon Glass uint val_mask, shift; 10079289db6cSSimon Glass ulong ldata, mask; 10089289db6cSSimon Glass 10099289db6cSSimon Glass switch (size) { 10109289db6cSSimon Glass case PCI_SIZE_8: 10119289db6cSSimon Glass off_mask = 3; 10129289db6cSSimon Glass val_mask = 0xff; 10139289db6cSSimon Glass break; 10149289db6cSSimon Glass case PCI_SIZE_16: 10159289db6cSSimon Glass off_mask = 2; 10169289db6cSSimon Glass val_mask = 0xffff; 10179289db6cSSimon Glass break; 10189289db6cSSimon Glass default: 10199289db6cSSimon Glass return value; 10209289db6cSSimon Glass } 10219289db6cSSimon Glass shift = (offset & off_mask) * 8; 10229289db6cSSimon Glass ldata = (value & val_mask) << shift; 10239289db6cSSimon Glass mask = val_mask << shift; 10249289db6cSSimon Glass value = (old & ~mask) | ldata; 10259289db6cSSimon Glass 10269289db6cSSimon Glass return value; 10279289db6cSSimon Glass } 10289289db6cSSimon Glass 1029f9260336SSimon Glass int pci_get_regions(struct udevice *dev, struct pci_region **iop, 1030f9260336SSimon Glass struct pci_region **memp, struct pci_region **prefp) 1031f9260336SSimon Glass { 1032f9260336SSimon Glass struct udevice *bus = pci_get_controller(dev); 1033f9260336SSimon Glass struct pci_controller *hose = dev_get_uclass_priv(bus); 1034f9260336SSimon Glass int i; 1035f9260336SSimon Glass 1036f9260336SSimon Glass *iop = NULL; 1037f9260336SSimon Glass *memp = NULL; 1038f9260336SSimon Glass *prefp = NULL; 1039f9260336SSimon Glass for (i = 0; i < hose->region_count; i++) { 1040f9260336SSimon Glass switch (hose->regions[i].flags) { 1041f9260336SSimon Glass case PCI_REGION_IO: 1042f9260336SSimon Glass if (!*iop || (*iop)->size < hose->regions[i].size) 1043f9260336SSimon Glass *iop = hose->regions + i; 1044f9260336SSimon Glass break; 1045f9260336SSimon Glass case PCI_REGION_MEM: 1046f9260336SSimon Glass if (!*memp || (*memp)->size < hose->regions[i].size) 1047f9260336SSimon Glass *memp = hose->regions + i; 1048f9260336SSimon Glass break; 1049f9260336SSimon Glass case (PCI_REGION_MEM | PCI_REGION_PREFETCH): 1050f9260336SSimon Glass if (!*prefp || (*prefp)->size < hose->regions[i].size) 1051f9260336SSimon Glass *prefp = hose->regions + i; 1052f9260336SSimon Glass break; 1053f9260336SSimon Glass } 1054f9260336SSimon Glass } 1055f9260336SSimon Glass 1056f9260336SSimon Glass return (*iop != NULL) + (*memp != NULL) + (*prefp != NULL); 1057f9260336SSimon Glass } 1058f9260336SSimon Glass 1059bab17cf1SSimon Glass u32 dm_pci_read_bar32(struct udevice *dev, int barnum) 1060bab17cf1SSimon Glass { 1061bab17cf1SSimon Glass u32 addr; 1062bab17cf1SSimon Glass int bar; 1063bab17cf1SSimon Glass 1064bab17cf1SSimon Glass bar = PCI_BASE_ADDRESS_0 + barnum * 4; 1065bab17cf1SSimon Glass dm_pci_read_config32(dev, bar, &addr); 1066bab17cf1SSimon Glass if (addr & PCI_BASE_ADDRESS_SPACE_IO) 1067bab17cf1SSimon Glass return addr & PCI_BASE_ADDRESS_IO_MASK; 1068bab17cf1SSimon Glass else 1069bab17cf1SSimon Glass return addr & PCI_BASE_ADDRESS_MEM_MASK; 1070bab17cf1SSimon Glass } 1071bab17cf1SSimon Glass 1072*21d1fe7eSSimon Glass static int _dm_pci_bus_to_phys(struct udevice *ctlr, 1073*21d1fe7eSSimon Glass pci_addr_t bus_addr, unsigned long flags, 1074*21d1fe7eSSimon Glass unsigned long skip_mask, phys_addr_t *pa) 1075*21d1fe7eSSimon Glass { 1076*21d1fe7eSSimon Glass struct pci_controller *hose = dev_get_uclass_priv(ctlr); 1077*21d1fe7eSSimon Glass struct pci_region *res; 1078*21d1fe7eSSimon Glass int i; 1079*21d1fe7eSSimon Glass 1080*21d1fe7eSSimon Glass for (i = 0; i < hose->region_count; i++) { 1081*21d1fe7eSSimon Glass res = &hose->regions[i]; 1082*21d1fe7eSSimon Glass 1083*21d1fe7eSSimon Glass if (((res->flags ^ flags) & PCI_REGION_TYPE) != 0) 1084*21d1fe7eSSimon Glass continue; 1085*21d1fe7eSSimon Glass 1086*21d1fe7eSSimon Glass if (res->flags & skip_mask) 1087*21d1fe7eSSimon Glass continue; 1088*21d1fe7eSSimon Glass 1089*21d1fe7eSSimon Glass if (bus_addr >= res->bus_start && 1090*21d1fe7eSSimon Glass (bus_addr - res->bus_start) < res->size) { 1091*21d1fe7eSSimon Glass *pa = (bus_addr - res->bus_start + res->phys_start); 1092*21d1fe7eSSimon Glass return 0; 1093*21d1fe7eSSimon Glass } 1094*21d1fe7eSSimon Glass } 1095*21d1fe7eSSimon Glass 1096*21d1fe7eSSimon Glass return 1; 1097*21d1fe7eSSimon Glass } 1098*21d1fe7eSSimon Glass 1099*21d1fe7eSSimon Glass phys_addr_t dm_pci_bus_to_phys(struct udevice *dev, pci_addr_t bus_addr, 1100*21d1fe7eSSimon Glass unsigned long flags) 1101*21d1fe7eSSimon Glass { 1102*21d1fe7eSSimon Glass phys_addr_t phys_addr = 0; 1103*21d1fe7eSSimon Glass struct udevice *ctlr; 1104*21d1fe7eSSimon Glass int ret; 1105*21d1fe7eSSimon Glass 1106*21d1fe7eSSimon Glass /* The root controller has the region information */ 1107*21d1fe7eSSimon Glass ctlr = pci_get_controller(dev); 1108*21d1fe7eSSimon Glass 1109*21d1fe7eSSimon Glass /* 1110*21d1fe7eSSimon Glass * if PCI_REGION_MEM is set we do a two pass search with preference 1111*21d1fe7eSSimon Glass * on matches that don't have PCI_REGION_SYS_MEMORY set 1112*21d1fe7eSSimon Glass */ 1113*21d1fe7eSSimon Glass if ((flags & PCI_REGION_TYPE) == PCI_REGION_MEM) { 1114*21d1fe7eSSimon Glass ret = _dm_pci_bus_to_phys(ctlr, bus_addr, 1115*21d1fe7eSSimon Glass flags, PCI_REGION_SYS_MEMORY, 1116*21d1fe7eSSimon Glass &phys_addr); 1117*21d1fe7eSSimon Glass if (!ret) 1118*21d1fe7eSSimon Glass return phys_addr; 1119*21d1fe7eSSimon Glass } 1120*21d1fe7eSSimon Glass 1121*21d1fe7eSSimon Glass ret = _dm_pci_bus_to_phys(ctlr, bus_addr, flags, 0, &phys_addr); 1122*21d1fe7eSSimon Glass 1123*21d1fe7eSSimon Glass if (ret) 1124*21d1fe7eSSimon Glass puts("pci_hose_bus_to_phys: invalid physical address\n"); 1125*21d1fe7eSSimon Glass 1126*21d1fe7eSSimon Glass return phys_addr; 1127*21d1fe7eSSimon Glass } 1128*21d1fe7eSSimon Glass 1129*21d1fe7eSSimon Glass int _dm_pci_phys_to_bus(struct udevice *dev, phys_addr_t phys_addr, 1130*21d1fe7eSSimon Glass unsigned long flags, unsigned long skip_mask, 1131*21d1fe7eSSimon Glass pci_addr_t *ba) 1132*21d1fe7eSSimon Glass { 1133*21d1fe7eSSimon Glass struct pci_region *res; 1134*21d1fe7eSSimon Glass struct udevice *ctlr; 1135*21d1fe7eSSimon Glass pci_addr_t bus_addr; 1136*21d1fe7eSSimon Glass int i; 1137*21d1fe7eSSimon Glass struct pci_controller *hose; 1138*21d1fe7eSSimon Glass 1139*21d1fe7eSSimon Glass /* The root controller has the region information */ 1140*21d1fe7eSSimon Glass ctlr = pci_get_controller(dev); 1141*21d1fe7eSSimon Glass hose = dev_get_uclass_priv(ctlr); 1142*21d1fe7eSSimon Glass 1143*21d1fe7eSSimon Glass for (i = 0; i < hose->region_count; i++) { 1144*21d1fe7eSSimon Glass res = &hose->regions[i]; 1145*21d1fe7eSSimon Glass 1146*21d1fe7eSSimon Glass if (((res->flags ^ flags) & PCI_REGION_TYPE) != 0) 1147*21d1fe7eSSimon Glass continue; 1148*21d1fe7eSSimon Glass 1149*21d1fe7eSSimon Glass if (res->flags & skip_mask) 1150*21d1fe7eSSimon Glass continue; 1151*21d1fe7eSSimon Glass 1152*21d1fe7eSSimon Glass bus_addr = phys_addr - res->phys_start + res->bus_start; 1153*21d1fe7eSSimon Glass 1154*21d1fe7eSSimon Glass if (bus_addr >= res->bus_start && 1155*21d1fe7eSSimon Glass (bus_addr - res->bus_start) < res->size) { 1156*21d1fe7eSSimon Glass *ba = bus_addr; 1157*21d1fe7eSSimon Glass return 0; 1158*21d1fe7eSSimon Glass } 1159*21d1fe7eSSimon Glass } 1160*21d1fe7eSSimon Glass 1161*21d1fe7eSSimon Glass return 1; 1162*21d1fe7eSSimon Glass } 1163*21d1fe7eSSimon Glass 1164*21d1fe7eSSimon Glass pci_addr_t dm_pci_phys_to_bus(struct udevice *dev, phys_addr_t phys_addr, 1165*21d1fe7eSSimon Glass unsigned long flags) 1166*21d1fe7eSSimon Glass { 1167*21d1fe7eSSimon Glass pci_addr_t bus_addr = 0; 1168*21d1fe7eSSimon Glass int ret; 1169*21d1fe7eSSimon Glass 1170*21d1fe7eSSimon Glass /* 1171*21d1fe7eSSimon Glass * if PCI_REGION_MEM is set we do a two pass search with preference 1172*21d1fe7eSSimon Glass * on matches that don't have PCI_REGION_SYS_MEMORY set 1173*21d1fe7eSSimon Glass */ 1174*21d1fe7eSSimon Glass if ((flags & PCI_REGION_TYPE) == PCI_REGION_MEM) { 1175*21d1fe7eSSimon Glass ret = _dm_pci_phys_to_bus(dev, phys_addr, flags, 1176*21d1fe7eSSimon Glass PCI_REGION_SYS_MEMORY, &bus_addr); 1177*21d1fe7eSSimon Glass if (!ret) 1178*21d1fe7eSSimon Glass return bus_addr; 1179*21d1fe7eSSimon Glass } 1180*21d1fe7eSSimon Glass 1181*21d1fe7eSSimon Glass ret = _dm_pci_phys_to_bus(dev, phys_addr, flags, 0, &bus_addr); 1182*21d1fe7eSSimon Glass 1183*21d1fe7eSSimon Glass if (ret) 1184*21d1fe7eSSimon Glass puts("pci_hose_phys_to_bus: invalid physical address\n"); 1185*21d1fe7eSSimon Glass 1186*21d1fe7eSSimon Glass return bus_addr; 1187*21d1fe7eSSimon Glass } 1188*21d1fe7eSSimon Glass 1189*21d1fe7eSSimon Glass void *dm_pci_map_bar(struct udevice *dev, int bar, int flags) 1190*21d1fe7eSSimon Glass { 1191*21d1fe7eSSimon Glass pci_addr_t pci_bus_addr; 1192*21d1fe7eSSimon Glass u32 bar_response; 1193*21d1fe7eSSimon Glass 1194*21d1fe7eSSimon Glass /* read BAR address */ 1195*21d1fe7eSSimon Glass dm_pci_read_config32(dev, bar, &bar_response); 1196*21d1fe7eSSimon Glass pci_bus_addr = (pci_addr_t)(bar_response & ~0xf); 1197*21d1fe7eSSimon Glass 1198*21d1fe7eSSimon Glass /* 1199*21d1fe7eSSimon Glass * Pass "0" as the length argument to pci_bus_to_virt. The arg 1200*21d1fe7eSSimon Glass * isn't actualy used on any platform because u-boot assumes a static 1201*21d1fe7eSSimon Glass * linear mapping. In the future, this could read the BAR size 1202*21d1fe7eSSimon Glass * and pass that as the size if needed. 1203*21d1fe7eSSimon Glass */ 1204*21d1fe7eSSimon Glass return dm_pci_bus_to_virt(dev, pci_bus_addr, flags, 0, MAP_NOCACHE); 1205*21d1fe7eSSimon Glass } 1206*21d1fe7eSSimon Glass 1207ff3e077bSSimon Glass UCLASS_DRIVER(pci) = { 1208ff3e077bSSimon Glass .id = UCLASS_PCI, 1209ff3e077bSSimon Glass .name = "pci", 12102bb02e4fSSimon Glass .flags = DM_UC_FLAG_SEQ_ALIAS, 1211ff3e077bSSimon Glass .post_bind = pci_uclass_post_bind, 1212ff3e077bSSimon Glass .pre_probe = pci_uclass_pre_probe, 1213ff3e077bSSimon Glass .post_probe = pci_uclass_post_probe, 1214ff3e077bSSimon Glass .child_post_bind = pci_uclass_child_post_bind, 1215ff3e077bSSimon Glass .per_device_auto_alloc_size = sizeof(struct pci_controller), 1216ff3e077bSSimon Glass .per_child_platdata_auto_alloc_size = 1217ff3e077bSSimon Glass sizeof(struct pci_child_platdata), 1218ff3e077bSSimon Glass }; 1219ff3e077bSSimon Glass 1220ff3e077bSSimon Glass static const struct dm_pci_ops pci_bridge_ops = { 1221ff3e077bSSimon Glass .read_config = pci_bridge_read_config, 1222ff3e077bSSimon Glass .write_config = pci_bridge_write_config, 1223ff3e077bSSimon Glass }; 1224ff3e077bSSimon Glass 1225ff3e077bSSimon Glass static const struct udevice_id pci_bridge_ids[] = { 1226ff3e077bSSimon Glass { .compatible = "pci-bridge" }, 1227ff3e077bSSimon Glass { } 1228ff3e077bSSimon Glass }; 1229ff3e077bSSimon Glass 1230ff3e077bSSimon Glass U_BOOT_DRIVER(pci_bridge_drv) = { 1231ff3e077bSSimon Glass .name = "pci_bridge_drv", 1232ff3e077bSSimon Glass .id = UCLASS_PCI, 1233ff3e077bSSimon Glass .of_match = pci_bridge_ids, 1234ff3e077bSSimon Glass .ops = &pci_bridge_ops, 1235ff3e077bSSimon Glass }; 1236ff3e077bSSimon Glass 1237ff3e077bSSimon Glass UCLASS_DRIVER(pci_generic) = { 1238ff3e077bSSimon Glass .id = UCLASS_PCI_GENERIC, 1239ff3e077bSSimon Glass .name = "pci_generic", 1240ff3e077bSSimon Glass }; 1241ff3e077bSSimon Glass 1242ff3e077bSSimon Glass static const struct udevice_id pci_generic_ids[] = { 1243ff3e077bSSimon Glass { .compatible = "pci-generic" }, 1244ff3e077bSSimon Glass { } 1245ff3e077bSSimon Glass }; 1246ff3e077bSSimon Glass 1247ff3e077bSSimon Glass U_BOOT_DRIVER(pci_generic_drv) = { 1248ff3e077bSSimon Glass .name = "pci_generic_drv", 1249ff3e077bSSimon Glass .id = UCLASS_PCI_GENERIC, 1250ff3e077bSSimon Glass .of_match = pci_generic_ids, 1251ff3e077bSSimon Glass }; 1252