This is an automated email from the ASF dual-hosted git repository.
xiaoxiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git
The following commit(s) were added to refs/heads/master by this push:
new aa1df4e9a9 pci: fix pci dev alloc bridge mem error
aa1df4e9a9 is described below
commit aa1df4e9a9e8cd3c0a2b32ae2d8054a4b0f7d08b
Author: lipengfei28 <[email protected]>
AuthorDate: Wed Nov 27 17:59:49 2024 +0800
pci: fix pci dev alloc bridge mem error
Signed-off-by: lipengfei28 <[email protected]>
---
drivers/devicetree/fdt_pci.c | 25 ++++++---
drivers/pci/pci.c | 118 +++++++++++++++++++++++++++++++------------
drivers/pci/pci_ecam.c | 2 +-
include/nuttx/pci/pci.h | 6 +--
4 files changed, 108 insertions(+), 43 deletions(-)
diff --git a/drivers/devicetree/fdt_pci.c b/drivers/devicetree/fdt_pci.c
index 96ce714095..7bdd6d9c5b 100644
--- a/drivers/devicetree/fdt_pci.c
+++ b/drivers/devicetree/fdt_pci.c
@@ -118,26 +118,39 @@ int fdt_pci_ecam_register(FAR const void *fdt)
if ((type & FDT_PCI_TYPE_MASK) == FDT_PCI_TYPE_IO)
{
- io.start = fdt_ld_by_cells(ranges + 1, na -1);
+ io.start = fdt_ld_by_cells(ranges + 1, na - 1);
io.end = io.start + fdt_ld_by_cells(ranges + na + pna, ns);
io.offset = fdt_ld_by_cells(ranges + na, pna) - io.start;
+ io.flags = PCI_RESOURCE_IO;
}
- else if ((type & FDT_PCI_PREFTCH) == FDT_PCI_PREFTCH)
+ else if ((type & FDT_PCI_PREFTCH) == FDT_PCI_PREFTCH ||
+ (type & FDT_PCI_TYPE_MASK) == FDT_PCI_TYPE_MEM64)
{
prefetch.start = fdt_ld_by_cells(ranges + 1, na - 1);
prefetch.end = prefetch.start +
fdt_ld_by_cells(ranges + na + pna, ns);
prefetch.offset = fdt_ld_by_cells(ranges + na, pna) -
prefetch.start;
+ if ((type & FDT_PCI_PREFTCH) == FDT_PCI_PREFTCH)
+ {
+ prefetch.flags = PCI_RESOURCE_PREFETCH;
+ }
+
+ if ((type & FDT_PCI_TYPE_MASK) == FDT_PCI_TYPE_MEM64)
+ {
+ prefetch.flags |= PCI_RESOURCE_MEM_64;
+ }
+ else
+ {
+ prefetch.flags |= PCI_RESOURCE_MEM;
+ }
}
- else if (((type & FDT_PCI_TYPE_MEM32) == FDT_PCI_TYPE_MEM32 &&
- sizeof(uintptr_t) == 4) ||
- ((type & FDT_PCI_TYPE_MEM64) == FDT_PCI_TYPE_MEM64 &&
- sizeof(uintptr_t) == 8))
+ else
{
mem.start = fdt_ld_by_cells(ranges + 1, na - 1);
mem.end = mem.start + fdt_ld_by_cells(ranges + na + pna, ns);
mem.offset = fdt_ld_by_cells(ranges + na, pna) - mem.start;
+ mem.flags = PCI_RESOURCE_MEM;
}
}
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index 869a8d797a..e55f6c2546 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -645,9 +645,9 @@ static void pci_register_bus_devices(FAR struct pci_bus_s
*bus)
*
****************************************************************************/
-static uint32_t pci_size(uint32_t base, uint32_t maxbase, uint32_t mask)
+static uint64_t pci_size(uint64_t base, uint64_t maxbase, uint64_t mask)
{
- uint32_t size = maxbase & mask;
+ uint64_t size = maxbase & mask;
if (size == 0)
{
@@ -689,8 +689,11 @@ static void pci_setup_device(FAR struct pci_device_s *dev,
int max_bar,
int bar;
uint32_t orig;
uint32_t mask;
- uint32_t size;
+ uint64_t orig64;
+ uint64_t size64;
uintptr_t start;
+ uint64_t maxbase;
+ uint64_t mask64 = 0;
#ifdef CONFIG_PCI_ASSIGN_ALL_BUSES
uint8_t cmd;
@@ -723,54 +726,91 @@ static void pci_setup_device(FAR struct pci_device_s
*dev, int max_bar,
{
/* IO */
- size = pci_size(orig, mask, 0xfffffffe);
- flags = PCI_RESOURCE_IO;
- res = io;
+ mask64 = 0xfffffffe;
+ flags = PCI_RESOURCE_IO;
+ res = io;
}
else if ((mask & PCI_BASE_ADDRESS_MEM_PREFETCH) &&
pci_resource_size(&dev->bus->ctrl->mem_pref))
{
- /* Prefetchable MEM */
+ if ((mask & PCI_BASE_ADDRESS_MEM_TYPE_MASK) ==
+ PCI_BASE_ADDRESS_MEM_TYPE_64)
+ {
+ /* Prefetchable MEM */
+
+ mask64 = 0xfffffff0;
+ flags = PCI_RESOURCE_MEM_64 | PCI_RESOURCE_PREFETCH;
+ res = mem_pref;
+ }
+ else if (((mask & PCI_BASE_ADDRESS_MEM_TYPE_MASK) ==
+ PCI_BASE_ADDRESS_MEM_TYPE_32) &&
+ (dev->bus->ctrl->mem_pref.flags & PCI_RESOURCE_MEM))
+ {
+ /* Prefetchable MEM */
+
+ mask64 = 0xfffffff0;
+ flags = PCI_RESOURCE_MEM | PCI_RESOURCE_PREFETCH;
+ res = mem_pref;
+ }
+ else
+ {
+ /* Non-prefetch MEM */
- size = pci_size(orig, mask, 0xfffffff0);
- flags = PCI_RESOURCE_MEM | PCI_RESOURCE_PREFETCH;
- res = mem_pref;
+ mask64 = 0xfffffff0;
+ flags = PCI_RESOURCE_MEM;
+ res = mem;
+ }
}
else
{
/* Non-prefetch MEM */
- size = pci_size(orig, mask, 0xfffffff0);
- flags = PCI_RESOURCE_MEM;
- res = mem;
+ mask64 = 0xfffffff0;
+ flags = PCI_RESOURCE_MEM;
+ res = mem;
+ }
+
+ orig64 = orig;
+ maxbase = mask;
+ if (mask & PCI_BASE_ADDRESS_MEM_TYPE_64)
+ {
+ uint32_t masktmp;
+
+ pci_read_config_dword(dev, base_address_1, &orig);
+ pci_write_config_dword(dev, base_address_1, 0xffffffff);
+ pci_read_config_dword(dev, base_address_1, &masktmp);
+ pci_write_config_dword(dev, base_address_1, orig);
+ mask64 |= (uint64_t)masktmp << 32;
+ orig64 |= (uint64_t)orig << 32;
+ maxbase |= (uint64_t)masktmp << 32;
}
- if (size == 0)
+ size64 = pci_size(orig64, maxbase, mask64);
+ if (size64 == 0)
{
pcierr("pbar%d bad mask\n", bar);
continue;
}
- pciinfo("pbar%d: mask=%08" PRIx32 " %" PRIu32 "bytes\n",
- bar, mask, size);
+ pciinfo("pbar%d: mask64=%08" PRIx64 " %" PRIu64 "bytes\n",
+ bar, mask64, size64);
#ifdef CONFIG_PCI_ASSIGN_ALL_BUSES
- if (ALIGN(res->start, size) + size > res->end)
+ if (ALIGN(res->start, size64) + size64 > res->end)
{
pcierr("pbar%d: does not fit within bus res\n", bar);
return;
}
- res->start = ALIGN(res->start, size);
+ res->start = ALIGN(res->start, size64);
pci_write_config_dword(dev, base_address_0, res->start);
if (mask & PCI_BASE_ADDRESS_MEM_TYPE_64)
{
- pci_write_config_dword(dev, base_address_1,
- (uint64_t)res->start >> 32);
+ pci_write_config_dword(dev, base_address_1, res->start >> 32);
}
start = res->start;
- res->start += size;
+ res->start += size64;
#else
UNUSED(res);
pci_read_config_dword(dev, base_address_0, &tmp);
@@ -792,7 +832,7 @@ static void pci_setup_device(FAR struct pci_device_s *dev,
int max_bar,
dev->resource[bar].flags = flags;
dev->resource[bar].start = start;
- dev->resource[bar].end = start + size - 1;
+ dev->resource[bar].end = start + size64 - 1;
if (mask & PCI_BASE_ADDRESS_MEM_TYPE_64)
{
@@ -806,13 +846,13 @@ static void pci_setup_device(FAR struct pci_device_s
*dev, int max_bar,
pci_read_config_dword(dev, rom_addr, &mask);
pci_write_config_dword(dev, rom_addr, orig);
start = PCI_ROM_ADDR(orig);
- size = PCI_ROM_SIZE(mask);
- if (start != 0 && size != 0)
+ size64 = PCI_ROM_SIZE(mask);
+ if (start != 0 && size64 != 0)
{
dev->resource[PCI_ROM_RESOURCE].flags |=
PCI_RESOURCE_MEM | PCI_RESOURCE_PREFETCH;
dev->resource[PCI_ROM_RESOURCE].start = start;
- dev->resource[PCI_ROM_RESOURCE].end = start + size - 1;
+ dev->resource[PCI_ROM_RESOURCE].end = start + size64 - 1;
}
#ifdef CONFIG_PCI_ASSIGN_ALL_BUSES
@@ -867,13 +907,18 @@ static void pci_presetup_bridge(FAR struct pci_device_s
*dev)
if (pci_resource_size(&ctrl->mem_pref))
{
- /* Set up memory and I/O filter limits, assume 32-bit I/O space */
+ uint8_t base;
+ pci_read_config_byte(dev, PCI_PREF_MEMORY_BASE, &base);
ctrl->mem_pref.start = ALIGN(ctrl->mem_pref.start, 1024 * 1024);
pci_write_config_word(dev, PCI_PREF_MEMORY_BASE,
(ctrl->mem_pref.start & 0xfff00000) >> 16);
- pci_write_config_dword(dev, PCI_PREF_BASE_UPPER32,
- (uint64_t)ctrl->mem_pref.start >> 32);
+ if (base & PCI_PREF_RANGE_TYPE_64)
+ {
+ pci_write_config_dword(dev, PCI_PREF_BASE_UPPER32,
+ ctrl->mem_pref.start >> 32);
+ }
+
cmdstat |= PCI_COMMAND_MEMORY;
}
else
@@ -888,11 +933,18 @@ static void pci_presetup_bridge(FAR struct pci_device_s
*dev)
if (pci_resource_size(&ctrl->io))
{
+ uint8_t base;
+
+ pci_read_config_byte(dev, PCI_IO_BASE, &base);
ctrl->io.start = ALIGN(ctrl->io.start, 1024 * 4);
pci_write_config_byte(dev, PCI_IO_BASE,
(ctrl->io.start & 0x0000f000) >> 8);
- pci_write_config_word(dev, PCI_IO_BASE_UPPER16,
- (ctrl->io.start & 0xffff0000) >> 16);
+ if (base & PCI_IO_RANGE_TYPE_32)
+ {
+ pci_write_config_word(dev, PCI_IO_BASE_UPPER16,
+ (ctrl->io.start & 0xffff0000) >> 16);
+ }
+
cmdstat |= PCI_COMMAND_IO;
}
@@ -925,7 +977,7 @@ static void pci_postsetup_bridge(FAR struct pci_device_s
*dev)
if (pci_resource_size(&ctrl->mem))
{
ctrl->mem.start = ALIGN(ctrl->mem.start, 1024 * 1024);
- pciinfo("bridge NP limit at %" PRIxPTR "\n", ctrl->mem.start);
+ pciinfo("bridge NP limit at %" PRIx64 "\n", ctrl->mem.start);
pci_write_config_word(dev, PCI_MEMORY_LIMIT,
((ctrl->mem.start - 1) & 0xfff00000) >> 16);
}
@@ -933,7 +985,7 @@ static void pci_postsetup_bridge(FAR struct pci_device_s
*dev)
if (pci_resource_size(&ctrl->mem_pref))
{
ctrl->mem_pref.start = ALIGN(ctrl->mem_pref.start, 1024 * 1024);
- pciinfo("bridge P limit at %" PRIxPTR "\n", ctrl->mem_pref.start);
+ pciinfo("bridge P limit at %" PRIx64 "\n", ctrl->mem_pref.start);
pci_write_config_word(dev, PCI_PREF_MEMORY_LIMIT,
((ctrl->mem_pref.start - 1) & 0xfff00000) >> 16);
pci_write_config_dword(dev, PCI_PREF_LIMIT_UPPER32,
@@ -943,7 +995,7 @@ static void pci_postsetup_bridge(FAR struct pci_device_s
*dev)
if (pci_resource_size(&ctrl->io))
{
ctrl->io.start = ALIGN(ctrl->io.start, 1024 * 4);
- pciinfo("bridge IO limit at %" PRIxPTR "\n", ctrl->io.start);
+ pciinfo("bridge IO limit at %" PRIx64 "\n", ctrl->io.start);
pci_write_config_byte(dev, PCI_IO_LIMIT,
((ctrl->io.start - 1) & 0x0000f000) >> 8);
pci_write_config_word(dev, PCI_IO_LIMIT_UPPER16,
diff --git a/drivers/pci/pci_ecam.c b/drivers/pci/pci_ecam.c
index 011e2c0d02..3a31d065ab 100644
--- a/drivers/pci/pci_ecam.c
+++ b/drivers/pci/pci_ecam.c
@@ -152,7 +152,7 @@ static FAR void *pci_ecam_conf_address(FAR const struct
pci_bus_s *bus,
FAR struct pci_ecam_s *ecam = pci_ecam_from_controller(bus->ctrl);
FAR void *addr;
- addr = (FAR void *)ecam->cfg.start;
+ addr = (FAR void *)(uintptr_t)ecam->cfg.start;
addr += bus->number << 20;
addr += PCI_SLOT(devfn) << 15;
addr += PCI_FUNC(devfn) << 12;
diff --git a/include/nuttx/pci/pci.h b/include/nuttx/pci/pci.h
index 07929342f2..3cc0af14c6 100644
--- a/include/nuttx/pci/pci.h
+++ b/include/nuttx/pci/pci.h
@@ -236,9 +236,9 @@
struct pci_resource_s
{
- uintptr_t start;
- uintptr_t end;
- uintptr_t offset;
+ uint64_t start;
+ uint64_t end;
+ uint64_t offset;
unsigned int flags;
};