[PATCH] i2c-mux-pca954x: use OF match table

2023-12-21 Thread Alvin Šipraga
From: Alvin Šipraga 

Allow the mux driver to match against device tree compatible strings.

Signed-off-by: Alvin Šipraga 
---
 drivers/i2c/muxes/i2c-mux-pca954x.c | 14 ++
 1 file changed, 14 insertions(+)

diff --git a/drivers/i2c/muxes/i2c-mux-pca954x.c 
b/drivers/i2c/muxes/i2c-mux-pca954x.c
index 6c21b92860f0..fef95fa57eb7 100644
--- a/drivers/i2c/muxes/i2c-mux-pca954x.c
+++ b/drivers/i2c/muxes/i2c-mux-pca954x.c
@@ -255,9 +255,23 @@ static int pca954x_probe(struct device *dev)
return ret;
 }
 
+static const struct of_device_id pca954x_dt_ids[] = {
+   { .compatible = "nxp,pca9540", .data = (const void *)pca_9540 },
+   { .compatible = "nxp,pca9542", .data = (const void *)pca_9542 },
+   { .compatible = "nxp,pca9543", .data = (const void *)pca_9543 },
+   { .compatible = "nxp,pca9544", .data = (const void *)pca_9544 },
+   { .compatible = "nxp,pca9545", .data = (const void *)pca_9545 },
+   { .compatible = "nxp,pca9546", .data = (const void *)pca_9546 },
+   { .compatible = "nxp,pca9547", .data = (const void *)pca_9547 },
+   { .compatible = "nxp,pca9548", .data = (const void *)pca_9548 },
+   {}
+};
+MODULE_DEVICE_TABLE(of, pca954x_of_match);
+
 static struct driver pca954x_driver = {
.name   = "pca954x",
.probe  = pca954x_probe,
+   .of_compatible  = DRV_OF_COMPAT(pca954x_dt_ids),
.id_table   = pca954x_id,
 };
 device_i2c_driver(pca954x_driver);

---
base-commit: cd2f24268402207a20467ddc41be9865a73ca4f8
change-id: 20231222-pca954x-of-dd6da5a25622




[PATCH 1/4] net: fec_imx: reverse registration order of mdiobus and edev

2023-12-21 Thread Alvin Šipraga
From: Alvin Šipraga 

This is necessary so that on systems with MDIO-connected Etheret
switches, DSA can find the master edev during switch registration.
Otherwise the switch setup will fail.

Signed-off-by: Alvin Šipraga 
---
 drivers/net/fec_imx.c | 10 +-
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/drivers/net/fec_imx.c b/drivers/net/fec_imx.c
index 203a2a8aa191..75a65962820b 100644
--- a/drivers/net/fec_imx.c
+++ b/drivers/net/fec_imx.c
@@ -895,18 +895,18 @@ static int fec_probe(struct device *dev)
fec->miibus.priv = fec;
fec->miibus.parent = dev;
 
-   ret = mdiobus_register(>miibus);
+   ret = eth_register(edev);
if (ret)
goto free_receive_packets;
 
-   ret = eth_register(edev);
+   ret = mdiobus_register(>miibus);
if (ret)
-   goto unregister_mdio;
+   goto unregister_eth;
 
return 0;
 
-unregister_mdio:
-   mdiobus_unregister(>miibus);
+unregister_eth:
+   eth_unregister(edev);
 free_receive_packets:
fec_free_receive_packets(fec, FEC_RBD_NUM, FEC_MAX_PKT_SIZE);
 free_xbd:

-- 
2.43.0




[PATCH 0/4] fix barebox support for MDIO-connected Realtek Ethernet switches

2023-12-21 Thread Alvin Šipraga
While bringing up a new board with an MDIO-connected RTL8365MB, I had to
make some changes to barebox to get network boot to work. This small
series addresses all of the problems I encountered along the way.

