[U-Boot] [PATCH 1/2] drivers: net: driver for MDIO muxes controlled over I2C

Bin Meng bmeng.cn at gmail.com
Sat Jul 13 04:02:04 UTC 2019


Hi Alex,

On Fri, Jul 12, 2019 at 10:21 PM Alex Marginean
<alexandru.marginean at nxp.com> wrote:
>
> This driver is used for MDIO muxes driven over I2C.  This is currently
> used on Freescale LS1028A QDS board, on which the physical MDIO MUX is
> controlled by an on-board FPGA which in turn is configured through I2C.
>
> Signed-off-by: Alex Marginean <alexm.osslist at gmail.com>
> ---
>
> Depends on https://patchwork.ozlabs.org/project/uboot/list/?series=119124
>
>  drivers/net/Kconfig            |   8 +++
>  drivers/net/Makefile           |   1 +
>  drivers/net/mdio_mux_i2c_reg.c | 108 +++++++++++++++++++++++++++++++++
>  3 files changed, 117 insertions(+)
>  create mode 100644 drivers/net/mdio_mux_i2c_reg.c
>
> diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
> index 4d85fb1716..93535f7acb 100644
> --- a/drivers/net/Kconfig
> +++ b/drivers/net/Kconfig
> @@ -595,4 +595,12 @@ config FSL_ENETC
>           This driver supports the NXP ENETC Ethernet controller found on some
>           of the NXP SoCs.
>
> +config MDIO_MUX_I2C_REG

I don't see current Linux upstream has any I2CREG support. I believe
you will upstream the Linux support too?

So based on existing Linux kernel MMIOREG support, (see
mdio-mux-mmioreg.txt in the Linux devicetree bindings direoctory),
looks we need name this as MDIO_MUX_I2CREG for consistency.

> +       bool "MDIO MUX accessed as a register over I2C"
> +       depends on DM_MDIO_MUX && DM_I2C
> +       help
> +         This driver is used for MDIO muxes driven by writing to a register of
> +         an I2C chip.  The board it was developed for uses a mux controlled by
> +         on-board FPGA which in turn is accessed as a chip over I2C.
> +
>  endif # NETDEVICES
> diff --git a/drivers/net/Makefile b/drivers/net/Makefile
> index 97119cec7c..9470f02dc6 100644
> --- a/drivers/net/Makefile
> +++ b/drivers/net/Makefile
> @@ -80,3 +80,4 @@ obj-$(CONFIG_HIGMACV300_ETH) += higmacv300.o
>  obj-$(CONFIG_MDIO_SANDBOX) += mdio_sandbox.o
>  obj-$(CONFIG_FSL_ENETC) += fsl_enetc.o fsl_enetc_mdio.o
>  obj-$(CONFIG_MDIO_MUX_SANDBOX) += mdio_mux_sandbox.o
> +obj-$(CONFIG_MDIO_MUX_I2C_REG) += mdio_mux_i2c_reg.o
> diff --git a/drivers/net/mdio_mux_i2c_reg.c b/drivers/net/mdio_mux_i2c_reg.c
> new file mode 100644
> index 0000000000..eb75c5e032
> --- /dev/null
> +++ b/drivers/net/mdio_mux_i2c_reg.c
> @@ -0,0 +1,108 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * (C) Copyright 2019
> + * Alex Marginean, NXP
> + */
> +
> +#include <dm.h>
> +#include <errno.h>
> +#include <miiphy.h>
> +#include <i2c.h>
> +
> +/*
> + * This driver is used for MDIO muxes driven by writing to a register of an I2C
> + * chip.  The board it was developed for uses a mux controlled by on-board FPGA
> + * which in turn is accessed as a chip over I2C.
> + */
> +
> +struct mmux_i2c_reg_priv {
> +       struct udevice *chip;
> +       int reg;
> +       int mask;
> +};
> +
> +static int mmux_i2c_reg_select(struct udevice *mux, int cur, int sel)
> +{
> +       struct mmux_i2c_reg_priv *priv = dev_get_priv(mux);
> +       u8 val, val_old;
> +
> +       /* if last selection didn't change we're good to go */
> +       if (cur == sel)
> +               return 0;
> +
> +       val_old = dm_i2c_reg_read(priv->chip, priv->reg);
> +       val = (val_old & ~priv->mask) | (sel & priv->mask);
> +       debug("%s: chip %s, reg %x, val %x => %x\n", __func__, priv->chip->name,
> +             priv->reg, val_old, val);
> +       dm_i2c_reg_write(priv->chip, priv->reg, val);
> +
> +       return 0;
> +}
> +
> +static const struct mdio_mux_ops mmux_i2c_reg_ops = {
> +       .select = mmux_i2c_reg_select,
> +};
> +
> +static int mmux_i2c_reg_probe(struct udevice *dev)
> +{
> +       struct mmux_i2c_reg_priv *priv = dev_get_priv(dev);
> +       ofnode chip_node, bus_node;
> +       struct udevice *i2c_bus;
> +       u32 reg_mask[2];
> +       u32 chip_addr;
> +       int err;
> +
> +       /* read the register addr/mask pair */
> +       err = dev_read_u32_array(dev, "mux-reg-masks", reg_mask, 2);
> +       if (err) {
> +               debug("%s: error reading mux-reg-masks property\n", __func__);
> +               return err;
> +       }
> +
> +       /* parent should be an I2C chip, grandparent should be an I2C bus */
> +       chip_node = ofnode_get_parent(dev->node);
> +       bus_node = ofnode_get_parent(chip_node);
> +
> +       err = uclass_get_device_by_ofnode(UCLASS_I2C, bus_node, &i2c_bus);
> +       if (err) {
> +               debug("%s: can't find I2C bus for node %s\n", __func__,
> +                     ofnode_get_name(bus_node));
> +               return err;
> +       }
> +
> +       err = ofnode_read_u32(chip_node, "reg", &chip_addr);
> +       if (err) {
> +               debug("%s: can't read chip address in %s\n", __func__,
> +                     ofnode_get_name(chip_node));
> +               return err;
> +       }
> +
> +       err = i2c_get_chip(i2c_bus, (uint)chip_addr, 1, &priv->chip);
> +       if (err) {
> +               debug("%s: can't find i2c chip device for addr %x\n", __func__,
> +                     chip_addr);
> +               return err;
> +       }
> +
> +       priv->reg = (int)reg_mask[0];
> +       priv->mask = (int)reg_mask[1];
> +
> +       debug("%s: chip %s, reg %x, mask %x\n", __func__, priv->chip->name,
> +             priv->reg, priv->mask);
> +
> +       return 0;
> +}
> +
> +static const struct udevice_id mmux_i2c_reg_ids[] = {
> +       { .compatible = "mdio-mux-i2c-reg" },

We should use the exact same compatible string as Linux, although
Linux upstream does not have such support for now, but I believe it
should be "mdio-mux-i2creg" for consistency with "mdio-mux-mmioreg".

> +       { }
> +};
> +
> +U_BOOT_DRIVER(mmux_i2c_reg) = {
> +       .name           = "mdio_mux_i2c_reg",
> +       .id             = UCLASS_MDIO_MUX,
> +       .of_match       = mmux_i2c_reg_ids,
> +       .probe          = mmux_i2c_reg_probe,
> +       .ops            = &mmux_i2c_reg_ops,
> +       .priv_auto_alloc_size = sizeof(struct mmux_i2c_reg_priv),
> +};

nits: please replace all mdio_mux_i2c_reg_xxx to mdio_mux_i2creg_xxx

Regards,
Bin


More information about the U-Boot mailing list