#include <common.h>
#include <dm.h>
#include <errno.h>
-#include <inttypes.h>
#include <pci.h>
#include <asm/io.h>
#include <dm/device-internal.h>
if (ret)
goto error;
debug("%s: Match found: %s\n", __func__, drv->name);
- dev->driver_data = find_id->driver_data;
+ dev->driver_data = id->driver_data;
*devp = dev;
return 0;
}
struct udevice *dev;
ulong class;
+ if (!PCI_FUNC(bdf))
+ found_multi = false;
if (PCI_FUNC(bdf) && !found_multi)
continue;
/* Check only the first access, we don't expect problems */
return ret;
}
-static int decode_regions(struct pci_controller *hose, ofnode parent_node,
- ofnode node)
+static void decode_regions(struct pci_controller *hose, ofnode parent_node,
+ ofnode node)
{
int pci_addr_cells, addr_cells, size_cells;
int cells_per_record;
int i;
prop = ofnode_get_property(node, "ranges", &len);
- if (!prop)
- return -EINVAL;
+ if (!prop) {
+ debug("%s: Cannot decode regions\n", __func__);
+ return;
+ }
+
pci_addr_cells = ofnode_read_simple_addr_cells(node);
addr_cells = ofnode_read_simple_addr_cells(parent_node);
size_cells = ofnode_read_simple_size_cells(node);
prop += addr_cells;
size = fdtdec_get_number(prop, size_cells);
prop += size_cells;
- debug("%s: region %d, pci_addr=%" PRIx64 ", addr=%" PRIx64
- ", size=%" PRIx64 ", space_code=%d\n", __func__,
- hose->region_count, pci_addr, addr, size, space_code);
+ debug("%s: region %d, pci_addr=%llx, addr=%llx, size=%llx, space_code=%d\n",
+ __func__, hose->region_count, pci_addr, addr, size, space_code);
if (space_code & 2) {
type = flags & (1U << 30) ? PCI_REGION_PREFETCH :
PCI_REGION_MEM;
bd_t *bd = gd->bd;
if (!bd)
- return 0;
+ return;
for (i = 0; i < CONFIG_NR_DRAM_BANKS; ++i) {
if (bd->bi_dram[i].size) {
base, size, PCI_REGION_MEM | PCI_REGION_SYS_MEMORY);
#endif
- return 0;
+ return;
}
static int pci_uclass_pre_probe(struct udevice *bus)
{
struct pci_controller *hose;
- int ret;
debug("%s, bus=%d/%s, parent=%s\n", __func__, bus->seq, bus->name,
bus->parent->name);
/* For bridges, use the top-level PCI controller */
if (!device_is_on_pci_bus(bus)) {
hose->ctlr = bus;
- ret = decode_regions(hose, dev_ofnode(bus->parent),
- dev_ofnode(bus));
- if (ret) {
- debug("%s: Cannot decode regions\n", __func__);
- return ret;
- }
+ decode_regions(hose, dev_ofnode(bus->parent), dev_ofnode(bus));
} else {
struct pci_controller *parent_hose;
if (!dev_of_valid(dev))
return 0;
- /*
- * We could read vendor, device, class if available. But for now we
- * just check the address.
- */
pplat = dev_get_parent_platdata(dev);
+
+ /* Extract vendor id and device id if available */
+ ofnode_read_pci_vendev(dev_ofnode(dev), &pplat->vendor, &pplat->device);
+
+ /* Extract the devfn from fdt_pci_addr */
ret = ofnode_read_pci_addr(dev_ofnode(dev), FDT_PCI_SPACE_CONFIG, "reg",
&addr);
-
if (ret) {
if (ret != -ENOENT)
return -EINVAL;
} else {
- /* extract the devfn from fdt_pci_addr */
pplat->devfn = addr.phys_hi & 0xff00;
}
struct pci_region *res;
int i;
+ if (hose->region_count == 0) {
+ *pa = bus_addr;
+ return 0;
+ }
+
for (i = 0; i < hose->region_count; i++) {
res = &hose->regions[i];
ctlr = pci_get_controller(dev);
hose = dev_get_uclass_priv(ctlr);
+ if (hose->region_count == 0) {
+ *ba = phys_addr;
+ return 0;
+ }
+
for (i = 0; i < hose->region_count; i++) {
res = &hose->regions[i];
return dm_pci_bus_to_virt(dev, pci_bus_addr, flags, 0, MAP_NOCACHE);
}
+int dm_pci_find_capability(struct udevice *dev, int cap)
+{
+ u16 status;
+ u8 header_type;
+ int ttl = PCI_FIND_CAP_TTL;
+ u8 id;
+ u16 ent;
+ u8 pos;
+
+ dm_pci_read_config16(dev, PCI_STATUS, &status);
+ if (!(status & PCI_STATUS_CAP_LIST))
+ return 0;
+
+ dm_pci_read_config8(dev, PCI_HEADER_TYPE, &header_type);
+ if ((header_type & 0x7f) == PCI_HEADER_TYPE_CARDBUS)
+ pos = PCI_CB_CAPABILITY_LIST;
+ else
+ pos = PCI_CAPABILITY_LIST;
+
+ dm_pci_read_config8(dev, pos, &pos);
+ while (ttl--) {
+ if (pos < PCI_STD_HEADER_SIZEOF)
+ break;
+ pos &= ~3;
+ dm_pci_read_config16(dev, pos, &ent);
+
+ id = ent & 0xff;
+ if (id == 0xff)
+ break;
+ if (id == cap)
+ return pos;
+ pos = (ent >> 8);
+ }
+
+ return 0;
+}
+
+int dm_pci_find_ext_capability(struct udevice *dev, int cap)
+{
+ u32 header;
+ int ttl;
+ int pos = PCI_CFG_SPACE_SIZE;
+
+ /* minimum 8 bytes per capability */
+ ttl = (PCI_CFG_SPACE_EXP_SIZE - PCI_CFG_SPACE_SIZE) / 8;
+
+ dm_pci_read_config32(dev, pos, &header);
+ /*
+ * If we have no capabilities, this is indicated by cap ID,
+ * cap version and next pointer all being 0.
+ */
+ if (header == 0)
+ return 0;
+
+ while (ttl--) {
+ if (PCI_EXT_CAP_ID(header) == cap)
+ return pos;
+
+ pos = PCI_EXT_CAP_NEXT(header);
+ if (pos < PCI_CFG_SPACE_SIZE)
+ break;
+
+ dm_pci_read_config32(dev, pos, &header);
+ }
+
+ return 0;
+}
+
UCLASS_DRIVER(pci) = {
.id = UCLASS_PCI,
.name = "pci",