diff options
author | Alex Marginean <alexm.osslist@gmail.com> | 2019-06-07 11:24:23 +0300 |
---|---|---|
committer | Simon Glass <sjg@chromium.org> | 2019-07-10 16:52:58 -0600 |
commit | 0b143d8ab2b84219552d652e46619360a38888d1 (patch) | |
tree | 165554ec7e72d81dcb55564cd6586e3635cf7688 /drivers | |
parent | 2204bc1bd3abedc37a72282b4ddcfb3eca8cfccb (diff) | |
download | u-boot-0b143d8ab2b84219552d652e46619360a38888d1.tar.gz |
drivers: pci: add map_bar support for Enhanced Allocation
Makes dm_pci_map_bar API available for integrated PCI devices that
support Enhanced Allocation instead of the original PCI BAR mechanism.
Signed-off-by: Alex Marginean <alexm.osslist@gmail.com>
Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/pci/pci-uclass.c | 46 |
1 files changed, 46 insertions, 0 deletions
diff --git a/drivers/pci/pci-uclass.c b/drivers/pci/pci-uclass.c index cf1e7617ae..389aec15ce 100644 --- a/drivers/pci/pci-uclass.c +++ b/drivers/pci/pci-uclass.c @@ -1341,10 +1341,56 @@ pci_addr_t dm_pci_phys_to_bus(struct udevice *dev, phys_addr_t phys_addr, return bus_addr; } +static void *dm_pci_map_ea_bar(struct udevice *dev, int bar, int flags, + int ea_off) +{ + int ea_cnt, i, entry_size; + int bar_id = (bar - PCI_BASE_ADDRESS_0) >> 2; + u32 ea_entry; + phys_addr_t addr; + + /* EA capability structure header */ + dm_pci_read_config32(dev, ea_off, &ea_entry); + ea_cnt = (ea_entry >> 16) & PCI_EA_NUM_ENT_MASK; + ea_off += PCI_EA_FIRST_ENT; + + for (i = 0; i < ea_cnt; i++, ea_off += entry_size) { + /* Entry header */ + dm_pci_read_config32(dev, ea_off, &ea_entry); + entry_size = ((ea_entry & PCI_EA_ES) + 1) << 2; + + if (((ea_entry & PCI_EA_BEI) >> 4) != bar_id) + continue; + + /* Base address, 1st DW */ + dm_pci_read_config32(dev, ea_off + 4, &ea_entry); + addr = ea_entry & PCI_EA_FIELD_MASK; + if (ea_entry & PCI_EA_IS_64) { + /* Base address, 2nd DW, skip over 4B MaxOffset */ + dm_pci_read_config32(dev, ea_off + 12, &ea_entry); + addr |= ((u64)ea_entry) << 32; + } + + /* size ignored for now */ + return map_physmem(addr, flags, 0); + } + + return 0; +} + void *dm_pci_map_bar(struct udevice *dev, int bar, int flags) { pci_addr_t pci_bus_addr; u32 bar_response; + int ea_off; + + /* + * if the function supports Enhanced Allocation use that instead of + * BARs + */ + ea_off = dm_pci_find_capability(dev, PCI_CAP_ID_EA); + if (ea_off) + return dm_pci_map_ea_bar(dev, bar, flags, ea_off); /* read BAR address */ dm_pci_read_config32(dev, bar, &bar_response); |