All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v6 net-next 00/14] net: phy: marvell-88q2xxx: add driver for the Marvell 88Q2220 PHY
@ 2024-02-13 21:39 Dimitri Fedrau
  2024-02-13 21:39 ` [PATCH v6 net-next 01/14] net: phy: Add BaseT1 auto-negotiation constants Dimitri Fedrau
                   ` (13 more replies)
  0 siblings, 14 replies; 28+ messages in thread
From: Dimitri Fedrau @ 2024-02-13 21:39 UTC (permalink / raw)
  Cc: Dimitri Fedrau, Andrew Lunn, Heiner Kallweit, Russell King,
	David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Stefan Eichenberger, netdev, linux-kernel

Changes in v2:
	- used defines MDIO_CTRL1_LPOWER and MDIO_PMA_CTRL1_SPEED1000
	  in mv88q222x_config_aneg_preinit
	- use genphy_c45_loopback
	- mv88q2xxx_read_status reads speed, master or slave state when
	  autonegotiation is enabled
	- added defines for magic values in mv88q222x_get_sqi

Changes in v3:
	- mv88q2xxx_read_status includes autonegotiation case
	- add support for 100BT1 and 1000BT1 linkmode advertisement
	- use mv88q2xxx_get_sqi and mv88q2xxx_get_sqi_max, remove
	  mv88q222x_get_sqi and mv88q222x_get_sqi_max
	- fix typo: rename mv88q2xxxx_get_sqi and mv88q2xxxx_get_sqi_max to
	  mv88q2xxx_get_sqi and mv88q2xxx_get_sqi
	- add define MDIO_MMD_PCS_MV_RX_STAT for magic value 0x8230, documented
	  in latest datasheets for both PHYs

Changes in V4:
	- clean up init sequence
	- separate patch for fixing typos in upstreamed code

Changes in V5:
	- add missing statics for mv88q222x_revb0_init_seq0 and
	  mv88q222x_revb0_init_seq1
	- fix typo in commit message: autonegotiation
	- fix ordering of Signed-off-by and Reviewed-by in commit messages
	- add interrupt support for link detection
	- add suspend / resume ops
	- add support for internal temperature sensor
	- add cable test support
	- call .soft_reset in mv88q2xxx_config_aneg, this makes
	  mv88q2xxx_config_aneg compatible for Marvell88Q222x devices and
	  remove mv88q222x_config_aneg which is then just duplicated code
	- cleanup mv88q2xxx_config_init and make it compatible with
	  Marvell88Q222x devices
	- move parts from mv88q222x_config_init to mv88q2xxx_config_init
	  that are applicable for all Marvell88Q2xxx devices.

Changes in V6:
	- add copyright and where the code is derived from (patch 5). Sorry
	  Andrew. It is already reviewed, but I think it is the right place.
	  Didn't remove the Reviewed-by because the changes doesn't touch any
	  code that is getting executed.
	- add HWMON dependeny in Kconfig (patch 8)
	- use IS_ENABLED(CONFIG_HWMON) instead of ifdef CONFIG_HWMON to support
	  hwmon built as module (patch 8)
	- drop shift constant MDIO_MMD_PCS_MV_TEMP_SENSOR3_INT_THRESH_SHIFT
	  and use FIELD_GET and FIELD_PREP instead(patch 8)
	- drop shift constant MDIO_MMD_PCS_MV_TDR_STATUS_DIST_SHIFT and use
	  FIELD_GET and FIELD_PREP instead (patch 9)
	- split previous patch 13 into two patches.

Dimitri Fedrau (14):
  net: phy: Add BaseT1 auto-negotiation constants
  net: phy: Support 100/1000BT1 linkmode advertisements
  net: phy: c45: detect 100/1000BASE-T1 linkmode advertisements
  net: phy: marvell-88q2xxx: fix typos
  net: phy: marvell-88q2xxx: add driver for the Marvell 88Q2220 PHY
  net: phy: marvell-88q2xxx: add interrupt support for link detection
  net: phy: marvell-88q2xxx: add suspend / resume ops
  net: phy: marvell-88q2xxx: add support for temperature sensor
  net: phy: marvell-88q2xxx: add cable test support
  net: phy: marvell-88q2xxx: make mv88q2xxx_config_aneg generic
  net: phy: marvell-88q2xxx: switch to mv88q2xxx_config_aneg
  net: phy: marvell-88q2xxx: cleanup mv88q2xxx_config_init
  net: phy: marvell-88q2xxx: remove duplicated assignment of pma_extable
  net: phy: marvell-88q2xxx: move interrupt configuration

 drivers/net/phy/Kconfig           |   1 +
 drivers/net/phy/marvell-88q2xxx.c | 630 ++++++++++++++++++++++++++++--
 drivers/net/phy/phy-c45.c         |   3 +-
 include/linux/marvell_phy.h       |   1 +
 include/linux/mdio.h              |   8 +
 include/uapi/linux/mdio.h         |   2 +
 6 files changed, 615 insertions(+), 30 deletions(-)

-- 
2.39.2


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

* [PATCH v6 net-next 01/14] net: phy: Add BaseT1 auto-negotiation constants
  2024-02-13 21:39 [PATCH v6 net-next 00/14] net: phy: marvell-88q2xxx: add driver for the Marvell 88Q2220 PHY Dimitri Fedrau
@ 2024-02-13 21:39 ` Dimitri Fedrau
  2024-02-13 21:39 ` [PATCH v6 net-next 02/14] net: phy: Support 100/1000BT1 linkmode advertisements Dimitri Fedrau
                   ` (12 subsequent siblings)
  13 siblings, 0 replies; 28+ messages in thread
From: Dimitri Fedrau @ 2024-02-13 21:39 UTC (permalink / raw)
  Cc: Dimitri Fedrau, Andrew Lunn, Heiner Kallweit, Russell King,
	David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Stefan Eichenberger, netdev, linux-kernel

Added constants for advertising 100BT1 and 1000BT1 in register BASE-T1
auto-negotiation advertisement register [31:16] (Register 7.515)

Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Signed-off-by: Dimitri Fedrau <dima.fedrau@gmail.com>
---
 include/uapi/linux/mdio.h | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/include/uapi/linux/mdio.h b/include/uapi/linux/mdio.h
index d03863da180e..020ccc810d23 100644
--- a/include/uapi/linux/mdio.h
+++ b/include/uapi/linux/mdio.h
@@ -348,6 +348,8 @@
 
 /* BASE-T1 auto-negotiation advertisement register [31:16] */
 #define MDIO_AN_T1_ADV_M_B10L		0x4000	/* device is compatible with 10BASE-T1L */
+#define MDIO_AN_T1_ADV_M_1000BT1	0x0080	/* advertise 1000BASE-T1 */
+#define MDIO_AN_T1_ADV_M_100BT1		0x0020	/* advertise 100BASE-T1 */
 #define MDIO_AN_T1_ADV_M_MST		0x0010	/* advertise master preference */
 
 /* BASE-T1 auto-negotiation advertisement register [47:32] */
-- 
2.39.2


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

* [PATCH v6 net-next 02/14] net: phy: Support 100/1000BT1 linkmode advertisements
  2024-02-13 21:39 [PATCH v6 net-next 00/14] net: phy: marvell-88q2xxx: add driver for the Marvell 88Q2220 PHY Dimitri Fedrau
  2024-02-13 21:39 ` [PATCH v6 net-next 01/14] net: phy: Add BaseT1 auto-negotiation constants Dimitri Fedrau
@ 2024-02-13 21:39 ` Dimitri Fedrau
  2024-02-13 21:39 ` [PATCH v6 net-next 03/14] net: phy: c45: detect 100/1000BASE-T1 " Dimitri Fedrau
                   ` (11 subsequent siblings)
  13 siblings, 0 replies; 28+ messages in thread
From: Dimitri Fedrau @ 2024-02-13 21:39 UTC (permalink / raw)
  Cc: Dimitri Fedrau, Andrew Lunn, Heiner Kallweit, Russell King,
	David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Stefan Eichenberger, netdev, linux-kernel

Extend helper functions mii_t1_adv_m_mod_linkmode_t and
linkmode_adv_to_mii_t1_adv_m_t to support 100BT1 and 1000BT1 linkmode
advertisements.

Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Signed-off-by: Dimitri Fedrau <dima.fedrau@gmail.com>
---
 include/linux/mdio.h | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/include/linux/mdio.h b/include/linux/mdio.h
index 79ceee3c8673..ecd21acc7eed 100644
--- a/include/linux/mdio.h
+++ b/include/linux/mdio.h
@@ -373,6 +373,10 @@ static inline void mii_t1_adv_m_mod_linkmode_t(unsigned long *advertising, u32 l
 {
 	linkmode_mod_bit(ETHTOOL_LINK_MODE_10baseT1L_Full_BIT,
 			 advertising, lpa & MDIO_AN_T1_ADV_M_B10L);
+	linkmode_mod_bit(ETHTOOL_LINK_MODE_100baseT1_Full_BIT,
+			 advertising, lpa & MDIO_AN_T1_ADV_M_100BT1);
+	linkmode_mod_bit(ETHTOOL_LINK_MODE_1000baseT1_Full_BIT,
+			 advertising, lpa & MDIO_AN_T1_ADV_M_1000BT1);
 }
 
 /**
@@ -409,6 +413,10 @@ static inline u32 linkmode_adv_to_mii_t1_adv_m_t(unsigned long *advertising)
 
 	if (linkmode_test_bit(ETHTOOL_LINK_MODE_10baseT1L_Full_BIT, advertising))
 		result |= MDIO_AN_T1_ADV_M_B10L;
+	if (linkmode_test_bit(ETHTOOL_LINK_MODE_100baseT1_Full_BIT, advertising))
+		result |= MDIO_AN_T1_ADV_M_100BT1;
+	if (linkmode_test_bit(ETHTOOL_LINK_MODE_1000baseT1_Full_BIT, advertising))
+		result |= MDIO_AN_T1_ADV_M_1000BT1;
 
 	return result;
 }
-- 
2.39.2


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

* [PATCH v6 net-next 03/14] net: phy: c45: detect 100/1000BASE-T1 linkmode advertisements
  2024-02-13 21:39 [PATCH v6 net-next 00/14] net: phy: marvell-88q2xxx: add driver for the Marvell 88Q2220 PHY Dimitri Fedrau
  2024-02-13 21:39 ` [PATCH v6 net-next 01/14] net: phy: Add BaseT1 auto-negotiation constants Dimitri Fedrau
  2024-02-13 21:39 ` [PATCH v6 net-next 02/14] net: phy: Support 100/1000BT1 linkmode advertisements Dimitri Fedrau
@ 2024-02-13 21:39 ` Dimitri Fedrau
  2024-02-13 21:39 ` [PATCH v6 net-next 04/14] net: phy: marvell-88q2xxx: fix typos Dimitri Fedrau
                   ` (10 subsequent siblings)
  13 siblings, 0 replies; 28+ messages in thread
From: Dimitri Fedrau @ 2024-02-13 21:39 UTC (permalink / raw)
  Cc: Dimitri Fedrau, Andrew Lunn, Heiner Kallweit, Russell King,
	David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Stefan Eichenberger, netdev, linux-kernel

Set 100BT1 and 1000BT1 linkmode advertisement bits to adv_l_mask to
enable detection.

Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Signed-off-by: Dimitri Fedrau <dima.fedrau@gmail.com>
---
 drivers/net/phy/phy-c45.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/net/phy/phy-c45.c b/drivers/net/phy/phy-c45.c
index 747d14bf152c..de8f5dc8be12 100644
--- a/drivers/net/phy/phy-c45.c
+++ b/drivers/net/phy/phy-c45.c
@@ -208,7 +208,8 @@ static int genphy_c45_baset1_an_config_aneg(struct phy_device *phydev)
 
 	adv_l_mask = MDIO_AN_T1_ADV_L_FORCE_MS | MDIO_AN_T1_ADV_L_PAUSE_CAP |
 		MDIO_AN_T1_ADV_L_PAUSE_ASYM;
