Re: [PATCH] net: add MMIO Register MDIO MUX driver

2021-03-08 Thread Neil Armstrong
On 25/02/2021 20:36, Ramon Fried wrote:
> On Wed, Feb 24, 2021 at 4:02 PM Neil Armstrong  
> wrote:
>>
>> Add support for MMIO register MDIO muxes based on the Linux mdio-mux-mmioreg 
>> driver.
>>
>> Signed-off-by: Neil Armstrong 
>> ---
>>  drivers/net/Kconfig|   7 ++
>>  drivers/net/Makefile   |   1 +
>>  drivers/net/mdio_mux_mmioreg.c | 129 +
>>  3 files changed, 137 insertions(+)
>>  create mode 100644 drivers/net/mdio_mux_mmioreg.c
>>
>> diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
>> index 0e84c22b50..41fa2fe566 100644
>> --- a/drivers/net/Kconfig
>> +++ b/drivers/net/Kconfig
>> @@ -790,4 +790,11 @@ config FSL_LS_MDIO
>>   This driver supports the MDIO bus found on the Fman 10G Ethernet 
>> MACs and
>>   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
>> diff --git a/drivers/net/Makefile b/drivers/net/Makefile
>> index a19511aaa7..511c87c3a5 100644
>> --- a/drivers/net/Makefile
>> +++ b/drivers/net/Makefile
>> @@ -43,6 +43,7 @@ obj-$(CONFIG_MACB) += macb.o
>>  obj-$(CONFIG_MCFFEC) += mcffec.o mcfmii.o
>>  obj-$(CONFIG_MDIO_IPQ4019) += mdio-ipq4019.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_MPC8XX_FEC) += mpc8xx_fec.o
>>  obj-$(CONFIG_MT7620_ETH) += mt7620-eth.o
>> diff --git a/drivers/net/mdio_mux_mmioreg.c b/drivers/net/mdio_mux_mmioreg.c
>> new file mode 100644
>> index 00..e1a23e40a2
>> --- /dev/null
>> +++ b/drivers/net/mdio_mux_mmioreg.c
>> @@ -0,0 +1,129 @@
>> +// SPDX-License-Identifier: GPL-2.0
>> +/*
>> + * (C) Copyright 2021 BayLibre, SAS
>> + * Author: Neil Armstrong 
>> + *
>> + * Based on linux/drivers/net/phy/mdio-mux-mmioreg.c :
>> + *   Copyright 2012 Freescale Semiconductor, Inc.
>> + */
>> +
>> +#include 
>> +#include 
>> +#include 
>> +#include 
>> +#include 
>> +
>> +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, _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", _mask);
>> +   if (err) {
>> 

Re: [PATCH] net: add MMIO Register MDIO MUX driver

2021-02-25 Thread Ramon Fried
On Wed, Feb 24, 2021 at 4:02 PM Neil Armstrong  wrote:
>
> Add support for MMIO register MDIO muxes based on the Linux mdio-mux-mmioreg 
> driver.
>
> Signed-off-by: Neil Armstrong 
> ---
>  drivers/net/Kconfig|   7 ++
>  drivers/net/Makefile   |   1 +
>  drivers/net/mdio_mux_mmioreg.c | 129 +
>  3 files changed, 137 insertions(+)
>  create mode 100644 drivers/net/mdio_mux_mmioreg.c
>
> diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
> index 0e84c22b50..41fa2fe566 100644
> --- a/drivers/net/Kconfig
> +++ b/drivers/net/Kconfig
> @@ -790,4 +790,11 @@ config FSL_LS_MDIO
>   This driver supports the MDIO bus found on the Fman 10G Ethernet 
> MACs and
>   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
> diff --git a/drivers/net/Makefile b/drivers/net/Makefile
> index a19511aaa7..511c87c3a5 100644
> --- a/drivers/net/Makefile
> +++ b/drivers/net/Makefile
> @@ -43,6 +43,7 @@ obj-$(CONFIG_MACB) += macb.o
>  obj-$(CONFIG_MCFFEC) += mcffec.o mcfmii.o
>  obj-$(CONFIG_MDIO_IPQ4019) += mdio-ipq4019.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_MPC8XX_FEC) += mpc8xx_fec.o
>  obj-$(CONFIG_MT7620_ETH) += mt7620-eth.o
> diff --git a/drivers/net/mdio_mux_mmioreg.c b/drivers/net/mdio_mux_mmioreg.c
> new file mode 100644
> index 00..e1a23e40a2
> --- /dev/null
> +++ b/drivers/net/mdio_mux_mmioreg.c
> @@ -0,0 +1,129 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * (C) Copyright 2021 BayLibre, SAS
> + * Author: Neil Armstrong 
> + *
> + * Based on linux/drivers/net/phy/mdio-mux-mmioreg.c :
> + *   Copyright 2012 Freescale Semiconductor, Inc.
> + */
> +
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +
> +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, _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", _mask);
> +   if (err) {
> +   debug("%s: error reading mux-mask property\n", __func__);
> +   return err;
> +   }
> +
> +   if (reg_mask >= BIT(reg_size * 8)) {
> +   printf("%s: 

[PATCH] net: add MMIO Register MDIO MUX driver

2021-02-24 Thread Neil Armstrong
Add support for MMIO register MDIO muxes based on the Linux mdio-mux-mmioreg 
driver.

Signed-off-by: Neil Armstrong 
---
 drivers/net/Kconfig|   7 ++
 drivers/net/Makefile   |   1 +
 drivers/net/mdio_mux_mmioreg.c | 129 +
 3 files changed, 137 insertions(+)
 create mode 100644 drivers/net/mdio_mux_mmioreg.c

diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 0e84c22b50..41fa2fe566 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -790,4 +790,11 @@ config FSL_LS_MDIO
  This driver supports the MDIO bus found on the Fman 10G Ethernet MACs 
and
  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
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index a19511aaa7..511c87c3a5 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -43,6 +43,7 @@ obj-$(CONFIG_MACB) += macb.o
 obj-$(CONFIG_MCFFEC) += mcffec.o mcfmii.o
 obj-$(CONFIG_MDIO_IPQ4019) += mdio-ipq4019.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_MPC8XX_FEC) += mpc8xx_fec.o
 obj-$(CONFIG_MT7620_ETH) += mt7620-eth.o
diff --git a/drivers/net/mdio_mux_mmioreg.c b/drivers/net/mdio_mux_mmioreg.c
new file mode 100644
index 00..e1a23e40a2
--- /dev/null
+++ b/drivers/net/mdio_mux_mmioreg.c
@@ -0,0 +1,129 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * (C) Copyright 2021 BayLibre, SAS
+ * Author: Neil Armstrong 
+ *
+ * Based on linux/drivers/net/phy/mdio-mux-mmioreg.c :
+ *   Copyright 2012 Freescale Semiconductor, Inc.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+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, _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", _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[] = {
+   {