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); 337*5afeb4bbSSimon 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 356ff3e077bSSimon Glass int pci_bind_bus_devices(struct udevice *bus) 357ff3e077bSSimon Glass { 358ff3e077bSSimon Glass ulong vendor, device; 359ff3e077bSSimon Glass ulong header_type; 360ff3e077bSSimon Glass pci_dev_t devfn, end; 361ff3e077bSSimon Glass bool found_multi; 362ff3e077bSSimon Glass int ret; 363ff3e077bSSimon Glass 364ff3e077bSSimon Glass found_multi = false; 365ff3e077bSSimon Glass end = PCI_DEVFN(PCI_MAX_PCI_DEVICES - 1, PCI_MAX_PCI_FUNCTIONS - 1); 366ff3e077bSSimon Glass for (devfn = PCI_DEVFN(0, 0); devfn < end; devfn += PCI_DEVFN(0, 1)) { 367ff3e077bSSimon Glass struct pci_child_platdata *pplat; 368ff3e077bSSimon Glass struct udevice *dev; 369ff3e077bSSimon Glass ulong class; 370ff3e077bSSimon Glass 371ff3e077bSSimon Glass if (PCI_FUNC(devfn) && !found_multi) 372ff3e077bSSimon Glass continue; 373ff3e077bSSimon Glass /* Check only the first access, we don't expect problems */ 374ff3e077bSSimon Glass ret = pci_bus_read_config(bus, devfn, PCI_HEADER_TYPE, 375ff3e077bSSimon Glass &header_type, PCI_SIZE_8); 376ff3e077bSSimon Glass if (ret) 377ff3e077bSSimon Glass goto error; 378ff3e077bSSimon Glass pci_bus_read_config(bus, devfn, PCI_VENDOR_ID, &vendor, 379ff3e077bSSimon Glass PCI_SIZE_16); 380ff3e077bSSimon Glass if (vendor == 0xffff || vendor == 0x0000) 381ff3e077bSSimon Glass continue; 382ff3e077bSSimon Glass 383ff3e077bSSimon Glass if (!PCI_FUNC(devfn)) 384ff3e077bSSimon Glass found_multi = header_type & 0x80; 385ff3e077bSSimon Glass 386ff3e077bSSimon Glass debug("%s: bus %d/%s: found device %x, function %d\n", __func__, 387ff3e077bSSimon Glass bus->seq, bus->name, PCI_DEV(devfn), PCI_FUNC(devfn)); 388ff3e077bSSimon Glass pci_bus_read_config(bus, devfn, PCI_DEVICE_ID, &device, 389ff3e077bSSimon Glass PCI_SIZE_16); 390ff3e077bSSimon Glass pci_bus_read_config(bus, devfn, PCI_CLASS_DEVICE, &class, 391ff3e077bSSimon Glass PCI_SIZE_16); 392ff3e077bSSimon Glass 393ff3e077bSSimon Glass /* Find this device in the device tree */ 394ff3e077bSSimon Glass ret = pci_bus_find_devfn(bus, devfn, &dev); 395ff3e077bSSimon Glass 396ff3e077bSSimon Glass /* If nothing in the device tree, bind a generic device */ 397ff3e077bSSimon Glass if (ret == -ENODEV) { 398ff3e077bSSimon Glass char name[30], *str; 399ff3e077bSSimon Glass const char *drv; 400ff3e077bSSimon Glass 401ff3e077bSSimon Glass sprintf(name, "pci_%x:%x.%x", bus->seq, 402ff3e077bSSimon Glass PCI_DEV(devfn), PCI_FUNC(devfn)); 403ff3e077bSSimon Glass str = strdup(name); 404ff3e077bSSimon Glass if (!str) 405ff3e077bSSimon Glass return -ENOMEM; 406ff3e077bSSimon Glass drv = class == PCI_CLASS_BRIDGE_PCI ? 407ff3e077bSSimon Glass "pci_bridge_drv" : "pci_generic_drv"; 408ff3e077bSSimon Glass ret = device_bind_driver(bus, drv, str, &dev); 409ff3e077bSSimon Glass } 410ff3e077bSSimon Glass if (ret) 411ff3e077bSSimon Glass return ret; 412ff3e077bSSimon Glass 413ff3e077bSSimon Glass /* Update the platform data */ 414ff3e077bSSimon Glass pplat = dev_get_parent_platdata(dev); 415ff3e077bSSimon Glass pplat->devfn = devfn; 416ff3e077bSSimon Glass pplat->vendor = vendor; 417ff3e077bSSimon Glass pplat->device = device; 418ff3e077bSSimon Glass pplat->class = class; 419ff3e077bSSimon Glass } 420ff3e077bSSimon Glass 421ff3e077bSSimon Glass return 0; 422ff3e077bSSimon Glass error: 423ff3e077bSSimon Glass printf("Cannot read bus configuration: %d\n", ret); 424ff3e077bSSimon Glass 425ff3e077bSSimon Glass return ret; 426ff3e077bSSimon Glass } 427ff3e077bSSimon Glass 428ff3e077bSSimon Glass static int pci_uclass_post_bind(struct udevice *bus) 429ff3e077bSSimon Glass { 430ff3e077bSSimon Glass /* 431ff3e077bSSimon Glass * Scan the device tree for devices. This does not probe the PCI bus, 432ff3e077bSSimon Glass * as this is not permitted while binding. It just finds devices 433ff3e077bSSimon Glass * mentioned in the device tree. 434ff3e077bSSimon Glass * 435ff3e077bSSimon Glass * Before relocation, only bind devices marked for pre-relocation 436ff3e077bSSimon Glass * use. 437ff3e077bSSimon Glass */ 438ff3e077bSSimon Glass return dm_scan_fdt_node(bus, gd->fdt_blob, bus->of_offset, 439ff3e077bSSimon Glass gd->flags & GD_FLG_RELOC ? false : true); 440ff3e077bSSimon Glass } 441ff3e077bSSimon Glass 442ff3e077bSSimon Glass static int decode_regions(struct pci_controller *hose, const void *blob, 443ff3e077bSSimon Glass int parent_node, int node) 444ff3e077bSSimon Glass { 445ff3e077bSSimon Glass int pci_addr_cells, addr_cells, size_cells; 446ff3e077bSSimon Glass int cells_per_record; 447ff3e077bSSimon Glass const u32 *prop; 448ff3e077bSSimon Glass int len; 449ff3e077bSSimon Glass int i; 450ff3e077bSSimon Glass 451ff3e077bSSimon Glass prop = fdt_getprop(blob, node, "ranges", &len); 452ff3e077bSSimon Glass if (!prop) 453ff3e077bSSimon Glass return -EINVAL; 454ff3e077bSSimon Glass pci_addr_cells = fdt_address_cells(blob, node); 455ff3e077bSSimon Glass addr_cells = fdt_address_cells(blob, parent_node); 456ff3e077bSSimon Glass size_cells = fdt_size_cells(blob, node); 457ff3e077bSSimon Glass 458ff3e077bSSimon Glass /* PCI addresses are always 3-cells */ 459ff3e077bSSimon Glass len /= sizeof(u32); 460ff3e077bSSimon Glass cells_per_record = pci_addr_cells + addr_cells + size_cells; 461ff3e077bSSimon Glass hose->region_count = 0; 462ff3e077bSSimon Glass debug("%s: len=%d, cells_per_record=%d\n", __func__, len, 463ff3e077bSSimon Glass cells_per_record); 464ff3e077bSSimon Glass for (i = 0; i < MAX_PCI_REGIONS; i++, len -= cells_per_record) { 465ff3e077bSSimon Glass u64 pci_addr, addr, size; 466ff3e077bSSimon Glass int space_code; 467ff3e077bSSimon Glass u32 flags; 468ff3e077bSSimon Glass int type; 469ff3e077bSSimon Glass 470ff3e077bSSimon Glass if (len < cells_per_record) 471ff3e077bSSimon Glass break; 472ff3e077bSSimon Glass flags = fdt32_to_cpu(prop[0]); 473ff3e077bSSimon Glass space_code = (flags >> 24) & 3; 474ff3e077bSSimon Glass pci_addr = fdtdec_get_number(prop + 1, 2); 475ff3e077bSSimon Glass prop += pci_addr_cells; 476ff3e077bSSimon Glass addr = fdtdec_get_number(prop, addr_cells); 477ff3e077bSSimon Glass prop += addr_cells; 478ff3e077bSSimon Glass size = fdtdec_get_number(prop, size_cells); 479ff3e077bSSimon Glass prop += size_cells; 480ff3e077bSSimon Glass debug("%s: region %d, pci_addr=%" PRIx64 ", addr=%" PRIx64 481ff3e077bSSimon Glass ", size=%" PRIx64 ", space_code=%d\n", __func__, 482ff3e077bSSimon Glass hose->region_count, pci_addr, addr, size, space_code); 483ff3e077bSSimon Glass if (space_code & 2) { 484ff3e077bSSimon Glass type = flags & (1U << 30) ? PCI_REGION_PREFETCH : 485ff3e077bSSimon Glass PCI_REGION_MEM; 486ff3e077bSSimon Glass } else if (space_code & 1) { 487ff3e077bSSimon Glass type = PCI_REGION_IO; 488ff3e077bSSimon Glass } else { 489ff3e077bSSimon Glass continue; 490ff3e077bSSimon Glass } 491ff3e077bSSimon Glass debug(" - type=%d\n", type); 492ff3e077bSSimon Glass pci_set_region(hose->regions + hose->region_count++, pci_addr, 493ff3e077bSSimon Glass addr, size, type); 494ff3e077bSSimon Glass } 495ff3e077bSSimon Glass 496ff3e077bSSimon Glass /* Add a region for our local memory */ 497ff3e077bSSimon Glass pci_set_region(hose->regions + hose->region_count++, 0, 0, 498ff3e077bSSimon Glass gd->ram_size, PCI_REGION_MEM | PCI_REGION_SYS_MEMORY); 499ff3e077bSSimon Glass 500ff3e077bSSimon Glass return 0; 501ff3e077bSSimon Glass } 502ff3e077bSSimon Glass 503ff3e077bSSimon Glass static int pci_uclass_pre_probe(struct udevice *bus) 504ff3e077bSSimon Glass { 505ff3e077bSSimon Glass struct pci_controller *hose; 506ff3e077bSSimon Glass int ret; 507ff3e077bSSimon Glass 508ff3e077bSSimon Glass debug("%s, bus=%d/%s, parent=%s\n", __func__, bus->seq, bus->name, 509ff3e077bSSimon Glass bus->parent->name); 510ff3e077bSSimon Glass hose = bus->uclass_priv; 511ff3e077bSSimon Glass 512ff3e077bSSimon Glass /* For bridges, use the top-level PCI controller */ 513ff3e077bSSimon Glass if (device_get_uclass_id(bus->parent) == UCLASS_ROOT) { 514ff3e077bSSimon Glass hose->ctlr = bus; 515ff3e077bSSimon Glass ret = decode_regions(hose, gd->fdt_blob, bus->parent->of_offset, 516ff3e077bSSimon Glass bus->of_offset); 517ff3e077bSSimon Glass if (ret) { 518ff3e077bSSimon Glass debug("%s: Cannot decode regions\n", __func__); 519ff3e077bSSimon Glass return ret; 520ff3e077bSSimon Glass } 521ff3e077bSSimon Glass } else { 522ff3e077bSSimon Glass struct pci_controller *parent_hose; 523ff3e077bSSimon Glass 524ff3e077bSSimon Glass parent_hose = dev_get_uclass_priv(bus->parent); 525ff3e077bSSimon Glass hose->ctlr = parent_hose->bus; 526ff3e077bSSimon Glass } 527ff3e077bSSimon Glass hose->bus = bus; 528ff3e077bSSimon Glass hose->first_busno = bus->seq; 529ff3e077bSSimon Glass hose->last_busno = bus->seq; 530ff3e077bSSimon Glass 531ff3e077bSSimon Glass return 0; 532ff3e077bSSimon Glass } 533ff3e077bSSimon Glass 534ff3e077bSSimon Glass static int pci_uclass_post_probe(struct udevice *bus) 535ff3e077bSSimon Glass { 536ff3e077bSSimon Glass int ret; 537ff3e077bSSimon Glass 538ff3e077bSSimon Glass /* Don't scan buses before relocation */ 539ff3e077bSSimon Glass if (!(gd->flags & GD_FLG_RELOC)) 540ff3e077bSSimon Glass return 0; 541ff3e077bSSimon Glass 542ff3e077bSSimon Glass debug("%s: probing bus %d\n", __func__, bus->seq); 543ff3e077bSSimon Glass ret = pci_bind_bus_devices(bus); 544ff3e077bSSimon Glass if (ret) 545ff3e077bSSimon Glass return ret; 546ff3e077bSSimon Glass 547ff3e077bSSimon Glass #ifdef CONFIG_PCI_PNP 548ff3e077bSSimon Glass ret = pci_auto_config_devices(bus); 549ff3e077bSSimon Glass #endif 550ff3e077bSSimon Glass 551ff3e077bSSimon Glass return ret < 0 ? ret : 0; 552ff3e077bSSimon Glass } 553ff3e077bSSimon Glass 554ff3e077bSSimon Glass static int pci_uclass_child_post_bind(struct udevice *dev) 555ff3e077bSSimon Glass { 556ff3e077bSSimon Glass struct pci_child_platdata *pplat; 557ff3e077bSSimon Glass struct fdt_pci_addr addr; 558ff3e077bSSimon Glass int ret; 559ff3e077bSSimon Glass 560ff3e077bSSimon Glass if (dev->of_offset == -1) 561ff3e077bSSimon Glass return 0; 562ff3e077bSSimon Glass 563ff3e077bSSimon Glass /* 564ff3e077bSSimon Glass * We could read vendor, device, class if available. But for now we 565ff3e077bSSimon Glass * just check the address. 566ff3e077bSSimon Glass */ 567ff3e077bSSimon Glass pplat = dev_get_parent_platdata(dev); 568ff3e077bSSimon Glass ret = fdtdec_get_pci_addr(gd->fdt_blob, dev->of_offset, 569ff3e077bSSimon Glass FDT_PCI_SPACE_CONFIG, "reg", &addr); 570ff3e077bSSimon Glass 571ff3e077bSSimon Glass if (ret) { 572ff3e077bSSimon Glass if (ret != -ENOENT) 573ff3e077bSSimon Glass return -EINVAL; 574ff3e077bSSimon Glass } else { 575ff3e077bSSimon Glass /* extract the bdf from fdt_pci_addr */ 576ff3e077bSSimon Glass pplat->devfn = addr.phys_hi & 0xffff00; 577ff3e077bSSimon Glass } 578ff3e077bSSimon Glass 579ff3e077bSSimon Glass return 0; 580ff3e077bSSimon Glass } 581ff3e077bSSimon Glass 582ff3e077bSSimon Glass int pci_bridge_read_config(struct udevice *bus, pci_dev_t devfn, uint offset, 583ff3e077bSSimon Glass ulong *valuep, enum pci_size_t size) 584ff3e077bSSimon Glass { 585ff3e077bSSimon Glass struct pci_controller *hose = bus->uclass_priv; 586ff3e077bSSimon Glass pci_dev_t bdf = PCI_ADD_BUS(bus->seq, devfn); 587ff3e077bSSimon Glass 588ff3e077bSSimon Glass return pci_bus_read_config(hose->ctlr, bdf, offset, valuep, size); 589ff3e077bSSimon Glass } 590ff3e077bSSimon Glass 591ff3e077bSSimon Glass int pci_bridge_write_config(struct udevice *bus, pci_dev_t devfn, uint offset, 592ff3e077bSSimon Glass ulong value, enum pci_size_t size) 593ff3e077bSSimon Glass { 594ff3e077bSSimon Glass struct pci_controller *hose = bus->uclass_priv; 595ff3e077bSSimon Glass pci_dev_t bdf = PCI_ADD_BUS(bus->seq, devfn); 596ff3e077bSSimon Glass 597ff3e077bSSimon Glass return pci_bus_write_config(hose->ctlr, bdf, offset, value, size); 598ff3e077bSSimon Glass } 599ff3e077bSSimon Glass 600ff3e077bSSimon Glass UCLASS_DRIVER(pci) = { 601ff3e077bSSimon Glass .id = UCLASS_PCI, 602ff3e077bSSimon Glass .name = "pci", 6032bb02e4fSSimon Glass .flags = DM_UC_FLAG_SEQ_ALIAS, 604ff3e077bSSimon Glass .post_bind = pci_uclass_post_bind, 605ff3e077bSSimon Glass .pre_probe = pci_uclass_pre_probe, 606ff3e077bSSimon Glass .post_probe = pci_uclass_post_probe, 607ff3e077bSSimon Glass .child_post_bind = pci_uclass_child_post_bind, 608ff3e077bSSimon Glass .per_device_auto_alloc_size = sizeof(struct pci_controller), 609ff3e077bSSimon Glass .per_child_platdata_auto_alloc_size = 610ff3e077bSSimon Glass sizeof(struct pci_child_platdata), 611ff3e077bSSimon Glass }; 612ff3e077bSSimon Glass 613ff3e077bSSimon Glass static const struct dm_pci_ops pci_bridge_ops = { 614ff3e077bSSimon Glass .read_config = pci_bridge_read_config, 615ff3e077bSSimon Glass .write_config = pci_bridge_write_config, 616ff3e077bSSimon Glass }; 617ff3e077bSSimon Glass 618ff3e077bSSimon Glass static const struct udevice_id pci_bridge_ids[] = { 619ff3e077bSSimon Glass { .compatible = "pci-bridge" }, 620ff3e077bSSimon Glass { } 621ff3e077bSSimon Glass }; 622ff3e077bSSimon Glass 623ff3e077bSSimon Glass U_BOOT_DRIVER(pci_bridge_drv) = { 624ff3e077bSSimon Glass .name = "pci_bridge_drv", 625ff3e077bSSimon Glass .id = UCLASS_PCI, 626ff3e077bSSimon Glass .of_match = pci_bridge_ids, 627ff3e077bSSimon Glass .ops = &pci_bridge_ops, 628ff3e077bSSimon Glass }; 629ff3e077bSSimon Glass 630ff3e077bSSimon Glass UCLASS_DRIVER(pci_generic) = { 631ff3e077bSSimon Glass .id = UCLASS_PCI_GENERIC, 632ff3e077bSSimon Glass .name = "pci_generic", 633ff3e077bSSimon Glass }; 634ff3e077bSSimon Glass 635ff3e077bSSimon Glass static const struct udevice_id pci_generic_ids[] = { 636ff3e077bSSimon Glass { .compatible = "pci-generic" }, 637ff3e077bSSimon Glass { } 638ff3e077bSSimon Glass }; 639ff3e077bSSimon Glass 640ff3e077bSSimon Glass U_BOOT_DRIVER(pci_generic_drv) = { 641ff3e077bSSimon Glass .name = "pci_generic_drv", 642ff3e077bSSimon Glass .id = UCLASS_PCI_GENERIC, 643ff3e077bSSimon Glass .of_match = pci_generic_ids, 644ff3e077bSSimon Glass }; 645