[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20260122105654.105600-2-vladimir.oltean@nxp.com>
Date: Thu, 22 Jan 2026 12:56:40 +0200
From: Vladimir Oltean <vladimir.oltean@....com>
To: netdev@...r.kernel.org
Cc: Andrew Lunn <andrew@...n.ch>,
Heiner Kallweit <hkallweit1@...il.com>,
Russell King <linux@...linux.org.uk>,
"David S. Miller" <davem@...emloft.net>,
Eric Dumazet <edumazet@...gle.com>,
Jakub Kicinski <kuba@...nel.org>,
Paolo Abeni <pabeni@...hat.com>,
linux-kernel@...r.kernel.org,
Andy Shevchenko <andriy.shevchenko@...ux.intel.com>,
Herve Codina <herve.codina@...tlin.com>,
Mark Brown <broonie@...nel.org>,
Serge Semin <fancer.lancer@...il.com>,
Maxime Chevallier <maxime.chevallier@...tlin.com>,
Lee Jones <lee@...nel.org>,
Rob Herring <robh@...nel.org>,
Krzysztof Kozlowski <krzk+dt@...nel.org>,
Conor Dooley <conor+dt@...nel.org>,
devicetree@...r.kernel.org,
Choong Yong Liang <yong.liang.choong@...ux.intel.com>,
Jiawen Wu <jiawenwu@...stnetic.com>
Subject: [PATCH v2 net-next 01/15] net: mdio-regmap: permit working with non-MMIO regmaps
The regmap world is seemingly split into two groups which attempt to
solve different problems. Effectively, this means that not all regmap
providers are compatible with all regmap consumers.
First, we have the group where the current mdio-regmap users fit:
altera_tse_main.c and dwmac-socfpga.c use devm_regmap_init_mmio() to
ioremap their pcs_base and obtain a regmap where address zero is the
first PCS register.
Second, we have the group where MFD parent drivers call
mfd_add_devices(), having previously initialized a non-MMIO (SPI, I2C)
regmap and added it to their devres list, and MFD child drivers use
dev_get_regmap(dev->parent, NULL) in their probe function, to find the
first (and single) regmap of the MFD parent. The address zero of this
regmap is global to the entire parent, so the children need to be
parent-aware and add their own offsets for the registers that they
should manage. This is essentially because MFD is seemingly coming from
a world where peripheral registers are all entangled with each other.
What I'm trying to support are potentially multiple instances of the
same kind of device, at well separated address space regions.
To provide isolated regmaps for each child device would essentially mean
solving the problem of how would each child device needs to find the
correct regmap. This further means that "dev_get_regmap(dev->parent,
NULL)" transforms either in:
- dev_get_regmap(dev, NULL): search in the child device's devres list,
not in the parent's. This means adding the regmap in between
platform_device_alloc() and platform_device_add(), but is
structurally impossible because &dev->devres_head is initialized way
too late, in device_initialize().
- dev_get_regmap(dev->parent, "unique-regmap-name"): now the child
device needs to know, in case there are multiple instances of it,
which one is it, to ask for the right one. I've seen
drivers/mfd/ocelot-core.c work around this rather elegantly, providing
a resource to the child, and then the child uses resource->name to
find the regmap of the same name in the parent. But then I also
stumbled upon drivers/net/pcs/pcs-xpcs-plat.c which I need to support
as a child platform device, and that superimposes its own naming
scheme for the resources: "direct" or "indirect" - scheme which is
obviously incompatible with namespacing per instance.
So a parent device needs to decide whether it is in the boat that
provides one isolated regmap for each child, or one big regmap for all.
The "one big regmap" is the lowest common denominator when considering
children like pcs-xpcs-plat.c.
This means that from mdio-regmap's perspective, it needs to deal with
regmaps coming from both kinds of providers, as neither of them is going
away.
Users who provide a big regmap but want to access only a window into it
should provide as a struct mdio_regmap_config field a resource that
describes the start and end of that window. Currently we only use the
start as an offset into the regmap, and hope that MDIO reads and writes
won't go past the end.
Cc: Mark Brown <broonie@...nel.org>
Cc: Maxime Chevallier <maxime.chevallier@...tlin.com>
Signed-off-by: Vladimir Oltean <vladimir.oltean@....com>
Reviewed-by: Maxime Chevallier <maxime.chevallier@...tlin.com>
---
v1->v2: add Maxime's review tag
drivers/net/mdio/mdio-regmap.c | 7 +++++--
include/linux/mdio/mdio-regmap.h | 2 ++
2 files changed, 7 insertions(+), 2 deletions(-)
diff --git a/drivers/net/mdio/mdio-regmap.c b/drivers/net/mdio/mdio-regmap.c
index 8a742a8d6387..2a0e9c519fa3 100644
--- a/drivers/net/mdio/mdio-regmap.c
+++ b/drivers/net/mdio/mdio-regmap.c
@@ -19,6 +19,7 @@
struct mdio_regmap_priv {
struct regmap *regmap;
+ unsigned int base;
u8 valid_addr;
};
@@ -31,7 +32,7 @@ static int mdio_regmap_read_c22(struct mii_bus *bus, int addr, int regnum)
if (ctx->valid_addr != addr)
return -ENODEV;
- ret = regmap_read(ctx->regmap, regnum, &val);
+ ret = regmap_read(ctx->regmap, ctx->base + regnum, &val);
if (ret < 0)
return ret;
@@ -46,7 +47,7 @@ static int mdio_regmap_write_c22(struct mii_bus *bus, int addr, int regnum,
if (ctx->valid_addr != addr)
return -ENODEV;
- return regmap_write(ctx->regmap, regnum, val);
+ return regmap_write(ctx->regmap, ctx->base + regnum, val);
}
struct mii_bus *devm_mdio_regmap_register(struct device *dev,
@@ -66,6 +67,8 @@ struct mii_bus *devm_mdio_regmap_register(struct device *dev,
mr = mii->priv;
mr->regmap = config->regmap;
mr->valid_addr = config->valid_addr;
+ if (config->resource)
+ mr->base = config->resource->start;
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..441cead97936 100644
--- a/include/linux/mdio/mdio-regmap.h
+++ b/include/linux/mdio/mdio-regmap.h
@@ -11,10 +11,12 @@
struct device;
struct regmap;
+struct resource;
struct mdio_regmap_config {
struct device *parent;
struct regmap *regmap;
+ const struct resource *resource;
char name[MII_BUS_ID_SIZE];
u8 valid_addr;
bool autoscan;
--
2.34.1
Powered by blists - more mailing lists