mirror of
https://github.com/Fishwaldo/u-boot.git
synced 2025-03-19 13:41:31 +00:00
dm: pci: Add a function to read a PCI BAR
At present PCI address transaction is not supported so drivers must manually read the correct BAR after reading the device tree info. The ns16550 has a suitable implementation, so move this code into the core DM support. Note that there is no live-tree equivalent at present. Signed-off-by: Simon Glass <sjg@chromium.org> Reviewed-by: Bin Meng <bmeng.cn@gmail.com> Tested-by: Bin Meng <bmeng.cn@gmail.com> [bmeng: correct the unclear comments in test.dts] Signed-off-by: Bin Meng <bmeng.cn@gmail.com>
This commit is contained in:
parent
6a73cf3d8f
commit
33c215af4b
7 changed files with 128 additions and 32 deletions
|
@ -456,12 +456,15 @@
|
||||||
};
|
};
|
||||||
pci@1,0 {
|
pci@1,0 {
|
||||||
compatible = "pci-generic";
|
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>;
|
sandbox,emul = <&swap_case_emul0_1>;
|
||||||
};
|
};
|
||||||
pci@1f,0 {
|
pci@1f,0 {
|
||||||
compatible = "pci-generic";
|
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>;
|
sandbox,emul = <&swap_case_emul0_1f>;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -190,3 +190,36 @@ void *devfdt_map_physmem(struct udevice *dev, unsigned long size)
|
||||||
|
|
||||||
return map_physmem(addr, size, MAP_NOCACHE);
|
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;
|
||||||
|
}
|
||||||
|
|
|
@ -307,3 +307,14 @@ int dev_read_alias_highest_id(const char *stem)
|
||||||
|
|
||||||
return fdtdec_get_alias_highest_id(gd->fdt_blob, stem);
|
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;
|
||||||
|
}
|
||||||
|
|
|
@ -440,36 +440,7 @@ int ns16550_serial_ofdata_to_platdata(struct udevice *dev)
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
/* try Processor Local Bus device first */
|
/* try Processor Local Bus device first */
|
||||||
addr = dev_read_addr(dev);
|
addr = dev_read_addr_pci(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
|
|
||||||
|
|
||||||
if (addr == FDT_ADDR_T_NONE)
|
if (addr == FDT_ADDR_T_NONE)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
|
|
|
@ -138,4 +138,12 @@ fdt_addr_t devfdt_get_addr_name(struct udevice *dev, const char *name);
|
||||||
fdt_addr_t devfdt_get_addr_size_name(struct udevice *dev, const char *name,
|
fdt_addr_t devfdt_get_addr_size_name(struct udevice *dev, const char *name,
|
||||||
fdt_size_t *size);
|
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
|
#endif
|
||||||
|
|
|
@ -248,6 +248,26 @@ fdt_addr_t dev_read_addr(struct udevice *dev);
|
||||||
*/
|
*/
|
||||||
void *dev_read_addr_ptr(struct udevice *dev);
|
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
|
* dev_remap_addr() - Get the reg property of a device as a
|
||||||
* memory-mapped I/O pointer
|
* memory-mapped I/O pointer
|
||||||
|
@ -691,6 +711,11 @@ static inline void *dev_read_addr_ptr(struct udevice *dev)
|
||||||
return devfdt_get_addr_ptr(dev);
|
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)
|
static inline void *dev_remap_addr(struct udevice *dev)
|
||||||
{
|
{
|
||||||
return devfdt_remap_addr(dev);
|
return devfdt_remap_addr(dev);
|
||||||
|
|
|
@ -294,3 +294,48 @@ static int dm_test_pci_ea(struct unit_test_state *uts)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
DM_TEST(dm_test_pci_ea, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
|
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);
|
||||||
|
|
Loading…
Add table
Reference in a new issue