Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 8 Jun 2021 15:52:45 GMT
From:      Marcin Wojtas <mw@FreeBSD.org>
To:        src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org
Subject:   git: ea52e815887b - main - pci_host_generic_fdt.c: Add support for mapping dts nodes to PCI devices
Message-ID:  <202106081552.158Fqj2L005319@gitrepo.freebsd.org>

next in thread | raw e-mail | index | archive | help
The branch main has been updated by mw:

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

commit ea52e815887b48f7eb10219777dc89ee0d99e8b6
Author:     Marcin Wojtas <mw@FreeBSD.org>
AuthorDate: 2021-05-27 08:07:19 +0000
Commit:     Marcin Wojtas <mw@FreeBSD.org>
CommitDate: 2021-06-08 15:51:40 +0000

    pci_host_generic_fdt.c: Add support for mapping dts nodes to PCI devices
    
    Some arm64 SoCs have nodes in their fdts that describe devices
    connected to the internal PCI bus. One such SoC is Freescale LS1028A.
    It expects the nodes to be mapped to devices enumerated using the standard
    PCI method. Mapping is done by reading device and function ids from "reg"
    property. Information is dts is used to describe MDIO/PHY connected
    to a given interface.
    
    Submitted by: Kornel Duleba <mindal@semihalf.com>
    Reviewed by: andrew
    Obtained from: Semihalf
    Sponsored by: Alstom Group
    Differential Revision: https://reviews.freebsd.org/D30180
---
 sys/dev/pci/pci_host_generic_fdt.c | 78 ++++++++++++++++++++++++++++++++++++++
 sys/dev/pci/pci_host_generic_fdt.h |  4 ++
 2 files changed, 82 insertions(+)

diff --git a/sys/dev/pci/pci_host_generic_fdt.c b/sys/dev/pci/pci_host_generic_fdt.c
index 26047135164c..cb77c0c674a9 100644
--- a/sys/dev/pci/pci_host_generic_fdt.c
+++ b/sys/dev/pci/pci_host_generic_fdt.c
@@ -71,10 +71,21 @@ __FBSDID("$FreeBSD$");
 #define	PROPS_CELL_SIZE		1
 #define	PCI_ADDR_CELL_SIZE	2
 
+struct pci_ofw_devinfo {
+	STAILQ_ENTRY(pci_ofw_devinfo) pci_ofw_link;
+	struct ofw_bus_devinfo  di_dinfo;
+	uint8_t slot;
+	uint8_t func;
+	uint8_t bus;
+};
+
 /* Forward prototypes */
 
 static int generic_pcie_fdt_probe(device_t dev);
 static int parse_pci_mem_ranges(device_t, struct generic_pcie_core_softc *);
+static int generic_pcie_ofw_bus_attach(device_t);
+static const struct ofw_bus_devinfo *generic_pcie_ofw_get_devinfo(device_t,
+    device_t);
 
 static int
 generic_pcie_fdt_probe(device_t dev)
@@ -104,12 +115,18 @@ pci_host_generic_setup_fdt(device_t dev)
 
 	sc = device_get_softc(dev);
 
+	STAILQ_INIT(&sc->pci_ofw_devlist);
+
 	/* Retrieve 'ranges' property from FDT */
 	if (bootverbose)
 		device_printf(dev, "parsing FDT for ECAM%d:\n", sc->base.ecam);
 	if (parse_pci_mem_ranges(dev, &sc->base))
 		return (ENXIO);
 
