summaryrefslogtreecommitdiff
path: root/drivers/pci
diff options
context:
space:
mode:
authorTuomas Tynkkynen <tuomas.tynkkynen@iki.fi>2017-09-19 23:18:03 +0300
committerTom Rini <trini@konsulko.com>2017-10-06 11:27:40 -0400
commitbadb99220a42f88bc823c884e487657bfe734a4d (patch)
tree8dffd731258ba71229fdc9440eefc60f380284ce /drivers/pci
parenta4d72869f83a7f31a2f0bd000cea86980ddb975f (diff)
pci: Add helper for implementing memory-mapped config space accesses
This sort of pattern for implementing memory-mapped PCI config space accesses appears in U-Boot twice already, and a third user is coming up. So add helper functions to avoid code duplication, similar to how Linux has pci_generic_config_write and pci_generic_config_read. Signed-off-by: Tuomas Tynkkynen <tuomas.tynkkynen@iki.fi> Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
Diffstat (limited to 'drivers/pci')
-rw-r--r--drivers/pci/pci-uclass.c58
1 files changed, 58 insertions, 0 deletions
diff --git a/drivers/pci/pci-uclass.c b/drivers/pci/pci-uclass.c
index 86df141d60..5a24eb6428 100644
--- a/drivers/pci/pci-uclass.c
+++ b/drivers/pci/pci-uclass.c
@@ -518,6 +518,64 @@ int pci_auto_config_devices(struct udevice *bus)
return sub_bus;
}
+int pci_generic_mmap_write_config(
+ struct udevice *bus,
+ int (*addr_f)(struct udevice *bus, pci_dev_t bdf, uint offset, void **addrp),
+ pci_dev_t bdf,
+ uint offset,
+ ulong value,
+ enum pci_size_t size)
+{
+ void *address;
+
+ if (addr_f(bus, bdf, offset, &address) < 0)
+ return 0;
+
+ switch (size) {
+ case PCI_SIZE_8:
+ writeb(value, address);
+ return 0;
+ case PCI_SIZE_16:
+ writew(value, address);
+ return 0;
+ case PCI_SIZE_32:
+ writel(value, address);
+ return 0;
+ default:
+ return -EINVAL;
+ }
+}
+
+int pci_generic_mmap_read_config(
+ struct udevice *bus,
+ int (*addr_f)(struct udevice *bus, pci_dev_t bdf, uint offset, void **addrp),
+ pci_dev_t bdf,
+ uint offset,
+ ulong *valuep,
+ enum pci_size_t size)
+{
+ void *address;
+
+ if (addr_f(bus, bdf, offset, &address) < 0) {
+ *valuep = pci_get_ff(size);
+ return 0;
+ }
+
+ switch (size) {
+ case PCI_SIZE_8:
+ *valuep = readb(address);
+ return 0;
+ case PCI_SIZE_16:
+ *valuep = readw(address);
+ return 0;
+ case PCI_SIZE_32:
+ *valuep = readl(address);
+ return 0;
+ default:
+ return -EINVAL;
+ }
+}
+
int dm_pci_hose_probe_bus(struct udevice *bus)
{
int sub_bus;