Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DPAA2: FDT MDIO support #16

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion sys/conf/files.arm64
Original file line number Diff line number Diff line change
Expand Up @@ -337,8 +337,8 @@ dev/dpaa2/dpaa2_mac.c optional SOC_NXP_LS dpaa2
dev/dpaa2/dpaa2_con.c optional SOC_NXP_LS dpaa2
dev/dpaa2/dpaa2_mc_acpi.c optional SOC_NXP_LS dpaa2 acpi
dev/dpaa2/dpaa2_mc_fdt.c optional SOC_NXP_LS dpaa2 fdt
dev/dpaa2/memac_mdio.c optional SOC_NXP_LS dpaa2 acpi | SOC_NXP_LS dpaa2 fdt
dev/dpaa2/memac_mdio_if.m optional SOC_NXP_LS dpaa2 acpi | SOC_NXP_LS dpaa2 fdt
dev/dpaa2/memac_mdio_acpi.c optional SOC_NXP_LS dpaa2 acpi

##
## SoC Support
Expand Down
1 change: 0 additions & 1 deletion sys/dev/dpaa2/dpaa2_mc_acpi.c
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,6 @@ DEFINE_CLASS_0(dpaa2_mac_dev, dpaa2_mac_dev_driver, dpaa2_mac_dev_methods,
DRIVER_MODULE(dpaa2_mac_dev, dpaa2_mc, dpaa2_mac_dev_driver, 0, 0);

MODULE_DEPEND(dpaa2_mac_dev, memac_mdio, 1, 1, 1);
MODULE_DEPEND(dpaa2_mac_dev, miibus, 1, 1, 1);

/*
* Device interface.
Expand Down
273 changes: 273 additions & 0 deletions sys/dev/dpaa2/dpaa2_mc_fdt.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD
*
* Copyright (c) 2021 Dmitry Salychev <dsl@mcusim.org>
* Copyright (c) 2022 Bjoern A. Zeeb
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
Expand Down Expand Up @@ -49,14 +50,164 @@ __FBSDID("$FreeBSD$");

#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
#include <dev/fdt/simplebus.h>

#include "pcib_if.h"
#include "pci_if.h"
#include "ofw_bus_if.h"

#include "dpaa2_mcp.h"
#include "dpaa2_mc.h"
#include "dpaa2_mc_if.h"

struct dpaa2_mac_fdt_softc {
uint32_t reg;
phandle_t sfp;
phandle_t pcs_handle;
phandle_t phy_handle;
char managed[64];
char phy_conn_type[64];
};

#if 0
ethernet@1 {

compatible = "fsl,qoriq-mc-dpmac";
reg = <0x1>;
sfp = <0x14>;
pcs-handle = <0x15>;
phy-connection-type = "10gbase-r";
managed = "in-band-status";
};
ethernet@3 {

compatible = "fsl,qoriq-mc-dpmac";
reg = <0x3>;
phy-handle = <0x18>;
phy-connection-type = "qsgmii";
managed = "in-band-status";
pcs-handle = <0x19>;
};
#endif

static int
dpaa2_mac_dev_probe(device_t dev)
{
phandle_t node;
uint64_t reg;
ssize_t s;

node = ofw_bus_get_node(dev);
if (!ofw_bus_node_is_compatible(node, "fsl,qoriq-mc-dpmac")) {
device_printf(dev, "'%s' not fsl,qoriq-mc-dpmac compatible\n", ofw_bus_get_name(dev));
return (ENXIO);
}

s = device_get_property(dev, "reg", &reg, sizeof(reg),
DEVICE_PROP_UINT32);
if (s == -1) {
device_printf(dev, "%s: '%s' has no 'reg' property, s %zd\n",
__func__, ofw_bus_get_name(dev), s);
return (ENXIO);
}

device_set_desc(dev, "DPAA2 MAC DEV");
return (BUS_PROBE_DEFAULT);
}

static int
dpaa2_mac_fdt_attach(device_t dev)
{
struct dpaa2_mac_fdt_softc *sc;
phandle_t node;
ssize_t s;

sc = device_get_softc(dev);
node = ofw_bus_get_node(dev);

s = device_get_property(dev, "reg", &sc->reg, sizeof(sc->reg),
DEVICE_PROP_UINT32);
if (s == -1) {
device_printf(dev, "Cannot find 'reg' property: %zd\n", s);
return (ENXIO);
}

s = device_get_property(dev, "managed", sc->managed,
sizeof(sc->managed), DEVICE_PROP_ANY);
s = device_get_property(dev, "phy-connection-type", sc->phy_conn_type,
sizeof(sc->phy_conn_type), DEVICE_PROP_ANY);
s = device_get_property(dev, "pcs-handle", &sc->pcs_handle, sizeof(sc->pcs_handle),
DEVICE_PROP_UINT32);

/* 'sfp' and 'phy-handle' are optional but we need one or the other. */
s = device_get_property(dev, "sfp", &sc->sfp, sizeof(sc->sfp),
DEVICE_PROP_UINT32);
s = device_get_property(dev, "phy-handle", &sc->phy_handle, sizeof(sc->phy_handle),
DEVICE_PROP_UINT32);

if (bootverbose)
device_printf(dev, "node %#x '%s': reg %#x sfp %#x pcs-handle "
"%#x phy-handle %#x managed '%s' phy-conn-type '%s'\n",
node, ofw_bus_get_name(dev),
sc->reg, sc->sfp, sc->pcs_handle, sc->phy_handle,
sc->managed, sc->phy_conn_type);

return (0);
}

