Skip to content

Commit

Permalink
DPAA2: FDT MDIO support
Browse files Browse the repository at this point in the history
Rename memac_mdio_acpi.c to memac_mdio.c and add FDT support.  Extend
dpaa2_mc_fdt.c for the equivalent of the ACPI version to add supoprt
for getting the xref to mdio from dpamc.
Add a new mdio interface to get the phy location as with the multi-phy
MDIO bits we need to pass the phyloc information in to mii_attach.

This all needs a bit more unificationa and cleanup but works for the
copper ports so far.  We do not yet have any (generic) 'sff,sfp'
support in FreeBSD so that needs to come before enabling the sfp
bits.  Until then keeping sfpmode legacy in u-boot is probably best.

Hardware provided by:	Traverse Technologies (Ten64)
  • Loading branch information
Bjoern A. Zeeb authored and dsalychev committed Jul 7, 2022
1 parent 29ddc38 commit 6a7b9a7
Show file tree
Hide file tree
Showing 8 changed files with 708 additions and 161 deletions.
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

0 comments on commit 6a7b9a7

Please sign in to comment.