Signed-off-by: Alvin Šipraga 
---
Alvin Šipraga (4):
  net: fec_imx: reverse registration order of mdiobus and edev
  net: dsa: realtek: fix support for MDIO-connected switches
  net: dsa: realtek: unify ds_ops
  net: mdio_bus: associate OF nodes with their devices

 drivers/net/fec_imx.c  |  10 ++--
 drivers/net/phy/mdio_bus.c |   4 ++
 drivers/net/realtek-dsa/realtek-mdio.c | 105 +
 drivers/net/realtek-dsa/realtek-smi.c  |   2 +-
 drivers/net/realtek-dsa/realtek.h  |   3 +-
 drivers/net/realtek-dsa/rtl8365mb.c|  24 +---
 drivers/net/realtek-dsa/rtl8366rb.c|  23 +---
 7 files changed, 97 insertions(+), 74 deletions(-)
---
base-commit: 934cb2146e5b34eb45c81e3f9bc9b63c95701e43
change-id: 20231222-realtek-mdio-fix-2672b2ef4ae6




[PATCH 4/4] net: mdio_bus: associate OF nodes with their devices

2023-12-21 Thread Alvin Šipraga
From: Alvin Šipraga 

barebox deep-probe will walk the device tree to ensure dependent devices
have been probed. In so doing, it uses the device_node::dev pointer to
check whether a given node has a device; if not, a device is created on
demand. The behaviour is recursive, so parent nodes without an
associated device will also have devices created on their behalf. The
recursion stops when a parent with a device is found.

Weird behaviour can ensure if, when devices with a device_node are
registered, the device_node::dev field is not populated. This patch
addresses a niche, benign, but also noisy error observed as a result of
this behaviour.

One mostly harmless consequence is that spurious devices can get created
when a suitable one already exists. In my case, I have an MDIO-connected
Ethernet switch with an internal MDIO bus and some internal PHYs. With
deep-probe, but without these changes, the devinfo output looks as
follows:

  `-- 30be.ether...@30be.of
 `-- eth0
 `-- miibus0
`-- mdio0-dev1d
   `-- 0x-0x003f (  64 Bytes): /dev/mdio0-phy1d
   `-- 
30be.ethernet@30be:mdio:ethernet-switch@1d:ports:p...@6.of
   `-- 
30be.ethernet@30be:mdio:ethernet-switch@1d:ports:p...@0.of
  `-- eth1
   `-- 
30be.ethernet@30be:mdio:ethernet-switch@1d:ports:p...@1.of
  `-- eth2
   `-- 
30be.ethernet@30be:mdio:ethernet-switch@1d:ports:p...@2.of
  `-- eth3
   `-- 
30be.ethernet@30be:mdio:ethernet-switch@1d:ports:p...@3.of
  `-- eth4
   `-- miibus1
  `-- mdio1-phy00
 `-- 0x-0x003f (  64 Bytes): /dev/mdio1-phy00
  `-- mdio1-phy01
 `-- 0x-0x003f (  64 Bytes): /dev/mdio1-phy01
  `-- mdio1-phy02
 `-- 0x-0x003f (  64 Bytes): /dev/mdio1-phy02
  `-- mdio1-phy03
 `-- 0x-0x003f (  64 Bytes): /dev/mdio1-phy03
 `-- 30be.ethernet@30be:mdio.of
`-- 30be.ethernet@30be:mdio:ethernet-swi...@1d.of
   `-- 30be.ethernet@30be:mdio:ethernet-switch@1d:mdio.of

Notice the last three devices with generic names; they are spurious
creations of the deep-probe algorithm. In fact, the devices have already
been created:

  real devspurious dev
  
  miibus0 30be.ethernet@30be:mdio.of
  mdio0-devid1d   30be.ethernet@30be:mdio:ethernet-swi...@1d.of
  miibus1 30be.ethernet@30be:mdio:ethernet-switch@1d:mdio.of

The only reason there aren't even more spurious devices created is that
deep-probe stopped at 30be.ether...@30be.of, a platform device
whose device_node had its dev field populated correctly. But these
so-called real devices are all created by mdio_bus, which only links one
way, i.e. sets device::of_node, but not device_node::dev.