static bool
dpaa2_mac_fdt_match_id(device_t dev, uint32_t id)
{
struct dpaa2_mac_fdt_softc *sc;

if (dev == NULL)
return (false);

sc = device_get_softc(dev);
if (sc->reg == id)
return (true);

return (false);
}

static device_t
dpaa2_mac_fdt_get_phy_dev(device_t dev)
{
struct dpaa2_mac_fdt_softc *sc;

if (dev == NULL)
return (NULL);

sc = device_get_softc(dev);
if (sc->phy_handle == 0 && sc->sfp == 0)
return (NULL);

#ifdef __not_yet__ /* No sff,sfp support yet. */
if (sc->sfp != 0) {
device_t xdev;

xdev = OF_device_from_xref(sc->sfp);
if (xdev != NULL)
return (xdev);
}
#endif
return (OF_device_from_xref(sc->phy_handle));
}

static device_method_t dpaa2_mac_fdt_methods[] = {
/* Device interface */
DEVMETHOD(device_probe, dpaa2_mac_dev_probe),
DEVMETHOD(device_attach, dpaa2_mac_fdt_attach),
DEVMETHOD(device_detach, bus_generic_detach),

DEVMETHOD_END
};

DEFINE_CLASS_0(dpaa2_mac_fdt, dpaa2_mac_fdt_driver, dpaa2_mac_fdt_methods,
sizeof(struct dpaa2_mac_fdt_softc));
DRIVER_MODULE(dpaa2_mac_fdt, dpaa2_mc, dpaa2_mac_fdt_driver, 0, 0);
MODULE_DEPEND(dpaa2_mac_fdt, memac_mdio, 1, 1, 1);

/*
* Device interface.
*/
Expand All @@ -74,18 +225,131 @@ dpaa2_mc_fdt_probe(device_t dev)
return (BUS_PROBE_DEFAULT);
}

static int
dpaa2_mc_fdt_probe_child(device_t bus, phandle_t child)
{
device_t childdev;

/* make sure we do not aliready have a device. */
childdev = ofw_bus_find_child_device_by_phandle(bus, child);
if (childdev != NULL)
return (0);

childdev = simplebus_add_device(bus, child, 0, "dpaa2_mac_fdt", -1, NULL);
if (childdev == NULL)
return (ENXIO);

return (device_probe_and_attach(childdev));
}

static int
dpaa2_mc_fdt_attach(device_t dev)
{
struct dpaa2_mc_softc *sc;
phandle_t node;
phandle_t child;

sc = device_get_softc(dev);
sc->acpi_based = false;
sc->ofw_node = ofw_bus_get_node(dev);

bus_generic_probe(dev);
bus_enumerate_hinted_children(dev);

bus_generic_probe(dev);
bus_enumerate_hinted_children(dev);
/*
* Attach the children represented in the device tree.
*/
/* fsl-mc -> dpamcs */
node = OF_child(sc->ofw_node);
simplebus_init(dev, node);

/* Attach the dpmac children represented in the device tree. */
child = ofw_bus_find_compatible(node, "fsl,qoriq-mc-dpmac");
for (; child > 0; child = OF_peer(child)) {
if (!ofw_bus_node_is_compatible(child, "fsl,qoriq-mc-dpmac"))
continue;
if (!OF_hasprop(child, "reg"))
continue;
if (!OF_hasprop(child, "pcs-handle"))
continue;
if (dpaa2_mc_fdt_probe_child(dev, child) != 0)
continue;
}

return (dpaa2_mc_attach(dev));
}

/*
* FDT compat layer.
*/
static device_t
dpaa2_mc_acpi_find_dpaa2_mac_dev(device_t dev, uint32_t id)
{
int devcount, error, i, len;
device_t *devlist, mdev;
const char *mdevname;

error = device_get_children(dev, &devlist, &devcount);
if (error != 0)
return (NULL);

for (i = 0; i < devcount; i++) {
mdev = devlist[i];
mdevname = device_get_name(mdev);
if (mdevname == NULL)
continue;
len = strlen(mdevname);
if (strncmp("dpaa2_mac_fdt", mdevname, len) != 0)
continue;
if (!device_is_attached(mdev))
continue;

if (dpaa2_mac_fdt_match_id(mdev, id))
return (mdev);
}

return (NULL);
}

