[net-next PATCH v12 07/13] net: mdio: regmap: add support for multiple valid addr

Christian Marangi posted 13 patches 11 months ago
There is a newer version of this series
[net-next PATCH v12 07/13] net: mdio: regmap: add support for multiple valid addr
Posted by Christian Marangi 11 months ago
Add support for multiple valid addr for mdio regmap. This can be done by
defining the new valid_addr_mask value in the mdio regmap config.

In such case, the PHY address is appended to the regmap regnum right
after the first 16 bit of the PHY register used for the read/write
operation.

The passed regmap will then extract the address from the passed regnum
and execute the needed operations accordingly.

Notice that if valid_addr_mask, the unique valid_addr in config is
ignored.

Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
---
 drivers/net/mdio/mdio-regmap.c   | 14 +++++++++++++-
 include/linux/mdio/mdio-regmap.h |  9 +++++++++
 2 files changed, 22 insertions(+), 1 deletion(-)

diff --git a/drivers/net/mdio/mdio-regmap.c b/drivers/net/mdio/mdio-regmap.c
index 810ba0a736f0..8bfcd9e415c8 100644
--- a/drivers/net/mdio/mdio-regmap.c
+++ b/drivers/net/mdio/mdio-regmap.c
@@ -20,6 +20,7 @@
 struct mdio_regmap_priv {
 	struct regmap *regmap;
 	u32 valid_addr_mask;
+	bool append_addr;
 };
 
 static int mdio_regmap_read_c22(struct mii_bus *bus, int addr, int regnum)
@@ -31,6 +32,9 @@ static int mdio_regmap_read_c22(struct mii_bus *bus, int addr, int regnum)
 	if (!(ctx->valid_addr_mask & BIT(addr)))
 		return -ENODEV;
 
+	if (ctx->append_addr)
+		regnum |= FIELD_PREP(MDIO_REGMAP_PHY_ADDR, addr);
+
 	ret = regmap_read(ctx->regmap, regnum, &val);
 	if (ret < 0)
 		return ret;
@@ -46,6 +50,9 @@ static int mdio_regmap_write_c22(struct mii_bus *bus, int addr, int regnum,
 	if (!(ctx->valid_addr_mask & BIT(addr)))
 		return -ENODEV;
 
+	if (ctx->append_addr)
+		regnum |= FIELD_PREP(MDIO_REGMAP_PHY_ADDR, addr);
+
 	return regmap_write(ctx->regmap, regnum, val);
 }
 
