};
pci@1,0 {
compatible = "pci-generic";
- reg = <0x0800 0 0 0 0>;
+ /* reg 0 is at 0x14, using FDT_PCI_SPACE_MEM32 */
+ reg = <0x02000814 0 0 0 0
+ 0x01000810 0 0 0 0>;
sandbox,emul = <&swap_case_emul0_1>;
};
pci@1f,0 {
compatible = "pci-generic";
- reg = <0xf800 0 0 0 0>;
+ /* reg 0 is at 0x10, using FDT_PCI_SPACE_IO */
+ reg = <0x0100f810 0 0 0 0>;
sandbox,emul = <&swap_case_emul0_1f>;
};
};
return map_physmem(addr, size, MAP_NOCACHE);
}
+
+fdt_addr_t devfdt_get_addr_pci(struct udevice *dev)
+{
+ ulong addr;
+
+ addr = devfdt_get_addr(dev);
+ if (CONFIG_IS_ENABLED(PCI) && IS_ENABLED(CONFIG_DM_PCI) &&
+ addr == FDT_ADDR_T_NONE) {
+ struct fdt_pci_addr pci_addr;
+ u32 bar;
+ int ret;
+
+ ret = fdtdec_get_pci_addr(gd->fdt_blob,
+ dev_of_offset(dev),
+ FDT_PCI_SPACE_MEM32, "reg",
+ &pci_addr);
+ if (ret) {
+ /* try if there is any i/o-mapped register */
+ ret = fdtdec_get_pci_addr(gd->fdt_blob,
+ dev_of_offset(dev),
+ FDT_PCI_SPACE_IO, "reg",
+ &pci_addr);
+ if (ret)
+ return FDT_ADDR_T_NONE;
+ }
+ ret = fdtdec_get_pci_bar32(dev, &pci_addr, &bar);
+ if (ret)
+ return FDT_ADDR_T_NONE;
+ addr = bar;
+ }
+
+ return addr;
+}
return fdtdec_get_alias_highest_id(gd->fdt_blob, stem);
}
+
+fdt_addr_t dev_read_addr_pci(struct udevice *dev)
+{
+ ulong addr;
+
+ addr = dev_read_addr(dev);
+ if (addr == FDT_ADDR_T_NONE && !of_live_active())
+ addr = devfdt_get_addr_pci(dev);
+
+ return addr;
+}
int err;
/* try Processor Local Bus device first */
- addr = dev_read_addr(dev);
-#if CONFIG_IS_ENABLED(PCI) && defined(CONFIG_DM_PCI)
- if (addr == FDT_ADDR_T_NONE) {
- /* then try pci device */
- struct fdt_pci_addr pci_addr;
- u32 bar;
- int ret;
-
- /* we prefer to use a memory-mapped register */
- ret = fdtdec_get_pci_addr(gd->fdt_blob, dev_of_offset(dev),
- FDT_PCI_SPACE_MEM32, "reg",
- &pci_addr);
- if (ret) {
- /* try if there is any i/o-mapped register */
- ret = fdtdec_get_pci_addr(gd->fdt_blob,
- dev_of_offset(dev),
- FDT_PCI_SPACE_IO,
- "reg", &pci_addr);
- if (ret)
- return ret;
- }
-
- ret = fdtdec_get_pci_bar32(dev, &pci_addr, &bar);
- if (ret)
- return ret;
-
- addr = bar;
- }
-#endif
-
+ addr = dev_read_addr_pci(dev);
if (addr == FDT_ADDR_T_NONE)
return -EINVAL;
fdt_addr_t devfdt_get_addr_size_name(struct udevice *dev, const char *name,
fdt_size_t *size);
+/**
+ * devfdt_get_addr_pci() - Read an address and handle PCI address translation
+ *
+ * @dev: Device to read from
+ * @return address or FDT_ADDR_T_NONE if not found
+ */
+fdt_addr_t devfdt_get_addr_pci(struct udevice *dev);
+
#endif
*/
void *dev_read_addr_ptr(struct udevice *dev);
+/**
+ * dev_read_addr_pci() - Read an address and handle PCI address translation
+ *
+ * At present U-Boot does not have address translation logic for PCI in the
+ * livetree implementation (of_addr.c). This special function supports this for
+ * the flat tree implementation.
+ *
+ * This function should be removed (and code should use dev_read() instead)
+ * once:
+ *
+ * 1. PCI address translation is added; and either
+ * 2. everything uses livetree where PCI translation is used (which is feasible
+ * in SPL and U-Boot proper) or PCI address translation is added to
+ * fdtdec_get_addr() and friends.
+ *
+ * @dev: Device to read from
+ * @return address or FDT_ADDR_T_NONE if not found
+ */
+fdt_addr_t dev_read_addr_pci(struct udevice *dev);
+
/**
* dev_remap_addr() - Get the reg property of a device as a
* memory-mapped I/O pointer
return devfdt_get_addr_ptr(dev);
}
+static inline fdt_addr_t dev_read_addr_pci(struct udevice *dev)
+{
+ return devfdt_get_addr_pci(dev);
+}
+
static inline void *dev_remap_addr(struct udevice *dev)
{
return devfdt_remap_addr(dev);
return 0;
}
DM_TEST(dm_test_pci_ea, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
+
+/* Test the dev_read_addr_pci() function */
+static int dm_test_pci_addr_flat(struct unit_test_state *uts)
+{
+ struct udevice *swap1f, *swap1;
+ ulong io_addr, mem_addr;
+
+ ut_assertok(dm_pci_bus_find_bdf(PCI_BDF(0, 0x1f, 0), &swap1f));
+ io_addr = dm_pci_read_bar32(swap1f, 0);
+ ut_asserteq(io_addr, dev_read_addr_pci(swap1f));
+
+ /*
+ * This device has both I/O and MEM spaces but the MEM space appears
+ * first
+ */
+ ut_assertok(dm_pci_bus_find_bdf(PCI_BDF(0, 0x1, 0), &swap1));
+ mem_addr = dm_pci_read_bar32(swap1, 1);
+ ut_asserteq(mem_addr, dev_read_addr_pci(swap1));
+
+ return 0;
+}
+DM_TEST(dm_test_pci_addr_flat, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT |
+ DM_TESTF_FLAT_TREE);
+
+/*
+ * Test the dev_read_addr_pci() function with livetree. That function is
+ * not currently fully implemented, in that it fails to return the BAR address.
+ * Once that is implemented this test can be removed and dm_test_pci_addr_flat()
+ * can be used for both flattree and livetree by removing the DM_TESTF_FLAT_TREE
+ * flag above.
+ */
+static int dm_test_pci_addr_live(struct unit_test_state *uts)
+{
+ struct udevice *swap1f, *swap1;
+
+ ut_assertok(dm_pci_bus_find_bdf(PCI_BDF(0, 0x1f, 0), &swap1f));
+ ut_asserteq(FDT_ADDR_T_NONE, dev_read_addr_pci(swap1f));
+
+ ut_assertok(dm_pci_bus_find_bdf(PCI_BDF(0, 0x1, 0), &swap1));
+ ut_asserteq(FDT_ADDR_T_NONE, dev_read_addr_pci(swap1));
+
+ return 0;
+}
+DM_TEST(dm_test_pci_addr_live, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT |
+ DM_TESTF_LIVE_TREE);