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> 14ff3e077bSSimon Glass #include <dm/lists.h> 15ff3e077bSSimon Glass #include <dm/root.h> 16ff3e077bSSimon Glass #include <dm/device-internal.h> 17348b744bSBin Meng #if defined(CONFIG_X86) && defined(CONFIG_HAVE_FSP) 18348b744bSBin Meng #include <asm/fsp/fsp_support.h> 19348b744bSBin Meng #endif 20ff3e077bSSimon Glass 21ff3e077bSSimon Glass DECLARE_GLOBAL_DATA_PTR; 22ff3e077bSSimon Glass 23983c6ba2SSimon Glass static int pci_get_bus(int busnum, struct udevice **busp) 24983c6ba2SSimon Glass { 25983c6ba2SSimon Glass int ret; 26983c6ba2SSimon Glass 27983c6ba2SSimon Glass ret = uclass_get_device_by_seq(UCLASS_PCI, busnum, busp); 28983c6ba2SSimon Glass 29983c6ba2SSimon Glass /* Since buses may not be numbered yet try a little harder with bus 0 */ 30983c6ba2SSimon Glass if (ret == -ENODEV) { 31983c6ba2SSimon Glass ret = uclass_first_device(UCLASS_PCI, busp); 32983c6ba2SSimon Glass if (ret) 33983c6ba2SSimon Glass return ret; 34983c6ba2SSimon Glass else if (!*busp) 35983c6ba2SSimon Glass return -ENODEV; 36983c6ba2SSimon Glass ret = uclass_get_device_by_seq(UCLASS_PCI, busnum, busp); 37983c6ba2SSimon Glass } 38983c6ba2SSimon Glass 39983c6ba2SSimon Glass return ret; 40983c6ba2SSimon Glass } 41983c6ba2SSimon Glass 42ff3e077bSSimon Glass struct pci_controller *pci_bus_to_hose(int busnum) 43ff3e077bSSimon Glass { 44ff3e077bSSimon Glass struct udevice *bus; 45ff3e077bSSimon Glass int ret; 46ff3e077bSSimon Glass 47983c6ba2SSimon Glass ret = pci_get_bus(busnum, &bus); 48ff3e077bSSimon Glass if (ret) { 49ff3e077bSSimon Glass debug("%s: Cannot get bus %d: ret=%d\n", __func__, busnum, ret); 50ff3e077bSSimon Glass return NULL; 51ff3e077bSSimon Glass } 52983c6ba2SSimon Glass 53ff3e077bSSimon Glass return dev_get_uclass_priv(bus); 54ff3e077bSSimon Glass } 55ff3e077bSSimon Glass 564b515e4fSSimon Glass pci_dev_t pci_get_bdf(struct udevice *dev) 574b515e4fSSimon Glass { 584b515e4fSSimon Glass struct pci_child_platdata *pplat = dev_get_parent_platdata(dev); 594b515e4fSSimon Glass struct udevice *bus = dev->parent; 604b515e4fSSimon Glass 614b515e4fSSimon Glass return PCI_ADD_BUS(bus->seq, pplat->devfn); 624b515e4fSSimon Glass } 634b515e4fSSimon Glass 64ff3e077bSSimon Glass /** 65ff3e077bSSimon Glass * pci_get_bus_max() - returns the bus number of the last active bus 66ff3e077bSSimon Glass * 67ff3e077bSSimon Glass * @return last bus number, or -1 if no active buses 68ff3e077bSSimon Glass */ 69ff3e077bSSimon Glass static int pci_get_bus_max(void) 70ff3e077bSSimon Glass { 71ff3e077bSSimon Glass struct udevice *bus; 72ff3e077bSSimon Glass struct uclass *uc; 73ff3e077bSSimon Glass int ret = -1; 74ff3e077bSSimon Glass 75ff3e077bSSimon Glass ret = uclass_get(UCLASS_PCI, &uc); 76ff3e077bSSimon Glass uclass_foreach_dev(bus, uc) { 77ff3e077bSSimon Glass if (bus->seq > ret) 78ff3e077bSSimon Glass ret = bus->seq; 79ff3e077bSSimon Glass } 80ff3e077bSSimon Glass 81ff3e077bSSimon Glass debug("%s: ret=%d\n", __func__, ret); 82ff3e077bSSimon Glass 83ff3e077bSSimon Glass return ret; 84ff3e077bSSimon Glass } 85ff3e077bSSimon Glass 86ff3e077bSSimon Glass int pci_last_busno(void) 87ff3e077bSSimon Glass { 88*069155cbSBin Meng return pci_get_bus_max(); 89ff3e077bSSimon Glass } 90ff3e077bSSimon Glass 91ff3e077bSSimon Glass int pci_get_ff(enum pci_size_t size) 92ff3e077bSSimon Glass { 93ff3e077bSSimon Glass switch (size) { 94ff3e077bSSimon Glass case PCI_SIZE_8: 95ff3e077bSSimon Glass return 0xff; 96ff3e077bSSimon Glass case PCI_SIZE_16: 97ff3e077bSSimon Glass return 0xffff; 98ff3e077bSSimon Glass default: 99ff3e077bSSimon Glass return 0xffffffff; 100ff3e077bSSimon Glass } 101ff3e077bSSimon Glass } 102ff3e077bSSimon Glass 103ff3e077bSSimon Glass int pci_bus_find_devfn(struct udevice *bus, pci_dev_t find_devfn, 104ff3e077bSSimon Glass struct udevice **devp) 105ff3e077bSSimon Glass { 106ff3e077bSSimon Glass struct udevice *dev; 107ff3e077bSSimon Glass 108ff3e077bSSimon Glass for (device_find_first_child(bus, &dev); 109ff3e077bSSimon Glass dev; 110ff3e077bSSimon Glass device_find_next_child(&dev)) { 111ff3e077bSSimon Glass struct pci_child_platdata *pplat; 112ff3e077bSSimon Glass 113ff3e077bSSimon Glass pplat = dev_get_parent_platdata(dev); 114ff3e077bSSimon Glass if (pplat && pplat->devfn == find_devfn) { 115ff3e077bSSimon Glass *devp = dev; 116ff3e077bSSimon Glass return 0; 117ff3e077bSSimon Glass } 118ff3e077bSSimon Glass } 119ff3e077bSSimon Glass 120ff3e077bSSimon Glass return -ENODEV; 121ff3e077bSSimon Glass } 122ff3e077bSSimon Glass 123ff3e077bSSimon Glass int pci_bus_find_bdf(pci_dev_t bdf, struct udevice **devp) 124ff3e077bSSimon Glass { 125ff3e077bSSimon Glass struct udevice *bus; 126ff3e077bSSimon Glass int ret; 127ff3e077bSSimon Glass 128983c6ba2SSimon Glass ret = pci_get_bus(PCI_BUS(bdf), &bus); 129ff3e077bSSimon Glass if (ret) 130ff3e077bSSimon Glass return ret; 131ff3e077bSSimon Glass return pci_bus_find_devfn(bus, PCI_MASK_BUS(bdf), devp); 132ff3e077bSSimon Glass } 133ff3e077bSSimon Glass 134ff3e077bSSimon Glass static int pci_device_matches_ids(struct udevice *dev, 135ff3e077bSSimon Glass struct pci_device_id *ids) 136ff3e077bSSimon Glass { 137ff3e077bSSimon Glass struct pci_child_platdata *pplat; 138ff3e077bSSimon Glass int i; 139ff3e077bSSimon Glass 140ff3e077bSSimon Glass pplat = dev_get_parent_platdata(dev); 141ff3e077bSSimon Glass if (!pplat) 142ff3e077bSSimon Glass return -EINVAL; 143ff3e077bSSimon Glass for (i = 0; ids[i].vendor != 0; i++) { 144ff3e077bSSimon Glass if (pplat->vendor == ids[i].vendor && 145ff3e077bSSimon Glass pplat->device == ids[i].device) 146ff3e077bSSimon Glass return i; 147ff3e077bSSimon Glass } 148ff3e077bSSimon Glass 149ff3e077bSSimon Glass return -EINVAL; 150ff3e077bSSimon Glass } 151ff3e077bSSimon Glass 152ff3e077bSSimon Glass int pci_bus_find_devices(struct udevice *bus, struct pci_device_id *ids, 153ff3e077bSSimon Glass int *indexp, struct udevice **devp) 154ff3e077bSSimon Glass { 155ff3e077bSSimon Glass struct udevice *dev; 156ff3e077bSSimon Glass 157ff3e077bSSimon Glass /* Scan all devices on this bus */ 158ff3e077bSSimon Glass for (device_find_first_child(bus, &dev); 159ff3e077bSSimon Glass dev; 160ff3e077bSSimon Glass device_find_next_child(&dev)) { 161ff3e077bSSimon Glass if (pci_device_matches_ids(dev, ids) >= 0) { 162ff3e077bSSimon Glass if ((*indexp)-- <= 0) { 163ff3e077bSSimon Glass *devp = dev; 164ff3e077bSSimon Glass return 0; 165ff3e077bSSimon Glass } 166ff3e077bSSimon Glass } 167ff3e077bSSimon Glass } 168ff3e077bSSimon Glass 169ff3e077bSSimon Glass return -ENODEV; 170ff3e077bSSimon Glass } 171ff3e077bSSimon Glass 172ff3e077bSSimon Glass int pci_find_device_id(struct pci_device_id *ids, int index, 173ff3e077bSSimon Glass struct udevice **devp) 174ff3e077bSSimon Glass { 175ff3e077bSSimon Glass struct udevice *bus; 176ff3e077bSSimon Glass 177ff3e077bSSimon Glass /* Scan all known buses */ 178ff3e077bSSimon Glass for (uclass_first_device(UCLASS_PCI, &bus); 179ff3e077bSSimon Glass bus; 180ff3e077bSSimon Glass uclass_next_device(&bus)) { 181ff3e077bSSimon Glass if (!pci_bus_find_devices(bus, ids, &index, devp)) 182ff3e077bSSimon Glass return 0; 183ff3e077bSSimon Glass } 184ff3e077bSSimon Glass *devp = NULL; 185ff3e077bSSimon Glass 186ff3e077bSSimon Glass return -ENODEV; 187ff3e077bSSimon Glass } 188ff3e077bSSimon Glass 189ff3e077bSSimon Glass int pci_bus_write_config(struct udevice *bus, pci_dev_t bdf, int offset, 190ff3e077bSSimon Glass unsigned long value, enum pci_size_t size) 191ff3e077bSSimon Glass { 192ff3e077bSSimon Glass struct dm_pci_ops *ops; 193ff3e077bSSimon Glass 194ff3e077bSSimon Glass ops = pci_get_ops(bus); 195ff3e077bSSimon Glass if (!ops->write_config) 196ff3e077bSSimon Glass return -ENOSYS; 197ff3e077bSSimon Glass return ops->write_config(bus, bdf, offset, value, size); 198ff3e077bSSimon Glass } 199ff3e077bSSimon Glass 200ff3e077bSSimon Glass int pci_write_config(pci_dev_t bdf, int offset, unsigned long value, 201ff3e077bSSimon Glass enum pci_size_t size) 202ff3e077bSSimon Glass { 203ff3e077bSSimon Glass struct udevice *bus; 204ff3e077bSSimon Glass int ret; 205ff3e077bSSimon Glass 206983c6ba2SSimon Glass ret = pci_get_bus(PCI_BUS(bdf), &bus); 207ff3e077bSSimon Glass if (ret) 208ff3e077bSSimon Glass return ret; 209ff3e077bSSimon Glass 2104d8615cbSBin Meng return pci_bus_write_config(bus, bdf, offset, value, size); 211ff3e077bSSimon Glass } 212ff3e077bSSimon Glass 21366afb4edSSimon Glass int dm_pci_write_config(struct udevice *dev, int offset, unsigned long value, 21466afb4edSSimon Glass enum pci_size_t size) 21566afb4edSSimon Glass { 21666afb4edSSimon Glass struct udevice *bus; 21766afb4edSSimon Glass 2181e0f2263SBin Meng for (bus = dev; device_is_on_pci_bus(bus);) 21966afb4edSSimon Glass bus = bus->parent; 22066afb4edSSimon Glass return pci_bus_write_config(bus, pci_get_bdf(dev), offset, value, size); 22166afb4edSSimon Glass } 22266afb4edSSimon Glass 22366afb4edSSimon Glass 224ff3e077bSSimon Glass int pci_write_config32(pci_dev_t bdf, int offset, u32 value) 225ff3e077bSSimon Glass { 226ff3e077bSSimon Glass return pci_write_config(bdf, offset, value, PCI_SIZE_32); 227ff3e077bSSimon Glass } 228ff3e077bSSimon Glass 229ff3e077bSSimon Glass int pci_write_config16(pci_dev_t bdf, int offset, u16 value) 230ff3e077bSSimon Glass { 231ff3e077bSSimon Glass return pci_write_config(bdf, offset, value, PCI_SIZE_16); 232ff3e077bSSimon Glass } 233ff3e077bSSimon Glass 234ff3e077bSSimon Glass int pci_write_config8(pci_dev_t bdf, int offset, u8 value) 235ff3e077bSSimon Glass { 236ff3e077bSSimon Glass return pci_write_config(bdf, offset, value, PCI_SIZE_8); 237ff3e077bSSimon Glass } 238ff3e077bSSimon Glass 23966afb4edSSimon Glass int dm_pci_write_config8(struct udevice *dev, int offset, u8 value) 24066afb4edSSimon Glass { 24166afb4edSSimon Glass return dm_pci_write_config(dev, offset, value, PCI_SIZE_8); 24266afb4edSSimon Glass } 24366afb4edSSimon Glass 24466afb4edSSimon Glass int dm_pci_write_config16(struct udevice *dev, int offset, u16 value) 24566afb4edSSimon Glass { 24666afb4edSSimon Glass return dm_pci_write_config(dev, offset, value, PCI_SIZE_16); 24766afb4edSSimon Glass } 24866afb4edSSimon Glass 24966afb4edSSimon Glass int dm_pci_write_config32(struct udevice *dev, int offset, u32 value) 25066afb4edSSimon Glass { 25166afb4edSSimon Glass return dm_pci_write_config(dev, offset, value, PCI_SIZE_32); 25266afb4edSSimon Glass } 25366afb4edSSimon Glass 254ff3e077bSSimon Glass int pci_bus_read_config(struct udevice *bus, pci_dev_t bdf, int offset, 255ff3e077bSSimon Glass unsigned long *valuep, enum pci_size_t size) 256ff3e077bSSimon Glass { 257ff3e077bSSimon Glass struct dm_pci_ops *ops; 258ff3e077bSSimon Glass 259ff3e077bSSimon Glass ops = pci_get_ops(bus); 260ff3e077bSSimon Glass if (!ops->read_config) 261ff3e077bSSimon Glass return -ENOSYS; 262ff3e077bSSimon Glass return ops->read_config(bus, bdf, offset, valuep, size); 263ff3e077bSSimon Glass } 264ff3e077bSSimon Glass 265ff3e077bSSimon Glass int pci_read_config(pci_dev_t bdf, int offset, unsigned long *valuep, 266ff3e077bSSimon Glass enum pci_size_t size) 267ff3e077bSSimon Glass { 268ff3e077bSSimon Glass struct udevice *bus; 269ff3e077bSSimon Glass int ret; 270ff3e077bSSimon Glass 271983c6ba2SSimon Glass ret = pci_get_bus(PCI_BUS(bdf), &bus); 272ff3e077bSSimon Glass if (ret) 273ff3e077bSSimon Glass return ret; 274ff3e077bSSimon Glass 2754d8615cbSBin Meng return pci_bus_read_config(bus, bdf, offset, valuep, size); 276ff3e077bSSimon Glass } 277ff3e077bSSimon Glass 27866afb4edSSimon Glass int dm_pci_read_config(struct udevice *dev, int offset, unsigned long *valuep, 27966afb4edSSimon Glass enum pci_size_t size) 28066afb4edSSimon Glass { 28166afb4edSSimon Glass struct udevice *bus; 28266afb4edSSimon Glass 2831e0f2263SBin Meng for (bus = dev; device_is_on_pci_bus(bus);) 28466afb4edSSimon Glass bus = bus->parent; 28566afb4edSSimon Glass return pci_bus_read_config(bus, pci_get_bdf(dev), offset, valuep, 28666afb4edSSimon Glass size); 28766afb4edSSimon Glass } 28866afb4edSSimon Glass 289ff3e077bSSimon Glass int pci_read_config32(pci_dev_t bdf, int offset, u32 *valuep) 290ff3e077bSSimon Glass { 291ff3e077bSSimon Glass unsigned long value; 292ff3e077bSSimon Glass int ret; 293ff3e077bSSimon Glass 294ff3e077bSSimon Glass ret = pci_read_config(bdf, offset, &value, PCI_SIZE_32); 295ff3e077bSSimon Glass if (ret) 296ff3e077bSSimon Glass return ret; 297ff3e077bSSimon Glass *valuep = value; 298ff3e077bSSimon Glass 299ff3e077bSSimon Glass return 0; 300ff3e077bSSimon Glass } 301ff3e077bSSimon Glass 302ff3e077bSSimon Glass int pci_read_config16(pci_dev_t bdf, int offset, u16 *valuep) 303ff3e077bSSimon Glass { 304ff3e077bSSimon Glass unsigned long value; 305ff3e077bSSimon Glass int ret; 306ff3e077bSSimon Glass 307ff3e077bSSimon Glass ret = pci_read_config(bdf, offset, &value, PCI_SIZE_16); 308ff3e077bSSimon Glass if (ret) 309ff3e077bSSimon Glass return ret; 310ff3e077bSSimon Glass *valuep = value; 311ff3e077bSSimon Glass 312ff3e077bSSimon Glass return 0; 313ff3e077bSSimon Glass } 314ff3e077bSSimon Glass 315ff3e077bSSimon Glass int pci_read_config8(pci_dev_t bdf, int offset, u8 *valuep) 316ff3e077bSSimon Glass { 317ff3e077bSSimon Glass unsigned long value; 318ff3e077bSSimon Glass int ret; 319ff3e077bSSimon Glass 320ff3e077bSSimon Glass ret = pci_read_config(bdf, offset, &value, PCI_SIZE_8); 321ff3e077bSSimon Glass if (ret) 322ff3e077bSSimon Glass return ret; 323ff3e077bSSimon Glass *valuep = value; 324ff3e077bSSimon Glass 325ff3e077bSSimon Glass return 0; 326ff3e077bSSimon Glass } 327ff3e077bSSimon Glass 32866afb4edSSimon Glass int dm_pci_read_config8(struct udevice *dev, int offset, u8 *valuep) 32966afb4edSSimon Glass { 33066afb4edSSimon Glass unsigned long value; 33166afb4edSSimon Glass int ret; 33266afb4edSSimon Glass 33366afb4edSSimon Glass ret = dm_pci_read_config(dev, offset, &value, PCI_SIZE_8); 33466afb4edSSimon Glass if (ret) 33566afb4edSSimon Glass return ret; 33666afb4edSSimon Glass *valuep = value; 33766afb4edSSimon Glass 33866afb4edSSimon Glass return 0; 33966afb4edSSimon Glass } 34066afb4edSSimon Glass 34166afb4edSSimon Glass int dm_pci_read_config16(struct udevice *dev, int offset, u16 *valuep) 34266afb4edSSimon Glass { 34366afb4edSSimon Glass unsigned long value; 34466afb4edSSimon Glass int ret; 34566afb4edSSimon Glass 34666afb4edSSimon Glass ret = dm_pci_read_config(dev, offset, &value, PCI_SIZE_16); 34766afb4edSSimon Glass if (ret) 34866afb4edSSimon Glass return ret; 34966afb4edSSimon Glass *valuep = value; 35066afb4edSSimon Glass 35166afb4edSSimon Glass return 0; 35266afb4edSSimon Glass } 35366afb4edSSimon Glass 35466afb4edSSimon Glass int dm_pci_read_config32(struct udevice *dev, int offset, u32 *valuep) 35566afb4edSSimon Glass { 35666afb4edSSimon Glass unsigned long value; 35766afb4edSSimon Glass int ret; 35866afb4edSSimon Glass 35966afb4edSSimon Glass ret = dm_pci_read_config(dev, offset, &value, PCI_SIZE_32); 36066afb4edSSimon Glass if (ret) 36166afb4edSSimon Glass return ret; 36266afb4edSSimon Glass *valuep = value; 36366afb4edSSimon Glass 36466afb4edSSimon Glass return 0; 36566afb4edSSimon Glass } 36666afb4edSSimon Glass 367ff3e077bSSimon Glass int pci_auto_config_devices(struct udevice *bus) 368ff3e077bSSimon Glass { 369ff3e077bSSimon Glass struct pci_controller *hose = bus->uclass_priv; 370ff3e077bSSimon Glass unsigned int sub_bus; 371ff3e077bSSimon Glass struct udevice *dev; 372ff3e077bSSimon Glass int ret; 373ff3e077bSSimon Glass 374ff3e077bSSimon Glass sub_bus = bus->seq; 375ff3e077bSSimon Glass debug("%s: start\n", __func__); 376ff3e077bSSimon Glass pciauto_config_init(hose); 377ff3e077bSSimon Glass for (ret = device_find_first_child(bus, &dev); 378ff3e077bSSimon Glass !ret && dev; 379ff3e077bSSimon Glass ret = device_find_next_child(&dev)) { 380ff3e077bSSimon Glass unsigned int max_bus; 3814d21455eSSimon Glass int ret; 382ff3e077bSSimon Glass 383ff3e077bSSimon Glass debug("%s: device %s\n", __func__, dev->name); 3844d21455eSSimon Glass ret = pciauto_config_device(hose, pci_get_bdf(dev)); 3854d21455eSSimon Glass if (ret < 0) 3864d21455eSSimon Glass return ret; 3874d21455eSSimon Glass max_bus = ret; 388ff3e077bSSimon Glass sub_bus = max(sub_bus, max_bus); 389ff3e077bSSimon Glass } 390ff3e077bSSimon Glass debug("%s: done\n", __func__); 391ff3e077bSSimon Glass 392ff3e077bSSimon Glass return sub_bus; 393ff3e077bSSimon Glass } 394ff3e077bSSimon Glass 395ff3e077bSSimon Glass int dm_pci_hose_probe_bus(struct pci_controller *hose, pci_dev_t bdf) 396ff3e077bSSimon Glass { 397ff3e077bSSimon Glass struct udevice *parent, *bus; 398ff3e077bSSimon Glass int sub_bus; 399ff3e077bSSimon Glass int ret; 400ff3e077bSSimon Glass 401ff3e077bSSimon Glass debug("%s\n", __func__); 402ff3e077bSSimon Glass parent = hose->bus; 403ff3e077bSSimon Glass 404ff3e077bSSimon Glass /* Find the bus within the parent */ 4058326f136SBin Meng ret = pci_bus_find_devfn(parent, PCI_MASK_BUS(bdf), &bus); 406ff3e077bSSimon Glass if (ret) { 407ff3e077bSSimon Glass debug("%s: Cannot find device %x on bus %s: %d\n", __func__, 408ff3e077bSSimon Glass bdf, parent->name, ret); 409ff3e077bSSimon Glass return ret; 410ff3e077bSSimon Glass } 411ff3e077bSSimon Glass 412ff3e077bSSimon Glass sub_bus = pci_get_bus_max() + 1; 413ff3e077bSSimon Glass debug("%s: bus = %d/%s\n", __func__, sub_bus, bus->name); 4145afeb4bbSSimon Glass pciauto_prescan_setup_bridge(hose, bdf, sub_bus); 415ff3e077bSSimon Glass 416ff3e077bSSimon Glass ret = device_probe(bus); 417ff3e077bSSimon Glass if (ret) { 4183129ace4SSimon Glass debug("%s: Cannot probe bus %s: %d\n", __func__, bus->name, 419ff3e077bSSimon Glass ret); 420ff3e077bSSimon Glass return ret; 421ff3e077bSSimon Glass } 422ff3e077bSSimon Glass if (sub_bus != bus->seq) { 423ff3e077bSSimon Glass printf("%s: Internal error, bus '%s' got seq %d, expected %d\n", 424ff3e077bSSimon Glass __func__, bus->name, bus->seq, sub_bus); 425ff3e077bSSimon Glass return -EPIPE; 426ff3e077bSSimon Glass } 427ff3e077bSSimon Glass sub_bus = pci_get_bus_max(); 428ff3e077bSSimon Glass pciauto_postscan_setup_bridge(hose, bdf, sub_bus); 429ff3e077bSSimon Glass 430ff3e077bSSimon Glass return sub_bus; 431ff3e077bSSimon Glass } 432ff3e077bSSimon Glass 433aba92962SSimon Glass /** 434aba92962SSimon Glass * pci_match_one_device - Tell if a PCI device structure has a matching 435aba92962SSimon Glass * PCI device id structure 436aba92962SSimon Glass * @id: single PCI device id structure to match 437aba92962SSimon Glass * @dev: the PCI device structure to match against 438aba92962SSimon Glass * 439aba92962SSimon Glass * Returns the matching pci_device_id structure or %NULL if there is no match. 440aba92962SSimon Glass */ 441aba92962SSimon Glass static bool pci_match_one_id(const struct pci_device_id *id, 442aba92962SSimon Glass const struct pci_device_id *find) 443aba92962SSimon Glass { 444aba92962SSimon Glass if ((id->vendor == PCI_ANY_ID || id->vendor == find->vendor) && 445aba92962SSimon Glass (id->device == PCI_ANY_ID || id->device == find->device) && 446aba92962SSimon Glass (id->subvendor == PCI_ANY_ID || id->subvendor == find->subvendor) && 447aba92962SSimon Glass (id->subdevice == PCI_ANY_ID || id->subdevice == find->subdevice) && 448aba92962SSimon Glass !((id->class ^ find->class) & id->class_mask)) 449aba92962SSimon Glass return true; 450aba92962SSimon Glass 451aba92962SSimon Glass return false; 452aba92962SSimon Glass } 453aba92962SSimon Glass 454aba92962SSimon Glass /** 455aba92962SSimon Glass * pci_find_and_bind_driver() - Find and bind the right PCI driver 456aba92962SSimon Glass * 457aba92962SSimon Glass * This only looks at certain fields in the descriptor. 4585dbcf3a0SSimon Glass * 4595dbcf3a0SSimon Glass * @parent: Parent bus 4605dbcf3a0SSimon Glass * @find_id: Specification of the driver to find 4615dbcf3a0SSimon Glass * @bdf: Bus/device/function addreess - see PCI_BDF() 4625dbcf3a0SSimon Glass * @devp: Returns a pointer to the device created 4635dbcf3a0SSimon Glass * @return 0 if OK, -EPERM if the device is not needed before relocation and 4645dbcf3a0SSimon Glass * therefore was not created, other -ve value on error 465aba92962SSimon Glass */ 466aba92962SSimon Glass static int pci_find_and_bind_driver(struct udevice *parent, 4675dbcf3a0SSimon Glass struct pci_device_id *find_id, 4685dbcf3a0SSimon Glass pci_dev_t bdf, struct udevice **devp) 469aba92962SSimon Glass { 470aba92962SSimon Glass struct pci_driver_entry *start, *entry; 471aba92962SSimon Glass const char *drv; 472aba92962SSimon Glass int n_ents; 473aba92962SSimon Glass int ret; 474aba92962SSimon Glass char name[30], *str; 47508fc7b8fSBin Meng bool bridge; 476aba92962SSimon Glass 477aba92962SSimon Glass *devp = NULL; 478aba92962SSimon Glass 479aba92962SSimon Glass debug("%s: Searching for driver: vendor=%x, device=%x\n", __func__, 480aba92962SSimon Glass find_id->vendor, find_id->device); 481aba92962SSimon Glass start = ll_entry_start(struct pci_driver_entry, pci_driver_entry); 482aba92962SSimon Glass n_ents = ll_entry_count(struct pci_driver_entry, pci_driver_entry); 483aba92962SSimon Glass for (entry = start; entry != start + n_ents; entry++) { 484aba92962SSimon Glass const struct pci_device_id *id; 485aba92962SSimon Glass struct udevice *dev; 486aba92962SSimon Glass const struct driver *drv; 487aba92962SSimon Glass 488aba92962SSimon Glass for (id = entry->match; 489aba92962SSimon Glass id->vendor || id->subvendor || id->class_mask; 490aba92962SSimon Glass id++) { 491aba92962SSimon Glass if (!pci_match_one_id(id, find_id)) 492aba92962SSimon Glass continue; 493aba92962SSimon Glass 494aba92962SSimon Glass drv = entry->driver; 49508fc7b8fSBin Meng 49608fc7b8fSBin Meng /* 49708fc7b8fSBin Meng * In the pre-relocation phase, we only bind devices 49808fc7b8fSBin Meng * whose driver has the DM_FLAG_PRE_RELOC set, to save 49908fc7b8fSBin Meng * precious memory space as on some platforms as that 50008fc7b8fSBin Meng * space is pretty limited (ie: using Cache As RAM). 50108fc7b8fSBin Meng */ 50208fc7b8fSBin Meng if (!(gd->flags & GD_FLG_RELOC) && 50308fc7b8fSBin Meng !(drv->flags & DM_FLAG_PRE_RELOC)) 5045dbcf3a0SSimon Glass return -EPERM; 50508fc7b8fSBin Meng 506aba92962SSimon Glass /* 507aba92962SSimon Glass * We could pass the descriptor to the driver as 508aba92962SSimon Glass * platdata (instead of NULL) and allow its bind() 509aba92962SSimon Glass * method to return -ENOENT if it doesn't support this 510aba92962SSimon Glass * device. That way we could continue the search to 511aba92962SSimon Glass * find another driver. For now this doesn't seem 512aba92962SSimon Glass * necesssary, so just bind the first match. 513aba92962SSimon Glass */ 514aba92962SSimon Glass ret = device_bind(parent, drv, drv->name, NULL, -1, 515aba92962SSimon Glass &dev); 516aba92962SSimon Glass if (ret) 517aba92962SSimon Glass goto error; 518aba92962SSimon Glass debug("%s: Match found: %s\n", __func__, drv->name); 519aba92962SSimon Glass dev->driver_data = find_id->driver_data; 520aba92962SSimon Glass *devp = dev; 521aba92962SSimon Glass return 0; 522aba92962SSimon Glass } 523aba92962SSimon Glass } 524aba92962SSimon Glass 52508fc7b8fSBin Meng bridge = (find_id->class >> 8) == PCI_CLASS_BRIDGE_PCI; 52608fc7b8fSBin Meng /* 52708fc7b8fSBin Meng * In the pre-relocation phase, we only bind bridge devices to save 52808fc7b8fSBin Meng * precious memory space as on some platforms as that space is pretty 52908fc7b8fSBin Meng * limited (ie: using Cache As RAM). 53008fc7b8fSBin Meng */ 53108fc7b8fSBin Meng if (!(gd->flags & GD_FLG_RELOC) && !bridge) 5325dbcf3a0SSimon Glass return -EPERM; 53308fc7b8fSBin Meng 534aba92962SSimon Glass /* Bind a generic driver so that the device can be used */ 5354d8615cbSBin Meng sprintf(name, "pci_%x:%x.%x", parent->seq, PCI_DEV(bdf), 5364d8615cbSBin Meng PCI_FUNC(bdf)); 537aba92962SSimon Glass str = strdup(name); 538aba92962SSimon Glass if (!str) 539aba92962SSimon Glass return -ENOMEM; 54008fc7b8fSBin Meng drv = bridge ? "pci_bridge_drv" : "pci_generic_drv"; 54108fc7b8fSBin Meng 542aba92962SSimon Glass ret = device_bind_driver(parent, drv, str, devp); 543aba92962SSimon Glass if (ret) { 5443129ace4SSimon Glass debug("%s: Failed to bind generic driver: %d\n", __func__, ret); 545aba92962SSimon Glass return ret; 546aba92962SSimon Glass } 547aba92962SSimon Glass debug("%s: No match found: bound generic driver instead\n", __func__); 548aba92962SSimon Glass 549aba92962SSimon Glass return 0; 550aba92962SSimon Glass 551aba92962SSimon Glass error: 552aba92962SSimon Glass debug("%s: No match found: error %d\n", __func__, ret); 553aba92962SSimon Glass return ret; 554aba92962SSimon Glass } 555aba92962SSimon Glass 556ff3e077bSSimon Glass int pci_bind_bus_devices(struct udevice *bus) 557ff3e077bSSimon Glass { 558ff3e077bSSimon Glass ulong vendor, device; 559ff3e077bSSimon Glass ulong header_type; 5604d8615cbSBin Meng pci_dev_t bdf, end; 561ff3e077bSSimon Glass bool found_multi; 562ff3e077bSSimon Glass int ret; 563ff3e077bSSimon Glass 564ff3e077bSSimon Glass found_multi = false; 5654d8615cbSBin Meng end = PCI_BDF(bus->seq, PCI_MAX_PCI_DEVICES - 1, 5664d8615cbSBin Meng PCI_MAX_PCI_FUNCTIONS - 1); 5674d8615cbSBin Meng for (bdf = PCI_BDF(bus->seq, 0, 0); bdf < end; 5684d8615cbSBin Meng bdf += PCI_BDF(0, 0, 1)) { 569ff3e077bSSimon Glass struct pci_child_platdata *pplat; 570ff3e077bSSimon Glass struct udevice *dev; 571ff3e077bSSimon Glass ulong class; 572ff3e077bSSimon Glass 5734d8615cbSBin Meng if (PCI_FUNC(bdf) && !found_multi) 574ff3e077bSSimon Glass continue; 575ff3e077bSSimon Glass /* Check only the first access, we don't expect problems */ 5764d8615cbSBin Meng ret = pci_bus_read_config(bus, bdf, PCI_HEADER_TYPE, 577ff3e077bSSimon Glass &header_type, PCI_SIZE_8); 578ff3e077bSSimon Glass if (ret) 579ff3e077bSSimon Glass goto error; 5804d8615cbSBin Meng pci_bus_read_config(bus, bdf, PCI_VENDOR_ID, &vendor, 581ff3e077bSSimon Glass PCI_SIZE_16); 582ff3e077bSSimon Glass if (vendor == 0xffff || vendor == 0x0000) 583ff3e077bSSimon Glass continue; 584ff3e077bSSimon Glass 5854d8615cbSBin Meng if (!PCI_FUNC(bdf)) 586ff3e077bSSimon Glass found_multi = header_type & 0x80; 587ff3e077bSSimon Glass 588ff3e077bSSimon Glass debug("%s: bus %d/%s: found device %x, function %d\n", __func__, 5894d8615cbSBin Meng bus->seq, bus->name, PCI_DEV(bdf), PCI_FUNC(bdf)); 5904d8615cbSBin Meng pci_bus_read_config(bus, bdf, PCI_DEVICE_ID, &device, 591ff3e077bSSimon Glass PCI_SIZE_16); 5924d8615cbSBin Meng pci_bus_read_config(bus, bdf, PCI_CLASS_REVISION, &class, 593aba92962SSimon Glass PCI_SIZE_32); 594aba92962SSimon Glass class >>= 8; 595ff3e077bSSimon Glass 596ff3e077bSSimon Glass /* Find this device in the device tree */ 5974d8615cbSBin Meng ret = pci_bus_find_devfn(bus, PCI_MASK_BUS(bdf), &dev); 598ff3e077bSSimon Glass 599aba92962SSimon Glass /* Search for a driver */ 600aba92962SSimon Glass 601ff3e077bSSimon Glass /* If nothing in the device tree, bind a generic device */ 602ff3e077bSSimon Glass if (ret == -ENODEV) { 603aba92962SSimon Glass struct pci_device_id find_id; 604aba92962SSimon Glass ulong val; 605ff3e077bSSimon Glass 606aba92962SSimon Glass memset(&find_id, '\0', sizeof(find_id)); 607aba92962SSimon Glass find_id.vendor = vendor; 608aba92962SSimon Glass find_id.device = device; 609aba92962SSimon Glass find_id.class = class; 610aba92962SSimon Glass if ((header_type & 0x7f) == PCI_HEADER_TYPE_NORMAL) { 6114d8615cbSBin Meng pci_bus_read_config(bus, bdf, 612aba92962SSimon Glass PCI_SUBSYSTEM_VENDOR_ID, 613aba92962SSimon Glass &val, PCI_SIZE_32); 614aba92962SSimon Glass find_id.subvendor = val & 0xffff; 615aba92962SSimon Glass find_id.subdevice = val >> 16; 616aba92962SSimon Glass } 6174d8615cbSBin Meng ret = pci_find_and_bind_driver(bus, &find_id, bdf, 618aba92962SSimon Glass &dev); 619ff3e077bSSimon Glass } 6205dbcf3a0SSimon Glass if (ret == -EPERM) 6215dbcf3a0SSimon Glass continue; 6225dbcf3a0SSimon Glass else if (ret) 623ff3e077bSSimon Glass return ret; 624ff3e077bSSimon Glass 625ff3e077bSSimon Glass /* Update the platform data */ 626ff3e077bSSimon Glass pplat = dev_get_parent_platdata(dev); 6274d8615cbSBin Meng pplat->devfn = PCI_MASK_BUS(bdf); 628ff3e077bSSimon Glass pplat->vendor = vendor; 629ff3e077bSSimon Glass pplat->device = device; 630ff3e077bSSimon Glass pplat->class = class; 631ff3e077bSSimon Glass } 632ff3e077bSSimon Glass 633ff3e077bSSimon Glass return 0; 634ff3e077bSSimon Glass error: 635ff3e077bSSimon Glass printf("Cannot read bus configuration: %d\n", ret); 636ff3e077bSSimon Glass 637ff3e077bSSimon Glass return ret; 638ff3e077bSSimon Glass } 639ff3e077bSSimon Glass 640ff3e077bSSimon Glass static int pci_uclass_post_bind(struct udevice *bus) 641ff3e077bSSimon Glass { 642ff3e077bSSimon Glass /* 6431887ed3aSBin Meng * If there is no pci device listed in the device tree, 6441887ed3aSBin Meng * don't bother scanning the device tree. 6451887ed3aSBin Meng */ 6461887ed3aSBin Meng if (bus->of_offset == -1) 6471887ed3aSBin Meng return 0; 6481887ed3aSBin Meng 6491887ed3aSBin Meng /* 650ff3e077bSSimon Glass * Scan the device tree for devices. This does not probe the PCI bus, 651ff3e077bSSimon Glass * as this is not permitted while binding. It just finds devices 652ff3e077bSSimon Glass * mentioned in the device tree. 653ff3e077bSSimon Glass * 654ff3e077bSSimon Glass * Before relocation, only bind devices marked for pre-relocation 655ff3e077bSSimon Glass * use. 656ff3e077bSSimon Glass */ 657ff3e077bSSimon Glass return dm_scan_fdt_node(bus, gd->fdt_blob, bus->of_offset, 658ff3e077bSSimon Glass gd->flags & GD_FLG_RELOC ? false : true); 659ff3e077bSSimon Glass } 660ff3e077bSSimon Glass 661ff3e077bSSimon Glass static int decode_regions(struct pci_controller *hose, const void *blob, 662ff3e077bSSimon Glass int parent_node, int node) 663ff3e077bSSimon Glass { 664ff3e077bSSimon Glass int pci_addr_cells, addr_cells, size_cells; 665ff3e077bSSimon Glass int cells_per_record; 666b9da5086SSimon Glass phys_addr_t addr; 667ff3e077bSSimon Glass const u32 *prop; 668ff3e077bSSimon Glass int len; 669ff3e077bSSimon Glass int i; 670ff3e077bSSimon Glass 671ff3e077bSSimon Glass prop = fdt_getprop(blob, node, "ranges", &len); 672ff3e077bSSimon Glass if (!prop) 673ff3e077bSSimon Glass return -EINVAL; 674ff3e077bSSimon Glass pci_addr_cells = fdt_address_cells(blob, node); 675ff3e077bSSimon Glass addr_cells = fdt_address_cells(blob, parent_node); 676ff3e077bSSimon Glass size_cells = fdt_size_cells(blob, node); 677ff3e077bSSimon Glass 678ff3e077bSSimon Glass /* PCI addresses are always 3-cells */ 679ff3e077bSSimon Glass len /= sizeof(u32); 680ff3e077bSSimon Glass cells_per_record = pci_addr_cells + addr_cells + size_cells; 681ff3e077bSSimon Glass hose->region_count = 0; 682ff3e077bSSimon Glass debug("%s: len=%d, cells_per_record=%d\n", __func__, len, 683ff3e077bSSimon Glass cells_per_record); 684ff3e077bSSimon Glass for (i = 0; i < MAX_PCI_REGIONS; i++, len -= cells_per_record) { 685ff3e077bSSimon Glass u64 pci_addr, addr, size; 686ff3e077bSSimon Glass int space_code; 687ff3e077bSSimon Glass u32 flags; 688ff3e077bSSimon Glass int type; 689ff3e077bSSimon Glass 690ff3e077bSSimon Glass if (len < cells_per_record) 691ff3e077bSSimon Glass break; 692ff3e077bSSimon Glass flags = fdt32_to_cpu(prop[0]); 693ff3e077bSSimon Glass space_code = (flags >> 24) & 3; 694ff3e077bSSimon Glass pci_addr = fdtdec_get_number(prop + 1, 2); 695ff3e077bSSimon Glass prop += pci_addr_cells; 696ff3e077bSSimon Glass addr = fdtdec_get_number(prop, addr_cells); 697ff3e077bSSimon Glass prop += addr_cells; 698ff3e077bSSimon Glass size = fdtdec_get_number(prop, size_cells); 699ff3e077bSSimon Glass prop += size_cells; 700ff3e077bSSimon Glass debug("%s: region %d, pci_addr=%" PRIx64 ", addr=%" PRIx64 701ff3e077bSSimon Glass ", size=%" PRIx64 ", space_code=%d\n", __func__, 702ff3e077bSSimon Glass hose->region_count, pci_addr, addr, size, space_code); 703ff3e077bSSimon Glass if (space_code & 2) { 704ff3e077bSSimon Glass type = flags & (1U << 30) ? PCI_REGION_PREFETCH : 705ff3e077bSSimon Glass PCI_REGION_MEM; 706ff3e077bSSimon Glass } else if (space_code & 1) { 707ff3e077bSSimon Glass type = PCI_REGION_IO; 708ff3e077bSSimon Glass } else { 709ff3e077bSSimon Glass continue; 710ff3e077bSSimon Glass } 711ff3e077bSSimon Glass debug(" - type=%d\n", type); 712ff3e077bSSimon Glass pci_set_region(hose->regions + hose->region_count++, pci_addr, 713ff3e077bSSimon Glass addr, size, type); 714ff3e077bSSimon Glass } 715ff3e077bSSimon Glass 716ff3e077bSSimon Glass /* Add a region for our local memory */ 717b9da5086SSimon Glass addr = gd->ram_size; 718b9da5086SSimon Glass if (gd->pci_ram_top && gd->pci_ram_top < addr) 719b9da5086SSimon Glass addr = gd->pci_ram_top; 720b9da5086SSimon Glass pci_set_region(hose->regions + hose->region_count++, 0, 0, addr, 721b9da5086SSimon Glass PCI_REGION_MEM | PCI_REGION_SYS_MEMORY); 722ff3e077bSSimon Glass 723ff3e077bSSimon Glass return 0; 724ff3e077bSSimon Glass } 725ff3e077bSSimon Glass 726ff3e077bSSimon Glass static int pci_uclass_pre_probe(struct udevice *bus) 727ff3e077bSSimon Glass { 728ff3e077bSSimon Glass struct pci_controller *hose; 729ff3e077bSSimon Glass int ret; 730ff3e077bSSimon Glass 731ff3e077bSSimon Glass debug("%s, bus=%d/%s, parent=%s\n", __func__, bus->seq, bus->name, 732ff3e077bSSimon Glass bus->parent->name); 733ff3e077bSSimon Glass hose = bus->uclass_priv; 734ff3e077bSSimon Glass 735ff3e077bSSimon Glass /* For bridges, use the top-level PCI controller */ 736ff3e077bSSimon Glass if (device_get_uclass_id(bus->parent) == UCLASS_ROOT) { 737ff3e077bSSimon Glass hose->ctlr = bus; 738ff3e077bSSimon Glass ret = decode_regions(hose, gd->fdt_blob, bus->parent->of_offset, 739ff3e077bSSimon Glass bus->of_offset); 740ff3e077bSSimon Glass if (ret) { 741ff3e077bSSimon Glass debug("%s: Cannot decode regions\n", __func__); 742ff3e077bSSimon Glass return ret; 743ff3e077bSSimon Glass } 744ff3e077bSSimon Glass } else { 745ff3e077bSSimon Glass struct pci_controller *parent_hose; 746ff3e077bSSimon Glass 747ff3e077bSSimon Glass parent_hose = dev_get_uclass_priv(bus->parent); 748ff3e077bSSimon Glass hose->ctlr = parent_hose->bus; 749ff3e077bSSimon Glass } 750ff3e077bSSimon Glass hose->bus = bus; 751ff3e077bSSimon Glass hose->first_busno = bus->seq; 752ff3e077bSSimon Glass hose->last_busno = bus->seq; 753ff3e077bSSimon Glass 754ff3e077bSSimon Glass return 0; 755ff3e077bSSimon Glass } 756ff3e077bSSimon Glass 757ff3e077bSSimon Glass static int pci_uclass_post_probe(struct udevice *bus) 758ff3e077bSSimon Glass { 759ff3e077bSSimon Glass int ret; 760ff3e077bSSimon Glass 761ff3e077bSSimon Glass debug("%s: probing bus %d\n", __func__, bus->seq); 762ff3e077bSSimon Glass ret = pci_bind_bus_devices(bus); 763ff3e077bSSimon Glass if (ret) 764ff3e077bSSimon Glass return ret; 765ff3e077bSSimon Glass 766ff3e077bSSimon Glass #ifdef CONFIG_PCI_PNP 767ff3e077bSSimon Glass ret = pci_auto_config_devices(bus); 7684d21455eSSimon Glass if (ret < 0) 7694d21455eSSimon Glass return ret; 770ff3e077bSSimon Glass #endif 771ff3e077bSSimon Glass 772348b744bSBin Meng #if defined(CONFIG_X86) && defined(CONFIG_HAVE_FSP) 773348b744bSBin Meng /* 774348b744bSBin Meng * Per Intel FSP specification, we should call FSP notify API to 775348b744bSBin Meng * inform FSP that PCI enumeration has been done so that FSP will 776348b744bSBin Meng * do any necessary initialization as required by the chipset's 777348b744bSBin Meng * BIOS Writer's Guide (BWG). 778348b744bSBin Meng * 779348b744bSBin Meng * Unfortunately we have to put this call here as with driver model, 780348b744bSBin Meng * the enumeration is all done on a lazy basis as needed, so until 781348b744bSBin Meng * something is touched on PCI it won't happen. 782348b744bSBin Meng * 783348b744bSBin Meng * Note we only call this 1) after U-Boot is relocated, and 2) 784348b744bSBin Meng * root bus has finished probing. 785348b744bSBin Meng */ 7864d21455eSSimon Glass if ((gd->flags & GD_FLG_RELOC) && (bus->seq == 0)) { 787348b744bSBin Meng ret = fsp_init_phase_pci(); 7884d21455eSSimon Glass if (ret) 7894d21455eSSimon Glass return ret; 7904d21455eSSimon Glass } 791348b744bSBin Meng #endif 792348b744bSBin Meng 7934d21455eSSimon Glass return 0; 794ff3e077bSSimon Glass } 795ff3e077bSSimon Glass 796ff3e077bSSimon Glass static int pci_uclass_child_post_bind(struct udevice *dev) 797ff3e077bSSimon Glass { 798ff3e077bSSimon Glass struct pci_child_platdata *pplat; 799ff3e077bSSimon Glass struct fdt_pci_addr addr; 800ff3e077bSSimon Glass int ret; 801ff3e077bSSimon Glass 802ff3e077bSSimon Glass if (dev->of_offset == -1) 803ff3e077bSSimon Glass return 0; 804ff3e077bSSimon Glass 805ff3e077bSSimon Glass /* 806ff3e077bSSimon Glass * We could read vendor, device, class if available. But for now we 807ff3e077bSSimon Glass * just check the address. 808ff3e077bSSimon Glass */ 809ff3e077bSSimon Glass pplat = dev_get_parent_platdata(dev); 810ff3e077bSSimon Glass ret = fdtdec_get_pci_addr(gd->fdt_blob, dev->of_offset, 811ff3e077bSSimon Glass FDT_PCI_SPACE_CONFIG, "reg", &addr); 812ff3e077bSSimon Glass 813ff3e077bSSimon Glass if (ret) { 814ff3e077bSSimon Glass if (ret != -ENOENT) 815ff3e077bSSimon Glass return -EINVAL; 816ff3e077bSSimon Glass } else { 817dce54dd6SBin Meng /* extract the devfn from fdt_pci_addr */ 818dce54dd6SBin Meng pplat->devfn = addr.phys_hi & 0xff00; 819ff3e077bSSimon Glass } 820ff3e077bSSimon Glass 821ff3e077bSSimon Glass return 0; 822ff3e077bSSimon Glass } 823ff3e077bSSimon Glass 8244d8615cbSBin Meng static int pci_bridge_read_config(struct udevice *bus, pci_dev_t bdf, 8254d8615cbSBin Meng uint offset, ulong *valuep, 8264d8615cbSBin Meng enum pci_size_t size) 827ff3e077bSSimon Glass { 828ff3e077bSSimon Glass struct pci_controller *hose = bus->uclass_priv; 829ff3e077bSSimon Glass 830ff3e077bSSimon Glass return pci_bus_read_config(hose->ctlr, bdf, offset, valuep, size); 831ff3e077bSSimon Glass } 832ff3e077bSSimon Glass 8334d8615cbSBin Meng static int pci_bridge_write_config(struct udevice *bus, pci_dev_t bdf, 8344d8615cbSBin Meng uint offset, ulong value, 8354d8615cbSBin Meng enum pci_size_t size) 836ff3e077bSSimon Glass { 837ff3e077bSSimon Glass struct pci_controller *hose = bus->uclass_priv; 838ff3e077bSSimon Glass 839ff3e077bSSimon Glass return pci_bus_write_config(hose->ctlr, bdf, offset, value, size); 840ff3e077bSSimon Glass } 841ff3e077bSSimon Glass 84276c3fbcdSSimon Glass static int skip_to_next_device(struct udevice *bus, struct udevice **devp) 84376c3fbcdSSimon Glass { 84476c3fbcdSSimon Glass struct udevice *dev; 84576c3fbcdSSimon Glass int ret = 0; 84676c3fbcdSSimon Glass 84776c3fbcdSSimon Glass /* 84876c3fbcdSSimon Glass * Scan through all the PCI controllers. On x86 there will only be one 84976c3fbcdSSimon Glass * but that is not necessarily true on other hardware. 85076c3fbcdSSimon Glass */ 85176c3fbcdSSimon Glass do { 85276c3fbcdSSimon Glass device_find_first_child(bus, &dev); 85376c3fbcdSSimon Glass if (dev) { 85476c3fbcdSSimon Glass *devp = dev; 85576c3fbcdSSimon Glass return 0; 85676c3fbcdSSimon Glass } 85776c3fbcdSSimon Glass ret = uclass_next_device(&bus); 85876c3fbcdSSimon Glass if (ret) 85976c3fbcdSSimon Glass return ret; 86076c3fbcdSSimon Glass } while (bus); 86176c3fbcdSSimon Glass 86276c3fbcdSSimon Glass return 0; 86376c3fbcdSSimon Glass } 86476c3fbcdSSimon Glass 86576c3fbcdSSimon Glass int pci_find_next_device(struct udevice **devp) 86676c3fbcdSSimon Glass { 86776c3fbcdSSimon Glass struct udevice *child = *devp; 86876c3fbcdSSimon Glass struct udevice *bus = child->parent; 86976c3fbcdSSimon Glass int ret; 87076c3fbcdSSimon Glass 87176c3fbcdSSimon Glass /* First try all the siblings */ 87276c3fbcdSSimon Glass *devp = NULL; 87376c3fbcdSSimon Glass while (child) { 87476c3fbcdSSimon Glass device_find_next_child(&child); 87576c3fbcdSSimon Glass if (child) { 87676c3fbcdSSimon Glass *devp = child; 87776c3fbcdSSimon Glass return 0; 87876c3fbcdSSimon Glass } 87976c3fbcdSSimon Glass } 88076c3fbcdSSimon Glass 88176c3fbcdSSimon Glass /* We ran out of siblings. Try the next bus */ 88276c3fbcdSSimon Glass ret = uclass_next_device(&bus); 88376c3fbcdSSimon Glass if (ret) 88476c3fbcdSSimon Glass return ret; 88576c3fbcdSSimon Glass 88676c3fbcdSSimon Glass return bus ? skip_to_next_device(bus, devp) : 0; 88776c3fbcdSSimon Glass } 88876c3fbcdSSimon Glass 88976c3fbcdSSimon Glass int pci_find_first_device(struct udevice **devp) 89076c3fbcdSSimon Glass { 89176c3fbcdSSimon Glass struct udevice *bus; 89276c3fbcdSSimon Glass int ret; 89376c3fbcdSSimon Glass 89476c3fbcdSSimon Glass *devp = NULL; 89576c3fbcdSSimon Glass ret = uclass_first_device(UCLASS_PCI, &bus); 89676c3fbcdSSimon Glass if (ret) 89776c3fbcdSSimon Glass return ret; 89876c3fbcdSSimon Glass 89976c3fbcdSSimon Glass return skip_to_next_device(bus, devp); 90076c3fbcdSSimon Glass } 90176c3fbcdSSimon Glass 902ff3e077bSSimon Glass UCLASS_DRIVER(pci) = { 903ff3e077bSSimon Glass .id = UCLASS_PCI, 904ff3e077bSSimon Glass .name = "pci", 9052bb02e4fSSimon Glass .flags = DM_UC_FLAG_SEQ_ALIAS, 906ff3e077bSSimon Glass .post_bind = pci_uclass_post_bind, 907ff3e077bSSimon Glass .pre_probe = pci_uclass_pre_probe, 908ff3e077bSSimon Glass .post_probe = pci_uclass_post_probe, 909ff3e077bSSimon Glass .child_post_bind = pci_uclass_child_post_bind, 910ff3e077bSSimon Glass .per_device_auto_alloc_size = sizeof(struct pci_controller), 911ff3e077bSSimon Glass .per_child_platdata_auto_alloc_size = 912ff3e077bSSimon Glass sizeof(struct pci_child_platdata), 913ff3e077bSSimon Glass }; 914ff3e077bSSimon Glass 915ff3e077bSSimon Glass static const struct dm_pci_ops pci_bridge_ops = { 916ff3e077bSSimon Glass .read_config = pci_bridge_read_config, 917ff3e077bSSimon Glass .write_config = pci_bridge_write_config, 918ff3e077bSSimon Glass }; 919ff3e077bSSimon Glass 920ff3e077bSSimon Glass static const struct udevice_id pci_bridge_ids[] = { 921ff3e077bSSimon Glass { .compatible = "pci-bridge" }, 922ff3e077bSSimon Glass { } 923ff3e077bSSimon Glass }; 924ff3e077bSSimon Glass 925ff3e077bSSimon Glass U_BOOT_DRIVER(pci_bridge_drv) = { 926ff3e077bSSimon Glass .name = "pci_bridge_drv", 927ff3e077bSSimon Glass .id = UCLASS_PCI, 928ff3e077bSSimon Glass .of_match = pci_bridge_ids, 929ff3e077bSSimon Glass .ops = &pci_bridge_ops, 930ff3e077bSSimon Glass }; 931ff3e077bSSimon Glass 932ff3e077bSSimon Glass UCLASS_DRIVER(pci_generic) = { 933ff3e077bSSimon Glass .id = UCLASS_PCI_GENERIC, 934ff3e077bSSimon Glass .name = "pci_generic", 935ff3e077bSSimon Glass }; 936ff3e077bSSimon Glass 937ff3e077bSSimon Glass static const struct udevice_id pci_generic_ids[] = { 938ff3e077bSSimon Glass { .compatible = "pci-generic" }, 939ff3e077bSSimon Glass { } 940ff3e077bSSimon Glass }; 941ff3e077bSSimon Glass 942ff3e077bSSimon Glass U_BOOT_DRIVER(pci_generic_drv) = { 943ff3e077bSSimon Glass .name = "pci_generic_drv", 944ff3e077bSSimon Glass .id = UCLASS_PCI_GENERIC, 945ff3e077bSSimon Glass .of_match = pci_generic_ids, 946ff3e077bSSimon Glass }; 947