netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH net-next v4 0/4] Support for RollBall 10G copper SFP modules
@ 2021-01-11  5:00 Marek Behún
  2021-01-11  5:00 ` [PATCH net-next v4 1/4] net: phy: mdio-i2c: support I2C MDIO protocol for RollBall " Marek Behún
                   ` (3 more replies)
  0 siblings, 4 replies; 29+ messages in thread
From: Marek Behún @ 2021-01-11  5:00 UTC (permalink / raw)
  To: netdev
  Cc: Russell King, Andrew Lunn, Jakub Kicinski, davem, pali, Marek Behún

Hello,

this is v4 of series adding support for RollBall/Hilink SFP modules.

Checked with:
  checkpatch.pl --max-line-length=80

Changes from v3:
- RollBall mdio-i2c driver now sets/restores SFP_PAGE for every MDIO
  access.
  I first wanted to achieve this operation (setting
  SFP_PAGE/doing MDIO/restoring SFP_PAGE) via one call do i2c_transfer,
  by constructing msgs array in such a way, but it turned out that this
  doesn't work on RollBall SFPs, because changed SFP_PAGE takes into
  account only after i2c_transfer ends.
  So instead I use i2c_lock_bus/serveral __i2c_transfers/i2c_unlock_bus.
- I have removed the patch which changes MACTYPE in the marvell10g
  driver, since Russell has in his net-queue a better solution. I still
  think that my patch would have sufficed temporarily (and would not
  cause regressions), but nobody wanted to review it. If you think that
  I should sent this series again with that patch, please let me know.

Changes from v2:
- added comment into the patch adding support for RollBall I2C MDIO
  protocol, saying that we expect the SFP_PAGE not to be changed by
  the SFP code, as requested by Russell. If, in the future, SFP code
  starts modifying SFP_PAGE, we will have to handle it in mdio-i2c
  somehow
- destruction of I2C MDIO bus in patch 3/5 now depends on whether the
  MDIO bus is not NULL, instead of whether PHY exists, as suggested by
  Russell
- changed waiting time for RollBall module to initialize from 30 seconds
  to 25 seconds. Testing shows that it is never longer than 21-22
  seconds, so waiting 25 seconds instead of 30 is IMO safe enough
- added Russell's Reviewed-by tags where relevant

Changes from v1:
- wrapped to 80 columns as per Russell's request
- initialization of RollBall MDIO I2C protocol moved from sfp.c to
  mdio-i2c.c as per Russell's request
- second patch removes the 802.3z check also from phylink_sfp_config
  as suggested by Russell
- creation/destruction of mdiobus for SFP now occurs before probing
  for PHY/after releasing PHY (as suggested by Russell)
- the last patch became a little simpler after the above was done

Cc: Andrew Lunn <andrew@lunn.ch>
Cc: Russell King <rmk+kernel@armlinux.org.uk>

Marek Behún (4):
  net: phy: mdio-i2c: support I2C MDIO protocol for RollBall SFP modules
  net: phylink: allow attaching phy for SFP modules on 802.3z mode
  net: sfp: create/destroy I2C mdiobus before PHY probe/after PHY
    release
  net: sfp: add support for multigig RollBall transceivers

 drivers/net/mdio/mdio-i2c.c   | 319 +++++++++++++++++++++++++++++++++-
 drivers/net/phy/phylink.c     |   5 +-
 drivers/net/phy/sfp.c         |  66 +++++--
 include/linux/mdio/mdio-i2c.h |   8 +-
 4 files changed, 378 insertions(+), 20 deletions(-)


base-commit: 73b7a6047971aa6ce4a70fc4901964d14f077171
-- 
2.26.2


^ permalink raw reply	[flat|nested] 29+ messages in thread

* [PATCH net-next v4 1/4] net: phy: mdio-i2c: support I2C MDIO protocol for RollBall SFP modules
  2021-01-11  5:00 [PATCH net-next v4 0/4] Support for RollBall 10G copper SFP modules Marek Behún
@ 2021-01-11  5:00 ` Marek Behún
  2021-01-12  8:42   ` Heiner Kallweit
                     ` (4 more replies)
  2021-01-11  5:00 ` [PATCH net-next v4 2/4] net: phylink: allow attaching phy for SFP modules on 802.3z mode Marek Behún
                   ` (2 subsequent siblings)
  3 siblings, 5 replies; 29+ messages in thread
From: Marek Behún @ 2021-01-11  5:00 UTC (permalink / raw)
  To: netdev
  Cc: Russell King, Andrew Lunn, Jakub Kicinski, davem, pali, Marek Behún

Some multigig SFPs from RollBall and Hilink do not expose functional
MDIO access to the internal PHY of the SFP via I2C address 0x56
(although there seems to be read-only clause 22 access on this address).

Instead these SFPs PHY can be accessed via I2C via the SFP Enhanced
Digital Diagnostic Interface - I2C address 0x51. The SFP_PAGE has to be
selected to 3 and the password must be filled with 0xff bytes for this
PHY communication to work.

This extends the mdio-i2c driver to support this protocol by adding a
special parameter to mdio_i2c_alloc function via which this RollBall
protocol can be selected.

Signed-off-by: Marek Behún <kabel@kernel.org>
Cc: Andrew Lunn <andrew@lunn.ch>
Cc: Russell King <rmk+kernel@armlinux.org.uk>
---
 drivers/net/mdio/mdio-i2c.c   | 319 +++++++++++++++++++++++++++++++++-
 drivers/net/phy/sfp.c         |   2 +-
 include/linux/mdio/mdio-i2c.h |   8 +-
 3 files changed, 322 insertions(+), 7 deletions(-)

diff --git a/drivers/net/mdio/mdio-i2c.c b/drivers/net/mdio/mdio-i2c.c
index 09200a70b315..7be582c0891a 100644
--- a/drivers/net/mdio/mdio-i2c.c
+++ b/drivers/net/mdio/mdio-i2c.c
@@ -3,6 +3,7 @@
  * MDIO I2C bridge
  *
  * Copyright (C) 2015-2016 Russell King
+ * Copyright (C) 2021 Marek Behun
  *
  * Network PHYs can appear on I2C buses when they are part of SFP module.
  * This driver exposes these PHYs to the networking PHY code, allowing
@@ -12,6 +13,7 @@
 #include <linux/i2c.h>
 #include <linux/mdio/mdio-i2c.h>
 #include <linux/phy.h>
+#include <linux/sfp.h>
 
 /*
  * I2C bus addresses 0x50 and 0x51 are normally an EEPROM, which is
@@ -28,7 +30,7 @@ static unsigned int i2c_mii_phy_addr(int phy_id)
 	return phy_id + 0x40;
 }
 
-static int i2c_mii_read(struct mii_bus *bus, int phy_id, int reg)
+static int i2c_mii_read_default(struct mii_bus *bus, int phy_id, int reg)
 {
 	struct i2c_adapter *i2c = bus->priv;
 	struct i2c_msg msgs[2];
@@ -62,7 +64,8 @@ static int i2c_mii_read(struct mii_bus *bus, int phy_id, int reg)
 	return data[0] << 8 | data[1];
 }
 
-static int i2c_mii_write(struct mii_bus *bus, int phy_id, int reg, u16 val)
+static int i2c_mii_write_default(struct mii_bus *bus, int phy_id, int reg,
+				 u16 val)
 {
 	struct i2c_adapter *i2c = bus->priv;
 	struct i2c_msg msg;
@@ -91,9 +94,297 @@ static int i2c_mii_write(struct mii_bus *bus, int phy_id, int reg, u16 val)
 	return ret < 0 ? ret : 0;
 }
 
-struct mii_bus *mdio_i2c_alloc(struct device *parent, struct i2c_adapter *i2c)
+/* RollBall SFPs do not access internal PHY via I2C address 0x56, but
+ * instead via address 0x51, when SFP page is set to 0x03 and password to
+ * 0xffffffff.
+ * Since current SFP code does not modify SFP_PAGE, we set it to 0x03 only at
+ * bus creation time, and expect it to remain set to 0x03 throughout the
+ * lifetime of the module plugged into the system. If the SFP code starts
+ * modifying SFP_PAGE in the future, this code will need to change.
+ *
+ * address  size  contents  description
+ * -------  ----  --------  -----------
+ * 0x80     1     CMD       0x01/0x02/0x04 for write/read/done
+ * 0x81     1     DEV       Clause 45 device
+ * 0x82     2     REG       Clause 45 register
+ * 0x84     2     VAL       Register value
+ */
+#define ROLLBALL_PHY_I2C_ADDR		0x51
+#define ROLLBALL_SFP_PASSWORD_ADDR	0x7b
+
+#define ROLLBALL_CMD_ADDR		0x80
+#define ROLLBALL_DATA_ADDR		0x81
+
+#define ROLLBALL_CMD_WRITE		0x01
+#define ROLLBALL_CMD_READ		0x02
+#define ROLLBALL_CMD_DONE		0x04
+
+#define SFP_PAGE_ROLLBALL_MDIO		3
+
+static int __i2c_transfer_err(struct i2c_adapter *i2c, struct i2c_msg *msgs,
+			      int num)
+{
+	int ret;
+
+	ret = __i2c_transfer(i2c, msgs, num);
+	if (ret < 0)
+		return ret;
+	else if (ret != num)
+		return -EIO;
+	else
+		return 0;
+}
+
+static int __i2c_rollball_get_page(struct i2c_adapter *i2c, int bus_addr,
+				   u8 *page)
+{
+	struct i2c_msg msgs[2];
+	u8 addr = SFP_PAGE;
+
+	msgs[0].addr = bus_addr;
+	msgs[0].flags = 0;
+	msgs[0].len = 1;
+	msgs[0].buf = &addr;
+
+	msgs[1].addr = bus_addr;
+	msgs[1].flags = I2C_M_RD;
+	msgs[1].len = 1;
+	msgs[1].buf = page;
+
+	return __i2c_transfer_err(i2c, msgs, 2);
+}
+
+static int __i2c_rollball_set_page(struct i2c_adapter *i2c, int bus_addr,
+				   u8 page)
+{
+	struct i2c_msg msg;
+	u8 buf[2];
+
+	buf[0] = SFP_PAGE;
+	buf[1] = page;
+
+	msg.addr = bus_addr;
+	msg.flags = 0;
+	msg.len = 2;
+	msg.buf = buf;
+
+	return __i2c_transfer_err(i2c, &msg, 1);
+}
+
+/* In order to not interfere with other SFP code (which possibly may manipulate
+ * SFP_PAGE), for every transfer we do this:
+ *   1. lock the bus
+ *   2. save content of SFP_PAGE
+ *   3. set SFP_PAGE to 3
+ *   4. do the transfer
+ *   5. restore original SFP_PAGE
+ *   6. unlock the bus
+ * Note that one might think that steps 2 to 5 could be theoretically done all
+ * in one call to i2c_transfer (by constructing msgs array in such a way), but
+ * unfortunately tests show that this does not work :-( Changed SFP_PAGE does
+ * not take into account until i2c_transfer() is done.
+ */
+static int i2c_transfer_rollball(struct i2c_adapter *i2c,
+				 struct i2c_msg *msgs, int num)
+{
+	u8 saved_page;
+	int ret;
+
+	i2c_lock_bus(i2c, I2C_LOCK_SEGMENT);
+
+	/* save original page */
+	ret = __i2c_rollball_get_page(i2c, msgs->addr, &saved_page);
+	if (ret)
+		goto unlock;
+
+	/* change to RollBall MDIO page */
+	ret = __i2c_rollball_set_page(i2c, msgs->addr, SFP_PAGE_ROLLBALL_MDIO);
+	if (ret)
+		goto unlock;
+
+	/* do the transfer */
+	ret = __i2c_transfer_err(i2c, msgs, num);
+	if (ret)
+		goto unlock;
+
+	/* restore original page */
+	ret = __i2c_rollball_set_page(i2c, msgs->addr, saved_page);
+
+unlock:
+	i2c_unlock_bus(i2c, I2C_LOCK_SEGMENT);
+
+	return ret;
+}
+
+static int i2c_rollball_mii_poll(struct mii_bus *bus, int bus_addr, u8 *buf,
+				 size_t len)
+{
+	struct i2c_adapter *i2c = bus->priv;
+	struct i2c_msg msgs[2];
+	u8 cmd_addr, tmp, *res;
+	int i, ret;
+
+	cmd_addr = ROLLBALL_CMD_ADDR;
+
+	res = buf ? buf : &tmp;
+	len = buf ? len : 1;
+
+	msgs[0].addr = bus_addr;
+	msgs[0].flags = 0;
+	msgs[0].len = 1;
+	msgs[0].buf = &cmd_addr;
+
+	msgs[1].addr = bus_addr;
+	msgs[1].flags = I2C_M_RD;
+	msgs[1].len = len;
+	msgs[1].buf = res;
+
+	/* By experiment it takes up to 70 ms to access a register for these
+	 * SFPs. Sleep 20ms between iteratios and try 10 times.
+	 */
+	i = 10;
+	do {
+		msleep(20);
+
+		ret = i2c_transfer_rollball(i2c, msgs, ARRAY_SIZE(msgs));
+		if (ret)
+			return ret;
+
+		if (*res == ROLLBALL_CMD_DONE)
+			return 0;
+	} while (i-- > 0);
+
+	dev_dbg(&bus->dev, "poll timed out\n");
+
+	return -ETIMEDOUT;
+}
+
+static int i2c_rollball_mii_cmd(struct mii_bus *bus, int bus_addr, u8 cmd,
+				u8 *data, size_t len)
+{
+	struct i2c_adapter *i2c = bus->priv;
+	struct i2c_msg msgs[2];
+	u8 cmdbuf[2];
+
+	cmdbuf[0] = ROLLBALL_CMD_ADDR;
+	cmdbuf[1] = cmd;
+
+	msgs[0].addr = bus_addr;
+	msgs[0].flags = 0;
+	msgs[0].len = len;
+	msgs[0].buf = data;
+
+	msgs[1].addr = bus_addr;
+	msgs[1].flags = 0;
+	msgs[1].len = sizeof(cmdbuf);
+	msgs[1].buf = cmdbuf;
+
+	return i2c_transfer_rollball(i2c, msgs, ARRAY_SIZE(msgs));
+}
+
+static int i2c_mii_read_rollball(struct mii_bus *bus, int phy_id, int reg)
+{
+	u8 buf[4], res[6];
+	int bus_addr, ret;
+	u16 val;
+
+	if (!(reg & MII_ADDR_C45))
+		return -EOPNOTSUPP;
+
+	bus_addr = i2c_mii_phy_addr(phy_id);
+	if (bus_addr != ROLLBALL_PHY_I2C_ADDR)
+		return 0xffff;
+
+	buf[0] = ROLLBALL_DATA_ADDR;
+	buf[1] = (reg >> 16) & 0x1f;
+	buf[2] = (reg >> 8) & 0xff;
+	buf[3] = reg & 0xff;
+
+	ret = i2c_rollball_mii_cmd(bus, bus_addr, ROLLBALL_CMD_READ, buf,
+				   sizeof(buf));
+	if (ret < 0)
+		return ret;
+
+	ret = i2c_rollball_mii_poll(bus, bus_addr, res, sizeof(res));
+	if (ret == -ETIMEDOUT)
+		return 0xffff;
+	else if (ret < 0)
+		return ret;
+
+	val = res[4] << 8 | res[5];
+
+	dev_dbg(&bus->dev, "read reg %02x:%04x = %04x\n", (reg >> 16) & 0x1f,
+		reg & 0xffff, val);
+
+	return val;
+}
+
+static int i2c_mii_write_rollball(struct mii_bus *bus, int phy_id, int reg,
+				  u16 val)
+{
+	int bus_addr, ret;
+	u8 buf[6];
+
+	if (!(reg & MII_ADDR_C45))
+		return -EOPNOTSUPP;
+
+	bus_addr = i2c_mii_phy_addr(phy_id);
+	if (bus_addr != ROLLBALL_PHY_I2C_ADDR)
+		return 0;
+
+	buf[0] = ROLLBALL_DATA_ADDR;
+	buf[1] = (reg >> 16) & 0x1f;
+	buf[2] = (reg >> 8) & 0xff;
+	buf[3] = reg & 0xff;
+	buf[4] = val >> 8;
+	buf[5] = val & 0xff;
+
+	ret = i2c_rollball_mii_cmd(bus, bus_addr, ROLLBALL_CMD_WRITE, buf,
+				   sizeof(buf));
+	if (ret < 0)
+		return ret;
+
+	ret = i2c_rollball_mii_poll(bus, bus_addr, NULL, 0);
+	if (ret < 0)
+		return ret;
+
+	dev_dbg(&bus->dev, "write reg %02x:%04x = %04x\n", (reg >> 16) & 0x1f,
+		reg & 0xffff, val);
+
+	return 0;
+}
+
+static int i2c_mii_init_rollball(struct i2c_adapter *i2c)
+{
+	struct i2c_msg msg;
+	u8 pw[5];
+	int ret;
+
+	pw[0] = ROLLBALL_SFP_PASSWORD_ADDR;
+	pw[1] = 0xff;
+	pw[2] = 0xff;
+	pw[3] = 0xff;
+	pw[4] = 0xff;
+
+	msg.addr = ROLLBALL_PHY_I2C_ADDR;
+	msg.flags = 0;
+	msg.len = sizeof(pw);
+	msg.buf = pw;
+
+	ret = i2c_transfer(i2c, &msg, 1);
+	if (ret < 0)
+		return ret;
+	else if (ret != 1)
+		return -EIO;
+	else
+		return 0;
+}
+
+struct mii_bus *mdio_i2c_alloc(struct device *parent, struct i2c_adapter *i2c,
+			       enum mdio_i2c_proto protocol)
 {
 	struct mii_bus *mii;
+	int ret;
 
 	if (!i2c_check_functionality(i2c, I2C_FUNC_I2C))
 		return ERR_PTR(-EINVAL);
@@ -104,10 +395,28 @@ struct mii_bus *mdio_i2c_alloc(struct device *parent, struct i2c_adapter *i2c)
 
 	snprintf(mii->id, MII_BUS_ID_SIZE, "i2c:%s", dev_name(parent));
 	mii->parent = parent;
-	mii->read = i2c_mii_read;
-	mii->write = i2c_mii_write;
 	mii->priv = i2c;
 
+	switch (protocol) {
+	case MDIO_I2C_ROLLBALL:
+		ret = i2c_mii_init_rollball(i2c);
+		if (ret < 0) {
+			dev_err(parent,
+				"Cannot initialize RollBall MDIO I2C protocol: %d\n",
+				ret);
+			mdiobus_free(mii);
+			return ERR_PTR(ret);
+		}
+
+		mii->read = i2c_mii_read_rollball;
+		mii->write = i2c_mii_write_rollball;
+		break;
+	default:
+		mii->read = i2c_mii_read_default;
+		mii->write = i2c_mii_write_default;
+		break;
+	}
+
 	return mii;
 }
 EXPORT_SYMBOL_GPL(mdio_i2c_alloc);
diff --git a/drivers/net/phy/sfp.c b/drivers/net/phy/sfp.c
index 91d74c1a920a..958fd514a3b4 100644
--- a/drivers/net/phy/sfp.c
+++ b/drivers/net/phy/sfp.c
@@ -419,7 +419,7 @@ static int sfp_i2c_configure(struct sfp *sfp, struct i2c_adapter *i2c)
 	sfp->read = sfp_i2c_read;
 	sfp->write = sfp_i2c_write;
 
-	i2c_mii = mdio_i2c_alloc(sfp->dev, i2c);
+	i2c_mii = mdio_i2c_alloc(sfp->dev, i2c, MDIO_I2C_DEFAULT);
 	if (IS_ERR(i2c_mii))
 		return PTR_ERR(i2c_mii);
 
diff --git a/include/linux/mdio/mdio-i2c.h b/include/linux/mdio/mdio-i2c.h
index b1d27f7cd23f..53eedb0dc1d3 100644
--- a/include/linux/mdio/mdio-i2c.h
+++ b/include/linux/mdio/mdio-i2c.h
@@ -11,6 +11,12 @@ struct device;
 struct i2c_adapter;
 struct mii_bus;
 
-struct mii_bus *mdio_i2c_alloc(struct device *parent, struct i2c_adapter *i2c);
+enum mdio_i2c_proto {
+	MDIO_I2C_DEFAULT,
+	MDIO_I2C_ROLLBALL,
+};
+
+struct mii_bus *mdio_i2c_alloc(struct device *parent, struct i2c_adapter *i2c,
+			       enum mdio_i2c_proto protocol);
 
 #endif
-- 
2.26.2


^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [PATCH net-next v4 2/4] net: phylink: allow attaching phy for SFP modules on 802.3z mode
  2021-01-11  5:00 [PATCH net-next v4 0/4] Support for RollBall 10G copper SFP modules Marek Behún
  2021-01-11  5:00 ` [PATCH net-next v4 1/4] net: phy: mdio-i2c: support I2C MDIO protocol for RollBall " Marek Behún
