[U-Boot] [PATCH v3 0/1] cmd: pci: add option to parse and display BAR information

From: Yehuda Yitschak yehuday@marvell.com
Updated v3 following review from Simon. The only issue i wasn't able to address is the warnings on the PCI BAR print format when compiling sandbox. I wasn't able to reproduce them on my machine nor when compiling to ARMv7 (32 bit) or ARMv8 (64 bit).
v2->v3: - removed support for !DM_PCI - Fixed error return values
v1->v2: - Added support for DM_PCI - Added print of memory type and prefetchable flag - Skipped printing of disabled BARs
Yehuda Yitschak (1): cmd: pci: add option to parse and display BAR information
cmd/pci.c | 82 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 82 insertions(+)

From: Yehuda Yitschak yehuday@marvell.com
Currently the PCI command only allows to see the BAR register values but not the size and actual base address. This little extension parses the BAR registers and displays the base, size and type of each BAR.
Signed-off-by: Yehuda Yitschak yehuday@marvell.com --- cmd/pci.c | 82 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 82 insertions(+)
diff --git a/cmd/pci.c b/cmd/pci.c index 2f4978a..8e4b7d8 100644 --- a/cmd/pci.c +++ b/cmd/pci.c @@ -92,6 +92,76 @@ static void pci_show_regs(pci_dev_t dev, struct pci_reg_info *regs) } #endif
+#ifdef CONFIG_DM_PCI +int pci_bar_show(struct udevice *dev) +{ + u8 header_type; + int bar_cnt, bar_id, is_64, is_io, mem_type; + u32 base_low, base_high; + u32 size_low, size_high; + u64 base, size; + u32 reg_addr; + int prefetchable; + + dm_pci_read_config8(dev, PCI_HEADER_TYPE, &header_type); + + if (header_type == PCI_HEADER_TYPE_CARDBUS) { + printf("CardBus doesn't support BARs\n"); + return -ENOSYS; + } + + bar_cnt = (header_type == PCI_HEADER_TYPE_NORMAL) ? 6 : 2; + + printf("ID Base Size Width Type\n"); + printf("----------------------------------------------------------\n"); + + bar_id = 0; + reg_addr = PCI_BASE_ADDRESS_0; + while (bar_cnt) { + dm_pci_read_config32(dev, reg_addr, &base_low); + dm_pci_write_config32(dev, reg_addr, 0xffffffff); + dm_pci_read_config32(dev, reg_addr, &size_low); + dm_pci_write_config32(dev, reg_addr, base_low); + reg_addr += 4; + + base = base_low & ~0xf; + size = size_low & ~0xf; + base_high = 0x0; + size_high = 0xffffffff; + is_64 = 0; + prefetchable = base_low & PCI_BASE_ADDRESS_MEM_PREFETCH; + is_io = base_low & PCI_BASE_ADDRESS_SPACE_IO; + mem_type = base_low & PCI_BASE_ADDRESS_MEM_TYPE_MASK; + + if (mem_type == PCI_BASE_ADDRESS_MEM_TYPE_64) { + dm_pci_read_config32(dev, reg_addr, &base_high); + dm_pci_write_config32(dev, reg_addr, 0xffffffff); + dm_pci_read_config32(dev, reg_addr, &size_high); + dm_pci_write_config32(dev, reg_addr, base_high); + bar_cnt--; + reg_addr += 4; + is_64 = 1; + } + + base = base | ((u64)base_high << 32); + size = size | ((u64)size_high << 32); + + if ((!is_64 && size_low) || (is_64 && size)) { + size = ~size + 1; + printf(" %d %#016llx %#016llx %d %s %s\n", + bar_id, base, size, is_64 ? 64 : 32, + is_io ? "I/O" : "MEM", + prefetchable ? "Prefetchable" : ""); + } + + bar_id++; + bar_cnt--; + } + + return 0; +} +#endif + static struct pci_reg_info regs_start[] = { { "vendor ID", PCI_SIZE_16, PCI_VENDOR_ID }, { "device ID", PCI_SIZE_16, PCI_DEVICE_ID }, @@ -573,6 +643,9 @@ static int do_pci(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) if (argc > 4) value = simple_strtoul(argv[4], NULL, 16); case 'h': /* header */ +#ifdef CONFIG_DM_PCI + case 'b': /* bars */ +#endif if (argc < 3) goto usage; if ((bdf = get_pci_dev(argv[2])) == -1) @@ -641,6 +714,11 @@ static int do_pci(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) ret = pci_cfg_write(dev, addr, size, value); #endif break; +#ifdef CONFIG_DM_PCI + + case 'b': /* bars */ + return pci_bar_show(dev); +#endif default: ret = CMD_RET_USAGE; break; @@ -663,6 +741,10 @@ static char pci_help_text[] = #endif "pci header b.d.f\n" " - show header of PCI device 'bus.device.function'\n" +#ifdef CONFIG_DM_PCI + "pci bar b.d.f\n" + " - show BARs base and size for device b.d.f'\n" +#endif "pci display[.b, .w, .l] b.d.f [address] [# of objects]\n" " - display PCI configuration space (CFG)\n" "pci next[.b, .w, .l] b.d.f address\n"

