2022-12-27 23:15:51

by Michael Walle

[permalink] [raw]
Subject: [PATCH RFC net-next v2 00/12] net: mdio: Start separating C22 and C45

I've picked this older series from Andrew up and rebased it onto
v6.2-rc1.

This patch set starts the separation of C22 and C45 MDIO bus
transactions at the API level to the MDIO Bus drivers. C45 read and
write ops are added to the MDIO bus driver structure, and the MDIO
core will try to use these ops if requested to perform a C45
transfer. If not available a fallback to the older API is made, to
allow backwards compatibility until all drivers are converted.

A few drivers are then converted to this new API.

Link to v1: https://lore.kernel.org/netdev/[email protected]/

To: Heiner Kallweit <[email protected]>
To: Russell King <[email protected]>
To: "David S. Miller" <[email protected]>
To: Eric Dumazet <[email protected]>
To: Jakub Kicinski <[email protected]>
To: Paolo Abeni <[email protected]>
To: Jose Abreu <[email protected]>
To: Sergey Shtylyov <[email protected]>
To: Wei Fang <[email protected]>
To: Shenwei Wang <[email protected]>
To: Clark Wang <[email protected]>
To: NXP Linux Team <[email protected]>
To: Sean Wang <[email protected]>
To: Landen Chao <[email protected]>
To: DENG Qingfang <[email protected]>
To: Florian Fainelli <[email protected]>
To: Vladimir Oltean <[email protected]>
To: Matthias Brugger <[email protected]>
Cc: [email protected]
Cc: [email protected]
Cc: [email protected]
Cc: [email protected]
Cc: [email protected]
Cc: Andrew Lunn <[email protected]>
Cc: Geert Uytterhoeven <[email protected]>

---
Andrew Lunn (12):
net: mdio: Add dedicated C45 API to MDIO bus drivers
net: pcs: pcs-xpcs: Use C45 MDIO API
net: mdio: mdiobus_register: update validation test
net: mdio: C22 is now optional, EOPNOTSUPP if not provided
net: mdio: Move mdiobus_c45_addr() next to users
net: mdio: mdio-bitbang: Separate C22 and C45 transactions
net: mdio: mvmdio: Convert XSMI bus to new API
net: ethernet: freescale: xgmac: Separate C22 and C45 transactions for xgmac
net: ethernet: freescale: fec: Separate C22 and C45 transactions for xgmac
net: mdio: add mdiobus_c45_read/write_nested helpers
net: dsa: Separate C22 and C45 MDIO bus transaction methods
net: dsa: mv88e6xxx: Separate C22 and C45 transactions

drivers/net/dsa/mt7530.c | 87 ++++-----
drivers/net/dsa/mt7530.h | 15 +-
drivers/net/dsa/mv88e6xxx/chip.c | 175 +++++++++++++-----
drivers/net/dsa/mv88e6xxx/chip.h | 7 +
drivers/net/dsa/mv88e6xxx/global2.c | 66 ++++---
drivers/net/dsa/mv88e6xxx/global2.h | 18 +-
drivers/net/dsa/mv88e6xxx/phy.c | 32 ++++
drivers/net/dsa/mv88e6xxx/phy.h | 4 +
drivers/net/dsa/mv88e6xxx/serdes.c | 8 +-
drivers/net/ethernet/freescale/fec_main.c | 153 +++++++++++-----
drivers/net/ethernet/freescale/xgmac_mdio.c | 150 +++++++++++----
drivers/net/ethernet/marvell/mvmdio.c | 24 +--
drivers/net/ethernet/renesas/sh_eth.c | 37 +++-
drivers/net/mdio/mdio-bitbang.c | 77 +++++---
drivers/net/pcs/pcs-xpcs.c | 4 +-
drivers/net/phy/mdio_bus.c | 273 +++++++++++++++++++++++++++-
include/linux/mdio-bitbang.h | 6 +-
include/linux/mdio.h | 48 ++---
include/linux/phy.h | 5 +
include/net/dsa.h | 2 +-
20 files changed, 891 insertions(+), 300 deletions(-)
---
base-commit: 1b929c02afd37871d5afb9d498426f83432e71c2
change-id: 20221227-v6-2-rc1-c45-seperation-53f762440aa1

Best regards,
--
Michael Walle <[email protected]>


2022-12-27 23:19:29

by Michael Walle

[permalink] [raw]
Subject: [PATCH RFC net-next v2 04/12] net: mdio: C22 is now optional, EOPNOTSUPP if not provided

From: Andrew Lunn <[email protected]>

When performing a C22 operation, check that the bus driver actually
provides the methods, and return -EOPNOTSUPP if not. C45 only busses
do exist, and in future their C22 methods will be NULL.

Signed-off-by: Andrew Lunn <[email protected]>
Signed-off-by: Michael Walle <[email protected]>
---
drivers/net/phy/mdio_bus.c | 10 ++++++++--
1 file changed, 8 insertions(+), 2 deletions(-)

diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c
index d14d7704e895..20ba38a346fe 100644
--- a/drivers/net/phy/mdio_bus.c
+++ b/drivers/net/phy/mdio_bus.c
@@ -769,7 +769,10 @@ int __mdiobus_read(struct mii_bus *bus, int addr, u32 regnum)

lockdep_assert_held_once(&bus->mdio_lock);

- retval = bus->read(bus, addr, regnum);
+ if (bus->read)
+ retval = bus->read(bus, addr, regnum);
+ else
+ retval = -EOPNOTSUPP;

trace_mdio_access(bus, 1, addr, regnum, retval, retval);
mdiobus_stats_acct(&bus->stats[addr], true, retval);
@@ -795,7 +798,10 @@ int __mdiobus_write(struct mii_bus *bus, int addr, u32 regnum, u16 val)

lockdep_assert_held_once(&bus->mdio_lock);

- err = bus->write(bus, addr, regnum, val);
+ if (bus->write)
+ err = bus->write(bus, addr, regnum, val);
+ else
+ err = -EOPNOTSUPP;

trace_mdio_access(bus, 0, addr, regnum, val, err);
mdiobus_stats_acct(&bus->stats[addr], false, err);

--
2.30.2

2022-12-27 23:23:13

by Michael Walle

[permalink] [raw]
Subject: [PATCH RFC net-next v2 08/12] net: ethernet: freescale: xgmac: Separate C22 and C45 transactions for xgmac

From: Andrew Lunn <[email protected]>

The xgmac MDIO bus driver can perform both C22 and C45 transfers.
Create separate functions for each and register the C45 versions using
the new API calls where appropriate.

Signed-off-by: Andrew Lunn <[email protected]>
Signed-off-by: Michael Walle <[email protected]>
---
v2:
- [al] Move the masking of regnum into the variable declarations
- [al] Remove a couple of blank lines
---
drivers/net/ethernet/freescale/xgmac_mdio.c | 150 +++++++++++++++++++++-------
1 file changed, 113 insertions(+), 37 deletions(-)

diff --git a/drivers/net/ethernet/freescale/xgmac_mdio.c b/drivers/net/ethernet/freescale/xgmac_mdio.c
index d7d39a58cd80..1861cf14f4d7 100644
--- a/drivers/net/ethernet/freescale/xgmac_mdio.c
+++ b/drivers/net/ethernet/freescale/xgmac_mdio.c
@@ -128,30 +128,57 @@ static int xgmac_wait_until_done(struct device *dev,
return 0;
}