@ 2021-01-11  5:00 ` Marek Behún
  2021-01-13 10:38   ` Pali Rohár
  2021-01-11  5:00 ` [PATCH net-next v4 3/4] net: sfp: create/destroy I2C mdiobus before PHY probe/after PHY release Marek Behún
  2021-01-11  5:00 ` [PATCH net-next v4 4/4] net: sfp: add support for multigig RollBall transceivers Marek Behún
  3 siblings, 1 reply; 29+ messages in thread
From: Marek Behún @ 2021-01-11  5:00 UTC (permalink / raw)
  To: netdev
  Cc: Russell King, Andrew Lunn, Jakub Kicinski, davem, pali, Marek Behún

Some SFPs may contain an internal PHY which may in some cases want to
connect with the host interface in 1000base-x/2500base-x mode.
Do not fail if such PHY is being attached in one of these PHY interface
modes.

Signed-off-by: Marek Behún <kabel@kernel.org>
Reviewed-by: Russell King <rmk+kernel@armlinux.org.uk>
Cc: Andrew Lunn <andrew@lunn.ch>
---
 drivers/net/phy/phylink.c | 5 +----
 1 file changed, 1 insertion(+), 4 deletions(-)

diff --git a/drivers/net/phy/phylink.c b/drivers/net/phy/phylink.c
index 84f6e197f965..f97d041f82f4 100644
--- a/drivers/net/phy/phylink.c
+++ b/drivers/net/phy/phylink.c
@@ -1018,7 +1018,7 @@ static int phylink_attach_phy(struct phylink *pl, struct phy_device *phy,
 {
 	if (WARN_ON(pl->cfg_link_an_mode == MLO_AN_FIXED ||
 		    (pl->cfg_link_an_mode == MLO_AN_INBAND &&
-		     phy_interface_mode_is_8023z(interface))))
+		     phy_interface_mode_is_8023z(interface) && !pl->sfp_bus)))
 		return -EINVAL;
 
 	if (pl->phydev)
@@ -2069,9 +2069,6 @@ static int phylink_sfp_config(struct phylink *pl, u8 mode,
 		    phylink_an_mode_str(mode), phy_modes(config.interface),
 		    __ETHTOOL_LINK_MODE_MASK_NBITS, support);
 