Hi,
On 30 November 2016 at 01:05, yehuday@marvell.com wrote:
From: Yehuda Yitschak yehuday@marvell.com
Currently the PCI command only allows to see the BAR register values but not the size and actual base address. This little extension parses the BAR registers and displays the base, size and type of each BAR.
Signed-off-by: Yehuda Yitschak yehuday@marvell.com
cmd/pci.c | 82 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 82 insertions(+)
Acked-by: Simon Glass sjg@chromium.org
Nit below.
diff --git a/cmd/pci.c b/cmd/pci.c index 2f4978a..8e4b7d8 100644 --- a/cmd/pci.c +++ b/cmd/pci.c @@ -92,6 +92,76 @@ static void pci_show_regs(pci_dev_t dev, struct pci_reg_info *regs) } #endif
+#ifdef CONFIG_DM_PCI +int pci_bar_show(struct udevice *dev) +{
u8 header_type;
int bar_cnt, bar_id, is_64, is_io, mem_type;
bool is_64;
u32 base_low, base_high;
u32 size_low, size_high;
u64 base, size;
u32 reg_addr;
int prefetchable;
dm_pci_read_config8(dev, PCI_HEADER_TYPE, &header_type);
if (header_type == PCI_HEADER_TYPE_CARDBUS) {
printf("CardBus doesn't support BARs\n");
return -ENOSYS;
}
bar_cnt = (header_type == PCI_HEADER_TYPE_NORMAL) ? 6 : 2;
printf("ID Base Size Width Type\n");
printf("----------------------------------------------------------\n");
bar_id = 0;
reg_addr = PCI_BASE_ADDRESS_0;
while (bar_cnt) {
dm_pci_read_config32(dev, reg_addr, &base_low);
dm_pci_write_config32(dev, reg_addr, 0xffffffff);
dm_pci_read_config32(dev, reg_addr, &size_low);
dm_pci_write_config32(dev, reg_addr, base_low);
reg_addr += 4;
base = base_low & ~0xf;
size = size_low & ~0xf;
base_high = 0x0;
size_high = 0xffffffff;
is_64 = 0;
prefetchable = base_low & PCI_BASE_ADDRESS_MEM_PREFETCH;
is_io = base_low & PCI_BASE_ADDRESS_SPACE_IO;
mem_type = base_low & PCI_BASE_ADDRESS_MEM_TYPE_MASK;
if (mem_type == PCI_BASE_ADDRESS_MEM_TYPE_64) {
dm_pci_read_config32(dev, reg_addr, &base_high);
dm_pci_write_config32(dev, reg_addr, 0xffffffff);
dm_pci_read_config32(dev, reg_addr, &size_high);
dm_pci_write_config32(dev, reg_addr, base_high);
bar_cnt--;
reg_addr += 4;
is_64 = 1;
}
base = base | ((u64)base_high << 32);
size = size | ((u64)size_high << 32);
if ((!is_64 && size_low) || (is_64 && size)) {
size = ~size + 1;
printf(" %d %#016llx %#016llx %d %s %s\n",
bar_id, base, size, is_64 ? 64 : 32,
is_io ? "I/O" : "MEM",
prefetchable ? "Prefetchable" : "");
}
bar_id++;
bar_cnt--;
}
return 0;
+} +#endif
static struct pci_reg_info regs_start[] = { { "vendor ID", PCI_SIZE_16, PCI_VENDOR_ID }, { "device ID", PCI_SIZE_16, PCI_DEVICE_ID }, @@ -573,6 +643,9 @@ static int do_pci(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) if (argc > 4) value = simple_strtoul(argv[4], NULL, 16); case 'h': /* header */ +#ifdef CONFIG_DM_PCI
case 'b': /* bars */
+#endif if (argc < 3) goto usage; if ((bdf = get_pci_dev(argv[2])) == -1) @@ -641,6 +714,11 @@ static int do_pci(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) ret = pci_cfg_write(dev, addr, size, value); #endif break; +#ifdef CONFIG_DM_PCI
case 'b': /* bars */
return pci_bar_show(dev);
+#endif default: ret = CMD_RET_USAGE; break; @@ -663,6 +741,10 @@ static char pci_help_text[] = #endif "pci header b.d.f\n" " - show header of PCI device 'bus.device.function'\n" +#ifdef CONFIG_DM_PCI
"pci bar b.d.f\n"
" - show BARs base and size for device b.d.f'\n"
+#endif "pci display[.b, .w, .l] b.d.f [address] [# of objects]\n" " - display PCI configuration space (CFG)\n" "pci next[.b, .w, .l] b.d.f address\n" -- 1.9.1
participants (2)
-
Simon Glass
-
yehuday@marvell.com