git: 92c66dc5f872 - main - pci_dw: improve pci_dw

From: Michal Meloun <mmel_at_FreeBSD.org>
Date: Sun, 22 Feb 2026 17:53:54 UTC
The branch main has been updated by mmel:

URL: https://cgit.FreeBSD.org/src/commit/?id=92c66dc5f8723083530efbbc5cfa4068105f472c

commit 92c66dc5f8723083530efbbc5cfa4068105f472c
Author:     Michal Meloun <mmel@FreeBSD.org>
AuthorDate: 2024-10-07 16:50:10 +0000
Commit:     Michal Meloun <mmel@FreeBSD.org>
CommitDate: 2026-02-22 17:53:27 +0000

    pci_dw: improve pci_dw
    
    Add support for 64-bit ranges.
    Process 'bus-range' property.
    Add some debug prints.
    
    MFC after:      3 weeks
---
 sys/dev/pci/pci_dw.c | 78 ++++++++++++++++++++++++++++++++++++++++------------
 sys/dev/pci/pci_dw.h |  3 ++
 2 files changed, 63 insertions(+), 18 deletions(-)

diff --git a/sys/dev/pci/pci_dw.c b/sys/dev/pci/pci_dw.c
index dcc9c0c5e369..7c9448a5593e 100644
--- a/sys/dev/pci/pci_dw.c
+++ b/sys/dev/pci/pci_dw.c
@@ -55,10 +55,10 @@
 #include "pcib_if.h"
 #include "pci_dw_if.h"
 
-#ifdef DEBUG
-#define	debugf(fmt, args...) do { printf(fmt,##args); } while (0)
+#if 0
+#define	dprintf(fmt, args...) do { printf(fmt,##args); } while (0)
 #else
-#define	debugf(fmt, args...)
+#define	dprintf(fmt, args...)
 #endif
 
 #define	DBI_WR1(sc, reg, val)	pci_dw_dbi_wr1((sc)->dev, reg, val)
@@ -92,7 +92,7 @@ pci_dw_dbi_read(device_t dev, u_int reg, int width)
 
 	sc = device_get_softc(dev);
 	MPASS(sc->dbi_res != NULL);