-	if (phy_interface_mode_is_8023z(iface) && pl->phydev)
-		return -EINVAL;
-
 	changed = !linkmode_equal(pl->supported, support);
 	if (changed) {
 		linkmode_copy(pl->supported, support);
-- 
2.26.2


^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [PATCH net-next v4 3/4] net: sfp: create/destroy I2C mdiobus before PHY probe/after PHY release
  2021-01-11  5:00 [PATCH net-next v4 0/4] Support for RollBall 10G copper SFP modules Marek Behún
  2021-01-11  5:00 ` [PATCH net-next v4 1/4] net: phy: mdio-i2c: support I2C MDIO protocol for RollBall " Marek Behún
  2021-01-11  5:00 ` [PATCH net-next v4 2/4] net: phylink: allow attaching phy for SFP modules on 802.3z mode Marek Behún
@ 2021-01-11  5:00 ` Marek Behún
  2021-01-13 10:41   ` Pali Rohár
  2021-01-11  5:00 ` [PATCH net-next v4 4/4] net: sfp: add support for multigig RollBall transceivers Marek Behún
  3 siblings, 1 reply; 29+ messages in thread
From: Marek Behún @ 2021-01-11  5:00 UTC (permalink / raw)
  To: netdev
  Cc: Russell King, Andrew Lunn, Jakub Kicinski, davem, pali, Marek Behún

Instead of configuring the I2C mdiobus when SFP driver is probed,
create/destroy the mdiobus before the PHY is probed for/after it is
released.

This way we can tell the mdio-i2c code which protocol to use for each
SFP transceiver.

Signed-off-by: Marek Behún <kabel@kernel.org>
Cc: Andrew Lunn <andrew@lunn.ch>
Cc: Russell King <rmk+kernel@armlinux.org.uk>
---
 drivers/net/phy/sfp.c | 30 ++++++++++++++++++++++++++----
 1 file changed, 26 insertions(+), 4 deletions(-)

diff --git a/drivers/net/phy/sfp.c b/drivers/net/phy/sfp.c
index 958fd514a3b4..0621d12cf878 100644
--- a/drivers/net/phy/sfp.c
+++ b/drivers/net/phy/sfp.c
@@ -217,6 +217,7 @@ struct sfp {
 	struct i2c_adapter *i2c;
 	struct mii_bus *i2c_mii;
 	struct sfp_bus *sfp_bus;
+	enum mdio_i2c_proto mdio_protocol;
 	struct phy_device *mod_phy;
 	const struct sff_data *type;
 	size_t i2c_block_size;
@@ -409,9 +410,6 @@ static int sfp_i2c_write(struct sfp *sfp, bool a2, u8 dev_addr, void *buf,
 
 static int sfp_i2c_configure(struct sfp *sfp, struct i2c_adapter *i2c)
 {
-	struct mii_bus *i2c_mii;
-	int ret;
-
 	if (!i2c_check_functionality(i2c, I2C_FUNC_I2C))
 		return -EINVAL;
 
@@ -419,7 +417,15 @@ static int sfp_i2c_configure(struct sfp *sfp, struct i2c_adapter *i2c)
 	sfp->read = sfp_i2c_read;
 	sfp->write = sfp_i2c_write;
 
-	i2c_mii = mdio_i2c_alloc(sfp->dev, i2c, MDIO_I2C_DEFAULT);
+	return 0;
+}
+
+static int sfp_i2c_mdiobus_create(struct sfp *sfp)
+{
+	struct mii_bus *i2c_mii;
+	int ret;
+
+	i2c_mii = mdio_i2c_alloc(sfp->dev, sfp->i2c, sfp->mdio_protocol);
 	if (IS_ERR(i2c_mii))
 		return PTR_ERR(i2c_mii);
 
@@ -437,6 +443,12 @@ static int sfp_i2c_configure(struct sfp *sfp, struct i2c_adapter *i2c)
 	return 0;
 }
 
+static void sfp_i2c_mdiobus_destroy(struct sfp *sfp)
+{
+	mdiobus_unregister(sfp->i2c_mii);
+	sfp->i2c_mii = NULL;
+}
+
 /* Interface */
 static int sfp_read(struct sfp *sfp, bool a2, u8 addr, void *buf, size_t len)
 {
@@ -1821,6 +1833,8 @@ static int sfp_sm_mod_probe(struct sfp *sfp, bool report)
 	else
 		sfp->module_t_start_up = T_START_UP;
 
+	sfp->mdio_protocol = MDIO_I2C_DEFAULT;
+
 	return 0;
 }
 
@@ -1991,6 +2005,8 @@ static void sfp_sm_main(struct sfp *sfp, unsigned int event)
 			sfp_module_stop(sfp->sfp_bus);
 		if (sfp->mod_phy)
 			sfp_sm_phy_detach(sfp);
+		if (sfp->i2c_mii)
+			sfp_i2c_mdiobus_destroy(sfp);
 		sfp_module_tx_disable(sfp);
 		sfp_soft_stop_poll(sfp);
 		sfp_sm_next(sfp, SFP_S_DOWN, 0);
@@ -2053,6 +2069,12 @@ static void sfp_sm_main(struct sfp *sfp, unsigned int event)
 				     sfp->sm_fault_retries == N_FAULT_INIT);
 		} else if (event == SFP_E_TIMEOUT || event == SFP_E_TX_CLEAR) {
 	init_done:
+			/* Create mdiobus and start trying for PHY */
+			ret = sfp_i2c_mdiobus_create(sfp);
+			if (ret < 0) {
+				sfp_sm_next(sfp, SFP_S_FAIL, 0);
+				break;
+			}
 			sfp->sm_phy_retries = R_PHY_RETRY;
 			goto phy_probe;
 		}
-- 
2.26.2


^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [PATCH net-next v4 4/4] net: sfp: add support for multigig RollBall transceivers
  2021-01-11  5:00 [PATCH net-next v4 0/4] Support for RollBall 10G copper SFP modules Marek Behún
                   ` (2 preceding siblings ...)
  2021-01-11  5:00 ` [PATCH net-next v4 3/4] net: sfp: create/destroy I2C mdiobus before PHY probe/after PHY release Marek Behún
@ 2021-01-11  5:00 ` Marek Behún
  2021-01-13 10:49   ` Pali Rohár
  3 siblings, 1 reply; 29+ messages in thread
From: Marek Behún @ 2021-01-11  5:00 UTC (permalink / raw)
  To: netdev
  Cc: Russell King, Andrew Lunn, Jakub Kicinski, davem, pali, Marek Behún

This adds support for multigig copper SFP modules from RollBall/Hilink.
These modules have a specific way to access clause 45 registers of the
internal PHY.

We also need to wait at least 22 seconds after deasserting TX disable
before accessing the PHY. The code waits for 25 seconds just to be sure.

Signed-off-by: Marek Behún <kabel@kernel.org>
Reviewed-by: Russell King <rmk+kernel@armlinux.org.uk>
Cc: Andrew Lunn <andrew@lunn.ch>
---
 drivers/net/phy/sfp.c | 36 ++++++++++++++++++++++++++++++------
 1 file changed, 30 insertions(+), 6 deletions(-)

diff --git a/drivers/net/phy/sfp.c b/drivers/net/phy/sfp.c
index 0621d12cf878..21fb96899518 100644
--- a/drivers/net/phy/sfp.c
+++ b/drivers/net/phy/sfp.c
@@ -165,6 +165,7 @@ static const enum gpiod_flags gpio_flags[] = {
  * on board (for a copper SFP) time to initialise.
  */
 #define T_WAIT			msecs_to_jiffies(50)
+#define T_WAIT_ROLLBALL		msecs_to_jiffies(25000)
 #define T_START_UP		msecs_to_jiffies(300)
 #define T_START_UP_BAD_GPON	msecs_to_jiffies(60000)
 
@@ -204,8 +205,11 @@ static const enum gpiod_flags gpio_flags[] = {
 
 /* SFP modules appear to always have their PHY configured for bus address
  * 0x56 (which with mdio-i2c, translates to a PHY address of 22).
+ * RollBall SFPs access phy via SFP Enhanced Digital Diagnostic Interface
+ * via address 0x51 (mdio-i2c will use RollBall protocol on this address).
  */
-#define SFP_PHY_ADDR	22
+#define SFP_PHY_ADDR		22
+#define SFP_PHY_ADDR_ROLLBALL	17
 
 struct sff_data {
 	unsigned int gpios;
@@ -218,6 +222,7 @@ struct sfp {
 	struct mii_bus *i2c_mii;
 	struct sfp_bus *sfp_bus;
 	enum mdio_i2c_proto mdio_protocol;
+	int phy_addr;
 	struct phy_device *mod_phy;
 	const struct sff_data *type;
 	size_t i2c_block_size;
@@ -250,6 +255,7 @@ struct sfp {
 	struct sfp_eeprom_id id;
 	unsigned int module_power_mW;
 	unsigned int module_t_start_up;
+	unsigned int module_t_wait;
 
 #if IS_ENABLED(CONFIG_HWMON)
 	struct sfp_diag diag;
@@ -1453,7 +1459,7 @@ static int sfp_sm_probe_phy(struct sfp *sfp, bool is_c45)
 	struct phy_device *phy;
 	int err;
 
-	phy = get_phy_device(sfp->i2c_mii, SFP_PHY_ADDR, is_c45);
+	phy = get_phy_device(sfp->i2c_mii, sfp->phy_addr, is_c45);
 	if (phy == ERR_PTR(-ENODEV))
 		return PTR_ERR(phy);
 	if (IS_ERR(phy)) {
@@ -1835,6 +1841,23 @@ static int sfp_sm_mod_probe(struct sfp *sfp, bool report)
 
 	sfp->mdio_protocol = MDIO_I2C_DEFAULT;
 
+	sfp->phy_addr = SFP_PHY_ADDR;
+	sfp->module_t_wait = T_WAIT;
+
+	if (((!memcmp(id.base.vendor_name, "OEM             ", 16) ||
+	      !memcmp(id.base.vendor_name, "Turris          ", 16)) &&
+	     (!memcmp(id.base.vendor_pn, "SFP-10G-T       ", 16) ||
+	      !memcmp(id.base.vendor_pn, "RTSFP-10", 8)))) {
+		sfp->mdio_protocol = MDIO_I2C_ROLLBALL;
+		sfp->phy_addr = SFP_PHY_ADDR_ROLLBALL;
+		sfp->module_t_wait = T_WAIT_ROLLBALL;
+
+		/* RollBall SFPs may have wrong (zero) extended compliacne code
+		 * burned in EEPROM. For PHY probing we need the correct one.
+		 */
+		id.base.extended_cc = SFF8024_ECC_10GBASE_T_SFI;
+	}
+
 	return 0;
 }
 
@@ -2030,9 +2053,10 @@ static void sfp_sm_main(struct sfp *sfp, unsigned int event)
 
 		/* We need to check the TX_FAULT state, which is not defined
 		 * while TX_DISABLE is asserted. The earliest we want to do
-		 * anything (such as probe for a PHY) is 50ms.
+		 * anything (such as probe for a PHY) is 50ms. (or more on
+		 * specific modules).
 		 */
-		sfp_sm_next(sfp, SFP_S_WAIT, T_WAIT);
+		sfp_sm_next(sfp, SFP_S_WAIT, sfp->module_t_wait);
 		break;
 
 	case SFP_S_WAIT:
@@ -2046,8 +2070,8 @@ static void sfp_sm_main(struct sfp *sfp, unsigned int event)
 			 * deasserting.
 			 */
 			timeout = sfp->module_t_start_up;
-			if (timeout > T_WAIT)
-				timeout -= T_WAIT;
+			if (timeout > sfp->module_t_wait)
+				timeout -= sfp->module_t_wait;
 			else
 				timeout = 1;
 
-- 
2.26.2


^ permalink raw reply related	[flat|nested] 29+ messages in thread

* Re: [PATCH net-next v4 1/4] net: phy: mdio-i2c: support I2C MDIO protocol for RollBall SFP modules
  2021-01-11  5:00 ` [PATCH net-next v4 1/4] net: phy: mdio-i2c: support I2C MDIO protocol for RollBall " Marek Behún
@ 2021-01-12  8:42   ` Heiner Kallweit
  2021-01-12 14:02     ` Andrew Lunn
  2021-01-12 19:22     ` Russell King - ARM Linux admin
  2021-01-12 20:20   ` Andrew Lunn
                     ` (3 subsequent siblings)
  4 siblings, 2 replies; 29+ messages in thread
From: Heiner Kallweit @ 2021-01-12  8:42 UTC (permalink / raw)
  To: Marek Behún, netdev
  Cc: Russell King, Andrew Lunn, Jakub Kicinski, davem, pali

On 11.01.2021 06:00, Marek Behún wrote:
> Some multigig SFPs from RollBall and Hilink do not expose functional
> MDIO access to the internal PHY of the SFP via I2C address 0x56
> (although there seems to be read-only clause 22 access on this address).
> 
> Instead these SFPs PHY can be accessed via I2C via the SFP Enhanced
> Digital Diagnostic Interface - I2C address 0x51. The SFP_PAGE has to be
> selected to 3 and the password must be filled with 0xff bytes for this
> PHY communication to work.
> 
> This extends the mdio-i2c driver to support this protocol by adding a
> special parameter to mdio_i2c_alloc function via which this RollBall
> protocol can be selected.
> 
I'd think that mdio-i2c.c is for generic code. When adding a
vendor-specific protocol, wouldn't it make sense to use a dedicated
source file for it?

> Signed-off-by: Marek Behún <kabel@kernel.org>
> Cc: Andrew Lunn <andrew@lunn.ch>
> Cc: Russell King <rmk+kernel@armlinux.org.uk>
> ---
>  drivers/net/mdio/mdio-i2c.c   | 319 +++++++++++++++++++++++++++++++++-
>  drivers/net/phy/sfp.c         |   2 +-
>  include/linux/mdio/mdio-i2c.h |   8 +-
>  3 files changed, 322 insertions(+), 7 deletions(-)
> 
> diff --git a/drivers/net/mdio/mdio-i2c.c b/drivers/net/mdio/mdio-i2c.c
> index 09200a70b315..7be582c0891a 100644
> --- a/drivers/net/mdio/mdio-i2c.c
> +++ b/drivers/net/mdio/mdio-i2c.c
> @@ -3,6 +3,7 @@
>   * MDIO I2C bridge
>   *
>   * Copyright (C) 2015-2016 Russell King
> + * Copyright (C) 2021 Marek Behun
>   *
>   * Network PHYs can appear on I2C buses when they are part of SFP module.
>   * This driver exposes these PHYs to the networking PHY code, allowing
> @@ -12,6 +13,7 @@
>  #include <linux/i2c.h>
>  #include <linux/mdio/mdio-i2c.h>
>  #include <linux/phy.h>
> +#include <linux/sfp.h>
>  
>  /*
>   * I2C bus addresses 0x50 and 0x51 are normally an EEPROM, which is
> @@ -28,7 +30,7 @@ static unsigned int i2c_mii_phy_addr(int phy_id)
>  	return phy_id + 0x40;
>  }
>  
> -static int i2c_mii_read(struct mii_bus *bus, int phy_id, int reg)
> +static int i2c_mii_read_default(struct mii_bus *bus, int phy_id, int reg)
>  {
>  	struct i2c_adapter *i2c = bus->priv;
>  	struct i2c_msg msgs[2];
> @@ -62,7 +64,8 @@ static int i2c_mii_read(struct mii_bus *bus, int phy_id, int reg)
>  	return data[0] << 8 | data[1];
>  }
>  
> -static int i2c_mii_write(struct mii_bus *bus, int phy_id, int reg, u16 val)
> +static int i2c_mii_write_default(struct mii_bus *bus, int phy_id, int reg,
> +				 u16 val)
>  {
>  	struct i2c_adapter *i2c = bus->priv;
>  	struct i2c_msg msg;
> @@ -91,9 +94,297 @@ static int i2c_mii_write(struct mii_bus *bus, int phy_id, int reg, u16 val)
>  	return ret < 0 ? ret : 0;
>  }
>  
> -struct mii_bus *mdio_i2c_alloc(struct device *parent, struct i2c_adapter *i2c)
> +/* RollBall SFPs do not access internal PHY via I2C address 0x56, but
> + * instead via address 0x51, when SFP page is set to 0x03 and password to
> + * 0xffffffff.
> + * Since current SFP code does not modify SFP_PAGE, we set it to 0x03 only at
> + * bus creation time, and expect it to remain set to 0x03 throughout the
> + * lifetime of the module plugged into the system. If the SFP code starts
> + * modifying SFP_PAGE in the future, this code will need to change.
> + *
> + * address  size  contents  description
> + * -------  ----  --------  -----------
> + * 0x80     1     CMD       0x01/0x02/0x04 for write/read/done
> + * 0x81     1     DEV       Clause 45 device
> + * 0x82     2     REG       Clause 45 register
> + * 0x84     2     VAL       Register value
> + */
> +#define ROLLBALL_PHY_I2C_ADDR		0x51
> +#define ROLLBALL_SFP_PASSWORD_ADDR	0x7b
> +
> +#define ROLLBALL_CMD_ADDR		0x80
> +#define ROLLBALL_DATA_ADDR		0x81
> +
> +#define ROLLBALL_CMD_WRITE		0x01
> +#define ROLLBALL_CMD_READ		0x02
> +#define ROLLBALL_CMD_DONE		0x04
> +
> +#define SFP_PAGE_ROLLBALL_MDIO		3
> +
> +static int __i2c_transfer_err(struct i2c_adapter *i2c, struct i2c_msg *msgs,
> +			      int num)
> +{
> +	int ret;
> +
> +	ret = __i2c_transfer(i2c, msgs, num);
> +	if (ret < 0)
> +		return ret;
> +	else if (ret != num)
> +		return -EIO;
> +	else
> +		return 0;
> +}
> +
> +static int __i2c_rollball_get_page(struct i2c_adapter *i2c, int bus_addr,
> +				   u8 *page)
> +{
> +	struct i2c_msg msgs[2];
> +	u8 addr = SFP_PAGE;
> +
> +	msgs[0].addr = bus_addr;
> +	msgs[0].flags = 0;
> +	msgs[0].len = 1;
> +	msgs[0].buf = &addr;
> +
> +	msgs[1].addr = bus_addr;
> +	msgs[1].flags = I2C_M_RD;
> +	msgs[1].len = 1;
> +	msgs[1].buf = page;
> +
> +	return __i2c_transfer_err(i2c, msgs, 2);
> +}
> +
> +static int __i2c_rollball_set_page(struct i2c_adapter *i2c, int bus_addr,
> +				   u8 page)
> +{
> +	struct i2c_msg msg;
> +	u8 buf[2];
> +
> +	buf[0] = SFP_PAGE;
> +	buf[1] = page;
> +
> +	msg.addr = bus_addr;
> +	msg.flags = 0;
> +	msg.len = 2;
> +	msg.buf = buf;
> +
> +	return __i2c_transfer_err(i2c, &msg, 1);
> +}
> +
> +/* In order to not interfere with other SFP code (which possibly may manipulate
> + * SFP_PAGE), for every transfer we do this:
> + *   1. lock the bus
> + *   2. save content of SFP_PAGE
> + *   3. set SFP_PAGE to 3
> + *   4. do the transfer
> + *   5. restore original SFP_PAGE
> + *   6. unlock the bus
> + * Note that one might think that steps 2 to 5 could be theoretically done all
> + * in one call to i2c_transfer (by constructing msgs array in such a way), but
> + * unfortunately tests show that this does not work :-( Changed SFP_PAGE does
> + * not take into account until i2c_transfer() is done.
> + */
> +static int i2c_transfer_rollball(struct i2c_adapter *i2c,
> +				 struct i2c_msg *msgs, int num)
> +{
> +	u8 saved_page;
> +	int ret;
> +
> +	i2c_lock_bus(i2c, I2C_LOCK_SEGMENT);
> +
> +	/* save original page */
> +	ret = __i2c_rollball_get_page(i2c, msgs->addr, &saved_page);
> +	if (ret)
> +		goto unlock;
> +
> +	/* change to RollBall MDIO page */
> +	ret = __i2c_rollball_set_page(i2c, msgs->addr, SFP_PAGE_ROLLBALL_MDIO);
> +	if (ret)
> +		goto unlock;
> +
> +	/* do the transfer */
> +	ret = __i2c_transfer_err(i2c, msgs, num);
> +	if (ret)
> +		goto unlock;
> +
> +	/* restore original page */
> +	ret = __i2c_rollball_set_page(i2c, msgs->addr, saved_page);
> +
> +unlock:
> +	i2c_unlock_bus(i2c, I2C_LOCK_SEGMENT);
> +
> +	return ret;
> +}
> +
> +static int i2c_rollball_mii_poll(struct mii_bus *bus, int bus_addr, u8 *buf,
> +				 size_t len)
> +{
> +	struct i2c_adapter *i2c = bus->priv;
> +	struct i2c_msg msgs[2];
> +	u8 cmd_addr, tmp, *res;
> +	int i, ret;
> +
> +	cmd_addr = ROLLBALL_CMD_ADDR;
> +
> +	res = buf ? buf : &tmp;
> +	len = buf ? len : 1;
> +
> +	msgs[0].addr = bus_addr;
> +	msgs[0].flags = 0;
> +	msgs[0].len = 1;
> +	msgs[0].buf = &cmd_addr;
> +
> +	msgs[1].addr = bus_addr;
> +	msgs[1].flags = I2C_M_RD;
> +	msgs[1].len = len;
> +	msgs[1].buf = res;
> +
> +	/* By experiment it takes up to 70 ms to access a register for these
> +	 * SFPs. Sleep 20ms between iteratios and try 10 times.
> +	 */
> +	i = 10;
> +	do {
> +		msleep(20);
> +
> +		ret = i2c_transfer_rollball(i2c, msgs, ARRAY_SIZE(msgs));
> +		if (ret)
> +			return ret;
> +
> +		if (*res == ROLLBALL_CMD_DONE)
> +			return 0;
> +	} while (i-- > 0);
> +
> +	dev_dbg(&bus->dev, "poll timed out\n");
> +
> +	return -ETIMEDOUT;
> +}
> +
> +static int i2c_rollball_mii_cmd(struct mii_bus *bus, int bus_addr, u8 cmd,
> +				u8 *data, size_t len)
> +{
> +	struct i2c_adapter *i2c = bus->priv;
> +	struct i2c_msg msgs[2];
> +	u8 cmdbuf[2];
> +
> +	cmdbuf[0] = ROLLBALL_CMD_ADDR;
> +	cmdbuf[1] = cmd;
> +
> +	msgs[0].addr = bus_addr;
> +	msgs[0].flags = 0;
> +	msgs[0].len = len;
> +	msgs[0].buf = data;
> +
> +	msgs[1].addr = bus_addr;
> +	msgs[1].flags = 0;
> +	msgs[1].len = sizeof(cmdbuf);
> +	msgs[1].buf = cmdbuf;
> +
> +	return i2c_transfer_rollball(i2c, msgs, ARRAY_SIZE(msgs));
> +}
> +
> +static int i2c_mii_read_rollball(struct mii_bus *bus, int phy_id, int reg)
> +{
> +	u8 buf[4], res[6];
> +	int bus_addr, ret;
> +	u16 val;
> +
> +	if (!(reg & MII_ADDR_C45))
> +		return -EOPNOTSUPP;
> +
> +	bus_addr = i2c_mii_phy_addr(phy_id);
> +	if (bus_addr != ROLLBALL_PHY_I2C_ADDR)
> +		return 0xffff;
> +
> +	buf[0] = ROLLBALL_DATA_ADDR;
> +	buf[1] = (reg >> 16) & 0x1f;
> +	buf[2] = (reg >> 8) & 0xff;
> +	buf[3] = reg & 0xff;
> +
> +	ret = i2c_rollball_mii_cmd(bus, bus_addr, ROLLBALL_CMD_READ, buf,
> +				   sizeof(buf));
> +	if (ret < 0)
> +		return ret;
> +
> +	ret = i2c_rollball_mii_poll(bus, bus_addr, res, sizeof(res));
> +	if (ret == -ETIMEDOUT)
> +		return 0xffff;
> +	else if (ret < 0)
> +		return ret;
> +
> +	val = res[4] << 8 | res[5];
> +
> +	dev_dbg(&bus->dev, "read reg %02x:%04x = %04x\n", (reg >> 16) & 0x1f,
> +		reg & 0xffff, val);
> +
> +	return val;
> +}
> +
> +static int i2c_mii_write_rollball(struct mii_bus *bus, int phy_id, int reg,
> +				  u16 val)
> +{
> +	int bus_addr, ret;
> +	u8 buf[6];
> +
> +	if (!(reg & MII_ADDR_C45))
> +		return -EOPNOTSUPP;
> +
> +	bus_addr = i2c_mii_phy_addr(phy_id);
> +	if (bus_addr != ROLLBALL_PHY_I2C_ADDR)
> +		return 0;
> +
> +	buf[0] = ROLLBALL_DATA_ADDR;
> +	buf[1] = (reg >> 16) & 0x1f;
> +	buf[2] = (reg >> 8) & 0xff;
> +	buf[3] = reg & 0xff;
> +	buf[4] = val >> 8;
> +	buf[5] = val & 0xff;
> +
> +	ret = i2c_rollball_mii_cmd(bus, bus_addr, ROLLBALL_CMD_WRITE, buf,
> +				   sizeof(buf));
> +	if (ret < 0)
> +		return ret;
> +
> +	ret = i2c_rollball_mii_poll(bus, bus_addr, NULL, 0);
> +	if (ret < 0)
> +		return ret;
> +
> +	dev_dbg(&bus->dev, "write reg %02x:%04x = %04x\n", (reg >> 16) & 0x1f,
> +		reg & 0xffff, val);
> +
> +	return 0;
> +}
> +
> +static int i2c_mii_init_rollball(struct i2c_adapter *i2c)
> +{
> +	struct i2c_msg msg;
> +	u8 pw[5];
> +	int ret;
> +
> +	pw[0] = ROLLBALL_SFP_PASSWORD_ADDR;
> +	pw[1] = 0xff;
> +	pw[2] = 0xff;
> +	pw[3] = 0xff;
> +	pw[4] = 0xff;
> +
> +	msg.addr = ROLLBALL_PHY_I2C_ADDR;
> +	msg.flags = 0;
> +	msg.len = sizeof(pw);
> +	msg.buf = pw;
> +
> +	ret = i2c_transfer(i2c, &msg, 1);
> +	if (ret < 0)
> +		return ret;
> +	else if (ret != 1)
> +		return -EIO;
> +	else
> +		return 0;
> +}
> +
> +struct mii_bus *mdio_i2c_alloc(struct device *parent, struct i2c_adapter *i2c,
> +			       enum mdio_i2c_proto protocol)
>  {
>  	struct mii_bus *mii;
> +	int ret;
>  
>  	if (!i2c_check_functionality(i2c, I2C_FUNC_I2C))
>  		return ERR_PTR(-EINVAL);
> @@ -104,10 +395,28 @@ struct mii_bus *mdio_i2c_alloc(struct device *parent, struct i2c_adapter *i2c)
>  
>  	snprintf(mii->id, MII_BUS_ID_SIZE, "i2c:%s", dev_name(parent));
>  	mii->parent = parent;
> -	mii->read = i2c_mii_read;
> -	mii->write = i2c_mii_write;
>  	mii->priv = i2c;
>  
> +	switch (protocol) {
> +	case MDIO_I2C_ROLLBALL:
> +		ret = i2c_mii_init_rollball(i2c);
> +		if (ret < 0) {
> +			dev_err(parent,
> +				"Cannot initialize RollBall MDIO I2C protocol: %d\n",
> +				ret);
> +			mdiobus_free(mii);
> +			return ERR_PTR(ret);
> +		}
> +
> +		mii->read = i2c_mii_read_rollball;
> +		mii->write = i2c_mii_write_rollball;
> +		break;
> +	default:
> +		mii->read = i2c_mii_read_default;
> +		mii->write = i2c_mii_write_default;
> +		break;
> +	}
> +
>  	return mii;
>  }
>  EXPORT_SYMBOL_GPL(mdio_i2c_alloc);
> diff --git a/drivers/net/phy/sfp.c b/drivers/net/phy/sfp.c
> index 91d74c1a920a..958fd514a3b4 100644
> --- a/drivers/net/phy/sfp.c
> +++ b/drivers/net/phy/sfp.c
> @@ -419,7 +419,7 @@ static int sfp_i2c_configure(struct sfp *sfp, struct i2c_adapter *i2c)
>  	sfp->read = sfp_i2c_read;
>  	sfp->write = sfp_i2c_write;
>  
> -	i2c_mii = mdio_i2c_alloc(sfp->dev, i2c);
> +	i2c_mii = mdio_i2c_alloc(sfp->dev, i2c, MDIO_I2C_DEFAULT);
>  	if (IS_ERR(i2c_mii))
>  		return PTR_ERR(i2c_mii);
>  
> diff --git a/include/linux/mdio/mdio-i2c.h b/include/linux/mdio/mdio-i2c.h
> index b1d27f7cd23f..53eedb0dc1d3 100644
> --- a/include/linux/mdio/mdio-i2c.h
> +++ b/include/linux/mdio/mdio-i2c.h
> @@ -11,6 +11,12 @@ struct device;
>  struct i2c_adapter;
>  struct mii_bus;
>  
> -struct mii_bus *mdio_i2c_alloc(struct device *parent, struct i2c_adapter *i2c);
> +enum mdio_i2c_proto {
> +	MDIO_I2C_DEFAULT,
> +	MDIO_I2C_ROLLBALL,
> +};
> +
> +struct mii_bus *mdio_i2c_alloc(struct device *parent, struct i2c_adapter *i2c,
> +			       enum mdio_i2c_proto protocol);
>  
>  #endif
> 


^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH net-next v4 1/4] net: phy: mdio-i2c: support I2C MDIO protocol for RollBall SFP modules
  2021-01-12  8:42   ` Heiner Kallweit
@ 2021-01-12 14:02     ` Andrew Lunn
  2021-01-12 14:40       ` Heiner Kallweit
  2021-01-12 17:49       ` Marek Behún
  2021-01-12 19:22     ` Russell King - ARM Linux admin
  1 sibling, 2 replies; 29+ messages in thread
From: Andrew Lunn @ 2021-01-12 14:02 UTC (permalink / raw)
  To: Heiner Kallweit
  Cc: Marek Behún, netdev, Russell King, Jakub Kicinski, davem, pali

> I'd think that mdio-i2c.c is for generic code. When adding a
> vendor-specific protocol, wouldn't it make sense to use a dedicated
> source file for it?

Hi Heiner

There is no standardised way to access MDIO over i2c. So the existing
code is vendor code, even if it is used by a few different vendors.

     Andrew

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH net-next v4 1/4] net: phy: mdio-i2c: support I2C MDIO protocol for RollBall SFP modules
  2021-01-12 14:02     ` Andrew Lunn
@ 2021-01-12 14:40       ` Heiner Kallweit
  2021-01-12 17:49       ` Marek Behún
  1 sibling, 0 replies; 29+ messages in thread
From: Heiner Kallweit @ 2021-01-12 14:40 UTC (permalink / raw)
  To: Andrew Lunn
  Cc: Marek Behún, netdev, Russell King, Jakub Kicinski, davem, pali

On 12.01.2021 15:02, Andrew Lunn wrote:
>> I'd think that mdio-i2c.c is for generic code. When adding a
>> vendor-specific protocol, wouldn't it make sense to use a dedicated
>> source file for it?
> 
> Hi Heiner
> 
> There is no standardised way to access MDIO over i2c. So the existing
> code is vendor code, even if it is used by a few different vendors.
> 
>      Andrew
> 
OK, I see. Thanks, Andrew.

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH net-next v4 1/4] net: phy: mdio-i2c: support I2C MDIO protocol for RollBall SFP modules
  2021-01-12 14:02     ` Andrew Lunn
  2021-01-12 14:40       ` Heiner Kallweit
@ 2021-01-12 17:49       ` Marek Behún
  1 sibling, 0 replies; 29+ messages in thread