This issue probably goes unnoticed on most boards because, while the
call to of_device_ensure_probed() returns -ENODEV on the bottom listed
node, the code in phy.c doesn't check the return code, and the real
devices have already been probed, so no harm is done.

I observed much more surprising behaviour on my board because the switch
I am using, an RTL8365MB, has multiple possible management interfaces,
for which barebox has two drivers: realtek-smi and realtek-mdio (for
SMI- and MDIO-connected switches, respectively). The compatible strings
are the same, "realtek,rtl8365mb", but the bus types are different: the
former is a platform driver, the latter a phy (read: mdio) driver. In my
bootloader I have both drivers built in, because some of my boards use
SMI while others use MDIO.

When I would run the command 'boot bnet', bringing up my network
interface, DSA would call phy_device_connect() to connect my edev with
its corresponding phy, and a deep-probe would kick off because the phy's
parent's device_node::dev field was not populated. And during the
creation of the spurious device for my (already probed) Ethernet switch,
the platform code would find a compatible string match with realtek-smi
and try to probe the device with that driver:

  Booting entry 'bnet'
  ERROR: gpiolib: _gpio_request: gpio-233 
(30be.ethernet@30be:mdio:ethernet-swi...@1d.of-reset) status -16
  ERROR: realtek-smi 30be.ethernet@30be:mdio:ethernet-swi...@1d.of: 
error Device or resource busy: failed to get RESET GPIO
  ERROR: realtek-smi 30be.ethernet@30be:mdio:ethernet-swi...@1d.of: 
probe failed: Device or resource busy

As stated above, my switch is connected over MDIO, not SMI, so I really
should not be seeing any "realtek-smi" in my log. Nevertheless, because
phy.c doesn't check for errors, the errors are benign and my network
boot runs just fine.

Dumping the stack around the above error print in the realtek-smi driver
reveals exactly why things are going wrong:

  

[PATCH 3/4] net: dsa: realtek: unify ds_ops

2023-12-21 Thread Alvin Šipraga
From: Alvin Šipraga 

Now that neither interface driver requires .phy_read or .phy_write, the
ops are the same and some code can be deleted. No functional change.

Signed-off-by: Alvin Šipraga 
---
 drivers/net/realtek-dsa/realtek-mdio.c |  2 +-
 drivers/net/realtek-dsa/realtek-smi.c  |  2 +-
 drivers/net/realtek-dsa/realtek.h  |  3 +--
 drivers/net/realtek-dsa/rtl8365mb.c| 11 ++-
 drivers/net/realtek-dsa/rtl8366rb.c| 10 ++
 5 files changed, 7 insertions(+), 21 deletions(-)

diff --git a/drivers/net/realtek-dsa/realtek-mdio.c 
b/drivers/net/realtek-dsa/realtek-mdio.c
index 2b8661b95677..4fc2295b1b5f 100644
--- a/drivers/net/realtek-dsa/realtek-mdio.c
+++ b/drivers/net/realtek-dsa/realtek-mdio.c
@@ -236,7 +236,7 @@ static int realtek_mdio_probe(struct phy_device *mdiodev)
priv->ds->dev = dev;
priv->ds->num_ports = priv->num_ports;
priv->ds->priv = priv;
-   priv->ds->ops = var->ds_ops_mdio;
+   priv->ds->ops = var->ds_ops;
 
ret = realtek_dsa_init_tagger(priv);
if (ret)
diff --git a/drivers/net/realtek-dsa/realtek-smi.c 
b/drivers/net/realtek-dsa/realtek-smi.c
index f93024ace516..da150dbc5d8b 100644
--- a/drivers/net/realtek-dsa/realtek-smi.c
+++ b/drivers/net/realtek-dsa/realtek-smi.c
@@ -450,7 +450,7 @@ static int realtek_smi_probe(struct device *dev)
priv->ds->dev = dev;
priv->ds->num_ports = priv->num_ports;
priv->ds->priv = priv;
-   priv->ds->ops = var->ds_ops_smi;
+   priv->ds->ops = var->ds_ops;
 
