summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPhil Sutter <phil@nwl.cc>2021-01-03 23:06:45 +0100
committerStefan Roese <sr@denx.de>2021-01-27 07:29:43 +0100
commitc1b1263b160ece33b2164dc3cd107f0d1dec52fd (patch)
treec51ca6f2e09f5595c973fe101ea2ab4a65768a67
parent7d3c6c6e9ff431669d22d5f46bc8ad4b963a905a (diff)
downloadu-boot-c1b1263b160ece33b2164dc3cd107f0d1dec52fd.tar.gz
pci: Make auto-config code a little more robust
On my DS414, some PCI devices return odd values when probing BAR sizes. An obvious case is all-ones response, the Linux driver (drivers/pci/probe.c) catches those explicitly and a comment explains that either bit 0 or bit 1 must be clear (depending on MEM or IO type). Other BARs return e.g. 0xfff0000f or 0xfff00004 and thus manage to break size calculation due to the "middle" zeroes. Mitigate that copying more or less what Linux does and do a "find least bit set". Signed-off-by: Phil Sutter <phil@nwl.cc> Reviewed-by: Stefan Roese <sr@denx.de> Reviewed-by: Simon Glass <sjg@chromium.org>
-rw-r--r--drivers/pci/pci_auto.c9
1 files changed, 5 insertions, 4 deletions
diff --git a/drivers/pci/pci_auto.c b/drivers/pci/pci_auto.c
index 68ef4e8092..b37dd994e5 100644
--- a/drivers/pci/pci_auto.c
+++ b/drivers/pci/pci_auto.c
@@ -47,16 +47,17 @@ void dm_pciauto_setup_device(struct udevice *dev, int bars_num,
dm_pci_write_config32(dev, bar, 0xffffffff);
dm_pci_read_config32(dev, bar, &bar_response);
- /* If BAR is not implemented go to the next BAR */
- if (!bar_response)
+ /* If BAR is not implemented (or invalid) go to the next BAR */
+ if (!bar_response || bar_response == 0xffffffff)
continue;
found_mem64 = 0;
/* Check the BAR type and set our address mask */
if (bar_response & PCI_BASE_ADDRESS_SPACE) {
- bar_size = ((~(bar_response & PCI_BASE_ADDRESS_IO_MASK))
- & 0xffff) + 1;
+ bar_size = bar_response & PCI_BASE_ADDRESS_IO_MASK;
+ bar_size &= ~(bar_size - 1);
+
if (!enum_only)
bar_res = io;