From: Marek Behún @ 2021-01-12 17:49 UTC (permalink / raw)
  To: Andrew Lunn
  Cc: Heiner Kallweit, netdev, Russell King, Jakub Kicinski, davem, pali

On Tue, 12 Jan 2021 15:02:49 +0100
Andrew Lunn <andrew@lunn.ch> wrote:

> > I'd think that mdio-i2c.c is for generic code. When adding a
> > vendor-specific protocol, wouldn't it make sense to use a dedicated
> > source file for it?  
> 
> Hi Heiner
> 
> There is no standardised way to access MDIO over i2c. So the existing
> code is vendor code, even if it is used by a few different vendors.
> 
>      Andrew

Andrew, if you could find the time, could you please review these
patches? Patches 2 and 4 already have reviewed-by Russell, but 1 and 3
still need some review.

Marek

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH net-next v4 1/4] net: phy: mdio-i2c: support I2C MDIO protocol for RollBall SFP modules
  2021-01-12  8:42   ` Heiner Kallweit
  2021-01-12 14:02     ` Andrew Lunn
@ 2021-01-12 19:22     ` Russell King - ARM Linux admin
  2021-01-18 12:13       ` Pali Rohár
  1 sibling, 1 reply; 29+ messages in thread
From: Russell King - ARM Linux admin @ 2021-01-12 19:22 UTC (permalink / raw)
  To: Heiner Kallweit
  Cc: Marek Behún, netdev, Andrew Lunn, Jakub Kicinski, davem, pali

On Tue, Jan 12, 2021 at 09:42:56AM +0100, Heiner Kallweit wrote:
> On 11.01.2021 06:00, Marek Behún wrote:
> > Some multigig SFPs from RollBall and Hilink do not expose functional
> > MDIO access to the internal PHY of the SFP via I2C address 0x56
> > (although there seems to be read-only clause 22 access on this address).
> > 
> > Instead these SFPs PHY can be accessed via I2C via the SFP Enhanced
> > Digital Diagnostic Interface - I2C address 0x51. The SFP_PAGE has to be
> > selected to 3 and the password must be filled with 0xff bytes for this
> > PHY communication to work.
> > 
> > This extends the mdio-i2c driver to support this protocol by adding a
> > special parameter to mdio_i2c_alloc function via which this RollBall
> > protocol can be selected.
> > 
> I'd think that mdio-i2c.c is for generic code. When adding a
> vendor-specific protocol, wouldn't it make sense to use a dedicated
> source file for it?

There is nothing in the SFP MSAs about how to access an on-board PHY
on a SFP. This is something that vendors choose to do (or in some
cases, not do.)

mdio-i2c currently implements the access protocol for Marvell 88E1111
PHYs which have an I2C mode. It was extended to support the DM7052
module which has a Broadcom Clause 45 PHY and either a microcontroller
or FPGA to convert I2C cycles to MDIO cycles - and sensibly performs
clock stretching.

There are modules that the clause 45 PHY is accessible via exactly the
same I2C address, using exactly the same data accesses, but do not
do the clock stretching thing, instead telling you that you must wait
N microseconds between the bus transactions. We don't yet support
these.

Then there is Marek's module, where the PHY is accessible via a page
in the diagnostic address - which is another entirely reasonable
implementation. The solution we have here is one that I've worked with
Marek for a few months now.

I don't think we should grow lots of separate mdio-i2c-vendorfoo.c
drivers - at least not yet. Maybe if we get lots of different access
methods, it may make sense in the future.

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

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH net-next v4 1/4] net: phy: mdio-i2c: support I2C MDIO protocol for RollBall SFP modules
  2021-01-11  5:00 ` [PATCH net-next v4 1/4] net: phy: mdio-i2c: support I2C MDIO protocol for RollBall " Marek Behún
  2021-01-12  8:42   ` Heiner Kallweit
@ 2021-01-12 20:20   ` Andrew Lunn
  2021-01-12 20:43   ` Andrew Lunn
                     ` (2 subsequent siblings)
  4 siblings, 0 replies; 29+ messages in thread
From: Andrew Lunn @ 2021-01-12 20:20 UTC (permalink / raw)
  To: Marek Behún; +Cc: netdev, Russell King, Jakub Kicinski, davem, pali

> -struct mii_bus *mdio_i2c_alloc(struct device *parent, struct i2c_adapter *i2c)
> +/* RollBall SFPs do not access internal PHY via I2C address 0x56, but
> + * instead via address 0x51, when SFP page is set to 0x03 and password to
> + * 0xffffffff.
> + * Since current SFP code does not modify SFP_PAGE, we set it to 0x03 only at
> + * bus creation time, and expect it to remain set to 0x03 throughout the
> + * lifetime of the module plugged into the system. If the SFP code starts
> + * modifying SFP_PAGE in the future, this code will need to change.

Just an FYI: This is likely to change. NVIDIA are working on
generalizing the API ethtool -m uses. The new API should allow access
to pages and banks. I've already said i will implement the API in the
generic phylink SFP code. But no need to address this now.

	Andrew

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH net-next v4 1/4] net: phy: mdio-i2c: support I2C MDIO protocol for RollBall SFP modules
  2021-01-11  5:00 ` [PATCH net-next v4 1/4] net: phy: mdio-i2c: support I2C MDIO protocol for RollBall " Marek Behún
  2021-01-12  8:42   ` Heiner Kallweit
  2021-01-12 20:20   ` Andrew Lunn
@ 2021-01-12 20:43   ` Andrew Lunn
  2021-01-12 20:53     ` Marek Behún
  2021-01-12 20:54   ` Andrew Lunn
  2021-01-13 11:22   ` Pali Rohár
  4 siblings, 1 reply; 29+ messages in thread
From: Andrew Lunn @ 2021-01-12 20:43 UTC (permalink / raw)
  To: Marek Behún; +Cc: netdev, Russell King, Jakub Kicinski, davem, pali

> +/* RollBall SFPs do not access internal PHY via I2C address 0x56, but
> + * instead via address 0x51, when SFP page is set to 0x03 and password to
> + * 0xffffffff.
> + * Since current SFP code does not modify SFP_PAGE, we set it to 0x03 only at
> + * bus creation time, and expect it to remain set to 0x03 throughout the
> + * lifetime of the module plugged into the system. If the SFP code starts
> + * modifying SFP_PAGE in the future, this code will need to change.

...

> +/* In order to not interfere with other SFP code (which possibly may manipulate
> + * SFP_PAGE), for every transfer we do this:
> + *   1. lock the bus
> + *   2. save content of SFP_PAGE
> + *   3. set SFP_PAGE to 3
> + *   4. do the transfer
> + *   5. restore original SFP_PAGE
> + *   6. unlock the bus

These two comments seem to contradict each other?

> +static int i2c_rollball_mii_poll(struct mii_bus *bus, int bus_addr, u8 *buf,
> +				 size_t len)
> +{
> +	struct i2c_adapter *i2c = bus->priv;
> +	struct i2c_msg msgs[2];
> +	u8 cmd_addr, tmp, *res;
> +	int i, ret;
> +
> +	cmd_addr = ROLLBALL_CMD_ADDR;
> +
> +	res = buf ? buf : &tmp;
> +	len = buf ? len : 1;
> +
> +	msgs[0].addr = bus_addr;
> +	msgs[0].flags = 0;
> +	msgs[0].len = 1;
> +	msgs[0].buf = &cmd_addr;
> +
> +	msgs[1].addr = bus_addr;
> +	msgs[1].flags = I2C_M_RD;
> +	msgs[1].len = len;
> +	msgs[1].buf = res;
> +
> +	/* By experiment it takes up to 70 ms to access a register for these
> +	 * SFPs. Sleep 20ms between iteratios and try 10 times.
> +	 */

iterations