+	/* Attach OFW bus */
+	if (generic_pcie_ofw_bus_attach(dev) != 0)
+		return (ENXIO);
+
 	node = ofw_bus_get_node(dev);
 	if (sc->base.coherent == 0) {
 		sc->base.coherent = OF_hasprop(node, "dma-coherent");
@@ -367,8 +384,62 @@ generic_pcie_get_id(device_t pci, device_t child, enum pci_id_type type,
 	return (0);
 }
 
+static const struct ofw_bus_devinfo *
+generic_pcie_ofw_get_devinfo(device_t bus, device_t child)
+{
+	struct generic_pcie_fdt_softc *sc;
+	struct pci_ofw_devinfo *di;
+	uint8_t slot, func, busno;
+
+	sc = device_get_softc(bus);
+	slot = pci_get_slot(child);
+	func = pci_get_function(child);
+	busno = pci_get_bus(child);
+
+	STAILQ_FOREACH(di, &sc->pci_ofw_devlist, pci_ofw_link)
+		if (slot == di->slot && func == di->func && busno == di->bus)
+			return (&di->di_dinfo);
+
+	return (NULL);
+}
+
 /* Helper functions */
 
+static int
+generic_pcie_ofw_bus_attach(device_t dev)
+{
+	struct generic_pcie_fdt_softc *sc;
+	struct pci_ofw_devinfo *di;
+	phandle_t parent, node;
+	pcell_t reg[5];
+	ssize_t len;
+
+	sc = device_get_softc(dev);
+	parent = ofw_bus_get_node(dev);
+	if (parent == 0)
+		return (0);
+
+	/* Iterate through all bus subordinates */
+	for (node = OF_child(parent); node > 0; node = OF_peer(node)) {
+		len = OF_getencprop(node, "reg", reg, sizeof(reg));
+		if (len != 5 * sizeof(pcell_t))
+			continue;
+
+		/* Allocate and populate devinfo. */
+		di = malloc(sizeof(*di), M_DEVBUF, M_WAITOK | M_ZERO);
+		if (ofw_bus_gen_setup_devinfo(&di->di_dinfo, node) != 0) {
+			free(di, M_DEVBUF);
+			continue;
+		}
+		di->func = OFW_PCI_PHYS_HI_FUNCTION(reg[0]);
+		di->slot = OFW_PCI_PHYS_HI_DEVICE(reg[0]);
+		di->bus = OFW_PCI_PHYS_HI_BUS(reg[0]);
+		STAILQ_INSERT_TAIL(&sc->pci_ofw_devlist, di, pci_ofw_link);
+	}
+
+	return (0);
+}
+
 static device_method_t generic_pcie_fdt_methods[] = {
 	DEVMETHOD(device_probe,		generic_pcie_fdt_probe),
 	DEVMETHOD(device_attach,	pci_host_generic_attach),
@@ -385,6 +456,13 @@ static device_method_t generic_pcie_fdt_methods[] = {
 	DEVMETHOD(pcib_get_id,		generic_pcie_get_id),
 	DEVMETHOD(pcib_request_feature,	pcib_request_feature_allow),
 
+	DEVMETHOD(ofw_bus_get_devinfo,	generic_pcie_ofw_get_devinfo),
+	DEVMETHOD(ofw_bus_get_compat,	ofw_bus_gen_get_compat),
+	DEVMETHOD(ofw_bus_get_model,	ofw_bus_gen_get_model),
+	DEVMETHOD(ofw_bus_get_name,	ofw_bus_gen_get_name),
+	DEVMETHOD(ofw_bus_get_node,	ofw_bus_gen_get_node),
+	DEVMETHOD(ofw_bus_get_type,	ofw_bus_gen_get_type),
+
 	DEVMETHOD_END
 };
 
diff --git a/sys/dev/pci/pci_host_generic_fdt.h b/sys/dev/pci/pci_host_generic_fdt.h
index 5c3e18e9ad35..a5d75eddc84d 100644
--- a/sys/dev/pci/pci_host_generic_fdt.h
+++ b/sys/dev/pci/pci_host_generic_fdt.h
@@ -34,9 +34,13 @@
 #ifndef __PCI_HOST_GENERIC_FDT_H_
 #define	__PCI_HOST_GENERIC_FDT_H_
 
+struct pci_ofw_devinfo;
+
 struct generic_pcie_fdt_softc {
 	struct generic_pcie_core_softc base;
 	struct ofw_bus_iinfo	pci_iinfo;
+
+	STAILQ_HEAD(, pci_ofw_devinfo) pci_ofw_devlist;
 };
 
 DECLARE_CLASS(generic_pcie_fdt_driver);



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202106081552.158Fqj2L005319>