-/*
- * Write value to the PHY for this device to the register at regnum,waiting
+/* Write value to the PHY for this device to the register at regnum,waiting
* until the write is done before it returns. All PHY configuration has to be
* done through the TSEC1 MIIM regs.
*/
-static int xgmac_mdio_write(struct mii_bus *bus, int phy_id, int regnum, u16 value)
+static int xgmac_mdio_write_c22(struct mii_bus *bus, int phy_id, int regnum,
+ u16 value)
{
struct mdio_fsl_priv *priv = (struct mdio_fsl_priv *)bus->priv;
struct tgec_mdio_controller __iomem *regs = priv->mdio_base;
- uint16_t dev_addr;
+ bool endian = priv->is_little_endian;
+ u16 dev_addr = regnum & 0x1f;
u32 mdio_ctl, mdio_stat;
int ret;
+
+ mdio_stat = xgmac_read32(&regs->mdio_stat, endian);
+ mdio_stat &= ~MDIO_STAT_ENC;
+ xgmac_write32(mdio_stat, &regs->mdio_stat, endian);
+
+ ret = xgmac_wait_until_free(&bus->dev, regs, endian);
+ if (ret)
+ return ret;
+
+ /* Set the port and dev addr */
+ mdio_ctl = MDIO_CTL_PORT_ADDR(phy_id) | MDIO_CTL_DEV_ADDR(dev_addr);
+ xgmac_write32(mdio_ctl, &regs->mdio_ctl, endian);
+
+ /* Write the value to the register */
+ xgmac_write32(MDIO_DATA(value), &regs->mdio_data, endian);
+
+ ret = xgmac_wait_until_done(&bus->dev, regs, endian);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+/* Write value to the PHY for this device to the register at regnum,waiting
+ * until the write is done before it returns. All PHY configuration has to be
+ * done through the TSEC1 MIIM regs.
+ */
+static int xgmac_mdio_write_c45(struct mii_bus *bus, int phy_id, int dev_addr,
+ int regnum, u16 value)
+{
+ struct mdio_fsl_priv *priv = (struct mdio_fsl_priv *)bus->priv;
+ struct tgec_mdio_controller __iomem *regs = priv->mdio_base;
bool endian = priv->is_little_endian;
+ u32 mdio_ctl, mdio_stat;
+ int ret;

mdio_stat = xgmac_read32(&regs->mdio_stat, endian);
- if (regnum & MII_ADDR_C45) {
- /* Clause 45 (ie 10G) */
- dev_addr = (regnum >> 16) & 0x1f;
- mdio_stat |= MDIO_STAT_ENC;
- } else {
- /* Clause 22 (ie 1G) */
- dev_addr = regnum & 0x1f;
- mdio_stat &= ~MDIO_STAT_ENC;
- }
+ mdio_stat |= MDIO_STAT_ENC;

xgmac_write32(mdio_stat, &regs->mdio_stat, endian);

@@ -164,13 +191,11 @@ static int xgmac_mdio_write(struct mii_bus *bus, int phy_id, int regnum, u16 val
xgmac_write32(mdio_ctl, &regs->mdio_ctl, endian);

/* Set the register address */
- if (regnum & MII_ADDR_C45) {
- xgmac_write32(regnum & 0xffff, &regs->mdio_addr, endian);
+ xgmac_write32(regnum & 0xffff, &regs->mdio_addr, endian);

- ret = xgmac_wait_until_free(&bus->dev, regs, endian);
- if (ret)
- return ret;
- }
+ ret = xgmac_wait_until_free(&bus->dev, regs, endian);
+ if (ret)
+ return ret;

/* Write the value to the register */
xgmac_write32(MDIO_DATA(value), &regs->mdio_data, endian);
@@ -182,31 +207,82 @@ static int xgmac_mdio_write(struct mii_bus *bus, int phy_id, int regnum, u16 val
return 0;
}

-/*
- * Reads from register regnum in the PHY for device dev, returning the value.
+/* Reads from register regnum in the PHY for device dev, returning the value.
* Clears miimcom first. All PHY configuration has to be done through the
* TSEC1 MIIM regs.
*/
-static int xgmac_mdio_read(struct mii_bus *bus, int phy_id, int regnum)
+static int xgmac_mdio_read_c22(struct mii_bus *bus, int phy_id, int regnum)
{
struct mdio_fsl_priv *priv = (struct mdio_fsl_priv *)bus->priv;
struct tgec_mdio_controller __iomem *regs = priv->mdio_base;
+ bool endian = priv->is_little_endian;
+ u16 dev_addr = regnum & 0x1f;
unsigned long flags;
- uint16_t dev_addr;
uint32_t mdio_stat;
uint32_t mdio_ctl;
int ret;
- bool endian = priv->is_little_endian;

mdio_stat = xgmac_read32(&regs->mdio_stat, endian);
- if (regnum & MII_ADDR_C45) {
- dev_addr = (regnum >> 16) & 0x1f;
- mdio_stat |= MDIO_STAT_ENC;
+ mdio_stat &= ~MDIO_STAT_ENC;
+ xgmac_write32(mdio_stat, &regs->mdio_stat, endian);
+
+ ret = xgmac_wait_until_free(&bus->dev, regs, endian);
+ if (ret)
+ return ret;
+
+ /* Set the Port and Device Addrs */
+ mdio_ctl = MDIO_CTL_PORT_ADDR(phy_id) | MDIO_CTL_DEV_ADDR(dev_addr);
+ xgmac_write32(mdio_ctl, &regs->mdio_ctl, endian);
+
+ if (priv->has_a009885)
+ /* Once the operation completes, i.e. MDIO_STAT_BSY clears, we
+ * must read back the data register within 16 MDC cycles.
+ */
+ local_irq_save(flags);
+
+ /* Initiate the read */
+ xgmac_write32(mdio_ctl | MDIO_CTL_READ, &regs->mdio_ctl, endian);
+
+ ret = xgmac_wait_until_done(&bus->dev, regs, endian);
+ if (ret)
+ goto irq_restore;
+
+ /* Return all Fs if nothing was there */
+ if ((xgmac_read32(&regs->mdio_stat, endian) & MDIO_STAT_RD_ER) &&
+ !priv->has_a011043) {
+ dev_dbg(&bus->dev,
+ "Error while reading PHY%d reg at %d.%d\n",
+ phy_id, dev_addr, regnum);
+ ret = 0xffff;
} else {
- dev_addr = regnum & 0x1f;
- mdio_stat &= ~MDIO_STAT_ENC;
+ ret = xgmac_read32(&regs->mdio_data, endian) & 0xffff;
+ dev_dbg(&bus->dev, "read %04x\n", ret);
}

+irq_restore:
+ if (priv->has_a009885)
+ local_irq_restore(flags);
+
+ return ret;
+}
+
+/* Reads from register regnum in the PHY for device dev, returning the value.
+ * Clears miimcom first. All PHY configuration has to be done through the
+ * TSEC1 MIIM regs.
+ */
+static int xgmac_mdio_read_c45(struct mii_bus *bus, int phy_id, int dev_addr,
+ int regnum)
+{
+ struct mdio_fsl_priv *priv = (struct mdio_fsl_priv *)bus->priv;
+ struct tgec_mdio_controller __iomem *regs = priv->mdio_base;
+ bool endian = priv->is_little_endian;
+ u32 mdio_stat, mdio_ctl;
+ unsigned long flags;
+ int ret;
+
+ mdio_stat = xgmac_read32(&regs->mdio_stat, endian);
+ mdio_stat |= MDIO_STAT_ENC;
+
xgmac_write32(mdio_stat, &regs->mdio_stat, endian);

ret = xgmac_wait_until_free(&bus->dev, regs, endian);
@@ -218,13 +294,11 @@ static int xgmac_mdio_read(struct mii_bus *bus, int phy_id, int regnum)
xgmac_write32(mdio_ctl, &regs->mdio_ctl, endian);

/* Set the register address */
- if (regnum & MII_ADDR_C45) {
- xgmac_write32(regnum & 0xffff, &regs->mdio_addr, endian);
+ xgmac_write32(regnum & 0xffff, &regs->mdio_addr, endian);

- ret = xgmac_wait_until_free(&bus->dev, regs, endian);
- if (ret)
- return ret;
- }
+ ret = xgmac_wait_until_free(&bus->dev, regs, endian);
+ if (ret)
+ return ret;

if (priv->has_a009885)
/* Once the operation completes, i.e. MDIO_STAT_BSY clears, we
@@ -326,8 +400,10 @@ static int xgmac_mdio_probe(struct platform_device *pdev)
return -ENOMEM;

bus->name = "Freescale XGMAC MDIO Bus";
- bus->read = xgmac_mdio_read;
- bus->write = xgmac_mdio_write;
+ bus->read = xgmac_mdio_read_c22;
+ bus->write = xgmac_mdio_write_c22;
+ bus->read_c45 = xgmac_mdio_read_c45;
+ bus->write_c45 = xgmac_mdio_write_c45;
bus->parent = &pdev->dev;
bus->probe_capabilities = MDIOBUS_C22_C45;
snprintf(bus->id, MII_BUS_ID_SIZE, "%pa", &res->start);

--
2.30.2

2022-12-27 23:32:04

by Michael Walle

[permalink] [raw]
Subject: [PATCH RFC net-next v2 11/12] net: dsa: Separate C22 and C45 MDIO bus transaction methods

From: Andrew Lunn <[email protected]>

By adding _c45 function pointers to the dsa_switch_op structure, the
dsa core can register an MDIO bus with C45 accessors.

The dsa-loop driver could in theory provide such accessors, since it
just passed requests to the MDIO bus it is on, but it seems unlikely
to be useful at the moment. It can however be added later.

mt7530 does support C45, but its uses a mix of registering its MDIO
bus and using the DSA core provided bus. This makes the change a bit
more complex.

Signed-off-by: Andrew Lunn <[email protected]>
Signed-off-by: Michael Walle <[email protected]>
---
v2:
- [al] Remove conditional c45, since all switches support c45
- [al] Remove dsa core changes, they are not needed
- [al] Add comment that DSA provided MDIO bus is C22 only.
---
drivers/net/dsa/mt7530.c | 87 ++++++++++++++++++++++++------------------------
drivers/net/dsa/mt7530.h | 15 ++++++---
include/net/dsa.h | 2 +-
3 files changed, 56 insertions(+), 48 deletions(-)

diff --git a/drivers/net/dsa/mt7530.c b/drivers/net/dsa/mt7530.c
index 908fa89444c9..616b21c90d05 100644
--- a/drivers/net/dsa/mt7530.c
+++ b/drivers/net/dsa/mt7530.c
@@ -608,17 +608,29 @@ mt7530_mib_reset(struct dsa_switch *ds)
mt7530_write(priv, MT7530_MIB_CCR, CCR_MIB_ACTIVATE);
}

-static int mt7530_phy_read(struct mt7530_priv *priv, int port, int regnum)
+static int mt7530_phy_read_c22(struct mt7530_priv *priv, int port, int regnum)
{
return mdiobus_read_nested(priv->bus, port, regnum);
}

-static int mt7530_phy_write(struct mt7530_priv *priv, int port, int regnum,
- u16 val)
+static int mt7530_phy_write_c22(struct mt7530_priv *priv, int port, int regnum,
+ u16 val)
{
return mdiobus_write_nested(priv->bus, port, regnum, val);
}

+static int mt7530_phy_read_c45(struct mt7530_priv *priv, int port,
+ int devad, int regnum)
+{
+ return mdiobus_c45_read_nested(priv->bus, port, devad, regnum);
+}
+
+static int mt7530_phy_write_c45(struct mt7530_priv *priv, int port, int devad,
+ int regnum, u16 val)
+{
+ return mdiobus_c45_write_nested(priv->bus, port, devad, regnum, val);
+}
+
static int
mt7531_ind_c45_phy_read(struct mt7530_priv *priv, int port, int devad,
int regnum)
@@ -670,7 +682,7 @@ mt7531_ind_c45_phy_read(struct mt7530_priv *priv, int port, int devad,

static int
mt7531_ind_c45_phy_write(struct mt7530_priv *priv, int port, int devad,
- int regnum, u32 data)
+ int regnum, u16 data)
{
struct mii_bus *bus = priv->bus;
struct mt7530_dummy_poll p;
@@ -793,55 +805,36 @@ mt7531_ind_c22_phy_write(struct mt7530_priv *priv, int port, int regnum,
}

static int
-mt7531_ind_phy_read(struct mt7530_priv *priv, int port, int regnum)
+mt753x_phy_read_c22(struct mii_bus *bus, int port, int regnum)
{
- int devad;
- int ret;
-
- if (regnum & MII_ADDR_C45) {
- devad = (regnum >> MII_DEVADDR_C45_SHIFT) & 0x1f;
- ret = mt7531_ind_c45_phy_read(priv, port, devad,
- regnum & MII_REGADDR_C45_MASK);
- } else {
- ret = mt7531_ind_c22_phy_read(priv, port, regnum);
- }
+ struct mt7530_priv *priv = bus->priv;

- return ret;
+ return priv->info->phy_read_c22(priv, port, regnum);
}

static int
-mt7531_ind_phy_write(struct mt7530_priv *priv, int port, int regnum,
- u16 data)
+mt753x_phy_read_c45(struct mii_bus *bus, int port, int devad, int regnum)
{
- int devad;
- int ret;
-
- if (regnum & MII_ADDR_C45) {
- devad = (regnum >> MII_DEVADDR_C45_SHIFT) & 0x1f;
- ret = mt7531_ind_c45_phy_write(priv, port, devad,
- regnum & MII_REGADDR_C45_MASK,
- data);
- } else {
- ret = mt7531_ind_c22_phy_write(priv, port, regnum, data);
- }
+ struct mt7530_priv *priv = bus->priv;

- return ret;
+ return priv->info->phy_read_c45(priv, port, devad, regnum);
}

static int
-mt753x_phy_read(struct mii_bus *bus, int port, int regnum)
+mt753x_phy_write_c22(struct mii_bus *bus, int port, int regnum, u16 val)
{
struct mt7530_priv *priv = bus->priv;

- return priv->info->phy_read(priv, port, regnum);
+ return priv->info->phy_write_c22(priv, port, regnum, val);
}

static int
-mt753x_phy_write(struct mii_bus *bus, int port, int regnum, u16 val)
+mt753x_phy_write_c45(struct mii_bus *bus, int port, int devad, int regnum,
+ u16 val)
{
struct mt7530_priv *priv = bus->priv;

- return priv->info->phy_write(priv, port, regnum, val);
+ return priv->info->phy_write_c45(priv, port, devad, regnum, val);
}

static void
@@ -2086,8 +2079,10 @@ mt7530_setup_mdio(struct mt7530_priv *priv)
bus->priv = priv;
bus->name = KBUILD_MODNAME "-mii";
snprintf(bus->id, MII_BUS_ID_SIZE, KBUILD_MODNAME "-%d", idx++);
- bus->read = mt753x_phy_read;
- bus->write = mt753x_phy_write;
+ bus->read = mt753x_phy_read_c22;
+ bus->write = mt753x_phy_write_c22;
+ bus->read_c45 = mt753x_phy_read_c45;
+ bus->write_c45 = mt753x_phy_write_c45;
bus->parent = dev;
bus->phy_mask = ~ds->phys_mii_mask;

@@ -3182,8 +3177,10 @@ static const struct mt753x_info mt753x_table[] = {
.id = ID_MT7621,
.pcs_ops = &mt7530_pcs_ops,
.sw_setup = mt7530_setup,
- .phy_read = mt7530_phy_read,
- .phy_write = mt7530_phy_write,
+ .phy_read_c22 = mt7530_phy_read_c22,
+ .phy_write_c22 = mt7530_phy_write_c22,
+ .phy_read_c45 = mt7530_phy_read_c45,
+ .phy_write_c45 = mt7530_phy_write_c45,
.pad_setup = mt7530_pad_clk_setup,
.mac_port_get_caps = mt7530_mac_port_get_caps,
.mac_port_config = mt7530_mac_config,
@@ -3192,8 +3189,10 @@ static const struct mt753x_info mt753x_table[] = {
.id = ID_MT7530,
.pcs_ops = &mt7530_pcs_ops,
.sw_setup = mt7530_setup,
- .phy_read = mt7530_phy_read,
- .phy_write = mt7530_phy_write,
+ .phy_read_c22 = mt7530_phy_read_c22,
+ .phy_write_c22 = mt7530_phy_write_c22,
+ .phy_read_c45 = mt7530_phy_read_c45,
+ .phy_write_c45 = mt7530_phy_write_c45,
.pad_setup = mt7530_pad_clk_setup,
.mac_port_get_caps = mt7530_mac_port_get_caps,
.mac_port_config = mt7530_mac_config,
@@ -3202,8 +3201,10 @@ static const struct mt753x_info mt753x_table[] = {
.id = ID_MT7531,
.pcs_ops = &mt7531_pcs_ops,
.sw_setup = mt7531_setup,
- .phy_read = mt7531_ind_phy_read,
- .phy_write = mt7531_ind_phy_write,
+ .phy_read_c22 = mt7531_ind_c22_phy_read,
+ .phy_write_c22 = mt7531_ind_c22_phy_write,
+ .phy_read_c45 = mt7531_ind_c45_phy_read,
+ .phy_write_c45 = mt7531_ind_c45_phy_write,
.pad_setup = mt7531_pad_setup,
.cpu_port_config = mt7531_cpu_port_config,
.mac_port_get_caps = mt7531_mac_port_get_caps,
@@ -3263,7 +3264,7 @@ mt7530_probe(struct mdio_device *mdiodev)
* properly.
*/
if (!priv->info->sw_setup || !priv->info->pad_setup ||
- !priv->info->phy_read || !priv->info->phy_write ||
+ !priv->info->phy_read_c22 || !priv->info->phy_write_c22 ||
!priv->info->mac_port_get_caps ||
!priv->info->mac_port_config)
return -EINVAL;
diff --git a/drivers/net/dsa/mt7530.h b/drivers/net/dsa/mt7530.h
index e8d966435350..6b2fc6290ea8 100644
--- a/drivers/net/dsa/mt7530.h
+++ b/drivers/net/dsa/mt7530.h
@@ -750,8 +750,10 @@ struct mt753x_pcs {
/* struct mt753x_info - This is the main data structure for holding the specific
* part for each supported device
* @sw_setup: Holding the handler to a device initialization
- * @phy_read: Holding the way reading PHY port
- * @phy_write: Holding the way writing PHY port
+ * @phy_read_c22: Holding the way reading PHY port using C22
+ * @phy_write_c22: Holding the way writing PHY port using C22
+ * @phy_read_c45: Holding the way reading PHY port using C45
+ * @phy_write_c45: Holding the way writing PHY port using C45
* @pad_setup: Holding the way setting up the bus pad for a certain
* MAC port
* @phy_mode_supported: Check if the PHY type is being supported on a certain
@@ -767,8 +769,13 @@ struct mt753x_info {
const struct phylink_pcs_ops *pcs_ops;

int (*sw_setup)(struct dsa_switch *ds);
- int (*phy_read)(struct mt7530_priv *priv, int port, int regnum);
- int (*phy_write)(struct mt7530_priv *priv, int port, int regnum, u16 val);
+ int (*phy_read_c22)(struct mt7530_priv *priv, int port, int regnum);
+ int (*phy_write_c22)(struct mt7530_priv *priv, int port, int regnum,
+ u16 val);
+ int (*phy_read_c45)(struct mt7530_priv *priv, int port, int devad,
+ int regnum);
+ int (*phy_write_c45)(struct mt7530_priv *priv, int port, int devad,
+ int regnum, u16 val);
int (*pad_setup)(struct dsa_switch *ds, phy_interface_t interface);
int (*cpu_port_config)(struct dsa_switch *ds, int port);
void (*mac_port_get_caps)(struct dsa_switch *ds, int port,
diff --git a/include/net/dsa.h b/include/net/dsa.h
index 96086289aa9b..732c7bc261a9 100644
--- a/include/net/dsa.h
+++ b/include/net/dsa.h
@@ -858,7 +858,7 @@ struct dsa_switch_ops {
u32 (*get_phy_flags)(struct dsa_switch *ds, int port);

/*
- * Access to the switch's PHY registers.
+ * Access to the switch's PHY registers. C22 only.
*/
int (*phy_read)(struct dsa_switch *ds, int port, int regnum);
int (*phy_write)(struct dsa_switch *ds, int port,

--
2.30.2

2022-12-27 23:32:04

by Michael Walle

[permalink] [raw]
Subject: [PATCH RFC net-next v2 03/12] net: mdio: mdiobus_register: update validation test

From: Andrew Lunn <[email protected]>

Now that C45 uses its own read/write methods, the validation performed
when a bus is registers needs updating. All combinations of C22 and
C45 are supported, but both read and write methods must be provided,
read only busses are not supported etc.

Signed-off-by: Andrew Lunn <[email protected]>
Signed-off-by: Michael Walle <[email protected]>
---
v2:
- [al] be consistent with other checks
- [mw] make the test a bit easier to read
---
drivers/net/phy/mdio_bus.c | 14 ++++++++++++--
1 file changed, 12 insertions(+), 2 deletions(-)

diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c
index bde195864c17..d14d7704e895 100644
--- a/drivers/net/phy/mdio_bus.c
+++ b/drivers/net/phy/mdio_bus.c
@@ -526,8 +526,18 @@ int __mdiobus_register(struct mii_bus *bus, struct module *owner)
int i, err;
struct gpio_desc *gpiod;

- if (NULL == bus || NULL == bus->name ||
- NULL == bus->read || NULL == bus->write)
+ if (!bus || !bus->name)
+ return -EINVAL;
+
+ /* An access method always needs both read and write operations */
+ if ((bus->read && !bus->write) ||
+ (!bus->read && bus->write) ||
+ (bus->read_c45 && !bus->write_c45) ||
+ (!bus->read_c45 && bus->write_c45))
+ return -EINVAL;
+
+ /* At least one method is mandatory */
+ if (!bus->read && !bus->read_c45)
return -EINVAL;

if (bus->parent && bus->parent->of_node)

--
2.30.2

2022-12-27 23:32:05

by Michael Walle

[permalink] [raw]
Subject: [PATCH RFC net-next v2 12/12] net: dsa: mv88e6xxx: Separate C22 and C45 transactions

From: Andrew Lunn <[email protected]>

The global2 SMI MDIO bus driver can perform both C22 and C45
transfers. Create separate functions for each and register the C45
versions using the new API calls where appropriate. Update the SERDES
code to make use of these new accessors.

Signed-off-by: Andrew Lunn <[email protected]>
Signed-off-by: Michael Walle <[email protected]>
---
drivers/net/dsa/mv88e6xxx/chip.c | 175 ++++++++++++++++++++++++++----------
drivers/net/dsa/mv88e6xxx/chip.h | 7 ++
drivers/net/dsa/mv88e6xxx/global2.c | 66 ++++++++------
drivers/net/dsa/mv88e6xxx/global2.h | 18 ++--
drivers/net/dsa/mv88e6xxx/phy.c | 32 +++++++
drivers/net/dsa/mv88e6xxx/phy.h | 4 +
drivers/net/dsa/mv88e6xxx/serdes.c | 8 +-
7 files changed, 225 insertions(+), 85 deletions(-)

diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c
index 242b8b325504..0ff9cd0be217 100644
--- a/drivers/net/dsa/mv88e6xxx/chip.c
+++ b/drivers/net/dsa/mv88e6xxx/chip.c
@@ -3884,6 +3884,24 @@ static int mv88e6xxx_mdio_read(struct mii_bus *bus, int phy, int reg)
return err ? err : val;
}

+static int mv88e6xxx_mdio_read_c45(struct mii_bus *bus, int phy, int devad,
+ int reg)
+{
+ struct mv88e6xxx_mdio_bus *mdio_bus = bus->priv;
+ struct mv88e6xxx_chip *chip = mdio_bus->chip;
+ u16 val;
+ int err;
+
+ if (!chip->info->ops->phy_read_c45)
+ return -EOPNOTSUPP;
+
+ mv88e6xxx_reg_lock(chip);
+ err = chip->info->ops->phy_read_c45(chip, bus, phy, devad, reg, &val);
+ mv88e6xxx_reg_unlock(chip);
+
+ return err ? err : val;
+}
+
static int mv88e6xxx_mdio_write(struct mii_bus *bus, int phy, int reg, u16 val)
{
struct mv88e6xxx_mdio_bus *mdio_bus = bus->priv;
@@ -3900,6 +3918,23 @@ static int mv88e6xxx_mdio_write(struct mii_bus *bus, int phy, int reg, u16 val)
return err;
}

+static int mv88e6xxx_mdio_write_c45(struct mii_bus *bus, int phy, int devad,
+ int reg, u16 val)
+{
+ struct mv88e6xxx_mdio_bus *mdio_bus = bus->priv;
+ struct mv88e6xxx_chip *chip = mdio_bus->chip;
+ int err;
+
+ if (!chip->info->ops->phy_write_c45)
+ return -EOPNOTSUPP;
+
+ mv88e6xxx_reg_lock(chip);
+ err = chip->info->ops->phy_write_c45(chip, bus, phy, devad, reg, val);
+ mv88e6xxx_reg_unlock(chip);
+
+ return err;
+}
+
static int mv88e6xxx_mdio_register(struct mv88e6xxx_chip *chip,
struct device_node *np,
bool external)
@@ -3938,6 +3973,8 @@ static int mv88e6xxx_mdio_register(struct mv88e6xxx_chip *chip,

bus->read = mv88e6xxx_mdio_read;
bus->write = mv88e6xxx_mdio_write;
+ bus->read_c45 = mv88e6xxx_mdio_read_c45;
+ bus->write_c45 = mv88e6xxx_mdio_write_c45;
bus->parent = chip->dev;

if (!external) {
@@ -4149,8 +4186,10 @@ static const struct mv88e6xxx_ops mv88e6097_ops = {
.ip_pri_map = mv88e6085_g1_ip_pri_map,
.irl_init_all = mv88e6352_g2_irl_init_all,
.set_switch_mac = mv88e6xxx_g2_set_switch_mac,
- .phy_read = mv88e6xxx_g2_smi_phy_read,
- .phy_write = mv88e6xxx_g2_smi_phy_write,
+ .phy_read = mv88e6xxx_g2_smi_phy_read_c22,
+ .phy_write = mv88e6xxx_g2_smi_phy_write_c22,
+ .phy_read_c45 = mv88e6xxx_g2_smi_phy_read_c45,
+ .phy_write_c45 = mv88e6xxx_g2_smi_phy_write_c45,
.port_set_link = mv88e6xxx_port_set_link,
.port_sync_link = mv88e6185_port_sync_link,
.port_set_speed_duplex = mv88e6185_port_set_speed_duplex,
@@ -4198,8 +4237,10 @@ static const struct mv88e6xxx_ops mv88e6123_ops = {
.ip_pri_map = mv88e6085_g1_ip_pri_map,
.irl_init_all = mv88e6352_g2_irl_init_all,
.set_switch_mac = mv88e6xxx_g2_set_switch_mac,
- .phy_read = mv88e6xxx_g2_smi_phy_read,
- .phy_write = mv88e6xxx_g2_smi_phy_write,
+ .phy_read = mv88e6xxx_g2_smi_phy_read_c22,
+ .phy_write = mv88e6xxx_g2_smi_phy_write_c22,
+ .phy_read_c45 = mv88e6xxx_g2_smi_phy_read_c45,
+ .phy_write_c45 = mv88e6xxx_g2_smi_phy_write_c45,
.port_set_link = mv88e6xxx_port_set_link,
.port_sync_link = mv88e6xxx_port_sync_link,
.port_set_speed_duplex = mv88e6185_port_set_speed_duplex,
@@ -4279,8 +4320,10 @@ static const struct mv88e6xxx_ops mv88e6141_ops = {
.get_eeprom = mv88e6xxx_g2_get_eeprom8,
.set_eeprom = mv88e6xxx_g2_set_eeprom8,
.set_switch_mac = mv88e6xxx_g2_set_switch_mac,
- .phy_read = mv88e6xxx_g2_smi_phy_read,
- .phy_write = mv88e6xxx_g2_smi_phy_write,
+ .phy_read = mv88e6xxx_g2_smi_phy_read_c22,
+ .phy_write = mv88e6xxx_g2_smi_phy_write_c22,
+ .phy_read_c45 = mv88e6xxx_g2_smi_phy_read_c45,
+ .phy_write_c45 = mv88e6xxx_g2_smi_phy_write_c45,
.port_set_link = mv88e6xxx_port_set_link,
.port_sync_link = mv88e6xxx_port_sync_link,
.port_set_rgmii_delay = mv88e6390_port_set_rgmii_delay,
@@ -4343,8 +4386,10 @@ static const struct mv88e6xxx_ops mv88e6161_ops = {
.ip_pri_map = mv88e6085_g1_ip_pri_map,
.irl_init_all = mv88e6352_g2_irl_init_all,
.set_switch_mac = mv88e6xxx_g2_set_switch_mac,
- .phy_read = mv88e6xxx_g2_smi_phy_read,
- .phy_write = mv88e6xxx_g2_smi_phy_write,
+ .phy_read = mv88e6xxx_g2_smi_phy_read_c22,
+ .phy_write = mv88e6xxx_g2_smi_phy_write_c22,
+ .phy_read_c45 = mv88e6xxx_g2_smi_phy_read_c45,
+ .phy_write_c45 = mv88e6xxx_g2_smi_phy_write_c45,
.port_set_link = mv88e6xxx_port_set_link,
.port_sync_link = mv88e6xxx_port_sync_link,
.port_set_speed_duplex = mv88e6185_port_set_speed_duplex,
@@ -4426,8 +4471,10 @@ static const struct mv88e6xxx_ops mv88e6171_ops = {
.ip_pri_map = mv88e6085_g1_ip_pri_map,
.irl_init_all = mv88e6352_g2_irl_init_all,
.set_switch_mac = mv88e6xxx_g2_set_switch_mac,
- .phy_read = mv88e6xxx_g2_smi_phy_read,
- .phy_write = mv88e6xxx_g2_smi_phy_write,
+ .phy_read = mv88e6xxx_g2_smi_phy_read_c22,
+ .phy_write = mv88e6xxx_g2_smi_phy_write_c22,
+ .phy_read_c45 = mv88e6xxx_g2_smi_phy_read_c45,
+ .phy_write_c45 = mv88e6xxx_g2_smi_phy_write_c45,
.port_set_link = mv88e6xxx_port_set_link,
.port_sync_link = mv88e6xxx_port_sync_link,
.port_set_rgmii_delay = mv88e6352_port_set_rgmii_delay,
@@ -4472,8 +4519,10 @@ static const struct mv88e6xxx_ops mv88e6172_ops = {
.get_eeprom = mv88e6xxx_g2_get_eeprom16,
.set_eeprom = mv88e6xxx_g2_set_eeprom16,
.set_switch_mac = mv88e6xxx_g2_set_switch_mac,
- .phy_read = mv88e6xxx_g2_smi_phy_read,
- .phy_write = mv88e6xxx_g2_smi_phy_write,
+ .phy_read = mv88e6xxx_g2_smi_phy_read_c22,
+ .phy_write = mv88e6xxx_g2_smi_phy_write_c22,
+ .phy_read_c45 = mv88e6xxx_g2_smi_phy_read_c45,
+ .phy_write_c45 = mv88e6xxx_g2_smi_phy_write_c45,
.port_set_link = mv88e6xxx_port_set_link,
.port_sync_link = mv88e6xxx_port_sync_link,
.port_set_rgmii_delay = mv88e6352_port_set_rgmii_delay,
@@ -4527,8 +4576,10 @@ static const struct mv88e6xxx_ops mv88e6175_ops = {
.ip_pri_map = mv88e6085_g1_ip_pri_map,
.irl_init_all = mv88e6352_g2_irl_init_all,
.set_switch_mac = mv88e6xxx_g2_set_switch_mac,
- .phy_read = mv88e6xxx_g2_smi_phy_read,
- .phy_write = mv88e6xxx_g2_smi_phy_write,
+ .phy_read = mv88e6xxx_g2_smi_phy_read_c22,
+ .phy_write = mv88e6xxx_g2_smi_phy_write_c22,
+ .phy_read_c45 = mv88e6xxx_g2_smi_phy_read_c45,
+ .phy_write_c45 = mv88e6xxx_g2_smi_phy_write_c45,
.port_set_link = mv88e6xxx_port_set_link,
.port_sync_link = mv88e6xxx_port_sync_link,
.port_set_rgmii_delay = mv88e6352_port_set_rgmii_delay,
@@ -4573,8 +4624,10 @@ static const struct mv88e6xxx_ops mv88e6176_ops = {
.get_eeprom = mv88e6xxx_g2_get_eeprom16,
.set_eeprom = mv88e6xxx_g2_set_eeprom16,
.set_switch_mac = mv88e6xxx_g2_set_switch_mac,
- .phy_read = mv88e6xxx_g2_smi_phy_read,
- .phy_write = mv88e6xxx_g2_smi_phy_write,
+ .phy_read = mv88e6xxx_g2_smi_phy_read_c22,
+ .phy_write = mv88e6xxx_g2_smi_phy_write_c22,
+ .phy_read_c45 = mv88e6xxx_g2_smi_phy_read_c45,
+ .phy_write_c45 = mv88e6xxx_g2_smi_phy_write_c45,
.port_set_link = mv88e6xxx_port_set_link,
.port_sync_link = mv88e6xxx_port_sync_link,
.port_set_rgmii_delay = mv88e6352_port_set_rgmii_delay,
@@ -4673,8 +4726,10 @@ static const struct mv88e6xxx_ops mv88e6190_ops = {
.get_eeprom = mv88e6xxx_g2_get_eeprom8,
.set_eeprom = mv88e6xxx_g2_set_eeprom8,
.set_switch_mac = mv88e6xxx_g2_set_switch_mac,
- .phy_read = mv88e6xxx_g2_smi_phy_read,
- .phy_write = mv88e6xxx_g2_smi_phy_write,
+ .phy_read = mv88e6xxx_g2_smi_phy_read_c22,
+ .phy_write = mv88e6xxx_g2_smi_phy_write_c22,
+ .phy_read_c45 = mv88e6xxx_g2_smi_phy_read_c45,
+ .phy_write_c45 = mv88e6xxx_g2_smi_phy_write_c45,
.port_set_link = mv88e6xxx_port_set_link,
.port_sync_link = mv88e6xxx_port_sync_link,
.port_set_rgmii_delay = mv88e6390_port_set_rgmii_delay,
@@ -4736,8 +4791,10 @@ static const struct mv88e6xxx_ops mv88e6190x_ops = {
.get_eeprom = mv88e6xxx_g2_get_eeprom8,
.set_eeprom = mv88e6xxx_g2_set_eeprom8,
.set_switch_mac = mv88e6xxx_g2_set_switch_mac,
- .phy_read = mv88e6xxx_g2_smi_phy_read,
- .phy_write = mv88e6xxx_g2_smi_phy_write,
+ .phy_read = mv88e6xxx_g2_smi_phy_read_c22,
+ .phy_write = mv88e6xxx_g2_smi_phy_write_c22,
+ .phy_read_c45 = mv88e6xxx_g2_smi_phy_read_c45,
+ .phy_write_c45 = mv88e6xxx_g2_smi_phy_write_c45,
.port_set_link = mv88e6xxx_port_set_link,
.port_sync_link = mv88e6xxx_port_sync_link,
.port_set_rgmii_delay = mv88e6390_port_set_rgmii_delay,
@@ -4799,8 +4856,10 @@ static const struct mv88e6xxx_ops mv88e6191_ops = {
.get_eeprom = mv88e6xxx_g2_get_eeprom8,
.set_eeprom = mv88e6xxx_g2_set_eeprom8,
.set_switch_mac = mv88e6xxx_g2_set_switch_mac,
- .phy_read = mv88e6xxx_g2_smi_phy_read,
- .phy_write = mv88e6xxx_g2_smi_phy_write,
+ .phy_read = mv88e6xxx_g2_smi_phy_read_c22,
+ .phy_write = mv88e6xxx_g2_smi_phy_write_c22,
+ .phy_read_c45 = mv88e6xxx_g2_smi_phy_read_c45,
+ .phy_write_c45 = mv88e6xxx_g2_smi_phy_write_c45,
.port_set_link = mv88e6xxx_port_set_link,
.port_sync_link = mv88e6xxx_port_sync_link,
.port_set_rgmii_delay = mv88e6390_port_set_rgmii_delay,
@@ -4862,8 +4921,10 @@ static const struct mv88e6xxx_ops mv88e6240_ops = {
.get_eeprom = mv88e6xxx_g2_get_eeprom16,
.set_eeprom = mv88e6xxx_g2_set_eeprom16,
.set_switch_mac = mv88e6xxx_g2_set_switch_mac,
- .phy_read = mv88e6xxx_g2_smi_phy_read,
- .phy_write = mv88e6xxx_g2_smi_phy_write,
+ .phy_read = mv88e6xxx_g2_smi_phy_read_c22,
+ .phy_write = mv88e6xxx_g2_smi_phy_write_c22,
+ .phy_read_c45 = mv88e6xxx_g2_smi_phy_read_c45,
+ .phy_write_c45 = mv88e6xxx_g2_smi_phy_write_c45,
.port_set_link = mv88e6xxx_port_set_link,
.port_sync_link = mv88e6xxx_port_sync_link,
.port_set_rgmii_delay = mv88e6352_port_set_rgmii_delay,
@@ -4925,8 +4986,10 @@ static const struct mv88e6xxx_ops mv88e6250_ops = {
.get_eeprom = mv88e6xxx_g2_get_eeprom16,
.set_eeprom = mv88e6xxx_g2_set_eeprom16,
.set_switch_mac = mv88e6xxx_g2_set_switch_mac,
- .phy_read = mv88e6xxx_g2_smi_phy_read,
- .phy_write = mv88e6xxx_g2_smi_phy_write,
+ .phy_read = mv88e6xxx_g2_smi_phy_read_c22,
+ .phy_write = mv88e6xxx_g2_smi_phy_write_c22,
+ .phy_read_c45 = mv88e6xxx_g2_smi_phy_read_c45,
+ .phy_write_c45 = mv88e6xxx_g2_smi_phy_write_c45,
.port_set_link = mv88e6xxx_port_set_link,
.port_sync_link = mv88e6xxx_port_sync_link,
.port_set_rgmii_delay = mv88e6352_port_set_rgmii_delay,
@@ -4964,8 +5027,10 @@ static const struct mv88e6xxx_ops mv88e6290_ops = {
.get_eeprom = mv88e6xxx_g2_get_eeprom8,
.set_eeprom = mv88e6xxx_g2_set_eeprom8,
.set_switch_mac = mv88e6xxx_g2_set_switch_mac,
- .phy_read = mv88e6xxx_g2_smi_phy_read,
- .phy_write = mv88e6xxx_g2_smi_phy_write,
+ .phy_read = mv88e6xxx_g2_smi_phy_read_c22,
+ .phy_write = mv88e6xxx_g2_smi_phy_write_c22,
+ .phy_read_c45 = mv88e6xxx_g2_smi_phy_read_c45,
+ .phy_write_c45 = mv88e6xxx_g2_smi_phy_write_c45,
.port_set_link = mv88e6xxx_port_set_link,
.port_sync_link = mv88e6xxx_port_sync_link,
.port_set_rgmii_delay = mv88e6390_port_set_rgmii_delay,
@@ -5029,8 +5094,10 @@ static const struct mv88e6xxx_ops mv88e6320_ops = {
.get_eeprom = mv88e6xxx_g2_get_eeprom16,
.set_eeprom = mv88e6xxx_g2_set_eeprom16,
.set_switch_mac = mv88e6xxx_g2_set_switch_mac,
- .phy_read = mv88e6xxx_g2_smi_phy_read,
- .phy_write = mv88e6xxx_g2_smi_phy_write,
+ .phy_read = mv88e6xxx_g2_smi_phy_read_c22,
+ .phy_write = mv88e6xxx_g2_smi_phy_write_c22,
+ .phy_read_c45 = mv88e6xxx_g2_smi_phy_read_c45,
+ .phy_write_c45 = mv88e6xxx_g2_smi_phy_write_c45,
.port_set_link = mv88e6xxx_port_set_link,
.port_sync_link = mv88e6xxx_port_sync_link,
.port_set_rgmii_delay = mv88e6320_port_set_rgmii_delay,
@@ -5074,8 +5141,10 @@ static const struct mv88e6xxx_ops mv88e6321_ops = {
.get_eeprom = mv88e6xxx_g2_get_eeprom16,
.set_eeprom = mv88e6xxx_g2_set_eeprom16,
.set_switch_mac = mv88e6xxx_g2_set_switch_mac,
- .phy_read = mv88e6xxx_g2_smi_phy_read,
- .phy_write = mv88e6xxx_g2_smi_phy_write,
+ .phy_read = mv88e6xxx_g2_smi_phy_read_c22,
+ .phy_write = mv88e6xxx_g2_smi_phy_write_c22,
+ .phy_read_c45 = mv88e6xxx_g2_smi_phy_read_c45,
+ .phy_write_c45 = mv88e6xxx_g2_smi_phy_write_c45,
.port_set_link = mv88e6xxx_port_set_link,
.port_sync_link = mv88e6xxx_port_sync_link,
.port_set_rgmii_delay = mv88e6320_port_set_rgmii_delay,
@@ -5117,8 +5186,10 @@ static const struct mv88e6xxx_ops mv88e6341_ops = {
.get_eeprom = mv88e6xxx_g2_get_eeprom8,
.set_eeprom = mv88e6xxx_g2_set_eeprom8,
.set_switch_mac = mv88e6xxx_g2_set_switch_mac,
- .phy_read = mv88e6xxx_g2_smi_phy_read,
- .phy_write = mv88e6xxx_g2_smi_phy_write,
+ .phy_read = mv88e6xxx_g2_smi_phy_read_c22,
+ .phy_write = mv88e6xxx_g2_smi_phy_write_c22,
+ .phy_read_c45 = mv88e6xxx_g2_smi_phy_read_c45,
+ .phy_write_c45 = mv88e6xxx_g2_smi_phy_write_c45,
.port_set_link = mv88e6xxx_port_set_link,
.port_sync_link = mv88e6xxx_port_sync_link,
.port_set_rgmii_delay = mv88e6390_port_set_rgmii_delay,
@@ -5183,8 +5254,10 @@ static const struct mv88e6xxx_ops mv88e6350_ops = {
.ip_pri_map = mv88e6085_g1_ip_pri_map,
.irl_init_all = mv88e6352_g2_irl_init_all,
.set_switch_mac = mv88e6xxx_g2_set_switch_mac,
- .phy_read = mv88e6xxx_g2_smi_phy_read,
- .phy_write = mv88e6xxx_g2_smi_phy_write,
+ .phy_read = mv88e6xxx_g2_smi_phy_read_c22,
+ .phy_write = mv88e6xxx_g2_smi_phy_write_c22,
+ .phy_read_c45 = mv88e6xxx_g2_smi_phy_read_c45,
+ .phy_write_c45 = mv88e6xxx_g2_smi_phy_write_c45,
.port_set_link = mv88e6xxx_port_set_link,
.port_sync_link = mv88e6xxx_port_sync_link,
.port_set_rgmii_delay = mv88e6352_port_set_rgmii_delay,
@@ -5227,8 +5300,10 @@ static const struct mv88e6xxx_ops mv88e6351_ops = {
.ip_pri_map = mv88e6085_g1_ip_pri_map,
.irl_init_all = mv88e6352_g2_irl_init_all,
.set_switch_mac = mv88e6xxx_g2_set_switch_mac,
- .phy_read = mv88e6xxx_g2_smi_phy_read,
- .phy_write = mv88e6xxx_g2_smi_phy_write,
+ .phy_read = mv88e6xxx_g2_smi_phy_read_c22,
+ .phy_write = mv88e6xxx_g2_smi_phy_write_c22,
+ .phy_read_c45 = mv88e6xxx_g2_smi_phy_read_c45,
+ .phy_write_c45 = mv88e6xxx_g2_smi_phy_write_c45,
.port_set_link = mv88e6xxx_port_set_link,
.port_sync_link = mv88e6xxx_port_sync_link,
.port_set_rgmii_delay = mv88e6352_port_set_rgmii_delay,
@@ -5275,8 +5350,10 @@ static const struct mv88e6xxx_ops mv88e6352_ops = {
.get_eeprom = mv88e6xxx_g2_get_eeprom16,
.set_eeprom = mv88e6xxx_g2_set_eeprom16,
.set_switch_mac = mv88e6xxx_g2_set_switch_mac,
- .phy_read = mv88e6xxx_g2_smi_phy_read,
- .phy_write = mv88e6xxx_g2_smi_phy_write,
+ .phy_read = mv88e6xxx_g2_smi_phy_read_c22,
+ .phy_write = mv88e6xxx_g2_smi_phy_write_c22,
+ .phy_read_c45 = mv88e6xxx_g2_smi_phy_read_c45,
+ .phy_write_c45 = mv88e6xxx_g2_smi_phy_write_c45,
.port_set_link = mv88e6xxx_port_set_link,
.port_sync_link = mv88e6xxx_port_sync_link,
.port_set_rgmii_delay = mv88e6352_port_set_rgmii_delay,
@@ -5340,8 +5417,10 @@ static const struct mv88e6xxx_ops mv88e6390_ops = {
.get_eeprom = mv88e6xxx_g2_get_eeprom8,
.set_eeprom = mv88e6xxx_g2_set_eeprom8,
.set_switch_mac = mv88e6xxx_g2_set_switch_mac,
- .phy_read = mv88e6xxx_g2_smi_phy_read,
- .phy_write = mv88e6xxx_g2_smi_phy_write,
+ .phy_read = mv88e6xxx_g2_smi_phy_read_c22,
+ .phy_write = mv88e6xxx_g2_smi_phy_write_c22,
+ .phy_read_c45 = mv88e6xxx_g2_smi_phy_read_c45,
+ .phy_write_c45 = mv88e6xxx_g2_smi_phy_write_c45,
.port_set_link = mv88e6xxx_port_set_link,
.port_sync_link = mv88e6xxx_port_sync_link,
.port_set_rgmii_delay = mv88e6390_port_set_rgmii_delay,
@@ -5407,8 +5486,10 @@ static const struct mv88e6xxx_ops mv88e6390x_ops = {
.get_eeprom = mv88e6xxx_g2_get_eeprom8,
.set_eeprom = mv88e6xxx_g2_set_eeprom8,
.set_switch_mac = mv88e6xxx_g2_set_switch_mac,
- .phy_read = mv88e6xxx_g2_smi_phy_read,
- .phy_write = mv88e6xxx_g2_smi_phy_write,
+ .phy_read = mv88e6xxx_g2_smi_phy_read_c22,
+ .phy_write = mv88e6xxx_g2_smi_phy_write_c22,
+ .phy_read_c45 = mv88e6xxx_g2_smi_phy_read_c45,
+ .phy_write_c45 = mv88e6xxx_g2_smi_phy_write_c45,
.port_set_link = mv88e6xxx_port_set_link,
.port_sync_link = mv88e6xxx_port_sync_link,
.port_set_rgmii_delay = mv88e6390_port_set_rgmii_delay,
@@ -5473,8 +5554,10 @@ static const struct mv88e6xxx_ops mv88e6393x_ops = {
.get_eeprom = mv88e6xxx_g2_get_eeprom8,
.set_eeprom = mv88e6xxx_g2_set_eeprom8,
.set_switch_mac = mv88e6xxx_g2_set_switch_mac,
- .phy_read = mv88e6xxx_g2_smi_phy_read,
- .phy_write = mv88e6xxx_g2_smi_phy_write,
+ .phy_read = mv88e6xxx_g2_smi_phy_read_c22,
+ .phy_write = mv88e6xxx_g2_smi_phy_write_c22,
+ .phy_read_c45 = mv88e6xxx_g2_smi_phy_read_c45,
+ .phy_write_c45 = mv88e6xxx_g2_smi_phy_write_c45,
.port_set_link = mv88e6xxx_port_set_link,
.port_sync_link = mv88e6xxx_port_sync_link,
.port_set_rgmii_delay = mv88e6390_port_set_rgmii_delay,
diff --git a/drivers/net/dsa/mv88e6xxx/chip.h b/drivers/net/dsa/mv88e6xxx/chip.h
index e693154cf803..751bede49942 100644
--- a/drivers/net/dsa/mv88e6xxx/chip.h
+++ b/drivers/net/dsa/mv88e6xxx/chip.h
@@ -451,6 +451,13 @@ struct mv88e6xxx_ops {
struct mii_bus *bus,
int addr, int reg, u16 val);

+ int (*phy_read_c45)(struct mv88e6xxx_chip *chip,
+ struct mii_bus *bus,
+ int addr, int devad, int reg, u16 *val);
+ int (*phy_write_c45)(struct mv88e6xxx_chip *chip,
+ struct mii_bus *bus,
+ int addr, int devad, int reg, u16 val);
+
/* Priority Override Table operations */
int (*pot_clear)(struct mv88e6xxx_chip *chip);

diff --git a/drivers/net/dsa/mv88e6xxx/global2.c b/drivers/net/dsa/mv88e6xxx/global2.c
index fa65ecd9cb85..ed3b2f88e783 100644
--- a/drivers/net/dsa/mv88e6xxx/global2.c
+++ b/drivers/net/dsa/mv88e6xxx/global2.c
@@ -739,20 +739,18 @@ static int mv88e6xxx_g2_smi_phy_read_data_c45(struct mv88e6xxx_chip *chip,
return mv88e6xxx_g2_read(chip, MV88E6XXX_G2_SMI_PHY_DATA, data);
}

-static int mv88e6xxx_g2_smi_phy_read_c45(struct mv88e6xxx_chip *chip,
- bool external, int port, int reg,
- u16 *data)
+static int _mv88e6xxx_g2_smi_phy_read_c45(struct mv88e6xxx_chip *chip,
+ bool external, int port, int devad,
+ int reg, u16 *data)
{
- int dev = (reg >> 16) & 0x1f;
- int addr = reg & 0xffff;
int err;

- err = mv88e6xxx_g2_smi_phy_write_addr_c45(chip, external, port, dev,
- addr);
+ err = mv88e6xxx_g2_smi_phy_write_addr_c45(chip, external, port, devad,
+ reg);
if (err)
return err;

- return mv88e6xxx_g2_smi_phy_read_data_c45(chip, external, port, dev,
+ return mv88e6xxx_g2_smi_phy_read_data_c45(chip, external, port, devad,
data);
}

@@ -771,51 +769,65 @@ static int mv88e6xxx_g2_smi_phy_write_data_c45(struct mv88e6xxx_chip *chip,
return mv88e6xxx_g2_smi_phy_access_c45(chip, external, op, port, dev);
}

-static int mv88e6xxx_g2_smi_phy_write_c45(struct mv88e6xxx_chip *chip,
- bool external, int port, int reg,
- u16 data)
+static int _mv88e6xxx_g2_smi_phy_write_c45(struct mv88e6xxx_chip *chip,
+ bool external, int port, int devad,
+ int reg, u16 data)
{
- int dev = (reg >> 16) & 0x1f;
- int addr = reg & 0xffff;
int err;

- err = mv88e6xxx_g2_smi_phy_write_addr_c45(chip, external, port, dev,
- addr);
+ err = mv88e6xxx_g2_smi_phy_write_addr_c45(chip, external, port, devad,
+ reg);
if (err)
return err;

- return mv88e6xxx_g2_smi_phy_write_data_c45(chip, external, port, dev,
+ return mv88e6xxx_g2_smi_phy_write_data_c45(chip, external, port, devad,
data);
}

-int mv88e6xxx_g2_smi_phy_read(struct mv88e6xxx_chip *chip, struct mii_bus *bus,
- int addr, int reg, u16 *val)
+int mv88e6xxx_g2_smi_phy_read_c22(struct mv88e6xxx_chip *chip,
+ struct mii_bus *bus,
+ int addr, int reg, u16 *val)
{
struct mv88e6xxx_mdio_bus *mdio_bus = bus->priv;
bool external = mdio_bus->external;

- if (reg & MII_ADDR_C45)
- return mv88e6xxx_g2_smi_phy_read_c45(chip, external, addr, reg,
- val);
-
return mv88e6xxx_g2_smi_phy_read_data_c22(chip, external, addr, reg,
val);
}

-int mv88e6xxx_g2_smi_phy_write(struct mv88e6xxx_chip *chip, struct mii_bus *bus,
- int addr, int reg, u16 val)
+int mv88e6xxx_g2_smi_phy_read_c45(struct mv88e6xxx_chip *chip,
+ struct mii_bus *bus, int addr, int devad,
+ int reg, u16 *val)
{
struct mv88e6xxx_mdio_bus *mdio_bus = bus->priv;
bool external = mdio_bus->external;

- if (reg & MII_ADDR_C45)
- return mv88e6xxx_g2_smi_phy_write_c45(chip, external, addr, reg,
- val);
+ return _mv88e6xxx_g2_smi_phy_read_c45(chip, external, addr, devad, reg,
+ val);
+}
+
+int mv88e6xxx_g2_smi_phy_write_c22(struct mv88e6xxx_chip *chip,
+ struct mii_bus *bus, int addr, int reg,
+ u16 val)
+{
+ struct mv88e6xxx_mdio_bus *mdio_bus = bus->priv;
+ bool external = mdio_bus->external;

return mv88e6xxx_g2_smi_phy_write_data_c22(chip, external, addr, reg,
val);
}

+int mv88e6xxx_g2_smi_phy_write_c45(struct mv88e6xxx_chip *chip,
+ struct mii_bus *bus, int addr, int devad,
+ int reg, u16 val)
+{
+ struct mv88e6xxx_mdio_bus *mdio_bus = bus->priv;
+ bool external = mdio_bus->external;
+
+ return _mv88e6xxx_g2_smi_phy_write_c45(chip, external, addr, devad, reg,
+ val);
+}
+
/* Offset 0x1B: Watchdog Control */
static int mv88e6097_watchdog_action(struct mv88e6xxx_chip *chip, int irq)
{
diff --git a/drivers/net/dsa/mv88e6xxx/global2.h b/drivers/net/dsa/mv88e6xxx/global2.h
index 7536b8b0ad01..e973114d6890 100644
--- a/drivers/net/dsa/mv88e6xxx/global2.h
+++ b/drivers/net/dsa/mv88e6xxx/global2.h
@@ -314,12 +314,18 @@ int mv88e6xxx_g2_wait_bit(struct mv88e6xxx_chip *chip, int reg,
int mv88e6352_g2_irl_init_all(struct mv88e6xxx_chip *chip, int port);
int mv88e6390_g2_irl_init_all(struct mv88e6xxx_chip *chip, int port);

-int mv88e6xxx_g2_smi_phy_read(struct mv88e6xxx_chip *chip,
- struct mii_bus *bus,
- int addr, int reg, u16 *val);
-int mv88e6xxx_g2_smi_phy_write(struct mv88e6xxx_chip *chip,
- struct mii_bus *bus,
- int addr, int reg, u16 val);
+int mv88e6xxx_g2_smi_phy_read_c22(struct mv88e6xxx_chip *chip,
+ struct mii_bus *bus,
+ int addr, int reg, u16 *val);
+int mv88e6xxx_g2_smi_phy_write_c22(struct mv88e6xxx_chip *chip,
+ struct mii_bus *bus,
+ int addr, int reg, u16 val);
+int mv88e6xxx_g2_smi_phy_read_c45(struct mv88e6xxx_chip *chip,
+ struct mii_bus *bus,
+ int addr, int devad, int reg, u16 *val);
+int mv88e6xxx_g2_smi_phy_write_c45(struct mv88e6xxx_chip *chip,
+ struct mii_bus *bus,
+ int addr, int devad, int reg, u16 val);
int mv88e6xxx_g2_set_switch_mac(struct mv88e6xxx_chip *chip, u8 *addr);

int mv88e6xxx_g2_get_eeprom8(struct mv88e6xxx_chip *chip,
diff --git a/drivers/net/dsa/mv88e6xxx/phy.c b/drivers/net/dsa/mv88e6xxx/phy.c
index 252b5b3a3efe..8bb88b3d900d 100644
--- a/drivers/net/dsa/mv88e6xxx/phy.c
+++ b/drivers/net/dsa/mv88e6xxx/phy.c
@@ -55,6 +55,38 @@ int mv88e6xxx_phy_write(struct mv88e6xxx_chip *chip, int phy, int reg, u16 val)
return chip->info->ops->phy_write(chip, bus, addr, reg, val);
}

+int mv88e6xxx_phy_read_c45(struct mv88e6xxx_chip *chip, int phy, int devad,
+ int reg, u16 *val)
+{
+ int addr = phy; /* PHY devices addresses start at 0x0 */
+ struct mii_bus *bus;
+
+ bus = mv88e6xxx_default_mdio_bus(chip);
+ if (!bus)
+ return -EOPNOTSUPP;
+
+ if (!chip->info->ops->phy_read_c45)
+ return -EOPNOTSUPP;
+
+ return chip->info->ops->phy_read_c45(chip, bus, addr, devad, reg, val);
+}
+
+int mv88e6xxx_phy_write_c45(struct mv88e6xxx_chip *chip, int phy, int devad,
+ int reg, u16 val)
+{
+ int addr = phy; /* PHY devices addresses start at 0x0 */
+ struct mii_bus *bus;
+
+ bus = mv88e6xxx_default_mdio_bus(chip);
+ if (!bus)
+ return -EOPNOTSUPP;
+
+ if (!chip->info->ops->phy_write_c45)
+ return -EOPNOTSUPP;
+
+ return chip->info->ops->phy_write_c45(chip, bus, addr, devad, reg, val);
+}
+
static int mv88e6xxx_phy_page_get(struct mv88e6xxx_chip *chip, int phy, u8 page)
{
return mv88e6xxx_phy_write(chip, phy, MV88E6XXX_PHY_PAGE, page);
diff --git a/drivers/net/dsa/mv88e6xxx/phy.h b/drivers/net/dsa/mv88e6xxx/phy.h
index 05ea0d546969..5f47722364cc 100644
--- a/drivers/net/dsa/mv88e6xxx/phy.h
+++ b/drivers/net/dsa/mv88e6xxx/phy.h
@@ -28,6 +28,10 @@ int mv88e6xxx_phy_read(struct mv88e6xxx_chip *chip, int phy,
int reg, u16 *val);
int mv88e6xxx_phy_write(struct mv88e6xxx_chip *chip, int phy,
int reg, u16 val);
+int mv88e6xxx_phy_read_c45(struct mv88e6xxx_chip *chip, int phy, int devad,
+ int reg, u16 *val);
+int mv88e6xxx_phy_write_c45(struct mv88e6xxx_chip *chip, int phy, int devad,
+ int reg, u16 val);
int mv88e6xxx_phy_page_read(struct mv88e6xxx_chip *chip, int phy,
u8 page, int reg, u16 *val);
int mv88e6xxx_phy_page_write(struct mv88e6xxx_chip *chip, int phy,
diff --git a/drivers/net/dsa/mv88e6xxx/serdes.c b/drivers/net/dsa/mv88e6xxx/serdes.c
index d94150d8f3f4..72faec8f44dc 100644
--- a/drivers/net/dsa/mv88e6xxx/serdes.c
+++ b/drivers/net/dsa/mv88e6xxx/serdes.c
@@ -36,17 +36,13 @@ static int mv88e6352_serdes_write(struct mv88e6xxx_chip *chip, int reg,
static int mv88e6390_serdes_read(struct mv88e6xxx_chip *chip,
int lane, int device, int reg, u16 *val)
{
- int reg_c45 = MII_ADDR_C45 | device << 16 | reg;
-
- return mv88e6xxx_phy_read(chip, lane, reg_c45, val);
+ return mv88e6xxx_phy_read_c45(chip, lane, device, reg, val);
}

static int mv88e6390_serdes_write(struct mv88e6xxx_chip *chip,
int lane, int device, int reg, u16 val)
{
- int reg_c45 = MII_ADDR_C45 | device << 16 | reg;
-
- return mv88e6xxx_phy_write(chip, lane, reg_c45, val);
+ return mv88e6xxx_phy_write_c45(chip, lane, device, reg, val);
}

static int mv88e6xxx_serdes_pcs_get_state(struct mv88e6xxx_chip *chip,

--
2.30.2

2022-12-27 23:32:10

by Michael Walle

[permalink] [raw]
Subject: [PATCH RFC net-next v2 02/12] net: pcs: pcs-xpcs: Use C45 MDIO API

From: Andrew Lunn <[email protected]>

Convert the PCS-XPCS driver to make use of the C45 MDIO bus API for
modify_change().

Signed-off-by: Andrew Lunn <[email protected]>
Signed-off-by: Michael Walle <[email protected]>
---
v2:
- [al] new patch
---
drivers/net/pcs/pcs-xpcs.c | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/drivers/net/pcs/pcs-xpcs.c b/drivers/net/pcs/pcs-xpcs.c
index f6a038a1d51e..bc428a816719 100644
--- a/drivers/net/pcs/pcs-xpcs.c
+++ b/drivers/net/pcs/pcs-xpcs.c
@@ -199,9 +199,7 @@ int xpcs_write(struct dw_xpcs *xpcs, int dev, u32 reg, u16 val)
static int xpcs_modify_changed(struct dw_xpcs *xpcs, int dev, u32 reg,
u16 mask, u16 set)
{
- u32 reg_addr = mdiobus_c45_addr(dev, reg);
-
- return mdiodev_modify_changed(xpcs->mdiodev, reg_addr, mask, set);
+ return mdiodev_c45_modify_changed(xpcs->mdiodev, dev, reg, mask, set);
}

static int xpcs_read_vendor(struct dw_xpcs *xpcs, int dev, u32 reg)

--
2.30.2

2022-12-27 23:32:10

by Michael Walle

[permalink] [raw]
Subject: [PATCH RFC net-next v2 07/12] net: mdio: mvmdio: Convert XSMI bus to new API

From: Andrew Lunn <[email protected]>

The marvell MDIO driver supports two different hardware blocks. The
XSMI block is C45 only. Convert this block to the new API, and only
populate the c45 calls in the bus structure.

Signed-off-by: Andrew Lunn <[email protected]>
Signed-off-by: Michael Walle <[email protected]>
---
drivers/net/ethernet/marvell/mvmdio.c | 24 ++++++++----------------
1 file changed, 8 insertions(+), 16 deletions(-)

diff --git a/drivers/net/ethernet/marvell/mvmdio.c b/drivers/net/ethernet/marvell/mvmdio.c
index ef878973b859..2d654a40af13 100644
--- a/drivers/net/ethernet/marvell/mvmdio.c
+++ b/drivers/net/ethernet/marvell/mvmdio.c
@@ -204,21 +204,17 @@ static const struct orion_mdio_ops orion_mdio_xsmi_ops = {
.poll_interval_max = MVMDIO_XSMI_POLL_INTERVAL_MAX,
};

-static int orion_mdio_xsmi_read(struct mii_bus *bus, int mii_id,
- int regnum)
+static int orion_mdio_xsmi_read_c45(struct mii_bus *bus, int mii_id,
+ int dev_addr, int regnum)
{
struct orion_mdio_dev *dev = bus->priv;
- u16 dev_addr = (regnum >> 16) & GENMASK(4, 0);
int ret;

- if (!(regnum & MII_ADDR_C45))
- return -EOPNOTSUPP;
-
ret = orion_mdio_wait_ready(&orion_mdio_xsmi_ops, bus);
if (ret < 0)
return ret;

- writel(regnum & GENMASK(15, 0), dev->regs + MVMDIO_XSMI_ADDR_REG);
+ writel(regnum, dev->regs + MVMDIO_XSMI_ADDR_REG);
writel((mii_id << MVMDIO_XSMI_PHYADDR_SHIFT) |
(dev_addr << MVMDIO_XSMI_DEVADDR_SHIFT) |
MVMDIO_XSMI_READ_OPERATION,
@@ -237,21 +233,17 @@ static int orion_mdio_xsmi_read(struct mii_bus *bus, int mii_id,
return readl(dev->regs + MVMDIO_XSMI_MGNT_REG) & GENMASK(15, 0);
}

-static int orion_mdio_xsmi_write(struct mii_bus *bus, int mii_id,
- int regnum, u16 value)
+static int orion_mdio_xsmi_write_c45(struct mii_bus *bus, int mii_id,
+ int dev_addr, int regnum, u16 value)
{
struct orion_mdio_dev *dev = bus->priv;
- u16 dev_addr = (regnum >> 16) & GENMASK(4, 0);
int ret;

- if (!(regnum & MII_ADDR_C45))
- return -EOPNOTSUPP;
-
ret = orion_mdio_wait_ready(&orion_mdio_xsmi_ops, bus);
if (ret < 0)
return ret;

- writel(regnum & GENMASK(15, 0), dev->regs + MVMDIO_XSMI_ADDR_REG);
+ writel(regnum, dev->regs + MVMDIO_XSMI_ADDR_REG);
writel((mii_id << MVMDIO_XSMI_PHYADDR_SHIFT) |
(dev_addr << MVMDIO_XSMI_DEVADDR_SHIFT) |
MVMDIO_XSMI_WRITE_OPERATION | value,
@@ -302,8 +294,8 @@ static int orion_mdio_probe(struct platform_device *pdev)
bus->write = orion_mdio_smi_write;
break;
case BUS_TYPE_XSMI:
- bus->read = orion_mdio_xsmi_read;
- bus->write = orion_mdio_xsmi_write;
+ bus->read_c45 = orion_mdio_xsmi_read_c45;
+ bus->write_c45 = orion_mdio_xsmi_write_c45;
break;
}


--
2.30.2

2022-12-27 23:32:22

by Michael Walle

[permalink] [raw]
Subject: [PATCH RFC net-next v2 05/12] net: mdio: Move mdiobus_c45_addr() next to users

From: Andrew Lunn <[email protected]>

Now that mdiobus_c45_addr() is only used within the MDIO code during
fallback, move the function next to its only users. This function
should not be used any more in drivers, the c45 helpers should be used
in its place, so hiding it away will prevent any new users from being
added.

Signed-off-by: Andrew Lunn <[email protected]>
Signed-off-by: Michael Walle <[email protected]>
---
drivers/net/phy/mdio_bus.c | 5 +++++
include/linux/mdio.h | 5 -----
2 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c
index 20ba38a346fe..0b04ce3766c8 100644
--- a/drivers/net/phy/mdio_bus.c
+++ b/drivers/net/phy/mdio_bus.c
@@ -842,6 +842,11 @@ int __mdiobus_modify_changed(struct mii_bus *bus, int addr, u32 regnum,
}
EXPORT_SYMBOL_GPL(__mdiobus_modify_changed);

+static u32 mdiobus_c45_addr(int devad, u16 regnum)
+{
+ return MII_ADDR_C45 | devad << MII_DEVADDR_C45_SHIFT | regnum;
+}
+
/**
* __mdiobus_c45_read - Unlocked version of the mdiobus_c45_read function
* @bus: the mii_bus struct
diff --git a/include/linux/mdio.h b/include/linux/mdio.h
index 1e78c8410b21..97b49765e8b5 100644
--- a/include/linux/mdio.h
+++ b/include/linux/mdio.h
@@ -459,11 +459,6 @@ static inline int mdiodev_modify_changed(struct mdio_device *mdiodev,
mask, set);
}

-static inline u32 mdiobus_c45_addr(int devad, u16 regnum)
-{
- return MII_ADDR_C45 | devad << MII_DEVADDR_C45_SHIFT | regnum;
-}
-
static inline u16 mdiobus_c45_regad(u32 regnum)
{
return FIELD_GET(MII_REGADDR_C45_MASK, regnum);

--
2.30.2

2022-12-27 23:33:32

by Michael Walle

[permalink] [raw]
Subject: [PATCH RFC net-next v2 06/12] net: mdio: mdio-bitbang: Separate C22 and C45 transactions

From: Andrew Lunn <[email protected]>

The bitbbanging bus driver can perform both C22 and C45 transfers.
Create separate functions for each and register the C45 versions using
the new driver API calls.

The SH Ethernet driver places wrappers around these functions. In
order to not break boards which might be using C45, add similar
wrappers for C45 operations.

Reviewed-by: Geert Uytterhoeven <[email protected]>
Signed-off-by: Andrew Lunn <[email protected]>
Signed-off-by: Michael Walle <[email protected]>
---
drivers/net/ethernet/renesas/sh_eth.c | 37 ++++++++++++++---
drivers/net/mdio/mdio-bitbang.c | 77 +++++++++++++++++++++++------------
include/linux/mdio-bitbang.h | 6 ++-
3 files changed, 87 insertions(+), 33 deletions(-)

diff --git a/drivers/net/ethernet/renesas/sh_eth.c b/drivers/net/ethernet/renesas/sh_eth.c
index 71a499113308..ed17163d7811 100644
--- a/drivers/net/ethernet/renesas/sh_eth.c
+++ b/drivers/net/ethernet/renesas/sh_eth.c
@@ -3044,23 +3044,46 @@ static int sh_mdio_release(struct sh_eth_private *mdp)
return 0;
}

-static int sh_mdiobb_read(struct mii_bus *bus, int phy, int reg)
+static int sh_mdiobb_read_c22(struct mii_bus *bus, int phy, int reg)
{
int res;

pm_runtime_get_sync(bus->parent);
- res = mdiobb_read(bus, phy, reg);
+ res = mdiobb_read_c22(bus, phy, reg);
pm_runtime_put(bus->parent);

return res;
}

-static int sh_mdiobb_write(struct mii_bus *bus, int phy, int reg, u16 val)
+static int sh_mdiobb_write_c22(struct mii_bus *bus, int phy, int reg, u16 val)
{
int res;

pm_runtime_get_sync(bus->parent);
- res = mdiobb_write(bus, phy, reg, val);
+ res = mdiobb_write_c22(bus, phy, reg, val);
+ pm_runtime_put(bus->parent);
+
+ return res;
+}
+
+static int sh_mdiobb_read_c45(struct mii_bus *bus, int phy, int devad, int reg)
+{
+ int res;
+
+ pm_runtime_get_sync(bus->parent);
+ res = mdiobb_read_c45(bus, phy, devad, reg);
+ pm_runtime_put(bus->parent);
+
+ return res;
+}
+
+static int sh_mdiobb_write_c45(struct mii_bus *bus, int phy, int devad,
+ int reg, u16 val)
+{
+ int res;
+
+ pm_runtime_get_sync(bus->parent);
+ res = mdiobb_write_c45(bus, phy, devad, reg, val);
pm_runtime_put(bus->parent);

return res;
@@ -3091,8 +3114,10 @@ static int sh_mdio_init(struct sh_eth_private *mdp,
return -ENOMEM;

/* Wrap accessors with Runtime PM-aware ops */
- mdp->mii_bus->read = sh_mdiobb_read;
- mdp->mii_bus->write = sh_mdiobb_write;
+ mdp->mii_bus->read = sh_mdiobb_read_c22;
+ mdp->mii_bus->write = sh_mdiobb_write_c22;
+ mdp->mii_bus->read_c45 = sh_mdiobb_read_c45;
+ mdp->mii_bus->write_c45 = sh_mdiobb_write_c45;

/* Hook up MII support for ethtool */
mdp->mii_bus->name = "sh_mii";
diff --git a/drivers/net/mdio/mdio-bitbang.c b/drivers/net/mdio/mdio-bitbang.c
index 07609114a26b..b83932562be2 100644
--- a/drivers/net/mdio/mdio-bitbang.c
+++ b/drivers/net/mdio/mdio-bitbang.c
@@ -127,14 +127,12 @@ static void mdiobb_cmd(struct mdiobb_ctrl *ctrl, int op, u8 phy, u8 reg)

/* In clause 45 mode all commands are prefixed by MDIO_ADDR to specify the
lower 16 bits of the 21 bit address. This transfer is done identically to a
- MDIO_WRITE except for a different code. To enable clause 45 mode or
- MII_ADDR_C45 into the address. Theoretically clause 45 and normal devices
- can exist on the same bus. Normal devices should ignore the MDIO_ADDR
+ MDIO_WRITE except for a different code. Theoretically clause 45 and normal
+ devices can exist on the same bus. Normal devices should ignore the MDIO_ADDR
phase. */
-static int mdiobb_cmd_addr(struct mdiobb_ctrl *ctrl, int phy, u32 addr)
+static void mdiobb_cmd_addr(struct mdiobb_ctrl *ctrl, int phy, int dev_addr,
+ int reg)
{
- unsigned int dev_addr = (addr >> 16) & 0x1F;
- unsigned int reg = addr & 0xFFFF;
mdiobb_cmd(ctrl, MDIO_C45_ADDR, phy, dev_addr);

/* send the turnaround (10) */
@@ -145,21 +143,13 @@ static int mdiobb_cmd_addr(struct mdiobb_ctrl *ctrl, int phy, u32 addr)

ctrl->ops->set_mdio_dir(ctrl, 0);
mdiobb_get_bit(ctrl);
-
- return dev_addr;
}

-int mdiobb_read(struct mii_bus *bus, int phy, int reg)
+static int mdiobb_read_common(struct mii_bus *bus, int phy)
{
struct mdiobb_ctrl *ctrl = bus->priv;
int ret, i;

- if (reg & MII_ADDR_C45) {
- reg = mdiobb_cmd_addr(ctrl, phy, reg);
- mdiobb_cmd(ctrl, MDIO_C45_READ, phy, reg);
- } else
- mdiobb_cmd(ctrl, ctrl->op_c22_read, phy, reg);
-
ctrl->ops->set_mdio_dir(ctrl, 0);

/* check the turnaround bit: the PHY should be driving it to zero, if this
@@ -180,17 +170,31 @@ int mdiobb_read(struct mii_bus *bus, int phy, int reg)
mdiobb_get_bit(ctrl);
return ret;
}
-EXPORT_SYMBOL(mdiobb_read);

-int mdiobb_write(struct mii_bus *bus, int phy, int reg, u16 val)
+int mdiobb_read_c22(struct mii_bus *bus, int phy, int reg)
{
struct mdiobb_ctrl *ctrl = bus->priv;

- if (reg & MII_ADDR_C45) {
- reg = mdiobb_cmd_addr(ctrl, phy, reg);
- mdiobb_cmd(ctrl, MDIO_C45_WRITE, phy, reg);
- } else
- mdiobb_cmd(ctrl, ctrl->op_c22_write, phy, reg);
+ mdiobb_cmd(ctrl, ctrl->op_c22_read, phy, reg);
+
+ return mdiobb_read_common(bus, phy);
+}
+EXPORT_SYMBOL(mdiobb_read_c22);
+
+int mdiobb_read_c45(struct mii_bus *bus, int phy, int devad, int reg)
+{
+ struct mdiobb_ctrl *ctrl = bus->priv;
+
+ mdiobb_cmd_addr(ctrl, phy, devad, reg);
+ mdiobb_cmd(ctrl, MDIO_C45_READ, phy, reg);
+
+ return mdiobb_read_common(bus, phy);
+}
+EXPORT_SYMBOL(mdiobb_read_c45);
+
+static int mdiobb_write_common(struct mii_bus *bus, u16 val)
+{
+ struct mdiobb_ctrl *ctrl = bus->priv;

/* send the turnaround (10) */
mdiobb_send_bit(ctrl, 1);
@@ -202,7 +206,27 @@ int mdiobb_write(struct mii_bus *bus, int phy, int reg, u16 val)
mdiobb_get_bit(ctrl);
return 0;
}
-EXPORT_SYMBOL(mdiobb_write);
+
+int mdiobb_write_c22(struct mii_bus *bus, int phy, int reg, u16 val)
+{
+ struct mdiobb_ctrl *ctrl = bus->priv;
+
+ mdiobb_cmd(ctrl, ctrl->op_c22_write, phy, reg);
+
+ return mdiobb_write_common(bus, val);
+}
+EXPORT_SYMBOL(mdiobb_write_c22);
+
+int mdiobb_write_c45(struct mii_bus *bus, int phy, int devad, int reg, u16 val)
+{
+ struct mdiobb_ctrl *ctrl = bus->priv;
+
+ mdiobb_cmd_addr(ctrl, phy, devad, reg);
+ mdiobb_cmd(ctrl, MDIO_C45_WRITE, phy, reg);
+
+ return mdiobb_write_common(bus, val);
+}
+EXPORT_SYMBOL(mdiobb_write_c45);

struct mii_bus *alloc_mdio_bitbang(struct mdiobb_ctrl *ctrl)
{
@@ -214,8 +238,11 @@ struct mii_bus *alloc_mdio_bitbang(struct mdiobb_ctrl *ctrl)

__module_get(ctrl->ops->owner);

- bus->read = mdiobb_read;
- bus->write = mdiobb_write;
+ bus->read = mdiobb_read_c22;
+ bus->write = mdiobb_write_c22;
+ bus->read_c45 = mdiobb_read_c45;
+ bus->write_c45 = mdiobb_write_c45;
+
bus->priv = ctrl;
if (!ctrl->override_op_c22) {
ctrl->op_c22_read = MDIO_READ;
diff --git a/include/linux/mdio-bitbang.h b/include/linux/mdio-bitbang.h
index 373630fe5c28..cffabdbce075 100644
--- a/include/linux/mdio-bitbang.h
+++ b/include/linux/mdio-bitbang.h
@@ -38,8 +38,10 @@ struct mdiobb_ctrl {
u8 op_c22_write;
};

-int mdiobb_read(struct mii_bus *bus, int phy, int reg);
-int mdiobb_write(struct mii_bus *bus, int phy, int reg, u16 val);
+int mdiobb_read_c22(struct mii_bus *bus, int phy, int reg);
+int mdiobb_write_c22(struct mii_bus *bus, int phy, int reg, u16 val);
+int mdiobb_read_c45(struct mii_bus *bus, int devad, int phy, int reg);
+int mdiobb_write_c45(struct mii_bus *bus, int devad, int phy, int reg, u16 val);

/* The returned bus is not yet registered with the phy layer. */
struct mii_bus *alloc_mdio_bitbang(struct mdiobb_ctrl *ctrl);

--
2.30.2

2022-12-27 23:33:56

by Michael Walle

[permalink] [raw]
Subject: [PATCH RFC net-next v2 01/12] net: mdio: Add dedicated C45 API to MDIO bus drivers

From: Andrew Lunn <[email protected]>

Currently C22 and C45 transactions are mixed over a combined API calls
which make use of a special bit in the reg address to indicate if a
C45 transaction should be performed. This makes it impossible to know
if the bus driver actually supports C45. Additionally, many C22 only
drivers don't return -EOPNOTSUPP when asked to perform a C45
transaction, they mistaking perform a C22 transaction.

This is the first step to cleanly separate C22 from C45. To maintain
backwards compatibility until all drivers which are capable of
performing C45 are converted to this new API, the helper functions
will fall back to the older API if the new API is not
supported. Eventually this fallback will be removed.

Signed-off-by: Andrew Lunn <[email protected]>
Signed-off-by: Michael Walle <[email protected]>
---
drivers/net/phy/mdio_bus.c | 189 +++++++++++++++++++++++++++++++++++++++++++++
include/linux/mdio.h | 39 +++++-----
include/linux/phy.h | 5 ++
3 files changed, 214 insertions(+), 19 deletions(-)

diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c
index 1cd604cd1fa1..bde195864c17 100644
--- a/drivers/net/phy/mdio_bus.c
+++ b/drivers/net/phy/mdio_bus.c
@@ -826,6 +826,100 @@ int __mdiobus_modify_changed(struct mii_bus *bus, int addr, u32 regnum,
}
EXPORT_SYMBOL_GPL(__mdiobus_modify_changed);

+/**
+ * __mdiobus_c45_read - Unlocked version of the mdiobus_c45_read function
+ * @bus: the mii_bus struct
+ * @addr: the phy address
+ * @devad: device address to read
+ * @regnum: register number to read
+ *
+ * Read a MDIO bus register. Caller must hold the mdio bus lock.
+ *
+ * NOTE: MUST NOT be called from interrupt context.
+ */
+int __mdiobus_c45_read(struct mii_bus *bus, int addr, int devad, u32 regnum)
+{
+ int retval;
+
+ lockdep_assert_held_once(&bus->mdio_lock);
+
+ if (bus->read_c45)
+ retval = bus->read_c45(bus, addr, devad, regnum);
+ else
+ retval = bus->read(bus, addr, mdiobus_c45_addr(devad, regnum));
+
+ trace_mdio_access(bus, 1, addr, regnum, retval, retval);
+ mdiobus_stats_acct(&bus->stats[addr], true, retval);
+
+ return retval;
+}
+EXPORT_SYMBOL(__mdiobus_c45_read);
+
+/**
+ * __mdiobus_c45_write - Unlocked version of the mdiobus_write function
+ * @bus: the mii_bus struct
+ * @addr: the phy address
+ * @devad: device address to read
+ * @regnum: register number to write
+ * @val: value to write to @regnum
+ *
+ * Write a MDIO bus register. Caller must hold the mdio bus lock.
+ *
+ * NOTE: MUST NOT be called from interrupt context.
+ */
+int __mdiobus_c45_write(struct mii_bus *bus, int addr, int devad, u32 regnum,
+ u16 val)
+{
+ int err;
+
+ lockdep_assert_held_once(&bus->mdio_lock);
+
+ if (bus->write_c45)
+ err = bus->write_c45(bus, addr, devad, regnum, val);
+ else
+ err = bus->write(bus, addr, mdiobus_c45_addr(devad, regnum),
+ val);
+
+ trace_mdio_access(bus, 0, addr, regnum, val, err);
+ mdiobus_stats_acct(&bus->stats[addr], false, err);
+
+ return err;
+}
+EXPORT_SYMBOL(__mdiobus_c45_write);
+
+/**
+ * __mdiobus_c45_modify_changed - Unlocked version of the mdiobus_modify function
+ * @bus: the mii_bus struct
+ * @addr: the phy address
+ * @devad: device address to read
+ * @regnum: register number to modify
+ * @mask: bit mask of bits to clear
+ * @set: bit mask of bits to set
+ *
+ * Read, modify, and if any change, write the register value back to the
+ * device. Any error returns a negative number.
+ *
+ * NOTE: MUST NOT be called from interrupt context.
+ */
+static int __mdiobus_c45_modify_changed(struct mii_bus *bus, int addr,
+ int devad, u32 regnum, u16 mask,
+ u16 set)
+{
+ int new, ret;
+
+ ret = __mdiobus_c45_read(bus, addr, devad, regnum);
+ if (ret < 0)
+ return ret;
+
+ new = (ret & ~mask) | set;
+ if (new == ret)
+ return 0;
+
+ ret = __mdiobus_c45_write(bus, addr, devad, regnum, new);
+
+ return ret < 0 ? ret : 1;
+}
+
/**
* mdiobus_read_nested - Nested version of the mdiobus_read function
* @bus: the mii_bus struct
@@ -873,6 +967,29 @@ int mdiobus_read(struct mii_bus *bus, int addr, u32 regnum)
}
EXPORT_SYMBOL(mdiobus_read);

+/**
+ * mdiobus_c45_read - Convenience function for reading a given MII mgmt register
+ * @bus: the mii_bus struct
+ * @addr: the phy address
+ * @devad: device address to read
+ * @regnum: register number to read
+ *
+ * NOTE: MUST NOT be called from interrupt context,
+ * because the bus read/write functions may wait for an interrupt
+ * to conclude the operation.
+ */
+int mdiobus_c45_read(struct mii_bus *bus, int addr, int devad, u32 regnum)
+{
+ int retval;
+
+ mutex_lock(&bus->mdio_lock);
+ retval = __mdiobus_c45_read(bus, addr, devad, regnum);
+ mutex_unlock(&bus->mdio_lock);
+
+ return retval;
+}
+EXPORT_SYMBOL(mdiobus_c45_read);
+
/**
* mdiobus_write_nested - Nested version of the mdiobus_write function
* @bus: the mii_bus struct
@@ -922,6 +1039,31 @@ int mdiobus_write(struct mii_bus *bus, int addr, u32 regnum, u16 val)
}
EXPORT_SYMBOL(mdiobus_write);

+/**
+ * mdiobus_c45_write - Convenience function for writing a given MII mgmt register
+ * @bus: the mii_bus struct
+ * @addr: the phy address
+ * @devad: device address to read
+ * @regnum: register number to write
+ * @val: value to write to @regnum
+ *
+ * NOTE: MUST NOT be called from interrupt context,
+ * because the bus read/write functions may wait for an interrupt
+ * to conclude the operation.
+ */
+int mdiobus_c45_write(struct mii_bus *bus, int addr, int devad, u32 regnum,
+ u16 val)
+{
+ int err;
+
+ mutex_lock(&bus->mdio_lock);
+ err = __mdiobus_c45_write(bus, addr, devad, regnum, val);
+ mutex_unlock(&bus->mdio_lock);
+
+ return err;
+}
+EXPORT_SYMBOL(mdiobus_c45_write);
+
/**
* mdiobus_modify - Convenience function for modifying a given mdio device
* register
@@ -943,6 +1085,30 @@ int mdiobus_modify(struct mii_bus *bus, int addr, u32 regnum, u16 mask, u16 set)
}
EXPORT_SYMBOL_GPL(mdiobus_modify);

+/**
+ * mdiobus_c45_modify - Convenience function for modifying a given mdio device
+ * register
+ * @bus: the mii_bus struct
+ * @addr: the phy address
+ * @devad: device address to read
+ * @regnum: register number to write
+ * @mask: bit mask of bits to clear
+ * @set: bit mask of bits to set
+ */
+int mdiobus_c45_modify(struct mii_bus *bus, int addr, int devad, u32 regnum,
+ u16 mask, u16 set)
+{
+ int err;
+
+ mutex_lock(&bus->mdio_lock);
+ err = __mdiobus_c45_modify_changed(bus, addr, devad, regnum,
+ mask, set);
+ mutex_unlock(&bus->mdio_lock);
+
+ return err < 0 ? err : 0;
+}
+EXPORT_SYMBOL_GPL(mdiobus_c45_modify);
+
/**
* mdiobus_modify_changed - Convenience function for modifying a given mdio
* device register and returning if it changed
@@ -965,6 +1131,29 @@ int mdiobus_modify_changed(struct mii_bus *bus, int addr, u32 regnum,
}
EXPORT_SYMBOL_GPL(mdiobus_modify_changed);

+/**
+ * mdiobus_c45_modify_changed - Convenience function for modifying a given mdio
+ * device register and returning if it changed
+ * @bus: the mii_bus struct
+ * @addr: the phy address
+ * @devad: device address to read
+ * @regnum: register number to write
+ * @mask: bit mask of bits to clear
+ * @set: bit mask of bits to set
+ */
+int mdiobus_c45_modify_changed(struct mii_bus *bus, int devad, int addr,
+ u32 regnum, u16 mask, u16 set)
+{
+ int err;
+
+ mutex_lock(&bus->mdio_lock);
+ err = __mdiobus_c45_modify_changed(bus, addr, devad, regnum, mask, set);
+ mutex_unlock(&bus->mdio_lock);
+
+ return err;
+}
+EXPORT_SYMBOL_GPL(mdiobus_c45_modify_changed);
+
/**
* mdio_bus_match - determine if given MDIO driver supports the given
* MDIO device
diff --git a/include/linux/mdio.h b/include/linux/mdio.h
index f7fbbf3069e7..1e78c8410b21 100644
--- a/include/linux/mdio.h
+++ b/include/linux/mdio.h
@@ -423,6 +423,17 @@ int mdiobus_modify(struct mii_bus *bus, int addr, u32 regnum, u16 mask,
u16 set);
int mdiobus_modify_changed(struct mii_bus *bus, int addr, u32 regnum,
u16 mask, u16 set);
+int __mdiobus_c45_read(struct mii_bus *bus, int addr, int devad, u32 regnum);
+int mdiobus_c45_read(struct mii_bus *bus, int addr, int devad, u32 regnum);
+int __mdiobus_c45_write(struct mii_bus *bus, int addr, int devad, u32 regnum,
+ u16 val);
+int mdiobus_c45_write(struct mii_bus *bus, int addr, int devad, u32 regnum,
+ u16 val);
+int mdiobus_c45_modify(struct mii_bus *bus, int addr, int devad, u32 regnum,
+ u16 mask, u16 set);
+
+int mdiobus_c45_modify_changed(struct mii_bus *bus, int addr, int devad,
+ u32 regnum, u16 mask, u16 set);

static inline int mdiodev_read(struct mdio_device *mdiodev, u32 regnum)
{
@@ -463,29 +474,19 @@ static inline u16 mdiobus_c45_devad(u32 regnum)
return FIELD_GET(MII_DEVADDR_C45_MASK, regnum);
}

-static inline int __mdiobus_c45_read(struct mii_bus *bus, int prtad, int devad,
- u16 regnum)
+static inline int mdiodev_c45_modify(struct mdio_device *mdiodev, int devad,
+ u32 regnum, u16 mask, u16 set)
{
- return __mdiobus_read(bus, prtad, mdiobus_c45_addr(devad, regnum));
+ return mdiobus_c45_modify(mdiodev->bus, mdiodev->addr, devad, regnum,
+ mask, set);
}

-static inline int __mdiobus_c45_write(struct mii_bus *bus, int prtad, int devad,
- u16 regnum, u16 val)
+static inline int mdiodev_c45_modify_changed(struct mdio_device *mdiodev,
+ int devad, u32 regnum, u16 mask,
+ u16 set)
{
- return __mdiobus_write(bus, prtad, mdiobus_c45_addr(devad, regnum),
- val);
-}
-
-static inline int mdiobus_c45_read(struct mii_bus *bus, int prtad, int devad,
- u16 regnum)
-{
- return mdiobus_read(bus, prtad, mdiobus_c45_addr(devad, regnum));
-}
-
-static inline int mdiobus_c45_write(struct mii_bus *bus, int prtad, int devad,
- u16 regnum, u16 val)
-{
- return mdiobus_write(bus, prtad, mdiobus_c45_addr(devad, regnum), val);
+ return mdiobus_c45_modify_changed(mdiodev->bus, mdiodev->addr, devad,
+ regnum, mask, set);
}

static inline int mdiodev_c45_read(struct mdio_device *mdiodev, int devad,
diff --git a/include/linux/phy.h b/include/linux/phy.h
index 71eeb4e3b1fd..c33ad3255e3a 100644
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -364,6 +364,11 @@ struct mii_bus {
int (*read)(struct mii_bus *bus, int addr, int regnum);
/** @write: Perform a write transfer on the bus */
int (*write)(struct mii_bus *bus, int addr, int regnum, u16 val);
+ /** @read: Perform a C45 read transfer on the bus */
+ int (*read_c45)(struct mii_bus *bus, int addr, int devnum, int regnum);
+ /** @write: Perform a C45 write transfer on the bus */
+ int (*write_c45)(struct mii_bus *bus, int addr, int devnum,
+ int regnum, u16 val);
/** @reset: Perform a reset of the bus */
int (*reset)(struct mii_bus *bus);


--
2.30.2

2022-12-27 23:43:25

by Michael Walle

[permalink] [raw]
Subject: [PATCH RFC net-next v2 09/12] net: ethernet: freescale: fec: Separate C22 and C45 transactions for xgmac

From: Andrew Lunn <[email protected]>

The fec MDIO bus driver can perform both C22 and C45 transfers.
Create separate functions for each and register the C45 versions using
the new API calls where appropriate.

Signed-off-by: Andrew Lunn <[email protected]>
Signed-off-by: Michael Walle <[email protected]>
---
v2:
- [al] Fixup some indentation
---
drivers/net/ethernet/freescale/fec_main.c | 153 ++++++++++++++++++++----------
1 file changed, 103 insertions(+), 50 deletions(-)

diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c
index 644f3c963730..e6238e53940d 100644
--- a/drivers/net/ethernet/freescale/fec_main.c
+++ b/drivers/net/ethernet/freescale/fec_main.c
@@ -1987,47 +1987,74 @@ static int fec_enet_mdio_wait(struct fec_enet_private *fep)
return ret;
}

-static int fec_enet_mdio_read(struct mii_bus *bus, int mii_id, int regnum)
+static int fec_enet_mdio_read_c22(struct mii_bus *bus, int mii_id, int regnum)
{
struct fec_enet_private *fep = bus->priv;
struct device *dev = &fep->pdev->dev;
int ret = 0, frame_start, frame_addr, frame_op;
- bool is_c45 = !!(regnum & MII_ADDR_C45);

ret = pm_runtime_resume_and_get(dev);
if (ret < 0)
return ret;

- if (is_c45) {
- frame_start = FEC_MMFR_ST_C45;
+ /* C22 read */
+ frame_op = FEC_MMFR_OP_READ;
+ frame_start = FEC_MMFR_ST;
+ frame_addr = regnum;

- /* write address */
- frame_addr = (regnum >> 16);
- writel(frame_start | FEC_MMFR_OP_ADDR_WRITE |
- FEC_MMFR_PA(mii_id) | FEC_MMFR_RA(frame_addr) |
- FEC_MMFR_TA | (regnum & 0xFFFF),
- fep->hwp + FEC_MII_DATA);
+ /* start a read op */
+ writel(frame_start | frame_op |
+ FEC_MMFR_PA(mii_id) | FEC_MMFR_RA(frame_addr) |
+ FEC_MMFR_TA, fep->hwp + FEC_MII_DATA);

- /* wait for end of transfer */
- ret = fec_enet_mdio_wait(fep);
- if (ret) {
- netdev_err(fep->netdev, "MDIO address write timeout\n");
- goto out;
- }
+ /* wait for end of transfer */
+ ret = fec_enet_mdio_wait(fep);
+ if (ret) {
+ netdev_err(fep->netdev, "MDIO read timeout\n");
+ goto out;
+ }

- frame_op = FEC_MMFR_OP_READ_C45;
+ ret = FEC_MMFR_DATA(readl(fep->hwp + FEC_MII_DATA));

- } else {
- /* C22 read */
- frame_op = FEC_MMFR_OP_READ;
- frame_start = FEC_MMFR_ST;
- frame_addr = regnum;
+out:
+ pm_runtime_mark_last_busy(dev);
+ pm_runtime_put_autosuspend(dev);
+
+ return ret;
+}
+
+static int fec_enet_mdio_read_c45(struct mii_bus *bus, int mii_id,
+ int devad, int regnum)
+{
+ struct fec_enet_private *fep = bus->priv;
+ struct device *dev = &fep->pdev->dev;
+ int ret = 0, frame_start, frame_op;
+
+ ret = pm_runtime_resume_and_get(dev);
+ if (ret < 0)
+ return ret;
+
+ frame_start = FEC_MMFR_ST_C45;
+
+ /* write address */
+ writel(frame_start | FEC_MMFR_OP_ADDR_WRITE |
+ FEC_MMFR_PA(mii_id) | FEC_MMFR_RA(devad) |
+ FEC_MMFR_TA | (regnum & 0xFFFF),
+ fep->hwp + FEC_MII_DATA);
+
+ /* wait for end of transfer */
+ ret = fec_enet_mdio_wait(fep);
+ if (ret) {
+ netdev_err(fep->netdev, "MDIO address write timeout\n");
+ goto out;
}

+ frame_op = FEC_MMFR_OP_READ_C45;
+
/* start a read op */
writel(frame_start | frame_op |
- FEC_MMFR_PA(mii_id) | FEC_MMFR_RA(frame_addr) |
- FEC_MMFR_TA, fep->hwp + FEC_MII_DATA);
+ FEC_MMFR_PA(mii_id) | FEC_MMFR_RA(devad) |
+ FEC_MMFR_TA, fep->hwp + FEC_MII_DATA);

/* wait for end of transfer */
ret = fec_enet_mdio_wait(fep);
@@ -2045,45 +2072,69 @@ static int fec_enet_mdio_read(struct mii_bus *bus, int mii_id, int regnum)
return ret;
}

-static int fec_enet_mdio_write(struct mii_bus *bus, int mii_id, int regnum,
- u16 value)
+static int fec_enet_mdio_write_c22(struct mii_bus *bus, int mii_id, int regnum,
+ u16 value)
{
struct fec_enet_private *fep = bus->priv;
struct device *dev = &fep->pdev->dev;
int ret, frame_start, frame_addr;
- bool is_c45 = !!(regnum & MII_ADDR_C45);

ret = pm_runtime_resume_and_get(dev);
if (ret < 0)
return ret;

- if (is_c45) {
- frame_start = FEC_MMFR_ST_C45;
+ /* C22 write */
+ frame_start = FEC_MMFR_ST;
+ frame_addr = regnum;

- /* write address */
- frame_addr = (regnum >> 16);
- writel(frame_start | FEC_MMFR_OP_ADDR_WRITE |
- FEC_MMFR_PA(mii_id) | FEC_MMFR_RA(frame_addr) |
- FEC_MMFR_TA | (regnum & 0xFFFF),
- fep->hwp + FEC_MII_DATA);
+ /* start a write op */
+ writel(frame_start | FEC_MMFR_OP_WRITE |
+ FEC_MMFR_PA(mii_id) | FEC_MMFR_RA(frame_addr) |
+ FEC_MMFR_TA | FEC_MMFR_DATA(value),
+ fep->hwp + FEC_MII_DATA);

- /* wait for end of transfer */
- ret = fec_enet_mdio_wait(fep);
- if (ret) {
- netdev_err(fep->netdev, "MDIO address write timeout\n");
- goto out;
- }
- } else {
- /* C22 write */
- frame_start = FEC_MMFR_ST;
- frame_addr = regnum;
+ /* wait for end of transfer */
+ ret = fec_enet_mdio_wait(fep);
+ if (ret)
+ netdev_err(fep->netdev, "MDIO write timeout\n");
+
+ pm_runtime_mark_last_busy(dev);
+ pm_runtime_put_autosuspend(dev);
+
+ return ret;
+}
+
+static int fec_enet_mdio_write_c45(struct mii_bus *bus, int mii_id,
+ int devad, int regnum, u16 value)
+{
+ struct fec_enet_private *fep = bus->priv;
+ struct device *dev = &fep->pdev->dev;
+ int ret, frame_start;
+
+ ret = pm_runtime_resume_and_get(dev);
+ if (ret < 0)
+ return ret;
+
+ frame_start = FEC_MMFR_ST_C45;
+
+ /* write address */
+ writel(frame_start | FEC_MMFR_OP_ADDR_WRITE |
+ FEC_MMFR_PA(mii_id) | FEC_MMFR_RA(devad) |
+ FEC_MMFR_TA | (regnum & 0xFFFF),
+ fep->hwp + FEC_MII_DATA);
+
+ /* wait for end of transfer */
+ ret = fec_enet_mdio_wait(fep);
+ if (ret) {
+ netdev_err(fep->netdev, "MDIO address write timeout\n");
+ goto out;
}

/* start a write op */
writel(frame_start | FEC_MMFR_OP_WRITE |
- FEC_MMFR_PA(mii_id) | FEC_MMFR_RA(frame_addr) |
- FEC_MMFR_TA | FEC_MMFR_DATA(value),
- fep->hwp + FEC_MII_DATA);
+ FEC_MMFR_PA(mii_id) | FEC_MMFR_RA(devad) |
+ FEC_MMFR_TA | FEC_MMFR_DATA(value),
+ fep->hwp + FEC_MII_DATA);

/* wait for end of transfer */
ret = fec_enet_mdio_wait(fep);
@@ -2381,8 +2432,10 @@ static int fec_enet_mii_init(struct platform_device *pdev)
}

fep->mii_bus->name = "fec_enet_mii_bus";
- fep->mii_bus->read = fec_enet_mdio_read;
- fep->mii_bus->write = fec_enet_mdio_write;
+ fep->mii_bus->read = fec_enet_mdio_read_c22;
+ fep->mii_bus->write = fec_enet_mdio_write_c22;
+ fep->mii_bus->read_c45 = fec_enet_mdio_read_c45;
+ fep->mii_bus->write_c45 = fec_enet_mdio_write_c45;
snprintf(fep->mii_bus->id, MII_BUS_ID_SIZE, "%s-%x",
pdev->name, fep->dev_id + 1);
fep->mii_bus->priv = fep;

--
2.30.2

2022-12-28 03:51:01

by Wei Fang

[permalink] [raw]
Subject: RE: [PATCH RFC net-next v2 09/12] net: ethernet: freescale: fec: Separate C22 and C45 transactions for xgmac

> -----Original Message-----
> From: Michael Walle <[email protected]>
> Sent: 2022年12月28日 7:07
> To: Heiner Kallweit <[email protected]>; Russell King
> <[email protected]>; David S. Miller <[email protected]>; Eric
> Dumazet <[email protected]>; Jakub Kicinski <[email protected]>; Paolo
> Abeni <[email protected]>; Jose Abreu <[email protected]>;
> Sergey Shtylyov <[email protected]>; Wei Fang <[email protected]>;
> Shenwei Wang <[email protected]>; Clark Wang
> <[email protected]>; dl-linux-imx <[email protected]>; Sean Wang
> <[email protected]>; Landen Chao <[email protected]>;
> DENG Qingfang <[email protected]>; Florian Fainelli <[email protected]>;
> Vladimir Oltean <[email protected]>; Matthias Brugger
> <[email protected]>
> Cc: [email protected]; [email protected];
> [email protected]; [email protected];
> [email protected]; Andrew Lunn <[email protected]>; Geert
> Uytterhoeven <[email protected]>; Michael Walle <[email protected]>
> Subject: [PATCH RFC net-next v2 09/12] net: ethernet: freescale: fec: Separate
> C22 and C45 transactions for xgmac
>
> From: Andrew Lunn <[email protected]>
>
> The fec MDIO bus driver can perform both C22 and C45 transfers.
> Create separate functions for each and register the C45 versions using
> the new API calls where appropriate.
>
> Signed-off-by: Andrew Lunn <[email protected]>
> Signed-off-by: Michael Walle <[email protected]>
> ---
> v2:
> - [al] Fixup some indentation
> ---
> drivers/net/ethernet/freescale/fec_main.c | 153
> ++++++++++++++++++++----------
> 1 file changed, 103 insertions(+), 50 deletions(-)
>
> diff --git a/drivers/net/ethernet/freescale/fec_main.c
> b/drivers/net/ethernet/freescale/fec_main.c
> index 644f3c963730..e6238e53940d 100644
> --- a/drivers/net/ethernet/freescale/fec_main.c
> +++ b/drivers/net/ethernet/freescale/fec_main.c
> @@ -1987,47 +1987,74 @@ static int fec_enet_mdio_wait(struct
> fec_enet_private *fep)
> return ret;
> }
>
> -static int fec_enet_mdio_read(struct mii_bus *bus, int mii_id, int regnum)
> +static int fec_enet_mdio_read_c22(struct mii_bus *bus, int mii_id, int
> regnum)
> {
> struct fec_enet_private *fep = bus->priv;
> struct device *dev = &fep->pdev->dev;
> int ret = 0, frame_start, frame_addr, frame_op;
> - bool is_c45 = !!(regnum & MII_ADDR_C45);
>
> ret = pm_runtime_resume_and_get(dev);
> if (ret < 0)
> return ret;
>
> - if (is_c45) {
> - frame_start = FEC_MMFR_ST_C45;
> + /* C22 read */
> + frame_op = FEC_MMFR_OP_READ;
> + frame_start = FEC_MMFR_ST;
> + frame_addr = regnum;
>
> - /* write address */
> - frame_addr = (regnum >> 16);
> - writel(frame_start | FEC_MMFR_OP_ADDR_WRITE |
> - FEC_MMFR_PA(mii_id) | FEC_MMFR_RA(frame_addr) |
> - FEC_MMFR_TA | (regnum & 0xFFFF),
> - fep->hwp + FEC_MII_DATA);
> + /* start a read op */
> + writel(frame_start | frame_op |
> + FEC_MMFR_PA(mii_id) | FEC_MMFR_RA(frame_addr) |
> + FEC_MMFR_TA, fep->hwp + FEC_MII_DATA);
>
> - /* wait for end of transfer */
> - ret = fec_enet_mdio_wait(fep);
> - if (ret) {
> - netdev_err(fep->netdev, "MDIO address write timeout\n");
> - goto out;
> - }
> + /* wait for end of transfer */
> + ret = fec_enet_mdio_wait(fep);
> + if (ret) {
> + netdev_err(fep->netdev, "MDIO read timeout\n");
> + goto out;
> + }
>
> - frame_op = FEC_MMFR_OP_READ_C45;
> + ret = FEC_MMFR_DATA(readl(fep->hwp + FEC_MII_DATA));
>
> - } else {
> - /* C22 read */
> - frame_op = FEC_MMFR_OP_READ;
> - frame_start = FEC_MMFR_ST;
> - frame_addr = regnum;
> +out:
> + pm_runtime_mark_last_busy(dev);
> + pm_runtime_put_autosuspend(dev);
> +
> + return ret;
> +}
> +
> +static int fec_enet_mdio_read_c45(struct mii_bus *bus, int mii_id,
> + int devad, int regnum)
> +{
> + struct fec_enet_private *fep = bus->priv;
> + struct device *dev = &fep->pdev->dev;
> + int ret = 0, frame_start, frame_op;
> +
> + ret = pm_runtime_resume_and_get(dev);
> + if (ret < 0)
> + return ret;
> +
> + frame_start = FEC_MMFR_ST_C45;
> +
> + /* write address */
> + writel(frame_start | FEC_MMFR_OP_ADDR_WRITE |
> + FEC_MMFR_PA(mii_id) | FEC_MMFR_RA(devad) |
> + FEC_MMFR_TA | (regnum & 0xFFFF),
> + fep->hwp + FEC_MII_DATA);
> +
> + /* wait for end of transfer */
> + ret = fec_enet_mdio_wait(fep);
> + if (ret) {
> + netdev_err(fep->netdev, "MDIO address write timeout\n");
> + goto out;
> }
>
> + frame_op = FEC_MMFR_OP_READ_C45;
> +
> /* start a read op */
> writel(frame_start | frame_op |
> - FEC_MMFR_PA(mii_id) | FEC_MMFR_RA(frame_addr) |
> - FEC_MMFR_TA, fep->hwp + FEC_MII_DATA);
> + FEC_MMFR_PA(mii_id) | FEC_MMFR_RA(devad) |
> + FEC_MMFR_TA, fep->hwp + FEC_MII_DATA);
>
> /* wait for end of transfer */
> ret = fec_enet_mdio_wait(fep);
> @@ -2045,45 +2072,69 @@ static int fec_enet_mdio_read(struct mii_bus
> *bus, int mii_id, int regnum)
> return ret;
> }
>
> -static int fec_enet_mdio_write(struct mii_bus *bus, int mii_id, int regnum,
> - u16 value)
> +static int fec_enet_mdio_write_c22(struct mii_bus *bus, int mii_id, int
> regnum,
> + u16 value)
> {
> struct fec_enet_private *fep = bus->priv;
> struct device *dev = &fep->pdev->dev;
> int ret, frame_start, frame_addr;
> - bool is_c45 = !!(regnum & MII_ADDR_C45);
>
> ret = pm_runtime_resume_and_get(dev);
> if (ret < 0)
> return ret;
>
> - if (is_c45) {
> - frame_start = FEC_MMFR_ST_C45;
> + /* C22 write */
> + frame_start = FEC_MMFR_ST;
> + frame_addr = regnum;
>
> - /* write address */
> - frame_addr = (regnum >> 16);
> - writel(frame_start | FEC_MMFR_OP_ADDR_WRITE |
> - FEC_MMFR_PA(mii_id) | FEC_MMFR_RA(frame_addr) |
> - FEC_MMFR_TA | (regnum & 0xFFFF),
> - fep->hwp + FEC_MII_DATA);
> + /* start a write op */
> + writel(frame_start | FEC_MMFR_OP_WRITE |
> + FEC_MMFR_PA(mii_id) | FEC_MMFR_RA(frame_addr) |
> + FEC_MMFR_TA | FEC_MMFR_DATA(value),
> + fep->hwp + FEC_MII_DATA);
>
> - /* wait for end of transfer */
> - ret = fec_enet_mdio_wait(fep);
> - if (ret) {
> - netdev_err(fep->netdev, "MDIO address write timeout\n");
> - goto out;
> - }
> - } else {
> - /* C22 write */
> - frame_start = FEC_MMFR_ST;
> - frame_addr = regnum;
> + /* wait for end of transfer */
> + ret = fec_enet_mdio_wait(fep);
> + if (ret)
> + netdev_err(fep->netdev, "MDIO write timeout\n");
> +
> + pm_runtime_mark_last_busy(dev);
> + pm_runtime_put_autosuspend(dev);
> +
> + return ret;
> +}
> +
> +static int fec_enet_mdio_write_c45(struct mii_bus *bus, int mii_id,
> + int devad, int regnum, u16 value)
> +{
> + struct fec_enet_private *fep = bus->priv;
> + struct device *dev = &fep->pdev->dev;
> + int ret, frame_start;
> +
> + ret = pm_runtime_resume_and_get(dev);
> + if (ret < 0)
> + return ret;
> +
> + frame_start = FEC_MMFR_ST_C45;
> +
> + /* write address */
> + writel(frame_start | FEC_MMFR_OP_ADDR_WRITE |
> + FEC_MMFR_PA(mii_id) | FEC_MMFR_RA(devad) |
> + FEC_MMFR_TA | (regnum & 0xFFFF),
> + fep->hwp + FEC_MII_DATA);
> +
> + /* wait for end of transfer */
> + ret = fec_enet_mdio_wait(fep);
> + if (ret) {
> + netdev_err(fep->netdev, "MDIO address write timeout\n");
> + goto out;
> }
>
> /* start a write op */
> writel(frame_start | FEC_MMFR_OP_WRITE |
> - FEC_MMFR_PA(mii_id) | FEC_MMFR_RA(frame_addr) |
> - FEC_MMFR_TA | FEC_MMFR_DATA(value),
> - fep->hwp + FEC_MII_DATA);
> + FEC_MMFR_PA(mii_id) | FEC_MMFR_RA(devad) |
> + FEC_MMFR_TA | FEC_MMFR_DATA(value),
> + fep->hwp + FEC_MII_DATA);
>
> /* wait for end of transfer */
> ret = fec_enet_mdio_wait(fep);
> @@ -2381,8 +2432,10 @@ static int fec_enet_mii_init(struct platform_device
> *pdev)
> }
>
> fep->mii_bus->name = "fec_enet_mii_bus";
> - fep->mii_bus->read = fec_enet_mdio_read;
> - fep->mii_bus->write = fec_enet_mdio_write;
> + fep->mii_bus->read = fec_enet_mdio_read_c22;
> + fep->mii_bus->write = fec_enet_mdio_write_c22;
> + fep->mii_bus->read_c45 = fec_enet_mdio_read_c45;
> + fep->mii_bus->write_c45 = fec_enet_mdio_write_c45;
> snprintf(fep->mii_bus->id, MII_BUS_ID_SIZE, "%s-%x",
> pdev->name, fep->dev_id + 1);
> fep->mii_bus->priv = fep;
>

It looks good to me.
Reviewed-by: Wei Fang <[email protected]>

2023-01-03 10:21:46

by Russell King (Oracle)

[permalink] [raw]
Subject: Re: [PATCH RFC net-next v2 03/12] net: mdio: mdiobus_register: update validation test

Hi Michael,

Thanks for picking this up!

On Wed, Dec 28, 2022 at 12:07:19AM +0100, Michael Walle wrote:
> + if (!bus || !bus->name)
> + return -EINVAL;
> +
> + /* An access method always needs both read and write operations */
> + if ((bus->read && !bus->write) ||
> + (!bus->read && bus->write) ||
> + (bus->read_c45 && !bus->write_c45) ||
> + (!bus->read_c45 && bus->write_c45))

I wonder whether the following would be even more readable:

if (!bus->read != !bus->write || !bus->read_c45 != !bus->write_c45)

which essentially asserts that the boolean of !method for the read and
write methods must match.

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

2023-01-03 10:49:10

by Michael Walle

[permalink] [raw]
Subject: Re: [PATCH RFC net-next v2 03/12] net: mdio: mdiobus_register: update validation test

Hi Russell,

Am 2023-01-03 11:13, schrieb Russell King (Oracle):
> On Wed, Dec 28, 2022 at 12:07:19AM +0100, Michael Walle wrote:
>> + if (!bus || !bus->name)
>> + return -EINVAL;
>> +
>> + /* An access method always needs both read and write operations */
>> + if ((bus->read && !bus->write) ||
>> + (!bus->read && bus->write) ||
>> + (bus->read_c45 && !bus->write_c45) ||
>> + (!bus->read_c45 && bus->write_c45))
>
> I wonder whether the following would be even more readable:
>
> if (!bus->read != !bus->write || !bus->read_c45 != !bus->write_c45)

That's what Andrew had originally. But there was a comment from Sergey
[1]
which I agree with. I had a hard time wrapping my head around that, so I
just listed all the possible bad cases.

I don't have a strong opinion, though.

> which essentially asserts that the boolean of !method for the read and
> write methods must match.

Maybe with that as a comment?

-michael

[1]
https://lore.kernel.org/netdev/[email protected]/

2023-01-03 13:38:51

by Michael Walle

[permalink] [raw]
Subject: Re: [PATCH RFC net-next v2 06/12] net: mdio: mdio-bitbang: Separate C22 and C45 transactions

Am 2023-01-03 14:15, schrieb Vladimir Oltean:
> On Wed, Dec 28, 2022 at 12:07:22AM +0100, Michael Walle wrote:
>> From: Andrew Lunn <[email protected]>
>>
>> The bitbbanging bus driver can perform both C22 and C45 transfers.
>> Create separate functions for each and register the C45 versions using
>> the new driver API calls.
>>
>> The SH Ethernet driver places wrappers around these functions. In
>> order to not break boards which might be using C45, add similar
>> wrappers for C45 operations.
>>
>> Reviewed-by: Geert Uytterhoeven <[email protected]>
>> Signed-off-by: Andrew Lunn <[email protected]>
>> Signed-off-by: Michael Walle <[email protected]>
>> ---
>
> Incomplete conversion, this breaks the build. Need to update all users
> of the bitbang driver (also davinci_mdio). Something like the diff
> below
> fixes that, but it leaves the davinci_mdio driver in a partially
> converted state (if data->manual_mode is true, new API is used,
> otherwise old API is used). So another patch to convert the other case
> will likely be needed.

The intel build bot already notified me about this. Unfortunately, only
privately as I just noticed.

And yes, these are just the first 12 patches of a larger series.

-michael

2023-01-03 13:40:22

by Vladimir Oltean

[permalink] [raw]
Subject: Re: [PATCH RFC net-next v2 02/12] net: pcs: pcs-xpcs: Use C45 MDIO API

On Wed, Dec 28, 2022 at 12:07:18AM +0100, Michael Walle wrote:
> From: Andrew Lunn <[email protected]>
>
> Convert the PCS-XPCS driver to make use of the C45 MDIO bus API for
> modify_change().
>
> Signed-off-by: Andrew Lunn <[email protected]>
> Signed-off-by: Michael Walle <[email protected]>
> ---

Reviewed-by: Vladimir Oltean <[email protected]>

2023-01-03 13:40:41

by Vladimir Oltean

[permalink] [raw]
Subject: Re: [PATCH RFC net-next v2 06/12] net: mdio: mdio-bitbang: Separate C22 and C45 transactions

On Wed, Dec 28, 2022 at 12:07:22AM +0100, Michael Walle wrote:
> From: Andrew Lunn <[email protected]>
>
> The bitbbanging bus driver can perform both C22 and C45 transfers.
> Create separate functions for each and register the C45 versions using
> the new driver API calls.
>
> The SH Ethernet driver places wrappers around these functions. In
> order to not break boards which might be using C45, add similar
> wrappers for C45 operations.
>
> Reviewed-by: Geert Uytterhoeven <[email protected]>
> Signed-off-by: Andrew Lunn <[email protected]>
> Signed-off-by: Michael Walle <[email protected]>
> ---

Incomplete conversion, this breaks the build. Need to update all users
of the bitbang driver (also davinci_mdio). Something like the diff below
fixes that, but it leaves the davinci_mdio driver in a partially
converted state (if data->manual_mode is true, new API is used,
otherwise old API is used). So another patch to convert the other case
will likely be needed.

diff --git a/drivers/net/ethernet/ti/davinci_mdio.c b/drivers/net/ethernet/ti/davinci_mdio.c
index 946b9753ccfb..23169e36a3d4 100644
--- a/drivers/net/ethernet/ti/davinci_mdio.c
+++ b/drivers/net/ethernet/ti/davinci_mdio.c
@@ -225,7 +225,7 @@ static int davinci_get_mdio_data(struct mdiobb_ctrl *ctrl)
return test_bit(MDIO_PIN, &reg);
}

-static int davinci_mdiobb_read(struct mii_bus *bus, int phy, int reg)
+static int davinci_mdiobb_read_c22(struct mii_bus *bus, int phy, int reg)
{
int ret;

@@ -233,7 +233,7 @@ static int davinci_mdiobb_read(struct mii_bus *bus, int phy, int reg)
if (ret < 0)
return ret;

- ret = mdiobb_read(bus, phy, reg);
+ ret = mdiobb_read_c22(bus, phy, reg);

pm_runtime_mark_last_busy(bus->parent);
pm_runtime_put_autosuspend(bus->parent);
@@ -241,8 +241,8 @@ static int davinci_mdiobb_read(struct mii_bus *bus, int phy, int reg)
return ret;
}

-static int davinci_mdiobb_write(struct mii_bus *bus, int phy, int reg,
- u16 val)
+static int davinci_mdiobb_write_c22(struct mii_bus *bus, int phy, int reg,
+ u16 val)
{
int ret;

@@ -250,7 +250,41 @@ static int davinci_mdiobb_write(struct mii_bus *bus, int phy, int reg,
if (ret < 0)
return ret;

- ret = mdiobb_write(bus, phy, reg, val);
+ ret = mdiobb_write_c22(bus, phy, reg, val);
+
+ pm_runtime_mark_last_busy(bus->parent);
+ pm_runtime_put_autosuspend(bus->parent);
+
+ return ret;
+}
+
+static int davinci_mdiobb_read_c45(struct mii_bus *bus, int phy, int devad,
+ int reg)
+{
+ int ret;
+
+ ret = pm_runtime_resume_and_get(bus->parent);
+ if (ret < 0)
+ return ret;
+
+ ret = mdiobb_read_c45(bus, phy, devad, reg);
+
+ pm_runtime_mark_last_busy(bus->parent);
+ pm_runtime_put_autosuspend(bus->parent);
+
+ return ret;
+}
+
+static int davinci_mdiobb_write_c45(struct mii_bus *bus, int phy, int devad,
+ int reg, u16 val)
+{
+ int ret;
+
+ ret = pm_runtime_resume_and_get(bus->parent);
+ if (ret < 0)
+ return ret;
+
+ ret = mdiobb_write_c45(bus, phy, devad, reg, val);

pm_runtime_mark_last_busy(bus->parent);
pm_runtime_put_autosuspend(bus->parent);
@@ -573,8 +607,10 @@ static int davinci_mdio_probe(struct platform_device *pdev)
data->bus->name = dev_name(dev);

if (data->manual_mode) {
- data->bus->read = davinci_mdiobb_read;
- data->bus->write = davinci_mdiobb_write;
+ data->bus->read = davinci_mdiobb_read_c22;
+ data->bus->write = davinci_mdiobb_write_c22;
+ data->bus->read_c45 = davinci_mdiobb_read_c45;
+ data->bus->write_c45 = davinci_mdiobb_write_c45;
data->bus->reset = davinci_mdiobb_reset;

dev_info(dev, "Configuring MDIO in manual mode\n");

2023-01-03 14:06:51

by Vladimir Oltean

[permalink] [raw]
Subject: Re: [PATCH RFC net-next v2 08/12] net: ethernet: freescale: xgmac: Separate C22 and C45 transactions for xgmac

Commit message can be: "net/fsl: xgmac_mdio: Separate C22 and C45 transactions".

On Wed, Dec 28, 2022 at 12:07:24AM +0100, Michael Walle wrote:
> From: Andrew Lunn <[email protected]>
>
> The xgmac MDIO bus driver can perform both C22 and C45 transfers.
> Create separate functions for each and register the C45 versions using
> the new API calls where appropriate.
>
> Signed-off-by: Andrew Lunn <[email protected]>
> Signed-off-by: Michael Walle <[email protected]>
> ---
> v2:
> - [al] Move the masking of regnum into the variable declarations
> - [al] Remove a couple of blank lines

Tested-by: Vladimir Oltean <[email protected]>

>
> -/*
> - * Reads from register regnum in the PHY for device dev, returning the value.
> +/* Reads from register regnum in the PHY for device dev, returning the value.
> * Clears miimcom first. All PHY configuration has to be done through the
> * TSEC1 MIIM regs.
> */

I have some reservations regarding the utility of the comments in this
driver. It's surely not worth duplicating them between C22 and C45.
It might also be more productive to just delete them, because:

- miimcom is a register accessed by fsl_pq_mdio.c, not by xgmac_mdio.c
- "device dev" doesn't really refer to anything (maybe "dev_addr").
- I don't understand what is meant by the comment "All PHY configuration
has to be done through the TSEC1 MIIM regs". Or rather said, I think I
understand, but it is irrelevant to the driver for 2 reasons:
* TSEC devices use the fsl_pq_mdio.c driver, not this one
* It doesn't matter to this driver whose TSEC registers are used for
MDIO access. The driver just works with the registers it's given,
which is a concern for the device tree.
- barring the above, the rest just describes the MDIO bus API, which is
superfluous

2023-01-03 14:16:46

by Vladimir Oltean

[permalink] [raw]
Subject: Re: [PATCH RFC net-next v2 09/12] net: ethernet: freescale: fec: Separate C22 and C45 transactions for xgmac

Regarding the commit title, there's no xgmac block in the FEC. "XG"
means 10 Gbps, surely there's no such thing on imx/Vybrid. Can just say:
"net: fec: Separate C22 and C45 MDIO transactions".

2023-01-03 16:09:04

by Andrew Lunn

[permalink] [raw]
Subject: Re: [PATCH RFC net-next v2 11/12] net: dsa: Separate C22 and C45 MDIO bus transaction methods

> Since clause 45 PHYs are identified by the "ethernet-phy-ieee802.3-c45"
> compatible string (otherwise they are C22), then a PHY which is not
> described in the device tree can only be C22. So this is why
> ds->slave_mii_bus only deals with clause 22 methods, and the true reason
> behind the comment above.
>
> But actually this premise is no longer true since Luiz' commit
> fe7324b93222 ("net: dsa: OF-ware slave_mii_bus"), which introduced the
> strange concept of an "OF-aware helper for internal PHYs which are not
> described in the device tree". After his patch, it is possible to have
> something like this:
>
> ethernet-switch {
> ethernet-ports {
> port@1 {
> reg = <1>;
> };
> };
>
> mdio {
> ethernet-phy@1 {
> compatible = "ethernet-phy-ieee802.3-c45"
> reg = <1>;
> };
> };
> };
>
> As you can see, this is a clause 45 internal PHY which lacks a
> phy-handle, so its bus must be put in ds->slave_mii_bus in order for
> dsa_slave_phy_connect() to see it without that phy-handle (based on the
> port number matching with the PHY number). After Luiz' patch, this kind
> of device tree is possible, and it invalidates the assumption about
> ds->slave_mii_bus only driving C22 PHYs.

My memory is hazy, but i think at the time i wrote these patches,
there was no DSA driver which made use of ds->slave_mii_bus with
C45. So i took the short cut of only supporting C22.

Those DSA drivers which do support C45 all register their bus directly
with the MDIO core.

So Luiz patches may allow a C45 bus, but are there any drivers today
actually using it?

Andrew

2023-01-03 16:11:02

by Vladimir Oltean

[permalink] [raw]
Subject: Re: [PATCH RFC net-next v2 11/12] net: dsa: Separate C22 and C45 MDIO bus transaction methods

On Wed, Dec 28, 2022 at 12:07:27AM +0100, Michael Walle wrote:
> From: Andrew Lunn <[email protected]>
>
> By adding _c45 function pointers to the dsa_switch_op structure, the
> dsa core can register an MDIO bus with C45 accessors.
>
> The dsa-loop driver could in theory provide such accessors, since it
> just passed requests to the MDIO bus it is on, but it seems unlikely
> to be useful at the moment. It can however be added later.
>
> mt7530 does support C45, but its uses a mix of registering its MDIO
> bus and using the DSA core provided bus. This makes the change a bit
> more complex.

"using the DSA core provided bus" is a misrepresentation AFAICS.
Rather said, "providing its private MDIO bus to the DSA core too".

>
> Signed-off-by: Andrew Lunn <[email protected]>
> Signed-off-by: Michael Walle <[email protected]>
> ---
> v2:
> - [al] Remove conditional c45, since all switches support c45
> - [al] Remove dsa core changes, they are not needed
> - [al] Add comment that DSA provided MDIO bus is C22 only.
> ---
> drivers/net/dsa/mt7530.c | 87 ++++++++++++++++++++++++------------------------
> drivers/net/dsa/mt7530.h | 15 ++++++---
> include/net/dsa.h | 2 +-
> 3 files changed, 56 insertions(+), 48 deletions(-)

This patch is not very coherent after the changes in v2.

There are really 2 distinct pieces:

1. a comment in include/net/dsa.h, which provides a justification for
why dsa_switch_ops :: {phy_read(), phy_write()} weren't split into
{phy_read(), phy_write()} and {phy_read_c45() and phy_write_c45()}.

2. a conversion of the mt7530 MDIO bus driver.

I would expect these to be distinct patches.

> diff --git a/include/net/dsa.h b/include/net/dsa.h
> index 96086289aa9b..732c7bc261a9 100644
> --- a/include/net/dsa.h
> +++ b/include/net/dsa.h
> @@ -858,7 +858,7 @@ struct dsa_switch_ops {
> u32 (*get_phy_flags)(struct dsa_switch *ds, int port);
>
> /*
> - * Access to the switch's PHY registers.
> + * Access to the switch's PHY registers. C22 only.
> */
> int (*phy_read)(struct dsa_switch *ds, int port, int regnum);
> int (*phy_write)(struct dsa_switch *ds, int port,

Let me try to untangle for you what these operations really do.
When they are present, DSA will allocate ds->slave_mii_bus on behalf of
the driver, and use these methods for MDIO access of internal PHYs.

The purpose of ds->slave_mii_bus is to offer a non-OF based
phy_connect() for old-style device trees where there is no phy-handle
between the user port fwnode and the internal PHY fwnode (normally
because the ethernet-phy isn't described in the device tree at all).

Like this:

ethernet-switch {
ethernet-ports {
port@1 {
reg = <1>;
};
};
};

So ds->slave_mii_bus is useful with or without the ds->ops->phy_read()
and ds->ops->phy_write() pointers, which is for example why mt7530
allocates its own MDIO bus with its own private methods (so it doesn't
populate ds->ops->phy_read()), but it also populates ds->slave_mii_bus
with its own bus.

Since clause 45 PHYs are identified by the "ethernet-phy-ieee802.3-c45"
compatible string (otherwise they are C22), then a PHY which is not
described in the device tree can only be C22. So this is why
ds->slave_mii_bus only deals with clause 22 methods, and the true reason
behind the comment above.

But actually this premise is no longer true since Luiz' commit
fe7324b93222 ("net: dsa: OF-ware slave_mii_bus"), which introduced the
strange concept of an "OF-aware helper for internal PHYs which are not
described in the device tree". After his patch, it is possible to have
something like this:

ethernet-switch {
ethernet-ports {
port@1 {
reg = <1>;
};
};

mdio {
ethernet-phy@1 {
compatible = "ethernet-phy-ieee802.3-c45"
reg = <1>;
};
};
};

As you can see, this is a clause 45 internal PHY which lacks a
phy-handle, so its bus must be put in ds->slave_mii_bus in order for
dsa_slave_phy_connect() to see it without that phy-handle (based on the
port number matching with the PHY number). After Luiz' patch, this kind
of device tree is possible, and it invalidates the assumption about
ds->slave_mii_bus only driving C22 PHYs.

>
> --
> 2.30.2

2023-01-03 16:12:40

by Vladimir Oltean

[permalink] [raw]
Subject: Re: [PATCH RFC net-next v2 11/12] net: dsa: Separate C22 and C45 MDIO bus transaction methods

On Tue, Jan 03, 2023 at 04:48:59PM +0100, Andrew Lunn wrote:
> > Since clause 45 PHYs are identified by the "ethernet-phy-ieee802.3-c45"
> > compatible string (otherwise they are C22), then a PHY which is not
> > described in the device tree can only be C22. So this is why
> > ds->slave_mii_bus only deals with clause 22 methods, and the true reason
> > behind the comment above.
> >
> > But actually this premise is no longer true since Luiz' commit
> > fe7324b93222 ("net: dsa: OF-ware slave_mii_bus"), which introduced the
> > strange concept of an "OF-aware helper for internal PHYs which are not
> > described in the device tree". After his patch, it is possible to have
> > something like this:
> >
> > ethernet-switch {
> > ethernet-ports {
> > port@1 {
> > reg = <1>;
> > };
> > };
> >
> > mdio {
> > ethernet-phy@1 {
> > compatible = "ethernet-phy-ieee802.3-c45"
> > reg = <1>;
> > };
> > };
> > };
> >
> > As you can see, this is a clause 45 internal PHY which lacks a
> > phy-handle, so its bus must be put in ds->slave_mii_bus in order for
> > dsa_slave_phy_connect() to see it without that phy-handle (based on the
> > port number matching with the PHY number). After Luiz' patch, this kind
> > of device tree is possible, and it invalidates the assumption about
> > ds->slave_mii_bus only driving C22 PHYs.
>
> My memory is hazy, but i think at the time i wrote these patches,
> there was no DSA driver which made use of ds->slave_mii_bus with
> C45. So i took the short cut of only supporting C22.

Actually I believe that in v1 you did extend ds->ops with C45 methods,
but it's me who told you to remove them:
https://patchwork.kernel.org/project/netdevbpf/patch/[email protected]/#24852813

>
> Those DSA drivers which do support C45 all register their bus directly
> with the MDIO core.

And rightfully so. IMHO, letting DSA allocate ds->slave_mii_bus out of
driver writer sheer convenience (a secondary purpose) should be deprecated,
unless the reason for using ds->slave_mii_bus is the lack of a phy-handle
(the primary purpose). It becomes that more confusing to have to extend
dsa_switch_ops with 2 more methods which serve the secondary purpose but
not the primary one.

> So Luiz patches may allow a C45 bus, but are there any drivers today
> actually using it?

I sent a private email to Luiz a few minutes ago asking him to confirm.

2023-01-03 16:24:31

by Vladimir Oltean

[permalink] [raw]
Subject: Re: [PATCH RFC net-next v2 12/12] net: dsa: mv88e6xxx: Separate C22 and C45 transactions

On Wed, Dec 28, 2022 at 12:07:28AM +0100, Michael Walle wrote:
> From: Andrew Lunn <[email protected]>
>
> The global2 SMI MDIO bus driver can perform both C22 and C45
> transfers. Create separate functions for each and register the C45
> versions using the new API calls where appropriate. Update the SERDES
> code to make use of these new accessors.
>
> Signed-off-by: Andrew Lunn <[email protected]>
> Signed-off-by: Michael Walle <[email protected]>
> ---

Reviewed-by: Vladimir Oltean <[email protected]>

2023-01-03 22:48:24

by Russell King (Oracle)

[permalink] [raw]
Subject: Re: [PATCH RFC net-next v2 03/12] net: mdio: mdiobus_register: update validation test

Hi Michael,

On Tue, Jan 03, 2023 at 11:21:08AM +0100, Michael Walle wrote:
> Hi Russell,
>
> Am 2023-01-03 11:13, schrieb Russell King (Oracle):
> > On Wed, Dec 28, 2022 at 12:07:19AM +0100, Michael Walle wrote:
> > > + if (!bus || !bus->name)
> > > + return -EINVAL;
> > > +
> > > + /* An access method always needs both read and write operations */
> > > + if ((bus->read && !bus->write) ||
> > > + (!bus->read && bus->write) ||
> > > + (bus->read_c45 && !bus->write_c45) ||
> > > + (!bus->read_c45 && bus->write_c45))
> >
> > I wonder whether the following would be even more readable:
> >
> > if (!bus->read != !bus->write || !bus->read_c45 != !bus->write_c45)
>
> That's what Andrew had originally. But there was a comment from Sergey [1]
> which I agree with. I had a hard time wrapping my head around that, so I
> just listed all the possible bad cases.

The only reason I suggested it was because when looked at your code,
it also took several reads to work out what it was trying to do!

Would using !!bus->read != !!bus->write would help or make it worse,
!!ptr being the more normal way to convert something to a boolean?

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

2023-01-09 12:44:49

by Michael Walle

[permalink] [raw]
Subject: Re: [PATCH RFC net-next v2 03/12] net: mdio: mdiobus_register: update validation test

Hi Russell,

Am 2023-01-03 23:19, schrieb Russell King (Oracle):
> On Tue, Jan 03, 2023 at 11:21:08AM +0100, Michael Walle wrote:
>> Am 2023-01-03 11:13, schrieb Russell King (Oracle):
>> > On Wed, Dec 28, 2022 at 12:07:19AM +0100, Michael Walle wrote:
>> > > + if (!bus || !bus->name)
>> > > + return -EINVAL;
>> > > +
>> > > + /* An access method always needs both read and write operations */
>> > > + if ((bus->read && !bus->write) ||
>> > > + (!bus->read && bus->write) ||
>> > > + (bus->read_c45 && !bus->write_c45) ||
>> > > + (!bus->read_c45 && bus->write_c45))
>> >
>> > I wonder whether the following would be even more readable:
>> >
>> > if (!bus->read != !bus->write || !bus->read_c45 != !bus->write_c45)
>>
>> That's what Andrew had originally. But there was a comment from Sergey
>> [1]
>> which I agree with. I had a hard time wrapping my head around that, so
>> I
>> just listed all the possible bad cases.
>
> The only reason I suggested it was because when looked at your code,
> it also took several reads to work out what it was trying to do!
>
> Would using !!bus->read != !!bus->write would help or make it worse,
> !!ptr being the more normal way to convert something to a boolean?

IMHO that makes it even harder. But I doubt we will find an expression
that will work for everyone. I'll go with your suggestion/Andrew's first
version in the next iteration.

-michael

2023-01-09 13:04:41

by Vladimir Oltean

[permalink] [raw]
Subject: Re: [PATCH RFC net-next v2 03/12] net: mdio: mdiobus_register: update validation test

On Mon, Jan 09, 2023 at 01:35:29PM +0100, Michael Walle wrote:
> Hi Russell,
>
> Am 2023-01-03 23:19, schrieb Russell King (Oracle):
> > On Tue, Jan 03, 2023 at 11:21:08AM +0100, Michael Walle wrote:
> > > Am 2023-01-03 11:13, schrieb Russell King (Oracle):
> > > > On Wed, Dec 28, 2022 at 12:07:19AM +0100, Michael Walle wrote:
> > > > > + if (!bus || !bus->name)
> > > > > + return -EINVAL;
> > > > > +
> > > > > + /* An access method always needs both read and write operations */
> > > > > + if ((bus->read && !bus->write) ||
> > > > > + (!bus->read && bus->write) ||
> > > > > + (bus->read_c45 && !bus->write_c45) ||
> > > > > + (!bus->read_c45 && bus->write_c45))
> > > >
> > > > I wonder whether the following would be even more readable:
> > > >
> > > > if (!bus->read != !bus->write || !bus->read_c45 != !bus->write_c45)
> > >
> > > That's what Andrew had originally. But there was a comment from
> > > Sergey [1]
> > > which I agree with. I had a hard time wrapping my head around that,
> > > so I
> > > just listed all the possible bad cases.
> >
> > The only reason I suggested it was because when looked at your code,
> > it also took several reads to work out what it was trying to do!
> >
> > Would using !!bus->read != !!bus->write would help or make it worse,
> > !!ptr being the more normal way to convert something to a boolean?
>
> IMHO that makes it even harder. But I doubt we will find an expression
> that will work for everyone. I'll go with your suggestion/Andrew's first
> version in the next iteration.

I think the double negation conveys the intention better than the simple
one, actually (maybe even xor instead of != ?). In terms of readability
I think I prefer the way the patch is written right now, but if you keep
the comment, the double negation should be pretty easy to swallow too.

2023-01-16 09:07:12

by Michael Walle

[permalink] [raw]
Subject: Re: [PATCH RFC net-next v2 11/12] net: dsa: Separate C22 and C45 MDIO bus transaction methods

Hi,

Am 2023-01-03 16:56, schrieb Vladimir Oltean:
>> So Luiz patches may allow a C45 bus, but are there any drivers today
>> actually using it?
>
> I sent a private email to Luiz a few minutes ago asking him to confirm.

Any news here? Do we need the c45 methods?

-michael

2023-01-16 19:38:17

by Vladimir Oltean

[permalink] [raw]
Subject: Re: [PATCH RFC net-next v2 11/12] net: dsa: Separate C22 and C45 MDIO bus transaction methods

On Mon, Jan 16, 2023 at 08:51:55AM +0100, Michael Walle wrote:
> Hi,
>
> Am 2023-01-03 16:56, schrieb Vladimir Oltean:
> > > So Luiz patches may allow a C45 bus, but are there any drivers today
> > > actually using it?
> >
> > I sent a private email to Luiz a few minutes ago asking him to confirm.
>
> Any news here? Do we need the c45 methods?

No news it seems. I am going to default to assuming that no, a ds->slave_mii_bus
created by dsa_switch_setup() does not need C45 accessors.

This patch should be modified to only touch the mt7530 driver, and
adjust the commit message accordingly. I see no connection to what the
DSA core does.