> +static int i2c_mii_read_rollball(struct mii_bus *bus, int phy_id, int reg)
> +{
> +	u8 buf[4], res[6];
> +	int bus_addr, ret;
> +	u16 val;
> +
> +	if (!(reg & MII_ADDR_C45))
> +		return -EOPNOTSUPP;
> +
> +	bus_addr = i2c_mii_phy_addr(phy_id);
> +	if (bus_addr != ROLLBALL_PHY_I2C_ADDR)
> +		return 0xffff;
> +
> +	buf[0] = ROLLBALL_DATA_ADDR;
> +	buf[1] = (reg >> 16) & 0x1f;
> +	buf[2] = (reg >> 8) & 0xff;
> +	buf[3] = reg & 0xff;

This looks odd. There are only 32 registers for C22 transactions, so
it fits in one byte. You can set buf[1] and buf[2] to zero.

C45 transactions allow for 65536 registers, and has the devtype field,
so would need 3 bytes. Which suggests that C45 might actually be
supported? At least by the protocol, if not the device.

> +	dev_dbg(&bus->dev, "read reg %02x:%04x = %04x\n", (reg >> 16) & 0x1f,
> +		reg & 0xffff, val);

There is a tracepoint that allows access to this information, so you
can probably remove this.

    Andrew

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH net-next v4 1/4] net: phy: mdio-i2c: support I2C MDIO protocol for RollBall SFP modules
  2021-01-12 20:43   ` Andrew Lunn
@ 2021-01-12 20:53     ` Marek Behún
  2021-01-12 20:55       ` Andrew Lunn
  0 siblings, 1 reply; 29+ messages in thread
From: Marek Behún @ 2021-01-12 20:53 UTC (permalink / raw)
  To: Andrew Lunn; +Cc: netdev, Russell King, Jakub Kicinski, davem, pali

On Tue, 12 Jan 2021 21:43:29 +0100
Andrew Lunn <andrew@lunn.ch> wrote:

> > +/* RollBall SFPs do not access internal PHY via I2C address 0x56, but
> > + * instead via address 0x51, when SFP page is set to 0x03 and password to
> > + * 0xffffffff.
> > + * Since current SFP code does not modify SFP_PAGE, we set it to 0x03 only at
> > + * bus creation time, and expect it to remain set to 0x03 throughout the
> > + * lifetime of the module plugged into the system. If the SFP code starts
> > + * modifying SFP_PAGE in the future, this code will need to change.  
> 
> ...
> 
> > +/* In order to not interfere with other SFP code (which possibly may manipulate
> > + * SFP_PAGE), for every transfer we do this:
> > + *   1. lock the bus
> > + *   2. save content of SFP_PAGE
> > + *   3. set SFP_PAGE to 3
> > + *   4. do the transfer
> > + *   5. restore original SFP_PAGE
> > + *   6. unlock the bus  
> 
> These two comments seem to contradict each other?

I forgot about the first comment. I will rewrite it and send again.

> 
> > +static int i2c_rollball_mii_poll(struct mii_bus *bus, int bus_addr, u8 *buf,
> > +				 size_t len)
> > +{
> > +	struct i2c_adapter *i2c = bus->priv;
> > +	struct i2c_msg msgs[2];
> > +	u8 cmd_addr, tmp, *res;
> > +	int i, ret;
> > +
> > +	cmd_addr = ROLLBALL_CMD_ADDR;
> > +
> > +	res = buf ? buf : &tmp;
> > +	len = buf ? len : 1;
> > +
> > +	msgs[0].addr = bus_addr;
> > +	msgs[0].flags = 0;
> > +	msgs[0].len = 1;
> > +	msgs[0].buf = &cmd_addr;
> > +
> > +	msgs[1].addr = bus_addr;
> > +	msgs[1].flags = I2C_M_RD;
> > +	msgs[1].len = len;
> > +	msgs[1].buf = res;
> > +
> > +	/* By experiment it takes up to 70 ms to access a register for these
> > +	 * SFPs. Sleep 20ms between iteratios and try 10 times.
> > +	 */  
> 
> iterations

THX.

> 
> > +static int i2c_mii_read_rollball(struct mii_bus *bus, int phy_id, int reg)
> > +{
> > +	u8 buf[4], res[6];
> > +	int bus_addr, ret;
> > +	u16 val;
> > +
> > +	if (!(reg & MII_ADDR_C45))
> > +		return -EOPNOTSUPP;
> > +
> > +	bus_addr = i2c_mii_phy_addr(phy_id);
> > +	if (bus_addr != ROLLBALL_PHY_I2C_ADDR)
> > +		return 0xffff;
> > +
> > +	buf[0] = ROLLBALL_DATA_ADDR;
> > +	buf[1] = (reg >> 16) & 0x1f;
> > +	buf[2] = (reg >> 8) & 0xff;
> > +	buf[3] = reg & 0xff;  
> 
> This looks odd. There are only 32 registers for C22 transactions, so
> it fits in one byte. You can set buf[1] and buf[2] to zero.

C22 is not supported by this protocol. A few line above there is
  if (!(reg & MII_ADDR_C45))
    return -EOPNOTSUPP;

> C45 transactions allow for 65536 registers, and has the devtype field,
> so would need 3 bytes. Which suggests that C45 might actually be
> supported? At least by the protocol, if not the device.

> > +	dev_dbg(&bus->dev, "read reg %02x:%04x = %04x\n", (reg >> 16) & 0x1f,
> > +		reg & 0xffff, val);  
> 
> There is a tracepoint that allows access to this information, so you
> can probably remove this.
> 
>     Andrew

OK then, I will remove this.

Thanks, Andrew.

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH net-next v4 1/4] net: phy: mdio-i2c: support I2C MDIO protocol for RollBall SFP modules
  2021-01-11  5:00 ` [PATCH net-next v4 1/4] net: phy: mdio-i2c: support I2C MDIO protocol for RollBall " Marek Behún
                     ` (2 preceding siblings ...)
  2021-01-12 20:43   ` Andrew Lunn
@ 2021-01-12 20:54   ` Andrew Lunn
  2021-01-12 21:01     ` Marek Behún
  2021-01-12 21:22     ` Russell King - ARM Linux admin
  2021-01-13 11:22   ` Pali Rohár
  4 siblings, 2 replies; 29+ messages in thread
From: Andrew Lunn @ 2021-01-12 20:54 UTC (permalink / raw)
  To: Marek Behún; +Cc: netdev, Russell King, Jakub Kicinski, davem, pali

> +static int i2c_transfer_rollball(struct i2c_adapter *i2c,
> +				 struct i2c_msg *msgs, int num)
> +{
> +	u8 saved_page;
> +	int ret;
> +
> +	i2c_lock_bus(i2c, I2C_LOCK_SEGMENT);
> +
> +	/* save original page */
> +	ret = __i2c_rollball_get_page(i2c, msgs->addr, &saved_page);
> +	if (ret)
> +		goto unlock;
> +
> +	/* change to RollBall MDIO page */
> +	ret = __i2c_rollball_set_page(i2c, msgs->addr, SFP_PAGE_ROLLBALL_MDIO);
> +	if (ret)
> +		goto unlock;
> +
> +	/* do the transfer */
> +	ret = __i2c_transfer_err(i2c, msgs, num);
> +	if (ret)
> +		goto unlock;

If get page and set page worked, and you get an error in during the
actual data transfer, i wonder if you should try restoring the page
before returning with the error?

> +
> +	/* restore original page */
> +	ret = __i2c_rollball_set_page(i2c, msgs->addr, saved_page);
> +
> +unlock:
> +	i2c_unlock_bus(i2c, I2C_LOCK_SEGMENT);
> +
> +	return ret;
> +}

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH net-next v4 1/4] net: phy: mdio-i2c: support I2C MDIO protocol for RollBall SFP modules
  2021-01-12 20:53     ` Marek Behún
@ 2021-01-12 20:55       ` Andrew Lunn
  0 siblings, 0 replies; 29+ messages in thread
From: Andrew Lunn @ 2021-01-12 20:55 UTC (permalink / raw)
  To: Marek Behún; +Cc: netdev, Russell King, Jakub Kicinski, davem, pali

> > > +static int i2c_mii_read_rollball(struct mii_bus *bus, int phy_id, int reg)
> > > +{
> > > +	u8 buf[4], res[6];
> > > +	int bus_addr, ret;
> > > +	u16 val;
> > > +
> > > +	if (!(reg & MII_ADDR_C45))
> > > +		return -EOPNOTSUPP;
> > > +
> > > +	bus_addr = i2c_mii_phy_addr(phy_id);
> > > +	if (bus_addr != ROLLBALL_PHY_I2C_ADDR)
> > > +		return 0xffff;
> > > +
> > > +	buf[0] = ROLLBALL_DATA_ADDR;
> > > +	buf[1] = (reg >> 16) & 0x1f;
> > > +	buf[2] = (reg >> 8) & 0xff;
> > > +	buf[3] = reg & 0xff;  
> > 
> > This looks odd. There are only 32 registers for C22 transactions, so
> > it fits in one byte. You can set buf[1] and buf[2] to zero.
> 
> C22 is not supported by this protocol.

Duh!

Sorry for the noise.

      Andrew

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH net-next v4 1/4] net: phy: mdio-i2c: support I2C MDIO protocol for RollBall SFP modules
  2021-01-12 20:54   ` Andrew Lunn
@ 2021-01-12 21:01     ` Marek Behún
  2021-01-13 10:51       ` Pali Rohár
  2021-01-12 21:22     ` Russell King - ARM Linux admin
  1 sibling, 1 reply; 29+ messages in thread
From: Marek Behún @ 2021-01-12 21:01 UTC (permalink / raw)
  To: Andrew Lunn; +Cc: netdev, Russell King, Jakub Kicinski, davem, pali

On Tue, 12 Jan 2021 21:54:24 +0100
Andrew Lunn <andrew@lunn.ch> wrote:

> > +static int i2c_transfer_rollball(struct i2c_adapter *i2c,
> > +				 struct i2c_msg *msgs, int num)
> > +{
> > +	u8 saved_page;
> > +	int ret;
> > +
> > +	i2c_lock_bus(i2c, I2C_LOCK_SEGMENT);
> > +
> > +	/* save original page */
> > +	ret = __i2c_rollball_get_page(i2c, msgs->addr, &saved_page);
> > +	if (ret)
> > +		goto unlock;
> > +
> > +	/* change to RollBall MDIO page */
> > +	ret = __i2c_rollball_set_page(i2c, msgs->addr, SFP_PAGE_ROLLBALL_MDIO);
> > +	if (ret)
> > +		goto unlock;
> > +
> > +	/* do the transfer */
> > +	ret = __i2c_transfer_err(i2c, msgs, num);
> > +	if (ret)
> > +		goto unlock;  
> 
> If get page and set page worked, and you get an error in during the
> actual data transfer, i wonder if you should try restoring the page
> before returning with the error?

I don't know. Can i2c trasfer fail and the next one succeed?

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH net-next v4 1/4] net: phy: mdio-i2c: support I2C MDIO protocol for RollBall SFP modules
  2021-01-12 20:54   ` Andrew Lunn
  2021-01-12 21:01     ` Marek Behún
@ 2021-01-12 21:22     ` Russell King - ARM Linux admin
  1 sibling, 0 replies; 29+ messages in thread
From: Russell King - ARM Linux admin @ 2021-01-12 21:22 UTC (permalink / raw)
  To: Andrew Lunn; +Cc: Marek Behún, netdev, Jakub Kicinski, davem, pali

On Tue, Jan 12, 2021 at 09:54:24PM +0100, Andrew Lunn wrote:
> > +static int i2c_transfer_rollball(struct i2c_adapter *i2c,
> > +				 struct i2c_msg *msgs, int num)
> > +{
> > +	u8 saved_page;
> > +	int ret;
> > +
> > +	i2c_lock_bus(i2c, I2C_LOCK_SEGMENT);
> > +
> > +	/* save original page */
> > +	ret = __i2c_rollball_get_page(i2c, msgs->addr, &saved_page);
> > +	if (ret)
> > +		goto unlock;
> > +
> > +	/* change to RollBall MDIO page */
> > +	ret = __i2c_rollball_set_page(i2c, msgs->addr, SFP_PAGE_ROLLBALL_MDIO);
> > +	if (ret)
> > +		goto unlock;
> > +
> > +	/* do the transfer */
> > +	ret = __i2c_transfer_err(i2c, msgs, num);
> > +	if (ret)
> > +		goto unlock;
> 
> If get page and set page worked, and you get an error in during the
> actual data transfer, i wonder if you should try restoring the page
> before returning with the error?

That's what we do with paged PHYs - if the access encounters an error,
we still attempt to restore the page and propagate the _original_ error.
We would only propagate the error from the page restore if it was the
only error.  See the logic and comments for phy_restore_page().

Note that phy_(save|select)_page()..phy_restore_page() deal with the
locking, which is why they always have to be paired (also means that
the user doesn't have to think too hard about error handling.)

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

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH net-next v4 2/4] net: phylink: allow attaching phy for SFP modules on 802.3z mode
  2021-01-11  5:00 ` [PATCH net-next v4 2/4] net: phylink: allow attaching phy for SFP modules on 802.3z mode Marek Behún
@ 2021-01-13 10:38   ` Pali Rohár
  0 siblings, 0 replies; 29+ messages in thread
From: Pali Rohár @ 2021-01-13 10:38 UTC (permalink / raw)
  To: Marek Behún; +Cc: netdev, Russell King, Andrew Lunn, Jakub Kicinski, davem

On Monday 11 January 2021 06:00:42 Marek Behún wrote:
> Some SFPs may contain an internal PHY which may in some cases want to
> connect with the host interface in 1000base-x/2500base-x mode.
> Do not fail if such PHY is being attached in one of these PHY interface
> modes.
> 
> Signed-off-by: Marek Behún <kabel@kernel.org>
> Reviewed-by: Russell King <rmk+kernel@armlinux.org.uk>
> Cc: Andrew Lunn <andrew@lunn.ch>

Reviewed-by: Pali Rohár <pali@kernel.org>

> ---
>  drivers/net/phy/phylink.c | 5 +----
>  1 file changed, 1 insertion(+), 4 deletions(-)
> 
> diff --git a/drivers/net/phy/phylink.c b/drivers/net/phy/phylink.c
> index 84f6e197f965..f97d041f82f4 100644
> --- a/drivers/net/phy/phylink.c
> +++ b/drivers/net/phy/phylink.c
> @@ -1018,7 +1018,7 @@ static int phylink_attach_phy(struct phylink *pl, struct phy_device *phy,
>  {
>  	if (WARN_ON(pl->cfg_link_an_mode == MLO_AN_FIXED ||
>  		    (pl->cfg_link_an_mode == MLO_AN_INBAND &&
> -		     phy_interface_mode_is_8023z(interface))))
> +		     phy_interface_mode_is_8023z(interface) && !pl->sfp_bus)))
>  		return -EINVAL;
>  
>  	if (pl->phydev)
> @@ -2069,9 +2069,6 @@ static int phylink_sfp_config(struct phylink *pl, u8 mode,
>  		    phylink_an_mode_str(mode), phy_modes(config.interface),
>  		    __ETHTOOL_LINK_MODE_MASK_NBITS, support);
>  
> -	if (phy_interface_mode_is_8023z(iface) && pl->phydev)
> -		return -EINVAL;
> -
>  	changed = !linkmode_equal(pl->supported, support);
>  	if (changed) {
>  		linkmode_copy(pl->supported, support);
> -- 
> 2.26.2
> 

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH net-next v4 3/4] net: sfp: create/destroy I2C mdiobus before PHY probe/after PHY release
  2021-01-11  5:00 ` [PATCH net-next v4 3/4] net: sfp: create/destroy I2C mdiobus before PHY probe/after PHY release Marek Behún
