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> 17ff3e077bSSimon Glass 18ff3e077bSSimon Glass DECLARE_GLOBAL_DATA_PTR; 19ff3e077bSSimon Glass 20ff3e077bSSimon Glass struct pci_controller *pci_bus_to_hose(int busnum) 21ff3e077bSSimon Glass { 22ff3e077bSSimon Glass struct udevice *bus; 23ff3e077bSSimon Glass int ret; 24ff3e077bSSimon Glass 25ff3e077bSSimon Glass ret = uclass_get_device_by_seq(UCLASS_PCI, busnum, &bus); 26ff3e077bSSimon Glass if (ret) { 27ff3e077bSSimon Glass debug("%s: Cannot get bus %d: ret=%d\n", __func__, busnum, ret); 28ff3e077bSSimon Glass return NULL; 29ff3e077bSSimon Glass } 30ff3e077bSSimon Glass return dev_get_uclass_priv(bus); 31ff3e077bSSimon Glass } 32ff3e077bSSimon Glass 33ff3e077bSSimon Glass /** 34ff3e077bSSimon Glass * pci_get_bus_max() - returns the bus number of the last active bus 35ff3e077bSSimon Glass * 36ff3e077bSSimon Glass * @return last bus number, or -1 if no active buses 37ff3e077bSSimon Glass */ 38ff3e077bSSimon Glass static int pci_get_bus_max(void) 39ff3e077bSSimon Glass { 40ff3e077bSSimon Glass struct udevice *bus; 41ff3e077bSSimon Glass struct uclass *uc; 42ff3e077bSSimon Glass int ret = -1; 43ff3e077bSSimon Glass 44ff3e077bSSimon Glass ret = uclass_get(UCLASS_PCI, &uc); 45ff3e077bSSimon Glass uclass_foreach_dev(bus, uc) { 46ff3e077bSSimon Glass if (bus->seq > ret) 47ff3e077bSSimon Glass ret = bus->seq; 48ff3e077bSSimon Glass } 49ff3e077bSSimon Glass 50ff3e077bSSimon Glass debug("%s: ret=%d\n", __func__, ret); 51ff3e077bSSimon Glass 52ff3e077bSSimon Glass return ret; 53ff3e077bSSimon Glass } 54ff3e077bSSimon Glass 55ff3e077bSSimon Glass int pci_last_busno(void) 56ff3e077bSSimon Glass { 57ff3e077bSSimon Glass struct pci_controller *hose; 58ff3e077bSSimon Glass struct udevice *bus; 59ff3e077bSSimon Glass struct uclass *uc; 60ff3e077bSSimon Glass int ret; 61ff3e077bSSimon Glass 62ff3e077bSSimon Glass debug("pci_last_busno\n"); 63ff3e077bSSimon Glass ret = uclass_get(UCLASS_PCI, &uc); 64ff3e077bSSimon Glass if (ret || list_empty(&uc->dev_head)) 65ff3e077bSSimon Glass return -1; 66ff3e077bSSimon Glass 67ff3e077bSSimon Glass /* Probe the last bus */ 68ff3e077bSSimon Glass bus = list_entry(uc->dev_head.prev, struct udevice, uclass_node); 69ff3e077bSSimon Glass debug("bus = %p, %s\n", bus, bus->name); 70ff3e077bSSimon Glass assert(bus); 71ff3e077bSSimon Glass ret = device_probe(bus); 72ff3e077bSSimon Glass if (ret) 73ff3e077bSSimon Glass return ret; 74ff3e077bSSimon Glass 75ff3e077bSSimon Glass /* If that bus has bridges, we may have new buses now. Get the last */ 76ff3e077bSSimon Glass bus = list_entry(uc->dev_head.prev, struct udevice, uclass_node); 77ff3e077bSSimon Glass hose = dev_get_uclass_priv(bus); 78ff3e077bSSimon Glass debug("bus = %s, hose = %p\n", bus->name, hose); 79ff3e077bSSimon Glass 80ff3e077bSSimon Glass return hose->last_busno; 81ff3e077bSSimon Glass } 82ff3e077bSSimon Glass 83ff3e077bSSimon Glass int pci_get_ff(enum pci_size_t size) 84ff3e077bSSimon Glass { 85ff3e077bSSimon Glass switch (size) { 86ff3e077bSSimon Glass case PCI_SIZE_8: 87ff3e077bSSimon Glass return 0xff; 88ff3e077bSSimon Glass case PCI_SIZE_16: 89ff3e077bSSimon Glass return 0xffff; 90ff3e077bSSimon Glass default: 91ff3e077bSSimon Glass return 0xffffffff; 92ff3e077bSSimon Glass } 93ff3e077bSSimon Glass } 94ff3e077bSSimon Glass 95ff3e077bSSimon Glass int pci_bus_find_devfn(struct udevice *bus, pci_dev_t find_devfn, 96ff3e077bSSimon Glass struct udevice **devp) 97ff3e077bSSimon Glass { 98ff3e077bSSimon Glass struct udevice *dev; 99ff3e077bSSimon Glass 100ff3e077bSSimon Glass for (device_find_first_child(bus, &dev); 101ff3e077bSSimon Glass dev; 102ff3e077bSSimon Glass device_find_next_child(&dev)) { 103ff3e077bSSimon Glass struct pci_child_platdata *pplat; 104ff3e077bSSimon Glass 105ff3e077bSSimon Glass pplat = dev_get_parent_platdata(dev); 106ff3e077bSSimon Glass if (pplat && pplat->devfn == find_devfn) { 107ff3e077bSSimon Glass *devp = dev; 108ff3e077bSSimon Glass return 0; 109ff3e077bSSimon Glass } 110ff3e077bSSimon Glass } 111ff3e077bSSimon Glass 112ff3e077bSSimon Glass return -ENODEV; 113ff3e077bSSimon Glass } 114ff3e077bSSimon Glass 115ff3e077bSSimon Glass int pci_bus_find_bdf(pci_dev_t bdf, struct udevice **devp) 116ff3e077bSSimon Glass { 117ff3e077bSSimon Glass struct udevice *bus; 118ff3e077bSSimon Glass int ret; 119ff3e077bSSimon Glass 120ff3e077bSSimon Glass ret = uclass_get_device_by_seq(UCLASS_PCI, PCI_BUS(bdf), &bus); 121ff3e077bSSimon Glass if (ret) 122ff3e077bSSimon Glass return ret; 123ff3e077bSSimon Glass return pci_bus_find_devfn(bus, PCI_MASK_BUS(bdf), devp); 124ff3e077bSSimon Glass } 125ff3e077bSSimon Glass 126ff3e077bSSimon Glass static int pci_device_matches_ids(struct udevice *dev, 127ff3e077bSSimon Glass struct pci_device_id *ids) 128ff3e077bSSimon Glass { 129ff3e077bSSimon Glass struct pci_child_platdata *pplat; 130ff3e077bSSimon Glass int i; 131ff3e077bSSimon Glass 132ff3e077bSSimon Glass pplat = dev_get_parent_platdata(dev); 133ff3e077bSSimon Glass if (!pplat) 134ff3e077bSSimon Glass return -EINVAL; 135ff3e077bSSimon Glass for (i = 0; ids[i].vendor != 0; i++) { 136ff3e077bSSimon Glass if (pplat->vendor == ids[i].vendor && 137ff3e077bSSimon Glass pplat->device == ids[i].device) 138ff3e077bSSimon Glass return i; 139ff3e077bSSimon Glass } 140ff3e077bSSimon Glass 141ff3e077bSSimon Glass return -EINVAL; 142ff3e077bSSimon Glass } 143ff3e077bSSimon Glass 144ff3e077bSSimon Glass int pci_bus_find_devices(struct udevice *bus, struct pci_device_id *ids, 145ff3e077bSSimon Glass int *indexp, struct udevice **devp) 146ff3e077bSSimon Glass { 147ff3e077bSSimon Glass struct udevice *dev; 148ff3e077bSSimon Glass 149ff3e077bSSimon Glass /* Scan all devices on this bus */ 150ff3e077bSSimon Glass for (device_find_first_child(bus, &dev); 151ff3e077bSSimon Glass dev; 152ff3e077bSSimon Glass device_find_next_child(&dev)) { 153ff3e077bSSimon Glass if (pci_device_matches_ids(dev, ids) >= 0) { 154ff3e077bSSimon Glass if ((*indexp)-- <= 0) { 155ff3e077bSSimon Glass *devp = dev; 156ff3e077bSSimon Glass return 0; 157ff3e077bSSimon Glass } 158ff3e077bSSimon Glass } 159ff3e077bSSimon Glass } 160ff3e077bSSimon Glass 161ff3e077bSSimon Glass return -ENODEV; 162ff3e077bSSimon Glass } 163ff3e077bSSimon Glass 164ff3e077bSSimon Glass int pci_find_device_id(struct pci_device_id *ids, int index, 165ff3e077bSSimon Glass struct udevice **devp) 166ff3e077bSSimon Glass { 167ff3e077bSSimon Glass struct udevice *bus; 168ff3e077bSSimon Glass 169ff3e077bSSimon Glass /* Scan all known buses */ 170ff3e077bSSimon Glass for (uclass_first_device(UCLASS_PCI, &bus); 171ff3e077bSSimon Glass bus; 172ff3e077bSSimon Glass uclass_next_device(&bus)) { 173ff3e077bSSimon Glass if (!pci_bus_find_devices(bus, ids, &index, devp)) 174ff3e077bSSimon Glass return 0; 175ff3e077bSSimon Glass } 176ff3e077bSSimon Glass *devp = NULL; 177ff3e077bSSimon Glass 178ff3e077bSSimon Glass return -ENODEV; 179ff3e077bSSimon Glass } 180ff3e077bSSimon Glass 181ff3e077bSSimon Glass int pci_bus_write_config(struct udevice *bus, pci_dev_t bdf, int offset, 182ff3e077bSSimon Glass unsigned long value, enum pci_size_t size) 183ff3e077bSSimon Glass { 184ff3e077bSSimon Glass struct dm_pci_ops *ops; 185ff3e077bSSimon Glass 186ff3e077bSSimon Glass ops = pci_get_ops(bus); 187ff3e077bSSimon Glass if (!ops->write_config) 188ff3e077bSSimon Glass return -ENOSYS; 189ff3e077bSSimon Glass return ops->write_config(bus, bdf, offset, value, size); 190ff3e077bSSimon Glass } 191ff3e077bSSimon Glass 192ff3e077bSSimon Glass int pci_write_config(pci_dev_t bdf, int offset, unsigned long value, 193ff3e077bSSimon Glass enum pci_size_t size) 194ff3e077bSSimon Glass { 195ff3e077bSSimon Glass struct udevice *bus; 196ff3e077bSSimon Glass int ret; 197ff3e077bSSimon Glass 198ff3e077bSSimon Glass ret = uclass_get_device_by_seq(UCLASS_PCI, PCI_BUS(bdf), &bus); 199ff3e077bSSimon Glass if (ret) 200ff3e077bSSimon Glass return ret; 201ff3e077bSSimon Glass 202ff3e077bSSimon Glass return pci_bus_write_config(bus, PCI_MASK_BUS(bdf), offset, value, 203ff3e077bSSimon Glass size); 204ff3e077bSSimon Glass } 205ff3e077bSSimon Glass 206ff3e077bSSimon Glass int pci_write_config32(pci_dev_t bdf, int offset, u32 value) 207ff3e077bSSimon Glass { 208ff3e077bSSimon Glass return pci_write_config(bdf, offset, value, PCI_SIZE_32); 209ff3e077bSSimon Glass } 210ff3e077bSSimon Glass 211ff3e077bSSimon Glass int pci_write_config16(pci_dev_t bdf, int offset, u16 value) 212ff3e077bSSimon Glass { 213ff3e077bSSimon Glass return pci_write_config(bdf, offset, value, PCI_SIZE_16); 214ff3e077bSSimon Glass } 215ff3e077bSSimon Glass 216ff3e077bSSimon Glass int pci_write_config8(pci_dev_t bdf, int offset, u8 value) 217ff3e077bSSimon Glass { 218ff3e077bSSimon Glass return pci_write_config(bdf, offset, value, PCI_SIZE_8); 219ff3e077bSSimon Glass } 220ff3e077bSSimon Glass 221ff3e077bSSimon Glass int pci_bus_read_config(struct udevice *bus, pci_dev_t bdf, int offset, 222ff3e077bSSimon Glass unsigned long *valuep, enum pci_size_t size) 223ff3e077bSSimon Glass { 224ff3e077bSSimon Glass struct dm_pci_ops *ops; 225ff3e077bSSimon Glass 226ff3e077bSSimon Glass ops = pci_get_ops(bus); 227ff3e077bSSimon Glass if (!ops->read_config) 228ff3e077bSSimon Glass return -ENOSYS; 229ff3e077bSSimon Glass return ops->read_config(bus, bdf, offset, valuep, size); 230ff3e077bSSimon Glass } 231ff3e077bSSimon Glass 232ff3e077bSSimon Glass int pci_read_config(pci_dev_t bdf, int offset, unsigned long *valuep, 233ff3e077bSSimon Glass enum pci_size_t size) 234ff3e077bSSimon Glass { 235ff3e077bSSimon Glass struct udevice *bus; 236ff3e077bSSimon Glass int ret; 237ff3e077bSSimon Glass 238ff3e077bSSimon Glass ret = uclass_get_device_by_seq(UCLASS_PCI, PCI_BUS(bdf), &bus); 239ff3e077bSSimon Glass if (ret) 240ff3e077bSSimon Glass return ret; 241ff3e077bSSimon Glass 242ff3e077bSSimon Glass return pci_bus_read_config(bus, PCI_MASK_BUS(bdf), offset, valuep, 243ff3e077bSSimon Glass size); 244ff3e077bSSimon Glass } 245ff3e077bSSimon Glass 246ff3e077bSSimon Glass int pci_read_config32(pci_dev_t bdf, int offset, u32 *valuep) 247ff3e077bSSimon Glass { 248ff3e077bSSimon Glass unsigned long value; 249ff3e077bSSimon Glass int ret; 250ff3e077bSSimon Glass 251ff3e077bSSimon Glass ret = pci_read_config(bdf, offset, &value, PCI_SIZE_32); 252ff3e077bSSimon Glass if (ret) 253ff3e077bSSimon Glass return ret; 254ff3e077bSSimon Glass *valuep = value; 255ff3e077bSSimon Glass 256ff3e077bSSimon Glass return 0; 257ff3e077bSSimon Glass } 258ff3e077bSSimon Glass 259ff3e077bSSimon Glass int pci_read_config16(pci_dev_t bdf, int offset, u16 *valuep) 260ff3e077bSSimon Glass { 261ff3e077bSSimon Glass unsigned long value; 262ff3e077bSSimon Glass int ret; 263ff3e077bSSimon Glass 264ff3e077bSSimon Glass ret = pci_read_config(bdf, offset, &value, PCI_SIZE_16); 265ff3e077bSSimon Glass if (ret) 266ff3e077bSSimon Glass return ret; 267ff3e077bSSimon Glass *valuep = value; 268ff3e077bSSimon Glass 269ff3e077bSSimon Glass return 0; 270ff3e077bSSimon Glass } 271ff3e077bSSimon Glass 272ff3e077bSSimon Glass int pci_read_config8(pci_dev_t bdf, int offset, u8 *valuep) 273ff3e077bSSimon Glass { 274ff3e077bSSimon Glass unsigned long value; 275ff3e077bSSimon Glass int ret; 276ff3e077bSSimon Glass 277ff3e077bSSimon Glass ret = pci_read_config(bdf, offset, &value, PCI_SIZE_8); 278ff3e077bSSimon Glass if (ret) 279ff3e077bSSimon Glass return ret; 280ff3e077bSSimon Glass *valuep = value; 281ff3e077bSSimon Glass 282ff3e077bSSimon Glass return 0; 283ff3e077bSSimon Glass } 284ff3e077bSSimon Glass 285ff3e077bSSimon Glass int pci_auto_config_devices(struct udevice *bus) 286ff3e077bSSimon Glass { 287ff3e077bSSimon Glass struct pci_controller *hose = bus->uclass_priv; 288ff3e077bSSimon Glass unsigned int sub_bus; 289ff3e077bSSimon Glass struct udevice *dev; 290ff3e077bSSimon Glass int ret; 291ff3e077bSSimon Glass 292ff3e077bSSimon Glass sub_bus = bus->seq; 293ff3e077bSSimon Glass debug("%s: start\n", __func__); 294ff3e077bSSimon Glass pciauto_config_init(hose); 295ff3e077bSSimon Glass for (ret = device_find_first_child(bus, &dev); 296ff3e077bSSimon Glass !ret && dev; 297ff3e077bSSimon Glass ret = device_find_next_child(&dev)) { 298ff3e077bSSimon Glass struct pci_child_platdata *pplat; 299aec241dfSSimon Glass struct pci_controller *ctlr_hose; 300ff3e077bSSimon Glass 301ff3e077bSSimon Glass pplat = dev_get_parent_platdata(dev); 302ff3e077bSSimon Glass unsigned int max_bus; 303ff3e077bSSimon Glass pci_dev_t bdf; 304ff3e077bSSimon Glass 305ff3e077bSSimon Glass bdf = PCI_ADD_BUS(bus->seq, pplat->devfn); 306ff3e077bSSimon Glass debug("%s: device %s\n", __func__, dev->name); 307aec241dfSSimon Glass 308aec241dfSSimon Glass /* The root controller has the region information */ 309aec241dfSSimon Glass ctlr_hose = hose->ctlr->uclass_priv; 310aec241dfSSimon Glass max_bus = pciauto_config_device(ctlr_hose, bdf); 311ff3e077bSSimon Glass sub_bus = max(sub_bus, max_bus); 312ff3e077bSSimon Glass } 313ff3e077bSSimon Glass debug("%s: done\n", __func__); 314ff3e077bSSimon Glass 315ff3e077bSSimon Glass return sub_bus; 316ff3e077bSSimon Glass } 317ff3e077bSSimon Glass 318ff3e077bSSimon Glass int dm_pci_hose_probe_bus(struct pci_controller *hose, pci_dev_t bdf) 319ff3e077bSSimon Glass { 320ff3e077bSSimon Glass struct udevice *parent, *bus; 321ff3e077bSSimon Glass int sub_bus; 322ff3e077bSSimon Glass int ret; 323ff3e077bSSimon Glass 324ff3e077bSSimon Glass debug("%s\n", __func__); 325ff3e077bSSimon Glass parent = hose->bus; 326ff3e077bSSimon Glass 327ff3e077bSSimon Glass /* Find the bus within the parent */ 328ff3e077bSSimon Glass ret = pci_bus_find_devfn(parent, bdf, &bus); 329ff3e077bSSimon Glass if (ret) { 330ff3e077bSSimon Glass debug("%s: Cannot find device %x on bus %s: %d\n", __func__, 331ff3e077bSSimon Glass bdf, parent->name, ret); 332ff3e077bSSimon Glass return ret; 333ff3e077bSSimon Glass } 334ff3e077bSSimon Glass 335ff3e077bSSimon Glass sub_bus = pci_get_bus_max() + 1; 336ff3e077bSSimon Glass debug("%s: bus = %d/%s\n", __func__, sub_bus, bus->name); 3375afeb4bbSSimon Glass pciauto_prescan_setup_bridge(hose, bdf, sub_bus); 338ff3e077bSSimon Glass 339ff3e077bSSimon Glass ret = device_probe(bus); 340ff3e077bSSimon Glass if (ret) { 341ff3e077bSSimon Glass debug("%s: Cannot probe bus bus %s: %d\n", __func__, bus->name, 342ff3e077bSSimon Glass ret); 343ff3e077bSSimon Glass return ret; 344ff3e077bSSimon Glass } 345ff3e077bSSimon Glass if (sub_bus != bus->seq) { 346ff3e077bSSimon Glass printf("%s: Internal error, bus '%s' got seq %d, expected %d\n", 347ff3e077bSSimon Glass __func__, bus->name, bus->seq, sub_bus); 348ff3e077bSSimon Glass return -EPIPE; 349ff3e077bSSimon Glass } 350ff3e077bSSimon Glass sub_bus = pci_get_bus_max(); 351ff3e077bSSimon Glass pciauto_postscan_setup_bridge(hose, bdf, sub_bus); 352ff3e077bSSimon Glass 353ff3e077bSSimon Glass return sub_bus; 354ff3e077bSSimon Glass } 355ff3e077bSSimon Glass 356*aba92962SSimon Glass /** 357*aba92962SSimon Glass * pci_match_one_device - Tell if a PCI device structure has a matching 358*aba92962SSimon Glass * PCI device id structure 359*aba92962SSimon Glass * @id: single PCI device id structure to match 360*aba92962SSimon Glass * @dev: the PCI device structure to match against 361*aba92962SSimon Glass * 362*aba92962SSimon Glass * Returns the matching pci_device_id structure or %NULL if there is no match. 363*aba92962SSimon Glass */ 364*aba92962SSimon Glass static bool pci_match_one_id(const struct pci_device_id *id, 365*aba92962SSimon Glass const struct pci_device_id *find) 366*aba92962SSimon Glass { 367*aba92962SSimon Glass if ((id->vendor == PCI_ANY_ID || id->vendor == find->vendor) && 368*aba92962SSimon Glass (id->device == PCI_ANY_ID || id->device == find->device) && 369*aba92962SSimon Glass (id->subvendor == PCI_ANY_ID || id->subvendor == find->subvendor) && 370*aba92962SSimon Glass (id->subdevice == PCI_ANY_ID || id->subdevice == find->subdevice) && 371*aba92962SSimon Glass !((id->class ^ find->class) & id->class_mask)) 372*aba92962SSimon Glass return true; 373*aba92962SSimon Glass 374*aba92962SSimon Glass return false; 375*aba92962SSimon Glass } 376*aba92962SSimon Glass 377*aba92962SSimon Glass /** 378*aba92962SSimon Glass * pci_find_and_bind_driver() - Find and bind the right PCI driver 379*aba92962SSimon Glass * 380*aba92962SSimon Glass * This only looks at certain fields in the descriptor. 381*aba92962SSimon Glass */ 382*aba92962SSimon Glass static int pci_find_and_bind_driver(struct udevice *parent, 383*aba92962SSimon Glass struct pci_device_id *find_id, int devfn, 384*aba92962SSimon Glass struct udevice **devp) 385*aba92962SSimon Glass { 386*aba92962SSimon Glass struct pci_driver_entry *start, *entry; 387*aba92962SSimon Glass const char *drv; 388*aba92962SSimon Glass int n_ents; 389*aba92962SSimon Glass int ret; 390*aba92962SSimon Glass char name[30], *str; 391*aba92962SSimon Glass 392*aba92962SSimon Glass *devp = NULL; 393*aba92962SSimon Glass 394*aba92962SSimon Glass debug("%s: Searching for driver: vendor=%x, device=%x\n", __func__, 395*aba92962SSimon Glass find_id->vendor, find_id->device); 396*aba92962SSimon Glass start = ll_entry_start(struct pci_driver_entry, pci_driver_entry); 397*aba92962SSimon Glass n_ents = ll_entry_count(struct pci_driver_entry, pci_driver_entry); 398*aba92962SSimon Glass for (entry = start; entry != start + n_ents; entry++) { 399*aba92962SSimon Glass const struct pci_device_id *id; 400*aba92962SSimon Glass struct udevice *dev; 401*aba92962SSimon Glass const struct driver *drv; 402*aba92962SSimon Glass 403*aba92962SSimon Glass for (id = entry->match; 404*aba92962SSimon Glass id->vendor || id->subvendor || id->class_mask; 405*aba92962SSimon Glass id++) { 406*aba92962SSimon Glass if (!pci_match_one_id(id, find_id)) 407*aba92962SSimon Glass continue; 408*aba92962SSimon Glass 409*aba92962SSimon Glass drv = entry->driver; 410*aba92962SSimon Glass /* 411*aba92962SSimon Glass * We could pass the descriptor to the driver as 412*aba92962SSimon Glass * platdata (instead of NULL) and allow its bind() 413*aba92962SSimon Glass * method to return -ENOENT if it doesn't support this 414*aba92962SSimon Glass * device. That way we could continue the search to 415*aba92962SSimon Glass * find another driver. For now this doesn't seem 416*aba92962SSimon Glass * necesssary, so just bind the first match. 417*aba92962SSimon Glass */ 418*aba92962SSimon Glass ret = device_bind(parent, drv, drv->name, NULL, -1, 419*aba92962SSimon Glass &dev); 420*aba92962SSimon Glass if (ret) 421*aba92962SSimon Glass goto error; 422*aba92962SSimon Glass debug("%s: Match found: %s\n", __func__, drv->name); 423*aba92962SSimon Glass dev->driver_data = find_id->driver_data; 424*aba92962SSimon Glass *devp = dev; 425*aba92962SSimon Glass return 0; 426*aba92962SSimon Glass } 427*aba92962SSimon Glass } 428*aba92962SSimon Glass 429*aba92962SSimon Glass /* Bind a generic driver so that the device can be used */ 430*aba92962SSimon Glass sprintf(name, "pci_%x:%x.%x", parent->seq, PCI_DEV(devfn), 431*aba92962SSimon Glass PCI_FUNC(devfn)); 432*aba92962SSimon Glass str = strdup(name); 433*aba92962SSimon Glass if (!str) 434*aba92962SSimon Glass return -ENOMEM; 435*aba92962SSimon Glass drv = (find_id->class >> 8) == PCI_CLASS_BRIDGE_PCI ? "pci_bridge_drv" : 436*aba92962SSimon Glass "pci_generic_drv"; 437*aba92962SSimon Glass ret = device_bind_driver(parent, drv, str, devp); 438*aba92962SSimon Glass if (ret) { 439*aba92962SSimon Glass debug("%s: Failed to bind generic driver: %d", __func__, ret); 440*aba92962SSimon Glass return ret; 441*aba92962SSimon Glass } 442*aba92962SSimon Glass debug("%s: No match found: bound generic driver instead\n", __func__); 443*aba92962SSimon Glass 444*aba92962SSimon Glass return 0; 445*aba92962SSimon Glass 446*aba92962SSimon Glass error: 447*aba92962SSimon Glass debug("%s: No match found: error %d\n", __func__, ret); 448*aba92962SSimon Glass return ret; 449*aba92962SSimon Glass } 450*aba92962SSimon Glass 451ff3e077bSSimon Glass int pci_bind_bus_devices(struct udevice *bus) 452ff3e077bSSimon Glass { 453ff3e077bSSimon Glass ulong vendor, device; 454ff3e077bSSimon Glass ulong header_type; 455ff3e077bSSimon Glass pci_dev_t devfn, end; 456ff3e077bSSimon Glass bool found_multi; 457ff3e077bSSimon Glass int ret; 458ff3e077bSSimon Glass 459ff3e077bSSimon Glass found_multi = false; 460ff3e077bSSimon Glass end = PCI_DEVFN(PCI_MAX_PCI_DEVICES - 1, PCI_MAX_PCI_FUNCTIONS - 1); 461ff3e077bSSimon Glass for (devfn = PCI_DEVFN(0, 0); devfn < end; devfn += PCI_DEVFN(0, 1)) { 462ff3e077bSSimon Glass struct pci_child_platdata *pplat; 463ff3e077bSSimon Glass struct udevice *dev; 464ff3e077bSSimon Glass ulong class; 465ff3e077bSSimon Glass 466ff3e077bSSimon Glass if (PCI_FUNC(devfn) && !found_multi) 467ff3e077bSSimon Glass continue; 468ff3e077bSSimon Glass /* Check only the first access, we don't expect problems */ 469ff3e077bSSimon Glass ret = pci_bus_read_config(bus, devfn, PCI_HEADER_TYPE, 470ff3e077bSSimon Glass &header_type, PCI_SIZE_8); 471ff3e077bSSimon Glass if (ret) 472ff3e077bSSimon Glass goto error; 473ff3e077bSSimon Glass pci_bus_read_config(bus, devfn, PCI_VENDOR_ID, &vendor, 474ff3e077bSSimon Glass PCI_SIZE_16); 475ff3e077bSSimon Glass if (vendor == 0xffff || vendor == 0x0000) 476ff3e077bSSimon Glass continue; 477ff3e077bSSimon Glass 478ff3e077bSSimon Glass if (!PCI_FUNC(devfn)) 479ff3e077bSSimon Glass found_multi = header_type & 0x80; 480ff3e077bSSimon Glass 481ff3e077bSSimon Glass debug("%s: bus %d/%s: found device %x, function %d\n", __func__, 482ff3e077bSSimon Glass bus->seq, bus->name, PCI_DEV(devfn), PCI_FUNC(devfn)); 483ff3e077bSSimon Glass pci_bus_read_config(bus, devfn, PCI_DEVICE_ID, &device, 484ff3e077bSSimon Glass PCI_SIZE_16); 485*aba92962SSimon Glass pci_bus_read_config(bus, devfn, PCI_CLASS_REVISION, &class, 486*aba92962SSimon Glass PCI_SIZE_32); 487*aba92962SSimon Glass class >>= 8; 488ff3e077bSSimon Glass 489ff3e077bSSimon Glass /* Find this device in the device tree */ 490ff3e077bSSimon Glass ret = pci_bus_find_devfn(bus, devfn, &dev); 491ff3e077bSSimon Glass 492*aba92962SSimon Glass /* Search for a driver */ 493*aba92962SSimon Glass 494ff3e077bSSimon Glass /* If nothing in the device tree, bind a generic device */ 495ff3e077bSSimon Glass if (ret == -ENODEV) { 496*aba92962SSimon Glass struct pci_device_id find_id; 497*aba92962SSimon Glass ulong val; 498ff3e077bSSimon Glass 499*aba92962SSimon Glass memset(&find_id, '\0', sizeof(find_id)); 500*aba92962SSimon Glass find_id.vendor = vendor; 501*aba92962SSimon Glass find_id.device = device; 502*aba92962SSimon Glass find_id.class = class; 503*aba92962SSimon Glass if ((header_type & 0x7f) == PCI_HEADER_TYPE_NORMAL) { 504*aba92962SSimon Glass pci_bus_read_config(bus, devfn, 505*aba92962SSimon Glass PCI_SUBSYSTEM_VENDOR_ID, 506*aba92962SSimon Glass &val, PCI_SIZE_32); 507*aba92962SSimon Glass find_id.subvendor = val & 0xffff; 508*aba92962SSimon Glass find_id.subdevice = val >> 16; 509*aba92962SSimon Glass } 510*aba92962SSimon Glass ret = pci_find_and_bind_driver(bus, &find_id, devfn, 511*aba92962SSimon Glass &dev); 512ff3e077bSSimon Glass } 513ff3e077bSSimon Glass if (ret) 514ff3e077bSSimon Glass return ret; 515ff3e077bSSimon Glass 516ff3e077bSSimon Glass /* Update the platform data */ 517ff3e077bSSimon Glass pplat = dev_get_parent_platdata(dev); 518ff3e077bSSimon Glass pplat->devfn = devfn; 519ff3e077bSSimon Glass pplat->vendor = vendor; 520ff3e077bSSimon Glass pplat->device = device; 521ff3e077bSSimon Glass pplat->class = class; 522ff3e077bSSimon Glass } 523ff3e077bSSimon Glass 524ff3e077bSSimon Glass return 0; 525ff3e077bSSimon Glass error: 526ff3e077bSSimon Glass printf("Cannot read bus configuration: %d\n", ret); 527ff3e077bSSimon Glass 528ff3e077bSSimon Glass return ret; 529ff3e077bSSimon Glass } 530ff3e077bSSimon Glass 531ff3e077bSSimon Glass static int pci_uclass_post_bind(struct udevice *bus) 532ff3e077bSSimon Glass { 533ff3e077bSSimon Glass /* 534ff3e077bSSimon Glass * Scan the device tree for devices. This does not probe the PCI bus, 535ff3e077bSSimon Glass * as this is not permitted while binding. It just finds devices 536ff3e077bSSimon Glass * mentioned in the device tree. 537ff3e077bSSimon Glass * 538ff3e077bSSimon Glass * Before relocation, only bind devices marked for pre-relocation 539ff3e077bSSimon Glass * use. 540ff3e077bSSimon Glass */ 541ff3e077bSSimon Glass return dm_scan_fdt_node(bus, gd->fdt_blob, bus->of_offset, 542ff3e077bSSimon Glass gd->flags & GD_FLG_RELOC ? false : true); 543ff3e077bSSimon Glass } 544ff3e077bSSimon Glass 545ff3e077bSSimon Glass static int decode_regions(struct pci_controller *hose, const void *blob, 546ff3e077bSSimon Glass int parent_node, int node) 547ff3e077bSSimon Glass { 548ff3e077bSSimon Glass int pci_addr_cells, addr_cells, size_cells; 549ff3e077bSSimon Glass int cells_per_record; 550b9da5086SSimon Glass phys_addr_t addr; 551ff3e077bSSimon Glass const u32 *prop; 552ff3e077bSSimon Glass int len; 553ff3e077bSSimon Glass int i; 554ff3e077bSSimon Glass 555ff3e077bSSimon Glass prop = fdt_getprop(blob, node, "ranges", &len); 556ff3e077bSSimon Glass if (!prop) 557ff3e077bSSimon Glass return -EINVAL; 558ff3e077bSSimon Glass pci_addr_cells = fdt_address_cells(blob, node); 559ff3e077bSSimon Glass addr_cells = fdt_address_cells(blob, parent_node); 560ff3e077bSSimon Glass size_cells = fdt_size_cells(blob, node); 561ff3e077bSSimon Glass 562ff3e077bSSimon Glass /* PCI addresses are always 3-cells */ 563ff3e077bSSimon Glass len /= sizeof(u32); 564ff3e077bSSimon Glass cells_per_record = pci_addr_cells + addr_cells + size_cells; 565ff3e077bSSimon Glass hose->region_count = 0; 566ff3e077bSSimon Glass debug("%s: len=%d, cells_per_record=%d\n", __func__, len, 567ff3e077bSSimon Glass cells_per_record); 568ff3e077bSSimon Glass for (i = 0; i < MAX_PCI_REGIONS; i++, len -= cells_per_record) { 569ff3e077bSSimon Glass u64 pci_addr, addr, size; 570ff3e077bSSimon Glass int space_code; 571ff3e077bSSimon Glass u32 flags; 572ff3e077bSSimon Glass int type; 573ff3e077bSSimon Glass 574ff3e077bSSimon Glass if (len < cells_per_record) 575ff3e077bSSimon Glass break; 576ff3e077bSSimon Glass flags = fdt32_to_cpu(prop[0]); 577ff3e077bSSimon Glass space_code = (flags >> 24) & 3; 578ff3e077bSSimon Glass pci_addr = fdtdec_get_number(prop + 1, 2); 579ff3e077bSSimon Glass prop += pci_addr_cells; 580ff3e077bSSimon Glass addr = fdtdec_get_number(prop, addr_cells); 581ff3e077bSSimon Glass prop += addr_cells; 582ff3e077bSSimon Glass size = fdtdec_get_number(prop, size_cells); 583ff3e077bSSimon Glass prop += size_cells; 584ff3e077bSSimon Glass debug("%s: region %d, pci_addr=%" PRIx64 ", addr=%" PRIx64 585ff3e077bSSimon Glass ", size=%" PRIx64 ", space_code=%d\n", __func__, 586ff3e077bSSimon Glass hose->region_count, pci_addr, addr, size, space_code); 587ff3e077bSSimon Glass if (space_code & 2) { 588ff3e077bSSimon Glass type = flags & (1U << 30) ? PCI_REGION_PREFETCH : 589ff3e077bSSimon Glass PCI_REGION_MEM; 590ff3e077bSSimon Glass } else if (space_code & 1) { 591ff3e077bSSimon Glass type = PCI_REGION_IO; 592ff3e077bSSimon Glass } else { 593ff3e077bSSimon Glass continue; 594ff3e077bSSimon Glass } 595ff3e077bSSimon Glass debug(" - type=%d\n", type); 596ff3e077bSSimon Glass pci_set_region(hose->regions + hose->region_count++, pci_addr, 597ff3e077bSSimon Glass addr, size, type); 598ff3e077bSSimon Glass } 599ff3e077bSSimon Glass 600ff3e077bSSimon Glass /* Add a region for our local memory */ 601b9da5086SSimon Glass addr = gd->ram_size; 602b9da5086SSimon Glass if (gd->pci_ram_top && gd->pci_ram_top < addr) 603b9da5086SSimon Glass addr = gd->pci_ram_top; 604b9da5086SSimon Glass pci_set_region(hose->regions + hose->region_count++, 0, 0, addr, 605b9da5086SSimon Glass PCI_REGION_MEM | PCI_REGION_SYS_MEMORY); 606ff3e077bSSimon Glass 607ff3e077bSSimon Glass return 0; 608ff3e077bSSimon Glass } 609ff3e077bSSimon Glass 610ff3e077bSSimon Glass static int pci_uclass_pre_probe(struct udevice *bus) 611ff3e077bSSimon Glass { 612ff3e077bSSimon Glass struct pci_controller *hose; 613ff3e077bSSimon Glass int ret; 614ff3e077bSSimon Glass 615ff3e077bSSimon Glass debug("%s, bus=%d/%s, parent=%s\n", __func__, bus->seq, bus->name, 616ff3e077bSSimon Glass bus->parent->name); 617ff3e077bSSimon Glass hose = bus->uclass_priv; 618ff3e077bSSimon Glass 619ff3e077bSSimon Glass /* For bridges, use the top-level PCI controller */ 620ff3e077bSSimon Glass if (device_get_uclass_id(bus->parent) == UCLASS_ROOT) { 621ff3e077bSSimon Glass hose->ctlr = bus; 622ff3e077bSSimon Glass ret = decode_regions(hose, gd->fdt_blob, bus->parent->of_offset, 623ff3e077bSSimon Glass bus->of_offset); 624ff3e077bSSimon Glass if (ret) { 625ff3e077bSSimon Glass debug("%s: Cannot decode regions\n", __func__); 626ff3e077bSSimon Glass return ret; 627ff3e077bSSimon Glass } 628ff3e077bSSimon Glass } else { 629ff3e077bSSimon Glass struct pci_controller *parent_hose; 630ff3e077bSSimon Glass 631ff3e077bSSimon Glass parent_hose = dev_get_uclass_priv(bus->parent); 632ff3e077bSSimon Glass hose->ctlr = parent_hose->bus; 633ff3e077bSSimon Glass } 634ff3e077bSSimon Glass hose->bus = bus; 635ff3e077bSSimon Glass hose->first_busno = bus->seq; 636ff3e077bSSimon Glass hose->last_busno = bus->seq; 637ff3e077bSSimon Glass 638ff3e077bSSimon Glass return 0; 639ff3e077bSSimon Glass } 640ff3e077bSSimon Glass 641ff3e077bSSimon Glass static int pci_uclass_post_probe(struct udevice *bus) 642ff3e077bSSimon Glass { 643ff3e077bSSimon Glass int ret; 644ff3e077bSSimon Glass 645ff3e077bSSimon Glass /* Don't scan buses before relocation */ 646ff3e077bSSimon Glass if (!(gd->flags & GD_FLG_RELOC)) 647ff3e077bSSimon Glass return 0; 648ff3e077bSSimon Glass 649ff3e077bSSimon Glass debug("%s: probing bus %d\n", __func__, bus->seq); 650ff3e077bSSimon Glass ret = pci_bind_bus_devices(bus); 651ff3e077bSSimon Glass if (ret) 652ff3e077bSSimon Glass return ret; 653ff3e077bSSimon Glass 654ff3e077bSSimon Glass #ifdef CONFIG_PCI_PNP 655ff3e077bSSimon Glass ret = pci_auto_config_devices(bus); 656ff3e077bSSimon Glass #endif 657ff3e077bSSimon Glass 658ff3e077bSSimon Glass return ret < 0 ? ret : 0; 659ff3e077bSSimon Glass } 660ff3e077bSSimon Glass 661ff3e077bSSimon Glass static int pci_uclass_child_post_bind(struct udevice *dev) 662ff3e077bSSimon Glass { 663ff3e077bSSimon Glass struct pci_child_platdata *pplat; 664ff3e077bSSimon Glass struct fdt_pci_addr addr; 665ff3e077bSSimon Glass int ret; 666ff3e077bSSimon Glass 667ff3e077bSSimon Glass if (dev->of_offset == -1) 668ff3e077bSSimon Glass return 0; 669ff3e077bSSimon Glass 670ff3e077bSSimon Glass /* 671ff3e077bSSimon Glass * We could read vendor, device, class if available. But for now we 672ff3e077bSSimon Glass * just check the address. 673ff3e077bSSimon Glass */ 674ff3e077bSSimon Glass pplat = dev_get_parent_platdata(dev); 675ff3e077bSSimon Glass ret = fdtdec_get_pci_addr(gd->fdt_blob, dev->of_offset, 676ff3e077bSSimon Glass FDT_PCI_SPACE_CONFIG, "reg", &addr); 677ff3e077bSSimon Glass 678ff3e077bSSimon Glass if (ret) { 679ff3e077bSSimon Glass if (ret != -ENOENT) 680ff3e077bSSimon Glass return -EINVAL; 681ff3e077bSSimon Glass } else { 682ff3e077bSSimon Glass /* extract the bdf from fdt_pci_addr */ 683ff3e077bSSimon Glass pplat->devfn = addr.phys_hi & 0xffff00; 684ff3e077bSSimon Glass } 685ff3e077bSSimon Glass 686ff3e077bSSimon Glass return 0; 687ff3e077bSSimon Glass } 688ff3e077bSSimon Glass 689ff3e077bSSimon Glass int pci_bridge_read_config(struct udevice *bus, pci_dev_t devfn, uint offset, 690ff3e077bSSimon Glass ulong *valuep, enum pci_size_t size) 691ff3e077bSSimon Glass { 692ff3e077bSSimon Glass struct pci_controller *hose = bus->uclass_priv; 693ff3e077bSSimon Glass pci_dev_t bdf = PCI_ADD_BUS(bus->seq, devfn); 694ff3e077bSSimon Glass 695ff3e077bSSimon Glass return pci_bus_read_config(hose->ctlr, bdf, offset, valuep, size); 696ff3e077bSSimon Glass } 697ff3e077bSSimon Glass 698ff3e077bSSimon Glass int pci_bridge_write_config(struct udevice *bus, pci_dev_t devfn, uint offset, 699ff3e077bSSimon Glass ulong value, enum pci_size_t size) 700ff3e077bSSimon Glass { 701ff3e077bSSimon Glass struct pci_controller *hose = bus->uclass_priv; 702ff3e077bSSimon Glass pci_dev_t bdf = PCI_ADD_BUS(bus->seq, devfn); 703ff3e077bSSimon Glass 704ff3e077bSSimon Glass return pci_bus_write_config(hose->ctlr, bdf, offset, value, size); 705ff3e077bSSimon Glass } 706ff3e077bSSimon Glass 707ff3e077bSSimon Glass UCLASS_DRIVER(pci) = { 708ff3e077bSSimon Glass .id = UCLASS_PCI, 709ff3e077bSSimon Glass .name = "pci", 7102bb02e4fSSimon Glass .flags = DM_UC_FLAG_SEQ_ALIAS, 711ff3e077bSSimon Glass .post_bind = pci_uclass_post_bind, 712ff3e077bSSimon Glass .pre_probe = pci_uclass_pre_probe, 713ff3e077bSSimon Glass .post_probe = pci_uclass_post_probe, 714ff3e077bSSimon Glass .child_post_bind = pci_uclass_child_post_bind, 715ff3e077bSSimon Glass .per_device_auto_alloc_size = sizeof(struct pci_controller), 716ff3e077bSSimon Glass .per_child_platdata_auto_alloc_size = 717ff3e077bSSimon Glass sizeof(struct pci_child_platdata), 718ff3e077bSSimon Glass }; 719ff3e077bSSimon Glass 720ff3e077bSSimon Glass static const struct dm_pci_ops pci_bridge_ops = { 721ff3e077bSSimon Glass .read_config = pci_bridge_read_config, 722ff3e077bSSimon Glass .write_config = pci_bridge_write_config, 723ff3e077bSSimon Glass }; 724ff3e077bSSimon Glass 725ff3e077bSSimon Glass static const struct udevice_id pci_bridge_ids[] = { 726ff3e077bSSimon Glass { .compatible = "pci-bridge" }, 727ff3e077bSSimon Glass { } 728ff3e077bSSimon Glass }; 729ff3e077bSSimon Glass 730ff3e077bSSimon Glass U_BOOT_DRIVER(pci_bridge_drv) = { 731ff3e077bSSimon Glass .name = "pci_bridge_drv", 732ff3e077bSSimon Glass .id = UCLASS_PCI, 733ff3e077bSSimon Glass .of_match = pci_bridge_ids, 734ff3e077bSSimon Glass .ops = &pci_bridge_ops, 735ff3e077bSSimon Glass }; 736ff3e077bSSimon Glass 737ff3e077bSSimon Glass UCLASS_DRIVER(pci_generic) = { 738ff3e077bSSimon Glass .id = UCLASS_PCI_GENERIC, 739ff3e077bSSimon Glass .name = "pci_generic", 740ff3e077bSSimon Glass }; 741ff3e077bSSimon Glass 742ff3e077bSSimon Glass static const struct udevice_id pci_generic_ids[] = { 743ff3e077bSSimon Glass { .compatible = "pci-generic" }, 744ff3e077bSSimon Glass { } 745ff3e077bSSimon Glass }; 746ff3e077bSSimon Glass 747ff3e077bSSimon Glass U_BOOT_DRIVER(pci_generic_drv) = { 748ff3e077bSSimon Glass .name = "pci_generic_drv", 749ff3e077bSSimon Glass .id = UCLASS_PCI_GENERIC, 750ff3e077bSSimon Glass .of_match = pci_generic_ids, 751ff3e077bSSimon Glass }; 752