felix: Use internal MDIO regs for PHY communication

Previously we would use an external MDIO device found on the PCI bus.
Switch to using MDIO mapped in a separate BAR of the switch device.
It is much easier this way since we don't have to depend on another
driver anymore.

Obtained from: Semihalf
Sponsored by: Alstom Group
This commit is contained in:
Kornel Duleba 2021-10-26 10:36:35 +02:00 committed by Wojciech Macek
parent 06e6ca6dd3
commit 29cf6a79ac
4 changed files with 35 additions and 42 deletions

View File

@ -44,6 +44,8 @@ __FBSDID("$FreeBSD$");
#include <net/if_media.h>
#include <net/if_types.h>
#include <dev/enetc/enetc_mdio.h>
#include <dev/etherswitch/etherswitch.h>
#include <dev/mii/mii.h>
#include <dev/mii/miivar.h>
@ -124,6 +126,10 @@ static device_method_t felix_methods[] = {
DEVMETHOD(etherswitch_setvgroup, felix_setvgroup),
DEVMETHOD(etherswitch_getvgroup, felix_getvgroup),
/* miibus interface */
DEVMETHOD(miibus_readreg, felix_readphy),
DEVMETHOD(miibus_writereg, felix_writephy),
DEVMETHOD_END
};
@ -131,15 +137,16 @@ static devclass_t felix_devclass;
DEFINE_CLASS_0(felix, felix_driver, felix_methods,
sizeof(struct felix_softc));
DRIVER_MODULE(felix, pci, felix_driver, felix_devclass, NULL, NULL);
DRIVER_MODULE_ORDERED(felix, pci, felix_driver, felix_devclass,
NULL, NULL, SI_ORDER_ANY);
DRIVER_MODULE(miibus, felix, miibus_driver, miibus_devclass,
NULL, NULL);
DRIVER_MODULE(etherswitch, felix, etherswitch_driver, etherswitch_devclass,
NULL, NULL);
MODULE_VERSION(felix, 1);
MODULE_PNP_INFO("U16:vendor;U16:device;D:#", pci, felix,
felix_pci_ids, nitems(felix_pci_ids) - 1);
MODULE_DEPEND(felix, enetc_mdio, 1, 1, 1);
static int
felix_probe(device_t dev)
{
@ -324,7 +331,6 @@ felix_attach(device_t dev)
phandle_t child, ports, node;
int error, port, rid;
felix_softc_t sc;
device_t mdio_dev;
uint32_t phy_addr;
ssize_t size;
@ -333,12 +339,21 @@ felix_attach(device_t dev)
sc->info.es_vlan_caps = ETHERSWITCH_VLAN_DOT1Q;
strlcpy(sc->info.es_name, "Felix TSN Switch", sizeof(sc->info.es_name));
rid = PCIR_BAR(FELIX_BAR_MDIO);
sc->mdio = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
RF_ACTIVE);
if (sc->mdio == NULL) {
device_printf(dev, "Failed to allocate MDIO registers.\n");
return (ENXIO);
}
rid = PCIR_BAR(FELIX_BAR_REGS);
sc->regs = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
RF_ACTIVE);
if (sc->regs == NULL) {
device_printf(dev, "Failed to allocate registers BAR.\n");
return (ENXIO);
error = ENXIO;
goto out_fail;
}
mtx_init(&sc->mtx, "felix lock", NULL, MTX_DEF);
@ -396,25 +411,9 @@ felix_attach(device_t dev)
goto out_fail;
}
node = OF_parent(node);
if (node <= 0) {
device_printf(sc->dev,
"Failed to obtain MDIO node.\n");
error = ENXIO;
goto out_fail;
}
mdio_dev = OF_device_from_xref(node);
if (mdio_dev == NULL) {
device_printf(sc->dev,
"Failed to obtain MDIO driver handle.\n");
error = ENXIO;
goto out_fail;
}
sc->ports[port].phyaddr = phy_addr;
sc->ports[port].miibus = NULL;
error = mii_attach(mdio_dev, &sc->ports[port].miibus, sc->ports[port].ifp,
error = mii_attach(dev, &sc->ports[port].miibus, sc->ports[port].ifp,
felix_ifmedia_upd, felix_ifmedia_sts, BMSR_DEFCAPMASK,
phy_addr, MII_OFFSET_ANY, 0);
if (error != 0)
@ -447,7 +446,6 @@ static int
felix_detach(device_t dev)
{
felix_softc_t sc;
device_t mdio_dev;
int error;
int i;
@ -468,10 +466,8 @@ felix_detach(device_t dev)
felix_setup(sc);
for (i = 0; i < sc->info.es_nports; i++) {
if (sc->ports[i].miibus != NULL) {
mdio_dev = device_get_parent(sc->ports[i].miibus);
device_delete_child(mdio_dev, sc->ports[i].miibus);
}
if (sc->ports[i].miibus != NULL)
device_delete_child(dev, sc->ports[i].miibus);
if (sc->ports[i].ifp != NULL)
if_free(sc->ports[i].ifp);
if (sc->ports[i].ifname != NULL)
@ -482,6 +478,10 @@ felix_detach(device_t dev)
error = bus_release_resource(sc->dev, SYS_RES_MEMORY,
rman_get_rid(sc->regs), sc->regs);
if (sc->mdio != NULL)
error = bus_release_resource(sc->dev, SYS_RES_MEMORY,
rman_get_rid(sc->mdio), sc->mdio);
return (error);
}
@ -759,32 +759,20 @@ static int
felix_readphy(device_t dev, int phy, int reg)
{
felix_softc_t sc;
device_t mdio_dev;
int port;
sc = device_get_softc(dev);
port = felix_phyforport(sc, phy);
if (port < 0)
return (UINT32_MAX); /* Can't return errors here. */
mdio_dev = device_get_parent(sc->ports[port].miibus);
return (MIIBUS_READREG(mdio_dev, phy, reg));
return (enetc_mdio_read(sc->mdio, FELIX_MDIO_BASE, phy, reg));
}
static int
felix_writephy(device_t dev, int phy, int reg, int data)
{
felix_softc_t sc;
device_t mdio_dev;
int port;
sc = device_get_softc(dev);
port = felix_phyforport(sc, phy);
if (port < 0)
return (ENXIO);
mdio_dev = device_get_parent(sc->ports[port].miibus);
return (MIIBUS_WRITEREG(mdio_dev, phy, reg, data));
return (enetc_mdio_write(sc->mdio, FELIX_MDIO_BASE, phy, reg, data));
}
static int

View File

@ -31,6 +31,8 @@
#define BIT(x) (1UL << (x))
#define FELIX_MDIO_BASE 0x1C00
#define FELIX_DEVCPU_GCB_RST 0x70004
#define FELIX_DEVCPU_GCB_RST_EN BIT(0)

View File

@ -38,6 +38,7 @@
#define PCI_VENDOR_FREESCALE 0x1957
#define FELIX_DEV_ID 0xEEF0
#define FELIX_BAR_MDIO 0
#define FELIX_BAR_REGS 4
#define FELIX_LOCK(_sc) mtx_lock(&(_sc)->mtx)
@ -92,6 +93,7 @@ struct felix_port {
typedef struct felix_softc {
device_t dev;
struct resource *regs;
struct resource *mdio;
etherswitch_info_t info;
struct callout tick_callout;

View File

@ -27,9 +27,10 @@
#
.PATH: ${SRCTOP}/sys/dev/etherswitch/felix
.PATH: ${SRCTOP}/sys/dev/enetc
KMOD = felix
SRCS = felix.c
SRCS = felix.c enetc_mdio.c
SRCS += bus_if.h device_if.h etherswitch_if.h miibus_if.h ofw_bus_if.h pci_if.h
.include <bsd.kmod.mk>