ret = realtek_dsa_init_tagger(priv);
if (ret)
diff --git a/drivers/net/realtek-dsa/realtek.h 
b/drivers/net/realtek-dsa/realtek.h
index ac84b18cdd14..dbca9494627a 100644
--- a/drivers/net/realtek-dsa/realtek.h
+++ b/drivers/net/realtek-dsa/realtek.h
@@ -69,8 +69,7 @@ struct realtek_ops {
 };
 
 struct realtek_variant {
-   const struct dsa_switch_ops *ds_ops_smi;
-   const struct dsa_switch_ops *ds_ops_mdio;
+   const struct dsa_switch_ops *ds_ops;
const struct realtek_ops *ops;
unsigned int clk_delay;
u8 cmd_read;
diff --git a/drivers/net/realtek-dsa/rtl8365mb.c 
b/drivers/net/realtek-dsa/rtl8365mb.c
index 0f4c471715d1..588998235827 100644
--- a/drivers/net/realtek-dsa/rtl8365mb.c
+++ b/drivers/net/realtek-dsa/rtl8365mb.c
@@ -1225,13 +1225,7 @@ static int rtl8365mb_detect(struct realtek_priv *priv)
return 0;
 }
 
-static const struct dsa_switch_ops rtl8365mb_switch_ops_smi = {
-   .port_pre_enable = rtl8365mb_phylink_mac_config,
-   .port_disable = rtl8365mb_phylink_mac_link_down,
-   .port_enable = rtl8365mb_phylink_mac_link_up,
-};
-
-static const struct dsa_switch_ops rtl8365mb_switch_ops_mdio = {
+static const struct dsa_switch_ops rtl8365mb_switch_ops = {
.port_pre_enable = rtl8365mb_phylink_mac_config,
.port_disable = rtl8365mb_phylink_mac_link_down,
.port_enable = rtl8365mb_phylink_mac_link_up,
@@ -1247,8 +1241,7 @@ static const struct realtek_ops rtl8365mb_ops = {
 };
 
 const struct realtek_variant rtl8365mb_variant = {
-   .ds_ops_smi = _switch_ops_smi,
-   .ds_ops_mdio = _switch_ops_mdio,
+   .ds_ops = _switch_ops,
.ops = _ops,
.clk_delay = 10,
.cmd_read = 0xb9,
diff --git a/drivers/net/realtek-dsa/rtl8366rb.c 
b/drivers/net/realtek-dsa/rtl8366rb.c
index 6fd2b1852159..35028d319ecd 100644
--- a/drivers/net/realtek-dsa/rtl8366rb.c
+++ b/drivers/net/realtek-dsa/rtl8366rb.c
@@ -1079,12 +1079,7 @@ static int rtl8366rb_detect(struct realtek_priv *priv)
return rtl8366rb_reset_chip(priv);
 }
 
-static const struct dsa_switch_ops rtl8366rb_switch_ops_smi = {
-   .port_enable = rtl8366rb_port_enable,
-   .port_disable = rtl8366rb_port_disable,
-};
-
-static const struct dsa_switch_ops rtl8366rb_switch_ops_mdio = {
+static const struct dsa_switch_ops rtl8366rb_switch_ops = {
.port_enable = rtl8366rb_port_enable,
.port_disable = rtl8366rb_port_disable,
 };
@@ -1098,8 +1093,7 @@ static const struct realtek_ops rtl8366rb_ops = {
 };
 
 const struct realtek_variant rtl8366rb_variant = {
-   .ds_ops_smi = _switch_ops_smi,
-   .ds_ops_mdio = _switch_ops_mdio,
+   .ds_ops = _switch_ops,
.ops = _ops,
.clk_delay = 10,
.cmd_read = 0xa9,

-- 
2.43.0




[PATCH 2/4] net: dsa: realtek: fix support for MDIO-connected switches

2023-12-21 Thread Alvin Šipraga
From: Alvin Šipraga 

DSA offers drivers the option to have the core register an MDIO bus,
intended for platforms which do not have a specific OF node for the MDIO
bus or corresponding phy-handle properties on the switch port nodes.
This logic works OK, but is incidentally broken in barebox because the
dsa_switch::phys_mii_mask field is not being set. That means all reads
and writes to the internal PHYs are dropped before anything goes out on
the bus.

Notwithstanding that barebox issue, there is an ongoing discussion [1]
on the Linux mailing list as to the virtues (or lack thereof) of
realtek-mdio opting into this core functionality to begin with. The fact
is that, for SMI-connected switches, realtek-smi absolutely expects an
MDIO bus node. And the device tree bindings strongly (albeit not
strictly) assert that this node for both MDIO and SMI connected
switches. In the specific case of barebox, the driver likely has even
fewer users, and realtek-mdio is currently broken, so there is nothing
to break by strictly enforcing the presence of an MDIO node.

The same discussion [1] centers around an effort to actually unify
large, common parts of the SMI and MDIO drivers, and ditching the
asymmetric MDIO bus registration would make this effort even easier.

To that end, add a little bit more code in order to bury this particular
issue once and for all in barebox. Further cleanup can be done to reduce
the overall quantity of code, probably following whatever ends up in
Linux.

A slice dependency is also added to the parent MDIO bus to prevent the
PHY status polling from interleaving MDIO accesses during switch
management.

Link: https://lore.kernel.org/all/20231221174746.hylsmr3f7g5byrsi@skbuf/ [1]
Fixes: f9f31a9a21e4 ("net: dsa: add Realtek (rtl8365mb/rtl8366rb) switch 
support")
Signed-off-by: Alvin Šipraga 
---
 drivers/net/realtek-dsa/realtek-mdio.c | 103 ++---
 drivers/net/realtek-dsa/rtl8365mb.c|  13 -
 drivers/net/realtek-dsa/rtl8366rb.c|  13 -
 3 files changed, 81 insertions(+), 48 deletions(-)

diff --git a/drivers/net/realtek-dsa/realtek-mdio.c 
b/drivers/net/realtek-dsa/realtek-mdio.c
index 463757711198..2b8661b95677 100644
--- a/drivers/net/realtek-dsa/realtek-mdio.c
+++ b/drivers/net/realtek-dsa/realtek-mdio.c
@@ -47,22 +47,27 @@ static int realtek_mdio_write(void *ctx, u32 reg, u32 val)
struct mii_bus *bus = priv->bus;
int ret;
 
-   ret = bus->write(bus, priv->mdio_addr, REALTEK_MDIO_CTRL0_REG, 
REALTEK_MDIO_ADDR_OP);
+   ret = mdiobus_write(bus, priv->mdio_addr, REALTEK_MDIO_CTRL0_REG,
+   REALTEK_MDIO_ADDR_OP);
if (ret)
-   goto out_unlock;
+   return ret;
 
-   ret = bus->write(bus, priv->mdio_addr, REALTEK_MDIO_ADDRESS_REG, reg);
+   ret = mdiobus_write(bus, priv->mdio_addr, REALTEK_MDIO_ADDRESS_REG,
+   reg);
if (ret)
-   goto out_unlock;
+   return ret;
 
-   ret = bus->write(bus, priv->mdio_addr, REALTEK_MDIO_DATA_WRITE_REG, 
val);
+   ret = mdiobus_write(bus, priv->mdio_addr, REALTEK_MDIO_DATA_WRITE_REG,
+   val);
if (ret)
-   goto out_unlock;
+   return ret;
 
-   ret = bus->write(bus, priv->mdio_addr, REALTEK_MDIO_CTRL1_REG, 
REALTEK_MDIO_WRITE_OP);
+   ret = mdiobus_write(bus, priv->mdio_addr, REALTEK_MDIO_CTRL1_REG,
+   REALTEK_MDIO_WRITE_OP);
+   if (ret)
+   return ret;
 
-out_unlock:
-   return ret;
+   return 0;
 }
 
 static int realtek_mdio_read(void *ctx, u32 reg, u32 *val)
@@ -71,26 +76,43 @@ static int realtek_mdio_read(void *ctx, u32 reg, u32 *val)
struct mii_bus *bus = priv->bus;
int ret;
 
-   ret = bus->write(bus, priv->mdio_addr, REALTEK_MDIO_CTRL0_REG, 
REALTEK_MDIO_ADDR_OP);
+   ret = mdiobus_write(bus, priv->mdio_addr, REALTEK_MDIO_CTRL0_REG,
+   REALTEK_MDIO_ADDR_OP);
if (ret)
-   goto out_unlock;
+   return ret;
 
-   ret = bus->write(bus, priv->mdio_addr, REALTEK_MDIO_ADDRESS_REG, reg);
+   ret = mdiobus_write(bus, priv->mdio_addr, REALTEK_MDIO_ADDRESS_REG,
+   reg);
if (ret)
-   goto out_unlock;
+   return ret;
 
-   ret = bus->write(bus, priv->mdio_addr, REALTEK_MDIO_CTRL1_REG, 
REALTEK_MDIO_READ_OP);
+   ret = mdiobus_write(bus, priv->mdio_addr, REALTEK_MDIO_CTRL1_REG,
+   REALTEK_MDIO_READ_OP);
if (ret)
-   goto out_unlock;
+   return ret;
 
-   ret = bus->read(bus, priv->mdio_addr, REALTEK_MDIO_DATA_READ_REG);
-   if (ret >= 0) {
-   *val = ret;
-   ret = 0;
-   }
+   ret = mdiobus_read(bus, priv->mdio_addr, REALTEK_MDIO_DATA_READ_REG);
+   if (ret < 0)
+   return ret;
 
-out_unlock:
-   return 

Re: [PATCH v2] nvmem: regmap: Fix nvmem size

2023-12-21 Thread Ahmad Fatoum
On 20.12.23 13:38, Robin van der Gracht wrote:
> Hi Ahmad,
> 
> On 2023-12-20 10:00, Ahmad Fatoum wrote:
>> Hello Robin,
>>
>> Thanks for the fix.
>>
>> On 20.12.23 09:29, Robin van der Gracht wrote:
>>> -    if (roffset + rbytes > stride * regmap_get_max_register(map))
>>> +    if (roffset + rbytes > regmap_size_bytes(map) * stride)
>>
>> Shouldn't stride on the right hand side be dropped?
> 
> roffset = register index * stride.
> 
> I.e. 380 for register with index 95.
> 
> For stm32mp1x bsec:
>  map->format.val_bytes = 4
>  map->reg_stride = 4
> 
> regmap_size_bytes() = map->format.val_bytes * (95 + 1) / map->reg_stride = 96

Ouch. What have I been thinking when I named regmap_size_bytes() this way...

Change looks ok then, but we should really rename regmap_size_bytes()...

> 
> So the result with the stride on the right size is correct.
> 
> I moved stride from left to right to be consistent with the size calculation
> in nvmem_regmap_register_with_pp()
> 
> Kind regards,
> Robin
> 
> 
>>
>> Cheers,
>> Ahmad
>>
>>>  return -EINVAL;
>>>
>>>  for (i = roffset; i < roffset + rbytes; i += stride) {
>>> @@ -78,7 +78,7 @@ nvmem_regmap_register_with_pp(struct regmap *map, const 
>>> char *name,
>>>  config.priv = map;
>>>  config.stride = 1;
>>>  config.word_size = 1;
>>> -    config.size = regmap_get_max_register(map) * 
>>> regmap_get_reg_stride(map);
>>> +    config.size = regmap_size_bytes(map) * regmap_get_reg_stride(map);
>>>  config.cell_post_process = cell_post_process;
>>>  config.reg_write = nvmem_regmap_write;
>>>  config.reg_read = nvmem_regmap_read;
> 

-- 
Pengutronix e.K.   | |
Steuerwalder Str. 21   | http://www.pengutronix.de/  |
31137 Hildesheim, Germany  | Phone: +49-5121-206917-0|
Amtsgericht Hildesheim, HRA 2686   | Fax:   +49-5121-206917- |