@ 2021-01-13 10:41   ` Pali Rohár
  0 siblings, 0 replies; 29+ messages in thread
From: Pali Rohár @ 2021-01-13 10:41 UTC (permalink / raw)
  To: Marek Behún; +Cc: netdev, Russell King, Andrew Lunn, Jakub Kicinski, davem

On Monday 11 January 2021 06:00:43 Marek Behún wrote:
> Instead of configuring the I2C mdiobus when SFP driver is probed,
> create/destroy the mdiobus before the PHY is probed for/after it is
> released.
> 
> This way we can tell the mdio-i2c code which protocol to use for each
> SFP transceiver.
> 
> Signed-off-by: Marek Behún <kabel@kernel.org>
> Cc: Andrew Lunn <andrew@lunn.ch>
> Cc: Russell King <rmk+kernel@armlinux.org.uk>

Reviewed-by: Pali Rohár <pali@kernel.org>

> ---
>  drivers/net/phy/sfp.c | 30 ++++++++++++++++++++++++++----
>  1 file changed, 26 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/net/phy/sfp.c b/drivers/net/phy/sfp.c
> index 958fd514a3b4..0621d12cf878 100644
> --- a/drivers/net/phy/sfp.c
> +++ b/drivers/net/phy/sfp.c
> @@ -217,6 +217,7 @@ struct sfp {
>  	struct i2c_adapter *i2c;
>  	struct mii_bus *i2c_mii;
>  	struct sfp_bus *sfp_bus;
> +	enum mdio_i2c_proto mdio_protocol;
>  	struct phy_device *mod_phy;
>  	const struct sff_data *type;
>  	size_t i2c_block_size;
> @@ -409,9 +410,6 @@ static int sfp_i2c_write(struct sfp *sfp, bool a2, u8 dev_addr, void *buf,
>  
>  static int sfp_i2c_configure(struct sfp *sfp, struct i2c_adapter *i2c)
>  {
> -	struct mii_bus *i2c_mii;
> -	int ret;
> -
>  	if (!i2c_check_functionality(i2c, I2C_FUNC_I2C))
>  		return -EINVAL;
>  
> @@ -419,7 +417,15 @@ static int sfp_i2c_configure(struct sfp *sfp, struct i2c_adapter *i2c)
>  	sfp->read = sfp_i2c_read;
>  	sfp->write = sfp_i2c_write;
>  
> -	i2c_mii = mdio_i2c_alloc(sfp->dev, i2c, MDIO_I2C_DEFAULT);
> +	return 0;
> +}
> +
> +static int sfp_i2c_mdiobus_create(struct sfp *sfp)
> +{
> +	struct mii_bus *i2c_mii;
> +	int ret;
> +
> +	i2c_mii = mdio_i2c_alloc(sfp->dev, sfp->i2c, sfp->mdio_protocol);
>  	if (IS_ERR(i2c_mii))
>  		return PTR_ERR(i2c_mii);
>  
> @@ -437,6 +443,12 @@ static int sfp_i2c_configure(struct sfp *sfp, struct i2c_adapter *i2c)
>  	return 0;
>  }
>  
> +static void sfp_i2c_mdiobus_destroy(struct sfp *sfp)
> +{
> +	mdiobus_unregister(sfp->i2c_mii);
> +	sfp->i2c_mii = NULL;
> +}
> +
>  /* Interface */
>  static int sfp_read(struct sfp *sfp, bool a2, u8 addr, void *buf, size_t len)
>  {
> @@ -1821,6 +1833,8 @@ static int sfp_sm_mod_probe(struct sfp *sfp, bool report)
>  	else
>  		sfp->module_t_start_up = T_START_UP;
>  
> +	sfp->mdio_protocol = MDIO_I2C_DEFAULT;
> +
>  	return 0;
>  }
>  
> @@ -1991,6 +2005,8 @@ static void sfp_sm_main(struct sfp *sfp, unsigned int event)
>  			sfp_module_stop(sfp->sfp_bus);
>  		if (sfp->mod_phy)
>  			sfp_sm_phy_detach(sfp);
> +		if (sfp->i2c_mii)
> +			sfp_i2c_mdiobus_destroy(sfp);
>  		sfp_module_tx_disable(sfp);
>  		sfp_soft_stop_poll(sfp);
>  		sfp_sm_next(sfp, SFP_S_DOWN, 0);
> @@ -2053,6 +2069,12 @@ static void sfp_sm_main(struct sfp *sfp, unsigned int event)
>  				     sfp->sm_fault_retries == N_FAULT_INIT);
>  		} else if (event == SFP_E_TIMEOUT || event == SFP_E_TX_CLEAR) {
>  	init_done:
> +			/* Create mdiobus and start trying for PHY */
> +			ret = sfp_i2c_mdiobus_create(sfp);
> +			if (ret < 0) {
> +				sfp_sm_next(sfp, SFP_S_FAIL, 0);
> +				break;
> +			}
>  			sfp->sm_phy_retries = R_PHY_RETRY;
>  			goto phy_probe;
>  		}
> -- 
> 2.26.2
> 

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH net-next v4 4/4] net: sfp: add support for multigig RollBall transceivers
  2021-01-11  5:00 ` [PATCH net-next v4 4/4] net: sfp: add support for multigig RollBall transceivers Marek Behún
@ 2021-01-13 10:49   ` Pali Rohár
  2021-01-13 11:08     ` Russell King - ARM Linux admin
  0 siblings, 1 reply; 29+ messages in thread
From: Pali Rohár @ 2021-01-13 10:49 UTC (permalink / raw)
  To: Marek Behún; +Cc: netdev, Russell King, Andrew Lunn, Jakub Kicinski, davem

Hello! (See comment below)

