kernel: copy kernel 4.19 code to 5.4
[openwrt/openwrt.git] / target / linux / generic / pending-5.4 / 745-net-mdio-i2c-add-support-for-Clause-45-accesses.patch
diff --git a/target/linux/generic/pending-5.4/745-net-mdio-i2c-add-support-for-Clause-45-accesses.patch b/target/linux/generic/pending-5.4/745-net-mdio-i2c-add-support-for-Clause-45-accesses.patch
new file mode 100644 (file)
index 0000000..9a4bb5b
--- /dev/null
@@ -0,0 +1,74 @@
+From c9de73988a35c6c85810a992954ac568cca503e5 Mon Sep 17 00:00:00 2001
+From: Russell King <rmk+kernel@armlinux.org.uk>
+Date: Wed, 2 Oct 2019 10:31:10 +0100
+Subject: [PATCH 648/660] net: mdio-i2c: add support for Clause 45 accesses
+
+Some SFP+ modules have PHYs on them just like SFP modules do, except
+they are Clause 45 PHYs.  The I2C protocol used to access them is
+modified slightly in order to send the device address and 16-bit
+register index.
+
+Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
+---
+ drivers/net/phy/mdio-i2c.c | 28 ++++++++++++++++++++--------
+ 1 file changed, 20 insertions(+), 8 deletions(-)
+
+--- a/drivers/net/phy/mdio-i2c.c
++++ b/drivers/net/phy/mdio-i2c.c
+@@ -36,17 +36,24 @@ static int i2c_mii_read(struct mii_bus *
+ {
+       struct i2c_adapter *i2c = bus->priv;
+       struct i2c_msg msgs[2];
+-      u8 data[2], dev_addr = reg;
++      u8 addr[3], data[2], *p;
+       int bus_addr, ret;
+       if (!i2c_mii_valid_phy_id(phy_id))
+               return 0xffff;
++      p = addr;
++      if (reg & MII_ADDR_C45) {
++              *p++ = 0x20 | ((reg >> 16) & 31);
++              *p++ = reg >> 8;
++      }
++      *p++ = reg;
++
+       bus_addr = i2c_mii_phy_addr(phy_id);
+       msgs[0].addr = bus_addr;
+       msgs[0].flags = 0;
+-      msgs[0].len = 1;
+-      msgs[0].buf = &dev_addr;
++      msgs[0].len = p - addr;
++      msgs[0].buf = addr;
+       msgs[1].addr = bus_addr;
+       msgs[1].flags = I2C_M_RD;
+       msgs[1].len = sizeof(data);
+@@ -64,18 +71,23 @@ static int i2c_mii_write(struct mii_bus
+       struct i2c_adapter *i2c = bus->priv;
+       struct i2c_msg msg;
+       int ret;
+-      u8 data[3];
++      u8 data[5], *p;
+       if (!i2c_mii_valid_phy_id(phy_id))
+               return 0;
+-      data[0] = reg;
+-      data[1] = val >> 8;
+-      data[2] = val;
++      p = data;
++      if (reg & MII_ADDR_C45) {
++              *p++ = (reg >> 16) & 31;
++              *p++ = reg >> 8;
++      }
++      *p++ = reg;
++      *p++ = val >> 8;
++      *p++ = val;
+       msg.addr = i2c_mii_phy_addr(phy_id);
+       msg.flags = 0;
+-      msg.len = 3;
++      msg.len = p - data;
+       msg.buf = data;
+       ret = i2c_transfer(i2c, &msg, 1);