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 569f60fb0dSSimon Glass struct udevice *pci_get_controller(struct udevice *dev) 579f60fb0dSSimon Glass { 589f60fb0dSSimon Glass while (device_is_on_pci_bus(dev)) 599f60fb0dSSimon Glass dev = dev->parent; 609f60fb0dSSimon Glass 619f60fb0dSSimon Glass return dev; 629f60fb0dSSimon Glass } 639f60fb0dSSimon Glass 6421ccce1bSSimon Glass pci_dev_t dm_pci_get_bdf(struct udevice *dev) 654b515e4fSSimon Glass { 664b515e4fSSimon Glass struct pci_child_platdata *pplat = dev_get_parent_platdata(dev); 674b515e4fSSimon Glass struct udevice *bus = dev->parent; 684b515e4fSSimon Glass 694b515e4fSSimon Glass return PCI_ADD_BUS(bus->seq, pplat->devfn); 704b515e4fSSimon Glass } 714b515e4fSSimon Glass 72ff3e077bSSimon Glass /** 73ff3e077bSSimon Glass * pci_get_bus_max() - returns the bus number of the last active bus 74ff3e077bSSimon Glass * 75ff3e077bSSimon Glass * @return last bus number, or -1 if no active buses 76ff3e077bSSimon Glass */ 77ff3e077bSSimon Glass static int pci_get_bus_max(void) 78ff3e077bSSimon Glass { 79ff3e077bSSimon Glass struct udevice *bus; 80ff3e077bSSimon Glass struct uclass *uc; 81ff3e077bSSimon Glass int ret = -1; 82ff3e077bSSimon Glass 83ff3e077bSSimon Glass ret = uclass_get(UCLASS_PCI, &uc); 84ff3e077bSSimon Glass uclass_foreach_dev(bus, uc) { 85ff3e077bSSimon Glass if (bus->seq > ret) 86ff3e077bSSimon Glass ret = bus->seq; 87ff3e077bSSimon Glass } 88ff3e077bSSimon Glass 89ff3e077bSSimon Glass debug("%s: ret=%d\n", __func__, ret); 90ff3e077bSSimon Glass 91ff3e077bSSimon Glass return ret; 92ff3e077bSSimon Glass } 93ff3e077bSSimon Glass 94ff3e077bSSimon Glass int pci_last_busno(void) 95ff3e077bSSimon Glass { 96069155cbSBin Meng return pci_get_bus_max(); 97ff3e077bSSimon Glass } 98ff3e077bSSimon Glass 99ff3e077bSSimon Glass int pci_get_ff(enum pci_size_t size) 100ff3e077bSSimon Glass { 101ff3e077bSSimon Glass switch (size) { 102ff3e077bSSimon Glass case PCI_SIZE_8: 103ff3e077bSSimon Glass return 0xff; 104ff3e077bSSimon Glass case PCI_SIZE_16: 105ff3e077bSSimon Glass return 0xffff; 106ff3e077bSSimon Glass default: 107ff3e077bSSimon Glass return 0xffffffff; 108ff3e077bSSimon Glass } 109ff3e077bSSimon Glass } 110ff3e077bSSimon Glass 111ff3e077bSSimon Glass int pci_bus_find_devfn(struct udevice *bus, pci_dev_t find_devfn, 112ff3e077bSSimon Glass struct udevice **devp) 113ff3e077bSSimon Glass { 114ff3e077bSSimon Glass struct udevice *dev; 115ff3e077bSSimon Glass 116ff3e077bSSimon Glass for (device_find_first_child(bus, &dev); 117ff3e077bSSimon Glass dev; 118ff3e077bSSimon Glass device_find_next_child(&dev)) { 119ff3e077bSSimon Glass struct pci_child_platdata *pplat; 120ff3e077bSSimon Glass 121ff3e077bSSimon Glass pplat = dev_get_parent_platdata(dev); 122ff3e077bSSimon Glass if (pplat && pplat->devfn == find_devfn) { 123ff3e077bSSimon Glass *devp = dev; 124ff3e077bSSimon Glass return 0; 125ff3e077bSSimon Glass } 126ff3e077bSSimon Glass } 127ff3e077bSSimon Glass 128ff3e077bSSimon Glass return -ENODEV; 129ff3e077bSSimon Glass } 130ff3e077bSSimon Glass 131*f3f1faefSSimon Glass int dm_pci_bus_find_bdf(pci_dev_t bdf, struct udevice **devp) 132ff3e077bSSimon Glass { 133ff3e077bSSimon Glass struct udevice *bus; 134ff3e077bSSimon Glass int ret; 135ff3e077bSSimon Glass 136983c6ba2SSimon Glass ret = pci_get_bus(PCI_BUS(bdf), &bus); 137ff3e077bSSimon Glass if (ret) 138ff3e077bSSimon Glass return ret; 139ff3e077bSSimon Glass return pci_bus_find_devfn(bus, PCI_MASK_BUS(bdf), devp); 140ff3e077bSSimon Glass } 141ff3e077bSSimon Glass 142ff3e077bSSimon Glass static int pci_device_matches_ids(struct udevice *dev, 143ff3e077bSSimon Glass struct pci_device_id *ids) 144ff3e077bSSimon Glass { 145ff3e077bSSimon Glass struct pci_child_platdata *pplat; 146ff3e077bSSimon Glass int i; 147ff3e077bSSimon Glass 148ff3e077bSSimon Glass pplat = dev_get_parent_platdata(dev); 149ff3e077bSSimon Glass if (!pplat) 150ff3e077bSSimon Glass return -EINVAL; 151ff3e077bSSimon Glass for (i = 0; ids[i].vendor != 0; i++) { 152ff3e077bSSimon Glass if (pplat->vendor == ids[i].vendor && 153ff3e077bSSimon Glass pplat->device == ids[i].device) 154ff3e077bSSimon Glass return i; 155ff3e077bSSimon Glass } 156ff3e077bSSimon Glass 157ff3e077bSSimon Glass return -EINVAL; 158ff3e077bSSimon Glass } 159ff3e077bSSimon Glass 160ff3e077bSSimon Glass int pci_bus_find_devices(struct udevice *bus, struct pci_device_id *ids, 161ff3e077bSSimon Glass int *indexp, struct udevice **devp) 162ff3e077bSSimon Glass { 163ff3e077bSSimon Glass struct udevice *dev; 164ff3e077bSSimon Glass 165ff3e077bSSimon Glass /* Scan all devices on this bus */ 166ff3e077bSSimon Glass for (device_find_first_child(bus, &dev); 167ff3e077bSSimon Glass dev; 168ff3e077bSSimon Glass device_find_next_child(&dev)) { 169ff3e077bSSimon Glass if (pci_device_matches_ids(dev, ids) >= 0) { 170ff3e077bSSimon Glass if ((*indexp)-- <= 0) { 171ff3e077bSSimon Glass *devp = dev; 172ff3e077bSSimon Glass return 0; 173ff3e077bSSimon Glass } 174ff3e077bSSimon Glass } 175ff3e077bSSimon Glass } 176ff3e077bSSimon Glass 177ff3e077bSSimon Glass return -ENODEV; 178ff3e077bSSimon Glass } 179ff3e077bSSimon Glass 180ff3e077bSSimon Glass int pci_find_device_id(struct pci_device_id *ids, int index, 181ff3e077bSSimon Glass struct udevice **devp) 182ff3e077bSSimon Glass { 183ff3e077bSSimon Glass struct udevice *bus; 184ff3e077bSSimon Glass 185ff3e077bSSimon Glass /* Scan all known buses */ 186ff3e077bSSimon Glass for (uclass_first_device(UCLASS_PCI, &bus); 187ff3e077bSSimon Glass bus; 188ff3e077bSSimon Glass uclass_next_device(&bus)) { 189ff3e077bSSimon Glass if (!pci_bus_find_devices(bus, ids, &index, devp)) 190ff3e077bSSimon Glass return 0; 191ff3e077bSSimon Glass } 192ff3e077bSSimon Glass *devp = NULL; 193ff3e077bSSimon Glass 194ff3e077bSSimon Glass return -ENODEV; 195ff3e077bSSimon Glass } 196ff3e077bSSimon Glass 197ff3e077bSSimon Glass int pci_bus_write_config(struct udevice *bus, pci_dev_t bdf, int offset, 198ff3e077bSSimon Glass unsigned long value, enum pci_size_t size) 199ff3e077bSSimon Glass { 200ff3e077bSSimon Glass struct dm_pci_ops *ops; 201ff3e077bSSimon Glass 202ff3e077bSSimon Glass ops = pci_get_ops(bus); 203ff3e077bSSimon Glass if (!ops->write_config) 204ff3e077bSSimon Glass return -ENOSYS; 205ff3e077bSSimon Glass return ops->write_config(bus, bdf, offset, value, size); 206ff3e077bSSimon Glass } 207ff3e077bSSimon Glass 208ff3e077bSSimon Glass int pci_write_config(pci_dev_t bdf, int offset, unsigned long value, 209ff3e077bSSimon Glass enum pci_size_t size) 210ff3e077bSSimon Glass { 211ff3e077bSSimon Glass struct udevice *bus; 212ff3e077bSSimon Glass int ret; 213ff3e077bSSimon Glass 214983c6ba2SSimon Glass ret = pci_get_bus(PCI_BUS(bdf), &bus); 215ff3e077bSSimon Glass if (ret) 216ff3e077bSSimon Glass return ret; 217ff3e077bSSimon Glass 2184d8615cbSBin Meng return pci_bus_write_config(bus, bdf, offset, value, size); 219ff3e077bSSimon Glass } 220ff3e077bSSimon Glass 22166afb4edSSimon Glass int dm_pci_write_config(struct udevice *dev, int offset, unsigned long value, 22266afb4edSSimon Glass enum pci_size_t size) 22366afb4edSSimon Glass { 22466afb4edSSimon Glass struct udevice *bus; 22566afb4edSSimon Glass 2261e0f2263SBin Meng for (bus = dev; device_is_on_pci_bus(bus);) 22766afb4edSSimon Glass bus = bus->parent; 22821ccce1bSSimon Glass return pci_bus_write_config(bus, dm_pci_get_bdf(dev), offset, value, 22921ccce1bSSimon Glass size); 23066afb4edSSimon Glass } 23166afb4edSSimon Glass 23266afb4edSSimon Glass 233ff3e077bSSimon Glass int pci_write_config32(pci_dev_t bdf, int offset, u32 value) 234ff3e077bSSimon Glass { 235ff3e077bSSimon Glass return pci_write_config(bdf, offset, value, PCI_SIZE_32); 236ff3e077bSSimon Glass } 237ff3e077bSSimon Glass 238ff3e077bSSimon Glass int pci_write_config16(pci_dev_t bdf, int offset, u16 value) 239ff3e077bSSimon Glass { 240ff3e077bSSimon Glass return pci_write_config(bdf, offset, value, PCI_SIZE_16); 241ff3e077bSSimon Glass } 242ff3e077bSSimon Glass 243ff3e077bSSimon Glass int pci_write_config8(pci_dev_t bdf, int offset, u8 value) 244ff3e077bSSimon Glass { 245ff3e077bSSimon Glass return pci_write_config(bdf, offset, value, PCI_SIZE_8); 246ff3e077bSSimon Glass } 247ff3e077bSSimon Glass 24866afb4edSSimon Glass int dm_pci_write_config8(struct udevice *dev, int offset, u8 value) 24966afb4edSSimon Glass { 25066afb4edSSimon Glass return dm_pci_write_config(dev, offset, value, PCI_SIZE_8); 25166afb4edSSimon Glass } 25266afb4edSSimon Glass 25366afb4edSSimon Glass int dm_pci_write_config16(struct udevice *dev, int offset, u16 value) 25466afb4edSSimon Glass { 25566afb4edSSimon Glass return dm_pci_write_config(dev, offset, value, PCI_SIZE_16); 25666afb4edSSimon Glass } 25766afb4edSSimon Glass 25866afb4edSSimon Glass int dm_pci_write_config32(struct udevice *dev, int offset, u32 value) 25966afb4edSSimon Glass { 26066afb4edSSimon Glass return dm_pci_write_config(dev, offset, value, PCI_SIZE_32); 26166afb4edSSimon Glass } 26266afb4edSSimon Glass 263ff3e077bSSimon Glass int pci_bus_read_config(struct udevice *bus, pci_dev_t bdf, int offset, 264ff3e077bSSimon Glass unsigned long *valuep, enum pci_size_t size) 265ff3e077bSSimon Glass { 266ff3e077bSSimon Glass struct dm_pci_ops *ops; 267ff3e077bSSimon Glass 268ff3e077bSSimon Glass ops = pci_get_ops(bus); 269ff3e077bSSimon Glass if (!ops->read_config) 270ff3e077bSSimon Glass return -ENOSYS; 271ff3e077bSSimon Glass return ops->read_config(bus, bdf, offset, valuep, size); 272ff3e077bSSimon Glass } 273ff3e077bSSimon Glass 274ff3e077bSSimon Glass int pci_read_config(pci_dev_t bdf, int offset, unsigned long *valuep, 275ff3e077bSSimon Glass enum pci_size_t size) 276ff3e077bSSimon Glass { 277ff3e077bSSimon Glass struct udevice *bus; 278ff3e077bSSimon Glass int ret; 279ff3e077bSSimon Glass 280983c6ba2SSimon Glass ret = pci_get_bus(PCI_BUS(bdf), &bus); 281ff3e077bSSimon Glass if (ret) 282ff3e077bSSimon Glass return ret; 283ff3e077bSSimon Glass 2844d8615cbSBin Meng return pci_bus_read_config(bus, bdf, offset, valuep, size); 285ff3e077bSSimon Glass } 286ff3e077bSSimon Glass 28766afb4edSSimon Glass int dm_pci_read_config(struct udevice *dev, int offset, unsigned long *valuep, 28866afb4edSSimon Glass enum pci_size_t size) 28966afb4edSSimon Glass { 29066afb4edSSimon Glass struct udevice *bus; 29166afb4edSSimon Glass 2921e0f2263SBin Meng for (bus = dev; device_is_on_pci_bus(bus);) 29366afb4edSSimon Glass bus = bus->parent; 29421ccce1bSSimon Glass return pci_bus_read_config(bus, dm_pci_get_bdf(dev), offset, valuep, 29566afb4edSSimon Glass size); 29666afb4edSSimon Glass } 29766afb4edSSimon Glass 298ff3e077bSSimon Glass int pci_read_config32(pci_dev_t bdf, int offset, u32 *valuep) 299ff3e077bSSimon Glass { 300ff3e077bSSimon Glass unsigned long value; 301ff3e077bSSimon Glass int ret; 302ff3e077bSSimon Glass 303ff3e077bSSimon Glass ret = pci_read_config(bdf, offset, &value, PCI_SIZE_32); 304ff3e077bSSimon Glass if (ret) 305ff3e077bSSimon Glass return ret; 306ff3e077bSSimon Glass *valuep = value; 307ff3e077bSSimon Glass 308ff3e077bSSimon Glass return 0; 309ff3e077bSSimon Glass } 310ff3e077bSSimon Glass 311ff3e077bSSimon Glass int pci_read_config16(pci_dev_t bdf, int offset, u16 *valuep) 312ff3e077bSSimon Glass { 313ff3e077bSSimon Glass unsigned long value; 314ff3e077bSSimon Glass int ret; 315ff3e077bSSimon Glass 316ff3e077bSSimon Glass ret = pci_read_config(bdf, offset, &value, PCI_SIZE_16); 317ff3e077bSSimon Glass if (ret) 318ff3e077bSSimon Glass return ret; 319ff3e077bSSimon Glass *valuep = value; 320ff3e077bSSimon Glass 321ff3e077bSSimon Glass return 0; 322ff3e077bSSimon Glass } 323ff3e077bSSimon Glass 324ff3e077bSSimon Glass int pci_read_config8(pci_dev_t bdf, int offset, u8 *valuep) 325ff3e077bSSimon Glass { 326ff3e077bSSimon Glass unsigned long value; 327ff3e077bSSimon Glass int ret; 328ff3e077bSSimon Glass 329ff3e077bSSimon Glass ret = pci_read_config(bdf, offset, &value, PCI_SIZE_8); 330ff3e077bSSimon Glass if (ret) 331ff3e077bSSimon Glass return ret; 332ff3e077bSSimon Glass *valuep = value; 333ff3e077bSSimon Glass 334ff3e077bSSimon Glass return 0; 335ff3e077bSSimon Glass } 336ff3e077bSSimon Glass 33766afb4edSSimon Glass int dm_pci_read_config8(struct udevice *dev, int offset, u8 *valuep) 33866afb4edSSimon Glass { 33966afb4edSSimon Glass unsigned long value; 34066afb4edSSimon Glass int ret; 34166afb4edSSimon Glass 34266afb4edSSimon Glass ret = dm_pci_read_config(dev, offset, &value, PCI_SIZE_8); 34366afb4edSSimon Glass if (ret) 34466afb4edSSimon Glass return ret; 34566afb4edSSimon Glass *valuep = value; 34666afb4edSSimon Glass 34766afb4edSSimon Glass return 0; 34866afb4edSSimon Glass } 34966afb4edSSimon Glass 35066afb4edSSimon Glass int dm_pci_read_config16(struct udevice *dev, int offset, u16 *valuep) 35166afb4edSSimon Glass { 35266afb4edSSimon Glass unsigned long value; 35366afb4edSSimon Glass int ret; 35466afb4edSSimon Glass 35566afb4edSSimon Glass ret = dm_pci_read_config(dev, offset, &value, PCI_SIZE_16); 35666afb4edSSimon Glass if (ret) 35766afb4edSSimon Glass return ret; 35866afb4edSSimon Glass *valuep = value; 35966afb4edSSimon Glass 36066afb4edSSimon Glass return 0; 36166afb4edSSimon Glass } 36266afb4edSSimon Glass 36366afb4edSSimon Glass int dm_pci_read_config32(struct udevice *dev, int offset, u32 *valuep) 36466afb4edSSimon Glass { 36566afb4edSSimon Glass unsigned long value; 36666afb4edSSimon Glass int ret; 36766afb4edSSimon Glass 36866afb4edSSimon Glass ret = dm_pci_read_config(dev, offset, &value, PCI_SIZE_32); 36966afb4edSSimon Glass if (ret) 37066afb4edSSimon Glass return ret; 37166afb4edSSimon Glass *valuep = value; 37266afb4edSSimon Glass 37366afb4edSSimon Glass return 0; 37466afb4edSSimon Glass } 37566afb4edSSimon Glass 376bbbcb526SBin Meng static void set_vga_bridge_bits(struct udevice *dev) 377bbbcb526SBin Meng { 378bbbcb526SBin Meng struct udevice *parent = dev->parent; 379bbbcb526SBin Meng u16 bc; 380bbbcb526SBin Meng 381bbbcb526SBin Meng while (parent->seq != 0) { 382bbbcb526SBin Meng dm_pci_read_config16(parent, PCI_BRIDGE_CONTROL, &bc); 383bbbcb526SBin Meng bc |= PCI_BRIDGE_CTL_VGA; 384bbbcb526SBin Meng dm_pci_write_config16(parent, PCI_BRIDGE_CONTROL, bc); 385bbbcb526SBin Meng parent = parent->parent; 386bbbcb526SBin Meng } 387bbbcb526SBin Meng } 388bbbcb526SBin Meng 389ff3e077bSSimon Glass int pci_auto_config_devices(struct udevice *bus) 390ff3e077bSSimon Glass { 391ff3e077bSSimon Glass struct pci_controller *hose = bus->uclass_priv; 392bbbcb526SBin Meng struct pci_child_platdata *pplat; 393ff3e077bSSimon Glass unsigned int sub_bus; 394ff3e077bSSimon Glass struct udevice *dev; 395ff3e077bSSimon Glass int ret; 396ff3e077bSSimon Glass 397ff3e077bSSimon Glass sub_bus = bus->seq; 398ff3e077bSSimon Glass debug("%s: start\n", __func__); 399ff3e077bSSimon Glass pciauto_config_init(hose); 400ff3e077bSSimon Glass for (ret = device_find_first_child(bus, &dev); 401ff3e077bSSimon Glass !ret && dev; 402ff3e077bSSimon Glass ret = device_find_next_child(&dev)) { 403ff3e077bSSimon Glass unsigned int max_bus; 4044d21455eSSimon Glass int ret; 405ff3e077bSSimon Glass 406ff3e077bSSimon Glass debug("%s: device %s\n", __func__, dev->name); 40721ccce1bSSimon Glass ret = pciauto_config_device(hose, dm_pci_get_bdf(dev)); 4084d21455eSSimon Glass if (ret < 0) 4094d21455eSSimon Glass return ret; 4104d21455eSSimon Glass max_bus = ret; 411ff3e077bSSimon Glass sub_bus = max(sub_bus, max_bus); 412bbbcb526SBin Meng 413bbbcb526SBin Meng pplat = dev_get_parent_platdata(dev); 414bbbcb526SBin Meng if (pplat->class == (PCI_CLASS_DISPLAY_VGA << 8)) 415bbbcb526SBin Meng set_vga_bridge_bits(dev); 416ff3e077bSSimon Glass } 417ff3e077bSSimon Glass debug("%s: done\n", __func__); 418ff3e077bSSimon Glass 419ff3e077bSSimon Glass return sub_bus; 420ff3e077bSSimon Glass } 421ff3e077bSSimon Glass 422ff3e077bSSimon Glass int dm_pci_hose_probe_bus(struct pci_controller *hose, pci_dev_t bdf) 423ff3e077bSSimon Glass { 424ff3e077bSSimon Glass struct udevice *parent, *bus; 425ff3e077bSSimon Glass int sub_bus; 426ff3e077bSSimon Glass int ret; 427ff3e077bSSimon Glass 428ff3e077bSSimon Glass debug("%s\n", __func__); 429ff3e077bSSimon Glass parent = hose->bus; 430ff3e077bSSimon Glass 431ff3e077bSSimon Glass /* Find the bus within the parent */ 4328326f136SBin Meng ret = pci_bus_find_devfn(parent, PCI_MASK_BUS(bdf), &bus); 433ff3e077bSSimon Glass if (ret) { 434ff3e077bSSimon Glass debug("%s: Cannot find device %x on bus %s: %d\n", __func__, 435ff3e077bSSimon Glass bdf, parent->name, ret); 436ff3e077bSSimon Glass return ret; 437ff3e077bSSimon Glass } 438ff3e077bSSimon Glass 439ff3e077bSSimon Glass sub_bus = pci_get_bus_max() + 1; 440ff3e077bSSimon Glass debug("%s: bus = %d/%s\n", __func__, sub_bus, bus->name); 4415afeb4bbSSimon Glass pciauto_prescan_setup_bridge(hose, bdf, sub_bus); 442ff3e077bSSimon Glass 443ff3e077bSSimon Glass ret = device_probe(bus); 444ff3e077bSSimon Glass if (ret) { 4453129ace4SSimon Glass debug("%s: Cannot probe bus %s: %d\n", __func__, bus->name, 446ff3e077bSSimon Glass ret); 447ff3e077bSSimon Glass return ret; 448ff3e077bSSimon Glass } 449ff3e077bSSimon Glass if (sub_bus != bus->seq) { 450ff3e077bSSimon Glass printf("%s: Internal error, bus '%s' got seq %d, expected %d\n", 451ff3e077bSSimon Glass __func__, bus->name, bus->seq, sub_bus); 452ff3e077bSSimon Glass return -EPIPE; 453ff3e077bSSimon Glass } 454ff3e077bSSimon Glass sub_bus = pci_get_bus_max(); 455ff3e077bSSimon Glass pciauto_postscan_setup_bridge(hose, bdf, sub_bus); 456ff3e077bSSimon Glass 457ff3e077bSSimon Glass return sub_bus; 458ff3e077bSSimon Glass } 459ff3e077bSSimon Glass 460aba92962SSimon Glass /** 461aba92962SSimon Glass * pci_match_one_device - Tell if a PCI device structure has a matching 462aba92962SSimon Glass * PCI device id structure 463aba92962SSimon Glass * @id: single PCI device id structure to match 464aba92962SSimon Glass * @dev: the PCI device structure to match against 465aba92962SSimon Glass * 466aba92962SSimon Glass * Returns the matching pci_device_id structure or %NULL if there is no match. 467aba92962SSimon Glass */ 468aba92962SSimon Glass static bool pci_match_one_id(const struct pci_device_id *id, 469aba92962SSimon Glass const struct pci_device_id *find) 470aba92962SSimon Glass { 471aba92962SSimon Glass if ((id->vendor == PCI_ANY_ID || id->vendor == find->vendor) && 472aba92962SSimon Glass (id->device == PCI_ANY_ID || id->device == find->device) && 473aba92962SSimon Glass (id->subvendor == PCI_ANY_ID || id->subvendor == find->subvendor) && 474aba92962SSimon Glass (id->subdevice == PCI_ANY_ID || id->subdevice == find->subdevice) && 475aba92962SSimon Glass !((id->class ^ find->class) & id->class_mask)) 476aba92962SSimon Glass return true; 477aba92962SSimon Glass 478aba92962SSimon Glass return false; 479aba92962SSimon Glass } 480aba92962SSimon Glass 481aba92962SSimon Glass /** 482aba92962SSimon Glass * pci_find_and_bind_driver() - Find and bind the right PCI driver 483aba92962SSimon Glass * 484aba92962SSimon Glass * This only looks at certain fields in the descriptor. 4855dbcf3a0SSimon Glass * 4865dbcf3a0SSimon Glass * @parent: Parent bus 4875dbcf3a0SSimon Glass * @find_id: Specification of the driver to find 4885dbcf3a0SSimon Glass * @bdf: Bus/device/function addreess - see PCI_BDF() 4895dbcf3a0SSimon Glass * @devp: Returns a pointer to the device created 4905dbcf3a0SSimon Glass * @return 0 if OK, -EPERM if the device is not needed before relocation and 4915dbcf3a0SSimon Glass * therefore was not created, other -ve value on error 492aba92962SSimon Glass */ 493aba92962SSimon Glass static int pci_find_and_bind_driver(struct udevice *parent, 4945dbcf3a0SSimon Glass struct pci_device_id *find_id, 4955dbcf3a0SSimon Glass pci_dev_t bdf, struct udevice **devp) 496aba92962SSimon Glass { 497aba92962SSimon Glass struct pci_driver_entry *start, *entry; 498aba92962SSimon Glass const char *drv; 499aba92962SSimon Glass int n_ents; 500aba92962SSimon Glass int ret; 501aba92962SSimon Glass char name[30], *str; 50208fc7b8fSBin Meng bool bridge; 503aba92962SSimon Glass 504aba92962SSimon Glass *devp = NULL; 505aba92962SSimon Glass 506aba92962SSimon Glass debug("%s: Searching for driver: vendor=%x, device=%x\n", __func__, 507aba92962SSimon Glass find_id->vendor, find_id->device); 508aba92962SSimon Glass start = ll_entry_start(struct pci_driver_entry, pci_driver_entry); 509aba92962SSimon Glass n_ents = ll_entry_count(struct pci_driver_entry, pci_driver_entry); 510aba92962SSimon Glass for (entry = start; entry != start + n_ents; entry++) { 511aba92962SSimon Glass const struct pci_device_id *id; 512aba92962SSimon Glass struct udevice *dev; 513aba92962SSimon Glass const struct driver *drv; 514aba92962SSimon Glass 515aba92962SSimon Glass for (id = entry->match; 516aba92962SSimon Glass id->vendor || id->subvendor || id->class_mask; 517aba92962SSimon Glass id++) { 518aba92962SSimon Glass if (!pci_match_one_id(id, find_id)) 519aba92962SSimon Glass continue; 520aba92962SSimon Glass 521aba92962SSimon Glass drv = entry->driver; 52208fc7b8fSBin Meng 52308fc7b8fSBin Meng /* 52408fc7b8fSBin Meng * In the pre-relocation phase, we only bind devices 52508fc7b8fSBin Meng * whose driver has the DM_FLAG_PRE_RELOC set, to save 52608fc7b8fSBin Meng * precious memory space as on some platforms as that 52708fc7b8fSBin Meng * space is pretty limited (ie: using Cache As RAM). 52808fc7b8fSBin Meng */ 52908fc7b8fSBin Meng if (!(gd->flags & GD_FLG_RELOC) && 53008fc7b8fSBin Meng !(drv->flags & DM_FLAG_PRE_RELOC)) 5315dbcf3a0SSimon Glass return -EPERM; 53208fc7b8fSBin Meng 533aba92962SSimon Glass /* 534aba92962SSimon Glass * We could pass the descriptor to the driver as 535aba92962SSimon Glass * platdata (instead of NULL) and allow its bind() 536aba92962SSimon Glass * method to return -ENOENT if it doesn't support this 537aba92962SSimon Glass * device. That way we could continue the search to 538aba92962SSimon Glass * find another driver. For now this doesn't seem 539aba92962SSimon Glass * necesssary, so just bind the first match. 540aba92962SSimon Glass */ 541aba92962SSimon Glass ret = device_bind(parent, drv, drv->name, NULL, -1, 542aba92962SSimon Glass &dev); 543aba92962SSimon Glass if (ret) 544aba92962SSimon Glass goto error; 545aba92962SSimon Glass debug("%s: Match found: %s\n", __func__, drv->name); 546aba92962SSimon Glass dev->driver_data = find_id->driver_data; 547aba92962SSimon Glass *devp = dev; 548aba92962SSimon Glass return 0; 549aba92962SSimon Glass } 550aba92962SSimon Glass } 551aba92962SSimon Glass 55208fc7b8fSBin Meng bridge = (find_id->class >> 8) == PCI_CLASS_BRIDGE_PCI; 55308fc7b8fSBin Meng /* 55408fc7b8fSBin Meng * In the pre-relocation phase, we only bind bridge devices to save 55508fc7b8fSBin Meng * precious memory space as on some platforms as that space is pretty 55608fc7b8fSBin Meng * limited (ie: using Cache As RAM). 55708fc7b8fSBin Meng */ 55808fc7b8fSBin Meng if (!(gd->flags & GD_FLG_RELOC) && !bridge) 5595dbcf3a0SSimon Glass return -EPERM; 56008fc7b8fSBin Meng 561aba92962SSimon Glass /* Bind a generic driver so that the device can be used */ 5624d8615cbSBin Meng sprintf(name, "pci_%x:%x.%x", parent->seq, PCI_DEV(bdf), 5634d8615cbSBin Meng PCI_FUNC(bdf)); 564aba92962SSimon Glass str = strdup(name); 565aba92962SSimon Glass if (!str) 566aba92962SSimon Glass return -ENOMEM; 56708fc7b8fSBin Meng drv = bridge ? "pci_bridge_drv" : "pci_generic_drv"; 56808fc7b8fSBin Meng 569aba92962SSimon Glass ret = device_bind_driver(parent, drv, str, devp); 570aba92962SSimon Glass if (ret) { 5713129ace4SSimon Glass debug("%s: Failed to bind generic driver: %d\n", __func__, ret); 572aba92962SSimon Glass return ret; 573aba92962SSimon Glass } 574aba92962SSimon Glass debug("%s: No match found: bound generic driver instead\n", __func__); 575aba92962SSimon Glass 576aba92962SSimon Glass return 0; 577aba92962SSimon Glass 578aba92962SSimon Glass error: 579aba92962SSimon Glass debug("%s: No match found: error %d\n", __func__, ret); 580aba92962SSimon Glass return ret; 581aba92962SSimon Glass } 582aba92962SSimon Glass 583ff3e077bSSimon Glass int pci_bind_bus_devices(struct udevice *bus) 584ff3e077bSSimon Glass { 585ff3e077bSSimon Glass ulong vendor, device; 586ff3e077bSSimon Glass ulong header_type; 5874d8615cbSBin Meng pci_dev_t bdf, end; 588ff3e077bSSimon Glass bool found_multi; 589ff3e077bSSimon Glass int ret; 590ff3e077bSSimon Glass 591ff3e077bSSimon Glass found_multi = false; 5924d8615cbSBin Meng end = PCI_BDF(bus->seq, PCI_MAX_PCI_DEVICES - 1, 5934d8615cbSBin Meng PCI_MAX_PCI_FUNCTIONS - 1); 5944d8615cbSBin Meng for (bdf = PCI_BDF(bus->seq, 0, 0); bdf < end; 5954d8615cbSBin Meng bdf += PCI_BDF(0, 0, 1)) { 596ff3e077bSSimon Glass struct pci_child_platdata *pplat; 597ff3e077bSSimon Glass struct udevice *dev; 598ff3e077bSSimon Glass ulong class; 599ff3e077bSSimon Glass 6004d8615cbSBin Meng if (PCI_FUNC(bdf) && !found_multi) 601ff3e077bSSimon Glass continue; 602ff3e077bSSimon Glass /* Check only the first access, we don't expect problems */ 6034d8615cbSBin Meng ret = pci_bus_read_config(bus, bdf, PCI_HEADER_TYPE, 604ff3e077bSSimon Glass &header_type, PCI_SIZE_8); 605ff3e077bSSimon Glass if (ret) 606ff3e077bSSimon Glass goto error; 6074d8615cbSBin Meng pci_bus_read_config(bus, bdf, PCI_VENDOR_ID, &vendor, 608ff3e077bSSimon Glass PCI_SIZE_16); 609ff3e077bSSimon Glass if (vendor == 0xffff || vendor == 0x0000) 610ff3e077bSSimon Glass continue; 611ff3e077bSSimon Glass 6124d8615cbSBin Meng if (!PCI_FUNC(bdf)) 613ff3e077bSSimon Glass found_multi = header_type & 0x80; 614ff3e077bSSimon Glass 615ff3e077bSSimon Glass debug("%s: bus %d/%s: found device %x, function %d\n", __func__, 6164d8615cbSBin Meng bus->seq, bus->name, PCI_DEV(bdf), PCI_FUNC(bdf)); 6174d8615cbSBin Meng pci_bus_read_config(bus, bdf, PCI_DEVICE_ID, &device, 618ff3e077bSSimon Glass PCI_SIZE_16); 6194d8615cbSBin Meng pci_bus_read_config(bus, bdf, PCI_CLASS_REVISION, &class, 620aba92962SSimon Glass PCI_SIZE_32); 621aba92962SSimon Glass class >>= 8; 622ff3e077bSSimon Glass 623ff3e077bSSimon Glass /* Find this device in the device tree */ 6244d8615cbSBin Meng ret = pci_bus_find_devfn(bus, PCI_MASK_BUS(bdf), &dev); 625ff3e077bSSimon Glass 626aba92962SSimon Glass /* Search for a driver */ 627aba92962SSimon Glass 628ff3e077bSSimon Glass /* If nothing in the device tree, bind a generic device */ 629ff3e077bSSimon Glass if (ret == -ENODEV) { 630aba92962SSimon Glass struct pci_device_id find_id; 631aba92962SSimon Glass ulong val; 632ff3e077bSSimon Glass 633aba92962SSimon Glass memset(&find_id, '\0', sizeof(find_id)); 634aba92962SSimon Glass find_id.vendor = vendor; 635aba92962SSimon Glass find_id.device = device; 636aba92962SSimon Glass find_id.class = class; 637aba92962SSimon Glass if ((header_type & 0x7f) == PCI_HEADER_TYPE_NORMAL) { 6384d8615cbSBin Meng pci_bus_read_config(bus, bdf, 639aba92962SSimon Glass PCI_SUBSYSTEM_VENDOR_ID, 640aba92962SSimon Glass &val, PCI_SIZE_32); 641aba92962SSimon Glass find_id.subvendor = val & 0xffff; 642aba92962SSimon Glass find_id.subdevice = val >> 16; 643aba92962SSimon Glass } 6444d8615cbSBin Meng ret = pci_find_and_bind_driver(bus, &find_id, bdf, 645aba92962SSimon Glass &dev); 646ff3e077bSSimon Glass } 6475dbcf3a0SSimon Glass if (ret == -EPERM) 6485dbcf3a0SSimon Glass continue; 6495dbcf3a0SSimon Glass else if (ret) 650ff3e077bSSimon Glass return ret; 651ff3e077bSSimon Glass 652ff3e077bSSimon Glass /* Update the platform data */ 653ff3e077bSSimon Glass pplat = dev_get_parent_platdata(dev); 6544d8615cbSBin Meng pplat->devfn = PCI_MASK_BUS(bdf); 655ff3e077bSSimon Glass pplat->vendor = vendor; 656ff3e077bSSimon Glass pplat->device = device; 657ff3e077bSSimon Glass pplat->class = class; 658ff3e077bSSimon Glass } 659ff3e077bSSimon Glass 660ff3e077bSSimon Glass return 0; 661ff3e077bSSimon Glass error: 662ff3e077bSSimon Glass printf("Cannot read bus configuration: %d\n", ret); 663ff3e077bSSimon Glass 664ff3e077bSSimon Glass return ret; 665ff3e077bSSimon Glass } 666ff3e077bSSimon Glass 667ff3e077bSSimon Glass static int pci_uclass_post_bind(struct udevice *bus) 668ff3e077bSSimon Glass { 669ff3e077bSSimon Glass /* 6701887ed3aSBin Meng * If there is no pci device listed in the device tree, 6711887ed3aSBin Meng * don't bother scanning the device tree. 6721887ed3aSBin Meng */ 6731887ed3aSBin Meng if (bus->of_offset == -1) 6741887ed3aSBin Meng return 0; 6751887ed3aSBin Meng 6761887ed3aSBin Meng /* 677ff3e077bSSimon Glass * Scan the device tree for devices. This does not probe the PCI bus, 678ff3e077bSSimon Glass * as this is not permitted while binding. It just finds devices 679ff3e077bSSimon Glass * mentioned in the device tree. 680ff3e077bSSimon Glass * 681ff3e077bSSimon Glass * Before relocation, only bind devices marked for pre-relocation 682ff3e077bSSimon Glass * use. 683ff3e077bSSimon Glass */ 684ff3e077bSSimon Glass return dm_scan_fdt_node(bus, gd->fdt_blob, bus->of_offset, 685ff3e077bSSimon Glass gd->flags & GD_FLG_RELOC ? false : true); 686ff3e077bSSimon Glass } 687ff3e077bSSimon Glass 688ff3e077bSSimon Glass static int decode_regions(struct pci_controller *hose, const void *blob, 689ff3e077bSSimon Glass int parent_node, int node) 690ff3e077bSSimon Glass { 691ff3e077bSSimon Glass int pci_addr_cells, addr_cells, size_cells; 6922084c5afSSimon Glass phys_addr_t base = 0, size; 693ff3e077bSSimon Glass int cells_per_record; 694ff3e077bSSimon Glass const u32 *prop; 695ff3e077bSSimon Glass int len; 696ff3e077bSSimon Glass int i; 697ff3e077bSSimon Glass 698ff3e077bSSimon Glass prop = fdt_getprop(blob, node, "ranges", &len); 699ff3e077bSSimon Glass if (!prop) 700ff3e077bSSimon Glass return -EINVAL; 701ff3e077bSSimon Glass pci_addr_cells = fdt_address_cells(blob, node); 702ff3e077bSSimon Glass addr_cells = fdt_address_cells(blob, parent_node); 703ff3e077bSSimon Glass size_cells = fdt_size_cells(blob, node); 704ff3e077bSSimon Glass 705ff3e077bSSimon Glass /* PCI addresses are always 3-cells */ 706ff3e077bSSimon Glass len /= sizeof(u32); 707ff3e077bSSimon Glass cells_per_record = pci_addr_cells + addr_cells + size_cells; 708ff3e077bSSimon Glass hose->region_count = 0; 709ff3e077bSSimon Glass debug("%s: len=%d, cells_per_record=%d\n", __func__, len, 710ff3e077bSSimon Glass cells_per_record); 711ff3e077bSSimon Glass for (i = 0; i < MAX_PCI_REGIONS; i++, len -= cells_per_record) { 712ff3e077bSSimon Glass u64 pci_addr, addr, size; 713ff3e077bSSimon Glass int space_code; 714ff3e077bSSimon Glass u32 flags; 715ff3e077bSSimon Glass int type; 7169526d83aSSimon Glass int pos; 717ff3e077bSSimon Glass 718ff3e077bSSimon Glass if (len < cells_per_record) 719ff3e077bSSimon Glass break; 720ff3e077bSSimon Glass flags = fdt32_to_cpu(prop[0]); 721ff3e077bSSimon Glass space_code = (flags >> 24) & 3; 722ff3e077bSSimon Glass pci_addr = fdtdec_get_number(prop + 1, 2); 723ff3e077bSSimon Glass prop += pci_addr_cells; 724ff3e077bSSimon Glass addr = fdtdec_get_number(prop, addr_cells); 725ff3e077bSSimon Glass prop += addr_cells; 726ff3e077bSSimon Glass size = fdtdec_get_number(prop, size_cells); 727ff3e077bSSimon Glass prop += size_cells; 728ff3e077bSSimon Glass debug("%s: region %d, pci_addr=%" PRIx64 ", addr=%" PRIx64 729ff3e077bSSimon Glass ", size=%" PRIx64 ", space_code=%d\n", __func__, 730ff3e077bSSimon Glass hose->region_count, pci_addr, addr, size, space_code); 731ff3e077bSSimon Glass if (space_code & 2) { 732ff3e077bSSimon Glass type = flags & (1U << 30) ? PCI_REGION_PREFETCH : 733ff3e077bSSimon Glass PCI_REGION_MEM; 734ff3e077bSSimon Glass } else if (space_code & 1) { 735ff3e077bSSimon Glass type = PCI_REGION_IO; 736ff3e077bSSimon Glass } else { 737ff3e077bSSimon Glass continue; 738ff3e077bSSimon Glass } 7399526d83aSSimon Glass pos = -1; 7409526d83aSSimon Glass for (i = 0; i < hose->region_count; i++) { 7419526d83aSSimon Glass if (hose->regions[i].flags == type) 7429526d83aSSimon Glass pos = i; 7439526d83aSSimon Glass } 7449526d83aSSimon Glass if (pos == -1) 7459526d83aSSimon Glass pos = hose->region_count++; 7469526d83aSSimon Glass debug(" - type=%d, pos=%d\n", type, pos); 7479526d83aSSimon Glass pci_set_region(hose->regions + pos, pci_addr, addr, size, type); 748ff3e077bSSimon Glass } 749ff3e077bSSimon Glass 750ff3e077bSSimon Glass /* Add a region for our local memory */ 7512084c5afSSimon Glass size = gd->ram_size; 7522084c5afSSimon Glass #ifdef CONFIG_SYS_SDRAM_BASE 7532084c5afSSimon Glass base = CONFIG_SYS_SDRAM_BASE; 7542084c5afSSimon Glass #endif 7552084c5afSSimon Glass if (gd->pci_ram_top && gd->pci_ram_top < base + size) 7562084c5afSSimon Glass size = gd->pci_ram_top - base; 7572084c5afSSimon Glass pci_set_region(hose->regions + hose->region_count++, base, base, 7582084c5afSSimon Glass size, PCI_REGION_MEM | PCI_REGION_SYS_MEMORY); 759ff3e077bSSimon Glass 760ff3e077bSSimon Glass return 0; 761ff3e077bSSimon Glass } 762ff3e077bSSimon Glass 763ff3e077bSSimon Glass static int pci_uclass_pre_probe(struct udevice *bus) 764ff3e077bSSimon Glass { 765ff3e077bSSimon Glass struct pci_controller *hose; 766ff3e077bSSimon Glass int ret; 767ff3e077bSSimon Glass 768ff3e077bSSimon Glass debug("%s, bus=%d/%s, parent=%s\n", __func__, bus->seq, bus->name, 769ff3e077bSSimon Glass bus->parent->name); 770ff3e077bSSimon Glass hose = bus->uclass_priv; 771ff3e077bSSimon Glass 772ff3e077bSSimon Glass /* For bridges, use the top-level PCI controller */ 773ff3e077bSSimon Glass if (device_get_uclass_id(bus->parent) == UCLASS_ROOT) { 774ff3e077bSSimon Glass hose->ctlr = bus; 775ff3e077bSSimon Glass ret = decode_regions(hose, gd->fdt_blob, bus->parent->of_offset, 776ff3e077bSSimon Glass bus->of_offset); 777ff3e077bSSimon Glass if (ret) { 778ff3e077bSSimon Glass debug("%s: Cannot decode regions\n", __func__); 779ff3e077bSSimon Glass return ret; 780ff3e077bSSimon Glass } 781ff3e077bSSimon Glass } else { 782ff3e077bSSimon Glass struct pci_controller *parent_hose; 783ff3e077bSSimon Glass 784ff3e077bSSimon Glass parent_hose = dev_get_uclass_priv(bus->parent); 785ff3e077bSSimon Glass hose->ctlr = parent_hose->bus; 786ff3e077bSSimon Glass } 787ff3e077bSSimon Glass hose->bus = bus; 788ff3e077bSSimon Glass hose->first_busno = bus->seq; 789ff3e077bSSimon Glass hose->last_busno = bus->seq; 790ff3e077bSSimon Glass 791ff3e077bSSimon Glass return 0; 792ff3e077bSSimon Glass } 793ff3e077bSSimon Glass 794ff3e077bSSimon Glass static int pci_uclass_post_probe(struct udevice *bus) 795ff3e077bSSimon Glass { 796ff3e077bSSimon Glass int ret; 797ff3e077bSSimon Glass 798ff3e077bSSimon Glass debug("%s: probing bus %d\n", __func__, bus->seq); 799ff3e077bSSimon Glass ret = pci_bind_bus_devices(bus); 800ff3e077bSSimon Glass if (ret) 801ff3e077bSSimon Glass return ret; 802ff3e077bSSimon Glass 803ff3e077bSSimon Glass #ifdef CONFIG_PCI_PNP 804ff3e077bSSimon Glass ret = pci_auto_config_devices(bus); 8054d21455eSSimon Glass if (ret < 0) 8064d21455eSSimon Glass return ret; 807ff3e077bSSimon Glass #endif 808ff3e077bSSimon Glass 809348b744bSBin Meng #if defined(CONFIG_X86) && defined(CONFIG_HAVE_FSP) 810348b744bSBin Meng /* 811348b744bSBin Meng * Per Intel FSP specification, we should call FSP notify API to 812348b744bSBin Meng * inform FSP that PCI enumeration has been done so that FSP will 813348b744bSBin Meng * do any necessary initialization as required by the chipset's 814348b744bSBin Meng * BIOS Writer's Guide (BWG). 815348b744bSBin Meng * 816348b744bSBin Meng * Unfortunately we have to put this call here as with driver model, 817348b744bSBin Meng * the enumeration is all done on a lazy basis as needed, so until 818348b744bSBin Meng * something is touched on PCI it won't happen. 819348b744bSBin Meng * 820348b744bSBin Meng * Note we only call this 1) after U-Boot is relocated, and 2) 821348b744bSBin Meng * root bus has finished probing. 822348b744bSBin Meng */ 8234d21455eSSimon Glass if ((gd->flags & GD_FLG_RELOC) && (bus->seq == 0)) { 824348b744bSBin Meng ret = fsp_init_phase_pci(); 8254d21455eSSimon Glass if (ret) 8264d21455eSSimon Glass return ret; 8274d21455eSSimon Glass } 828348b744bSBin Meng #endif 829348b744bSBin Meng 8304d21455eSSimon Glass return 0; 831ff3e077bSSimon Glass } 832ff3e077bSSimon Glass 833ff3e077bSSimon Glass static int pci_uclass_child_post_bind(struct udevice *dev) 834ff3e077bSSimon Glass { 835ff3e077bSSimon Glass struct pci_child_platdata *pplat; 836ff3e077bSSimon Glass struct fdt_pci_addr addr; 837ff3e077bSSimon Glass int ret; 838ff3e077bSSimon Glass 839ff3e077bSSimon Glass if (dev->of_offset == -1) 840ff3e077bSSimon Glass return 0; 841ff3e077bSSimon Glass 842ff3e077bSSimon Glass /* 843ff3e077bSSimon Glass * We could read vendor, device, class if available. But for now we 844ff3e077bSSimon Glass * just check the address. 845ff3e077bSSimon Glass */ 846ff3e077bSSimon Glass pplat = dev_get_parent_platdata(dev); 847ff3e077bSSimon Glass ret = fdtdec_get_pci_addr(gd->fdt_blob, dev->of_offset, 848ff3e077bSSimon Glass FDT_PCI_SPACE_CONFIG, "reg", &addr); 849ff3e077bSSimon Glass 850ff3e077bSSimon Glass if (ret) { 851ff3e077bSSimon Glass if (ret != -ENOENT) 852ff3e077bSSimon Glass return -EINVAL; 853ff3e077bSSimon Glass } else { 854dce54dd6SBin Meng /* extract the devfn from fdt_pci_addr */ 855dce54dd6SBin Meng pplat->devfn = addr.phys_hi & 0xff00; 856ff3e077bSSimon Glass } 857ff3e077bSSimon Glass 858ff3e077bSSimon Glass return 0; 859ff3e077bSSimon Glass } 860ff3e077bSSimon Glass 8614d8615cbSBin Meng static int pci_bridge_read_config(struct udevice *bus, pci_dev_t bdf, 8624d8615cbSBin Meng uint offset, ulong *valuep, 8634d8615cbSBin Meng enum pci_size_t size) 864ff3e077bSSimon Glass { 865ff3e077bSSimon Glass struct pci_controller *hose = bus->uclass_priv; 866ff3e077bSSimon Glass 867ff3e077bSSimon Glass return pci_bus_read_config(hose->ctlr, bdf, offset, valuep, size); 868ff3e077bSSimon Glass } 869ff3e077bSSimon Glass 8704d8615cbSBin Meng static int pci_bridge_write_config(struct udevice *bus, pci_dev_t bdf, 8714d8615cbSBin Meng uint offset, ulong value, 8724d8615cbSBin Meng enum pci_size_t size) 873ff3e077bSSimon Glass { 874ff3e077bSSimon Glass struct pci_controller *hose = bus->uclass_priv; 875ff3e077bSSimon Glass 876ff3e077bSSimon Glass return pci_bus_write_config(hose->ctlr, bdf, offset, value, size); 877ff3e077bSSimon Glass } 878ff3e077bSSimon Glass 87976c3fbcdSSimon Glass static int skip_to_next_device(struct udevice *bus, struct udevice **devp) 88076c3fbcdSSimon Glass { 88176c3fbcdSSimon Glass struct udevice *dev; 88276c3fbcdSSimon Glass int ret = 0; 88376c3fbcdSSimon Glass 88476c3fbcdSSimon Glass /* 88576c3fbcdSSimon Glass * Scan through all the PCI controllers. On x86 there will only be one 88676c3fbcdSSimon Glass * but that is not necessarily true on other hardware. 88776c3fbcdSSimon Glass */ 88876c3fbcdSSimon Glass do { 88976c3fbcdSSimon Glass device_find_first_child(bus, &dev); 89076c3fbcdSSimon Glass if (dev) { 89176c3fbcdSSimon Glass *devp = dev; 89276c3fbcdSSimon Glass return 0; 89376c3fbcdSSimon Glass } 89476c3fbcdSSimon Glass ret = uclass_next_device(&bus); 89576c3fbcdSSimon Glass if (ret) 89676c3fbcdSSimon Glass return ret; 89776c3fbcdSSimon Glass } while (bus); 89876c3fbcdSSimon Glass 89976c3fbcdSSimon Glass return 0; 90076c3fbcdSSimon Glass } 90176c3fbcdSSimon Glass 90276c3fbcdSSimon Glass int pci_find_next_device(struct udevice **devp) 90376c3fbcdSSimon Glass { 90476c3fbcdSSimon Glass struct udevice *child = *devp; 90576c3fbcdSSimon Glass struct udevice *bus = child->parent; 90676c3fbcdSSimon Glass int ret; 90776c3fbcdSSimon Glass 90876c3fbcdSSimon Glass /* First try all the siblings */ 90976c3fbcdSSimon Glass *devp = NULL; 91076c3fbcdSSimon Glass while (child) { 91176c3fbcdSSimon Glass device_find_next_child(&child); 91276c3fbcdSSimon Glass if (child) { 91376c3fbcdSSimon Glass *devp = child; 91476c3fbcdSSimon Glass return 0; 91576c3fbcdSSimon Glass } 91676c3fbcdSSimon Glass } 91776c3fbcdSSimon Glass 91876c3fbcdSSimon Glass /* We ran out of siblings. Try the next bus */ 91976c3fbcdSSimon Glass ret = uclass_next_device(&bus); 92076c3fbcdSSimon Glass if (ret) 92176c3fbcdSSimon Glass return ret; 92276c3fbcdSSimon Glass 92376c3fbcdSSimon Glass return bus ? skip_to_next_device(bus, devp) : 0; 92476c3fbcdSSimon Glass } 92576c3fbcdSSimon Glass 92676c3fbcdSSimon Glass int pci_find_first_device(struct udevice **devp) 92776c3fbcdSSimon Glass { 92876c3fbcdSSimon Glass struct udevice *bus; 92976c3fbcdSSimon Glass int ret; 93076c3fbcdSSimon Glass 93176c3fbcdSSimon Glass *devp = NULL; 93276c3fbcdSSimon Glass ret = uclass_first_device(UCLASS_PCI, &bus); 93376c3fbcdSSimon Glass if (ret) 93476c3fbcdSSimon Glass return ret; 93576c3fbcdSSimon Glass 93676c3fbcdSSimon Glass return skip_to_next_device(bus, devp); 93776c3fbcdSSimon Glass } 93876c3fbcdSSimon Glass 9399289db6cSSimon Glass ulong pci_conv_32_to_size(ulong value, uint offset, enum pci_size_t size) 9409289db6cSSimon Glass { 9419289db6cSSimon Glass switch (size) { 9429289db6cSSimon Glass case PCI_SIZE_8: 9439289db6cSSimon Glass return (value >> ((offset & 3) * 8)) & 0xff; 9449289db6cSSimon Glass case PCI_SIZE_16: 9459289db6cSSimon Glass return (value >> ((offset & 2) * 8)) & 0xffff; 9469289db6cSSimon Glass default: 9479289db6cSSimon Glass return value; 9489289db6cSSimon Glass } 9499289db6cSSimon Glass } 9509289db6cSSimon Glass 9519289db6cSSimon Glass ulong pci_conv_size_to_32(ulong old, ulong value, uint offset, 9529289db6cSSimon Glass enum pci_size_t size) 9539289db6cSSimon Glass { 9549289db6cSSimon Glass uint off_mask; 9559289db6cSSimon Glass uint val_mask, shift; 9569289db6cSSimon Glass ulong ldata, mask; 9579289db6cSSimon Glass 9589289db6cSSimon Glass switch (size) { 9599289db6cSSimon Glass case PCI_SIZE_8: 9609289db6cSSimon Glass off_mask = 3; 9619289db6cSSimon Glass val_mask = 0xff; 9629289db6cSSimon Glass break; 9639289db6cSSimon Glass case PCI_SIZE_16: 9649289db6cSSimon Glass off_mask = 2; 9659289db6cSSimon Glass val_mask = 0xffff; 9669289db6cSSimon Glass break; 9679289db6cSSimon Glass default: 9689289db6cSSimon Glass return value; 9699289db6cSSimon Glass } 9709289db6cSSimon Glass shift = (offset & off_mask) * 8; 9719289db6cSSimon Glass ldata = (value & val_mask) << shift; 9729289db6cSSimon Glass mask = val_mask << shift; 9739289db6cSSimon Glass value = (old & ~mask) | ldata; 9749289db6cSSimon Glass 9759289db6cSSimon Glass return value; 9769289db6cSSimon Glass } 9779289db6cSSimon Glass 978f9260336SSimon Glass int pci_get_regions(struct udevice *dev, struct pci_region **iop, 979f9260336SSimon Glass struct pci_region **memp, struct pci_region **prefp) 980f9260336SSimon Glass { 981f9260336SSimon Glass struct udevice *bus = pci_get_controller(dev); 982f9260336SSimon Glass struct pci_controller *hose = dev_get_uclass_priv(bus); 983f9260336SSimon Glass int i; 984f9260336SSimon Glass 985f9260336SSimon Glass *iop = NULL; 986f9260336SSimon Glass *memp = NULL; 987f9260336SSimon Glass *prefp = NULL; 988f9260336SSimon Glass for (i = 0; i < hose->region_count; i++) { 989f9260336SSimon Glass switch (hose->regions[i].flags) { 990f9260336SSimon Glass case PCI_REGION_IO: 991f9260336SSimon Glass if (!*iop || (*iop)->size < hose->regions[i].size) 992f9260336SSimon Glass *iop = hose->regions + i; 993f9260336SSimon Glass break; 994f9260336SSimon Glass case PCI_REGION_MEM: 995f9260336SSimon Glass if (!*memp || (*memp)->size < hose->regions[i].size) 996f9260336SSimon Glass *memp = hose->regions + i; 997f9260336SSimon Glass break; 998f9260336SSimon Glass case (PCI_REGION_MEM | PCI_REGION_PREFETCH): 999f9260336SSimon Glass if (!*prefp || (*prefp)->size < hose->regions[i].size) 1000f9260336SSimon Glass *prefp = hose->regions + i; 1001f9260336SSimon Glass break; 1002f9260336SSimon Glass } 1003f9260336SSimon Glass } 1004f9260336SSimon Glass 1005f9260336SSimon Glass return (*iop != NULL) + (*memp != NULL) + (*prefp != NULL); 1006f9260336SSimon Glass } 1007f9260336SSimon Glass 1008ff3e077bSSimon Glass UCLASS_DRIVER(pci) = { 1009ff3e077bSSimon Glass .id = UCLASS_PCI, 1010ff3e077bSSimon Glass .name = "pci", 10112bb02e4fSSimon Glass .flags = DM_UC_FLAG_SEQ_ALIAS, 1012ff3e077bSSimon Glass .post_bind = pci_uclass_post_bind, 1013ff3e077bSSimon Glass .pre_probe = pci_uclass_pre_probe, 1014ff3e077bSSimon Glass .post_probe = pci_uclass_post_probe, 1015ff3e077bSSimon Glass .child_post_bind = pci_uclass_child_post_bind, 1016ff3e077bSSimon Glass .per_device_auto_alloc_size = sizeof(struct pci_controller), 1017ff3e077bSSimon Glass .per_child_platdata_auto_alloc_size = 1018ff3e077bSSimon Glass sizeof(struct pci_child_platdata), 1019ff3e077bSSimon Glass }; 1020ff3e077bSSimon Glass 1021ff3e077bSSimon Glass static const struct dm_pci_ops pci_bridge_ops = { 1022ff3e077bSSimon Glass .read_config = pci_bridge_read_config, 1023ff3e077bSSimon Glass .write_config = pci_bridge_write_config, 1024ff3e077bSSimon Glass }; 1025ff3e077bSSimon Glass 1026ff3e077bSSimon Glass static const struct udevice_id pci_bridge_ids[] = { 1027ff3e077bSSimon Glass { .compatible = "pci-bridge" }, 1028ff3e077bSSimon Glass { } 1029ff3e077bSSimon Glass }; 1030ff3e077bSSimon Glass 1031ff3e077bSSimon Glass U_BOOT_DRIVER(pci_bridge_drv) = { 1032ff3e077bSSimon Glass .name = "pci_bridge_drv", 1033ff3e077bSSimon Glass .id = UCLASS_PCI, 1034ff3e077bSSimon Glass .of_match = pci_bridge_ids, 1035ff3e077bSSimon Glass .ops = &pci_bridge_ops, 1036ff3e077bSSimon Glass }; 1037ff3e077bSSimon Glass 1038ff3e077bSSimon Glass UCLASS_DRIVER(pci_generic) = { 1039ff3e077bSSimon Glass .id = UCLASS_PCI_GENERIC, 1040ff3e077bSSimon Glass .name = "pci_generic", 1041ff3e077bSSimon Glass }; 1042ff3e077bSSimon Glass 1043ff3e077bSSimon Glass static const struct udevice_id pci_generic_ids[] = { 1044ff3e077bSSimon Glass { .compatible = "pci-generic" }, 1045ff3e077bSSimon Glass { } 1046ff3e077bSSimon Glass }; 1047ff3e077bSSimon Glass 1048ff3e077bSSimon Glass U_BOOT_DRIVER(pci_generic_drv) = { 1049ff3e077bSSimon Glass .name = "pci_generic_drv", 1050ff3e077bSSimon Glass .id = UCLASS_PCI_GENERIC, 1051ff3e077bSSimon Glass .of_match = pci_generic_ids, 1052ff3e077bSSimon Glass }; 1053