-	adv_m_mask = MDIO_AN_T1_ADV_M_MST | MDIO_AN_T1_ADV_M_B10L;
+	adv_m_mask = MDIO_AN_T1_ADV_M_1000BT1 | MDIO_AN_T1_ADV_M_100BT1 |
+		MDIO_AN_T1_ADV_M_MST | MDIO_AN_T1_ADV_M_B10L;
 
 	switch (phydev->master_slave_set) {
 	case MASTER_SLAVE_CFG_MASTER_FORCE:
-- 
2.39.2


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

* [PATCH v6 net-next 04/14] net: phy: marvell-88q2xxx: fix typos
  2024-02-13 21:39 [PATCH v6 net-next 00/14] net: phy: marvell-88q2xxx: add driver for the Marvell 88Q2220 PHY Dimitri Fedrau
                   ` (2 preceding siblings ...)
  2024-02-13 21:39 ` [PATCH v6 net-next 03/14] net: phy: c45: detect 100/1000BASE-T1 " Dimitri Fedrau
@ 2024-02-13 21:39 ` Dimitri Fedrau
  2024-02-13 21:39 ` [PATCH v6 net-next 05/14] net: phy: marvell-88q2xxx: add driver for the Marvell 88Q2220 PHY Dimitri Fedrau
                   ` (9 subsequent siblings)
  13 siblings, 0 replies; 28+ messages in thread
From: Dimitri Fedrau @ 2024-02-13 21:39 UTC (permalink / raw)
  Cc: Dimitri Fedrau, Andrew Lunn, Heiner Kallweit, Russell King,
	David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Stefan Eichenberger, netdev, linux-kernel

Rename mv88q2xxxx_get_sqi to mv88q2xxx_get_sqi and
mv88q2xxxx_get_sqi_max to mv88q2xxx_get_sqi_max.
Fix linebreaks and use everywhere hexadecimal numbers written with
lowercase letters instead of mixing it up.

Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Signed-off-by: Dimitri Fedrau <dima.fedrau@gmail.com>
---
 drivers/net/phy/marvell-88q2xxx.c | 28 +++++++++++++++++-----------
 1 file changed, 17 insertions(+), 11 deletions(-)

diff --git a/drivers/net/phy/marvell-88q2xxx.c b/drivers/net/phy/marvell-88q2xxx.c
index 1c3ff77de56b..dcebb4643aff 100644
--- a/drivers/net/phy/marvell-88q2xxx.c
+++ b/drivers/net/phy/marvell-88q2xxx.c
@@ -14,7 +14,7 @@
 #define MDIO_MMD_AN_MV_STAT_MS_CONF_FAULT	0x8000
 
 #define MDIO_MMD_PCS_MV_100BT1_STAT1			33032
-#define MDIO_MMD_PCS_MV_100BT1_STAT1_IDLE_ERROR	0x00FF
+#define MDIO_MMD_PCS_MV_100BT1_STAT1_IDLE_ERROR		0x00ff
 #define MDIO_MMD_PCS_MV_100BT1_STAT1_JABBER		0x0100
 #define MDIO_MMD_PCS_MV_100BT1_STAT1_LINK		0x0200
 #define MDIO_MMD_PCS_MV_100BT1_STAT1_LOCAL_RX		0x1000
@@ -27,6 +27,8 @@
 #define MDIO_MMD_PCS_MV_100BT1_STAT2_LINK	0x0004
 #define MDIO_MMD_PCS_MV_100BT1_STAT2_ANGE	0x0008
 
+#define MDIO_MMD_PCS_MV_RX_STAT			33328
+
 static int mv88q2xxx_soft_reset(struct phy_device *phydev)
 {
 	int ret;
@@ -63,7 +65,8 @@ static int mv88q2xxx_read_link_gbit(struct phy_device *phydev)
 		 * the link was already down.
 		 */
 		if (!phy_polling_mode(phydev) || !phydev->link) {
-			ret = phy_read_mmd(phydev, MDIO_MMD_PCS, MDIO_PCS_1000BT1_STAT);
+			ret = phy_read_mmd(phydev, MDIO_MMD_PCS,
+					   MDIO_PCS_1000BT1_STAT);
 			if (ret < 0)
 				return ret;
 			else if (ret & MDIO_PCS_1000BT1_STAT_LINK)
@@ -71,7 +74,8 @@ static int mv88q2xxx_read_link_gbit(struct phy_device *phydev)
 		}
 
 		if (!link) {
-			ret = phy_read_mmd(phydev, MDIO_MMD_PCS, MDIO_PCS_1000BT1_STAT);
+			ret = phy_read_mmd(phydev, MDIO_MMD_PCS,
+					   MDIO_PCS_1000BT1_STAT);
 			if (ret < 0)
 				return ret;
 			else if (ret & MDIO_PCS_1000BT1_STAT_LINK)
@@ -95,7 +99,8 @@ static int mv88q2xxx_read_link_100m(struct phy_device *phydev)
 	 * we always read the realtime status.
 	 */
 	if (!phy_polling_mode(phydev) || !phydev->link) {
-		ret = phy_read_mmd(phydev, MDIO_MMD_PCS, MDIO_MMD_PCS_MV_100BT1_STAT1);
+		ret = phy_read_mmd(phydev, MDIO_MMD_PCS,
+				   MDIO_MMD_PCS_MV_100BT1_STAT1);
 		if (ret < 0)
 			return ret;
 		else if (ret & MDIO_MMD_PCS_MV_100BT1_STAT1_LINK)
@@ -200,7 +205,7 @@ static int mv88q2xxx_config_init(struct phy_device *phydev)
 	return mv88q2xxx_config_aneg(phydev);
 }
 
-static int mv88q2xxxx_get_sqi(struct phy_device *phydev)
+static int mv88q2xxx_get_sqi(struct phy_device *phydev)
 {
 	int ret;
 
@@ -208,7 +213,8 @@ static int mv88q2xxxx_get_sqi(struct phy_device *phydev)
 		/* Read the SQI from the vendor specific receiver status
 		 * register
 		 */
-		ret = phy_read_mmd(phydev, MDIO_MMD_PCS, 0x8230);
+		ret = phy_read_mmd(phydev, MDIO_MMD_PCS,
+				   MDIO_MMD_PCS_MV_RX_STAT);
 		if (ret < 0)
 			return ret;
 
@@ -218,7 +224,7 @@ static int mv88q2xxxx_get_sqi(struct phy_device *phydev)
 		 * but can be found in the Software Initialization Guide. Only
 		 * revisions >= A0 are supported.
 		 */
-		ret = phy_modify_mmd(phydev, MDIO_MMD_PCS, 0xFC5D, 0x00FF, 0x00AC);
+		ret = phy_modify_mmd(phydev, MDIO_MMD_PCS, 0xfc5d, 0xff, 0xac);
 		if (ret < 0)
 			return ret;
 
@@ -227,10 +233,10 @@ static int mv88q2xxxx_get_sqi(struct phy_device *phydev)
 			return ret;
 	}
 
-	return ret & 0x0F;
+	return ret & 0x0f;
 }
 
-static int mv88q2xxxx_get_sqi_max(struct phy_device *phydev)
+static int mv88q2xxx_get_sqi_max(struct phy_device *phydev)
 {
 	return 15;
 }
@@ -246,8 +252,8 @@ static struct phy_driver mv88q2xxx_driver[] = {
 		.read_status		= mv88q2xxx_read_status,
 		.soft_reset		= mv88q2xxx_soft_reset,
 		.set_loopback		= genphy_c45_loopback,
-		.get_sqi		= mv88q2xxxx_get_sqi,
-		.get_sqi_max		= mv88q2xxxx_get_sqi_max,
+		.get_sqi		= mv88q2xxx_get_sqi,
+		.get_sqi_max		= mv88q2xxx_get_sqi_max,
 	},
 };
 
-- 
2.39.2


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

* [PATCH v6 net-next 05/14] net: phy: marvell-88q2xxx: add driver for the Marvell 88Q2220 PHY
  2024-02-13 21:39 [PATCH v6 net-next 00/14] net: phy: marvell-88q2xxx: add driver for the Marvell 88Q2220 PHY Dimitri Fedrau
                   ` (3 preceding siblings ...)
  2024-02-13 21:39 ` [PATCH v6 net-next 04/14] net: phy: marvell-88q2xxx: fix typos Dimitri Fedrau
@ 2024-02-13 21:39 ` Dimitri Fedrau
  2024-02-14 13:20   ` Gregor Herburger
  2024-02-13 21:39 ` [PATCH v6 net-next 06/14] net: phy: marvell-88q2xxx: add interrupt support for link detection Dimitri Fedrau
                   ` (8 subsequent siblings)
  13 siblings, 1 reply; 28+ messages in thread
From: Dimitri Fedrau @ 2024-02-13 21:39 UTC (permalink / raw)
  Cc: Dimitri Fedrau, Andrew Lunn, Heiner Kallweit, Russell King,
	David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Stefan Eichenberger, netdev, linux-kernel

Add a driver for the Marvell 88Q2220. This driver allows to detect the
link, switch between 100BASE-T1 and 1000BASE-T1 and switch between
master and slave mode. Autonegotiation is supported.

Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Signed-off-by: Dimitri Fedrau <dima.fedrau@gmail.com>
---
 drivers/net/phy/marvell-88q2xxx.c | 210 +++++++++++++++++++++++++++++-
 include/linux/marvell_phy.h       |   1 +
 2 files changed, 205 insertions(+), 6 deletions(-)

diff --git a/drivers/net/phy/marvell-88q2xxx.c b/drivers/net/phy/marvell-88q2xxx.c
index dcebb4643aff..9829facde253 100644
--- a/drivers/net/phy/marvell-88q2xxx.c
+++ b/drivers/net/phy/marvell-88q2xxx.c
@@ -1,11 +1,17 @@
 // SPDX-License-Identifier: GPL-2.0
 /*
  * Marvell 88Q2XXX automotive 100BASE-T1/1000BASE-T1 PHY driver
+ *
+ * Derived from Marvell Q222x API
+ *
+ * Copyright (C) 2024 Liebherr-Electronics and Drives GmbH
  */
 #include <linux/ethtool_netlink.h>
 #include <linux/marvell_phy.h>
 #include <linux/phy.h>
 
+#define PHY_ID_88Q2220_REVB0	(MARVELL_PHY_ID_88Q2220 | 0x1)
+
 #define MDIO_MMD_AN_MV_STAT			32769
 #define MDIO_MMD_AN_MV_STAT_ANEG		0x0100
 #define MDIO_MMD_AN_MV_STAT_LOCAL_RX		0x1000
@@ -13,6 +19,11 @@
 #define MDIO_MMD_AN_MV_STAT_LOCAL_MASTER	0x4000
 #define MDIO_MMD_AN_MV_STAT_MS_CONF_FAULT	0x8000
 
+#define MDIO_MMD_AN_MV_STAT2			32794
+#define MDIO_MMD_AN_MV_STAT2_AN_RESOLVED	0x0800
+#define MDIO_MMD_AN_MV_STAT2_100BT1		0x2000
+#define MDIO_MMD_AN_MV_STAT2_1000BT1		0x4000
+
 #define MDIO_MMD_PCS_MV_100BT1_STAT1			33032
 #define MDIO_MMD_PCS_MV_100BT1_STAT1_IDLE_ERROR		0x00ff
 #define MDIO_MMD_PCS_MV_100BT1_STAT1_JABBER		0x0100
@@ -29,6 +40,42 @@
 
 #define MDIO_MMD_PCS_MV_RX_STAT			33328
 
+struct mmd_val {
+	int devad;
+	u32 regnum;
+	u16 val;
+};
+
+static const struct mmd_val mv88q222x_revb0_init_seq0[] = {
+	{ MDIO_MMD_PCS, 0x8033, 0x6801 },
+	{ MDIO_MMD_AN, MDIO_AN_T1_CTRL, 0x0 },
+	{ MDIO_MMD_PMAPMD, MDIO_CTRL1,
+	  MDIO_CTRL1_LPOWER | MDIO_PMA_CTRL1_SPEED1000 },
+	{ MDIO_MMD_PCS, 0xfe1b, 0x48 },
+	{ MDIO_MMD_PCS, 0xffe4, 0x6b6 },
+	{ MDIO_MMD_PMAPMD, MDIO_CTRL1, 0x0 },
+	{ MDIO_MMD_PCS, MDIO_CTRL1, 0x0 },
+};
+
+static const struct mmd_val mv88q222x_revb0_init_seq1[] = {
+	{ MDIO_MMD_PCS, 0xfe79, 0x0 },
+	{ MDIO_MMD_PCS, 0xfe07, 0x125a },
+	{ MDIO_MMD_PCS, 0xfe09, 0x1288 },
+	{ MDIO_MMD_PCS, 0xfe08, 0x2588 },
+	{ MDIO_MMD_PCS, 0xfe11, 0x1105 },
+	{ MDIO_MMD_PCS, 0xfe72, 0x042c },
+	{ MDIO_MMD_PCS, 0xfbba, 0xcb2 },
+	{ MDIO_MMD_PCS, 0xfbbb, 0xc4a },
+	{ MDIO_MMD_AN, 0x8032, 0x2020 },
+	{ MDIO_MMD_AN, 0x8031, 0xa28 },
+	{ MDIO_MMD_AN, 0x8031, 0xc28 },
+	{ MDIO_MMD_PCS, 0xffdb, 0xfc10 },
+	{ MDIO_MMD_PCS, 0xfe1b, 0x58 },
+	{ MDIO_MMD_PCS, 0xfe79, 0x4 },
+	{ MDIO_MMD_PCS, 0xfe5f, 0xe8 },
+	{ MDIO_MMD_PCS, 0xfe05, 0x755c },
+};
+
 static int mv88q2xxx_soft_reset(struct phy_device *phydev)
 {
 	int ret;
@@ -125,24 +172,90 @@ static int mv88q2xxx_read_link_100m(struct phy_device *phydev)
 
 static int mv88q2xxx_read_link(struct phy_device *phydev)
 {
-	int ret;
-
 	/* The 88Q2XXX PHYs do not have the PMA/PMD status register available,
 	 * therefore we need to read the link status from the vendor specific
 	 * registers depending on the speed.
 	 */
+
 	if (phydev->speed == SPEED_1000)
-		ret = mv88q2xxx_read_link_gbit(phydev);
+		return mv88q2xxx_read_link_gbit(phydev);
+	else if (phydev->speed == SPEED_100)
+		return mv88q2xxx_read_link_100m(phydev);
+
+	phydev->link = false;
+	return 0;
+}
+
+static int mv88q2xxx_read_master_slave_state(struct phy_device *phydev)
+{
+	int ret;
+
+	phydev->master_slave_state = MASTER_SLAVE_STATE_UNKNOWN;
+	ret = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_MMD_AN_MV_STAT);
+	if (ret < 0)
+		return ret;
+
+	if (ret & MDIO_MMD_AN_MV_STAT_LOCAL_MASTER)
+		phydev->master_slave_state = MASTER_SLAVE_STATE_MASTER;
 	else
-		ret = mv88q2xxx_read_link_100m(phydev);
+		phydev->master_slave_state = MASTER_SLAVE_STATE_SLAVE;
 
-	return ret;
+	return 0;
+}
+
+static int mv88q2xxx_read_aneg_speed(struct phy_device *phydev)
+{
+	int ret;
+
+	phydev->speed = SPEED_UNKNOWN;
+	ret = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_MMD_AN_MV_STAT2);
+	if (ret < 0)
+		return ret;
+
+	if (!(ret & MDIO_MMD_AN_MV_STAT2_AN_RESOLVED))
+		return 0;
+
+	if (ret & MDIO_MMD_AN_MV_STAT2_100BT1)
+		phydev->speed = SPEED_100;
+	else if (ret & MDIO_MMD_AN_MV_STAT2_1000BT1)
+		phydev->speed = SPEED_1000;
+
+	return 0;
 }
 
 static int mv88q2xxx_read_status(struct phy_device *phydev)
 {
 	int ret;
 
+	if (phydev->autoneg == AUTONEG_ENABLE) {
+		/* We have to get the negotiated speed first, otherwise we are
+		 * not able to read the link.
+		 */
+		ret = mv88q2xxx_read_aneg_speed(phydev);
+		if (ret < 0)
+			return ret;
+
+		ret = mv88q2xxx_read_link(phydev);
+		if (ret < 0)
+			return ret;
+
+		ret = genphy_c45_read_lpa(phydev);
+		if (ret < 0)
+			return ret;
+
+		ret = genphy_c45_baset1_read_status(phydev);
+		if (ret < 0)
+			return ret;
+
+		ret = mv88q2xxx_read_master_slave_state(phydev);
+		if (ret < 0)
+			return ret;
+
+		phy_resolve_aneg_linkmode(phydev);
+
+		return 0;
+	}
+
 	ret = mv88q2xxx_read_link(phydev);
 	if (ret < 0)
 		return ret;
@@ -171,7 +284,9 @@ static int mv88q2xxx_get_features(struct phy_device *phydev)
 	 * sequence provided by Marvell. Disable it for now until a proper
 	 * workaround is found or a new PHY revision is released.
 	 */
-	linkmode_clear_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, phydev->supported);
+	if (phydev->drv->phy_id == MARVELL_PHY_ID_88Q2110)
+		linkmode_clear_bit(ETHTOOL_LINK_MODE_Autoneg_BIT,
+				   phydev->supported);
 
 	return 0;
 }
@@ -241,6 +356,75 @@ static int mv88q2xxx_get_sqi_max(struct phy_device *phydev)
 	return 15;
 }
 
+static int mv88q222x_soft_reset(struct phy_device *phydev)
+{
+	int ret;
+
+	/* Enable RESET of DCL */
+	if (phydev->autoneg == AUTONEG_ENABLE || phydev->speed == SPEED_1000) {
+		ret = phy_write_mmd(phydev, MDIO_MMD_PCS, 0xfe1b, 0x48);
+		if (ret < 0)
+			return ret;
+	}
+
+	ret = phy_write_mmd(phydev, MDIO_MMD_PCS, MDIO_PCS_1000BT1_CTRL,
+			    MDIO_PCS_1000BT1_CTRL_RESET);
+	if (ret < 0)
+		return ret;
+
+	ret = phy_write_mmd(phydev, MDIO_MMD_PCS, 0xffe4, 0xc);
+	if (ret < 0)
+		return ret;
+
+	/* Disable RESET of DCL */
+	if (phydev->autoneg == AUTONEG_ENABLE || phydev->speed == SPEED_1000)
+		return phy_write_mmd(phydev, MDIO_MMD_PCS, 0xfe1b, 0x58);
+
+	return 0;
+}
+
+static int mv88q222x_config_aneg(struct phy_device *phydev)
+{
+	int ret;
+
+	ret = genphy_c45_config_aneg(phydev);
+	if (ret)
+		return ret;
+
+	return mv88q222x_soft_reset(phydev);
+}
+
+static int mv88q222x_revb0_config_init(struct phy_device *phydev)
+{
+	int ret, i;
+
+	for (i = 0; i < ARRAY_SIZE(mv88q222x_revb0_init_seq0); i++) {
+		ret = phy_write_mmd(phydev, mv88q222x_revb0_init_seq0[i].devad,
+				    mv88q222x_revb0_init_seq0[i].regnum,
+				    mv88q222x_revb0_init_seq0[i].val);
+		if (ret < 0)
+			return ret;
+	}
+
+	usleep_range(5000, 10000);
+
+	for (i = 0; i < ARRAY_SIZE(mv88q222x_revb0_init_seq1); i++) {
+		ret = phy_write_mmd(phydev, mv88q222x_revb0_init_seq1[i].devad,
+				    mv88q222x_revb0_init_seq1[i].regnum,
+				    mv88q222x_revb0_init_seq1[i].val);
+		if (ret < 0)
+			return ret;
+	}
+
+	/* The 88Q2XXX PHYs do have the extended ability register available, but
+	 * register MDIO_PMA_EXTABLE where they should signalize it does not
+	 * work according to specification. Therefore, we force it here.
+	 */
+	phydev->pma_extable = MDIO_PMA_EXTABLE_BT1;
+
+	return 0;
+}
+
 static struct phy_driver mv88q2xxx_driver[] = {
 	{
 		.phy_id			= MARVELL_PHY_ID_88Q2110,
@@ -255,12 +439,26 @@ static struct phy_driver mv88q2xxx_driver[] = {
 		.get_sqi		= mv88q2xxx_get_sqi,
 		.get_sqi_max		= mv88q2xxx_get_sqi_max,
 	},
+	{
+		PHY_ID_MATCH_EXACT(PHY_ID_88Q2220_REVB0),
+		.name			= "mv88q2220",
+		.get_features		= mv88q2xxx_get_features,
+		.config_aneg		= mv88q222x_config_aneg,
+		.aneg_done		= genphy_c45_aneg_done,
+		.config_init		= mv88q222x_revb0_config_init,
+		.read_status		= mv88q2xxx_read_status,
+		.soft_reset		= mv88q222x_soft_reset,
+		.set_loopback		= genphy_c45_loopback,
+		.get_sqi		= mv88q2xxx_get_sqi,
+		.get_sqi_max		= mv88q2xxx_get_sqi_max,
+	},
 };
 
 module_phy_driver(mv88q2xxx_driver);
 
 static struct mdio_device_id __maybe_unused mv88q2xxx_tbl[] = {
 	{ MARVELL_PHY_ID_88Q2110, MARVELL_PHY_ID_MASK },
+	{ PHY_ID_MATCH_EXACT(PHY_ID_88Q2220_REVB0), },
 	{ /*sentinel*/ }
 };
 MODULE_DEVICE_TABLE(mdio, mv88q2xxx_tbl);
diff --git a/include/linux/marvell_phy.h b/include/linux/marvell_phy.h
index 9b54c4f0677f..693eba9869e4 100644
--- a/include/linux/marvell_phy.h
+++ b/include/linux/marvell_phy.h
@@ -26,6 +26,7 @@
 #define MARVELL_PHY_ID_88E2110		0x002b09b0
 #define MARVELL_PHY_ID_88X2222		0x01410f10
 #define MARVELL_PHY_ID_88Q2110		0x002b0980
+#define MARVELL_PHY_ID_88Q2220		0x002b0b20
 
 /* Marvel 88E1111 in Finisar SFP module with modified PHY ID */
 #define MARVELL_PHY_ID_88E1111_FINISAR	0x01ff0cc0
-- 
2.39.2


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

* [PATCH v6 net-next 06/14] net: phy: marvell-88q2xxx: add interrupt support for link detection
  2024-02-13 21:39 [PATCH v6 net-next 00/14] net: phy: marvell-88q2xxx: add driver for the Marvell 88Q2220 PHY Dimitri Fedrau
                   ` (4 preceding siblings ...)
  2024-02-13 21:39 ` [PATCH v6 net-next 05/14] net: phy: marvell-88q2xxx: add driver for the Marvell 88Q2220 PHY Dimitri Fedrau
@ 2024-02-13 21:39 ` Dimitri Fedrau
  2024-02-13 21:39 ` [PATCH v6 net-next 07/14] net: phy: marvell-88q2xxx: add suspend / resume ops Dimitri Fedrau
                   ` (7 subsequent siblings)
  13 siblings, 0 replies; 28+ messages in thread
From: Dimitri Fedrau @ 2024-02-13 21:39 UTC (permalink / raw)
  Cc: Dimitri Fedrau, Andrew Lunn, Heiner Kallweit, Russell King,
	David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Stefan Eichenberger, netdev, linux-kernel

Added .config_intr and .handle_interrupt callbacks. Whenever the link
goes up or down an interrupt will be triggered. Interrupts are configured
separately for 100/1000BASET1.

Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Signed-off-by: Dimitri Fedrau <dima.fedrau@gmail.com>
---
 drivers/net/phy/marvell-88q2xxx.c | 123 +++++++++++++++++++++++++++++-
 1 file changed, 119 insertions(+), 4 deletions(-)

diff --git a/drivers/net/phy/marvell-88q2xxx.c b/drivers/net/phy/marvell-88q2xxx.c
index 9829facde253..7c7517af346b 100644
--- a/drivers/net/phy/marvell-88q2xxx.c
+++ b/drivers/net/phy/marvell-88q2xxx.c
@@ -24,6 +24,19 @@
 #define MDIO_MMD_AN_MV_STAT2_100BT1		0x2000
 #define MDIO_MMD_AN_MV_STAT2_1000BT1		0x4000
 
+#define MDIO_MMD_PCS_MV_INT_EN			32784
+#define MDIO_MMD_PCS_MV_INT_EN_LINK_UP		0x0040
+#define MDIO_MMD_PCS_MV_INT_EN_LINK_DOWN	0x0080
+#define MDIO_MMD_PCS_MV_INT_EN_100BT1		0x1000
+
+#define MDIO_MMD_PCS_MV_GPIO_INT_STAT			32785
+#define MDIO_MMD_PCS_MV_GPIO_INT_STAT_LINK_UP		0x0040
+#define MDIO_MMD_PCS_MV_GPIO_INT_STAT_LINK_DOWN		0x0080
+#define MDIO_MMD_PCS_MV_GPIO_INT_STAT_100BT1_GEN	0x1000
+
+#define MDIO_MMD_PCS_MV_GPIO_INT_CTRL			32787
+#define MDIO_MMD_PCS_MV_GPIO_INT_CTRL_TRI_DIS		0x0800
+
 #define MDIO_MMD_PCS_MV_100BT1_STAT1			33032
 #define MDIO_MMD_PCS_MV_100BT1_STAT1_IDLE_ERROR		0x00ff
 #define MDIO_MMD_PCS_MV_100BT1_STAT1_JABBER		0x0100
@@ -38,6 +51,12 @@
 #define MDIO_MMD_PCS_MV_100BT1_STAT2_LINK	0x0004
 #define MDIO_MMD_PCS_MV_100BT1_STAT2_ANGE	0x0008
 
+#define MDIO_MMD_PCS_MV_100BT1_INT_EN			33042
+#define MDIO_MMD_PCS_MV_100BT1_INT_EN_LINKEVENT		0x0400
+
+#define MDIO_MMD_PCS_MV_COPPER_INT_STAT			33043
+#define MDIO_MMD_PCS_MV_COPPER_INT_STAT_LINKEVENT	0x0400
+
 #define MDIO_MMD_PCS_MV_RX_STAT			33328
 
 struct mmd_val {
@@ -99,13 +118,15 @@ static int mv88q2xxx_read_link_gbit(struct phy_device *phydev)
 
 	/* Read vendor specific Auto-Negotiation status register to get local
 	 * and remote receiver status according to software initialization
-	 * guide.
+	 * guide. However, when not in polling mode the local and remote
+	 * receiver status are not evaluated due to the Marvell 88Q2xxx APIs.
 	 */
 	ret = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_MMD_AN_MV_STAT);
 	if (ret < 0) {
 		return ret;
-	} else if ((ret & MDIO_MMD_AN_MV_STAT_LOCAL_RX) &&
-		   (ret & MDIO_MMD_AN_MV_STAT_REMOTE_RX)) {
+	} else if (((ret & MDIO_MMD_AN_MV_STAT_LOCAL_RX) &&
+		   (ret & MDIO_MMD_AN_MV_STAT_REMOTE_RX)) ||
+		   !phy_polling_mode(phydev)) {
 		/* The link state is latched low so that momentary link
 		 * drops can be detected. Do not double-read the status
 		 * in polling mode to detect such short link drops except
@@ -145,7 +166,18 @@ static int mv88q2xxx_read_link_100m(struct phy_device *phydev)
 	 * the link was already down. In case we are not polling,
 	 * we always read the realtime status.
 	 */
-	if (!phy_polling_mode(phydev) || !phydev->link) {
+	if (!phy_polling_mode(phydev)) {
+		phydev->link = false;
+		ret = phy_read_mmd(phydev, MDIO_MMD_PCS,
+				   MDIO_MMD_PCS_MV_100BT1_STAT2);
+		if (ret < 0)
+			return ret;
+
+		if (ret & MDIO_MMD_PCS_MV_100BT1_STAT2_LINK)
+			phydev->link = true;
+
+		return 0;
+	} else if (!phydev->link) {
 		ret = phy_read_mmd(phydev, MDIO_MMD_PCS,
 				   MDIO_MMD_PCS_MV_100BT1_STAT1);
 		if (ret < 0)
@@ -356,6 +388,79 @@ static int mv88q2xxx_get_sqi_max(struct phy_device *phydev)
 	return 15;
 }
 
+static int mv88q2xxx_config_intr(struct phy_device *phydev)
+{
+	int ret;
+
+	if (phydev->interrupts == PHY_INTERRUPT_ENABLED) {
+		/* Enable interrupts for 1000BASE-T1 link up and down events
+		 * and enable general interrupts for 100BASE-T1.
+		 */
+		ret = phy_write_mmd(phydev, MDIO_MMD_PCS,
+				    MDIO_MMD_PCS_MV_INT_EN,
+				    MDIO_MMD_PCS_MV_INT_EN_LINK_UP |
+				    MDIO_MMD_PCS_MV_INT_EN_LINK_DOWN |
+				    MDIO_MMD_PCS_MV_INT_EN_100BT1);
+		if (ret < 0)
+			return ret;
+
+		/* Enable interrupts for 100BASE-T1 link events */
+		return phy_write_mmd(phydev, MDIO_MMD_PCS,
+				     MDIO_MMD_PCS_MV_100BT1_INT_EN,
+				     MDIO_MMD_PCS_MV_100BT1_INT_EN_LINKEVENT);
+	} else {
+		ret = phy_write_mmd(phydev, MDIO_MMD_PCS,
+				    MDIO_MMD_PCS_MV_INT_EN, 0);
+		if (ret < 0)
+			return ret;
+
+		return phy_write_mmd(phydev, MDIO_MMD_PCS,
+				     MDIO_MMD_PCS_MV_100BT1_INT_EN, 0);
+	}
+}
+
+static irqreturn_t mv88q2xxx_handle_interrupt(struct phy_device *phydev)
+{
+	bool trigger_machine = false;
+	int irq;
+
+	/* Before we can acknowledge the 100BT1 general interrupt, that is in
+	 * the 1000BT1 interrupt status register, we have to acknowledge any
+	 * interrupts that are related to it. Therefore we read first the 100BT1
+	 * interrupt status register, followed by reading the 1000BT1 interrupt
+	 * status register.
+	 */
+
+	irq = phy_read_mmd(phydev, MDIO_MMD_PCS,
+			   MDIO_MMD_PCS_MV_COPPER_INT_STAT);
+	if (irq < 0) {
+		phy_error(phydev);
+		return IRQ_NONE;
+	}
+
+	/* Check link status for 100BT1 */
+	if (irq & MDIO_MMD_PCS_MV_COPPER_INT_STAT_LINKEVENT)
+		trigger_machine = true;
+
+	irq = phy_read_mmd(phydev, MDIO_MMD_PCS, MDIO_MMD_PCS_MV_GPIO_INT_STAT);
+	if (irq < 0) {
+		phy_error(phydev);
+		return IRQ_NONE;
+	}
+
+	/* Check link status for 1000BT1 */
+	if ((irq & MDIO_MMD_PCS_MV_GPIO_INT_STAT_LINK_UP) ||
+	    (irq & MDIO_MMD_PCS_MV_GPIO_INT_STAT_LINK_DOWN))
+		trigger_machine = true;
+
+	if (!trigger_machine)
+		return IRQ_NONE;
+
+	phy_trigger_machine(phydev);
+
+	return IRQ_HANDLED;
+}
+
 static int mv88q222x_soft_reset(struct phy_device *phydev)
 {
 	int ret;
@@ -422,6 +527,14 @@ static int mv88q222x_revb0_config_init(struct phy_device *phydev)
 	 */
 	phydev->pma_extable = MDIO_PMA_EXTABLE_BT1;
 
+	/* Configure interrupt with default settings, output is driven low for
+	 * active interrupt and high for inactive.
+	 */
+	if (phy_interrupt_is_valid(phydev))
+		return phy_set_bits_mmd(phydev, MDIO_MMD_PCS,
+					MDIO_MMD_PCS_MV_GPIO_INT_CTRL,
+					MDIO_MMD_PCS_MV_GPIO_INT_CTRL_TRI_DIS);
+
 	return 0;
 }
 
@@ -448,6 +561,8 @@ static struct phy_driver mv88q2xxx_driver[] = {
 		.config_init		= mv88q222x_revb0_config_init,
 		.read_status		= mv88q2xxx_read_status,
 		.soft_reset		= mv88q222x_soft_reset,
+		.config_intr		= mv88q2xxx_config_intr,
+		.handle_interrupt	= mv88q2xxx_handle_interrupt,
 		.set_loopback		= genphy_c45_loopback,
 		.get_sqi		= mv88q2xxx_get_sqi,
 		.get_sqi_max		= mv88q2xxx_get_sqi_max,
-- 
2.39.2


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

* [PATCH v6 net-next 07/14] net: phy: marvell-88q2xxx: add suspend / resume ops
  2024-02-13 21:39 [PATCH v6 net-next 00/14] net: phy: marvell-88q2xxx: add driver for the Marvell 88Q2220 PHY Dimitri Fedrau
                   ` (5 preceding siblings ...)
  2024-02-13 21:39 ` [PATCH v6 net-next 06/14] net: phy: marvell-88q2xxx: add interrupt support for link detection Dimitri Fedrau
@ 2024-02-13 21:39 ` Dimitri Fedrau
  2024-02-13 21:39 ` [PATCH v6 net-next 08/14] net: phy: marvell-88q2xxx: add support for temperature sensor Dimitri Fedrau
                   ` (6 subsequent siblings)
  13 siblings, 0 replies; 28+ messages in thread
From: Dimitri Fedrau @ 2024-02-13 21:39 UTC (permalink / raw)
  Cc: Dimitri Fedrau, Andrew Lunn, Heiner Kallweit, Russell King,
	David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Stefan Eichenberger, netdev, linux-kernel

Add suspend/resume ops for Marvell 88Q2xxx devices.

Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Signed-off-by: Dimitri Fedrau <dima.fedrau@gmail.com>
---
 drivers/net/phy/marvell-88q2xxx.c | 34 +++++++++++++++++++++++++++++++
 1 file changed, 34 insertions(+)

diff --git a/drivers/net/phy/marvell-88q2xxx.c b/drivers/net/phy/marvell-88q2xxx.c
index 7c7517af346b..8b8275552014 100644
--- a/drivers/net/phy/marvell-88q2xxx.c
+++ b/drivers/net/phy/marvell-88q2xxx.c
@@ -461,6 +461,38 @@ static irqreturn_t mv88q2xxx_handle_interrupt(struct phy_device *phydev)
 	return IRQ_HANDLED;
 }
 
+static int mv88q2xxx_suspend(struct phy_device *phydev)
+{
+	int ret;
+
+	/* Disable PHY interrupts */
+	if (phy_interrupt_is_valid(phydev)) {
+		phydev->interrupts = PHY_INTERRUPT_DISABLED;
+		ret = mv88q2xxx_config_intr(phydev);
+		if (ret)
+			return ret;
+	}
+
+	return phy_set_bits_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_CTRL1,
+				MDIO_CTRL1_LPOWER);
+}
+
+static int mv88q2xxx_resume(struct phy_device *phydev)
+{
+	int ret;
+
+	/* Enable PHY interrupts */
+	if (phy_interrupt_is_valid(phydev)) {
+		phydev->interrupts = PHY_INTERRUPT_ENABLED;
+		ret = mv88q2xxx_config_intr(phydev);
+		if (ret)
+			return ret;
+	}
+
+	return phy_clear_bits_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_CTRL1,
+				  MDIO_CTRL1_LPOWER);
+}
+
 static int mv88q222x_soft_reset(struct phy_device *phydev)
 {
 	int ret;
@@ -566,6 +598,8 @@ static struct phy_driver mv88q2xxx_driver[] = {
 		.set_loopback		= genphy_c45_loopback,
 		.get_sqi		= mv88q2xxx_get_sqi,
 		.get_sqi_max		= mv88q2xxx_get_sqi_max,
+		.suspend		= mv88q2xxx_suspend,
+		.resume			= mv88q2xxx_resume,
 	},
 };
 
-- 
2.39.2


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

* [PATCH v6 net-next 08/14] net: phy: marvell-88q2xxx: add support for temperature sensor
  2024-02-13 21:39 [PATCH v6 net-next 00/14] net: phy: marvell-88q2xxx: add driver for the Marvell 88Q2220 PHY Dimitri Fedrau
                   ` (6 preceding siblings ...)
  2024-02-13 21:39 ` [PATCH v6 net-next 07/14] net: phy: marvell-88q2xxx: add suspend / resume ops Dimitri Fedrau
@ 2024-02-13 21:39 ` Dimitri Fedrau
  2024-02-13 22:52   ` Guenter Roeck
  2024-02-14 17:50   ` Andrew Lunn
  2024-02-13 21:39 ` [PATCH v6 net-next 09/14] net: phy: marvell-88q2xxx: add cable test support Dimitri Fedrau
                   ` (5 subsequent siblings)
  13 siblings, 2 replies; 28+ messages in thread
From: Dimitri Fedrau @ 2024-02-13 21:39 UTC (permalink / raw)
  Cc: Dimitri Fedrau, Andrew Lunn, Heiner Kallweit, Russell King,
	David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Jean Delvare, Guenter Roeck, Stefan Eichenberger, netdev,
	linux-kernel, linux-hwmon

Marvell 88q2xxx devices have an inbuilt temperature sensor. Add hwmon
support for this sensor.

Signed-off-by: Dimitri Fedrau <dima.fedrau@gmail.com>
---
 drivers/net/phy/Kconfig           |   1 +
 drivers/net/phy/marvell-88q2xxx.c | 146 ++++++++++++++++++++++++++++++
 2 files changed, 147 insertions(+)

diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig
index 9e2672800f0b..f21f46ea736b 100644
--- a/drivers/net/phy/Kconfig
+++ b/drivers/net/phy/Kconfig
@@ -232,6 +232,7 @@ config MARVELL_10G_PHY
 
 config MARVELL_88Q2XXX_PHY
 	tristate "Marvell 88Q2XXX PHY"
+	depends on HWMON || HWMON=n
 	help
 	  Support for the Marvell 88Q2XXX 100/1000BASE-T1 Automotive Ethernet
 	  PHYs.
diff --git a/drivers/net/phy/marvell-88q2xxx.c b/drivers/net/phy/marvell-88q2xxx.c
index 8b8275552014..2ca1b47e8f8f 100644
--- a/drivers/net/phy/marvell-88q2xxx.c
+++ b/drivers/net/phy/marvell-88q2xxx.c
@@ -9,6 +9,7 @@
 #include <linux/ethtool_netlink.h>
 #include <linux/marvell_phy.h>
 #include <linux/phy.h>
+#include <linux/hwmon.h>
 
 #define PHY_ID_88Q2220_REVB0	(MARVELL_PHY_ID_88Q2220 | 0x1)
 
@@ -37,6 +38,18 @@
 #define MDIO_MMD_PCS_MV_GPIO_INT_CTRL			32787
 #define MDIO_MMD_PCS_MV_GPIO_INT_CTRL_TRI_DIS		0x0800
 
+#define MDIO_MMD_PCS_MV_TEMP_SENSOR1			32833
+#define MDIO_MMD_PCS_MV_TEMP_SENSOR1_RAW_INT		0x0001
+#define MDIO_MMD_PCS_MV_TEMP_SENSOR1_INT		0x0040
+#define MDIO_MMD_PCS_MV_TEMP_SENSOR1_INT_EN		0x0080
+
+#define MDIO_MMD_PCS_MV_TEMP_SENSOR2			32834
+#define MDIO_MMD_PCS_MV_TEMP_SENSOR2_DIS_MASK		0xc000
+
+#define MDIO_MMD_PCS_MV_TEMP_SENSOR3			32835
+#define MDIO_MMD_PCS_MV_TEMP_SENSOR3_INT_THRESH_MASK	0xff00
+#define MDIO_MMD_PCS_MV_TEMP_SENSOR3_MASK		0x00ff
+
 #define MDIO_MMD_PCS_MV_100BT1_STAT1			33032
 #define MDIO_MMD_PCS_MV_100BT1_STAT1_IDLE_ERROR		0x00ff
 #define MDIO_MMD_PCS_MV_100BT1_STAT1_JABBER		0x0100
@@ -493,6 +506,138 @@ static int mv88q2xxx_resume(struct phy_device *phydev)
 				  MDIO_CTRL1_LPOWER);
 }
 
+#if IS_ENABLED(CONFIG_HWMON)
+static const struct hwmon_channel_info * const mv88q2xxx_hwmon_info[] = {
+	HWMON_CHANNEL_INFO(temp, HWMON_T_INPUT | HWMON_T_MAX | HWMON_T_ALARM),
+	NULL
+};
+
+static umode_t mv88q2xxx_hwmon_is_visible(const void *data,
+					  enum hwmon_sensor_types type,
+					  u32 attr, int channel)
+{
+	switch (attr) {
+	case hwmon_temp_input:
+		return 0444;
+	case hwmon_temp_max:
+		return 0644;
+	case hwmon_temp_alarm:
+		return 0444;
+	default:
+		return 0;
+	}
+}
+
+static int mv88q2xxx_hwmon_read(struct device *dev,
+				enum hwmon_sensor_types type,
+				u32 attr, int channel, long *val)
+{
+	struct phy_device *phydev = dev_get_drvdata(dev);
+	int ret;
+
+	switch (attr) {
+	case hwmon_temp_input:
+		ret = phy_read_mmd(phydev, MDIO_MMD_PCS,
+				   MDIO_MMD_PCS_MV_TEMP_SENSOR3);
+		if (ret < 0)
+			return ret;
+
+		ret = FIELD_GET(MDIO_MMD_PCS_MV_TEMP_SENSOR3_MASK, ret);
+		*val = (ret - 75) * 1000;
+		return 0;
+	case hwmon_temp_max:
+		ret = phy_read_mmd(phydev, MDIO_MMD_PCS,
+				   MDIO_MMD_PCS_MV_TEMP_SENSOR3);
+		if (ret < 0)
+			return ret;
+
+		ret = FIELD_GET(MDIO_MMD_PCS_MV_TEMP_SENSOR3_INT_THRESH_MASK,
+				ret);
+		*val = (ret - 75) * 1000;
+		return 0;
+	case hwmon_temp_alarm:
+		ret = phy_read_mmd(phydev, MDIO_MMD_PCS,
+				   MDIO_MMD_PCS_MV_TEMP_SENSOR1);
+		if (ret < 0)
+			return ret;
+
+		*val = !!(ret & MDIO_MMD_PCS_MV_TEMP_SENSOR1_RAW_INT);
+		return 0;
+	default:
+		return -EOPNOTSUPP;
+	}
+}
+
+static int mv88q2xxx_hwmon_write(struct device *dev,
+				 enum hwmon_sensor_types type, u32 attr,
+				 int channel, long val)
+{
+	struct phy_device *phydev = dev_get_drvdata(dev);
+
+	switch (attr) {
+	case hwmon_temp_max:
+		clamp_val(val, -75000, 180000);
+		val = (val / 1000) + 75;
+		val = FIELD_PREP(MDIO_MMD_PCS_MV_TEMP_SENSOR3_INT_THRESH_MASK,
+				 val);
+		return phy_modify_mmd(phydev, MDIO_MMD_PCS,
+				      MDIO_MMD_PCS_MV_TEMP_SENSOR3,
+				      MDIO_MMD_PCS_MV_TEMP_SENSOR3_INT_THRESH_MASK,
+				      val);
+	default:
+		return -EOPNOTSUPP;
+	}
+}
+
+static const struct hwmon_ops mv88q2xxx_hwmon_hwmon_ops = {
+	.is_visible = mv88q2xxx_hwmon_is_visible,
+	.read = mv88q2xxx_hwmon_read,
+	.write = mv88q2xxx_hwmon_write,
+};
+
+static const struct hwmon_chip_info mv88q2xxx_hwmon_chip_info = {
+	.ops = &mv88q2xxx_hwmon_hwmon_ops,
+	.info = mv88q2xxx_hwmon_info,
+};
+
+static int mv88q2xxx_hwmon_probe(struct phy_device *phydev)
+{
+	struct device *dev = &phydev->mdio.dev;
+	struct device *hwmon;
+	char *hwmon_name;
+	int ret;
+
+	/* Enable temperature sense */
+	ret = phy_modify_mmd(phydev, MDIO_MMD_PCS, MDIO_MMD_PCS_MV_TEMP_SENSOR2,
+			     MDIO_MMD_PCS_MV_TEMP_SENSOR2_DIS_MASK, 0);
+	if (ret < 0)
+		return ret;
+
+	hwmon_name = devm_hwmon_sanitize_name(dev, dev_name(dev));
+	if (IS_ERR(hwmon_name))
+		return PTR_ERR(hwmon_name);
+
+	hwmon = devm_hwmon_device_register_with_info(dev,
+						     hwmon_name,
+						     phydev,
+						     &mv88q2xxx_hwmon_chip_info,
+						     NULL);
+
+	return PTR_ERR_OR_ZERO(hwmon);
+}
+
+#else
+static int mv88q2xxx_hwmon_probe(struct phy_device *phydev)
+{
+	return 0;
+}
+#endif
+
+static int mv88q2xxx_probe(struct phy_device *phydev)
+{
+	return mv88q2xxx_hwmon_probe(phydev);
+}
+
 static int mv88q222x_soft_reset(struct phy_device *phydev)
 {
 	int ret;
@@ -587,6 +732,7 @@ static struct phy_driver mv88q2xxx_driver[] = {
 	{
 		PHY_ID_MATCH_EXACT(PHY_ID_88Q2220_REVB0),
 		.name			= "mv88q2220",
+		.probe			= mv88q2xxx_probe,
 		.get_features		= mv88q2xxx_get_features,
 		.config_aneg		= mv88q222x_config_aneg,
 		.aneg_done		= genphy_c45_aneg_done,
-- 
2.39.2


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

* [PATCH v6 net-next 09/14] net: phy: marvell-88q2xxx: add cable test support
  2024-02-13 21:39 [PATCH v6 net-next 00/14] net: phy: marvell-88q2xxx: add driver for the Marvell 88Q2220 PHY Dimitri Fedrau
                   ` (7 preceding siblings ...)
  2024-02-13 21:39 ` [PATCH v6 net-next 08/14] net: phy: marvell-88q2xxx: add support for temperature sensor Dimitri Fedrau
@ 2024-02-13 21:39 ` Dimitri Fedrau
  2024-02-14 17:54   ` Andrew Lunn
  2024-02-13 21:39 ` [PATCH v6 net-next 10/14] net: phy: marvell-88q2xxx: make mv88q2xxx_config_aneg generic Dimitri Fedrau
                   ` (4 subsequent siblings)
  13 siblings, 1 reply; 28+ messages in thread
From: Dimitri Fedrau @ 2024-02-13 21:39 UTC (permalink / raw)
  Cc: Dimitri Fedrau, Andrew Lunn, Heiner Kallweit, Russell King,
	David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Stefan Eichenberger, netdev, linux-kernel

Add cable test support for Marvell 88Q222x devices. Reported distance
granularity is 1m.

1m cable, open:
  Cable test started for device eth0.
  Cable test completed for device eth0.
  Pair A code Open Circuit
  Pair A, fault length: 1.00m

1m cable, shorted:
  Cable test started for device eth0.
  Cable test completed for device eth0.
  Pair A code Short within Pair
  Pair A, fault length: 1.00m

6m cable, open:
  Cable test started for device eth0.
  Cable test completed for device eth0.
  Pair A code Open Circuit
  Pair A, fault length: 6.00m

6m cable, shorted:
  Cable test started for device eth0.
  Cable test completed for device eth0.
  Pair A code Short within Pair
  Pair A, fault length: 6.00m

Signed-off-by: Dimitri Fedrau <dima.fedrau@gmail.com>
---
 drivers/net/phy/marvell-88q2xxx.c | 97 +++++++++++++++++++++++++++++++
 1 file changed, 97 insertions(+)

diff --git a/drivers/net/phy/marvell-88q2xxx.c b/drivers/net/phy/marvell-88q2xxx.c
index 2ca1b47e8f8f..93a6a9dff722 100644
--- a/drivers/net/phy/marvell-88q2xxx.c
+++ b/drivers/net/phy/marvell-88q2xxx.c
@@ -72,6 +72,26 @@
 
 #define MDIO_MMD_PCS_MV_RX_STAT			33328
 
+#define MDIO_MMD_PCS_MV_TDR_RESET			65226
+#define MDIO_MMD_PCS_MV_TDR_RESET_TDR_RST		0x1000
+
+#define MDIO_MMD_PCS_MV_TDR_OFF_SHORT_CABLE		65241
+
+#define MDIO_MMD_PCS_MV_TDR_OFF_LONG_CABLE		65242
+
+#define MDIO_MMD_PCS_MV_TDR_STATUS			65245
+#define MDIO_MMD_PCS_MV_TDR_STATUS_OFF			0x0001
+#define MDIO_MMD_PCS_MV_TDR_STATUS_ON			0x0002
+#define MDIO_MMD_PCS_MV_TDR_STATUS_DIST_MASK		0xff00
+#define MDIO_MMD_PCS_MV_TDR_STATUS_VCT_STAT_MASK	0x00f0
+#define MDIO_MMD_PCS_MV_TDR_STATUS_VCT_STAT_SHORT	0x0030
+#define MDIO_MMD_PCS_MV_TDR_STATUS_VCT_STAT_OPEN	0x00e0
+#define MDIO_MMD_PCS_MV_TDR_STATUS_VCT_STAT_OK		0x0070
+#define MDIO_MMD_PCS_MV_TDR_STATUS_VCT_STAT_IN_PROGR	0x0080
+#define MDIO_MMD_PCS_MV_TDR_STATUS_VCT_STAT_NOISE	0x0050
+
+#define MDIO_MMD_PCS_MV_TDR_OFF_CUTOFF			65246
+
 struct mmd_val {
 	int devad;
 	u32 regnum;
@@ -715,6 +735,80 @@ static int mv88q222x_revb0_config_init(struct phy_device *phydev)
 	return 0;
 }
 
+static int mv88q222x_cable_test_start(struct phy_device *phydev)
+{
+	int ret;
+
+	ret = phy_write_mmd(phydev, MDIO_MMD_PCS,
+			    MDIO_MMD_PCS_MV_TDR_OFF_CUTOFF, 0x0058);
+	if (ret < 0)
+		return ret;
+
+	ret = phy_write_mmd(phydev, MDIO_MMD_PCS,
+			    MDIO_MMD_PCS_MV_TDR_OFF_LONG_CABLE, 0x00eb);
+	if (ret < 0)
+		return ret;
+
+	ret = phy_write_mmd(phydev, MDIO_MMD_PCS,
+			    MDIO_MMD_PCS_MV_TDR_OFF_SHORT_CABLE, 0x010e);
+	if (ret < 0)
+		return ret;
+
+	ret = phy_write_mmd(phydev, MDIO_MMD_PCS, MDIO_MMD_PCS_MV_TDR_RESET,
+			    0x0d90);
+	if (ret < 0)
+		return ret;
+
+	return phy_write_mmd(phydev, MDIO_MMD_PCS, MDIO_MMD_PCS_MV_TDR_STATUS,
+			     MDIO_MMD_PCS_MV_TDR_STATUS_ON);
+}
+
+static int mv88q222x_cable_test_get_status(struct phy_device *phydev,
+					   bool *finished)
+{
+	int ret;
+	u32 dist;
+
+	ret = phy_read_mmd(phydev, MDIO_MMD_PCS, MDIO_MMD_PCS_MV_TDR_STATUS);
+	if (ret < 0)
+		return ret;
+
+	*finished = true;
+	/* fault length in meters */
+	dist = FIELD_GET(MDIO_MMD_PCS_MV_TDR_STATUS_DIST_MASK, ret) * 100;
+	switch (ret & MDIO_MMD_PCS_MV_TDR_STATUS_VCT_STAT_MASK) {
+	case MDIO_MMD_PCS_MV_TDR_STATUS_VCT_STAT_OPEN:
+		ethnl_cable_test_result(phydev, ETHTOOL_A_CABLE_PAIR_A,
+					ETHTOOL_A_CABLE_RESULT_CODE_OPEN);
+		ethnl_cable_test_fault_length(phydev, ETHTOOL_A_CABLE_PAIR_A,
+					      dist);
+		break;
+	case MDIO_MMD_PCS_MV_TDR_STATUS_VCT_STAT_SHORT:
+		ethnl_cable_test_result(phydev, ETHTOOL_A_CABLE_PAIR_A,
+					ETHTOOL_A_CABLE_RESULT_CODE_SAME_SHORT);
+		ethnl_cable_test_fault_length(phydev, ETHTOOL_A_CABLE_PAIR_A,
+					      dist);
+		break;
+	case MDIO_MMD_PCS_MV_TDR_STATUS_VCT_STAT_OK:
+		ethnl_cable_test_result(phydev, ETHTOOL_A_CABLE_PAIR_A,
+					ETHTOOL_A_CABLE_RESULT_CODE_OK);
+		break;
+	case MDIO_MMD_PCS_MV_TDR_STATUS_VCT_STAT_IN_PROGR:
+		*finished = false;
+		break;
+	default:
+		ethnl_cable_test_result(phydev, ETHTOOL_A_CABLE_PAIR_A,
+					ETHTOOL_A_CABLE_RESULT_CODE_UNSPEC);
+	}
+
+	if (*finished)
+		return phy_write_mmd(phydev, MDIO_MMD_PCS,
+				     MDIO_MMD_PCS_MV_TDR_RESET,
+				     MDIO_MMD_PCS_MV_TDR_RESET_TDR_RST | 0xd90);
+
+	return 0;
+}
+
 static struct phy_driver mv88q2xxx_driver[] = {
 	{
 		.phy_id			= MARVELL_PHY_ID_88Q2110,
@@ -732,6 +826,7 @@ static struct phy_driver mv88q2xxx_driver[] = {
 	{
 		PHY_ID_MATCH_EXACT(PHY_ID_88Q2220_REVB0),
 		.name			= "mv88q2220",
+		.flags			= PHY_POLL_CABLE_TEST,
 		.probe			= mv88q2xxx_probe,
 		.get_features		= mv88q2xxx_get_features,
 		.config_aneg		= mv88q222x_config_aneg,
@@ -742,6 +837,8 @@ static struct phy_driver mv88q2xxx_driver[] = {
 		.config_intr		= mv88q2xxx_config_intr,
 		.handle_interrupt	= mv88q2xxx_handle_interrupt,
 		.set_loopback		= genphy_c45_loopback,
+		.cable_test_start	= mv88q222x_cable_test_start,
+		.cable_test_get_status	= mv88q222x_cable_test_get_status,
 		.get_sqi		= mv88q2xxx_get_sqi,
 		.get_sqi_max		= mv88q2xxx_get_sqi_max,
 		.suspend		= mv88q2xxx_suspend,
-- 
2.39.2


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

* [PATCH v6 net-next 10/14] net: phy: marvell-88q2xxx: make mv88q2xxx_config_aneg generic
  2024-02-13 21:39 [PATCH v6 net-next 00/14] net: phy: marvell-88q2xxx: add driver for the Marvell 88Q2220 PHY Dimitri Fedrau
                   ` (8 preceding siblings ...)
  2024-02-13 21:39 ` [PATCH v6 net-next 09/14] net: phy: marvell-88q2xxx: add cable test support Dimitri Fedrau
@ 2024-02-13 21:39 ` Dimitri Fedrau
  2024-02-13 21:39 ` [PATCH v6 net-next 11/14] net: phy: marvell-88q2xxx: switch to mv88q2xxx_config_aneg Dimitri Fedrau
                   ` (3 subsequent siblings)
  13 siblings, 0 replies; 28+ messages in thread
From: Dimitri Fedrau @ 2024-02-13 21:39 UTC (permalink / raw)
  Cc: Dimitri Fedrau, Andrew Lunn, Heiner Kallweit, Russell King,
	David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Stefan Eichenberger, netdev, linux-kernel

Marvell 88Q2xxx devices follow the same scheme, after configuration they
need a soft reset. Soft resets differ between devices, so we use the
.soft_reset callback instead of creating .config_aneg callbacks for each
device.

Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Signed-off-by: Dimitri Fedrau <dima.fedrau@gmail.com>
---
 drivers/net/phy/marvell-88q2xxx.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/net/phy/marvell-88q2xxx.c b/drivers/net/phy/marvell-88q2xxx.c
index 93a6a9dff722..fa75d34d1d04 100644
--- a/drivers/net/phy/marvell-88q2xxx.c
+++ b/drivers/net/phy/marvell-88q2xxx.c
@@ -364,7 +364,7 @@ static int mv88q2xxx_config_aneg(struct phy_device *phydev)
 	if (ret)
 		return ret;
 
-	return mv88q2xxx_soft_reset(phydev);
+	return phydev->drv->soft_reset(phydev);
 }
 
 static int mv88q2xxx_config_init(struct phy_device *phydev)
-- 
2.39.2


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

* [PATCH v6 net-next 11/14] net: phy: marvell-88q2xxx: switch to mv88q2xxx_config_aneg
  2024-02-13 21:39 [PATCH v6 net-next 00/14] net: phy: marvell-88q2xxx: add driver for the Marvell 88Q2220 PHY Dimitri Fedrau
                   ` (9 preceding siblings ...)
  2024-02-13 21:39 ` [PATCH v6 net-next 10/14] net: phy: marvell-88q2xxx: make mv88q2xxx_config_aneg generic Dimitri Fedrau
@ 2024-02-13 21:39 ` Dimitri Fedrau
  2024-02-13 21:39 ` [PATCH v6 net-next 12/14] net: phy: marvell-88q2xxx: cleanup mv88q2xxx_config_init Dimitri Fedrau
                   ` (2 subsequent siblings)
  13 siblings, 0 replies; 28+ messages in thread
From: Dimitri Fedrau @ 2024-02-13 21:39 UTC (permalink / raw)
  Cc: Dimitri Fedrau, Andrew Lunn, Heiner Kallweit, Russell King,
	David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Stefan Eichenberger, netdev, linux-kernel

Switch to mv88q2xxx_config_aneg for Marvell 88Q2220 devices and remove
the mv88q222x_config_aneg function which is basically a copy of the
mv88q2xxx_config_aneg function.

Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Signed-off-by: Dimitri Fedrau <dima.fedrau@gmail.com>
---
 drivers/net/phy/marvell-88q2xxx.c | 13 +------------
 1 file changed, 1 insertion(+), 12 deletions(-)

diff --git a/drivers/net/phy/marvell-88q2xxx.c b/drivers/net/phy/marvell-88q2xxx.c
index fa75d34d1d04..58140dfd75cb 100644
--- a/drivers/net/phy/marvell-88q2xxx.c
+++ b/drivers/net/phy/marvell-88q2xxx.c
@@ -685,17 +685,6 @@ static int mv88q222x_soft_reset(struct phy_device *phydev)
 	return 0;
 }
 
-static int mv88q222x_config_aneg(struct phy_device *phydev)
-{
-	int ret;
-
-	ret = genphy_c45_config_aneg(phydev);
-	if (ret)
-		return ret;
-
-	return mv88q222x_soft_reset(phydev);
-}
-
 static int mv88q222x_revb0_config_init(struct phy_device *phydev)
 {
 	int ret, i;
@@ -829,7 +818,7 @@ static struct phy_driver mv88q2xxx_driver[] = {
 		.flags			= PHY_POLL_CABLE_TEST,
 		.probe			= mv88q2xxx_probe,
 		.get_features		= mv88q2xxx_get_features,
-		.config_aneg		= mv88q222x_config_aneg,
+		.config_aneg		= mv88q2xxx_config_aneg,
 		.aneg_done		= genphy_c45_aneg_done,
 		.config_init		= mv88q222x_revb0_config_init,
 		.read_status		= mv88q2xxx_read_status,
-- 
2.39.2


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

* [PATCH v6 net-next 12/14] net: phy: marvell-88q2xxx: cleanup mv88q2xxx_config_init
  2024-02-13 21:39 [PATCH v6 net-next 00/14] net: phy: marvell-88q2xxx: add driver for the Marvell 88Q2220 PHY Dimitri Fedrau
                   ` (10 preceding siblings ...)
  2024-02-13 21:39 ` [PATCH v6 net-next 11/14] net: phy: marvell-88q2xxx: switch to mv88q2xxx_config_aneg Dimitri Fedrau
@ 2024-02-13 21:39 ` Dimitri Fedrau
  2024-02-14  6:39   ` Stefan Eichenberger
  2024-02-13 21:39 ` [PATCH v6 net-next 13/14] net: phy: marvell-88q2xxx: remove duplicated assignment of pma_extable Dimitri Fedrau
  2024-02-13 21:39 ` [PATCH v6 net-next 14/14] net: phy: marvell-88q2xxx: move interrupt configuration Dimitri Fedrau
  13 siblings, 1 reply; 28+ messages in thread
From: Dimitri Fedrau @ 2024-02-13 21:39 UTC (permalink / raw)
  Cc: Dimitri Fedrau, Andrew Lunn, Heiner Kallweit, Russell King,
	David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Stefan Eichenberger, netdev, linux-kernel

mv88q2xxx_config_init calls genphy_c45_read_pma which is done by
mv88q2xxx_read_status, it calls also mv88q2xxx_config_aneg which is
also called by the PHY state machine. Let the PHY state machine handle
the phydriver ops in their intendend way.

Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Signed-off-by: Dimitri Fedrau <dima.fedrau@gmail.com>
---
 drivers/net/phy/marvell-88q2xxx.c | 9 +--------
 1 file changed, 1 insertion(+), 8 deletions(-)

diff --git a/drivers/net/phy/marvell-88q2xxx.c b/drivers/net/phy/marvell-88q2xxx.c
index 58140dfd75cb..64b96ca83a0f 100644
--- a/drivers/net/phy/marvell-88q2xxx.c
+++ b/drivers/net/phy/marvell-88q2xxx.c
@@ -369,20 +369,13 @@ static int mv88q2xxx_config_aneg(struct phy_device *phydev)
 
 static int mv88q2xxx_config_init(struct phy_device *phydev)
 {
-	int ret;
-
 	/* The 88Q2XXX PHYs do have the extended ability register available, but
 	 * register MDIO_PMA_EXTABLE where they should signalize it does not
 	 * work according to specification. Therefore, we force it here.
 	 */
 	phydev->pma_extable = MDIO_PMA_EXTABLE_BT1;
 
-	/* Read the current PHY configuration */
-	ret = genphy_c45_read_pma(phydev);
-	if (ret)
-		return ret;
-
-	return mv88q2xxx_config_aneg(phydev);
+	return 0;
 }
 
 static int mv88q2xxx_get_sqi(struct phy_device *phydev)
-- 
2.39.2


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

* [PATCH v6 net-next 13/14] net: phy: marvell-88q2xxx: remove duplicated assignment of pma_extable
  2024-02-13 21:39 [PATCH v6 net-next 00/14] net: phy: marvell-88q2xxx: add driver for the Marvell 88Q2220 PHY Dimitri Fedrau
                   ` (11 preceding siblings ...)
  2024-02-13 21:39 ` [PATCH v6 net-next 12/14] net: phy: marvell-88q2xxx: cleanup mv88q2xxx_config_init Dimitri Fedrau
@ 2024-02-13 21:39 ` Dimitri Fedrau
  2024-02-14 17:55   ` Andrew Lunn
  2024-02-13 21:39 ` [PATCH v6 net-next 14/14] net: phy: marvell-88q2xxx: move interrupt configuration Dimitri Fedrau
  13 siblings, 1 reply; 28+ messages in thread
From: Dimitri Fedrau @ 2024-02-13 21:39 UTC (permalink / raw)
  Cc: Dimitri Fedrau, Andrew Lunn, Heiner Kallweit, Russell King,
	David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Stefan Eichenberger, netdev, linux-kernel

Remove assignment of phydev->pma_extable in mv88q222x_revb0_config_init.
It is already done in mv88q2xxx_config_init, just call
mv88q2xxx_config_init.

Signed-off-by: Dimitri Fedrau <dima.fedrau@gmail.com>
---
 drivers/net/phy/marvell-88q2xxx.c | 8 +-------
 1 file changed, 1 insertion(+), 7 deletions(-)

diff --git a/drivers/net/phy/marvell-88q2xxx.c b/drivers/net/phy/marvell-88q2xxx.c
index 64b96ca83a0f..7afaa693316f 100644
--- a/drivers/net/phy/marvell-88q2xxx.c
+++ b/drivers/net/phy/marvell-88q2xxx.c
@@ -700,12 +700,6 @@ static int mv88q222x_revb0_config_init(struct phy_device *phydev)
 			return ret;
 	}
 
-	/* The 88Q2XXX PHYs do have the extended ability register available, but
-	 * register MDIO_PMA_EXTABLE where they should signalize it does not
-	 * work according to specification. Therefore, we force it here.
-	 */
-	phydev->pma_extable = MDIO_PMA_EXTABLE_BT1;
-
 	/* Configure interrupt with default settings, output is driven low for
 	 * active interrupt and high for inactive.
 	 */
@@ -714,7 +708,7 @@ static int mv88q222x_revb0_config_init(struct phy_device *phydev)
 					MDIO_MMD_PCS_MV_GPIO_INT_CTRL,
 					MDIO_MMD_PCS_MV_GPIO_INT_CTRL_TRI_DIS);
 
-	return 0;
+	return mv88q2xxx_config_init(phydev);
 }
 
 static int mv88q222x_cable_test_start(struct phy_device *phydev)
-- 
2.39.2


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

* [PATCH v6 net-next 14/14] net: phy: marvell-88q2xxx: move interrupt configuration
  2024-02-13 21:39 [PATCH v6 net-next 00/14] net: phy: marvell-88q2xxx: add driver for the Marvell 88Q2220 PHY Dimitri Fedrau
                   ` (12 preceding siblings ...)
  2024-02-13 21:39 ` [PATCH v6 net-next 13/14] net: phy: marvell-88q2xxx: remove duplicated assignment of pma_extable Dimitri Fedrau
@ 2024-02-13 21:39 ` Dimitri Fedrau
  2024-02-14  6:56   ` Stefan Eichenberger
  2024-02-14 17:56   ` Andrew Lunn
  13 siblings, 2 replies; 28+ messages in thread
From: Dimitri Fedrau @ 2024-02-13 21:39 UTC (permalink / raw)
  Cc: Dimitri Fedrau, Andrew Lunn, Heiner Kallweit, Russell King,
	David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Stefan Eichenberger, netdev, linux-kernel

Move interrupt configuration from mv88q222x_revb0_config_init to
mv88q2xxx_config_init. Same register and bits are used for the 88q2xxx
devices.

Signed-off-by: Dimitri Fedrau <dima.fedrau@gmail.com>
---
 drivers/net/phy/marvell-88q2xxx.c | 16 ++++++++--------
 1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/drivers/net/phy/marvell-88q2xxx.c b/drivers/net/phy/marvell-88q2xxx.c
index 7afaa693316f..dc0f150826f0 100644
--- a/drivers/net/phy/marvell-88q2xxx.c
+++ b/drivers/net/phy/marvell-88q2xxx.c
@@ -375,6 +375,14 @@ static int mv88q2xxx_config_init(struct phy_device *phydev)
 	 */
 	phydev->pma_extable = MDIO_PMA_EXTABLE_BT1;
 
+	/* Configure interrupt with default settings, output is driven low for
+	 * active interrupt and high for inactive.
+	 */
+	if (phy_interrupt_is_valid(phydev))
+		return phy_set_bits_mmd(phydev, MDIO_MMD_PCS,
+					MDIO_MMD_PCS_MV_GPIO_INT_CTRL,
+					MDIO_MMD_PCS_MV_GPIO_INT_CTRL_TRI_DIS);
+
 	return 0;
 }
 
@@ -700,14 +708,6 @@ static int mv88q222x_revb0_config_init(struct phy_device *phydev)
 			return ret;
 	}
 
-	/* Configure interrupt with default settings, output is driven low for
-	 * active interrupt and high for inactive.
-	 */
-	if (phy_interrupt_is_valid(phydev))
-		return phy_set_bits_mmd(phydev, MDIO_MMD_PCS,
-					MDIO_MMD_PCS_MV_GPIO_INT_CTRL,
-					MDIO_MMD_PCS_MV_GPIO_INT_CTRL_TRI_DIS);
-
 	return mv88q2xxx_config_init(phydev);
 }
 
-- 
2.39.2


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

* Re: [PATCH v6 net-next 08/14] net: phy: marvell-88q2xxx: add support for temperature sensor
  2024-02-13 21:39 ` [PATCH v6 net-next 08/14] net: phy: marvell-88q2xxx: add support for temperature sensor Dimitri Fedrau
@ 2024-02-13 22:52   ` Guenter Roeck
  2024-02-14 17:50   ` Andrew Lunn
  1 sibling, 0 replies; 28+ messages in thread
From: Guenter Roeck @ 2024-02-13 22:52 UTC (permalink / raw)
  To: Dimitri Fedrau
  Cc: Andrew Lunn, Heiner Kallweit, Russell King, David S. Miller,
	Eric Dumazet, Jakub Kicinski, Paolo Abeni, Jean Delvare,
	Stefan Eichenberger, netdev, linux-kernel, linux-hwmon

On 2/13/24 13:39, Dimitri Fedrau wrote:
> Marvell 88q2xxx devices have an inbuilt temperature sensor. Add hwmon
> support for this sensor.
> 
> Signed-off-by: Dimitri Fedrau <dima.fedrau@gmail.com>

Reviewed-by: Guenter Roeck <linux@roeck-us.net>

Guenter


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

* Re: [PATCH v6 net-next 12/14] net: phy: marvell-88q2xxx: cleanup mv88q2xxx_config_init
  2024-02-13 21:39 ` [PATCH v6 net-next 12/14] net: phy: marvell-88q2xxx: cleanup mv88q2xxx_config_init Dimitri Fedrau
@ 2024-02-14  6:39   ` Stefan Eichenberger
  0 siblings, 0 replies; 28+ messages in thread
From: Stefan Eichenberger @ 2024-02-14  6:39 UTC (permalink / raw)
  To: Dimitri Fedrau
  Cc: Andrew Lunn, Heiner Kallweit, Russell King, David S. Miller,
	Eric Dumazet, Jakub Kicinski, Paolo Abeni, netdev, linux-kernel

On Tue, Feb 13, 2024 at 10:39:51PM +0100, Dimitri Fedrau wrote:
> mv88q2xxx_config_init calls genphy_c45_read_pma which is done by
> mv88q2xxx_read_status, it calls also mv88q2xxx_config_aneg which is
> also called by the PHY state machine. Let the PHY state machine handle
> the phydriver ops in their intendend way.
> 
> Reviewed-by: Andrew Lunn <andrew@lunn.ch>
> Signed-off-by: Dimitri Fedrau <dima.fedrau@gmail.com>

I tested the whole series on the MV88Q2110 and it works as expected.
Because this is the only change that really affects the MV88Q2110, I add
my tested by only here.

Tested-by: Stefan Eichenberger <eichest@gmail.com>

Regards,
Stefan

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

* Re: [PATCH v6 net-next 14/14] net: phy: marvell-88q2xxx: move interrupt configuration
  2024-02-13 21:39 ` [PATCH v6 net-next 14/14] net: phy: marvell-88q2xxx: move interrupt configuration Dimitri Fedrau
@ 2024-02-14  6:56   ` Stefan Eichenberger
  2024-02-14 17:56   ` Andrew Lunn
  1 sibling, 0 replies; 28+ messages in thread
From: Stefan Eichenberger @ 2024-02-14  6:56 UTC (permalink / raw)
  To: Dimitri Fedrau
  Cc: Andrew Lunn, Heiner Kallweit, Russell King, David S. Miller,
	Eric Dumazet, Jakub Kicinski, Paolo Abeni, netdev, linux-kernel

On Tue, Feb 13, 2024 at 10:39:53PM +0100, Dimitri Fedrau wrote:
> Move interrupt configuration from mv88q222x_revb0_config_init to
> mv88q2xxx_config_init. Same register and bits are used for the 88q2xxx
> devices.
> 
> Signed-off-by: Dimitri Fedrau <dima.fedrau@gmail.com>

I couldn't test it because we don't have the interrupt pin connected but
according to datasheet of the 88Q2110 it looks good.

Reviewed-by: Stefan Eichenberger <eichest@gmail.com>

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

* Re: [PATCH v6 net-next 05/14] net: phy: marvell-88q2xxx: add driver for the Marvell 88Q2220 PHY
  2024-02-13 21:39 ` [PATCH v6 net-next 05/14] net: phy: marvell-88q2xxx: add driver for the Marvell 88Q2220 PHY Dimitri Fedrau
@ 2024-02-14 13:20   ` Gregor Herburger
  2024-02-15 20:24     ` Dimitri Fedrau
  0 siblings, 1 reply; 28+ messages in thread
From: Gregor Herburger @ 2024-02-14 13:20 UTC (permalink / raw)
  To: Dimitri Fedrau
  Cc: Andrew Lunn, Heiner Kallweit, Russell King, David S. Miller,
	Eric Dumazet, Jakub Kicinski, Paolo Abeni, Stefan Eichenberger,
	netdev, linux-kernel

Hi Dimitri,

On Tue, Feb 13, 2024 at 10:39:44PM +0100, Dimitri Fedrau wrote:
>  static struct phy_driver mv88q2xxx_driver[] = {
>  	{
>  		.phy_id			= MARVELL_PHY_ID_88Q2110,
> @@ -255,12 +439,26 @@ static struct phy_driver mv88q2xxx_driver[] = {
>  		.get_sqi		= mv88q2xxx_get_sqi,
>  		.get_sqi_max		= mv88q2xxx_get_sqi_max,
>  	},
> +	{
> +		PHY_ID_MATCH_EXACT(PHY_ID_88Q2220_REVB0),

I tested the series on a 88Q2220 REV B1 (which is id 0x002b0b22). The
driver works fine on this revision.

I understand that in the Marvell API the initialization for Rev B0 and
B1 differ. For B0 some additional init sequence is executed. I did not look
into the details of this sequence. However this patch seems to work on
Rev B1.

Would you consider adding compatibility for Rev B1 and following? I
tested with:
		.phy_id			= MARVELL_PHY_ID_88Q2220,
		.phy_id_mask		= MARVELL_PHY_ID_MASK,

Otherwise:

Tested-by: Gregor Herburger <gregor.herburger@ew.tq-group.com>

Best regards
Gregor
-- 
TQ-Systems GmbH | Mühlstraße 2, Gut Delling | 82229 Seefeld, Germany
Amtsgericht München, HRB 105018
Geschäftsführer: Detlef Schneider, Rüdiger Stahl, Stefan Schneider
https://www.tq-group.com/

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

* Re: [PATCH v6 net-next 08/14] net: phy: marvell-88q2xxx: add support for temperature sensor
  2024-02-13 21:39 ` [PATCH v6 net-next 08/14] net: phy: marvell-88q2xxx: add support for temperature sensor Dimitri Fedrau
  2024-02-13 22:52   ` Guenter Roeck
@ 2024-02-14 17:50   ` Andrew Lunn
  1 sibling, 0 replies; 28+ messages in thread
From: Andrew Lunn @ 2024-02-14 17:50 UTC (permalink / raw)
  To: Dimitri Fedrau
  Cc: Heiner Kallweit, Russell King, David S. Miller, Eric Dumazet,
	Jakub Kicinski, Paolo Abeni, Jean Delvare, Guenter Roeck,
	Stefan Eichenberger, netdev, linux-kernel, linux-hwmon

On Tue, Feb 13, 2024 at 10:39:47PM +0100, Dimitri Fedrau wrote:
> Marvell 88q2xxx devices have an inbuilt temperature sensor. Add hwmon
> support for this sensor.
> 
> Signed-off-by: Dimitri Fedrau <dima.fedrau@gmail.com>

Reviewed-by: Andrew Lunn <andrew@lunn.ch>

    Andrew

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

* Re: [PATCH v6 net-next 09/14] net: phy: marvell-88q2xxx: add cable test support
  2024-02-13 21:39 ` [PATCH v6 net-next 09/14] net: phy: marvell-88q2xxx: add cable test support Dimitri Fedrau
@ 2024-02-14 17:54   ` Andrew Lunn
  2024-02-15 21:03     ` Dimitri Fedrau
  0 siblings, 1 reply; 28+ messages in thread
From: Andrew Lunn @ 2024-02-14 17:54 UTC (permalink / raw)
  To: Dimitri Fedrau
  Cc: Heiner Kallweit, Russell King, David S. Miller, Eric Dumazet,
	Jakub Kicinski, Paolo Abeni, Stefan Eichenberger, netdev,
	linux-kernel

> +static int mv88q222x_cable_test_get_status(struct phy_device *phydev,
> +					   bool *finished)
> +{
> +	int ret;
> +	u32 dist;
> +
> +	ret = phy_read_mmd(phydev, MDIO_MMD_PCS, MDIO_MMD_PCS_MV_TDR_STATUS);
> +	if (ret < 0)
> +		return ret;
> +
> +	*finished = true;

That looks odd. Is there no status bit which says it has completed? Is
it guaranteed to complete within a fixed time? How is it guaranteed that
mv88q222x_cable_test_get_status() is called at the necessary delay after 
mv88q222x_cable_test_start()?

	Andrew

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

* Re: [PATCH v6 net-next 13/14] net: phy: marvell-88q2xxx: remove duplicated assignment of pma_extable
  2024-02-13 21:39 ` [PATCH v6 net-next 13/14] net: phy: marvell-88q2xxx: remove duplicated assignment of pma_extable Dimitri Fedrau
@ 2024-02-14 17:55   ` Andrew Lunn
  0 siblings, 0 replies; 28+ messages in thread
From: Andrew Lunn @ 2024-02-14 17:55 UTC (permalink / raw)
  To: Dimitri Fedrau
  Cc: Heiner Kallweit, Russell King, David S. Miller, Eric Dumazet,
	Jakub Kicinski, Paolo Abeni, Stefan Eichenberger, netdev,
	linux-kernel

On Tue, Feb 13, 2024 at 10:39:52PM +0100, Dimitri Fedrau wrote:
> Remove assignment of phydev->pma_extable in mv88q222x_revb0_config_init.
> It is already done in mv88q2xxx_config_init, just call
> mv88q2xxx_config_init.
> 
> Signed-off-by: Dimitri Fedrau <dima.fedrau@gmail.com>

Reviewed-by: Andrew Lunn <andrew@lunn.ch>

    Andrew

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

* Re: [PATCH v6 net-next 14/14] net: phy: marvell-88q2xxx: move interrupt configuration
  2024-02-13 21:39 ` [PATCH v6 net-next 14/14] net: phy: marvell-88q2xxx: move interrupt configuration Dimitri Fedrau
  2024-02-14  6:56   ` Stefan Eichenberger
@ 2024-02-14 17:56   ` Andrew Lunn
  1 sibling, 0 replies; 28+ messages in thread
From: Andrew Lunn @ 2024-02-14 17:56 UTC (permalink / raw)
  To: Dimitri Fedrau
  Cc: Heiner Kallweit, Russell King, David S. Miller, Eric Dumazet,
	Jakub Kicinski, Paolo Abeni, Stefan Eichenberger, netdev,
	linux-kernel

On Tue, Feb 13, 2024 at 10:39:53PM +0100, Dimitri Fedrau wrote:
> Move interrupt configuration from mv88q222x_revb0_config_init to
> mv88q2xxx_config_init. Same register and bits are used for the 88q2xxx
> devices.
> 
> Signed-off-by: Dimitri Fedrau <dima.fedrau@gmail.com>

Reviewed-by: Andrew Lunn <andrew@lunn.ch>

    Andrew

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

* Re: [PATCH v6 net-next 05/14] net: phy: marvell-88q2xxx: add driver for the Marvell 88Q2220 PHY
  2024-02-14 13:20   ` Gregor Herburger
@ 2024-02-15 20:24     ` Dimitri Fedrau
  2024-02-16  9:18       ` Gregor Herburger
  0 siblings, 1 reply; 28+ messages in thread
From: Dimitri Fedrau @ 2024-02-15 20:24 UTC (permalink / raw)
  To: Gregor Herburger
  Cc: Andrew Lunn, Heiner Kallweit, Russell King, David S. Miller,
	Eric Dumazet, Jakub Kicinski, Paolo Abeni, Stefan Eichenberger,
	netdev, linux-kernel

Am Wed, Feb 14, 2024 at 02:20:37PM +0100 schrieb Gregor Herburger:
> Hi Dimitri,
>
Hi Gregor,

> On Tue, Feb 13, 2024 at 10:39:44PM +0100, Dimitri Fedrau wrote:
> >  static struct phy_driver mv88q2xxx_driver[] = {
> >  	{
> >  		.phy_id			= MARVELL_PHY_ID_88Q2110,
> > @@ -255,12 +439,26 @@ static struct phy_driver mv88q2xxx_driver[] = {
> >  		.get_sqi		= mv88q2xxx_get_sqi,
> >  		.get_sqi_max		= mv88q2xxx_get_sqi_max,
> >  	},
> > +	{
> > +		PHY_ID_MATCH_EXACT(PHY_ID_88Q2220_REVB0),
> 
> I tested the series on a 88Q2220 REV B1 (which is id 0x002b0b22). The
> driver works fine on this revision.
> 
> I understand that in the Marvell API the initialization for Rev B0 and
> B1 differ. For B0 some additional init sequence is executed. I did not look
> into the details of this sequence. However this patch seems to work on
> Rev B1.
>
> Would you consider adding compatibility for Rev B1 and following? I
> tested with:
> 		.phy_id			= MARVELL_PHY_ID_88Q2220,
> 		.phy_id_mask		= MARVELL_PHY_ID_MASK,
>

thanks for testing. I would stick to the exact initialization sequence
provided by the Marvell API. Registers and bits are mostly undocumented
and I think it is safest this way. Besides that it should be relatively
easy to add the support for rev. B1 by just adding the init sequence for
it.

Best regards,
Dimitri Fedrau

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

* Re: [PATCH v6 net-next 09/14] net: phy: marvell-88q2xxx: add cable test support
  2024-02-14 17:54   ` Andrew Lunn
@ 2024-02-15 21:03     ` Dimitri Fedrau
  2024-02-15 23:43       ` Andrew Lunn
  0 siblings, 1 reply; 28+ messages in thread
From: Dimitri Fedrau @ 2024-02-15 21:03 UTC (permalink / raw)
  To: Andrew Lunn
  Cc: Heiner Kallweit, Russell King, David S. Miller, Eric Dumazet,
	Jakub Kicinski, Paolo Abeni, Stefan Eichenberger, netdev,
	linux-kernel

Am Wed, Feb 14, 2024 at 06:54:58PM +0100 schrieb Andrew Lunn:
> > +static int mv88q222x_cable_test_get_status(struct phy_device *phydev,
> > +					   bool *finished)
> > +{
> > +	int ret;
> > +	u32 dist;
> > +
> > +	ret = phy_read_mmd(phydev, MDIO_MMD_PCS, MDIO_MMD_PCS_MV_TDR_STATUS);
> > +	if (ret < 0)
> > +		return ret;
> > +
> > +	*finished = true;
> 
> That looks odd. Is there no status bit which says it has completed? Is
> it guaranteed to complete within a fixed time? How is it guaranteed that
> mv88q222x_cable_test_get_status() is called at the necessary delay after 
> mv88q222x_cable_test_start()?
> 
According to the datasheet and the Marvell API bits(0:1) can be used to
check if the test has completed. Sample code waits 500ms before checking
the bits. If the test is not completed after the delay the corresponding
function returns with an error.

I just used bits(7:4) where 2'b1000 means that the test is in progress,
and setting *finished = false. I didn't introduced any delay, relying
on the reschedule delay of the PHY state machine. I didn't notice any
problems with this approach. Anyway if the test does not complete for
whatever reasons we get stuck here, right ? Don't know if this can
happen. Probably we should take the safer path described in the Marvell
API.

Dimitri

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

* Re: [PATCH v6 net-next 09/14] net: phy: marvell-88q2xxx: add cable test support
  2024-02-15 21:03     ` Dimitri Fedrau
@ 2024-02-15 23:43       ` Andrew Lunn
  0 siblings, 0 replies; 28+ messages in thread
From: Andrew Lunn @ 2024-02-15 23:43 UTC (permalink / raw)
  To: Dimitri Fedrau
  Cc: Heiner Kallweit, Russell King, David S. Miller, Eric Dumazet,
	Jakub Kicinski, Paolo Abeni, Stefan Eichenberger, netdev,
	linux-kernel

On Thu, Feb 15, 2024 at 10:03:50PM +0100, Dimitri Fedrau wrote:
> Am Wed, Feb 14, 2024 at 06:54:58PM +0100 schrieb Andrew Lunn:
> > > +static int mv88q222x_cable_test_get_status(struct phy_device *phydev,
> > > +					   bool *finished)
> > > +{
> > > +	int ret;
> > > +	u32 dist;
> > > +
> > > +	ret = phy_read_mmd(phydev, MDIO_MMD_PCS, MDIO_MMD_PCS_MV_TDR_STATUS);
> > > +	if (ret < 0)
> > > +		return ret;
> > > +
> > > +	*finished = true;
> > 
> > That looks odd. Is there no status bit which says it has completed? Is
> > it guaranteed to complete within a fixed time? How is it guaranteed that
> > mv88q222x_cable_test_get_status() is called at the necessary delay after 
> > mv88q222x_cable_test_start()?
> > 
> According to the datasheet and the Marvell API bits(0:1) can be used to
> check if the test has completed. Sample code waits 500ms before checking
> the bits. If the test is not completed after the delay the corresponding
> function returns with an error.

Thanks for the explanation.

> 
> I just used bits(7:4) where 2'b1000 means that the test is in progress,
> and setting *finished = false. I didn't introduced any delay, relying
> on the reschedule delay of the PHY state machine. I didn't notice any
> problems with this approach. Anyway if the test does not complete for
> whatever reasons we get stuck here, right ?

It should not happen, and if it does, its a bug in the PHY
firmware. And if that happens, the PHY is probably dead anyway.

phylib does allow you to break out of the cable test state by calling
phy_stop(). That generally happens when you admin down the interface.

So please do check the test has completed.

	Andrew

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

* Re: Re: [PATCH v6 net-next 05/14] net: phy: marvell-88q2xxx: add driver for the Marvell 88Q2220 PHY
  2024-02-15 20:24     ` Dimitri Fedrau
@ 2024-02-16  9:18       ` Gregor Herburger
  2024-02-16 20:53         ` Dimitri Fedrau
  0 siblings, 1 reply; 28+ messages in thread
From: Gregor Herburger @ 2024-02-16  9:18 UTC (permalink / raw)
  To: Dimitri Fedrau
  Cc: Andrew Lunn, Heiner Kallweit, Russell King, David S. Miller,
	Eric Dumazet, Jakub Kicinski, Paolo Abeni, Stefan Eichenberger,
	netdev, linux-kernel

On Thu, Feb 15, 2024 at 09:24:03PM +0100, Dimitri Fedrau wrote:
> > Hi Dimitri,
> >
> Hi Gregor,
> 
> > On Tue, Feb 13, 2024 at 10:39:44PM +0100, Dimitri Fedrau wrote:
> > >  static struct phy_driver mv88q2xxx_driver[] = {
> > >  	{
> > >  		.phy_id			= MARVELL_PHY_ID_88Q2110,
> > > @@ -255,12 +439,26 @@ static struct phy_driver mv88q2xxx_driver[] = {
> > >  		.get_sqi		= mv88q2xxx_get_sqi,
> > >  		.get_sqi_max		= mv88q2xxx_get_sqi_max,
> > >  	},
> > > +	{
> > > +		PHY_ID_MATCH_EXACT(PHY_ID_88Q2220_REVB0),
> > 
> > I tested the series on a 88Q2220 REV B1 (which is id 0x002b0b22). The
> > driver works fine on this revision.
> > 
> > I understand that in the Marvell API the initialization for Rev B0 and
> > B1 differ. For B0 some additional init sequence is executed. I did not look
> > into the details of this sequence. However this patch seems to work on
> > Rev B1.
> >
> > Would you consider adding compatibility for Rev B1 and following? I
> > tested with:
> > 		.phy_id			= MARVELL_PHY_ID_88Q2220,
> > 		.phy_id_mask		= MARVELL_PHY_ID_MASK,
> >
> 
> thanks for testing. I would stick to the exact initialization sequence
> provided by the Marvell API. Registers and bits are mostly undocumented
> and I think it is safest this way. Besides that it should be relatively
> easy to add the support for rev. B1 by just adding the init sequence for
> it.

Ok. I will have an closer look at the marvell API and eventually come up
with a patch for Rev. B1.

There is also a Rev.B2 for which I cannot find any init sequence. But
Rev. B1 will no longer be produced so I need a solution for B2
eventually.

Best regards
Gregor

-- 
TQ-Systems GmbH | Mühlstraße 2, Gut Delling | 82229 Seefeld, Germany
Amtsgericht München, HRB 105018
Geschäftsführer: Detlef Schneider, Rüdiger Stahl, Stefan Schneider
https://www.tq-group.com/

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

* Re: Re: [PATCH v6 net-next 05/14] net: phy: marvell-88q2xxx: add driver for the Marvell 88Q2220 PHY
  2024-02-16  9:18       ` Gregor Herburger
@ 2024-02-16 20:53         ` Dimitri Fedrau
  0 siblings, 0 replies; 28+ messages in thread
From: Dimitri Fedrau @ 2024-02-16 20:53 UTC (permalink / raw)
  To: Gregor Herburger
  Cc: Andrew Lunn, Heiner Kallweit, Russell King, David S. Miller,
	Eric Dumazet, Jakub Kicinski, Paolo Abeni, Stefan Eichenberger,
	netdev, linux-kernel

Am Fri, Feb 16, 2024 at 10:18:10AM +0100 schrieb Gregor Herburger:
> On Thu, Feb 15, 2024 at 09:24:03PM +0100, Dimitri Fedrau wrote:
> > > Hi Dimitri,
> > >
> > Hi Gregor,
> > 
> > > On Tue, Feb 13, 2024 at 10:39:44PM +0100, Dimitri Fedrau wrote:
> > > >  static struct phy_driver mv88q2xxx_driver[] = {
> > > >  	{
> > > >  		.phy_id			= MARVELL_PHY_ID_88Q2110,
> > > > @@ -255,12 +439,26 @@ static struct phy_driver mv88q2xxx_driver[] = {
> > > >  		.get_sqi		= mv88q2xxx_get_sqi,
> > > >  		.get_sqi_max		= mv88q2xxx_get_sqi_max,
> > > >  	},
> > > > +	{
> > > > +		PHY_ID_MATCH_EXACT(PHY_ID_88Q2220_REVB0),
> > > 
> > > I tested the series on a 88Q2220 REV B1 (which is id 0x002b0b22). The
> > > driver works fine on this revision.
> > > 
> > > I understand that in the Marvell API the initialization for Rev B0 and
> > > B1 differ. For B0 some additional init sequence is executed. I did not look
> > > into the details of this sequence. However this patch seems to work on
> > > Rev B1.
> > >
> > > Would you consider adding compatibility for Rev B1 and following? I
> > > tested with:
> > > 		.phy_id			= MARVELL_PHY_ID_88Q2220,
> > > 		.phy_id_mask		= MARVELL_PHY_ID_MASK,
> > >
> > 
> > thanks for testing. I would stick to the exact initialization sequence
> > provided by the Marvell API. Registers and bits are mostly undocumented
> > and I think it is safest this way. Besides that it should be relatively
> > easy to add the support for rev. B1 by just adding the init sequence for
> > it.
> 
> Ok. I will have an closer look at the marvell API and eventually come up
> with a patch for Rev. B1.
> 
> There is also a Rev.B2 for which I cannot find any init sequence. But
> Rev. B1 will no longer be produced so I need a solution for B2
> eventually.
>
After having a quick glance at the latest Marvell API release, the init
sequences for B1 and B2 are almost the same. It differs by a single
register write. Would be great if you can come up with a patch.

Dimitri

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

end of thread, other threads:[~2024-02-16 20:53 UTC | newest]

Thread overview: 28+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2024-02-13 21:39 [PATCH v6 net-next 00/14] net: phy: marvell-88q2xxx: add driver for the Marvell 88Q2220 PHY Dimitri Fedrau
2024-02-13 21:39 ` [PATCH v6 net-next 01/14] net: phy: Add BaseT1 auto-negotiation constants Dimitri Fedrau
2024-02-13 21:39 ` [PATCH v6 net-next 02/14] net: phy: Support 100/1000BT1 linkmode advertisements Dimitri Fedrau
2024-02-13 21:39 ` [PATCH v6 net-next 03/14] net: phy: c45: detect 100/1000BASE-T1 " Dimitri Fedrau
2024-02-13 21:39 ` [PATCH v6 net-next 04/14] net: phy: marvell-88q2xxx: fix typos Dimitri Fedrau
2024-02-13 21:39 ` [PATCH v6 net-next 05/14] net: phy: marvell-88q2xxx: add driver for the Marvell 88Q2220 PHY Dimitri Fedrau
2024-02-14 13:20   ` Gregor Herburger
2024-02-15 20:24     ` Dimitri Fedrau
2024-02-16  9:18       ` Gregor Herburger
2024-02-16 20:53         ` Dimitri Fedrau
2024-02-13 21:39 ` [PATCH v6 net-next 06/14] net: phy: marvell-88q2xxx: add interrupt support for link detection Dimitri Fedrau
2024-02-13 21:39 ` [PATCH v6 net-next 07/14] net: phy: marvell-88q2xxx: add suspend / resume ops Dimitri Fedrau
2024-02-13 21:39 ` [PATCH v6 net-next 08/14] net: phy: marvell-88q2xxx: add support for temperature sensor Dimitri Fedrau
2024-02-13 22:52   ` Guenter Roeck
2024-02-14 17:50   ` Andrew Lunn
2024-02-13 21:39 ` [PATCH v6 net-next 09/14] net: phy: marvell-88q2xxx: add cable test support Dimitri Fedrau
2024-02-14 17:54   ` Andrew Lunn
2024-02-15 21:03     ` Dimitri Fedrau
2024-02-15 23:43       ` Andrew Lunn
2024-02-13 21:39 ` [PATCH v6 net-next 10/14] net: phy: marvell-88q2xxx: make mv88q2xxx_config_aneg generic Dimitri Fedrau
2024-02-13 21:39 ` [PATCH v6 net-next 11/14] net: phy: marvell-88q2xxx: switch to mv88q2xxx_config_aneg Dimitri Fedrau
2024-02-13 21:39 ` [PATCH v6 net-next 12/14] net: phy: marvell-88q2xxx: cleanup mv88q2xxx_config_init Dimitri Fedrau
2024-02-14  6:39   ` Stefan Eichenberger
2024-02-13 21:39 ` [PATCH v6 net-next 13/14] net: phy: marvell-88q2xxx: remove duplicated assignment of pma_extable Dimitri Fedrau
2024-02-14 17:55   ` Andrew Lunn
2024-02-13 21:39 ` [PATCH v6 net-next 14/14] net: phy: marvell-88q2xxx: move interrupt configuration Dimitri Fedrau
2024-02-14  6:56   ` Stefan Eichenberger
2024-02-14 17:56   ` Andrew Lunn

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.