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 <inttypes.h> 12ff3e077bSSimon Glass #include <pci.h> 1321d1fe7eSSimon Glass #include <asm/io.h> 14ff3e077bSSimon Glass #include <dm/device-internal.h> 15bf501595SSimon Glass #include <dm/lists.h> 16348b744bSBin Meng #if defined(CONFIG_X86) && defined(CONFIG_HAVE_FSP) 17348b744bSBin Meng #include <asm/fsp/fsp_support.h> 18348b744bSBin Meng #endif 195e23b8b4SSimon Glass #include "pci_internal.h" 20ff3e077bSSimon Glass 21ff3e077bSSimon Glass DECLARE_GLOBAL_DATA_PTR; 22ff3e077bSSimon Glass 23a6eb93b3SSimon Glass 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) { 313f603cbbSSimon Glass ret = uclass_first_device_err(UCLASS_PCI, busp); 32983c6ba2SSimon Glass if (ret) 33983c6ba2SSimon Glass return ret; 34983c6ba2SSimon Glass ret = uclass_get_device_by_seq(UCLASS_PCI, busnum, busp); 35983c6ba2SSimon Glass } 36983c6ba2SSimon Glass 37983c6ba2SSimon Glass return ret; 38983c6ba2SSimon Glass } 39983c6ba2SSimon Glass 409f60fb0dSSimon Glass struct udevice *pci_get_controller(struct udevice *dev) 419f60fb0dSSimon Glass { 429f60fb0dSSimon Glass while (device_is_on_pci_bus(dev)) 439f60fb0dSSimon Glass dev = dev->parent; 449f60fb0dSSimon Glass 459f60fb0dSSimon Glass return dev; 469f60fb0dSSimon Glass } 479f60fb0dSSimon Glass 4821ccce1bSSimon Glass pci_dev_t dm_pci_get_bdf(struct udevice *dev) 494b515e4fSSimon Glass { 504b515e4fSSimon Glass struct pci_child_platdata *pplat = dev_get_parent_platdata(dev); 514b515e4fSSimon Glass struct udevice *bus = dev->parent; 524b515e4fSSimon Glass 534b515e4fSSimon Glass return PCI_ADD_BUS(bus->seq, pplat->devfn); 544b515e4fSSimon Glass } 554b515e4fSSimon Glass 56ff3e077bSSimon Glass /** 57ff3e077bSSimon Glass * pci_get_bus_max() - returns the bus number of the last active bus 58ff3e077bSSimon Glass * 59ff3e077bSSimon Glass * @return last bus number, or -1 if no active buses 60ff3e077bSSimon Glass */ 61ff3e077bSSimon Glass static int pci_get_bus_max(void) 62ff3e077bSSimon Glass { 63ff3e077bSSimon Glass struct udevice *bus; 64ff3e077bSSimon Glass struct uclass *uc; 65ff3e077bSSimon Glass int ret = -1; 66ff3e077bSSimon Glass 67ff3e077bSSimon Glass ret = uclass_get(UCLASS_PCI, &uc); 68ff3e077bSSimon Glass uclass_foreach_dev(bus, uc) { 69ff3e077bSSimon Glass if (bus->seq > ret) 70ff3e077bSSimon Glass ret = bus->seq; 71ff3e077bSSimon Glass } 72ff3e077bSSimon Glass 73ff3e077bSSimon Glass debug("%s: ret=%d\n", __func__, ret); 74ff3e077bSSimon Glass 75ff3e077bSSimon Glass return ret; 76ff3e077bSSimon Glass } 77ff3e077bSSimon Glass 78ff3e077bSSimon Glass int pci_last_busno(void) 79ff3e077bSSimon Glass { 80069155cbSBin Meng return pci_get_bus_max(); 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 115f3f1faefSSimon Glass int dm_pci_bus_find_bdf(pci_dev_t bdf, struct udevice **devp) 116ff3e077bSSimon Glass { 117ff3e077bSSimon Glass struct udevice *bus; 118ff3e077bSSimon Glass int ret; 119ff3e077bSSimon Glass 120983c6ba2SSimon Glass ret = pci_get_bus(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 1815c0bf647SSimon Glass static int dm_pci_bus_find_device(struct udevice *bus, unsigned int vendor, 1825c0bf647SSimon Glass unsigned int device, int *indexp, 1835c0bf647SSimon Glass struct udevice **devp) 1845c0bf647SSimon Glass { 1855c0bf647SSimon Glass struct pci_child_platdata *pplat; 1865c0bf647SSimon Glass struct udevice *dev; 1875c0bf647SSimon Glass 1885c0bf647SSimon Glass for (device_find_first_child(bus, &dev); 1895c0bf647SSimon Glass dev; 1905c0bf647SSimon Glass device_find_next_child(&dev)) { 1915c0bf647SSimon Glass pplat = dev_get_parent_platdata(dev); 1925c0bf647SSimon Glass if (pplat->vendor == vendor && pplat->device == device) { 1935c0bf647SSimon Glass if (!(*indexp)--) { 1945c0bf647SSimon Glass *devp = dev; 1955c0bf647SSimon Glass return 0; 1965c0bf647SSimon Glass } 1975c0bf647SSimon Glass } 1985c0bf647SSimon Glass } 1995c0bf647SSimon Glass 2005c0bf647SSimon Glass return -ENODEV; 2015c0bf647SSimon Glass } 2025c0bf647SSimon Glass 2035c0bf647SSimon Glass int dm_pci_find_device(unsigned int vendor, unsigned int device, int index, 2045c0bf647SSimon Glass struct udevice **devp) 2055c0bf647SSimon Glass { 2065c0bf647SSimon Glass struct udevice *bus; 2075c0bf647SSimon Glass 2085c0bf647SSimon Glass /* Scan all known buses */ 2095c0bf647SSimon Glass for (uclass_first_device(UCLASS_PCI, &bus); 2105c0bf647SSimon Glass bus; 2115c0bf647SSimon Glass uclass_next_device(&bus)) { 2125c0bf647SSimon Glass if (!dm_pci_bus_find_device(bus, vendor, device, &index, devp)) 2135c0bf647SSimon Glass return device_probe(*devp); 2145c0bf647SSimon Glass } 2155c0bf647SSimon Glass *devp = NULL; 2165c0bf647SSimon Glass 2175c0bf647SSimon Glass return -ENODEV; 2185c0bf647SSimon Glass } 2195c0bf647SSimon Glass 220a0eb8356SSimon Glass int dm_pci_find_class(uint find_class, int index, struct udevice **devp) 221a0eb8356SSimon Glass { 222a0eb8356SSimon Glass struct udevice *dev; 223a0eb8356SSimon Glass 224a0eb8356SSimon Glass /* Scan all known buses */ 225a0eb8356SSimon Glass for (pci_find_first_device(&dev); 226a0eb8356SSimon Glass dev; 227a0eb8356SSimon Glass pci_find_next_device(&dev)) { 228a0eb8356SSimon Glass struct pci_child_platdata *pplat = dev_get_parent_platdata(dev); 229a0eb8356SSimon Glass 230a0eb8356SSimon Glass if (pplat->class == find_class && !index--) { 231a0eb8356SSimon Glass *devp = dev; 232a0eb8356SSimon Glass return device_probe(*devp); 233a0eb8356SSimon Glass } 234a0eb8356SSimon Glass } 235a0eb8356SSimon Glass *devp = NULL; 236a0eb8356SSimon Glass 237a0eb8356SSimon Glass return -ENODEV; 238a0eb8356SSimon Glass } 239a0eb8356SSimon Glass 240ff3e077bSSimon Glass int pci_bus_write_config(struct udevice *bus, pci_dev_t bdf, int offset, 241ff3e077bSSimon Glass unsigned long value, enum pci_size_t size) 242ff3e077bSSimon Glass { 243ff3e077bSSimon Glass struct dm_pci_ops *ops; 244ff3e077bSSimon Glass 245ff3e077bSSimon Glass ops = pci_get_ops(bus); 246ff3e077bSSimon Glass if (!ops->write_config) 247ff3e077bSSimon Glass return -ENOSYS; 248ff3e077bSSimon Glass return ops->write_config(bus, bdf, offset, value, size); 249ff3e077bSSimon Glass } 250ff3e077bSSimon Glass 251319dba1fSSimon Glass int pci_bus_clrset_config32(struct udevice *bus, pci_dev_t bdf, int offset, 252319dba1fSSimon Glass u32 clr, u32 set) 253319dba1fSSimon Glass { 254319dba1fSSimon Glass ulong val; 255319dba1fSSimon Glass int ret; 256319dba1fSSimon Glass 257319dba1fSSimon Glass ret = pci_bus_read_config(bus, bdf, offset, &val, PCI_SIZE_32); 258319dba1fSSimon Glass if (ret) 259319dba1fSSimon Glass return ret; 260319dba1fSSimon Glass val &= ~clr; 261319dba1fSSimon Glass val |= set; 262319dba1fSSimon Glass 263319dba1fSSimon Glass return pci_bus_write_config(bus, bdf, offset, val, PCI_SIZE_32); 264319dba1fSSimon Glass } 265319dba1fSSimon Glass 266ff3e077bSSimon Glass int pci_write_config(pci_dev_t bdf, int offset, unsigned long value, 267ff3e077bSSimon Glass enum pci_size_t size) 268ff3e077bSSimon Glass { 269ff3e077bSSimon Glass struct udevice *bus; 270ff3e077bSSimon Glass int ret; 271ff3e077bSSimon Glass 272983c6ba2SSimon Glass ret = pci_get_bus(PCI_BUS(bdf), &bus); 273ff3e077bSSimon Glass if (ret) 274ff3e077bSSimon Glass return ret; 275ff3e077bSSimon Glass 2764d8615cbSBin Meng return pci_bus_write_config(bus, bdf, offset, value, size); 277ff3e077bSSimon Glass } 278ff3e077bSSimon Glass 27966afb4edSSimon Glass int dm_pci_write_config(struct udevice *dev, int offset, unsigned long value, 28066afb4edSSimon Glass enum pci_size_t size) 28166afb4edSSimon Glass { 28266afb4edSSimon Glass struct udevice *bus; 28366afb4edSSimon Glass 2841e0f2263SBin Meng for (bus = dev; device_is_on_pci_bus(bus);) 28566afb4edSSimon Glass bus = bus->parent; 28621ccce1bSSimon Glass return pci_bus_write_config(bus, dm_pci_get_bdf(dev), offset, value, 28721ccce1bSSimon Glass size); 28866afb4edSSimon Glass } 28966afb4edSSimon Glass 290ff3e077bSSimon Glass int pci_write_config32(pci_dev_t bdf, int offset, u32 value) 291ff3e077bSSimon Glass { 292ff3e077bSSimon Glass return pci_write_config(bdf, offset, value, PCI_SIZE_32); 293ff3e077bSSimon Glass } 294ff3e077bSSimon Glass 295ff3e077bSSimon Glass int pci_write_config16(pci_dev_t bdf, int offset, u16 value) 296ff3e077bSSimon Glass { 297ff3e077bSSimon Glass return pci_write_config(bdf, offset, value, PCI_SIZE_16); 298ff3e077bSSimon Glass } 299ff3e077bSSimon Glass 300ff3e077bSSimon Glass int pci_write_config8(pci_dev_t bdf, int offset, u8 value) 301ff3e077bSSimon Glass { 302ff3e077bSSimon Glass return pci_write_config(bdf, offset, value, PCI_SIZE_8); 303ff3e077bSSimon Glass } 304ff3e077bSSimon Glass 30566afb4edSSimon Glass int dm_pci_write_config8(struct udevice *dev, int offset, u8 value) 30666afb4edSSimon Glass { 30766afb4edSSimon Glass return dm_pci_write_config(dev, offset, value, PCI_SIZE_8); 30866afb4edSSimon Glass } 30966afb4edSSimon Glass 31066afb4edSSimon Glass int dm_pci_write_config16(struct udevice *dev, int offset, u16 value) 31166afb4edSSimon Glass { 31266afb4edSSimon Glass return dm_pci_write_config(dev, offset, value, PCI_SIZE_16); 31366afb4edSSimon Glass } 31466afb4edSSimon Glass 31566afb4edSSimon Glass int dm_pci_write_config32(struct udevice *dev, int offset, u32 value) 31666afb4edSSimon Glass { 31766afb4edSSimon Glass return dm_pci_write_config(dev, offset, value, PCI_SIZE_32); 31866afb4edSSimon Glass } 31966afb4edSSimon Glass 320ff3e077bSSimon Glass int pci_bus_read_config(struct udevice *bus, pci_dev_t bdf, int offset, 321ff3e077bSSimon Glass unsigned long *valuep, enum pci_size_t size) 322ff3e077bSSimon Glass { 323ff3e077bSSimon Glass struct dm_pci_ops *ops; 324ff3e077bSSimon Glass 325ff3e077bSSimon Glass ops = pci_get_ops(bus); 326ff3e077bSSimon Glass if (!ops->read_config) 327ff3e077bSSimon Glass return -ENOSYS; 328ff3e077bSSimon Glass return ops->read_config(bus, bdf, offset, valuep, size); 329ff3e077bSSimon Glass } 330ff3e077bSSimon Glass 331ff3e077bSSimon Glass int pci_read_config(pci_dev_t bdf, int offset, unsigned long *valuep, 332ff3e077bSSimon Glass enum pci_size_t size) 333ff3e077bSSimon Glass { 334ff3e077bSSimon Glass struct udevice *bus; 335ff3e077bSSimon Glass int ret; 336ff3e077bSSimon Glass 337983c6ba2SSimon Glass ret = pci_get_bus(PCI_BUS(bdf), &bus); 338ff3e077bSSimon Glass if (ret) 339ff3e077bSSimon Glass return ret; 340ff3e077bSSimon Glass 3414d8615cbSBin Meng return pci_bus_read_config(bus, bdf, offset, valuep, size); 342ff3e077bSSimon Glass } 343ff3e077bSSimon Glass 34466afb4edSSimon Glass int dm_pci_read_config(struct udevice *dev, int offset, unsigned long *valuep, 34566afb4edSSimon Glass enum pci_size_t size) 34666afb4edSSimon Glass { 34766afb4edSSimon Glass struct udevice *bus; 34866afb4edSSimon Glass 3491e0f2263SBin Meng for (bus = dev; device_is_on_pci_bus(bus);) 35066afb4edSSimon Glass bus = bus->parent; 35121ccce1bSSimon Glass return pci_bus_read_config(bus, dm_pci_get_bdf(dev), offset, valuep, 35266afb4edSSimon Glass size); 35366afb4edSSimon Glass } 35466afb4edSSimon Glass 355ff3e077bSSimon Glass int pci_read_config32(pci_dev_t bdf, int offset, u32 *valuep) 356ff3e077bSSimon Glass { 357ff3e077bSSimon Glass unsigned long value; 358ff3e077bSSimon Glass int ret; 359ff3e077bSSimon Glass 360ff3e077bSSimon Glass ret = pci_read_config(bdf, offset, &value, PCI_SIZE_32); 361ff3e077bSSimon Glass if (ret) 362ff3e077bSSimon Glass return ret; 363ff3e077bSSimon Glass *valuep = value; 364ff3e077bSSimon Glass 365ff3e077bSSimon Glass return 0; 366ff3e077bSSimon Glass } 367ff3e077bSSimon Glass 368ff3e077bSSimon Glass int pci_read_config16(pci_dev_t bdf, int offset, u16 *valuep) 369ff3e077bSSimon Glass { 370ff3e077bSSimon Glass unsigned long value; 371ff3e077bSSimon Glass int ret; 372ff3e077bSSimon Glass 373ff3e077bSSimon Glass ret = pci_read_config(bdf, offset, &value, PCI_SIZE_16); 374ff3e077bSSimon Glass if (ret) 375ff3e077bSSimon Glass return ret; 376ff3e077bSSimon Glass *valuep = value; 377ff3e077bSSimon Glass 378ff3e077bSSimon Glass return 0; 379ff3e077bSSimon Glass } 380ff3e077bSSimon Glass 381ff3e077bSSimon Glass int pci_read_config8(pci_dev_t bdf, int offset, u8 *valuep) 382ff3e077bSSimon Glass { 383ff3e077bSSimon Glass unsigned long value; 384ff3e077bSSimon Glass int ret; 385ff3e077bSSimon Glass 386ff3e077bSSimon Glass ret = pci_read_config(bdf, offset, &value, PCI_SIZE_8); 387ff3e077bSSimon Glass if (ret) 388ff3e077bSSimon Glass return ret; 389ff3e077bSSimon Glass *valuep = value; 390ff3e077bSSimon Glass 391ff3e077bSSimon Glass return 0; 392ff3e077bSSimon Glass } 393ff3e077bSSimon Glass 39466afb4edSSimon Glass int dm_pci_read_config8(struct udevice *dev, int offset, u8 *valuep) 39566afb4edSSimon Glass { 39666afb4edSSimon Glass unsigned long value; 39766afb4edSSimon Glass int ret; 39866afb4edSSimon Glass 39966afb4edSSimon Glass ret = dm_pci_read_config(dev, offset, &value, PCI_SIZE_8); 40066afb4edSSimon Glass if (ret) 40166afb4edSSimon Glass return ret; 40266afb4edSSimon Glass *valuep = value; 40366afb4edSSimon Glass 40466afb4edSSimon Glass return 0; 40566afb4edSSimon Glass } 40666afb4edSSimon Glass 40766afb4edSSimon Glass int dm_pci_read_config16(struct udevice *dev, int offset, u16 *valuep) 40866afb4edSSimon Glass { 40966afb4edSSimon Glass unsigned long value; 41066afb4edSSimon Glass int ret; 41166afb4edSSimon Glass 41266afb4edSSimon Glass ret = dm_pci_read_config(dev, offset, &value, PCI_SIZE_16); 41366afb4edSSimon Glass if (ret) 41466afb4edSSimon Glass return ret; 41566afb4edSSimon Glass *valuep = value; 41666afb4edSSimon Glass 41766afb4edSSimon Glass return 0; 41866afb4edSSimon Glass } 41966afb4edSSimon Glass 42066afb4edSSimon Glass int dm_pci_read_config32(struct udevice *dev, int offset, u32 *valuep) 42166afb4edSSimon Glass { 42266afb4edSSimon Glass unsigned long value; 42366afb4edSSimon Glass int ret; 42466afb4edSSimon Glass 42566afb4edSSimon Glass ret = dm_pci_read_config(dev, offset, &value, PCI_SIZE_32); 42666afb4edSSimon Glass if (ret) 42766afb4edSSimon Glass return ret; 42866afb4edSSimon Glass *valuep = value; 42966afb4edSSimon Glass 43066afb4edSSimon Glass return 0; 43166afb4edSSimon Glass } 43266afb4edSSimon Glass 433319dba1fSSimon Glass int dm_pci_clrset_config8(struct udevice *dev, int offset, u32 clr, u32 set) 434319dba1fSSimon Glass { 435319dba1fSSimon Glass u8 val; 436319dba1fSSimon Glass int ret; 437319dba1fSSimon Glass 438319dba1fSSimon Glass ret = dm_pci_read_config8(dev, offset, &val); 439319dba1fSSimon Glass if (ret) 440319dba1fSSimon Glass return ret; 441319dba1fSSimon Glass val &= ~clr; 442319dba1fSSimon Glass val |= set; 443319dba1fSSimon Glass 444319dba1fSSimon Glass return dm_pci_write_config8(dev, offset, val); 445319dba1fSSimon Glass } 446319dba1fSSimon Glass 447319dba1fSSimon Glass int dm_pci_clrset_config16(struct udevice *dev, int offset, u32 clr, u32 set) 448319dba1fSSimon Glass { 449319dba1fSSimon Glass u16 val; 450319dba1fSSimon Glass int ret; 451319dba1fSSimon Glass 452319dba1fSSimon Glass ret = dm_pci_read_config16(dev, offset, &val); 453319dba1fSSimon Glass if (ret) 454319dba1fSSimon Glass return ret; 455319dba1fSSimon Glass val &= ~clr; 456319dba1fSSimon Glass val |= set; 457319dba1fSSimon Glass 458319dba1fSSimon Glass return dm_pci_write_config16(dev, offset, val); 459319dba1fSSimon Glass } 460319dba1fSSimon Glass 461319dba1fSSimon Glass int dm_pci_clrset_config32(struct udevice *dev, int offset, u32 clr, u32 set) 462319dba1fSSimon Glass { 463319dba1fSSimon Glass u32 val; 464319dba1fSSimon Glass int ret; 465319dba1fSSimon Glass 466319dba1fSSimon Glass ret = dm_pci_read_config32(dev, offset, &val); 467319dba1fSSimon Glass if (ret) 468319dba1fSSimon Glass return ret; 469319dba1fSSimon Glass val &= ~clr; 470319dba1fSSimon Glass val |= set; 471319dba1fSSimon Glass 472319dba1fSSimon Glass return dm_pci_write_config32(dev, offset, val); 473319dba1fSSimon Glass } 474319dba1fSSimon Glass 475bbbcb526SBin Meng static void set_vga_bridge_bits(struct udevice *dev) 476bbbcb526SBin Meng { 477bbbcb526SBin Meng struct udevice *parent = dev->parent; 478bbbcb526SBin Meng u16 bc; 479bbbcb526SBin Meng 480bbbcb526SBin Meng while (parent->seq != 0) { 481bbbcb526SBin Meng dm_pci_read_config16(parent, PCI_BRIDGE_CONTROL, &bc); 482bbbcb526SBin Meng bc |= PCI_BRIDGE_CTL_VGA; 483bbbcb526SBin Meng dm_pci_write_config16(parent, PCI_BRIDGE_CONTROL, bc); 484bbbcb526SBin Meng parent = parent->parent; 485bbbcb526SBin Meng } 486bbbcb526SBin Meng } 487bbbcb526SBin Meng 488ff3e077bSSimon Glass int pci_auto_config_devices(struct udevice *bus) 489ff3e077bSSimon Glass { 490ff3e077bSSimon Glass struct pci_controller *hose = bus->uclass_priv; 491bbbcb526SBin Meng struct pci_child_platdata *pplat; 492ff3e077bSSimon Glass unsigned int sub_bus; 493ff3e077bSSimon Glass struct udevice *dev; 494ff3e077bSSimon Glass int ret; 495ff3e077bSSimon Glass 496ff3e077bSSimon Glass sub_bus = bus->seq; 497ff3e077bSSimon Glass debug("%s: start\n", __func__); 498ff3e077bSSimon Glass pciauto_config_init(hose); 499ff3e077bSSimon Glass for (ret = device_find_first_child(bus, &dev); 500ff3e077bSSimon Glass !ret && dev; 501ff3e077bSSimon Glass ret = device_find_next_child(&dev)) { 502ff3e077bSSimon Glass unsigned int max_bus; 5034d21455eSSimon Glass int ret; 504ff3e077bSSimon Glass 505ff3e077bSSimon Glass debug("%s: device %s\n", __func__, dev->name); 5065e23b8b4SSimon Glass ret = dm_pciauto_config_device(dev); 5074d21455eSSimon Glass if (ret < 0) 5084d21455eSSimon Glass return ret; 5094d21455eSSimon Glass max_bus = ret; 510ff3e077bSSimon Glass sub_bus = max(sub_bus, max_bus); 511bbbcb526SBin Meng 512bbbcb526SBin Meng pplat = dev_get_parent_platdata(dev); 513bbbcb526SBin Meng if (pplat->class == (PCI_CLASS_DISPLAY_VGA << 8)) 514bbbcb526SBin Meng set_vga_bridge_bits(dev); 515ff3e077bSSimon Glass } 516ff3e077bSSimon Glass debug("%s: done\n", __func__); 517ff3e077bSSimon Glass 518ff3e077bSSimon Glass return sub_bus; 519ff3e077bSSimon Glass } 520ff3e077bSSimon Glass 5215e23b8b4SSimon Glass int dm_pci_hose_probe_bus(struct udevice *bus) 522ff3e077bSSimon Glass { 523ff3e077bSSimon Glass int sub_bus; 524ff3e077bSSimon Glass int ret; 525ff3e077bSSimon Glass 526ff3e077bSSimon Glass debug("%s\n", __func__); 527ff3e077bSSimon Glass 528ff3e077bSSimon Glass sub_bus = pci_get_bus_max() + 1; 529ff3e077bSSimon Glass debug("%s: bus = %d/%s\n", __func__, sub_bus, bus->name); 5305e23b8b4SSimon Glass dm_pciauto_prescan_setup_bridge(bus, sub_bus); 531ff3e077bSSimon Glass 532ff3e077bSSimon Glass ret = device_probe(bus); 533ff3e077bSSimon Glass if (ret) { 5343129ace4SSimon Glass debug("%s: Cannot probe bus %s: %d\n", __func__, bus->name, 535ff3e077bSSimon Glass ret); 536ff3e077bSSimon Glass return ret; 537ff3e077bSSimon Glass } 538ff3e077bSSimon Glass if (sub_bus != bus->seq) { 539ff3e077bSSimon Glass printf("%s: Internal error, bus '%s' got seq %d, expected %d\n", 540ff3e077bSSimon Glass __func__, bus->name, bus->seq, sub_bus); 541ff3e077bSSimon Glass return -EPIPE; 542ff3e077bSSimon Glass } 543ff3e077bSSimon Glass sub_bus = pci_get_bus_max(); 5445e23b8b4SSimon Glass dm_pciauto_postscan_setup_bridge(bus, sub_bus); 545ff3e077bSSimon Glass 546ff3e077bSSimon Glass return sub_bus; 547ff3e077bSSimon Glass } 548ff3e077bSSimon Glass 549aba92962SSimon Glass /** 550aba92962SSimon Glass * pci_match_one_device - Tell if a PCI device structure has a matching 551aba92962SSimon Glass * PCI device id structure 552aba92962SSimon Glass * @id: single PCI device id structure to match 5530367bd4dSHou Zhiqiang * @find: the PCI device id structure to match against 554aba92962SSimon Glass * 5550367bd4dSHou Zhiqiang * Returns true if the finding pci_device_id structure matched or false if 5560367bd4dSHou Zhiqiang * there is no match. 557aba92962SSimon Glass */ 558aba92962SSimon Glass static bool pci_match_one_id(const struct pci_device_id *id, 559aba92962SSimon Glass const struct pci_device_id *find) 560aba92962SSimon Glass { 561aba92962SSimon Glass if ((id->vendor == PCI_ANY_ID || id->vendor == find->vendor) && 562aba92962SSimon Glass (id->device == PCI_ANY_ID || id->device == find->device) && 563aba92962SSimon Glass (id->subvendor == PCI_ANY_ID || id->subvendor == find->subvendor) && 564aba92962SSimon Glass (id->subdevice == PCI_ANY_ID || id->subdevice == find->subdevice) && 565aba92962SSimon Glass !((id->class ^ find->class) & id->class_mask)) 566aba92962SSimon Glass return true; 567aba92962SSimon Glass 568aba92962SSimon Glass return false; 569aba92962SSimon Glass } 570aba92962SSimon Glass 571aba92962SSimon Glass /** 572aba92962SSimon Glass * pci_find_and_bind_driver() - Find and bind the right PCI driver 573aba92962SSimon Glass * 574aba92962SSimon Glass * This only looks at certain fields in the descriptor. 5755dbcf3a0SSimon Glass * 5765dbcf3a0SSimon Glass * @parent: Parent bus 5775dbcf3a0SSimon Glass * @find_id: Specification of the driver to find 5785dbcf3a0SSimon Glass * @bdf: Bus/device/function addreess - see PCI_BDF() 5795dbcf3a0SSimon Glass * @devp: Returns a pointer to the device created 5805dbcf3a0SSimon Glass * @return 0 if OK, -EPERM if the device is not needed before relocation and 5815dbcf3a0SSimon Glass * therefore was not created, other -ve value on error 582aba92962SSimon Glass */ 583aba92962SSimon Glass static int pci_find_and_bind_driver(struct udevice *parent, 5845dbcf3a0SSimon Glass struct pci_device_id *find_id, 5855dbcf3a0SSimon Glass pci_dev_t bdf, struct udevice **devp) 586aba92962SSimon Glass { 587aba92962SSimon Glass struct pci_driver_entry *start, *entry; 588aba92962SSimon Glass const char *drv; 589aba92962SSimon Glass int n_ents; 590aba92962SSimon Glass int ret; 591aba92962SSimon Glass char name[30], *str; 59208fc7b8fSBin Meng bool bridge; 593aba92962SSimon Glass 594aba92962SSimon Glass *devp = NULL; 595aba92962SSimon Glass 596aba92962SSimon Glass debug("%s: Searching for driver: vendor=%x, device=%x\n", __func__, 597aba92962SSimon Glass find_id->vendor, find_id->device); 598aba92962SSimon Glass start = ll_entry_start(struct pci_driver_entry, pci_driver_entry); 599aba92962SSimon Glass n_ents = ll_entry_count(struct pci_driver_entry, pci_driver_entry); 600aba92962SSimon Glass for (entry = start; entry != start + n_ents; entry++) { 601aba92962SSimon Glass const struct pci_device_id *id; 602aba92962SSimon Glass struct udevice *dev; 603aba92962SSimon Glass const struct driver *drv; 604aba92962SSimon Glass 605aba92962SSimon Glass for (id = entry->match; 606aba92962SSimon Glass id->vendor || id->subvendor || id->class_mask; 607aba92962SSimon Glass id++) { 608aba92962SSimon Glass if (!pci_match_one_id(id, find_id)) 609aba92962SSimon Glass continue; 610aba92962SSimon Glass 611aba92962SSimon Glass drv = entry->driver; 61208fc7b8fSBin Meng 61308fc7b8fSBin Meng /* 61408fc7b8fSBin Meng * In the pre-relocation phase, we only bind devices 61508fc7b8fSBin Meng * whose driver has the DM_FLAG_PRE_RELOC set, to save 61608fc7b8fSBin Meng * precious memory space as on some platforms as that 61708fc7b8fSBin Meng * space is pretty limited (ie: using Cache As RAM). 61808fc7b8fSBin Meng */ 61908fc7b8fSBin Meng if (!(gd->flags & GD_FLG_RELOC) && 62008fc7b8fSBin Meng !(drv->flags & DM_FLAG_PRE_RELOC)) 6215dbcf3a0SSimon Glass return -EPERM; 62208fc7b8fSBin Meng 623aba92962SSimon Glass /* 624aba92962SSimon Glass * We could pass the descriptor to the driver as 625aba92962SSimon Glass * platdata (instead of NULL) and allow its bind() 626aba92962SSimon Glass * method to return -ENOENT if it doesn't support this 627aba92962SSimon Glass * device. That way we could continue the search to 628aba92962SSimon Glass * find another driver. For now this doesn't seem 629aba92962SSimon Glass * necesssary, so just bind the first match. 630aba92962SSimon Glass */ 631aba92962SSimon Glass ret = device_bind(parent, drv, drv->name, NULL, -1, 632aba92962SSimon Glass &dev); 633aba92962SSimon Glass if (ret) 634aba92962SSimon Glass goto error; 635aba92962SSimon Glass debug("%s: Match found: %s\n", __func__, drv->name); 636aba92962SSimon Glass dev->driver_data = find_id->driver_data; 637aba92962SSimon Glass *devp = dev; 638aba92962SSimon Glass return 0; 639aba92962SSimon Glass } 640aba92962SSimon Glass } 641aba92962SSimon Glass 64208fc7b8fSBin Meng bridge = (find_id->class >> 8) == PCI_CLASS_BRIDGE_PCI; 64308fc7b8fSBin Meng /* 64408fc7b8fSBin Meng * In the pre-relocation phase, we only bind bridge devices to save 64508fc7b8fSBin Meng * precious memory space as on some platforms as that space is pretty 64608fc7b8fSBin Meng * limited (ie: using Cache As RAM). 64708fc7b8fSBin Meng */ 64808fc7b8fSBin Meng if (!(gd->flags & GD_FLG_RELOC) && !bridge) 6495dbcf3a0SSimon Glass return -EPERM; 65008fc7b8fSBin Meng 651aba92962SSimon Glass /* Bind a generic driver so that the device can be used */ 6524d8615cbSBin Meng sprintf(name, "pci_%x:%x.%x", parent->seq, PCI_DEV(bdf), 6534d8615cbSBin Meng PCI_FUNC(bdf)); 654aba92962SSimon Glass str = strdup(name); 655aba92962SSimon Glass if (!str) 656aba92962SSimon Glass return -ENOMEM; 65708fc7b8fSBin Meng drv = bridge ? "pci_bridge_drv" : "pci_generic_drv"; 65808fc7b8fSBin Meng 659aba92962SSimon Glass ret = device_bind_driver(parent, drv, str, devp); 660aba92962SSimon Glass if (ret) { 6613129ace4SSimon Glass debug("%s: Failed to bind generic driver: %d\n", __func__, ret); 662c42640c7Sxypron.glpk@gmx.de free(str); 663aba92962SSimon Glass return ret; 664aba92962SSimon Glass } 665aba92962SSimon Glass debug("%s: No match found: bound generic driver instead\n", __func__); 666aba92962SSimon Glass 667aba92962SSimon Glass return 0; 668aba92962SSimon Glass 669aba92962SSimon Glass error: 670aba92962SSimon Glass debug("%s: No match found: error %d\n", __func__, ret); 671aba92962SSimon Glass return ret; 672aba92962SSimon Glass } 673aba92962SSimon Glass 674ff3e077bSSimon Glass int pci_bind_bus_devices(struct udevice *bus) 675ff3e077bSSimon Glass { 676ff3e077bSSimon Glass ulong vendor, device; 677ff3e077bSSimon Glass ulong header_type; 6784d8615cbSBin Meng pci_dev_t bdf, end; 679ff3e077bSSimon Glass bool found_multi; 680ff3e077bSSimon Glass int ret; 681ff3e077bSSimon Glass 682ff3e077bSSimon Glass found_multi = false; 6834d8615cbSBin Meng end = PCI_BDF(bus->seq, PCI_MAX_PCI_DEVICES - 1, 6844d8615cbSBin Meng PCI_MAX_PCI_FUNCTIONS - 1); 6856d9f5b03SYoshinori Sato for (bdf = PCI_BDF(bus->seq, 0, 0); bdf <= end; 6864d8615cbSBin Meng bdf += PCI_BDF(0, 0, 1)) { 687ff3e077bSSimon Glass struct pci_child_platdata *pplat; 688ff3e077bSSimon Glass struct udevice *dev; 689ff3e077bSSimon Glass ulong class; 690ff3e077bSSimon Glass 6914d8615cbSBin Meng if (PCI_FUNC(bdf) && !found_multi) 692ff3e077bSSimon Glass continue; 693ff3e077bSSimon Glass /* Check only the first access, we don't expect problems */ 6944d8615cbSBin Meng ret = pci_bus_read_config(bus, bdf, PCI_HEADER_TYPE, 695ff3e077bSSimon Glass &header_type, PCI_SIZE_8); 696ff3e077bSSimon Glass if (ret) 697ff3e077bSSimon Glass goto error; 6984d8615cbSBin Meng pci_bus_read_config(bus, bdf, PCI_VENDOR_ID, &vendor, 699ff3e077bSSimon Glass PCI_SIZE_16); 700ff3e077bSSimon Glass if (vendor == 0xffff || vendor == 0x0000) 701ff3e077bSSimon Glass continue; 702ff3e077bSSimon Glass 7034d8615cbSBin Meng if (!PCI_FUNC(bdf)) 704ff3e077bSSimon Glass found_multi = header_type & 0x80; 705ff3e077bSSimon Glass 706ff3e077bSSimon Glass debug("%s: bus %d/%s: found device %x, function %d\n", __func__, 7074d8615cbSBin Meng bus->seq, bus->name, PCI_DEV(bdf), PCI_FUNC(bdf)); 7084d8615cbSBin Meng pci_bus_read_config(bus, bdf, PCI_DEVICE_ID, &device, 709ff3e077bSSimon Glass PCI_SIZE_16); 7104d8615cbSBin Meng pci_bus_read_config(bus, bdf, PCI_CLASS_REVISION, &class, 711aba92962SSimon Glass PCI_SIZE_32); 712aba92962SSimon Glass class >>= 8; 713ff3e077bSSimon Glass 714ff3e077bSSimon Glass /* Find this device in the device tree */ 7154d8615cbSBin Meng ret = pci_bus_find_devfn(bus, PCI_MASK_BUS(bdf), &dev); 716ff3e077bSSimon Glass 7178bd42525SSimon Glass /* If nothing in the device tree, bind a device */ 718ff3e077bSSimon Glass if (ret == -ENODEV) { 719aba92962SSimon Glass struct pci_device_id find_id; 720aba92962SSimon Glass ulong val; 721ff3e077bSSimon Glass 722aba92962SSimon Glass memset(&find_id, '\0', sizeof(find_id)); 723aba92962SSimon Glass find_id.vendor = vendor; 724aba92962SSimon Glass find_id.device = device; 725aba92962SSimon Glass find_id.class = class; 726aba92962SSimon Glass if ((header_type & 0x7f) == PCI_HEADER_TYPE_NORMAL) { 7274d8615cbSBin Meng pci_bus_read_config(bus, bdf, 728aba92962SSimon Glass PCI_SUBSYSTEM_VENDOR_ID, 729aba92962SSimon Glass &val, PCI_SIZE_32); 730aba92962SSimon Glass find_id.subvendor = val & 0xffff; 731aba92962SSimon Glass find_id.subdevice = val >> 16; 732aba92962SSimon Glass } 7334d8615cbSBin Meng ret = pci_find_and_bind_driver(bus, &find_id, bdf, 734aba92962SSimon Glass &dev); 735ff3e077bSSimon Glass } 7365dbcf3a0SSimon Glass if (ret == -EPERM) 7375dbcf3a0SSimon Glass continue; 7385dbcf3a0SSimon Glass else if (ret) 739ff3e077bSSimon Glass return ret; 740ff3e077bSSimon Glass 741ff3e077bSSimon Glass /* Update the platform data */ 742ff3e077bSSimon Glass pplat = dev_get_parent_platdata(dev); 7434d8615cbSBin Meng pplat->devfn = PCI_MASK_BUS(bdf); 744ff3e077bSSimon Glass pplat->vendor = vendor; 745ff3e077bSSimon Glass pplat->device = device; 746ff3e077bSSimon Glass pplat->class = class; 747ff3e077bSSimon Glass } 748ff3e077bSSimon Glass 749ff3e077bSSimon Glass return 0; 750ff3e077bSSimon Glass error: 751ff3e077bSSimon Glass printf("Cannot read bus configuration: %d\n", ret); 752ff3e077bSSimon Glass 753ff3e077bSSimon Glass return ret; 754ff3e077bSSimon Glass } 755ff3e077bSSimon Glass 756bf501595SSimon Glass static int decode_regions(struct pci_controller *hose, ofnode parent_node, 757bf501595SSimon Glass ofnode node) 758ff3e077bSSimon Glass { 759ff3e077bSSimon Glass int pci_addr_cells, addr_cells, size_cells; 7602084c5afSSimon Glass phys_addr_t base = 0, size; 761ff3e077bSSimon Glass int cells_per_record; 762ff3e077bSSimon Glass const u32 *prop; 763ff3e077bSSimon Glass int len; 764ff3e077bSSimon Glass int i; 765ff3e077bSSimon Glass 76661e51babSMasahiro Yamada prop = ofnode_get_property(node, "ranges", &len); 767ff3e077bSSimon Glass if (!prop) 768ff3e077bSSimon Glass return -EINVAL; 769878d68c0SSimon Glass pci_addr_cells = ofnode_read_simple_addr_cells(node); 770878d68c0SSimon Glass addr_cells = ofnode_read_simple_addr_cells(parent_node); 771878d68c0SSimon Glass size_cells = ofnode_read_simple_size_cells(node); 772ff3e077bSSimon Glass 773ff3e077bSSimon Glass /* PCI addresses are always 3-cells */ 774ff3e077bSSimon Glass len /= sizeof(u32); 775ff3e077bSSimon Glass cells_per_record = pci_addr_cells + addr_cells + size_cells; 776ff3e077bSSimon Glass hose->region_count = 0; 777ff3e077bSSimon Glass debug("%s: len=%d, cells_per_record=%d\n", __func__, len, 778ff3e077bSSimon Glass cells_per_record); 779ff3e077bSSimon Glass for (i = 0; i < MAX_PCI_REGIONS; i++, len -= cells_per_record) { 780ff3e077bSSimon Glass u64 pci_addr, addr, size; 781ff3e077bSSimon Glass int space_code; 782ff3e077bSSimon Glass u32 flags; 783ff3e077bSSimon Glass int type; 7849526d83aSSimon Glass int pos; 785ff3e077bSSimon Glass 786ff3e077bSSimon Glass if (len < cells_per_record) 787ff3e077bSSimon Glass break; 788ff3e077bSSimon Glass flags = fdt32_to_cpu(prop[0]); 789ff3e077bSSimon Glass space_code = (flags >> 24) & 3; 790ff3e077bSSimon Glass pci_addr = fdtdec_get_number(prop + 1, 2); 791ff3e077bSSimon Glass prop += pci_addr_cells; 792ff3e077bSSimon Glass addr = fdtdec_get_number(prop, addr_cells); 793ff3e077bSSimon Glass prop += addr_cells; 794ff3e077bSSimon Glass size = fdtdec_get_number(prop, size_cells); 795ff3e077bSSimon Glass prop += size_cells; 796ff3e077bSSimon Glass debug("%s: region %d, pci_addr=%" PRIx64 ", addr=%" PRIx64 797ff3e077bSSimon Glass ", size=%" PRIx64 ", space_code=%d\n", __func__, 798ff3e077bSSimon Glass hose->region_count, pci_addr, addr, size, space_code); 799ff3e077bSSimon Glass if (space_code & 2) { 800ff3e077bSSimon Glass type = flags & (1U << 30) ? PCI_REGION_PREFETCH : 801ff3e077bSSimon Glass PCI_REGION_MEM; 802*fdb7e29cSShawn Lin #ifndef CONFIG_SYS_PCI_64BIT 803*fdb7e29cSShawn Lin if (upper_32_bits(pci_addr)) 804*fdb7e29cSShawn Lin continue; 805*fdb7e29cSShawn Lin #endif 806ff3e077bSSimon Glass } else if (space_code & 1) { 807ff3e077bSSimon Glass type = PCI_REGION_IO; 808ff3e077bSSimon Glass } else { 809ff3e077bSSimon Glass continue; 810ff3e077bSSimon Glass } 8119526d83aSSimon Glass pos = -1; 8129526d83aSSimon Glass for (i = 0; i < hose->region_count; i++) { 813*fdb7e29cSShawn Lin if (hose->regions[i].flags == type) { 814*fdb7e29cSShawn Lin #if defined(CONFIG_SYS_PCI_64BIT) 815*fdb7e29cSShawn Lin if (type == PCI_REGION_MEM) { 816*fdb7e29cSShawn Lin if ((upper_32_bits(pci_addr) && 817*fdb7e29cSShawn Lin !upper_32_bits(hose->regions[i].bus_start)) || 818*fdb7e29cSShawn Lin (!upper_32_bits(pci_addr) && 819*fdb7e29cSShawn Lin upper_32_bits(hose->regions[i].bus_start))) 820*fdb7e29cSShawn Lin continue; 821*fdb7e29cSShawn Lin } 822*fdb7e29cSShawn Lin #endif 8239526d83aSSimon Glass pos = i; 8249526d83aSSimon Glass } 825*fdb7e29cSShawn Lin } 8269526d83aSSimon Glass if (pos == -1) 8279526d83aSSimon Glass pos = hose->region_count++; 8289526d83aSSimon Glass debug(" - type=%d, pos=%d\n", type, pos); 8299526d83aSSimon Glass pci_set_region(hose->regions + pos, pci_addr, addr, size, type); 830ff3e077bSSimon Glass } 831ff3e077bSSimon Glass 832ff3e077bSSimon Glass /* Add a region for our local memory */ 8332084c5afSSimon Glass size = gd->ram_size; 8342084c5afSSimon Glass #ifdef CONFIG_SYS_SDRAM_BASE 8352084c5afSSimon Glass base = CONFIG_SYS_SDRAM_BASE; 8362084c5afSSimon Glass #endif 8372084c5afSSimon Glass if (gd->pci_ram_top && gd->pci_ram_top < base + size) 8382084c5afSSimon Glass size = gd->pci_ram_top - base; 8392084c5afSSimon Glass pci_set_region(hose->regions + hose->region_count++, base, base, 8402084c5afSSimon Glass size, PCI_REGION_MEM | PCI_REGION_SYS_MEMORY); 841ff3e077bSSimon Glass 842ff3e077bSSimon Glass return 0; 843ff3e077bSSimon Glass } 844ff3e077bSSimon Glass 845ff3e077bSSimon Glass static int pci_uclass_pre_probe(struct udevice *bus) 846ff3e077bSSimon Glass { 847ff3e077bSSimon Glass struct pci_controller *hose; 848ff3e077bSSimon Glass int ret; 849ff3e077bSSimon Glass 850ff3e077bSSimon Glass debug("%s, bus=%d/%s, parent=%s\n", __func__, bus->seq, bus->name, 851ff3e077bSSimon Glass bus->parent->name); 852ff3e077bSSimon Glass hose = bus->uclass_priv; 853ff3e077bSSimon Glass 854ff3e077bSSimon Glass /* For bridges, use the top-level PCI controller */ 85565f62b1cSPaul Burton if (!device_is_on_pci_bus(bus)) { 856ff3e077bSSimon Glass hose->ctlr = bus; 857bf501595SSimon Glass ret = decode_regions(hose, dev_ofnode(bus->parent), 858bf501595SSimon Glass dev_ofnode(bus)); 859ff3e077bSSimon Glass if (ret) { 860ff3e077bSSimon Glass debug("%s: Cannot decode regions\n", __func__); 861ff3e077bSSimon Glass return ret; 862ff3e077bSSimon Glass } 863ff3e077bSSimon Glass } else { 864ff3e077bSSimon Glass struct pci_controller *parent_hose; 865ff3e077bSSimon Glass 866ff3e077bSSimon Glass parent_hose = dev_get_uclass_priv(bus->parent); 867ff3e077bSSimon Glass hose->ctlr = parent_hose->bus; 868ff3e077bSSimon Glass } 869ff3e077bSSimon Glass hose->bus = bus; 870ff3e077bSSimon Glass hose->first_busno = bus->seq; 871ff3e077bSSimon Glass hose->last_busno = bus->seq; 872ff3e077bSSimon Glass 873ff3e077bSSimon Glass return 0; 874ff3e077bSSimon Glass } 875ff3e077bSSimon Glass 876ff3e077bSSimon Glass static int pci_uclass_post_probe(struct udevice *bus) 877ff3e077bSSimon Glass { 878ff3e077bSSimon Glass int ret; 879ff3e077bSSimon Glass 880ff3e077bSSimon Glass debug("%s: probing bus %d\n", __func__, bus->seq); 881ff3e077bSSimon Glass ret = pci_bind_bus_devices(bus); 882ff3e077bSSimon Glass if (ret) 883ff3e077bSSimon Glass return ret; 884ff3e077bSSimon Glass 885ff3e077bSSimon Glass #ifdef CONFIG_PCI_PNP 886ff3e077bSSimon Glass ret = pci_auto_config_devices(bus); 8874d21455eSSimon Glass if (ret < 0) 8884d21455eSSimon Glass return ret; 889ff3e077bSSimon Glass #endif 890ff3e077bSSimon Glass 891348b744bSBin Meng #if defined(CONFIG_X86) && defined(CONFIG_HAVE_FSP) 892348b744bSBin Meng /* 893348b744bSBin Meng * Per Intel FSP specification, we should call FSP notify API to 894348b744bSBin Meng * inform FSP that PCI enumeration has been done so that FSP will 895348b744bSBin Meng * do any necessary initialization as required by the chipset's 896348b744bSBin Meng * BIOS Writer's Guide (BWG). 897348b744bSBin Meng * 898348b744bSBin Meng * Unfortunately we have to put this call here as with driver model, 899348b744bSBin Meng * the enumeration is all done on a lazy basis as needed, so until 900348b744bSBin Meng * something is touched on PCI it won't happen. 901348b744bSBin Meng * 902348b744bSBin Meng * Note we only call this 1) after U-Boot is relocated, and 2) 903348b744bSBin Meng * root bus has finished probing. 904348b744bSBin Meng */ 9054d21455eSSimon Glass if ((gd->flags & GD_FLG_RELOC) && (bus->seq == 0)) { 906348b744bSBin Meng ret = fsp_init_phase_pci(); 9074d21455eSSimon Glass if (ret) 9084d21455eSSimon Glass return ret; 9094d21455eSSimon Glass } 910348b744bSBin Meng #endif 911348b744bSBin Meng 9124d21455eSSimon Glass return 0; 913ff3e077bSSimon Glass } 914ff3e077bSSimon Glass 915ff3e077bSSimon Glass static int pci_uclass_child_post_bind(struct udevice *dev) 916ff3e077bSSimon Glass { 917ff3e077bSSimon Glass struct pci_child_platdata *pplat; 918ff3e077bSSimon Glass struct fdt_pci_addr addr; 919ff3e077bSSimon Glass int ret; 920ff3e077bSSimon Glass 921bf501595SSimon Glass if (!dev_of_valid(dev)) 922ff3e077bSSimon Glass return 0; 923ff3e077bSSimon Glass 924ff3e077bSSimon Glass /* 925ff3e077bSSimon Glass * We could read vendor, device, class if available. But for now we 926ff3e077bSSimon Glass * just check the address. 927ff3e077bSSimon Glass */ 928ff3e077bSSimon Glass pplat = dev_get_parent_platdata(dev); 929bf501595SSimon Glass ret = ofnode_read_pci_addr(dev_ofnode(dev), FDT_PCI_SPACE_CONFIG, "reg", 930bf501595SSimon Glass &addr); 931ff3e077bSSimon Glass 932ff3e077bSSimon Glass if (ret) { 933ff3e077bSSimon Glass if (ret != -ENOENT) 934ff3e077bSSimon Glass return -EINVAL; 935ff3e077bSSimon Glass } else { 936dce54dd6SBin Meng /* extract the devfn from fdt_pci_addr */ 937dce54dd6SBin Meng pplat->devfn = addr.phys_hi & 0xff00; 938ff3e077bSSimon Glass } 939ff3e077bSSimon Glass 940ff3e077bSSimon Glass return 0; 941ff3e077bSSimon Glass } 942ff3e077bSSimon Glass 9434d8615cbSBin Meng static int pci_bridge_read_config(struct udevice *bus, pci_dev_t bdf, 9444d8615cbSBin Meng uint offset, ulong *valuep, 9454d8615cbSBin Meng enum pci_size_t size) 946ff3e077bSSimon Glass { 947ff3e077bSSimon Glass struct pci_controller *hose = bus->uclass_priv; 948ff3e077bSSimon Glass 949ff3e077bSSimon Glass return pci_bus_read_config(hose->ctlr, bdf, offset, valuep, size); 950ff3e077bSSimon Glass } 951ff3e077bSSimon Glass 9524d8615cbSBin Meng static int pci_bridge_write_config(struct udevice *bus, pci_dev_t bdf, 9534d8615cbSBin Meng uint offset, ulong value, 9544d8615cbSBin Meng enum pci_size_t size) 955ff3e077bSSimon Glass { 956ff3e077bSSimon Glass struct pci_controller *hose = bus->uclass_priv; 957ff3e077bSSimon Glass 958ff3e077bSSimon Glass return pci_bus_write_config(hose->ctlr, bdf, offset, value, size); 959ff3e077bSSimon Glass } 960ff3e077bSSimon Glass 96176c3fbcdSSimon Glass static int skip_to_next_device(struct udevice *bus, struct udevice **devp) 96276c3fbcdSSimon Glass { 96376c3fbcdSSimon Glass struct udevice *dev; 96476c3fbcdSSimon Glass 96576c3fbcdSSimon Glass /* 96676c3fbcdSSimon Glass * Scan through all the PCI controllers. On x86 there will only be one 96776c3fbcdSSimon Glass * but that is not necessarily true on other hardware. 96876c3fbcdSSimon Glass */ 96976c3fbcdSSimon Glass do { 97076c3fbcdSSimon Glass device_find_first_child(bus, &dev); 97176c3fbcdSSimon Glass if (dev) { 97276c3fbcdSSimon Glass *devp = dev; 97376c3fbcdSSimon Glass return 0; 97476c3fbcdSSimon Glass } 9755395ac06SMichal Suchanek uclass_next_device(&bus); 97676c3fbcdSSimon Glass } while (bus); 97776c3fbcdSSimon Glass 97876c3fbcdSSimon Glass return 0; 97976c3fbcdSSimon Glass } 98076c3fbcdSSimon Glass 98176c3fbcdSSimon Glass int pci_find_next_device(struct udevice **devp) 98276c3fbcdSSimon Glass { 98376c3fbcdSSimon Glass struct udevice *child = *devp; 98476c3fbcdSSimon Glass struct udevice *bus = child->parent; 98576c3fbcdSSimon Glass 98676c3fbcdSSimon Glass /* First try all the siblings */ 98776c3fbcdSSimon Glass *devp = NULL; 98876c3fbcdSSimon Glass while (child) { 98976c3fbcdSSimon Glass device_find_next_child(&child); 99076c3fbcdSSimon Glass if (child) { 99176c3fbcdSSimon Glass *devp = child; 99276c3fbcdSSimon Glass return 0; 99376c3fbcdSSimon Glass } 99476c3fbcdSSimon Glass } 99576c3fbcdSSimon Glass 99676c3fbcdSSimon Glass /* We ran out of siblings. Try the next bus */ 9975395ac06SMichal Suchanek uclass_next_device(&bus); 99876c3fbcdSSimon Glass 99976c3fbcdSSimon Glass return bus ? skip_to_next_device(bus, devp) : 0; 100076c3fbcdSSimon Glass } 100176c3fbcdSSimon Glass 100276c3fbcdSSimon Glass int pci_find_first_device(struct udevice **devp) 100376c3fbcdSSimon Glass { 100476c3fbcdSSimon Glass struct udevice *bus; 100576c3fbcdSSimon Glass 100676c3fbcdSSimon Glass *devp = NULL; 10075395ac06SMichal Suchanek uclass_first_device(UCLASS_PCI, &bus); 100876c3fbcdSSimon Glass 100976c3fbcdSSimon Glass return skip_to_next_device(bus, devp); 101076c3fbcdSSimon Glass } 101176c3fbcdSSimon Glass 10129289db6cSSimon Glass ulong pci_conv_32_to_size(ulong value, uint offset, enum pci_size_t size) 10139289db6cSSimon Glass { 10149289db6cSSimon Glass switch (size) { 10159289db6cSSimon Glass case PCI_SIZE_8: 10169289db6cSSimon Glass return (value >> ((offset & 3) * 8)) & 0xff; 10179289db6cSSimon Glass case PCI_SIZE_16: 10189289db6cSSimon Glass return (value >> ((offset & 2) * 8)) & 0xffff; 10199289db6cSSimon Glass default: 10209289db6cSSimon Glass return value; 10219289db6cSSimon Glass } 10229289db6cSSimon Glass } 10239289db6cSSimon Glass 10249289db6cSSimon Glass ulong pci_conv_size_to_32(ulong old, ulong value, uint offset, 10259289db6cSSimon Glass enum pci_size_t size) 10269289db6cSSimon Glass { 10279289db6cSSimon Glass uint off_mask; 10289289db6cSSimon Glass uint val_mask, shift; 10299289db6cSSimon Glass ulong ldata, mask; 10309289db6cSSimon Glass 10319289db6cSSimon Glass switch (size) { 10329289db6cSSimon Glass case PCI_SIZE_8: 10339289db6cSSimon Glass off_mask = 3; 10349289db6cSSimon Glass val_mask = 0xff; 10359289db6cSSimon Glass break; 10369289db6cSSimon Glass case PCI_SIZE_16: 10379289db6cSSimon Glass off_mask = 2; 10389289db6cSSimon Glass val_mask = 0xffff; 10399289db6cSSimon Glass break; 10409289db6cSSimon Glass default: 10419289db6cSSimon Glass return value; 10429289db6cSSimon Glass } 10439289db6cSSimon Glass shift = (offset & off_mask) * 8; 10449289db6cSSimon Glass ldata = (value & val_mask) << shift; 10459289db6cSSimon Glass mask = val_mask << shift; 10469289db6cSSimon Glass value = (old & ~mask) | ldata; 10479289db6cSSimon Glass 10489289db6cSSimon Glass return value; 10499289db6cSSimon Glass } 10509289db6cSSimon Glass 1051f9260336SSimon Glass int pci_get_regions(struct udevice *dev, struct pci_region **iop, 1052f9260336SSimon Glass struct pci_region **memp, struct pci_region **prefp) 1053f9260336SSimon Glass { 1054f9260336SSimon Glass struct udevice *bus = pci_get_controller(dev); 1055f9260336SSimon Glass struct pci_controller *hose = dev_get_uclass_priv(bus); 1056f9260336SSimon Glass int i; 1057f9260336SSimon Glass 1058f9260336SSimon Glass *iop = NULL; 1059f9260336SSimon Glass *memp = NULL; 1060f9260336SSimon Glass *prefp = NULL; 1061f9260336SSimon Glass for (i = 0; i < hose->region_count; i++) { 1062f9260336SSimon Glass switch (hose->regions[i].flags) { 1063f9260336SSimon Glass case PCI_REGION_IO: 1064f9260336SSimon Glass if (!*iop || (*iop)->size < hose->regions[i].size) 1065f9260336SSimon Glass *iop = hose->regions + i; 1066f9260336SSimon Glass break; 1067f9260336SSimon Glass case PCI_REGION_MEM: 1068f9260336SSimon Glass if (!*memp || (*memp)->size < hose->regions[i].size) 1069f9260336SSimon Glass *memp = hose->regions + i; 1070f9260336SSimon Glass break; 1071f9260336SSimon Glass case (PCI_REGION_MEM | PCI_REGION_PREFETCH): 1072f9260336SSimon Glass if (!*prefp || (*prefp)->size < hose->regions[i].size) 1073f9260336SSimon Glass *prefp = hose->regions + i; 1074f9260336SSimon Glass break; 1075f9260336SSimon Glass } 1076f9260336SSimon Glass } 1077f9260336SSimon Glass 1078f9260336SSimon Glass return (*iop != NULL) + (*memp != NULL) + (*prefp != NULL); 1079f9260336SSimon Glass } 1080f9260336SSimon Glass 1081bab17cf1SSimon Glass u32 dm_pci_read_bar32(struct udevice *dev, int barnum) 1082bab17cf1SSimon Glass { 1083bab17cf1SSimon Glass u32 addr; 1084bab17cf1SSimon Glass int bar; 1085bab17cf1SSimon Glass 1086bab17cf1SSimon Glass bar = PCI_BASE_ADDRESS_0 + barnum * 4; 1087bab17cf1SSimon Glass dm_pci_read_config32(dev, bar, &addr); 1088bab17cf1SSimon Glass if (addr & PCI_BASE_ADDRESS_SPACE_IO) 1089bab17cf1SSimon Glass return addr & PCI_BASE_ADDRESS_IO_MASK; 1090bab17cf1SSimon Glass else 1091bab17cf1SSimon Glass return addr & PCI_BASE_ADDRESS_MEM_MASK; 1092bab17cf1SSimon Glass } 1093bab17cf1SSimon Glass 10949d731c82SSimon Glass void dm_pci_write_bar32(struct udevice *dev, int barnum, u32 addr) 10959d731c82SSimon Glass { 10969d731c82SSimon Glass int bar; 10979d731c82SSimon Glass 10989d731c82SSimon Glass bar = PCI_BASE_ADDRESS_0 + barnum * 4; 10999d731c82SSimon Glass dm_pci_write_config32(dev, bar, addr); 11009d731c82SSimon Glass } 11019d731c82SSimon Glass 110221d1fe7eSSimon Glass static int _dm_pci_bus_to_phys(struct udevice *ctlr, 110321d1fe7eSSimon Glass pci_addr_t bus_addr, unsigned long flags, 110421d1fe7eSSimon Glass unsigned long skip_mask, phys_addr_t *pa) 110521d1fe7eSSimon Glass { 110621d1fe7eSSimon Glass struct pci_controller *hose = dev_get_uclass_priv(ctlr); 110721d1fe7eSSimon Glass struct pci_region *res; 110821d1fe7eSSimon Glass int i; 110921d1fe7eSSimon Glass 111021d1fe7eSSimon Glass for (i = 0; i < hose->region_count; i++) { 111121d1fe7eSSimon Glass res = &hose->regions[i]; 111221d1fe7eSSimon Glass 111321d1fe7eSSimon Glass if (((res->flags ^ flags) & PCI_REGION_TYPE) != 0) 111421d1fe7eSSimon Glass continue; 111521d1fe7eSSimon Glass 111621d1fe7eSSimon Glass if (res->flags & skip_mask) 111721d1fe7eSSimon Glass continue; 111821d1fe7eSSimon Glass 111921d1fe7eSSimon Glass if (bus_addr >= res->bus_start && 112021d1fe7eSSimon Glass (bus_addr - res->bus_start) < res->size) { 112121d1fe7eSSimon Glass *pa = (bus_addr - res->bus_start + res->phys_start); 112221d1fe7eSSimon Glass return 0; 112321d1fe7eSSimon Glass } 112421d1fe7eSSimon Glass } 112521d1fe7eSSimon Glass 112621d1fe7eSSimon Glass return 1; 112721d1fe7eSSimon Glass } 112821d1fe7eSSimon Glass 112921d1fe7eSSimon Glass phys_addr_t dm_pci_bus_to_phys(struct udevice *dev, pci_addr_t bus_addr, 113021d1fe7eSSimon Glass unsigned long flags) 113121d1fe7eSSimon Glass { 113221d1fe7eSSimon Glass phys_addr_t phys_addr = 0; 113321d1fe7eSSimon Glass struct udevice *ctlr; 113421d1fe7eSSimon Glass int ret; 113521d1fe7eSSimon Glass 113621d1fe7eSSimon Glass /* The root controller has the region information */ 113721d1fe7eSSimon Glass ctlr = pci_get_controller(dev); 113821d1fe7eSSimon Glass 113921d1fe7eSSimon Glass /* 114021d1fe7eSSimon Glass * if PCI_REGION_MEM is set we do a two pass search with preference 114121d1fe7eSSimon Glass * on matches that don't have PCI_REGION_SYS_MEMORY set 114221d1fe7eSSimon Glass */ 114321d1fe7eSSimon Glass if ((flags & PCI_REGION_TYPE) == PCI_REGION_MEM) { 114421d1fe7eSSimon Glass ret = _dm_pci_bus_to_phys(ctlr, bus_addr, 114521d1fe7eSSimon Glass flags, PCI_REGION_SYS_MEMORY, 114621d1fe7eSSimon Glass &phys_addr); 114721d1fe7eSSimon Glass if (!ret) 114821d1fe7eSSimon Glass return phys_addr; 114921d1fe7eSSimon Glass } 115021d1fe7eSSimon Glass 115121d1fe7eSSimon Glass ret = _dm_pci_bus_to_phys(ctlr, bus_addr, flags, 0, &phys_addr); 115221d1fe7eSSimon Glass 115321d1fe7eSSimon Glass if (ret) 115421d1fe7eSSimon Glass puts("pci_hose_bus_to_phys: invalid physical address\n"); 115521d1fe7eSSimon Glass 115621d1fe7eSSimon Glass return phys_addr; 115721d1fe7eSSimon Glass } 115821d1fe7eSSimon Glass 115921d1fe7eSSimon Glass int _dm_pci_phys_to_bus(struct udevice *dev, phys_addr_t phys_addr, 116021d1fe7eSSimon Glass unsigned long flags, unsigned long skip_mask, 116121d1fe7eSSimon Glass pci_addr_t *ba) 116221d1fe7eSSimon Glass { 116321d1fe7eSSimon Glass struct pci_region *res; 116421d1fe7eSSimon Glass struct udevice *ctlr; 116521d1fe7eSSimon Glass pci_addr_t bus_addr; 116621d1fe7eSSimon Glass int i; 116721d1fe7eSSimon Glass struct pci_controller *hose; 116821d1fe7eSSimon Glass 116921d1fe7eSSimon Glass /* The root controller has the region information */ 117021d1fe7eSSimon Glass ctlr = pci_get_controller(dev); 117121d1fe7eSSimon Glass hose = dev_get_uclass_priv(ctlr); 117221d1fe7eSSimon Glass 117321d1fe7eSSimon Glass for (i = 0; i < hose->region_count; i++) { 117421d1fe7eSSimon Glass res = &hose->regions[i]; 117521d1fe7eSSimon Glass 117621d1fe7eSSimon Glass if (((res->flags ^ flags) & PCI_REGION_TYPE) != 0) 117721d1fe7eSSimon Glass continue; 117821d1fe7eSSimon Glass 117921d1fe7eSSimon Glass if (res->flags & skip_mask) 118021d1fe7eSSimon Glass continue; 118121d1fe7eSSimon Glass 118221d1fe7eSSimon Glass bus_addr = phys_addr - res->phys_start + res->bus_start; 118321d1fe7eSSimon Glass 118421d1fe7eSSimon Glass if (bus_addr >= res->bus_start && 118521d1fe7eSSimon Glass (bus_addr - res->bus_start) < res->size) { 118621d1fe7eSSimon Glass *ba = bus_addr; 118721d1fe7eSSimon Glass return 0; 118821d1fe7eSSimon Glass } 118921d1fe7eSSimon Glass } 119021d1fe7eSSimon Glass 119121d1fe7eSSimon Glass return 1; 119221d1fe7eSSimon Glass } 119321d1fe7eSSimon Glass 119421d1fe7eSSimon Glass pci_addr_t dm_pci_phys_to_bus(struct udevice *dev, phys_addr_t phys_addr, 119521d1fe7eSSimon Glass unsigned long flags) 119621d1fe7eSSimon Glass { 119721d1fe7eSSimon Glass pci_addr_t bus_addr = 0; 119821d1fe7eSSimon Glass int ret; 119921d1fe7eSSimon Glass 120021d1fe7eSSimon Glass /* 120121d1fe7eSSimon Glass * if PCI_REGION_MEM is set we do a two pass search with preference 120221d1fe7eSSimon Glass * on matches that don't have PCI_REGION_SYS_MEMORY set 120321d1fe7eSSimon Glass */ 120421d1fe7eSSimon Glass if ((flags & PCI_REGION_TYPE) == PCI_REGION_MEM) { 120521d1fe7eSSimon Glass ret = _dm_pci_phys_to_bus(dev, phys_addr, flags, 120621d1fe7eSSimon Glass PCI_REGION_SYS_MEMORY, &bus_addr); 120721d1fe7eSSimon Glass if (!ret) 120821d1fe7eSSimon Glass return bus_addr; 120921d1fe7eSSimon Glass } 121021d1fe7eSSimon Glass 121121d1fe7eSSimon Glass ret = _dm_pci_phys_to_bus(dev, phys_addr, flags, 0, &bus_addr); 121221d1fe7eSSimon Glass 121321d1fe7eSSimon Glass if (ret) 121421d1fe7eSSimon Glass puts("pci_hose_phys_to_bus: invalid physical address\n"); 121521d1fe7eSSimon Glass 121621d1fe7eSSimon Glass return bus_addr; 121721d1fe7eSSimon Glass } 121821d1fe7eSSimon Glass 121921d1fe7eSSimon Glass void *dm_pci_map_bar(struct udevice *dev, int bar, int flags) 122021d1fe7eSSimon Glass { 122121d1fe7eSSimon Glass pci_addr_t pci_bus_addr; 122221d1fe7eSSimon Glass u32 bar_response; 122321d1fe7eSSimon Glass 122421d1fe7eSSimon Glass /* read BAR address */ 122521d1fe7eSSimon Glass dm_pci_read_config32(dev, bar, &bar_response); 122621d1fe7eSSimon Glass pci_bus_addr = (pci_addr_t)(bar_response & ~0xf); 122721d1fe7eSSimon Glass 1228*fdb7e29cSShawn Lin #if defined(CONFIG_SYS_PCI_64BIT) 1229*fdb7e29cSShawn Lin if (bar_response & PCI_BASE_ADDRESS_MEM_TYPE_64) { 1230*fdb7e29cSShawn Lin dm_pci_read_config32(dev, bar + 4, &bar_response); 1231*fdb7e29cSShawn Lin pci_bus_addr |= (pci_addr_t)bar_response << 32; } 1232*fdb7e29cSShawn Lin #endif /* CONFIG_SYS_PCI_64BIT */ 123321d1fe7eSSimon Glass /* 123421d1fe7eSSimon Glass * Pass "0" as the length argument to pci_bus_to_virt. The arg 123521d1fe7eSSimon Glass * isn't actualy used on any platform because u-boot assumes a static 123621d1fe7eSSimon Glass * linear mapping. In the future, this could read the BAR size 123721d1fe7eSSimon Glass * and pass that as the size if needed. 123821d1fe7eSSimon Glass */ 123921d1fe7eSSimon Glass return dm_pci_bus_to_virt(dev, pci_bus_addr, flags, 0, MAP_NOCACHE); 124021d1fe7eSSimon Glass } 124121d1fe7eSSimon Glass 1242ff3e077bSSimon Glass UCLASS_DRIVER(pci) = { 1243ff3e077bSSimon Glass .id = UCLASS_PCI, 1244ff3e077bSSimon Glass .name = "pci", 12452bb02e4fSSimon Glass .flags = DM_UC_FLAG_SEQ_ALIAS, 124691195485SSimon Glass .post_bind = dm_scan_fdt_dev, 1247ff3e077bSSimon Glass .pre_probe = pci_uclass_pre_probe, 1248ff3e077bSSimon Glass .post_probe = pci_uclass_post_probe, 1249ff3e077bSSimon Glass .child_post_bind = pci_uclass_child_post_bind, 1250ff3e077bSSimon Glass .per_device_auto_alloc_size = sizeof(struct pci_controller), 1251ff3e077bSSimon Glass .per_child_platdata_auto_alloc_size = 1252ff3e077bSSimon Glass sizeof(struct pci_child_platdata), 1253ff3e077bSSimon Glass }; 1254ff3e077bSSimon Glass 1255ff3e077bSSimon Glass static const struct dm_pci_ops pci_bridge_ops = { 1256ff3e077bSSimon Glass .read_config = pci_bridge_read_config, 1257ff3e077bSSimon Glass .write_config = pci_bridge_write_config, 1258ff3e077bSSimon Glass }; 1259ff3e077bSSimon Glass 1260ff3e077bSSimon Glass static const struct udevice_id pci_bridge_ids[] = { 1261ff3e077bSSimon Glass { .compatible = "pci-bridge" }, 1262ff3e077bSSimon Glass { } 1263ff3e077bSSimon Glass }; 1264ff3e077bSSimon Glass 1265ff3e077bSSimon Glass U_BOOT_DRIVER(pci_bridge_drv) = { 1266ff3e077bSSimon Glass .name = "pci_bridge_drv", 1267ff3e077bSSimon Glass .id = UCLASS_PCI, 1268ff3e077bSSimon Glass .of_match = pci_bridge_ids, 1269ff3e077bSSimon Glass .ops = &pci_bridge_ops, 1270ff3e077bSSimon Glass }; 1271ff3e077bSSimon Glass 1272ff3e077bSSimon Glass UCLASS_DRIVER(pci_generic) = { 1273ff3e077bSSimon Glass .id = UCLASS_PCI_GENERIC, 1274ff3e077bSSimon Glass .name = "pci_generic", 1275ff3e077bSSimon Glass }; 1276ff3e077bSSimon Glass 1277ff3e077bSSimon Glass static const struct udevice_id pci_generic_ids[] = { 1278ff3e077bSSimon Glass { .compatible = "pci-generic" }, 1279ff3e077bSSimon Glass { } 1280ff3e077bSSimon Glass }; 1281ff3e077bSSimon Glass 1282ff3e077bSSimon Glass U_BOOT_DRIVER(pci_generic_drv) = { 1283ff3e077bSSimon Glass .name = "pci_generic_drv", 1284ff3e077bSSimon Glass .id = UCLASS_PCI_GENERIC, 1285ff3e077bSSimon Glass .of_match = pci_generic_ids, 1286ff3e077bSSimon Glass }; 1287e578b92cSStephen Warren 1288e578b92cSStephen Warren void pci_init(void) 1289e578b92cSStephen Warren { 1290e578b92cSStephen Warren struct udevice *bus; 1291e578b92cSStephen Warren 1292e578b92cSStephen Warren /* 1293e578b92cSStephen Warren * Enumerate all known controller devices. Enumeration has the side- 1294e578b92cSStephen Warren * effect of probing them, so PCIe devices will be enumerated too. 1295e578b92cSStephen Warren */ 1296e578b92cSStephen Warren for (uclass_first_device(UCLASS_PCI, &bus); 1297e578b92cSStephen Warren bus; 1298e578b92cSStephen Warren uclass_next_device(&bus)) { 1299e578b92cSStephen Warren ; 1300e578b92cSStephen Warren } 1301e578b92cSStephen Warren } 1302