-
+	dprintf("%s: reg: 0x%04X, width: %d\n", __func__, reg, width);
 	switch (width) {
 	case 4:
 		return (bus_read_4(sc->dbi_res, reg));
@@ -113,6 +113,8 @@ pci_dw_dbi_write(device_t dev, u_int reg, uint32_t val, int width)
 
 	sc = device_get_softc(dev);
 	MPASS(sc->dbi_res != NULL);
+	dprintf("%s: reg: 0x%04X, val: 0x%08X, width: %d\n", __func__,
+	    reg, val, width);
 
 	switch (width) {
 	case 4:
@@ -162,7 +164,7 @@ pci_dw_check_dev(struct pci_dw_softc *sc, u_int bus, u_int slot, u_int func,
 		return (true);
 	}
 
-	/* we have only 1 device with 1 function root port */
+	/* we have only 1 device with 1 function on root port */
 	if (slot > 0 || func > 0)
 		return (false);
 	return (true);
@@ -434,9 +436,14 @@ pci_dw_decode_ranges(struct pci_dw_softc *sc, struct ofw_pci_range *ranges,
 
 	nmem = 0;
 	for (i = 0; i < nranges; i++) {
-		if ((ranges[i].pci_hi & OFW_PCI_PHYS_HI_SPACEMASK) ==
-		    OFW_PCI_PHYS_HI_SPACE_MEM32)
+		switch (ranges[i].pci_hi & OFW_PCI_PHYS_HI_SPACEMASK) {
+		case OFW_PCI_PHYS_HI_SPACE_MEM32:
+		case OFW_PCI_PHYS_HI_SPACE_MEM64:
 			++nmem;
+			break;
+		default:
+			break;
+		}
 	}
 
 	sc->mem_ranges = malloc(nmem * sizeof(*sc->mem_ranges), M_DEVBUF,
@@ -445,8 +452,9 @@ pci_dw_decode_ranges(struct pci_dw_softc *sc, struct ofw_pci_range *ranges,
 
 	nmem = 0;
 	for (i = 0; i < nranges; i++) {
-		if ((ranges[i].pci_hi & OFW_PCI_PHYS_HI_SPACEMASK)  ==
-		    OFW_PCI_PHYS_HI_SPACE_IO) {
+		switch (ranges[i].pci_hi & OFW_PCI_PHYS_HI_SPACEMASK) {
+
+		case OFW_PCI_PHYS_HI_SPACE_IO:
 			if (sc->io_range.size != 0) {
 				device_printf(sc->dev,
 				    "Duplicated IO range found in DT\n");
@@ -462,9 +470,10 @@ pci_dw_decode_ranges(struct pci_dw_softc *sc, struct ofw_pci_range *ranges,
 				    "trimming window size to 4GB\n");
 				sc->io_range.size = UINT32_MAX;
 			}
-		}
-		if ((ranges[i].pci_hi & OFW_PCI_PHYS_HI_SPACEMASK) ==
-		    OFW_PCI_PHYS_HI_SPACE_MEM32) {
+			break;
+
+		case OFW_PCI_PHYS_HI_SPACE_MEM32:
+		case OFW_PCI_PHYS_HI_SPACE_MEM64:
 			MPASS(nmem < sc->num_mem_ranges);
 			sc->mem_ranges[nmem] = ranges[i];
 			if (sc->mem_ranges[nmem].size > UINT32_MAX) {
@@ -475,6 +484,13 @@ pci_dw_decode_ranges(struct pci_dw_softc *sc, struct ofw_pci_range *ranges,
 				sc->mem_ranges[nmem].size = UINT32_MAX;
 			}
 			++nmem;
+			break;
+
+		default:
+			device_printf(sc->dev,
+				    "%s: Unsupported range type (0x%X)\n",
+				    __func__, ranges[i].pci_hi &
+				    OFW_PCI_PHYS_HI_SPACEMASK);
 		}
 	}
 
@@ -703,6 +719,7 @@ pci_dw_init(device_t dev)
 	struct pci_dw_softc *sc;
 	int rv, rid;
 	bool unroll_mode;
+	u_int32_t br[2];
 
 	sc = device_get_softc(dev);
 	sc->dev = dev;
@@ -710,11 +727,30 @@ pci_dw_init(device_t dev)
 
 	mtx_init(&sc->mtx, "pci_dw_mtx", NULL, MTX_DEF);
 
-	/* XXXn Should not be this configurable ? */
-	sc->bus_start = 0;
-	sc->bus_end = 255;
-	sc->root_bus = 0;
-	sc->sub_bus = 1;
+	if (OF_hasprop(sc->node, "bus-range")) {
+		rv = OF_getencprop(sc->node, "bus-range", br, sizeof(br));
+		if (rv < 0) {
+			device_printf(dev,
+			    "Cannot read 'bus-range' property: %d\n", rv);
+			rv = ENXIO;
+			goto out;
+		}
+		if (rv != 8) {
+			device_printf(dev,
+			    "Malformed 'bus-range' property: %d\n", rv);
+			rv = ENXIO;
+			goto out;
+		}
+		sc->bus_start = br[0];
+		sc->bus_end = br[1];
+	} else {
+		sc->bus_start = 0;
+		sc->bus_end = 255;
+	}
+	sc->root_bus = sc->bus_start;
+	sc->sub_bus = sc->bus_start + 1;
+	dprintf("%s: bus range[%d..%d], root bus %d, sub bus: %d\n", __func__,
+	    sc->bus_end, sc->bus_start, sc->root_bus, sc->sub_bus);
 
 	/* Read FDT properties */
 	if (!sc->coherent)
@@ -724,6 +760,8 @@ pci_dw_init(device_t dev)
 	    sizeof(sc->num_lanes));
 	if (rv != sizeof(sc->num_lanes))
 		sc->num_lanes = 1;
+	dprintf("%s: num lanes: %d\n", __func__, sc->num_lanes);
+
 	if (sc->num_lanes != 1 && sc->num_lanes != 2 &&
 	    sc->num_lanes != 4 && sc->num_lanes != 8) {
 		device_printf(dev,
@@ -769,7 +807,6 @@ pci_dw_init(device_t dev)
 	    &sc->dmat);
 	if (rv != 0)
 		goto out;
-
 	rv = ofw_pcib_init(dev);
 	if (rv != 0)
 		goto out;
@@ -778,6 +815,9 @@ pci_dw_init(device_t dev)
 	if (rv != 0)
 		goto out;
 
+	dprintf("%s: version: 0x%08X, version type:0x%08X\n", __func__,
+	    DBI_RD4(sc, DW_MISC_VERSION), DBI_RD4(sc, DW_MISC_VERSION_TYPE));
+
 	unroll_mode = pci_dw_detect_atu_unroll(sc);
 	if (bootverbose)
 		device_printf(dev, "Using iATU %s mode\n",
@@ -786,6 +826,7 @@ pci_dw_init(device_t dev)
 		rid = 0;
 		rv = ofw_bus_find_string_index(sc->node, "reg-names", "atu", &rid);
 		if (rv == 0) {
+			dprintf("%s: Have 'atu' regs\n", __func__);
 			sc->iatu_ur_res = bus_alloc_resource_any(dev,
 			    SYS_RES_MEMORY, &rid, RF_ACTIVE);
 			if (sc->iatu_ur_res == NULL) {
@@ -798,6 +839,7 @@ pci_dw_init(device_t dev)
 			sc->iatu_ur_offset = 0;
 			sc->iatu_ur_size = rman_get_size(sc->iatu_ur_res);
 		} else if (rv == ENOENT) {
+			dprintf("%s: Using 'dbi' regs for atu\n", __func__);
 			sc->iatu_ur_res = sc->dbi_res;
 			sc->iatu_ur_offset = DW_DEFAULT_IATU_UR_DBI_OFFSET;
 			sc->iatu_ur_size = DW_DEFAULT_IATU_UR_DBI_SIZE;
diff --git a/sys/dev/pci/pci_dw.h b/sys/dev/pci/pci_dw.h
index 388eae86e40f..5b6f62ad6c84 100644
--- a/sys/dev/pci/pci_dw.h
+++ b/sys/dev/pci/pci_dw.h
@@ -61,6 +61,9 @@
 #define	DW_MISC_CONTROL_1		0x8BC
 #define	 DBI_RO_WR_EN				(1 << 0)
 
+#define DW_MISC_VERSION			0x8F8
+#define DW_MISC_VERSION_TYPE		0x8FC
+
 /* Legacy (pre-4.80) iATU mode */
 #define	DW_IATU_VIEWPORT			0x900
 #define	 IATU_REGION_INBOUND			(1U << 31)