
Hi Alex,
On Fri, Jul 12, 2019 at 10:21 PM Alex Marginean alexandru.marginean@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@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