]> git.proxmox.com Git - mirror_ubuntu-kernels.git/commitdiff
net: mdio: mdio-bitbang: Separate C22 and C45 transactions
authorAndrew Lunn <andrew@lunn.ch>
Mon, 9 Jan 2023 15:30:46 +0000 (16:30 +0100)
committerJakub Kicinski <kuba@kernel.org>
Tue, 10 Jan 2023 23:53:36 +0000 (15:53 -0800)
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 <geert+renesas@glider.be>
Signed-off-by: Andrew Lunn <andrew@lunn.ch>
Signed-off-by: Michael Walle <michael@walle.cc>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
drivers/net/ethernet/renesas/sh_eth.c
drivers/net/ethernet/ti/davinci_mdio.c
drivers/net/mdio/mdio-bitbang.c
include/linux/mdio-bitbang.h

index 71a4991133080fac9bbbbc20437a09025795fc6d..ed17163d781144f7d41aca9a356f66e4f6ca3879 100644 (file)
@@ -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";
index 946b9753ccfb3837de38f117c0b32fea43f797e7..23169e36a3d4c227edae9c8db2b88c19ec609e8d 100644 (file)
@@ -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");
index 07609114a26b231294dadc2202ef6b2f624c5e2c..b83932562be2157dbbe1512a816b5fa60ee4eff7 100644 (file)
@@ -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;
index 373630fe5c281a60a21976095ae65b8fea1d1ff7..cffabdbce075a541c849dce7851b2836d6e47e33 100644 (file)
@@ -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);