[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