On Monday 11 January 2021 06:00:44 Marek Behún wrote:
> This adds support for multigig copper SFP modules from RollBall/Hilink.
> These modules have a specific way to access clause 45 registers of the
> internal PHY.
> 
> We also need to wait at least 22 seconds after deasserting TX disable
> before accessing the PHY. The code waits for 25 seconds just to be sure.
> 
> Signed-off-by: Marek Behún <kabel@kernel.org>
> Reviewed-by: Russell King <rmk+kernel@armlinux.org.uk>
> Cc: Andrew Lunn <andrew@lunn.ch>
> ---
>  drivers/net/phy/sfp.c | 36 ++++++++++++++++++++++++++++++------
>  1 file changed, 30 insertions(+), 6 deletions(-)
> 
> diff --git a/drivers/net/phy/sfp.c b/drivers/net/phy/sfp.c
> index 0621d12cf878..21fb96899518 100644
> --- a/drivers/net/phy/sfp.c
> +++ b/drivers/net/phy/sfp.c
> @@ -165,6 +165,7 @@ static const enum gpiod_flags gpio_flags[] = {
>   * on board (for a copper SFP) time to initialise.
>   */
>  #define T_WAIT			msecs_to_jiffies(50)
> +#define T_WAIT_ROLLBALL		msecs_to_jiffies(25000)
>  #define T_START_UP		msecs_to_jiffies(300)
>  #define T_START_UP_BAD_GPON	msecs_to_jiffies(60000)
>  
> @@ -204,8 +205,11 @@ static const enum gpiod_flags gpio_flags[] = {
>  
>  /* SFP modules appear to always have their PHY configured for bus address
>   * 0x56 (which with mdio-i2c, translates to a PHY address of 22).
> + * RollBall SFPs access phy via SFP Enhanced Digital Diagnostic Interface
> + * via address 0x51 (mdio-i2c will use RollBall protocol on this address).
>   */
> -#define SFP_PHY_ADDR	22
> +#define SFP_PHY_ADDR		22
> +#define SFP_PHY_ADDR_ROLLBALL	17
>  
>  struct sff_data {
>  	unsigned int gpios;
> @@ -218,6 +222,7 @@ struct sfp {
>  	struct mii_bus *i2c_mii;
>  	struct sfp_bus *sfp_bus;
>  	enum mdio_i2c_proto mdio_protocol;
> +	int phy_addr;
>  	struct phy_device *mod_phy;
>  	const struct sff_data *type;
>  	size_t i2c_block_size;
> @@ -250,6 +255,7 @@ struct sfp {
>  	struct sfp_eeprom_id id;
>  	unsigned int module_power_mW;
>  	unsigned int module_t_start_up;
> +	unsigned int module_t_wait;
>  
>  #if IS_ENABLED(CONFIG_HWMON)
>  	struct sfp_diag diag;
> @@ -1453,7 +1459,7 @@ static int sfp_sm_probe_phy(struct sfp *sfp, bool is_c45)
>  	struct phy_device *phy;
>  	int err;
>  
> -	phy = get_phy_device(sfp->i2c_mii, SFP_PHY_ADDR, is_c45);
> +	phy = get_phy_device(sfp->i2c_mii, sfp->phy_addr, is_c45);
>  	if (phy == ERR_PTR(-ENODEV))
>  		return PTR_ERR(phy);
>  	if (IS_ERR(phy)) {
> @@ -1835,6 +1841,23 @@ static int sfp_sm_mod_probe(struct sfp *sfp, bool report)
>  
>  	sfp->mdio_protocol = MDIO_I2C_DEFAULT;
>  
> +	sfp->phy_addr = SFP_PHY_ADDR;
> +	sfp->module_t_wait = T_WAIT;
> +
> +	if (((!memcmp(id.base.vendor_name, "OEM             ", 16) ||
> +	      !memcmp(id.base.vendor_name, "Turris          ", 16)) &&
> +	     (!memcmp(id.base.vendor_pn, "SFP-10G-T       ", 16) ||
> +	      !memcmp(id.base.vendor_pn, "RTSFP-10", 8)))) {
> +		sfp->mdio_protocol = MDIO_I2C_ROLLBALL;
> +		sfp->phy_addr = SFP_PHY_ADDR_ROLLBALL;
> +		sfp->module_t_wait = T_WAIT_ROLLBALL;
> +
> +		/* RollBall SFPs may have wrong (zero) extended compliacne code
> +		 * burned in EEPROM. For PHY probing we need the correct one.
> +		 */
> +		id.base.extended_cc = SFF8024_ECC_10GBASE_T_SFI;

Should not we rather in sfp_sm_probe_for_phy() function in "default"
section try to probe also for clause 45 PHY when clause 22 fails?

> +	}
> +
>  	return 0;
>  }
>  
> @@ -2030,9 +2053,10 @@ static void sfp_sm_main(struct sfp *sfp, unsigned int event)
>  
>  		/* We need to check the TX_FAULT state, which is not defined
>  		 * while TX_DISABLE is asserted. The earliest we want to do
> -		 * anything (such as probe for a PHY) is 50ms.
> +		 * anything (such as probe for a PHY) is 50ms. (or more on
> +		 * specific modules).
>  		 */
> -		sfp_sm_next(sfp, SFP_S_WAIT, T_WAIT);
> +		sfp_sm_next(sfp, SFP_S_WAIT, sfp->module_t_wait);
>  		break;
>  
>  	case SFP_S_WAIT:
> @@ -2046,8 +2070,8 @@ static void sfp_sm_main(struct sfp *sfp, unsigned int event)
>  			 * deasserting.
>  			 */
>  			timeout = sfp->module_t_start_up;
> -			if (timeout > T_WAIT)
> -				timeout -= T_WAIT;
> +			if (timeout > sfp->module_t_wait)
> +				timeout -= sfp->module_t_wait;
>  			else
>  				timeout = 1;
>  
> -- 
> 2.26.2
> 

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH net-next v4 1/4] net: phy: mdio-i2c: support I2C MDIO protocol for RollBall SFP modules
  2021-01-12 21:01     ` Marek Behún
@ 2021-01-13 10:51       ` Pali Rohár
  0 siblings, 0 replies; 29+ messages in thread
From: Pali Rohár @ 2021-01-13 10:51 UTC (permalink / raw)
  To: Marek Behún; +Cc: Andrew Lunn, netdev, Russell King, Jakub Kicinski, davem

On Tuesday 12 January 2021 22:01:14 Marek Behún wrote:
> On Tue, 12 Jan 2021 21:54:24 +0100
> Andrew Lunn <andrew@lunn.ch> wrote:
> 
> > > +static int i2c_transfer_rollball(struct i2c_adapter *i2c,
> > > +				 struct i2c_msg *msgs, int num)
> > > +{
> > > +	u8 saved_page;
> > > +	int ret;
> > > +
> > > +	i2c_lock_bus(i2c, I2C_LOCK_SEGMENT);
> > > +
> > > +	/* save original page */
> > > +	ret = __i2c_rollball_get_page(i2c, msgs->addr, &saved_page);
> > > +	if (ret)
> > > +		goto unlock;
> > > +
> > > +	/* change to RollBall MDIO page */
> > > +	ret = __i2c_rollball_set_page(i2c, msgs->addr, SFP_PAGE_ROLLBALL_MDIO);
> > > +	if (ret)
> > > +		goto unlock;
> > > +
> > > +	/* do the transfer */
> > > +	ret = __i2c_transfer_err(i2c, msgs, num);
> > > +	if (ret)
> > > +		goto unlock;  
> > 
> > If get page and set page worked, and you get an error in during the
> > actual data transfer, i wonder if you should try restoring the page
> > before returning with the error?
> 
> I don't know. Can i2c trasfer fail and the next one succeed?

I guess it can depend also on i2c driver. I'm for trying to restore
previous i2c page on failure. In the worst case also restoring fails...

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH net-next v4 4/4] net: sfp: add support for multigig RollBall transceivers
  2021-01-13 10:49   ` Pali Rohár
@ 2021-01-13 11:08     ` Russell King - ARM Linux admin
  2021-01-13 11:26       ` Pali Rohár
  0 siblings, 1 reply; 29+ messages in thread
From: Russell King - ARM Linux admin @ 2021-01-13 11:08 UTC (permalink / raw)
  To: Pali Rohár
  Cc: Marek Behún, netdev, Andrew Lunn, Jakub Kicinski, davem

On Wed, Jan 13, 2021 at 11:49:36AM +0100, Pali Rohár wrote:
> On Monday 11 January 2021 06:00:44 Marek Behún wrote:
> > @@ -1453,7 +1459,7 @@ static int sfp_sm_probe_phy(struct sfp *sfp, bool is_c45)
> >  	struct phy_device *phy;
> >  	int err;
> >  
> > -	phy = get_phy_device(sfp->i2c_mii, SFP_PHY_ADDR, is_c45);
> > +	phy = get_phy_device(sfp->i2c_mii, sfp->phy_addr, is_c45);
> >  	if (phy == ERR_PTR(-ENODEV))
> >  		return PTR_ERR(phy);
> >  	if (IS_ERR(phy)) {
> > @@ -1835,6 +1841,23 @@ static int sfp_sm_mod_probe(struct sfp *sfp, bool report)
> >  
> >  	sfp->mdio_protocol = MDIO_I2C_DEFAULT;
> >  
> > +	sfp->phy_addr = SFP_PHY_ADDR;
> > +	sfp->module_t_wait = T_WAIT;
> > +
> > +	if (((!memcmp(id.base.vendor_name, "OEM             ", 16) ||
> > +	      !memcmp(id.base.vendor_name, "Turris          ", 16)) &&
> > +	     (!memcmp(id.base.vendor_pn, "SFP-10G-T       ", 16) ||
> > +	      !memcmp(id.base.vendor_pn, "RTSFP-10", 8)))) {
> > +		sfp->mdio_protocol = MDIO_I2C_ROLLBALL;
> > +		sfp->phy_addr = SFP_PHY_ADDR_ROLLBALL;
> > +		sfp->module_t_wait = T_WAIT_ROLLBALL;
> > +
> > +		/* RollBall SFPs may have wrong (zero) extended compliacne code

Spelling error - "compliance"

> > +		 * burned in EEPROM. For PHY probing we need the correct one.
> > +		 */
> > +		id.base.extended_cc = SFF8024_ECC_10GBASE_T_SFI;
> 
> Should not we rather in sfp_sm_probe_for_phy() function in "default"
> section try to probe also for clause 45 PHY when clause 22 fails?

Why? That's opening the possibilities for more problems - remember,
the access method is vendor defined, and we already have the situation
where I2C address 0x56 is used in two different styles that are
indistinguishable:

- Clause 22 write:
	Write register address, value high, value low.
- Clause 22 read:
	Write register address.
	Read value high, low.
- Clause 45 write:
	Write devad, register address high, register address low,
		value high, value low.
- Clause 45 read:
	Write devad, register address high, register address low.
	Read value high, low.

Look closely at the similarities of Clause 22 write and Clause 45
read, you'll see that if you issue a clause 45 read to a SFP module
that implements Clause 22, you actually end up issuing a write to it.

Sending random MDIO cycles to a SFP is a really bad idea.

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

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH net-next v4 1/4] net: phy: mdio-i2c: support I2C MDIO protocol for RollBall SFP modules
  2021-01-11  5:00 ` [PATCH net-next v4 1/4] net: phy: mdio-i2c: support I2C MDIO protocol for RollBall " Marek Behún
                     ` (3 preceding siblings ...)
  2021-01-12 20:54   ` Andrew Lunn
@ 2021-01-13 11:22   ` Pali Rohár
  2021-01-13 13:56     ` Andrew Lunn
  4 siblings, 1 reply; 29+ messages in thread
From: Pali Rohár @ 2021-01-13 11:22 UTC (permalink / raw)
  To: Marek Behún; +Cc: netdev, Russell King, Andrew Lunn, Jakub Kicinski, davem

Hello! See my comments below.

On Monday 11 January 2021 06:00:41 Marek Behún wrote:
> Some multigig SFPs from RollBall and Hilink do not expose functional
> MDIO access to the internal PHY of the SFP via I2C address 0x56
> (although there seems to be read-only clause 22 access on this address).

Maybe it could be interesting to test if clause 22 access via i2c
address 0x56 can work also in write mode after setting rollball
password...

> Instead these SFPs PHY can be accessed via I2C via the SFP Enhanced
> Digital Diagnostic Interface - I2C address 0x51. The SFP_PAGE has to be
> selected to 3 and the password must be filled with 0xff bytes for this
> PHY communication to work.
> 
> This extends the mdio-i2c driver to support this protocol by adding a
> special parameter to mdio_i2c_alloc function via which this RollBall
> protocol can be selected.
> 
> Signed-off-by: Marek Behún <kabel@kernel.org>
> Cc: Andrew Lunn <andrew@lunn.ch>
> Cc: Russell King <rmk+kernel@armlinux.org.uk>
> ---
>  drivers/net/mdio/mdio-i2c.c   | 319 +++++++++++++++++++++++++++++++++-
>  drivers/net/phy/sfp.c         |   2 +-
>  include/linux/mdio/mdio-i2c.h |   8 +-
>  3 files changed, 322 insertions(+), 7 deletions(-)
> 
> diff --git a/drivers/net/mdio/mdio-i2c.c b/drivers/net/mdio/mdio-i2c.c
> index 09200a70b315..7be582c0891a 100644
> --- a/drivers/net/mdio/mdio-i2c.c
> +++ b/drivers/net/mdio/mdio-i2c.c
...
> @@ -91,9 +94,297 @@ static int i2c_mii_write(struct mii_bus *bus, int phy_id, int reg, u16 val)
>  	return ret < 0 ? ret : 0;
>  }
>  
> -struct mii_bus *mdio_i2c_alloc(struct device *parent, struct i2c_adapter *i2c)
> +/* RollBall SFPs do not access internal PHY via I2C address 0x56, but
> + * instead via address 0x51, when SFP page is set to 0x03 and password to
> + * 0xffffffff.
> + * Since current SFP code does not modify SFP_PAGE, we set it to 0x03 only at
> + * bus creation time, and expect it to remain set to 0x03 throughout the
> + * lifetime of the module plugged into the system. If the SFP code starts
> + * modifying SFP_PAGE in the future, this code will need to change.
> + *
> + * address  size  contents  description
> + * -------  ----  --------  -----------
> + * 0x80     1     CMD       0x01/0x02/0x04 for write/read/done
> + * 0x81     1     DEV       Clause 45 device
> + * 0x82     2     REG       Clause 45 register
> + * 0x84     2     VAL       Register value
> + */
> +#define ROLLBALL_PHY_I2C_ADDR		0x51
> +#define ROLLBALL_SFP_PASSWORD_ADDR	0x7b

It looks like that this password entry is standard field described in
QSFP+ specifications SFF-8436 and SFF-8636. Should not it be rather
named vendor-neutral (as it is not Rollball specific)? And maybe defined
in include/linux/sfp.h file where also also other standard macros, like
SFP_PAGE macro?

> +
> +#define ROLLBALL_CMD_ADDR		0x80
> +#define ROLLBALL_DATA_ADDR		0x81
> +
> +#define ROLLBALL_CMD_WRITE		0x01
> +#define ROLLBALL_CMD_READ		0x02
> +#define ROLLBALL_CMD_DONE		0x04
> +
> +#define SFP_PAGE_ROLLBALL_MDIO		3
...
> diff --git a/include/linux/mdio/mdio-i2c.h b/include/linux/mdio/mdio-i2c.h
> index b1d27f7cd23f..53eedb0dc1d3 100644
> --- a/include/linux/mdio/mdio-i2c.h
> +++ b/include/linux/mdio/mdio-i2c.h
> @@ -11,6 +11,12 @@ struct device;
>  struct i2c_adapter;
>  struct mii_bus;
>  
> -struct mii_bus *mdio_i2c_alloc(struct device *parent, struct i2c_adapter *i2c);
> +enum mdio_i2c_proto {
> +	MDIO_I2C_DEFAULT,

Russel wrote that current mdio i2c (default) access method is also
vendor specific for Marvell chips. Should not we rather call it
MDIO_I2C_MARVELL if both methods are vendor/chip specific?

> +	MDIO_I2C_ROLLBALL,
> +};
> +
> +struct mii_bus *mdio_i2c_alloc(struct device *parent, struct i2c_adapter *i2c,
> +			       enum mdio_i2c_proto protocol);
>  
>  #endif
> -- 
> 2.26.2
> 

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH net-next v4 4/4] net: sfp: add support for multigig RollBall transceivers
  2021-01-13 11:08     ` Russell King - ARM Linux admin
@ 2021-01-13 11:26       ` Pali Rohár
  0 siblings, 0 replies; 29+ messages in thread
From: Pali Rohár @ 2021-01-13 11:26 UTC (permalink / raw)
  To: Russell King - ARM Linux admin
  Cc: Marek Behún, netdev, Andrew Lunn, Jakub Kicinski, davem

On Wednesday 13 January 2021 11:08:52 Russell King - ARM Linux admin wrote:
> On Wed, Jan 13, 2021 at 11:49:36AM +0100, Pali Rohár wrote:
> > On Monday 11 January 2021 06:00:44 Marek Behún wrote:
> > > @@ -1453,7 +1459,7 @@ static int sfp_sm_probe_phy(struct sfp *sfp, bool is_c45)
> > >  	struct phy_device *phy;
> > >  	int err;
> > >  
> > > -	phy = get_phy_device(sfp->i2c_mii, SFP_PHY_ADDR, is_c45);
> > > +	phy = get_phy_device(sfp->i2c_mii, sfp->phy_addr, is_c45);
> > >  	if (phy == ERR_PTR(-ENODEV))
> > >  		return PTR_ERR(phy);
> > >  	if (IS_ERR(phy)) {
> > > @@ -1835,6 +1841,23 @@ static int sfp_sm_mod_probe(struct sfp *sfp, bool report)
> > >  
> > >  	sfp->mdio_protocol = MDIO_I2C_DEFAULT;
> > >  
> > > +	sfp->phy_addr = SFP_PHY_ADDR;
> > > +	sfp->module_t_wait = T_WAIT;
> > > +
> > > +	if (((!memcmp(id.base.vendor_name, "OEM             ", 16) ||
> > > +	      !memcmp(id.base.vendor_name, "Turris          ", 16)) &&
> > > +	     (!memcmp(id.base.vendor_pn, "SFP-10G-T       ", 16) ||
> > > +	      !memcmp(id.base.vendor_pn, "RTSFP-10", 8)))) {
> > > +		sfp->mdio_protocol = MDIO_I2C_ROLLBALL;
> > > +		sfp->phy_addr = SFP_PHY_ADDR_ROLLBALL;
> > > +		sfp->module_t_wait = T_WAIT_ROLLBALL;
> > > +
> > > +		/* RollBall SFPs may have wrong (zero) extended compliacne code
> 
> Spelling error - "compliance"
> 
> > > +		 * burned in EEPROM. For PHY probing we need the correct one.
> > > +		 */
> > > +		id.base.extended_cc = SFF8024_ECC_10GBASE_T_SFI;
> > 
> > Should not we rather in sfp_sm_probe_for_phy() function in "default"
> > section try to probe also for clause 45 PHY when clause 22 fails?
> 
> Why? That's opening the possibilities for more problems - remember,
> the access method is vendor defined, and we already have the situation
> where I2C address 0x56 is used in two different styles that are
> indistinguishable:
> 
> - Clause 22 write:
> 	Write register address, value high, value low.
> - Clause 22 read:
> 	Write register address.
> 	Read value high, low.
> - Clause 45 write:
> 	Write devad, register address high, register address low,
> 		value high, value low.
> - Clause 45 read:
> 	Write devad, register address high, register address low.
> 	Read value high, low.
> 
> Look closely at the similarities of Clause 22 write and Clause 45
> read, you'll see that if you issue a clause 45 read to a SFP module
> that implements Clause 22, you actually end up issuing a write to it.
> 
> Sending random MDIO cycles to a SFP is a really bad idea.

I see, thank you for explanation. Incorrect data in SFP EEPROM may cause
lot of other issues :-(

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH net-next v4 1/4] net: phy: mdio-i2c: support I2C MDIO protocol for RollBall SFP modules
  2021-01-13 11:22   ` Pali Rohár
@ 2021-01-13 13:56     ` Andrew Lunn
  2021-01-13 13:58       ` Pali Rohár
  2021-01-13 16:14       ` Russell King - ARM Linux admin
  0 siblings, 2 replies; 29+ messages in thread
From: Andrew Lunn @ 2021-01-13 13:56 UTC (permalink / raw)
  To: Pali Rohár
  Cc: Marek Behún, netdev, Russell King, Jakub Kicinski, davem

On Wed, Jan 13, 2021 at 12:22:04PM +0100, Pali Rohár wrote:
> Hello! See my comments below.
> 
> On Monday 11 January 2021 06:00:41 Marek Behún wrote:
> > Some multigig SFPs from RollBall and Hilink do not expose functional
> > MDIO access to the internal PHY of the SFP via I2C address 0x56
> > (although there seems to be read-only clause 22 access on this address).
> 
> Maybe it could be interesting to test if clause 22 access via i2c
> address 0x56 can work also in write mode after setting rollball
> password...
> 
> > Instead these SFPs PHY can be accessed via I2C via the SFP Enhanced
> > Digital Diagnostic Interface - I2C address 0x51. The SFP_PAGE has to be
> > selected to 3 and the password must be filled with 0xff bytes for this
> > PHY communication to work.
> > 
> > This extends the mdio-i2c driver to support this protocol by adding a
> > special parameter to mdio_i2c_alloc function via which this RollBall
> > protocol can be selected.
> > 
> > Signed-off-by: Marek Behún <kabel@kernel.org>
> > Cc: Andrew Lunn <andrew@lunn.ch>
> > Cc: Russell King <rmk+kernel@armlinux.org.uk>
> > ---
> >  drivers/net/mdio/mdio-i2c.c   | 319 +++++++++++++++++++++++++++++++++-
> >  drivers/net/phy/sfp.c         |   2 +-
> >  include/linux/mdio/mdio-i2c.h |   8 +-
> >  3 files changed, 322 insertions(+), 7 deletions(-)
> > 
> > diff --git a/drivers/net/mdio/mdio-i2c.c b/drivers/net/mdio/mdio-i2c.c
> > index 09200a70b315..7be582c0891a 100644
> > --- a/drivers/net/mdio/mdio-i2c.c
> > +++ b/drivers/net/mdio/mdio-i2c.c
> ...
> > @@ -91,9 +94,297 @@ static int i2c_mii_write(struct mii_bus *bus, int phy_id, int reg, u16 val)
> >  	return ret < 0 ? ret : 0;
> >  }
> >  
> > -struct mii_bus *mdio_i2c_alloc(struct device *parent, struct i2c_adapter *i2c)
> > +/* RollBall SFPs do not access internal PHY via I2C address 0x56, but
> > + * instead via address 0x51, when SFP page is set to 0x03 and password to
> > + * 0xffffffff.
> > + * Since current SFP code does not modify SFP_PAGE, we set it to 0x03 only at
> > + * bus creation time, and expect it to remain set to 0x03 throughout the
> > + * lifetime of the module plugged into the system. If the SFP code starts
> > + * modifying SFP_PAGE in the future, this code will need to change.
> > + *
> > + * address  size  contents  description
> > + * -------  ----  --------  -----------
> > + * 0x80     1     CMD       0x01/0x02/0x04 for write/read/done
> > + * 0x81     1     DEV       Clause 45 device
> > + * 0x82     2     REG       Clause 45 register
> > + * 0x84     2     VAL       Register value
> > + */
> > +#define ROLLBALL_PHY_I2C_ADDR		0x51
> > +#define ROLLBALL_SFP_PASSWORD_ADDR	0x7b
> 
> It looks like that this password entry is standard field described in
> QSFP+ specifications SFF-8436 and SFF-8636. Should not it be rather
> named vendor-neutral (as it is not Rollball specific)? And maybe defined
> in include/linux/sfp.h file where also also other standard macros, like
> SFP_PAGE macro?

If it is generic, the functions themselves should probably move into
sfp.c. Being able to swap pages is something needed for accessing the
diagnostic registers under some conditions. Because we don't have
support for changing the page, the HWMON support is disabled in this
condition.

	Andrew

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH net-next v4 1/4] net: phy: mdio-i2c: support I2C MDIO protocol for RollBall SFP modules
  2021-01-13 13:56     ` Andrew Lunn
@ 2021-01-13 13:58       ` Pali Rohár
  2021-01-13 16:14       ` Russell King - ARM Linux admin
  1 sibling, 0 replies; 29+ messages in thread
From: Pali Rohár @ 2021-01-13 13:58 UTC (permalink / raw)
  To: Andrew Lunn; +Cc: Marek Behún, netdev, Russell King, Jakub Kicinski, davem

On Wednesday 13 January 2021 14:56:13 Andrew Lunn wrote:
> On Wed, Jan 13, 2021 at 12:22:04PM +0100, Pali Rohár wrote:
> > Hello! See my comments below.
> > 
> > On Monday 11 January 2021 06:00:41 Marek Behún wrote:
> > > Some multigig SFPs from RollBall and Hilink do not expose functional
> > > MDIO access to the internal PHY of the SFP via I2C address 0x56
> > > (although there seems to be read-only clause 22 access on this address).
> > 
> > Maybe it could be interesting to test if clause 22 access via i2c
> > address 0x56 can work also in write mode after setting rollball
> > password...
> > 
> > > Instead these SFPs PHY can be accessed via I2C via the SFP Enhanced
> > > Digital Diagnostic Interface - I2C address 0x51. The SFP_PAGE has to be
> > > selected to 3 and the password must be filled with 0xff bytes for this
> > > PHY communication to work.
> > > 
> > > This extends the mdio-i2c driver to support this protocol by adding a
> > > special parameter to mdio_i2c_alloc function via which this RollBall
> > > protocol can be selected.
> > > 
> > > Signed-off-by: Marek Behún <kabel@kernel.org>
> > > Cc: Andrew Lunn <andrew@lunn.ch>
> > > Cc: Russell King <rmk+kernel@armlinux.org.uk>
> > > ---
> > >  drivers/net/mdio/mdio-i2c.c   | 319 +++++++++++++++++++++++++++++++++-
> > >  drivers/net/phy/sfp.c         |   2 +-
> > >  include/linux/mdio/mdio-i2c.h |   8 +-
> > >  3 files changed, 322 insertions(+), 7 deletions(-)
> > > 
> > > diff --git a/drivers/net/mdio/mdio-i2c.c b/drivers/net/mdio/mdio-i2c.c
> > > index 09200a70b315..7be582c0891a 100644
> > > --- a/drivers/net/mdio/mdio-i2c.c
> > > +++ b/drivers/net/mdio/mdio-i2c.c
> > ...
> > > @@ -91,9 +94,297 @@ static int i2c_mii_write(struct mii_bus *bus, int phy_id, int reg, u16 val)
> > >  	return ret < 0 ? ret : 0;
> > >  }
> > >  
> > > -struct mii_bus *mdio_i2c_alloc(struct device *parent, struct i2c_adapter *i2c)
> > > +/* RollBall SFPs do not access internal PHY via I2C address 0x56, but
> > > + * instead via address 0x51, when SFP page is set to 0x03 and password to
> > > + * 0xffffffff.
> > > + * Since current SFP code does not modify SFP_PAGE, we set it to 0x03 only at
> > > + * bus creation time, and expect it to remain set to 0x03 throughout the
> > > + * lifetime of the module plugged into the system. If the SFP code starts
> > > + * modifying SFP_PAGE in the future, this code will need to change.
> > > + *
> > > + * address  size  contents  description
> > > + * -------  ----  --------  -----------
> > > + * 0x80     1     CMD       0x01/0x02/0x04 for write/read/done
> > > + * 0x81     1     DEV       Clause 45 device
> > > + * 0x82     2     REG       Clause 45 register
> > > + * 0x84     2     VAL       Register value
> > > + */
> > > +#define ROLLBALL_PHY_I2C_ADDR		0x51
> > > +#define ROLLBALL_SFP_PASSWORD_ADDR	0x7b
> > 
> > It looks like that this password entry is standard field described in
> > QSFP+ specifications SFF-8436 and SFF-8636. Should not it be rather
> > named vendor-neutral (as it is not Rollball specific)? And maybe defined
> > in include/linux/sfp.h file where also also other standard macros, like
> > SFP_PAGE macro?
> 
> If it is generic, the functions themselves should probably move into
> sfp.c. Being able to swap pages is something needed for accessing the
> diagnostic registers under some conditions. Because we don't have
> support for changing the page, the HWMON support is disabled in this
> condition.

Only password is described in SFF-8436 and SFF-8636, nothing more.

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH net-next v4 1/4] net: phy: mdio-i2c: support I2C MDIO protocol for RollBall SFP modules
  2021-01-13 13:56     ` Andrew Lunn
  2021-01-13 13:58       ` Pali Rohár
@ 2021-01-13 16:14       ` Russell King - ARM Linux admin
  1 sibling, 0 replies; 29+ messages in thread
From: Russell King - ARM Linux admin @ 2021-01-13 16:14 UTC (permalink / raw)
  To: Andrew Lunn
  Cc: Pali Rohár, Marek Behún, netdev, Jakub Kicinski, davem

On Wed, Jan 13, 2021 at 02:56:13PM +0100, Andrew Lunn wrote:
> On Wed, Jan 13, 2021 at 12:22:04PM +0100, Pali Rohár wrote:
> > Hello! See my comments below.
> > 
> > On Monday 11 January 2021 06:00:41 Marek Behún wrote:
> > > Some multigig SFPs from RollBall and Hilink do not expose functional
> > > MDIO access to the internal PHY of the SFP via I2C address 0x56
> > > (although there seems to be read-only clause 22 access on this address).
> > 
> > Maybe it could be interesting to test if clause 22 access via i2c
> > address 0x56 can work also in write mode after setting rollball
> > password...
> > 
> > > Instead these SFPs PHY can be accessed via I2C via the SFP Enhanced
> > > Digital Diagnostic Interface - I2C address 0x51. The SFP_PAGE has to be
> > > selected to 3 and the password must be filled with 0xff bytes for this
> > > PHY communication to work.
> > > 
> > > This extends the mdio-i2c driver to support this protocol by adding a
> > > special parameter to mdio_i2c_alloc function via which this RollBall
> > > protocol can be selected.
> > > 
> > > Signed-off-by: Marek Behún <kabel@kernel.org>
> > > Cc: Andrew Lunn <andrew@lunn.ch>
> > > Cc: Russell King <rmk+kernel@armlinux.org.uk>
> > > ---
> > >  drivers/net/mdio/mdio-i2c.c   | 319 +++++++++++++++++++++++++++++++++-
> > >  drivers/net/phy/sfp.c         |   2 +-
> > >  include/linux/mdio/mdio-i2c.h |   8 +-
> > >  3 files changed, 322 insertions(+), 7 deletions(-)
> > > 
> > > diff --git a/drivers/net/mdio/mdio-i2c.c b/drivers/net/mdio/mdio-i2c.c
> > > index 09200a70b315..7be582c0891a 100644
> > > --- a/drivers/net/mdio/mdio-i2c.c
> > > +++ b/drivers/net/mdio/mdio-i2c.c
> > ...
> > > @@ -91,9 +94,297 @@ static int i2c_mii_write(struct mii_bus *bus, int phy_id, int reg, u16 val)
> > >  	return ret < 0 ? ret : 0;
> > >  }
> > >  
> > > -struct mii_bus *mdio_i2c_alloc(struct device *parent, struct i2c_adapter *i2c)
> > > +/* RollBall SFPs do not access internal PHY via I2C address 0x56, but
> > > + * instead via address 0x51, when SFP page is set to 0x03 and password to
> > > + * 0xffffffff.
> > > + * Since current SFP code does not modify SFP_PAGE, we set it to 0x03 only at
> > > + * bus creation time, and expect it to remain set to 0x03 throughout the
> > > + * lifetime of the module plugged into the system. If the SFP code starts
> > > + * modifying SFP_PAGE in the future, this code will need to change.
> > > + *
> > > + * address  size  contents  description
> > > + * -------  ----  --------  -----------
> > > + * 0x80     1     CMD       0x01/0x02/0x04 for write/read/done
> > > + * 0x81     1     DEV       Clause 45 device
> > > + * 0x82     2     REG       Clause 45 register
> > > + * 0x84     2     VAL       Register value
> > > + */
> > > +#define ROLLBALL_PHY_I2C_ADDR		0x51
> > > +#define ROLLBALL_SFP_PASSWORD_ADDR	0x7b
> > 
> > It looks like that this password entry is standard field described in
> > QSFP+ specifications SFF-8436 and SFF-8636. Should not it be rather
> > named vendor-neutral (as it is not Rollball specific)? And maybe defined
> > in include/linux/sfp.h file where also also other standard macros, like
> > SFP_PAGE macro?
> 
> If it is generic, the functions themselves should probably move into
> sfp.c. Being able to swap pages is something needed for accessing the
> diagnostic registers under some conditions. Because we don't have
> support for changing the page, the HWMON support is disabled in this
> condition.

QSFPs are quite different from SFPs.
- the data structures in the "I2C device" are quite different.
- they don't have as many controls signals either - signals such as
  RX_LOS, TX_DISABLE etc are handled per channel and are only exposed
  via the I2C bus.

I've some rudimentary code for QSFP support in my CEX7 branch, which is
currently entirely separate from the SFP code. I haven't done much on
that for quite some time due to the historical difficulties of working
with NXP, but I have over the course of the last week updated my branch
to 5.10 and have patches to move SFP support forward. However, I expect
further difficulties interacting with NXP and fully expect to be
blocked from being able to achieve anything useful.

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

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH net-next v4 1/4] net: phy: mdio-i2c: support I2C MDIO protocol for RollBall SFP modules
  2021-01-12 19:22     ` Russell King - ARM Linux admin
@ 2021-01-18 12:13       ` Pali Rohár
  2021-01-18 15:45         ` Russell King - ARM Linux admin
  0 siblings, 1 reply; 29+ messages in thread
From: Pali Rohár @ 2021-01-18 12:13 UTC (permalink / raw)
  To: Russell King - ARM Linux admin
  Cc: Heiner Kallweit, Marek Behún, netdev, Andrew Lunn,
	Jakub Kicinski, davem

On Tuesday 12 January 2021 19:22:33 Russell King - ARM Linux admin wrote:
> On Tue, Jan 12, 2021 at 09:42:56AM +0100, Heiner Kallweit wrote:
> > On 11.01.2021 06:00, Marek Behún wrote:
> > > Some multigig SFPs from RollBall and Hilink do not expose functional
> > > MDIO access to the internal PHY of the SFP via I2C address 0x56
> > > (although there seems to be read-only clause 22 access on this address).
> > > 
> > > Instead these SFPs PHY can be accessed via I2C via the SFP Enhanced
> > > Digital Diagnostic Interface - I2C address 0x51. The SFP_PAGE has to be
> > > selected to 3 and the password must be filled with 0xff bytes for this
> > > PHY communication to work.
> > > 
> > > This extends the mdio-i2c driver to support this protocol by adding a
> > > special parameter to mdio_i2c_alloc function via which this RollBall
> > > protocol can be selected.
> > > 
> > I'd think that mdio-i2c.c is for generic code. When adding a
> > vendor-specific protocol, wouldn't it make sense to use a dedicated
> > source file for it?
> 
> There is nothing in the SFP MSAs about how to access an on-board PHY
> on a SFP. This is something that vendors choose to do (or in some
> cases, not do.)
> 
> mdio-i2c currently implements the access protocol for Marvell 88E1111
> PHYs which have an I2C mode. It was extended to support the DM7052
> module which has a Broadcom Clause 45 PHY and either a microcontroller
> or FPGA to convert I2C cycles to MDIO cycles - and sensibly performs
> clock stretching.

Just to note that there is also another Marvell way how to access Clause
45 registers via existing Marvell PHY Clause 22 I2C mode:

https://www.ieee802.org/3/efm/public/nov02/oam/pannell_oam_1_1102.pdf

Clause 45 registers are accessed via Clause 22 regs 13 and 14.

> There are modules that the clause 45 PHY is accessible via exactly the
> same I2C address, using exactly the same data accesses, but do not
> do the clock stretching thing, instead telling you that you must wait
> N microseconds between the bus transactions. We don't yet support
> these.
> 
> Then there is Marek's module, where the PHY is accessible via a page
> in the diagnostic address - which is another entirely reasonable
> implementation. The solution we have here is one that I've worked with
> Marek for a few months now.
> 
> I don't think we should grow lots of separate mdio-i2c-vendorfoo.c
> drivers - at least not yet. Maybe if we get lots of different access
> methods, it may make sense in the future.
> 
> -- 
> RMK's Patch system: https://www.armlinux.org.uk/developer/patches/
> FTTP is here! 40Mbps down 10Mbps up. Decent connectivity at last!

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH net-next v4 1/4] net: phy: mdio-i2c: support I2C MDIO protocol for RollBall SFP modules
  2021-01-18 12:13       ` Pali Rohár
