net: add MMIO Register MDIO MUX driver

Add support for MMIO register MDIO muxes based on the Linux mdio-mux-mmioreg driver.

Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
Reviewed-by: Ramon Fried <rfried.dev@gmail.com>
This commit is contained in:
Neil Armstrong 2021-02-24 15:02:23 +01:00
parent 90eba245a6
commit 6c7bc9fec0
3 changed files with 137 additions and 0 deletions

View File

@ -790,4 +790,11 @@ config FSL_LS_MDIO
This driver supports the MDIO bus found on the Fman 10G Ethernet MACs and This driver supports the MDIO bus found on the Fman 10G Ethernet MACs and
on the mEMAC (which supports both Clauses 22 and 45). on the mEMAC (which supports both Clauses 22 and 45).
config MDIO_MUX_MMIOREG
bool "MDIO MUX accessed as a MMIO register access"
depends on DM_MDIO_MUX
help
This driver is used for MDIO muxes driven by writing to a register in
the MMIO physical memory.
endif # NETDEVICES endif # NETDEVICES

View File

@ -43,6 +43,7 @@ obj-$(CONFIG_MACB) += macb.o
obj-$(CONFIG_MCFFEC) += mcffec.o mcfmii.o obj-$(CONFIG_MCFFEC) += mcffec.o mcfmii.o
obj-$(CONFIG_MDIO_IPQ4019) += mdio-ipq4019.o obj-$(CONFIG_MDIO_IPQ4019) += mdio-ipq4019.o
obj-$(CONFIG_MDIO_MUX_I2CREG) += mdio_mux_i2creg.o obj-$(CONFIG_MDIO_MUX_I2CREG) += mdio_mux_i2creg.o
obj-$(CONFIG_MDIO_MUX_MMIOREG) += mdio_mux_mmioreg.o
obj-$(CONFIG_MDIO_MUX_SANDBOX) += mdio_mux_sandbox.o obj-$(CONFIG_MDIO_MUX_SANDBOX) += mdio_mux_sandbox.o
obj-$(CONFIG_MPC8XX_FEC) += mpc8xx_fec.o obj-$(CONFIG_MPC8XX_FEC) += mpc8xx_fec.o
obj-$(CONFIG_MT7620_ETH) += mt7620-eth.o obj-$(CONFIG_MT7620_ETH) += mt7620-eth.o

View File

@ -0,0 +1,129 @@
// SPDX-License-Identifier: GPL-2.0
/*
* (C) Copyright 2021 BayLibre, SAS
* Author: Neil Armstrong <narmstrong@baylibre.com>
*
* Based on linux/drivers/net/phy/mdio-mux-mmioreg.c :
* Copyright 2012 Freescale Semiconductor, Inc.
*/
#include <dm.h>
#include <errno.h>
#include <log.h>
#include <miiphy.h>
#include <linux/io.h>
struct mdio_mux_mmioreg_priv {
struct udevice *chip;
phys_addr_t phys;
unsigned int iosize;
unsigned int mask;
};
static int mdio_mux_mmioreg_select(struct udevice *mux, int cur, int sel)
{
struct mdio_mux_mmioreg_priv *priv = dev_get_priv(mux);
debug("%s: %x -> %x\n", __func__, (u32)cur, (u32)sel);
/* if last selection didn't change we're good to go */
if (cur == sel)
return 0;
switch (priv->iosize) {
case sizeof(u8): {
u8 x, y;
x = ioread8((void *)priv->phys);
y = (x & ~priv->mask) | (u32)sel;
if (x != y) {
iowrite8((x & ~priv->mask) | sel, (void *)priv->phys);
debug("%s: %02x -> %02x\n", __func__, x, y);
}
break;
}
case sizeof(u16): {
u16 x, y;
x = ioread16((void *)priv->phys);
y = (x & ~priv->mask) | (u32)sel;
if (x != y) {
iowrite16((x & ~priv->mask) | sel, (void *)priv->phys);
debug("%s: %04x -> %04x\n", __func__, x, y);
}
break;
}
case sizeof(u32): {
u32 x, y;
x = ioread32((void *)priv->phys);
y = (x & ~priv->mask) | (u32)sel;
if (x != y) {
iowrite32((x & ~priv->mask) | sel, (void *)priv->phys);
debug("%s: %08x -> %08x\n", __func__, x, y);
}
break;
}
}
return 0;
}
static const struct mdio_mux_ops mdio_mux_mmioreg_ops = {
.select = mdio_mux_mmioreg_select,
};
static int mdio_mux_mmioreg_probe(struct udevice *dev)
{
struct mdio_mux_mmioreg_priv *priv = dev_get_priv(dev);
phys_addr_t reg_base, reg_size;
u32 reg_mask;
int err;
reg_base = ofnode_get_addr_size_index(dev_ofnode(dev), 0, &reg_size);
if (reg_base == FDT_ADDR_T_NONE)
return -EINVAL;
if (reg_size != sizeof(u8) &&
reg_size != sizeof(u16) &&
reg_size != sizeof(u32)) {
printf("%s: only 8/16/32-bit registers are supported\n", __func__);
return -EINVAL;
}
err = dev_read_u32(dev, "mux-mask", &reg_mask);
if (err) {
debug("%s: error reading mux-mask property\n", __func__);
return err;
}
if (reg_mask >= BIT(reg_size * 8)) {
printf("%s: mask doesn't fix in register width\n", __func__);
return -EINVAL;
}
priv->phys = reg_base;
priv->iosize = reg_size;
priv->mask = reg_mask;
debug("%s: %llx@%lld / %x\n", __func__, reg_base, reg_size, reg_mask);
return 0;
}
static const struct udevice_id mdio_mux_mmioreg_ids[] = {
{ .compatible = "mdio-mux-mmioreg" },
{ }
};
U_BOOT_DRIVER(mdio_mux_mmioreg) = {
.name = "mdio_mux_mmioreg",
.id = UCLASS_MDIO_MUX,
.of_match = mdio_mux_mmioreg_ids,
.probe = mdio_mux_mmioreg_probe,
.ops = &mdio_mux_mmioreg_ops,
.priv_auto = sizeof(struct mdio_mux_mmioreg_priv),
};