static int
dpaa2_mc_fdt_get_phy_dev(device_t dev, device_t *phy_dev, uint32_t id)
{
device_t mdev, pdev;

mdev = dpaa2_mc_acpi_find_dpaa2_mac_dev(dev, id);
if (mdev == NULL) {
device_printf(dev, "%s: error finding dpmac device with id=%u\n",
__func__, id);
return (ENXIO);
}

pdev = dpaa2_mac_fdt_get_phy_dev(mdev);
if (pdev == NULL) {
device_printf(dev, "%s: error getting MDIO device for dpamc %s "
"(id=%u)\n", __func__, device_get_nameunit(mdev), id);
return (ENXIO);
}

if (phy_dev != NULL)
*phy_dev = pdev;

if (bootverbose)
device_printf(dev, "dpmac_id %u mdev %p (%s) pdev %p (%s)\n",
id, mdev, device_get_nameunit(mdev),
pdev, device_get_nameunit(pdev));

return (0);
}

static const struct ofw_bus_devinfo *
dpaa2_mc_simplebus_get_devinfo(device_t bus, device_t child)
{

return (OFW_BUS_GET_DEVINFO(device_get_parent(bus), child));
}

static device_method_t dpaa2_mc_fdt_methods[] = {
/* Device interface */
DEVMETHOD(device_probe, dpaa2_mc_fdt_probe),
Expand Down Expand Up @@ -114,6 +378,15 @@ static device_method_t dpaa2_mc_fdt_methods[] = {
DEVMETHOD(dpaa2_mc_get_shared_dev, dpaa2_mc_get_shared_dev),
DEVMETHOD(dpaa2_mc_reserve_dev, dpaa2_mc_reserve_dev),
DEVMETHOD(dpaa2_mc_release_dev, dpaa2_mc_release_dev),
DEVMETHOD(dpaa2_mc_get_phy_dev, dpaa2_mc_fdt_get_phy_dev),

/* OFW/simplebus */
DEVMETHOD(ofw_bus_get_devinfo, dpaa2_mc_simplebus_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
};
Expand Down
20 changes: 17 additions & 3 deletions sys/dev/dpaa2/dpaa2_ni.c
Original file line number Diff line number Diff line change
Expand Up @@ -832,7 +832,8 @@ dpaa2_ni_setup(device_t dev)
error = DPAA2_CMD_MAC_OPEN(sc->dev, child,
dpaa2_mcp_tk(sc->cmd, sc->rc_token),
sc->mac.dpmac_id, &mac_token);
/* Under VFIO, the DPMAC might be sitting in another
/*
* Under VFIO, the DPMAC might be sitting in another
* container (DPRC) we don't have access to.
* Assume DPAA2_MAC_LINK_TYPE_FIXED if this is
* the case.
Expand All @@ -841,7 +842,7 @@ dpaa2_ni_setup(device_t dev)
device_printf(dev, "%s: failed to open "
"connected DPMAC: %d (assuming in other DPRC)\n", __func__,
sc->mac.dpmac_id);
link_type = DPAA2_MAC_LINK_TYPE_FIXED;
link_type = DPAA2_MAC_LINK_TYPE_FIXED;
} else {
error = DPAA2_CMD_MAC_GET_ATTRIBUTES(dev, child,
sc->cmd, &attr);
Expand Down Expand Up @@ -876,12 +877,25 @@ dpaa2_ni_setup(device_t dev)
device_get_nameunit(
sc->mac.phy_dev), error);
}
if (error == 0) {
error = MEMAC_MDIO_GET_PHY_LOC(
sc->mac.phy_dev, &sc->mac.phy_loc);
if (error == ENODEV)
error = 0;
if (error != 0)
device_printf(dev, "%s: failed "
"to get phy location from "
"memac mdio dev %s: error=%d\n",
__func__, device_get_nameunit(
sc->mac.phy_dev), error);
}
if (error == 0) {
error = mii_attach(sc->mac.phy_dev,
&sc->miibus, sc->ifp,
dpaa2_ni_media_change,
dpaa2_ni_media_status,
BMSR_DEFCAPMASK, MII_PHY_ANY, 0, 0);
BMSR_DEFCAPMASK, sc->mac.phy_loc,
MII_OFFSET_ANY, 0);
if (error != 0)
device_printf(dev, "%s: failed "
"to attach to miibus: "
Expand Down
1 change: 1 addition & 0 deletions sys/dev/dpaa2/dpaa2_ni.h
Original file line number Diff line number Diff line change
Expand Up @@ -628,6 +628,7 @@ struct dpaa2_ni_softc {
uint32_t dpmac_id;
uint8_t addr[ETHER_ADDR_LEN];
device_t phy_dev;
int phy_loc;
} mac; /* Info about connected DPMAC (if exists). */
};

Expand Down
Loading