@ 2021-01-18 15:45         ` Russell King - ARM Linux admin
  0 siblings, 0 replies; 29+ messages in thread
From: Russell King - ARM Linux admin @ 2021-01-18 15:45 UTC (permalink / raw)
  To: Pali Rohár
  Cc: Heiner Kallweit, Marek Behún, netdev, Andrew Lunn,
	Jakub Kicinski, davem

On Mon, Jan 18, 2021 at 01:13:38PM +0100, Pali Rohár wrote:
> On Tuesday 12 January 2021 19:22:33 Russell King - ARM Linux admin wrote:
> > On Tue, Jan 12, 2021 at 09:42:56AM +0100, Heiner Kallweit wrote:
> > > On 11.01.2021 06:00, Marek Behún wrote:
> > > > Some multigig SFPs from RollBall and Hilink do not expose functional
> > > > MDIO access to the internal PHY of the SFP via I2C address 0x56
> > > > (although there seems to be read-only clause 22 access on this address).
> > > > 
> > > > Instead these SFPs PHY can be accessed via I2C via the SFP Enhanced
> > > > Digital Diagnostic Interface - I2C address 0x51. The SFP_PAGE has to be
> > > > selected to 3 and the password must be filled with 0xff bytes for this
> > > > PHY communication to work.
> > > > 
> > > > This extends the mdio-i2c driver to support this protocol by adding a
> > > > special parameter to mdio_i2c_alloc function via which this RollBall
> > > > protocol can be selected.
> > > > 
> > > I'd think that mdio-i2c.c is for generic code. When adding a
> > > vendor-specific protocol, wouldn't it make sense to use a dedicated
> > > source file for it?
> > 
> > There is nothing in the SFP MSAs about how to access an on-board PHY
> > on a SFP. This is something that vendors choose to do (or in some
> > cases, not do.)
> > 
> > mdio-i2c currently implements the access protocol for Marvell 88E1111
> > PHYs which have an I2C mode. It was extended to support the DM7052
> > module which has a Broadcom Clause 45 PHY and either a microcontroller
> > or FPGA to convert I2C cycles to MDIO cycles - and sensibly performs
> > clock stretching.
> 
> Just to note that there is also another Marvell way how to access Clause
> 45 registers via existing Marvell PHY Clause 22 I2C mode:
> 
> https://www.ieee802.org/3/efm/public/nov02/oam/pannell_oam_1_1102.pdf
> 
> Clause 45 registers are accessed via Clause 22 regs 13 and 14.

Only if the Clause 45 PHY supports the Clause 22 interface. Not all do.

However, which access method really only depends on the SFP module,
and how they interface the PHY to the I2C bus. As I've previously
mentioned, using a wrong access method will be misinterpreted by
the SFP.

Even if the PHY supports both Clause 22 and Clause 45 accesses,
if the I2C-to-MDIO layer in the SFP only supports Clause 45, then
Clause 22 accesses will not work. As I've previously said, a
Clause 45 read access is indistinguishable from a Clause 22 write
access on the I2C bus.

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

^ permalink raw reply	[flat|nested] 29+ messages in thread

end of thread, other threads:[~2021-01-18 15:49 UTC | newest]

Thread overview: 29+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-01-11  5:00 [PATCH net-next v4 0/4] Support for RollBall 10G copper SFP modules Marek Behún
2021-01-11  5:00 ` [PATCH net-next v4 1/4] net: phy: mdio-i2c: support I2C MDIO protocol for RollBall " Marek Behún
2021-01-12  8:42   ` Heiner Kallweit
2021-01-12 14:02     ` Andrew Lunn
2021-01-12 14:40       ` Heiner Kallweit
2021-01-12 17:49       ` Marek Behún
2021-01-12 19:22     ` Russell King - ARM Linux admin
2021-01-18 12:13       ` Pali Rohár
2021-01-18 15:45         ` Russell King - ARM Linux admin
2021-01-12 20:20   ` Andrew Lunn
2021-01-12 20:43   ` Andrew Lunn
2021-01-12 20:53     ` Marek Behún
2021-01-12 20:55       ` Andrew Lunn
2021-01-12 20:54   ` Andrew Lunn
2021-01-12 21:01     ` Marek Behún
2021-01-13 10:51       ` Pali Rohár
2021-01-12 21:22     ` Russell King - ARM Linux admin
2021-01-13 11:22   ` Pali Rohár
2021-01-13 13:56     ` Andrew Lunn
2021-01-13 13:58       ` Pali Rohár
2021-01-13 16:14       ` Russell King - ARM Linux admin
2021-01-11  5:00 ` [PATCH net-next v4 2/4] net: phylink: allow attaching phy for SFP modules on 802.3z mode Marek Behún
2021-01-13 10:38   ` Pali Rohár
2021-01-11  5:00 ` [PATCH net-next v4 3/4] net: sfp: create/destroy I2C mdiobus before PHY probe/after PHY release Marek Behún
2021-01-13 10:41   ` Pali Rohár
2021-01-11  5:00 ` [PATCH net-next v4 4/4] net: sfp: add support for multigig RollBall transceivers Marek Behún
2021-01-13 10:49   ` Pali Rohár
2021-01-13 11:08     ` Russell King - ARM Linux admin
2021-01-13 11:26       ` Pali Rohár

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).