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> 1421d1fe7eSSimon 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 25a6eb93b3SSimon Glass 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) { 33*3f603cbbSSimon Glass ret = uclass_first_device_err(UCLASS_PCI, busp); 34983c6ba2SSimon Glass if (ret) 35983c6ba2SSimon Glass return ret; 36983c6ba2SSimon Glass ret = uclass_get_device_by_seq(UCLASS_PCI, busnum, busp); 37983c6ba2SSimon Glass } 38983c6ba2SSimon Glass 39983c6ba2SSimon Glass return ret; 40983c6ba2SSimon Glass } 41983c6ba2SSimon Glass 429f60fb0dSSimon Glass struct udevice *pci_get_controller(struct udevice *dev) 439f60fb0dSSimon Glass { 449f60fb0dSSimon Glass while (device_is_on_pci_bus(dev)) 459f60fb0dSSimon Glass dev = dev->parent; 469f60fb0dSSimon Glass 479f60fb0dSSimon Glass return dev; 489f60fb0dSSimon Glass } 499f60fb0dSSimon Glass 5021ccce1bSSimon Glass pci_dev_t dm_pci_get_bdf(struct udevice *dev) 514b515e4fSSimon Glass { 524b515e4fSSimon Glass struct pci_child_platdata *pplat = dev_get_parent_platdata(dev); 534b515e4fSSimon Glass struct udevice *bus = dev->parent; 544b515e4fSSimon Glass 554b515e4fSSimon Glass return PCI_ADD_BUS(bus->seq, pplat->devfn); 564b515e4fSSimon Glass } 574b515e4fSSimon Glass 58ff3e077bSSimon Glass /** 59ff3e077bSSimon Glass * pci_get_bus_max() - returns the bus number of the last active bus 60ff3e077bSSimon Glass * 61ff3e077bSSimon Glass * @return last bus number, or -1 if no active buses 62ff3e077bSSimon Glass */ 63ff3e077bSSimon Glass static int pci_get_bus_max(void) 64ff3e077bSSimon Glass { 65ff3e077bSSimon Glass struct udevice *bus; 66ff3e077bSSimon Glass struct uclass *uc; 67ff3e077bSSimon Glass int ret = -1; 68ff3e077bSSimon Glass 69ff3e077bSSimon Glass ret = uclass_get(UCLASS_PCI, &uc); 70ff3e077bSSimon Glass uclass_foreach_dev(bus, uc) { 71ff3e077bSSimon Glass if (bus->seq > ret) 72ff3e077bSSimon Glass ret = bus->seq; 73ff3e077bSSimon Glass } 74ff3e077bSSimon Glass 75ff3e077bSSimon Glass debug("%s: ret=%d\n", __func__, ret); 76ff3e077bSSimon Glass 77ff3e077bSSimon Glass return ret; 78ff3e077bSSimon Glass } 79ff3e077bSSimon Glass 80ff3e077bSSimon Glass int pci_last_busno(void) 81ff3e077bSSimon Glass { 82069155cbSBin Meng return pci_get_bus_max(); 83ff3e077bSSimon Glass } 84ff3e077bSSimon Glass 85ff3e077bSSimon Glass int pci_get_ff(enum pci_size_t size) 86ff3e077bSSimon Glass { 87ff3e077bSSimon Glass switch (size) { 88ff3e077bSSimon Glass case PCI_SIZE_8: 89ff3e077bSSimon Glass return 0xff; 90ff3e077bSSimon Glass case PCI_SIZE_16: 91ff3e077bSSimon Glass return 0xffff; 92ff3e077bSSimon Glass default: 93ff3e077bSSimon Glass return 0xffffffff; 94ff3e077bSSimon Glass } 95ff3e077bSSimon Glass } 96ff3e077bSSimon Glass 97ff3e077bSSimon Glass int pci_bus_find_devfn(struct udevice *bus, pci_dev_t find_devfn, 98ff3e077bSSimon Glass struct udevice **devp) 99ff3e077bSSimon Glass { 100ff3e077bSSimon Glass struct udevice *dev; 101ff3e077bSSimon Glass 102ff3e077bSSimon Glass for (device_find_first_child(bus, &dev); 103ff3e077bSSimon Glass dev; 104ff3e077bSSimon Glass device_find_next_child(&dev)) { 105ff3e077bSSimon Glass struct pci_child_platdata *pplat; 106ff3e077bSSimon Glass 107ff3e077bSSimon Glass pplat = dev_get_parent_platdata(dev); 108ff3e077bSSimon Glass if (pplat && pplat->devfn == find_devfn) { 109ff3e077bSSimon Glass *devp = dev; 110ff3e077bSSimon Glass return 0; 111ff3e077bSSimon Glass } 112ff3e077bSSimon Glass } 113ff3e077bSSimon Glass 114ff3e077bSSimon Glass return -ENODEV; 115ff3e077bSSimon Glass } 116ff3e077bSSimon Glass 117f3f1faefSSimon Glass int dm_pci_bus_find_bdf(pci_dev_t bdf, struct udevice **devp) 118ff3e077bSSimon Glass { 119ff3e077bSSimon Glass struct udevice *bus; 120ff3e077bSSimon Glass int ret; 121ff3e077bSSimon Glass 122983c6ba2SSimon Glass ret = pci_get_bus(PCI_BUS(bdf), &bus); 123ff3e077bSSimon Glass if (ret) 124ff3e077bSSimon Glass return ret; 125ff3e077bSSimon Glass return pci_bus_find_devfn(bus, PCI_MASK_BUS(bdf), devp); 126ff3e077bSSimon Glass } 127ff3e077bSSimon Glass 128ff3e077bSSimon Glass static int pci_device_matches_ids(struct udevice *dev, 129ff3e077bSSimon Glass struct pci_device_id *ids) 130ff3e077bSSimon Glass { 131ff3e077bSSimon Glass struct pci_child_platdata *pplat; 132ff3e077bSSimon Glass int i; 133ff3e077bSSimon Glass 134ff3e077bSSimon Glass pplat = dev_get_parent_platdata(dev); 135ff3e077bSSimon Glass if (!pplat) 136ff3e077bSSimon Glass return -EINVAL; 137ff3e077bSSimon Glass for (i = 0; ids[i].vendor != 0; i++) { 138ff3e077bSSimon Glass if (pplat->vendor == ids[i].vendor && 139ff3e077bSSimon Glass pplat->device == ids[i].device) 140ff3e077bSSimon Glass return i; 141ff3e077bSSimon Glass } 142ff3e077bSSimon Glass 143ff3e077bSSimon Glass return -EINVAL; 144ff3e077bSSimon Glass } 145ff3e077bSSimon Glass 146ff3e077bSSimon Glass int pci_bus_find_devices(struct udevice *bus, struct pci_device_id *ids, 147ff3e077bSSimon Glass int *indexp, struct udevice **devp) 148ff3e077bSSimon Glass { 149ff3e077bSSimon Glass struct udevice *dev; 150ff3e077bSSimon Glass 151ff3e077bSSimon Glass /* Scan all devices on this bus */ 152ff3e077bSSimon Glass for (device_find_first_child(bus, &dev); 153ff3e077bSSimon Glass dev; 154ff3e077bSSimon Glass device_find_next_child(&dev)) { 155ff3e077bSSimon Glass if (pci_device_matches_ids(dev, ids) >= 0) { 156ff3e077bSSimon Glass if ((*indexp)-- <= 0) { 157ff3e077bSSimon Glass *devp = dev; 158ff3e077bSSimon Glass return 0; 159ff3e077bSSimon Glass } 160ff3e077bSSimon Glass } 161ff3e077bSSimon Glass } 162ff3e077bSSimon Glass 163ff3e077bSSimon Glass return -ENODEV; 164ff3e077bSSimon Glass } 165ff3e077bSSimon Glass 166ff3e077bSSimon Glass int pci_find_device_id(struct pci_device_id *ids, int index, 167ff3e077bSSimon Glass struct udevice **devp) 168ff3e077bSSimon Glass { 169ff3e077bSSimon Glass struct udevice *bus; 170ff3e077bSSimon Glass 171ff3e077bSSimon Glass /* Scan all known buses */ 172ff3e077bSSimon Glass for (uclass_first_device(UCLASS_PCI, &bus); 173ff3e077bSSimon Glass bus; 174ff3e077bSSimon Glass uclass_next_device(&bus)) { 175ff3e077bSSimon Glass if (!pci_bus_find_devices(bus, ids, &index, devp)) 176ff3e077bSSimon Glass return 0; 177ff3e077bSSimon Glass } 178ff3e077bSSimon Glass *devp = NULL; 179ff3e077bSSimon Glass 180ff3e077bSSimon Glass return -ENODEV; 181ff3e077bSSimon Glass } 182ff3e077bSSimon Glass 1835c0bf647SSimon Glass static int dm_pci_bus_find_device(struct udevice *bus, unsigned int vendor, 1845c0bf647SSimon Glass unsigned int device, int *indexp, 1855c0bf647SSimon Glass struct udevice **devp) 1865c0bf647SSimon Glass { 1875c0bf647SSimon Glass struct pci_child_platdata *pplat; 1885c0bf647SSimon Glass struct udevice *dev; 1895c0bf647SSimon Glass 1905c0bf647SSimon Glass for (device_find_first_child(bus, &dev); 1915c0bf647SSimon Glass dev; 1925c0bf647SSimon Glass device_find_next_child(&dev)) { 1935c0bf647SSimon Glass pplat = dev_get_parent_platdata(dev); 1945c0bf647SSimon Glass if (pplat->vendor == vendor && pplat->device == device) { 1955c0bf647SSimon Glass if (!(*indexp)--) { 1965c0bf647SSimon Glass *devp = dev; 1975c0bf647SSimon Glass return 0; 1985c0bf647SSimon Glass } 1995c0bf647SSimon Glass } 2005c0bf647SSimon Glass } 2015c0bf647SSimon Glass 2025c0bf647SSimon Glass return -ENODEV; 2035c0bf647SSimon Glass } 2045c0bf647SSimon Glass 2055c0bf647SSimon Glass int dm_pci_find_device(unsigned int vendor, unsigned int device, int index, 2065c0bf647SSimon Glass struct udevice **devp) 2075c0bf647SSimon Glass { 2085c0bf647SSimon Glass struct udevice *bus; 2095c0bf647SSimon Glass 2105c0bf647SSimon Glass /* Scan all known buses */ 2115c0bf647SSimon Glass for (uclass_first_device(UCLASS_PCI, &bus); 2125c0bf647SSimon Glass bus; 2135c0bf647SSimon Glass uclass_next_device(&bus)) { 2145c0bf647SSimon Glass if (!dm_pci_bus_find_device(bus, vendor, device, &index, devp)) 2155c0bf647SSimon Glass return device_probe(*devp); 2165c0bf647SSimon Glass } 2175c0bf647SSimon Glass *devp = NULL; 2185c0bf647SSimon Glass 2195c0bf647SSimon Glass return -ENODEV; 2205c0bf647SSimon Glass } 2215c0bf647SSimon Glass 222a0eb8356SSimon Glass int dm_pci_find_class(uint find_class, int index, struct udevice **devp) 223a0eb8356SSimon Glass { 224a0eb8356SSimon Glass struct udevice *dev; 225a0eb8356SSimon Glass 226a0eb8356SSimon Glass /* Scan all known buses */ 227a0eb8356SSimon Glass for (pci_find_first_device(&dev); 228a0eb8356SSimon Glass dev; 229a0eb8356SSimon Glass pci_find_next_device(&dev)) { 230a0eb8356SSimon Glass struct pci_child_platdata *pplat = dev_get_parent_platdata(dev); 231a0eb8356SSimon Glass 232a0eb8356SSimon Glass if (pplat->class == find_class && !index--) { 233a0eb8356SSimon Glass *devp = dev; 234a0eb8356SSimon Glass return device_probe(*devp); 235a0eb8356SSimon Glass } 236a0eb8356SSimon Glass } 237a0eb8356SSimon Glass *devp = NULL; 238a0eb8356SSimon Glass 239a0eb8356SSimon Glass return -ENODEV; 240a0eb8356SSimon Glass } 241a0eb8356SSimon Glass 242ff3e077bSSimon Glass int pci_bus_write_config(struct udevice *bus, pci_dev_t bdf, int offset, 243ff3e077bSSimon Glass unsigned long value, enum pci_size_t size) 244ff3e077bSSimon Glass { 245ff3e077bSSimon Glass struct dm_pci_ops *ops; 246ff3e077bSSimon Glass 247ff3e077bSSimon Glass ops = pci_get_ops(bus); 248ff3e077bSSimon Glass if (!ops->write_config) 249ff3e077bSSimon Glass return -ENOSYS; 250ff3e077bSSimon Glass return ops->write_config(bus, bdf, offset, value, size); 251ff3e077bSSimon Glass } 252ff3e077bSSimon Glass 253ff3e077bSSimon Glass int pci_write_config(pci_dev_t bdf, int offset, unsigned long value, 254ff3e077bSSimon Glass enum pci_size_t size) 255ff3e077bSSimon Glass { 256ff3e077bSSimon Glass struct udevice *bus; 257ff3e077bSSimon Glass int ret; 258ff3e077bSSimon Glass 259983c6ba2SSimon Glass ret = pci_get_bus(PCI_BUS(bdf), &bus); 260ff3e077bSSimon Glass if (ret) 261ff3e077bSSimon Glass return ret; 262ff3e077bSSimon Glass 2634d8615cbSBin Meng return pci_bus_write_config(bus, bdf, offset, value, size); 264ff3e077bSSimon Glass } 265ff3e077bSSimon Glass 26666afb4edSSimon Glass int dm_pci_write_config(struct udevice *dev, int offset, unsigned long value, 26766afb4edSSimon Glass enum pci_size_t size) 26866afb4edSSimon Glass { 26966afb4edSSimon Glass struct udevice *bus; 27066afb4edSSimon Glass 2711e0f2263SBin Meng for (bus = dev; device_is_on_pci_bus(bus);) 27266afb4edSSimon Glass bus = bus->parent; 27321ccce1bSSimon Glass return pci_bus_write_config(bus, dm_pci_get_bdf(dev), offset, value, 27421ccce1bSSimon Glass size); 27566afb4edSSimon Glass } 27666afb4edSSimon Glass 27766afb4edSSimon Glass 278ff3e077bSSimon Glass int pci_write_config32(pci_dev_t bdf, int offset, u32 value) 279ff3e077bSSimon Glass { 280ff3e077bSSimon Glass return pci_write_config(bdf, offset, value, PCI_SIZE_32); 281ff3e077bSSimon Glass } 282ff3e077bSSimon Glass 283ff3e077bSSimon Glass int pci_write_config16(pci_dev_t bdf, int offset, u16 value) 284ff3e077bSSimon Glass { 285ff3e077bSSimon Glass return pci_write_config(bdf, offset, value, PCI_SIZE_16); 286ff3e077bSSimon Glass } 287ff3e077bSSimon Glass 288ff3e077bSSimon Glass int pci_write_config8(pci_dev_t bdf, int offset, u8 value) 289ff3e077bSSimon Glass { 290ff3e077bSSimon Glass return pci_write_config(bdf, offset, value, PCI_SIZE_8); 291ff3e077bSSimon Glass } 292ff3e077bSSimon Glass 29366afb4edSSimon Glass int dm_pci_write_config8(struct udevice *dev, int offset, u8 value) 29466afb4edSSimon Glass { 29566afb4edSSimon Glass return dm_pci_write_config(dev, offset, value, PCI_SIZE_8); 29666afb4edSSimon Glass } 29766afb4edSSimon Glass 29866afb4edSSimon Glass int dm_pci_write_config16(struct udevice *dev, int offset, u16 value) 29966afb4edSSimon Glass { 30066afb4edSSimon Glass return dm_pci_write_config(dev, offset, value, PCI_SIZE_16); 30166afb4edSSimon Glass } 30266afb4edSSimon Glass 30366afb4edSSimon Glass int dm_pci_write_config32(struct udevice *dev, int offset, u32 value) 30466afb4edSSimon Glass { 30566afb4edSSimon Glass return dm_pci_write_config(dev, offset, value, PCI_SIZE_32); 30666afb4edSSimon Glass } 30766afb4edSSimon Glass 308ff3e077bSSimon Glass int pci_bus_read_config(struct udevice *bus, pci_dev_t bdf, int offset, 309ff3e077bSSimon Glass unsigned long *valuep, enum pci_size_t size) 310ff3e077bSSimon Glass { 311ff3e077bSSimon Glass struct dm_pci_ops *ops; 312ff3e077bSSimon Glass 313ff3e077bSSimon Glass ops = pci_get_ops(bus); 314ff3e077bSSimon Glass if (!ops->read_config) 315ff3e077bSSimon Glass return -ENOSYS; 316ff3e077bSSimon Glass return ops->read_config(bus, bdf, offset, valuep, size); 317ff3e077bSSimon Glass } 318ff3e077bSSimon Glass 319ff3e077bSSimon Glass int pci_read_config(pci_dev_t bdf, int offset, unsigned long *valuep, 320ff3e077bSSimon Glass enum pci_size_t size) 321ff3e077bSSimon Glass { 322ff3e077bSSimon Glass struct udevice *bus; 323ff3e077bSSimon Glass int ret; 324ff3e077bSSimon Glass 325983c6ba2SSimon Glass ret = pci_get_bus(PCI_BUS(bdf), &bus); 326ff3e077bSSimon Glass if (ret) 327ff3e077bSSimon Glass return ret; 328ff3e077bSSimon Glass 3294d8615cbSBin Meng return pci_bus_read_config(bus, bdf, offset, valuep, size); 330ff3e077bSSimon Glass } 331ff3e077bSSimon Glass 33266afb4edSSimon Glass int dm_pci_read_config(struct udevice *dev, int offset, unsigned long *valuep, 33366afb4edSSimon Glass enum pci_size_t size) 33466afb4edSSimon Glass { 33566afb4edSSimon Glass struct udevice *bus; 33666afb4edSSimon Glass 3371e0f2263SBin Meng for (bus = dev; device_is_on_pci_bus(bus);) 33866afb4edSSimon Glass bus = bus->parent; 33921ccce1bSSimon Glass return pci_bus_read_config(bus, dm_pci_get_bdf(dev), offset, valuep, 34066afb4edSSimon Glass size); 34166afb4edSSimon Glass } 34266afb4edSSimon Glass 343ff3e077bSSimon Glass int pci_read_config32(pci_dev_t bdf, int offset, u32 *valuep) 344ff3e077bSSimon Glass { 345ff3e077bSSimon Glass unsigned long value; 346ff3e077bSSimon Glass int ret; 347ff3e077bSSimon Glass 348ff3e077bSSimon Glass ret = pci_read_config(bdf, offset, &value, PCI_SIZE_32); 349ff3e077bSSimon Glass if (ret) 350ff3e077bSSimon Glass return ret; 351ff3e077bSSimon Glass *valuep = value; 352ff3e077bSSimon Glass 353ff3e077bSSimon Glass return 0; 354ff3e077bSSimon Glass } 355ff3e077bSSimon Glass 356ff3e077bSSimon Glass int pci_read_config16(pci_dev_t bdf, int offset, u16 *valuep) 357ff3e077bSSimon Glass { 358ff3e077bSSimon Glass unsigned long value; 359ff3e077bSSimon Glass int ret; 360ff3e077bSSimon Glass 361ff3e077bSSimon Glass ret = pci_read_config(bdf, offset, &value, PCI_SIZE_16); 362ff3e077bSSimon Glass if (ret) 363ff3e077bSSimon Glass return ret; 364ff3e077bSSimon Glass *valuep = value; 365ff3e077bSSimon Glass 366ff3e077bSSimon Glass return 0; 367ff3e077bSSimon Glass } 368ff3e077bSSimon Glass 369ff3e077bSSimon Glass int pci_read_config8(pci_dev_t bdf, int offset, u8 *valuep) 370ff3e077bSSimon Glass { 371ff3e077bSSimon Glass unsigned long value; 372ff3e077bSSimon Glass int ret; 373ff3e077bSSimon Glass 374ff3e077bSSimon Glass ret = pci_read_config(bdf, offset, &value, PCI_SIZE_8); 375ff3e077bSSimon Glass if (ret) 376ff3e077bSSimon Glass return ret; 377ff3e077bSSimon Glass *valuep = value; 378ff3e077bSSimon Glass 379ff3e077bSSimon Glass return 0; 380ff3e077bSSimon Glass } 381ff3e077bSSimon Glass 38266afb4edSSimon Glass int dm_pci_read_config8(struct udevice *dev, int offset, u8 *valuep) 38366afb4edSSimon Glass { 38466afb4edSSimon Glass unsigned long value; 38566afb4edSSimon Glass int ret; 38666afb4edSSimon Glass 38766afb4edSSimon Glass ret = dm_pci_read_config(dev, offset, &value, PCI_SIZE_8); 38866afb4edSSimon Glass if (ret) 38966afb4edSSimon Glass return ret; 39066afb4edSSimon Glass *valuep = value; 39166afb4edSSimon Glass 39266afb4edSSimon Glass return 0; 39366afb4edSSimon Glass } 39466afb4edSSimon Glass 39566afb4edSSimon Glass int dm_pci_read_config16(struct udevice *dev, int offset, u16 *valuep) 39666afb4edSSimon Glass { 39766afb4edSSimon Glass unsigned long value; 39866afb4edSSimon Glass int ret; 39966afb4edSSimon Glass 40066afb4edSSimon Glass ret = dm_pci_read_config(dev, offset, &value, PCI_SIZE_16); 40166afb4edSSimon Glass if (ret) 40266afb4edSSimon Glass return ret; 40366afb4edSSimon Glass *valuep = value; 40466afb4edSSimon Glass 40566afb4edSSimon Glass return 0; 40666afb4edSSimon Glass } 40766afb4edSSimon Glass 40866afb4edSSimon Glass int dm_pci_read_config32(struct udevice *dev, int offset, u32 *valuep) 40966afb4edSSimon Glass { 41066afb4edSSimon Glass unsigned long value; 41166afb4edSSimon Glass int ret; 41266afb4edSSimon Glass 41366afb4edSSimon Glass ret = dm_pci_read_config(dev, offset, &value, PCI_SIZE_32); 41466afb4edSSimon Glass if (ret) 41566afb4edSSimon Glass return ret; 41666afb4edSSimon Glass *valuep = value; 41766afb4edSSimon Glass 41866afb4edSSimon Glass return 0; 41966afb4edSSimon Glass } 42066afb4edSSimon Glass 421bbbcb526SBin Meng static void set_vga_bridge_bits(struct udevice *dev) 422bbbcb526SBin Meng { 423bbbcb526SBin Meng struct udevice *parent = dev->parent; 424bbbcb526SBin Meng u16 bc; 425bbbcb526SBin Meng 426bbbcb526SBin Meng while (parent->seq != 0) { 427bbbcb526SBin Meng dm_pci_read_config16(parent, PCI_BRIDGE_CONTROL, &bc); 428bbbcb526SBin Meng bc |= PCI_BRIDGE_CTL_VGA; 429bbbcb526SBin Meng dm_pci_write_config16(parent, PCI_BRIDGE_CONTROL, bc); 430bbbcb526SBin Meng parent = parent->parent; 431bbbcb526SBin Meng } 432bbbcb526SBin Meng } 433bbbcb526SBin Meng 434ff3e077bSSimon Glass int pci_auto_config_devices(struct udevice *bus) 435ff3e077bSSimon Glass { 436ff3e077bSSimon Glass struct pci_controller *hose = bus->uclass_priv; 437bbbcb526SBin Meng struct pci_child_platdata *pplat; 438ff3e077bSSimon Glass unsigned int sub_bus; 439ff3e077bSSimon Glass struct udevice *dev; 440ff3e077bSSimon Glass int ret; 441ff3e077bSSimon Glass 442ff3e077bSSimon Glass sub_bus = bus->seq; 443ff3e077bSSimon Glass debug("%s: start\n", __func__); 444ff3e077bSSimon Glass pciauto_config_init(hose); 445ff3e077bSSimon Glass for (ret = device_find_first_child(bus, &dev); 446ff3e077bSSimon Glass !ret && dev; 447ff3e077bSSimon Glass ret = device_find_next_child(&dev)) { 448ff3e077bSSimon Glass unsigned int max_bus; 4494d21455eSSimon Glass int ret; 450ff3e077bSSimon Glass 451ff3e077bSSimon Glass debug("%s: device %s\n", __func__, dev->name); 4525e23b8b4SSimon Glass ret = dm_pciauto_config_device(dev); 4534d21455eSSimon Glass if (ret < 0) 4544d21455eSSimon Glass return ret; 4554d21455eSSimon Glass max_bus = ret; 456ff3e077bSSimon Glass sub_bus = max(sub_bus, max_bus); 457bbbcb526SBin Meng 458bbbcb526SBin Meng pplat = dev_get_parent_platdata(dev); 459bbbcb526SBin Meng if (pplat->class == (PCI_CLASS_DISPLAY_VGA << 8)) 460bbbcb526SBin Meng set_vga_bridge_bits(dev); 461ff3e077bSSimon Glass } 462ff3e077bSSimon Glass debug("%s: done\n", __func__); 463ff3e077bSSimon Glass 464ff3e077bSSimon Glass return sub_bus; 465ff3e077bSSimon Glass } 466ff3e077bSSimon Glass 4675e23b8b4SSimon Glass int dm_pci_hose_probe_bus(struct udevice *bus) 468ff3e077bSSimon Glass { 469ff3e077bSSimon Glass int sub_bus; 470ff3e077bSSimon Glass int ret; 471ff3e077bSSimon Glass 472ff3e077bSSimon Glass debug("%s\n", __func__); 473ff3e077bSSimon Glass 474ff3e077bSSimon Glass sub_bus = pci_get_bus_max() + 1; 475ff3e077bSSimon Glass debug("%s: bus = %d/%s\n", __func__, sub_bus, bus->name); 4765e23b8b4SSimon Glass dm_pciauto_prescan_setup_bridge(bus, sub_bus); 477ff3e077bSSimon Glass 478ff3e077bSSimon Glass ret = device_probe(bus); 479ff3e077bSSimon Glass if (ret) { 4803129ace4SSimon Glass debug("%s: Cannot probe bus %s: %d\n", __func__, bus->name, 481ff3e077bSSimon Glass ret); 482ff3e077bSSimon Glass return ret; 483ff3e077bSSimon Glass } 484ff3e077bSSimon Glass if (sub_bus != bus->seq) { 485ff3e077bSSimon Glass printf("%s: Internal error, bus '%s' got seq %d, expected %d\n", 486ff3e077bSSimon Glass __func__, bus->name, bus->seq, sub_bus); 487ff3e077bSSimon Glass return -EPIPE; 488ff3e077bSSimon Glass } 489ff3e077bSSimon Glass sub_bus = pci_get_bus_max(); 4905e23b8b4SSimon Glass dm_pciauto_postscan_setup_bridge(bus, sub_bus); 491ff3e077bSSimon Glass 492ff3e077bSSimon Glass return sub_bus; 493ff3e077bSSimon Glass } 494ff3e077bSSimon Glass 495aba92962SSimon Glass /** 496aba92962SSimon Glass * pci_match_one_device - Tell if a PCI device structure has a matching 497aba92962SSimon Glass * PCI device id structure 498aba92962SSimon Glass * @id: single PCI device id structure to match 499aba92962SSimon Glass * @dev: the PCI device structure to match against 500aba92962SSimon Glass * 501aba92962SSimon Glass * Returns the matching pci_device_id structure or %NULL if there is no match. 502aba92962SSimon Glass */ 503aba92962SSimon Glass static bool pci_match_one_id(const struct pci_device_id *id, 504aba92962SSimon Glass const struct pci_device_id *find) 505aba92962SSimon Glass { 506aba92962SSimon Glass if ((id->vendor == PCI_ANY_ID || id->vendor == find->vendor) && 507aba92962SSimon Glass (id->device == PCI_ANY_ID || id->device == find->device) && 508aba92962SSimon Glass (id->subvendor == PCI_ANY_ID || id->subvendor == find->subvendor) && 509aba92962SSimon Glass (id->subdevice == PCI_ANY_ID || id->subdevice == find->subdevice) && 510aba92962SSimon Glass !((id->class ^ find->class) & id->class_mask)) 511aba92962SSimon Glass return true; 512aba92962SSimon Glass 513aba92962SSimon Glass return false; 514aba92962SSimon Glass } 515aba92962SSimon Glass 516aba92962SSimon Glass /** 517aba92962SSimon Glass * pci_find_and_bind_driver() - Find and bind the right PCI driver 518aba92962SSimon Glass * 519aba92962SSimon Glass * This only looks at certain fields in the descriptor. 5205dbcf3a0SSimon Glass * 5215dbcf3a0SSimon Glass * @parent: Parent bus 5225dbcf3a0SSimon Glass * @find_id: Specification of the driver to find 5235dbcf3a0SSimon Glass * @bdf: Bus/device/function addreess - see PCI_BDF() 5245dbcf3a0SSimon Glass * @devp: Returns a pointer to the device created 5255dbcf3a0SSimon Glass * @return 0 if OK, -EPERM if the device is not needed before relocation and 5265dbcf3a0SSimon Glass * therefore was not created, other -ve value on error 527aba92962SSimon Glass */ 528aba92962SSimon Glass static int pci_find_and_bind_driver(struct udevice *parent, 5295dbcf3a0SSimon Glass struct pci_device_id *find_id, 5305dbcf3a0SSimon Glass pci_dev_t bdf, struct udevice **devp) 531aba92962SSimon Glass { 532aba92962SSimon Glass struct pci_driver_entry *start, *entry; 533aba92962SSimon Glass const char *drv; 534aba92962SSimon Glass int n_ents; 535aba92962SSimon Glass int ret; 536aba92962SSimon Glass char name[30], *str; 53708fc7b8fSBin Meng bool bridge; 538aba92962SSimon Glass 539aba92962SSimon Glass *devp = NULL; 540aba92962SSimon Glass 541aba92962SSimon Glass debug("%s: Searching for driver: vendor=%x, device=%x\n", __func__, 542aba92962SSimon Glass find_id->vendor, find_id->device); 543aba92962SSimon Glass start = ll_entry_start(struct pci_driver_entry, pci_driver_entry); 544aba92962SSimon Glass n_ents = ll_entry_count(struct pci_driver_entry, pci_driver_entry); 545aba92962SSimon Glass for (entry = start; entry != start + n_ents; entry++) { 546aba92962SSimon Glass const struct pci_device_id *id; 547aba92962SSimon Glass struct udevice *dev; 548aba92962SSimon Glass const struct driver *drv; 549aba92962SSimon Glass 550aba92962SSimon Glass for (id = entry->match; 551aba92962SSimon Glass id->vendor || id->subvendor || id->class_mask; 552aba92962SSimon Glass id++) { 553aba92962SSimon Glass if (!pci_match_one_id(id, find_id)) 554aba92962SSimon Glass continue; 555aba92962SSimon Glass 556aba92962SSimon Glass drv = entry->driver; 55708fc7b8fSBin Meng 55808fc7b8fSBin Meng /* 55908fc7b8fSBin Meng * In the pre-relocation phase, we only bind devices 56008fc7b8fSBin Meng * whose driver has the DM_FLAG_PRE_RELOC set, to save 56108fc7b8fSBin Meng * precious memory space as on some platforms as that 56208fc7b8fSBin Meng * space is pretty limited (ie: using Cache As RAM). 56308fc7b8fSBin Meng */ 56408fc7b8fSBin Meng if (!(gd->flags & GD_FLG_RELOC) && 56508fc7b8fSBin Meng !(drv->flags & DM_FLAG_PRE_RELOC)) 5665dbcf3a0SSimon Glass return -EPERM; 56708fc7b8fSBin Meng 568aba92962SSimon Glass /* 569aba92962SSimon Glass * We could pass the descriptor to the driver as 570aba92962SSimon Glass * platdata (instead of NULL) and allow its bind() 571aba92962SSimon Glass * method to return -ENOENT if it doesn't support this 572aba92962SSimon Glass * device. That way we could continue the search to 573aba92962SSimon Glass * find another driver. For now this doesn't seem 574aba92962SSimon Glass * necesssary, so just bind the first match. 575aba92962SSimon Glass */ 576aba92962SSimon Glass ret = device_bind(parent, drv, drv->name, NULL, -1, 577aba92962SSimon Glass &dev); 578aba92962SSimon Glass if (ret) 579aba92962SSimon Glass goto error; 580aba92962SSimon Glass debug("%s: Match found: %s\n", __func__, drv->name); 581aba92962SSimon Glass dev->driver_data = find_id->driver_data; 582aba92962SSimon Glass *devp = dev; 583aba92962SSimon Glass return 0; 584aba92962SSimon Glass } 585aba92962SSimon Glass } 586aba92962SSimon Glass 58708fc7b8fSBin Meng bridge = (find_id->class >> 8) == PCI_CLASS_BRIDGE_PCI; 58808fc7b8fSBin Meng /* 58908fc7b8fSBin Meng * In the pre-relocation phase, we only bind bridge devices to save 59008fc7b8fSBin Meng * precious memory space as on some platforms as that space is pretty 59108fc7b8fSBin Meng * limited (ie: using Cache As RAM). 59208fc7b8fSBin Meng */ 59308fc7b8fSBin Meng if (!(gd->flags & GD_FLG_RELOC) && !bridge) 5945dbcf3a0SSimon Glass return -EPERM; 59508fc7b8fSBin Meng 596aba92962SSimon Glass /* Bind a generic driver so that the device can be used */ 5974d8615cbSBin Meng sprintf(name, "pci_%x:%x.%x", parent->seq, PCI_DEV(bdf), 5984d8615cbSBin Meng PCI_FUNC(bdf)); 599aba92962SSimon Glass str = strdup(name); 600aba92962SSimon Glass if (!str) 601aba92962SSimon Glass return -ENOMEM; 60208fc7b8fSBin Meng drv = bridge ? "pci_bridge_drv" : "pci_generic_drv"; 60308fc7b8fSBin Meng 604aba92962SSimon Glass ret = device_bind_driver(parent, drv, str, devp); 605aba92962SSimon Glass if (ret) { 6063129ace4SSimon Glass debug("%s: Failed to bind generic driver: %d\n", __func__, ret); 607aba92962SSimon Glass return ret; 608aba92962SSimon Glass } 609aba92962SSimon Glass debug("%s: No match found: bound generic driver instead\n", __func__); 610aba92962SSimon Glass 611aba92962SSimon Glass return 0; 612aba92962SSimon Glass 613aba92962SSimon Glass error: 614aba92962SSimon Glass debug("%s: No match found: error %d\n", __func__, ret); 615aba92962SSimon Glass return ret; 616aba92962SSimon Glass } 617aba92962SSimon Glass 618ff3e077bSSimon Glass int pci_bind_bus_devices(struct udevice *bus) 619ff3e077bSSimon Glass { 620ff3e077bSSimon Glass ulong vendor, device; 621ff3e077bSSimon Glass ulong header_type; 6224d8615cbSBin Meng pci_dev_t bdf, end; 623ff3e077bSSimon Glass bool found_multi; 624ff3e077bSSimon Glass int ret; 625ff3e077bSSimon Glass 626ff3e077bSSimon Glass found_multi = false; 6274d8615cbSBin Meng end = PCI_BDF(bus->seq, PCI_MAX_PCI_DEVICES - 1, 6284d8615cbSBin Meng PCI_MAX_PCI_FUNCTIONS - 1); 6294d8615cbSBin Meng for (bdf = PCI_BDF(bus->seq, 0, 0); bdf < end; 6304d8615cbSBin Meng bdf += PCI_BDF(0, 0, 1)) { 631ff3e077bSSimon Glass struct pci_child_platdata *pplat; 632ff3e077bSSimon Glass struct udevice *dev; 633ff3e077bSSimon Glass ulong class; 634ff3e077bSSimon Glass 6354d8615cbSBin Meng if (PCI_FUNC(bdf) && !found_multi) 636ff3e077bSSimon Glass continue; 637ff3e077bSSimon Glass /* Check only the first access, we don't expect problems */ 6384d8615cbSBin Meng ret = pci_bus_read_config(bus, bdf, PCI_HEADER_TYPE, 639ff3e077bSSimon Glass &header_type, PCI_SIZE_8); 640ff3e077bSSimon Glass if (ret) 641ff3e077bSSimon Glass goto error; 6424d8615cbSBin Meng pci_bus_read_config(bus, bdf, PCI_VENDOR_ID, &vendor, 643ff3e077bSSimon Glass PCI_SIZE_16); 644ff3e077bSSimon Glass if (vendor == 0xffff || vendor == 0x0000) 645ff3e077bSSimon Glass continue; 646ff3e077bSSimon Glass 6474d8615cbSBin Meng if (!PCI_FUNC(bdf)) 648ff3e077bSSimon Glass found_multi = header_type & 0x80; 649ff3e077bSSimon Glass 650ff3e077bSSimon Glass debug("%s: bus %d/%s: found device %x, function %d\n", __func__, 6514d8615cbSBin Meng bus->seq, bus->name, PCI_DEV(bdf), PCI_FUNC(bdf)); 6524d8615cbSBin Meng pci_bus_read_config(bus, bdf, PCI_DEVICE_ID, &device, 653ff3e077bSSimon Glass PCI_SIZE_16); 6544d8615cbSBin Meng pci_bus_read_config(bus, bdf, PCI_CLASS_REVISION, &class, 655aba92962SSimon Glass PCI_SIZE_32); 656aba92962SSimon Glass class >>= 8; 657ff3e077bSSimon Glass 658ff3e077bSSimon Glass /* Find this device in the device tree */ 6594d8615cbSBin Meng ret = pci_bus_find_devfn(bus, PCI_MASK_BUS(bdf), &dev); 660ff3e077bSSimon Glass 6618bd42525SSimon Glass /* If nothing in the device tree, bind a device */ 662ff3e077bSSimon Glass if (ret == -ENODEV) { 663aba92962SSimon Glass struct pci_device_id find_id; 664aba92962SSimon Glass ulong val; 665ff3e077bSSimon Glass 666aba92962SSimon Glass memset(&find_id, '\0', sizeof(find_id)); 667aba92962SSimon Glass find_id.vendor = vendor; 668aba92962SSimon Glass find_id.device = device; 669aba92962SSimon Glass find_id.class = class; 670aba92962SSimon Glass if ((header_type & 0x7f) == PCI_HEADER_TYPE_NORMAL) { 6714d8615cbSBin Meng pci_bus_read_config(bus, bdf, 672aba92962SSimon Glass PCI_SUBSYSTEM_VENDOR_ID, 673aba92962SSimon Glass &val, PCI_SIZE_32); 674aba92962SSimon Glass find_id.subvendor = val & 0xffff; 675aba92962SSimon Glass find_id.subdevice = val >> 16; 676aba92962SSimon Glass } 6774d8615cbSBin Meng ret = pci_find_and_bind_driver(bus, &find_id, bdf, 678aba92962SSimon Glass &dev); 679ff3e077bSSimon Glass } 6805dbcf3a0SSimon Glass if (ret == -EPERM) 6815dbcf3a0SSimon Glass continue; 6825dbcf3a0SSimon Glass else if (ret) 683ff3e077bSSimon Glass return ret; 684ff3e077bSSimon Glass 685ff3e077bSSimon Glass /* Update the platform data */ 686ff3e077bSSimon Glass pplat = dev_get_parent_platdata(dev); 6874d8615cbSBin Meng pplat->devfn = PCI_MASK_BUS(bdf); 688ff3e077bSSimon Glass pplat->vendor = vendor; 689ff3e077bSSimon Glass pplat->device = device; 690ff3e077bSSimon Glass pplat->class = class; 691ff3e077bSSimon Glass } 692ff3e077bSSimon Glass 693ff3e077bSSimon Glass return 0; 694ff3e077bSSimon Glass error: 695ff3e077bSSimon Glass printf("Cannot read bus configuration: %d\n", ret); 696ff3e077bSSimon Glass 697ff3e077bSSimon Glass return ret; 698ff3e077bSSimon Glass } 699ff3e077bSSimon Glass 700ff3e077bSSimon Glass static int pci_uclass_post_bind(struct udevice *bus) 701ff3e077bSSimon Glass { 702ff3e077bSSimon Glass /* 7031887ed3aSBin Meng * If there is no pci device listed in the device tree, 7041887ed3aSBin Meng * don't bother scanning the device tree. 7051887ed3aSBin Meng */ 7061887ed3aSBin Meng if (bus->of_offset == -1) 7071887ed3aSBin Meng return 0; 7081887ed3aSBin Meng 7091887ed3aSBin Meng /* 710ff3e077bSSimon Glass * Scan the device tree for devices. This does not probe the PCI bus, 711ff3e077bSSimon Glass * as this is not permitted while binding. It just finds devices 712ff3e077bSSimon Glass * mentioned in the device tree. 713ff3e077bSSimon Glass * 714ff3e077bSSimon Glass * Before relocation, only bind devices marked for pre-relocation 715ff3e077bSSimon Glass * use. 716ff3e077bSSimon Glass */ 717ff3e077bSSimon Glass return dm_scan_fdt_node(bus, gd->fdt_blob, bus->of_offset, 718ff3e077bSSimon Glass gd->flags & GD_FLG_RELOC ? false : true); 719ff3e077bSSimon Glass } 720ff3e077bSSimon Glass 721ff3e077bSSimon Glass static int decode_regions(struct pci_controller *hose, const void *blob, 722ff3e077bSSimon Glass int parent_node, int node) 723ff3e077bSSimon Glass { 724ff3e077bSSimon Glass int pci_addr_cells, addr_cells, size_cells; 7252084c5afSSimon Glass phys_addr_t base = 0, size; 726ff3e077bSSimon Glass int cells_per_record; 727ff3e077bSSimon Glass const u32 *prop; 728ff3e077bSSimon Glass int len; 729ff3e077bSSimon Glass int i; 730ff3e077bSSimon Glass 731ff3e077bSSimon Glass prop = fdt_getprop(blob, node, "ranges", &len); 732ff3e077bSSimon Glass if (!prop) 733ff3e077bSSimon Glass return -EINVAL; 734ff3e077bSSimon Glass pci_addr_cells = fdt_address_cells(blob, node); 735ff3e077bSSimon Glass addr_cells = fdt_address_cells(blob, parent_node); 736ff3e077bSSimon Glass size_cells = fdt_size_cells(blob, node); 737ff3e077bSSimon Glass 738ff3e077bSSimon Glass /* PCI addresses are always 3-cells */ 739ff3e077bSSimon Glass len /= sizeof(u32); 740ff3e077bSSimon Glass cells_per_record = pci_addr_cells + addr_cells + size_cells; 741ff3e077bSSimon Glass hose->region_count = 0; 742ff3e077bSSimon Glass debug("%s: len=%d, cells_per_record=%d\n", __func__, len, 743ff3e077bSSimon Glass cells_per_record); 744ff3e077bSSimon Glass for (i = 0; i < MAX_PCI_REGIONS; i++, len -= cells_per_record) { 745ff3e077bSSimon Glass u64 pci_addr, addr, size; 746ff3e077bSSimon Glass int space_code; 747ff3e077bSSimon Glass u32 flags; 748ff3e077bSSimon Glass int type; 7499526d83aSSimon Glass int pos; 750ff3e077bSSimon Glass 751ff3e077bSSimon Glass if (len < cells_per_record) 752ff3e077bSSimon Glass break; 753ff3e077bSSimon Glass flags = fdt32_to_cpu(prop[0]); 754ff3e077bSSimon Glass space_code = (flags >> 24) & 3; 755ff3e077bSSimon Glass pci_addr = fdtdec_get_number(prop + 1, 2); 756ff3e077bSSimon Glass prop += pci_addr_cells; 757ff3e077bSSimon Glass addr = fdtdec_get_number(prop, addr_cells); 758ff3e077bSSimon Glass prop += addr_cells; 759ff3e077bSSimon Glass size = fdtdec_get_number(prop, size_cells); 760ff3e077bSSimon Glass prop += size_cells; 761ff3e077bSSimon Glass debug("%s: region %d, pci_addr=%" PRIx64 ", addr=%" PRIx64 762ff3e077bSSimon Glass ", size=%" PRIx64 ", space_code=%d\n", __func__, 763ff3e077bSSimon Glass hose->region_count, pci_addr, addr, size, space_code); 764ff3e077bSSimon Glass if (space_code & 2) { 765ff3e077bSSimon Glass type = flags & (1U << 30) ? PCI_REGION_PREFETCH : 766ff3e077bSSimon Glass PCI_REGION_MEM; 767ff3e077bSSimon Glass } else if (space_code & 1) { 768ff3e077bSSimon Glass type = PCI_REGION_IO; 769ff3e077bSSimon Glass } else { 770ff3e077bSSimon Glass continue; 771ff3e077bSSimon Glass } 7729526d83aSSimon Glass pos = -1; 7739526d83aSSimon Glass for (i = 0; i < hose->region_count; i++) { 7749526d83aSSimon Glass if (hose->regions[i].flags == type) 7759526d83aSSimon Glass pos = i; 7769526d83aSSimon Glass } 7779526d83aSSimon Glass if (pos == -1) 7789526d83aSSimon Glass pos = hose->region_count++; 7799526d83aSSimon Glass debug(" - type=%d, pos=%d\n", type, pos); 7809526d83aSSimon Glass pci_set_region(hose->regions + pos, pci_addr, addr, size, type); 781ff3e077bSSimon Glass } 782ff3e077bSSimon Glass 783ff3e077bSSimon Glass /* Add a region for our local memory */ 7842084c5afSSimon Glass size = gd->ram_size; 7852084c5afSSimon Glass #ifdef CONFIG_SYS_SDRAM_BASE 7862084c5afSSimon Glass base = CONFIG_SYS_SDRAM_BASE; 7872084c5afSSimon Glass #endif 7882084c5afSSimon Glass if (gd->pci_ram_top && gd->pci_ram_top < base + size) 7892084c5afSSimon Glass size = gd->pci_ram_top - base; 7902084c5afSSimon Glass pci_set_region(hose->regions + hose->region_count++, base, base, 7912084c5afSSimon Glass size, PCI_REGION_MEM | PCI_REGION_SYS_MEMORY); 792ff3e077bSSimon Glass 793ff3e077bSSimon Glass return 0; 794ff3e077bSSimon Glass } 795ff3e077bSSimon Glass 796ff3e077bSSimon Glass static int pci_uclass_pre_probe(struct udevice *bus) 797ff3e077bSSimon Glass { 798ff3e077bSSimon Glass struct pci_controller *hose; 799ff3e077bSSimon Glass int ret; 800ff3e077bSSimon Glass 801ff3e077bSSimon Glass debug("%s, bus=%d/%s, parent=%s\n", __func__, bus->seq, bus->name, 802ff3e077bSSimon Glass bus->parent->name); 803ff3e077bSSimon Glass hose = bus->uclass_priv; 804ff3e077bSSimon Glass 805ff3e077bSSimon Glass /* For bridges, use the top-level PCI controller */ 806ff3e077bSSimon Glass if (device_get_uclass_id(bus->parent) == UCLASS_ROOT) { 807ff3e077bSSimon Glass hose->ctlr = bus; 808ff3e077bSSimon Glass ret = decode_regions(hose, gd->fdt_blob, bus->parent->of_offset, 809ff3e077bSSimon Glass bus->of_offset); 810ff3e077bSSimon Glass if (ret) { 811ff3e077bSSimon Glass debug("%s: Cannot decode regions\n", __func__); 812ff3e077bSSimon Glass return ret; 813ff3e077bSSimon Glass } 814ff3e077bSSimon Glass } else { 815ff3e077bSSimon Glass struct pci_controller *parent_hose; 816ff3e077bSSimon Glass 817ff3e077bSSimon Glass parent_hose = dev_get_uclass_priv(bus->parent); 818ff3e077bSSimon Glass hose->ctlr = parent_hose->bus; 819ff3e077bSSimon Glass } 820ff3e077bSSimon Glass hose->bus = bus; 821ff3e077bSSimon Glass hose->first_busno = bus->seq; 822ff3e077bSSimon Glass hose->last_busno = bus->seq; 823ff3e077bSSimon Glass 824ff3e077bSSimon Glass return 0; 825ff3e077bSSimon Glass } 826ff3e077bSSimon Glass 827ff3e077bSSimon Glass static int pci_uclass_post_probe(struct udevice *bus) 828ff3e077bSSimon Glass { 829ff3e077bSSimon Glass int ret; 830ff3e077bSSimon Glass 831ff3e077bSSimon Glass debug("%s: probing bus %d\n", __func__, bus->seq); 832ff3e077bSSimon Glass ret = pci_bind_bus_devices(bus); 833ff3e077bSSimon Glass if (ret) 834ff3e077bSSimon Glass return ret; 835ff3e077bSSimon Glass 836ff3e077bSSimon Glass #ifdef CONFIG_PCI_PNP 837ff3e077bSSimon Glass ret = pci_auto_config_devices(bus); 8384d21455eSSimon Glass if (ret < 0) 8394d21455eSSimon Glass return ret; 840ff3e077bSSimon Glass #endif 841ff3e077bSSimon Glass 842348b744bSBin Meng #if defined(CONFIG_X86) && defined(CONFIG_HAVE_FSP) 843348b744bSBin Meng /* 844348b744bSBin Meng * Per Intel FSP specification, we should call FSP notify API to 845348b744bSBin Meng * inform FSP that PCI enumeration has been done so that FSP will 846348b744bSBin Meng * do any necessary initialization as required by the chipset's 847348b744bSBin Meng * BIOS Writer's Guide (BWG). 848348b744bSBin Meng * 849348b744bSBin Meng * Unfortunately we have to put this call here as with driver model, 850348b744bSBin Meng * the enumeration is all done on a lazy basis as needed, so until 851348b744bSBin Meng * something is touched on PCI it won't happen. 852348b744bSBin Meng * 853348b744bSBin Meng * Note we only call this 1) after U-Boot is relocated, and 2) 854348b744bSBin Meng * root bus has finished probing. 855348b744bSBin Meng */ 8564d21455eSSimon Glass if ((gd->flags & GD_FLG_RELOC) && (bus->seq == 0)) { 857348b744bSBin Meng ret = fsp_init_phase_pci(); 8584d21455eSSimon Glass if (ret) 8594d21455eSSimon Glass return ret; 8604d21455eSSimon Glass } 861348b744bSBin Meng #endif 862348b744bSBin Meng 8634d21455eSSimon Glass return 0; 864ff3e077bSSimon Glass } 865ff3e077bSSimon Glass 866ff3e077bSSimon Glass static int pci_uclass_child_post_bind(struct udevice *dev) 867ff3e077bSSimon Glass { 868ff3e077bSSimon Glass struct pci_child_platdata *pplat; 869ff3e077bSSimon Glass struct fdt_pci_addr addr; 870ff3e077bSSimon Glass int ret; 871ff3e077bSSimon Glass 872ff3e077bSSimon Glass if (dev->of_offset == -1) 873ff3e077bSSimon Glass return 0; 874ff3e077bSSimon Glass 875ff3e077bSSimon Glass /* 876ff3e077bSSimon Glass * We could read vendor, device, class if available. But for now we 877ff3e077bSSimon Glass * just check the address. 878ff3e077bSSimon Glass */ 879ff3e077bSSimon Glass pplat = dev_get_parent_platdata(dev); 880ff3e077bSSimon Glass ret = fdtdec_get_pci_addr(gd->fdt_blob, dev->of_offset, 881ff3e077bSSimon Glass FDT_PCI_SPACE_CONFIG, "reg", &addr); 882ff3e077bSSimon Glass 883ff3e077bSSimon Glass if (ret) { 884ff3e077bSSimon Glass if (ret != -ENOENT) 885ff3e077bSSimon Glass return -EINVAL; 886ff3e077bSSimon Glass } else { 887dce54dd6SBin Meng /* extract the devfn from fdt_pci_addr */ 888dce54dd6SBin Meng pplat->devfn = addr.phys_hi & 0xff00; 889ff3e077bSSimon Glass } 890ff3e077bSSimon Glass 891ff3e077bSSimon Glass return 0; 892ff3e077bSSimon Glass } 893ff3e077bSSimon Glass 8944d8615cbSBin Meng static int pci_bridge_read_config(struct udevice *bus, pci_dev_t bdf, 8954d8615cbSBin Meng uint offset, ulong *valuep, 8964d8615cbSBin Meng enum pci_size_t size) 897ff3e077bSSimon Glass { 898ff3e077bSSimon Glass struct pci_controller *hose = bus->uclass_priv; 899ff3e077bSSimon Glass 900ff3e077bSSimon Glass return pci_bus_read_config(hose->ctlr, bdf, offset, valuep, size); 901ff3e077bSSimon Glass } 902ff3e077bSSimon Glass 9034d8615cbSBin Meng static int pci_bridge_write_config(struct udevice *bus, pci_dev_t bdf, 9044d8615cbSBin Meng uint offset, ulong value, 9054d8615cbSBin Meng enum pci_size_t size) 906ff3e077bSSimon Glass { 907ff3e077bSSimon Glass struct pci_controller *hose = bus->uclass_priv; 908ff3e077bSSimon Glass 909ff3e077bSSimon Glass return pci_bus_write_config(hose->ctlr, bdf, offset, value, size); 910ff3e077bSSimon Glass } 911ff3e077bSSimon Glass 91276c3fbcdSSimon Glass static int skip_to_next_device(struct udevice *bus, struct udevice **devp) 91376c3fbcdSSimon Glass { 91476c3fbcdSSimon Glass struct udevice *dev; 91576c3fbcdSSimon Glass int ret = 0; 91676c3fbcdSSimon Glass 91776c3fbcdSSimon Glass /* 91876c3fbcdSSimon Glass * Scan through all the PCI controllers. On x86 there will only be one 91976c3fbcdSSimon Glass * but that is not necessarily true on other hardware. 92076c3fbcdSSimon Glass */ 92176c3fbcdSSimon Glass do { 92276c3fbcdSSimon Glass device_find_first_child(bus, &dev); 92376c3fbcdSSimon Glass if (dev) { 92476c3fbcdSSimon Glass *devp = dev; 92576c3fbcdSSimon Glass return 0; 92676c3fbcdSSimon Glass } 92776c3fbcdSSimon Glass ret = uclass_next_device(&bus); 92876c3fbcdSSimon Glass if (ret) 92976c3fbcdSSimon Glass return ret; 93076c3fbcdSSimon Glass } while (bus); 93176c3fbcdSSimon Glass 93276c3fbcdSSimon Glass return 0; 93376c3fbcdSSimon Glass } 93476c3fbcdSSimon Glass 93576c3fbcdSSimon Glass int pci_find_next_device(struct udevice **devp) 93676c3fbcdSSimon Glass { 93776c3fbcdSSimon Glass struct udevice *child = *devp; 93876c3fbcdSSimon Glass struct udevice *bus = child->parent; 93976c3fbcdSSimon Glass int ret; 94076c3fbcdSSimon Glass 94176c3fbcdSSimon Glass /* First try all the siblings */ 94276c3fbcdSSimon Glass *devp = NULL; 94376c3fbcdSSimon Glass while (child) { 94476c3fbcdSSimon Glass device_find_next_child(&child); 94576c3fbcdSSimon Glass if (child) { 94676c3fbcdSSimon Glass *devp = child; 94776c3fbcdSSimon Glass return 0; 94876c3fbcdSSimon Glass } 94976c3fbcdSSimon Glass } 95076c3fbcdSSimon Glass 95176c3fbcdSSimon Glass /* We ran out of siblings. Try the next bus */ 95276c3fbcdSSimon Glass ret = uclass_next_device(&bus); 95376c3fbcdSSimon Glass if (ret) 95476c3fbcdSSimon Glass return ret; 95576c3fbcdSSimon Glass 95676c3fbcdSSimon Glass return bus ? skip_to_next_device(bus, devp) : 0; 95776c3fbcdSSimon Glass } 95876c3fbcdSSimon Glass 95976c3fbcdSSimon Glass int pci_find_first_device(struct udevice **devp) 96076c3fbcdSSimon Glass { 96176c3fbcdSSimon Glass struct udevice *bus; 96276c3fbcdSSimon Glass int ret; 96376c3fbcdSSimon Glass 96476c3fbcdSSimon Glass *devp = NULL; 96576c3fbcdSSimon Glass ret = uclass_first_device(UCLASS_PCI, &bus); 96676c3fbcdSSimon Glass if (ret) 96776c3fbcdSSimon Glass return ret; 96876c3fbcdSSimon Glass 96976c3fbcdSSimon Glass return skip_to_next_device(bus, devp); 97076c3fbcdSSimon Glass } 97176c3fbcdSSimon Glass 9729289db6cSSimon Glass ulong pci_conv_32_to_size(ulong value, uint offset, enum pci_size_t size) 9739289db6cSSimon Glass { 9749289db6cSSimon Glass switch (size) { 9759289db6cSSimon Glass case PCI_SIZE_8: 9769289db6cSSimon Glass return (value >> ((offset & 3) * 8)) & 0xff; 9779289db6cSSimon Glass case PCI_SIZE_16: 9789289db6cSSimon Glass return (value >> ((offset & 2) * 8)) & 0xffff; 9799289db6cSSimon Glass default: 9809289db6cSSimon Glass return value; 9819289db6cSSimon Glass } 9829289db6cSSimon Glass } 9839289db6cSSimon Glass 9849289db6cSSimon Glass ulong pci_conv_size_to_32(ulong old, ulong value, uint offset, 9859289db6cSSimon Glass enum pci_size_t size) 9869289db6cSSimon Glass { 9879289db6cSSimon Glass uint off_mask; 9889289db6cSSimon Glass uint val_mask, shift; 9899289db6cSSimon Glass ulong ldata, mask; 9909289db6cSSimon Glass 9919289db6cSSimon Glass switch (size) { 9929289db6cSSimon Glass case PCI_SIZE_8: 9939289db6cSSimon Glass off_mask = 3; 9949289db6cSSimon Glass val_mask = 0xff; 9959289db6cSSimon Glass break; 9969289db6cSSimon Glass case PCI_SIZE_16: 9979289db6cSSimon Glass off_mask = 2; 9989289db6cSSimon Glass val_mask = 0xffff; 9999289db6cSSimon Glass break; 10009289db6cSSimon Glass default: 10019289db6cSSimon Glass return value; 10029289db6cSSimon Glass } 10039289db6cSSimon Glass shift = (offset & off_mask) * 8; 10049289db6cSSimon Glass ldata = (value & val_mask) << shift; 10059289db6cSSimon Glass mask = val_mask << shift; 10069289db6cSSimon Glass value = (old & ~mask) | ldata; 10079289db6cSSimon Glass 10089289db6cSSimon Glass return value; 10099289db6cSSimon Glass } 10109289db6cSSimon Glass 1011f9260336SSimon Glass int pci_get_regions(struct udevice *dev, struct pci_region **iop, 1012f9260336SSimon Glass struct pci_region **memp, struct pci_region **prefp) 1013f9260336SSimon Glass { 1014f9260336SSimon Glass struct udevice *bus = pci_get_controller(dev); 1015f9260336SSimon Glass struct pci_controller *hose = dev_get_uclass_priv(bus); 1016f9260336SSimon Glass int i; 1017f9260336SSimon Glass 1018f9260336SSimon Glass *iop = NULL; 1019f9260336SSimon Glass *memp = NULL; 1020f9260336SSimon Glass *prefp = NULL; 1021f9260336SSimon Glass for (i = 0; i < hose->region_count; i++) { 1022f9260336SSimon Glass switch (hose->regions[i].flags) { 1023f9260336SSimon Glass case PCI_REGION_IO: 1024f9260336SSimon Glass if (!*iop || (*iop)->size < hose->regions[i].size) 1025f9260336SSimon Glass *iop = hose->regions + i; 1026f9260336SSimon Glass break; 1027f9260336SSimon Glass case PCI_REGION_MEM: 1028f9260336SSimon Glass if (!*memp || (*memp)->size < hose->regions[i].size) 1029f9260336SSimon Glass *memp = hose->regions + i; 1030f9260336SSimon Glass break; 1031f9260336SSimon Glass case (PCI_REGION_MEM | PCI_REGION_PREFETCH): 1032f9260336SSimon Glass if (!*prefp || (*prefp)->size < hose->regions[i].size) 1033f9260336SSimon Glass *prefp = hose->regions + i; 1034f9260336SSimon Glass break; 1035f9260336SSimon Glass } 1036f9260336SSimon Glass } 1037f9260336SSimon Glass 1038f9260336SSimon Glass return (*iop != NULL) + (*memp != NULL) + (*prefp != NULL); 1039f9260336SSimon Glass } 1040f9260336SSimon Glass 1041bab17cf1SSimon Glass u32 dm_pci_read_bar32(struct udevice *dev, int barnum) 1042bab17cf1SSimon Glass { 1043bab17cf1SSimon Glass u32 addr; 1044bab17cf1SSimon Glass int bar; 1045bab17cf1SSimon Glass 1046bab17cf1SSimon Glass bar = PCI_BASE_ADDRESS_0 + barnum * 4; 1047bab17cf1SSimon Glass dm_pci_read_config32(dev, bar, &addr); 1048bab17cf1SSimon Glass if (addr & PCI_BASE_ADDRESS_SPACE_IO) 1049bab17cf1SSimon Glass return addr & PCI_BASE_ADDRESS_IO_MASK; 1050bab17cf1SSimon Glass else 1051bab17cf1SSimon Glass return addr & PCI_BASE_ADDRESS_MEM_MASK; 1052bab17cf1SSimon Glass } 1053bab17cf1SSimon Glass 10549d731c82SSimon Glass void dm_pci_write_bar32(struct udevice *dev, int barnum, u32 addr) 10559d731c82SSimon Glass { 10569d731c82SSimon Glass int bar; 10579d731c82SSimon Glass 10589d731c82SSimon Glass bar = PCI_BASE_ADDRESS_0 + barnum * 4; 10599d731c82SSimon Glass dm_pci_write_config32(dev, bar, addr); 10609d731c82SSimon Glass } 10619d731c82SSimon Glass 106221d1fe7eSSimon Glass static int _dm_pci_bus_to_phys(struct udevice *ctlr, 106321d1fe7eSSimon Glass pci_addr_t bus_addr, unsigned long flags, 106421d1fe7eSSimon Glass unsigned long skip_mask, phys_addr_t *pa) 106521d1fe7eSSimon Glass { 106621d1fe7eSSimon Glass struct pci_controller *hose = dev_get_uclass_priv(ctlr); 106721d1fe7eSSimon Glass struct pci_region *res; 106821d1fe7eSSimon Glass int i; 106921d1fe7eSSimon Glass 107021d1fe7eSSimon Glass for (i = 0; i < hose->region_count; i++) { 107121d1fe7eSSimon Glass res = &hose->regions[i]; 107221d1fe7eSSimon Glass 107321d1fe7eSSimon Glass if (((res->flags ^ flags) & PCI_REGION_TYPE) != 0) 107421d1fe7eSSimon Glass continue; 107521d1fe7eSSimon Glass 107621d1fe7eSSimon Glass if (res->flags & skip_mask) 107721d1fe7eSSimon Glass continue; 107821d1fe7eSSimon Glass 107921d1fe7eSSimon Glass if (bus_addr >= res->bus_start && 108021d1fe7eSSimon Glass (bus_addr - res->bus_start) < res->size) { 108121d1fe7eSSimon Glass *pa = (bus_addr - res->bus_start + res->phys_start); 108221d1fe7eSSimon Glass return 0; 108321d1fe7eSSimon Glass } 108421d1fe7eSSimon Glass } 108521d1fe7eSSimon Glass 108621d1fe7eSSimon Glass return 1; 108721d1fe7eSSimon Glass } 108821d1fe7eSSimon Glass 108921d1fe7eSSimon Glass phys_addr_t dm_pci_bus_to_phys(struct udevice *dev, pci_addr_t bus_addr, 109021d1fe7eSSimon Glass unsigned long flags) 109121d1fe7eSSimon Glass { 109221d1fe7eSSimon Glass phys_addr_t phys_addr = 0; 109321d1fe7eSSimon Glass struct udevice *ctlr; 109421d1fe7eSSimon Glass int ret; 109521d1fe7eSSimon Glass 109621d1fe7eSSimon Glass /* The root controller has the region information */ 109721d1fe7eSSimon Glass ctlr = pci_get_controller(dev); 109821d1fe7eSSimon Glass 109921d1fe7eSSimon Glass /* 110021d1fe7eSSimon Glass * if PCI_REGION_MEM is set we do a two pass search with preference 110121d1fe7eSSimon Glass * on matches that don't have PCI_REGION_SYS_MEMORY set 110221d1fe7eSSimon Glass */ 110321d1fe7eSSimon Glass if ((flags & PCI_REGION_TYPE) == PCI_REGION_MEM) { 110421d1fe7eSSimon Glass ret = _dm_pci_bus_to_phys(ctlr, bus_addr, 110521d1fe7eSSimon Glass flags, PCI_REGION_SYS_MEMORY, 110621d1fe7eSSimon Glass &phys_addr); 110721d1fe7eSSimon Glass if (!ret) 110821d1fe7eSSimon Glass return phys_addr; 110921d1fe7eSSimon Glass } 111021d1fe7eSSimon Glass 111121d1fe7eSSimon Glass ret = _dm_pci_bus_to_phys(ctlr, bus_addr, flags, 0, &phys_addr); 111221d1fe7eSSimon Glass 111321d1fe7eSSimon Glass if (ret) 111421d1fe7eSSimon Glass puts("pci_hose_bus_to_phys: invalid physical address\n"); 111521d1fe7eSSimon Glass 111621d1fe7eSSimon Glass return phys_addr; 111721d1fe7eSSimon Glass } 111821d1fe7eSSimon Glass 111921d1fe7eSSimon Glass int _dm_pci_phys_to_bus(struct udevice *dev, phys_addr_t phys_addr, 112021d1fe7eSSimon Glass unsigned long flags, unsigned long skip_mask, 112121d1fe7eSSimon Glass pci_addr_t *ba) 112221d1fe7eSSimon Glass { 112321d1fe7eSSimon Glass struct pci_region *res; 112421d1fe7eSSimon Glass struct udevice *ctlr; 112521d1fe7eSSimon Glass pci_addr_t bus_addr; 112621d1fe7eSSimon Glass int i; 112721d1fe7eSSimon Glass struct pci_controller *hose; 112821d1fe7eSSimon Glass 112921d1fe7eSSimon Glass /* The root controller has the region information */ 113021d1fe7eSSimon Glass ctlr = pci_get_controller(dev); 113121d1fe7eSSimon Glass hose = dev_get_uclass_priv(ctlr); 113221d1fe7eSSimon Glass 113321d1fe7eSSimon Glass for (i = 0; i < hose->region_count; i++) { 113421d1fe7eSSimon Glass res = &hose->regions[i]; 113521d1fe7eSSimon Glass 113621d1fe7eSSimon Glass if (((res->flags ^ flags) & PCI_REGION_TYPE) != 0) 113721d1fe7eSSimon Glass continue; 113821d1fe7eSSimon Glass 113921d1fe7eSSimon Glass if (res->flags & skip_mask) 114021d1fe7eSSimon Glass continue; 114121d1fe7eSSimon Glass 114221d1fe7eSSimon Glass bus_addr = phys_addr - res->phys_start + res->bus_start; 114321d1fe7eSSimon Glass 114421d1fe7eSSimon Glass if (bus_addr >= res->bus_start && 114521d1fe7eSSimon Glass (bus_addr - res->bus_start) < res->size) { 114621d1fe7eSSimon Glass *ba = bus_addr; 114721d1fe7eSSimon Glass return 0; 114821d1fe7eSSimon Glass } 114921d1fe7eSSimon Glass } 115021d1fe7eSSimon Glass 115121d1fe7eSSimon Glass return 1; 115221d1fe7eSSimon Glass } 115321d1fe7eSSimon Glass 115421d1fe7eSSimon Glass pci_addr_t dm_pci_phys_to_bus(struct udevice *dev, phys_addr_t phys_addr, 115521d1fe7eSSimon Glass unsigned long flags) 115621d1fe7eSSimon Glass { 115721d1fe7eSSimon Glass pci_addr_t bus_addr = 0; 115821d1fe7eSSimon Glass int ret; 115921d1fe7eSSimon Glass 116021d1fe7eSSimon Glass /* 116121d1fe7eSSimon Glass * if PCI_REGION_MEM is set we do a two pass search with preference 116221d1fe7eSSimon Glass * on matches that don't have PCI_REGION_SYS_MEMORY set 116321d1fe7eSSimon Glass */ 116421d1fe7eSSimon Glass if ((flags & PCI_REGION_TYPE) == PCI_REGION_MEM) { 116521d1fe7eSSimon Glass ret = _dm_pci_phys_to_bus(dev, phys_addr, flags, 116621d1fe7eSSimon Glass PCI_REGION_SYS_MEMORY, &bus_addr); 116721d1fe7eSSimon Glass if (!ret) 116821d1fe7eSSimon Glass return bus_addr; 116921d1fe7eSSimon Glass } 117021d1fe7eSSimon Glass 117121d1fe7eSSimon Glass ret = _dm_pci_phys_to_bus(dev, phys_addr, flags, 0, &bus_addr); 117221d1fe7eSSimon Glass 117321d1fe7eSSimon Glass if (ret) 117421d1fe7eSSimon Glass puts("pci_hose_phys_to_bus: invalid physical address\n"); 117521d1fe7eSSimon Glass 117621d1fe7eSSimon Glass return bus_addr; 117721d1fe7eSSimon Glass } 117821d1fe7eSSimon Glass 117921d1fe7eSSimon Glass void *dm_pci_map_bar(struct udevice *dev, int bar, int flags) 118021d1fe7eSSimon Glass { 118121d1fe7eSSimon Glass pci_addr_t pci_bus_addr; 118221d1fe7eSSimon Glass u32 bar_response; 118321d1fe7eSSimon Glass 118421d1fe7eSSimon Glass /* read BAR address */ 118521d1fe7eSSimon Glass dm_pci_read_config32(dev, bar, &bar_response); 118621d1fe7eSSimon Glass pci_bus_addr = (pci_addr_t)(bar_response & ~0xf); 118721d1fe7eSSimon Glass 118821d1fe7eSSimon Glass /* 118921d1fe7eSSimon Glass * Pass "0" as the length argument to pci_bus_to_virt. The arg 119021d1fe7eSSimon Glass * isn't actualy used on any platform because u-boot assumes a static 119121d1fe7eSSimon Glass * linear mapping. In the future, this could read the BAR size 119221d1fe7eSSimon Glass * and pass that as the size if needed. 119321d1fe7eSSimon Glass */ 119421d1fe7eSSimon Glass return dm_pci_bus_to_virt(dev, pci_bus_addr, flags, 0, MAP_NOCACHE); 119521d1fe7eSSimon Glass } 119621d1fe7eSSimon Glass 1197ff3e077bSSimon Glass UCLASS_DRIVER(pci) = { 1198ff3e077bSSimon Glass .id = UCLASS_PCI, 1199ff3e077bSSimon Glass .name = "pci", 12002bb02e4fSSimon Glass .flags = DM_UC_FLAG_SEQ_ALIAS, 1201ff3e077bSSimon Glass .post_bind = pci_uclass_post_bind, 1202ff3e077bSSimon Glass .pre_probe = pci_uclass_pre_probe, 1203ff3e077bSSimon Glass .post_probe = pci_uclass_post_probe, 1204ff3e077bSSimon Glass .child_post_bind = pci_uclass_child_post_bind, 1205ff3e077bSSimon Glass .per_device_auto_alloc_size = sizeof(struct pci_controller), 1206ff3e077bSSimon Glass .per_child_platdata_auto_alloc_size = 1207ff3e077bSSimon Glass sizeof(struct pci_child_platdata), 1208ff3e077bSSimon Glass }; 1209ff3e077bSSimon Glass 1210ff3e077bSSimon Glass static const struct dm_pci_ops pci_bridge_ops = { 1211ff3e077bSSimon Glass .read_config = pci_bridge_read_config, 1212ff3e077bSSimon Glass .write_config = pci_bridge_write_config, 1213ff3e077bSSimon Glass }; 1214ff3e077bSSimon Glass 1215ff3e077bSSimon Glass static const struct udevice_id pci_bridge_ids[] = { 1216ff3e077bSSimon Glass { .compatible = "pci-bridge" }, 1217ff3e077bSSimon Glass { } 1218ff3e077bSSimon Glass }; 1219ff3e077bSSimon Glass 1220ff3e077bSSimon Glass U_BOOT_DRIVER(pci_bridge_drv) = { 1221ff3e077bSSimon Glass .name = "pci_bridge_drv", 1222ff3e077bSSimon Glass .id = UCLASS_PCI, 1223ff3e077bSSimon Glass .of_match = pci_bridge_ids, 1224ff3e077bSSimon Glass .ops = &pci_bridge_ops, 1225ff3e077bSSimon Glass }; 1226ff3e077bSSimon Glass 1227ff3e077bSSimon Glass UCLASS_DRIVER(pci_generic) = { 1228ff3e077bSSimon Glass .id = UCLASS_PCI_GENERIC, 1229ff3e077bSSimon Glass .name = "pci_generic", 1230ff3e077bSSimon Glass }; 1231ff3e077bSSimon Glass 1232ff3e077bSSimon Glass static const struct udevice_id pci_generic_ids[] = { 1233ff3e077bSSimon Glass { .compatible = "pci-generic" }, 1234ff3e077bSSimon Glass { } 1235ff3e077bSSimon Glass }; 1236ff3e077bSSimon Glass 1237ff3e077bSSimon Glass U_BOOT_DRIVER(pci_generic_drv) = { 1238ff3e077bSSimon Glass .name = "pci_generic_drv", 1239ff3e077bSSimon Glass .id = UCLASS_PCI_GENERIC, 1240ff3e077bSSimon Glass .of_match = pci_generic_ids, 1241ff3e077bSSimon Glass }; 1242e578b92cSStephen Warren 1243e578b92cSStephen Warren void pci_init(void) 1244e578b92cSStephen Warren { 1245e578b92cSStephen Warren struct udevice *bus; 1246e578b92cSStephen Warren 1247e578b92cSStephen Warren /* 1248e578b92cSStephen Warren * Enumerate all known controller devices. Enumeration has the side- 1249e578b92cSStephen Warren * effect of probing them, so PCIe devices will be enumerated too. 1250e578b92cSStephen Warren */ 1251e578b92cSStephen Warren for (uclass_first_device(UCLASS_PCI, &bus); 1252e578b92cSStephen Warren bus; 1253e578b92cSStephen Warren uclass_next_device(&bus)) { 1254e578b92cSStephen Warren ; 1255e578b92cSStephen Warren } 1256e578b92cSStephen Warren } 1257