@@ -65,7 +72,12 @@ struct mii_bus *devm_mdio_regmap_register(struct device *dev,
 
 	mr = mii->priv;
 	mr->regmap = config->regmap;
-	mr->valid_addr_mask = BIT(config->valid_addr);
+	if (config->valid_addr_mask) {
+		mr->valid_addr_mask = config->valid_addr_mask;
+		mr->append_addr = true;
+	} else {
+		mr->valid_addr_mask = BIT(config->valid_addr);
+	}
 
 	mii->name = DRV_NAME;
 	strscpy(mii->id, config->name, MII_BUS_ID_SIZE);
diff --git a/include/linux/mdio/mdio-regmap.h b/include/linux/mdio/mdio-regmap.h
index 679d9069846b..8c7061e39ccb 100644
--- a/include/linux/mdio/mdio-regmap.h
+++ b/include/linux/mdio/mdio-regmap.h
@@ -12,11 +12,20 @@
 struct device;
 struct regmap;
 
+/* If a non empty valid_addr_mask is passed, PHY address and
+ * read/write register are encoded in the regmap register
+ * by placing the register in the first 16 bits and the PHY address
+ * right after.
+ */
+#define MDIO_REGMAP_PHY_ADDR		GENMASK(20, 16)
+#define MDIO_REGMAP_PHY_REG		GENMASK(15, 0)
+
 struct mdio_regmap_config {
 	struct device *parent;
 	struct regmap *regmap;
 	char name[MII_BUS_ID_SIZE];
 	u8 valid_addr;
+	u32 valid_addr_mask;
 	bool autoscan;
 };
 
-- 
2.48.1
Re: [net-next PATCH v12 07/13] net: mdio: regmap: add support for multiple valid addr
Posted by Russell King (Oracle) 11 months ago
On Sun, Mar 09, 2025 at 06:26:52PM +0100, Christian Marangi wrote:
> +/* If a non empty valid_addr_mask is passed, PHY address and
> + * read/write register are encoded in the regmap register
> + * by placing the register in the first 16 bits and the PHY address
> + * right after.
> + */
> +#define MDIO_REGMAP_PHY_ADDR		GENMASK(20, 16)
> +#define MDIO_REGMAP_PHY_REG		GENMASK(15, 0)

Clause 45 PHYs have 5 bits of PHY address, then 5 bits of mmd address,
and then 16 bits of register address - significant in that order. Can
we adjust the mask for the PHY address later to add the MMD between
the PHY address and register number?

-- 
RMK's Patch system: https://www.armlinux.org.uk/developer/patches/
FTTP is here! 80Mbps down 10Mbps up. Decent connectivity at last!
Re: [net-next PATCH v12 07/13] net: mdio: regmap: add support for multiple valid addr
Posted by Christian Marangi 11 months ago
On Sun, Mar 09, 2025 at 05:36:49PM +0000, Russell King (Oracle) wrote:
> On Sun, Mar 09, 2025 at 06:26:52PM +0100, Christian Marangi wrote:
> > +/* If a non empty valid_addr_mask is passed, PHY address and
> > + * read/write register are encoded in the regmap register
> > + * by placing the register in the first 16 bits and the PHY address
> > + * right after.
> > + */
> > +#define MDIO_REGMAP_PHY_ADDR		GENMASK(20, 16)
> > +#define MDIO_REGMAP_PHY_REG		GENMASK(15, 0)
> 
> Clause 45 PHYs have 5 bits of PHY address, then 5 bits of mmd address,
> and then 16 bits of register address - significant in that order. Can
> we adjust the mask for the PHY address later to add the MMD between
> the PHY address and register number?
>

Honestly to future proof this, I think a good idea might be to add
helper to encode these info and use Clause 45 format even for C22.
Maybe we can use an extra bit to signal if the format is C22 or C45.

BIT(26) 0: C22 1:C45
GENMASK(25, 21) PHY ADDR
GENMASK(20, 16) MMD ADDR
GENMASK(15, 0) REG

What do you think?

-- 
	Ansuel
Re: [net-next PATCH v12 07/13] net: mdio: regmap: add support for multiple valid addr
Posted by Andrew Lunn 11 months ago
On Sun, Mar 09, 2025 at 06:45:43PM +0100, Christian Marangi wrote:
> On Sun, Mar 09, 2025 at 05:36:49PM +0000, Russell King (Oracle) wrote:
> > On Sun, Mar 09, 2025 at 06:26:52PM +0100, Christian Marangi wrote:
> > > +/* If a non empty valid_addr_mask is passed, PHY address and
> > > + * read/write register are encoded in the regmap register
> > > + * by placing the register in the first 16 bits and the PHY address
> > > + * right after.
> > > + */
> > > +#define MDIO_REGMAP_PHY_ADDR		GENMASK(20, 16)
> > > +#define MDIO_REGMAP_PHY_REG		GENMASK(15, 0)
> > 
> > Clause 45 PHYs have 5 bits of PHY address, then 5 bits of mmd address,
> > and then 16 bits of register address - significant in that order. Can
> > we adjust the mask for the PHY address later to add the MMD between
> > the PHY address and register number?
> >
> 
> Honestly to future proof this, I think a good idea might be to add
> helper to encode these info and use Clause 45 format even for C22.
> Maybe we can use an extra bit to signal if the format is C22 or C45.
> 
> BIT(26) 0: C22 1:C45
> GENMASK(25, 21) PHY ADDR
> GENMASK(20, 16) MMD ADDR
> GENMASK(15, 0) REG

If you look back at older kernels, there was some helpers to do
something like this, but the C22/C45 was in bit 31. When i cleaned up
MDIO drivers to have separate C22 and C45 read/write functions, they
become redundant and they were removed. You might want to bring them
back again.

	Andrew
Re: [net-next PATCH v12 07/13] net: mdio: regmap: add support for multiple valid addr
Posted by Russell King (Oracle) 11 months ago
On Fri, Mar 14, 2025 at 08:41:33PM +0100, Andrew Lunn wrote:
> On Sun, Mar 09, 2025 at 06:45:43PM +0100, Christian Marangi wrote:
> > On Sun, Mar 09, 2025 at 05:36:49PM +0000, Russell King (Oracle) wrote:
> > > On Sun, Mar 09, 2025 at 06:26:52PM +0100, Christian Marangi wrote:
> > > > +/* If a non empty valid_addr_mask is passed, PHY address and
> > > > + * read/write register are encoded in the regmap register
> > > > + * by placing the register in the first 16 bits and the PHY address
> > > > + * right after.
> > > > + */
> > > > +#define MDIO_REGMAP_PHY_ADDR		GENMASK(20, 16)
> > > > +#define MDIO_REGMAP_PHY_REG		GENMASK(15, 0)
> > > 
> > > Clause 45 PHYs have 5 bits of PHY address, then 5 bits of mmd address,
> > > and then 16 bits of register address - significant in that order. Can
> > > we adjust the mask for the PHY address later to add the MMD between
> > > the PHY address and register number?
> > >
> > 
> > Honestly to future proof this, I think a good idea might be to add
> > helper to encode these info and use Clause 45 format even for C22.
> > Maybe we can use an extra bit to signal if the format is C22 or C45.
> > 
> > BIT(26) 0: C22 1:C45
> > GENMASK(25, 21) PHY ADDR
> > GENMASK(20, 16) MMD ADDR
> > GENMASK(15, 0) REG
> 
> If you look back at older kernels, there was some helpers to do
> something like this, but the C22/C45 was in bit 31. When i cleaned up
> MDIO drivers to have separate C22 and C45 read/write functions, they
> become redundant and they were removed. You might want to bring them
> back again.

I'd prefer we didn't bring that abomination back. The detail about how
things are stored in regmap should be internal within regmap, and I
think it would be better to have an API presented that takes sensible
parameters, rather than something that's been encoded.

-- 
RMK's Patch system: https://www.armlinux.org.uk/developer/patches/
FTTP is here! 80Mbps down 10Mbps up. Decent connectivity at last!
Re: [net-next PATCH v12 07/13] net: mdio: regmap: add support for multiple valid addr
Posted by Christian Marangi 11 months ago
On Fri, Mar 14, 2025 at 09:01:56PM +0000, Russell King (Oracle) wrote:
> On Fri, Mar 14, 2025 at 08:41:33PM +0100, Andrew Lunn wrote:
> > On Sun, Mar 09, 2025 at 06:45:43PM +0100, Christian Marangi wrote:
> > > On Sun, Mar 09, 2025 at 05:36:49PM +0000, Russell King (Oracle) wrote:
> > > > On Sun, Mar 09, 2025 at 06:26:52PM +0100, Christian Marangi wrote:
> > > > > +/* If a non empty valid_addr_mask is passed, PHY address and
> > > > > + * read/write register are encoded in the regmap register
> > > > > + * by placing the register in the first 16 bits and the PHY address
> > > > > + * right after.
> > > > > + */
> > > > > +#define MDIO_REGMAP_PHY_ADDR		GENMASK(20, 16)
> > > > > +#define MDIO_REGMAP_PHY_REG		GENMASK(15, 0)
> > > > 
> > > > Clause 45 PHYs have 5 bits of PHY address, then 5 bits of mmd address,
> > > > and then 16 bits of register address - significant in that order. Can
> > > > we adjust the mask for the PHY address later to add the MMD between
> > > > the PHY address and register number?
> > > >
> > > 
> > > Honestly to future proof this, I think a good idea might be to add
> > > helper to encode these info and use Clause 45 format even for C22.
> > > Maybe we can use an extra bit to signal if the format is C22 or C45.
> > > 
> > > BIT(26) 0: C22 1:C45
> > > GENMASK(25, 21) PHY ADDR
> > > GENMASK(20, 16) MMD ADDR
> > > GENMASK(15, 0) REG
> > 
> > If you look back at older kernels, there was some helpers to do
> > something like this, but the C22/C45 was in bit 31. When i cleaned up
> > MDIO drivers to have separate C22 and C45 read/write functions, they
> > become redundant and they were removed. You might want to bring them
> > back again.
> 
> I'd prefer we didn't bring that abomination back. The detail about how
> things are stored in regmap should be internal within regmap, and I
> think it would be better to have an API presented that takes sensible
> parameters, rather than something that's been encoded.
>

Well problem is that regmap_write and regmap_read will take max 2 value
at the very end (reg and value) so it's really a matter of making the
encoding part internal but encoding it can't be skipped.

You are suggesting to introduce additional API like

mdio_regmap_write(regmap, phy, addr, val);
mdio_mmd_regmap_write(regmap, phy, mmd, addr, val);

And the encoding is done internally?

My concern is the decoding part from the .write/read_bits regmap OPs.
I guess for that also some helper should be exposed (to keep the
decoding/encoding internal to the driver and not expose the
_abomination_)

What do you think?

-- 
	Ansuel
Re: [net-next PATCH v12 07/13] net: mdio: regmap: add support for multiple valid addr
Posted by Russell King (Oracle) 11 months ago
On Fri, Mar 14, 2025 at 10:19:29PM +0100, Christian Marangi wrote:
> On Fri, Mar 14, 2025 at 09:01:56PM +0000, Russell King (Oracle) wrote:
> > I'd prefer we didn't bring that abomination back. The detail about how
> > things are stored in regmap should be internal within regmap, and I
> > think it would be better to have an API presented that takes sensible
> > parameters, rather than something that's been encoded.
> 
> Well problem is that regmap_write and regmap_read will take max 2 value
> at the very end (reg and value) so it's really a matter of making the
> encoding part internal but encoding it can't be skipped.
> 
> You are suggesting to introduce additional API like
> 
> mdio_regmap_write(regmap, phy, addr, val);
> mdio_mmd_regmap_write(regmap, phy, mmd, addr, val);
> 
> And the encoding is done internally?

Yes, because littering drivers with the details of the conversion is
unreasonable.

> My concern is the decoding part from the .write/read_bits regmap OPs.
> I guess for that also some helper should be exposed (to keep the
> decoding/encoding internal to the driver and not expose the
> _abomination_)

Sadly, I don't think that's something we can get away from, but we
should make it _easy_ for people to get it right.

From what I remember from the days of shoe-horning C45 into the C22
MDIO API, encoding and/or decoding addresses was buggy because people
would use the wrong encoders and decoders.

For example, we had MDIO drivers using mdio_phy_id_is_c45() to test
whether the access being requested was C45 - mdio_phy_id_is_c45() is
for the _userspace_ MII API encoding (struct mii_ioctl_data), not the
kernel space. Kernel space used:

-#define MII_ADDR_C45 (1<<30)
-#define MII_DEVADDR_C45_SHIFT  16
-#define MII_REGADDR_C45_MASK   GENMASK(15, 0)

to encode into the register number argument vs the userspace encoding
into the phy_id member of struct mii_ioctl_data:

#define MDIO_PHY_ID_C45                 0x8000
#define MDIO_PHY_ID_PRTAD               0x03e0
#define MDIO_PHY_ID_DEVAD               0x001f

which is what the mdio_phy_id_*() accessors are using. The two
approaches are incompatible, and using the userspace one in a MDIO
driver wasn't going to work correctly - but people did it.

This is one of the reasons I hated the old MDIO API, and why we now
have separate C22 and C45 interfaces in the driver code.

This is exactly why I don't like reintroducing a new set of "massage
the package, mmd and address into some single integer representation"
and "decode a single integer into their respective parts" - we've
been here before, it's lead to problems because driver authors can't
grasp what the right approach is, and it results in bugs.

Given the history here, my personal opinion would be... if regmap can't
cope with MDIO devices having a three-part address without requiring
callers to flatten it first, and then have various regmap drivers
unflatten it, then regmap is unsuitable to be used with MDIO and ought
not be used.

So, this encoding/decoding is a problem that should be solved entirely
within regmap, and not spread out into users of regmap and drivers
behind regmap. Anything else is, IMHO, insane.

-- 
RMK's Patch system: https://www.armlinux.org.uk/developer/patches/
FTTP is here! 80Mbps down 10Mbps up. Decent connectivity at last!