u-boot.lists.denx.de archive mirror
 help / color / mirror / Atom feed
* [PATCH 1/5] net: phy: marvell: Import and use marvell_phy.h from Linux
@ 2023-03-19 17:08 Marek Vasut
  2023-03-19 17:08 ` [PATCH 2/5] net: phy: Add phy_modify_mmd() and phy_modify_mmd_changed() " Marek Vasut
                   ` (4 more replies)
  0 siblings, 5 replies; 10+ messages in thread
From: Marek Vasut @ 2023-03-19 17:08 UTC (permalink / raw)
  To: u-boot
  Cc: Marek Vasut, Ariel D'Alessandro, Marek Behún,
	Joe Hershberger, Michael Trimarchi, Nate Drude, Ramon Fried,
	Simon Glass, Stefan Roese, Tim Harvey, Vladimir Oltean

Import marvell_phy.h from Linux 5.14.y as of commit
a5de4be0aaaa6 ("net: phy: marvell10g: fix differentiation of 88X3310 from 88X3340")
and use it in marvell PHY driver instead of current ad-hoc macros.
Two of the PHY IDs are unknown to Linux, 88E1149S and 88E1680, for
those two, only sync the length of the hexadecimal number to 8 digits.

No functional change.

Signed-off-by: Marek Vasut <marek.vasut+renesas@mailbox.org>
---
Cc: "Ariel D'Alessandro" <ariel.dalessandro@collabora.com>
Cc: "Marek Behún" <kabel@kernel.org>
Cc: Joe Hershberger <joe.hershberger@ni.com>
Cc: Marek Vasut <marek.vasut+renesas@mailbox.org>
Cc: Michael Trimarchi <michael@amarulasolutions.com>
Cc: Nate Drude <nate.d@variscite.com>
Cc: Ramon Fried <rfried.dev@gmail.com>
Cc: Simon Glass <sjg@chromium.org>
Cc: Stefan Roese <sr@denx.de>
Cc: Tim Harvey <tharvey@gateworks.com>
Cc: Vladimir Oltean <vladimir.oltean@nxp.com>
---
 drivers/net/phy/marvell.c | 45 +++++++++++++++++++------------------
 include/marvell_phy.h     | 47 +++++++++++++++++++++++++++++++++++++++
 2 files changed, 70 insertions(+), 22 deletions(-)
 create mode 100644 include/marvell_phy.h

diff --git a/drivers/net/phy/marvell.c b/drivers/net/phy/marvell.c
index 8992be6e89e..0a90f710dfe 100644
--- a/drivers/net/phy/marvell.c
+++ b/drivers/net/phy/marvell.c
@@ -7,6 +7,7 @@
  */
 #include <common.h>
 #include <errno.h>
+#include <marvell_phy.h>
 #include <phy.h>
 #include <linux/bitops.h>
 #include <linux/delay.h>
@@ -695,8 +696,8 @@ static int m88e1680_config(struct phy_device *phydev)
 
 U_BOOT_PHY_DRIVER(m88e1011s) = {
 	.name = "Marvell 88E1011S",
-	.uid = 0x1410c60,
-	.mask = 0xffffff0,
+	.uid = MARVELL_PHY_ID_88E1101,
+	.mask = MARVELL_PHY_ID_MASK,
 	.features = PHY_GBIT_FEATURES,
 	.config = &m88e1011s_config,
 	.startup = &m88e1011s_startup,
@@ -705,8 +706,8 @@ U_BOOT_PHY_DRIVER(m88e1011s) = {
 
 U_BOOT_PHY_DRIVER(m88e1111s) = {
 	.name = "Marvell 88E1111S",
-	.uid = 0x1410cc0,
-	.mask = 0xffffff0,
+	.uid = MARVELL_PHY_ID_88E1111,
+	.mask = MARVELL_PHY_ID_MASK,
 	.features = PHY_GBIT_FEATURES,
 	.config = &m88e1111s_config,
 	.startup = &m88e1011s_startup,
@@ -715,8 +716,8 @@ U_BOOT_PHY_DRIVER(m88e1111s) = {
 
 U_BOOT_PHY_DRIVER(m88e1118) = {
 	.name = "Marvell 88E1118",
-	.uid = 0x1410e10,
-	.mask = 0xffffff0,
+	.uid = MARVELL_PHY_ID_88E1118,
+	.mask = MARVELL_PHY_ID_MASK,
 	.features = PHY_GBIT_FEATURES,
 	.config = &m88e1118_config,
 	.startup = &m88e1118_startup,
@@ -725,8 +726,8 @@ U_BOOT_PHY_DRIVER(m88e1118) = {
 
 U_BOOT_PHY_DRIVER(m88e1118r) = {
 	.name = "Marvell 88E1118R",
-	.uid = 0x1410e40,
-	.mask = 0xffffff0,
+	.uid = MARVELL_PHY_ID_88E1116R,
+	.mask = MARVELL_PHY_ID_MASK,
 	.features = PHY_GBIT_FEATURES,
 	.config = &m88e1118_config,
 	.startup = &m88e1118_startup,
@@ -735,8 +736,8 @@ U_BOOT_PHY_DRIVER(m88e1118r) = {
 
 U_BOOT_PHY_DRIVER(m88e1121r) = {
 	.name = "Marvell 88E1121R",
-	.uid = 0x1410cb0,
-	.mask = 0xffffff0,
+	.uid = MARVELL_PHY_ID_88E1121R,
+	.mask = MARVELL_PHY_ID_MASK,
 	.features = PHY_GBIT_FEATURES,
 	.config = &m88e1121_config,
 	.startup = &genphy_startup,
@@ -745,8 +746,8 @@ U_BOOT_PHY_DRIVER(m88e1121r) = {
 
 U_BOOT_PHY_DRIVER(m88e1145) = {
 	.name = "Marvell 88E1145",
-	.uid = 0x1410cd0,
-	.mask = 0xffffff0,
+	.uid = MARVELL_PHY_ID_88E1145,
+	.mask = MARVELL_PHY_ID_MASK,
 	.features = PHY_GBIT_FEATURES,
 	.config = &m88e1145_config,
 	.startup = &m88e1145_startup,
@@ -755,8 +756,8 @@ U_BOOT_PHY_DRIVER(m88e1145) = {
 
 U_BOOT_PHY_DRIVER(m88e1149s) = {
 	.name = "Marvell 88E1149S",
-	.uid = 0x1410ca0,
-	.mask = 0xffffff0,
+	.uid = 0x01410ca0,
+	.mask = MARVELL_PHY_ID_MASK,
 	.features = PHY_GBIT_FEATURES,
 	.config = &m88e1149_config,
 	.startup = &m88e1011s_startup,
@@ -765,8 +766,8 @@ U_BOOT_PHY_DRIVER(m88e1149s) = {
 
 U_BOOT_PHY_DRIVER(m88e1240) = {
 	.name = "Marvell 88E1240",
-	.uid = 0x1410e30,
-	.mask = 0xffffff0,
+	.uid = MARVELL_PHY_ID_88E1240,
+	.mask = MARVELL_PHY_ID_MASK,
 	.features = PHY_GBIT_FEATURES,
 	.config = &m88e1240_config,
 	.startup = &m88e1011s_startup,
@@ -775,8 +776,8 @@ U_BOOT_PHY_DRIVER(m88e1240) = {
 
 U_BOOT_PHY_DRIVER(m88e151x) = {
 	.name = "Marvell 88E151x",
-	.uid = 0x1410dd0,
-	.mask = 0xffffff0,
+	.uid = MARVELL_PHY_ID_88E1510,
+	.mask = MARVELL_PHY_ID_MASK,
 	.features = PHY_GBIT_FEATURES,
 	.config = &m88e151x_config,
 	.startup = &m88e1011s_startup,
@@ -787,8 +788,8 @@ U_BOOT_PHY_DRIVER(m88e151x) = {
 
 U_BOOT_PHY_DRIVER(m88e1310) = {
 	.name = "Marvell 88E1310",
-	.uid = 0x01410e90,
-	.mask = 0xffffff0,
+	.uid = MARVELL_PHY_ID_88E1318S,
+	.mask = MARVELL_PHY_ID_MASK,
 	.features = PHY_GBIT_FEATURES,
 	.config = &m88e1310_config,
 	.startup = &m88e1011s_startup,
@@ -797,8 +798,8 @@ U_BOOT_PHY_DRIVER(m88e1310) = {
 
 U_BOOT_PHY_DRIVER(m88e1680) = {
 	.name = "Marvell 88E1680",
-	.uid = 0x1410ed0,
-	.mask = 0xffffff0,
+	.uid = 0x01410ed0,
+	.mask = MARVELL_PHY_ID_MASK,
 	.features = PHY_GBIT_FEATURES,
 	.config = &m88e1680_config,
 	.startup = &genphy_startup,
diff --git a/include/marvell_phy.h b/include/marvell_phy.h
new file mode 100644
index 00000000000..0f06c2287b5
--- /dev/null
+++ b/include/marvell_phy.h
@@ -0,0 +1,47 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _MARVELL_PHY_H
+#define _MARVELL_PHY_H
+
+/* Mask used for ID comparisons */
+#define MARVELL_PHY_ID_MASK		0xfffffff0
+
+/* Known PHY IDs */
+#define MARVELL_PHY_ID_88E1101		0x01410c60
+#define MARVELL_PHY_ID_88E1112		0x01410c90
+#define MARVELL_PHY_ID_88E1111		0x01410cc0
+#define MARVELL_PHY_ID_88E1118		0x01410e10
+#define MARVELL_PHY_ID_88E1121R		0x01410cb0
+#define MARVELL_PHY_ID_88E1145		0x01410cd0
+#define MARVELL_PHY_ID_88E1149R		0x01410e50
+#define MARVELL_PHY_ID_88E1240		0x01410e30
+#define MARVELL_PHY_ID_88E1318S		0x01410e90
+#define MARVELL_PHY_ID_88E1340S		0x01410dc0
+#define MARVELL_PHY_ID_88E1116R		0x01410e40
+#define MARVELL_PHY_ID_88E1510		0x01410dd0
+#define MARVELL_PHY_ID_88E1540		0x01410eb0
+#define MARVELL_PHY_ID_88E1545		0x01410ea0
+#define MARVELL_PHY_ID_88E1548P		0x01410ec0
+#define MARVELL_PHY_ID_88E3016		0x01410e60
+#define MARVELL_PHY_ID_88X3310		0x002b09a0
+#define MARVELL_PHY_ID_88E2110		0x002b09b0
+#define MARVELL_PHY_ID_88X2222		0x01410f10
+
+/* Marvel 88E1111 in Finisar SFP module with modified PHY ID */
+#define MARVELL_PHY_ID_88E1111_FINISAR	0x01ff0cc0
+
+/* These Ethernet switch families contain embedded PHYs, but they do
+ * not have a model ID. So the switch driver traps reads to the ID2
+ * register and returns the switch family ID
+ */
+#define MARVELL_PHY_ID_88E6341_FAMILY	0x01410f41
+#define MARVELL_PHY_ID_88E6390_FAMILY	0x01410f90
+#define MARVELL_PHY_ID_88E6393_FAMILY	0x002b0b9b
+
+#define MARVELL_PHY_FAMILY_ID(id)	((id) >> 4)
+
+/* struct phy_device dev_flags definitions */
+#define MARVELL_PHY_M1145_FLAGS_RESISTANCE	0x00000001
+#define MARVELL_PHY_M1118_DNS323_LEDS		0x00000002
+#define MARVELL_PHY_LED0_LINK_LED1_ACTIVE	0x00000004
+
+#endif /* _MARVELL_PHY_H */
-- 
2.39.2


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

* [PATCH 2/5] net: phy: Add phy_modify_mmd() and phy_modify_mmd_changed() from Linux
  2023-03-19 17:08 [PATCH 1/5] net: phy: marvell: Import and use marvell_phy.h from Linux Marek Vasut
@ 2023-03-19 17:08 ` Marek Vasut
  2023-04-01 18:49   ` Ramon Fried
  2023-03-19 17:08 ` [PATCH 3/5] net: phy: Add phy_read_mmd_poll_timeout() " Marek Vasut
                   ` (3 subsequent siblings)
  4 siblings, 1 reply; 10+ messages in thread
From: Marek Vasut @ 2023-03-19 17:08 UTC (permalink / raw)
  To: u-boot
  Cc: Marek Vasut, Ariel D'Alessandro, Marek Behún,
	Joe Hershberger, Michael Trimarchi, Nate Drude, Ramon Fried,
	Simon Glass, Stefan Roese, Tim Harvey, Vladimir Oltean

Add phy_modify_mmd()/phy_modify_mmd_changed() from Linux 5.1.y as of commit
b8554d4f7288f ("net: phy: add register modifying helpers returning 1 on change")
This is used by the upcoming Marvell 10G PHY driver.

Signed-off-by: Marek Vasut <marek.vasut+renesas@mailbox.org>
---
Cc: "Ariel D'Alessandro" <ariel.dalessandro@collabora.com>
Cc: "Marek Behún" <kabel@kernel.org>
Cc: Joe Hershberger <joe.hershberger@ni.com>
Cc: Marek Vasut <marek.vasut+renesas@mailbox.org>
Cc: Michael Trimarchi <michael@amarulasolutions.com>
Cc: Nate Drude <nate.d@variscite.com>
Cc: Ramon Fried <rfried.dev@gmail.com>
Cc: Simon Glass <sjg@chromium.org>
Cc: Stefan Roese <sr@denx.de>
Cc: Tim Harvey <tharvey@gateworks.com>
Cc: Vladimir Oltean <vladimir.oltean@nxp.com>
---
 drivers/net/phy/phy.c | 54 +++++++++++++++++++++++++++++++++++++++++++
 include/phy.h         |  4 ++++
 2 files changed, 58 insertions(+)

diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c
index f720d0a7920..0eeb0cb3a85 100644
--- a/drivers/net/phy/phy.c
+++ b/drivers/net/phy/phy.c
@@ -1158,6 +1158,60 @@ int phy_clear_bits_mmd(struct phy_device *phydev, int devad, u32 regnum, u16 val
 	return 0;
 }
 
+/**
+ * phy_modify_mmd_changed - Function for modifying a register on MMD
+ * @phydev: the phy_device struct
+ * @devad: the MMD containing register to modify
+ * @regnum: register number to modify
+ * @mask: bit mask of bits to clear
+ * @set: new value of bits set in mask to write to @regnum
+ *
+ * NOTE: MUST NOT be called from interrupt context,
+ * because the bus read/write functions may wait for an interrupt
+ * to conclude the operation.
+ *
+ * Returns negative errno, 0 if there was no change, and 1 in case of change
+ */
+int phy_modify_mmd_changed(struct phy_device *phydev, int devad, u32 regnum,
+			   u16 mask, u16 set)
+{
+	int new, ret;
+
+	ret = phy_read_mmd(phydev, devad, regnum);
+	if (ret < 0)
+		return ret;
+
+	new = (ret & ~mask) | set;
+	if (new == ret)
+		return 0;
+
+	ret = phy_write_mmd(phydev, devad, regnum, new);
+
+	return ret < 0 ? ret : 1;
+}
+
+/**
+ * phy_modify_mmd - Convenience function for modifying a register on MMD
+ * @phydev: the phy_device struct
+ * @devad: the MMD containing register to modify
+ * @regnum: register number to modify
+ * @mask: bit mask of bits to clear
+ * @set: new value of bits set in mask to write to @regnum
+ *
+ * NOTE: MUST NOT be called from interrupt context,
+ * because the bus read/write functions may wait for an interrupt
+ * to conclude the operation.
+ */
+int phy_modify_mmd(struct phy_device *phydev, int devad, u32 regnum,
+		   u16 mask, u16 set)
+{
+	int ret;
+
+	ret = phy_modify_mmd_changed(phydev, devad, regnum, mask, set);
+
+	return ret < 0 ? ret : 0;
+}
+
 bool phy_interface_is_ncsi(void)
 {
 #ifdef CONFIG_PHY_NCSI
diff --git a/include/phy.h b/include/phy.h
index 4a9de461152..34675b2c9c0 100644
--- a/include/phy.h
+++ b/include/phy.h
@@ -289,6 +289,10 @@ int phy_read_mmd(struct phy_device *phydev, int devad, int regnum);
 int phy_write_mmd(struct phy_device *phydev, int devad, int regnum, u16 val);
 int phy_set_bits_mmd(struct phy_device *phydev, int devad, u32 regnum, u16 val);
 int phy_clear_bits_mmd(struct phy_device *phydev, int devad, u32 regnum, u16 val);
+int phy_modify_mmd_changed(struct phy_device *phydev, int devad, u32 regnum,
+			   u16 mask, u16 set);
+int phy_modify_mmd(struct phy_device *phydev, int devad, u32 regnum,
+		   u16 mask, u16 set);
 
 int phy_startup(struct phy_device *phydev);
 int phy_config(struct phy_device *phydev);
-- 
2.39.2


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

* [PATCH 3/5] net: phy: Add phy_read_mmd_poll_timeout() from Linux
  2023-03-19 17:08 [PATCH 1/5] net: phy: marvell: Import and use marvell_phy.h from Linux Marek Vasut
  2023-03-19 17:08 ` [PATCH 2/5] net: phy: Add phy_modify_mmd() and phy_modify_mmd_changed() " Marek Vasut
@ 2023-03-19 17:08 ` Marek Vasut
  2023-04-01 18:50   ` Ramon Fried
  2023-03-19 17:08 ` [PATCH 4/5] net: phy: Add MDIO PCS 2.5G and 5G speed macros " Marek Vasut
                   ` (2 subsequent siblings)
  4 siblings, 1 reply; 10+ messages in thread
From: Marek Vasut @ 2023-03-19 17:08 UTC (permalink / raw)
  To: u-boot
  Cc: Marek Vasut, Ariel D'Alessandro, Marek Behún,
	Joe Hershberger, Michael Trimarchi, Nate Drude, Ramon Fried,
	Simon Glass, Stefan Roese, Tim Harvey, Vladimir Oltean

Add phy_read_mmd_poll_timeout() from Linux 5.7.y as of commit
bd971ff0b7392 ("net: phy: introduce phy_read_mmd_poll_timeout macro")
This is used by the upcoming Marvell 10G PHY driver.

Signed-off-by: Marek Vasut <marek.vasut+renesas@mailbox.org>
---
Cc: "Ariel D'Alessandro" <ariel.dalessandro@collabora.com>
Cc: "Marek Behún" <kabel@kernel.org>
Cc: Joe Hershberger <joe.hershberger@ni.com>
Cc: Marek Vasut <marek.vasut+renesas@mailbox.org>
Cc: Michael Trimarchi <michael@amarulasolutions.com>
Cc: Nate Drude <nate.d@variscite.com>
Cc: Ramon Fried <rfried.dev@gmail.com>
Cc: Simon Glass <sjg@chromium.org>
Cc: Stefan Roese <sr@denx.de>
Cc: Tim Harvey <tharvey@gateworks.com>
Cc: Vladimir Oltean <vladimir.oltean@nxp.com>
---
 include/phy.h | 31 +++++++++++++++++++++++++++++++
 1 file changed, 31 insertions(+)

diff --git a/include/phy.h b/include/phy.h
index 34675b2c9c0..a837fed7235 100644
--- a/include/phy.h
+++ b/include/phy.h
@@ -282,6 +282,37 @@ static inline ofnode phy_get_ofnode(struct phy_device *phydev)
 		return dev_ofnode(phydev->dev);
 }
 
+/**
+ * phy_read_mmd_poll_timeout - Periodically poll a PHY register until a
+ *                             condition is met or a timeout occurs
+ *
+ * @phydev: The phy_device struct
+ * @devaddr: The MMD to read from
+ * @regnum: The register on the MMD to read
+ * @val: Variable to read the register into
+ * @cond: Break condition (usually involving @val)
+ * @sleep_us: Maximum time to sleep between reads in us (0
+ *            tight-loops).  Should be less than ~20ms since usleep_range
+ *            is used (see Documentation/timers/timers-howto.rst).
+ * @timeout_us: Timeout in us, 0 means never timeout
+ * @sleep_before_read: if it is true, sleep @sleep_us before read.
+ * Returns 0 on success and -ETIMEDOUT upon a timeout. In either
+ * case, the last read value at @args is stored in @val. Must not
+ * be called from atomic context if sleep_us or timeout_us are used.
+ */
+#define phy_read_mmd_poll_timeout(phydev, devaddr, regnum, val, cond, \
+				  sleep_us, timeout_us, sleep_before_read) \
+({ \
+	int __ret = read_poll_timeout(phy_read_mmd, val, (cond) || val < 0, \
+				  sleep_us, timeout_us, \
+				  phydev, devaddr, regnum); \
+	if (val <  0) \
+		__ret = val; \
+	if (__ret) \
+		dev_err(phydev->dev, "%s failed: %d\n", __func__, __ret); \
+	__ret; \
+})
+
 int phy_read(struct phy_device *phydev, int devad, int regnum);
 int phy_write(struct phy_device *phydev, int devad, int regnum, u16 val);
 void phy_mmd_start_indirect(struct phy_device *phydev, int devad, int regnum);
-- 
2.39.2


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

* [PATCH 4/5] net: phy: Add MDIO PCS 2.5G and 5G speed macros from Linux
  2023-03-19 17:08 [PATCH 1/5] net: phy: marvell: Import and use marvell_phy.h from Linux Marek Vasut
  2023-03-19 17:08 ` [PATCH 2/5] net: phy: Add phy_modify_mmd() and phy_modify_mmd_changed() " Marek Vasut
  2023-03-19 17:08 ` [PATCH 3/5] net: phy: Add phy_read_mmd_poll_timeout() " Marek Vasut
@ 2023-03-19 17:08 ` Marek Vasut
  2023-04-01 18:50   ` Ramon Fried
  2023-03-19 17:08 ` [PATCH 5/5] net: phy: marvell10g: Adapt Marvell 10G PHY driver " Marek Vasut
  2023-04-01 18:49 ` [PATCH 1/5] net: phy: marvell: Import and use marvell_phy.h " Ramon Fried
  4 siblings, 1 reply; 10+ messages in thread
From: Marek Vasut @ 2023-03-19 17:08 UTC (permalink / raw)
  To: u-boot
  Cc: Marek Vasut, Ariel D'Alessandro, Marek Behún,
	Joe Hershberger, Michael Trimarchi, Nate Drude, Ramon Fried,
	Simon Glass, Stefan Roese, Tim Harvey, Vladimir Oltean

Add MDIO PCS 2.5G and 5G speed macros from Linux 5.1.y as of commit
7fd8afa8933a0 ("net: phy: Add generic support for 2.5GBaseT and 5GBaseT")
This is used by the upcoming Marvell 10G PHY driver.

Signed-off-by: Marek Vasut <marek.vasut+renesas@mailbox.org>
---
Cc: "Ariel D'Alessandro" <ariel.dalessandro@collabora.com>
Cc: "Marek Behún" <kabel@kernel.org>
Cc: Joe Hershberger <joe.hershberger@ni.com>
Cc: Marek Vasut <marek.vasut+renesas@mailbox.org>
Cc: Michael Trimarchi <michael@amarulasolutions.com>
Cc: Nate Drude <nate.d@variscite.com>
Cc: Ramon Fried <rfried.dev@gmail.com>
Cc: Simon Glass <sjg@chromium.org>
Cc: Stefan Roese <sr@denx.de>
Cc: Tim Harvey <tharvey@gateworks.com>
Cc: Vladimir Oltean <vladimir.oltean@nxp.com>
---
 include/linux/mdio.h | 18 ++++++++++++++++++
 1 file changed, 18 insertions(+)

diff --git a/include/linux/mdio.h b/include/linux/mdio.h
index 6e821d906fb..b7c845155e4 100644
--- a/include/linux/mdio.h
+++ b/include/linux/mdio.h
@@ -44,6 +44,7 @@
 #define MDIO_AN_ADVERTISE	16	/* AN advertising (base page) */
 #define MDIO_AN_LPA		19	/* AN LP abilities (base page) */
 #define MDIO_PCS_EEE_ABLE	20	/* EEE Capability register */
+#define MDIO_PMA_NG_EXTABLE	21	/* 2.5G/5G PMA/PMD extended ability */
 #define MDIO_PCS_EEE_WK_ERR	22	/* EEE wake error counter */
 #define MDIO_PHYXS_LNSTAT	24	/* PHY XGXS lane state */
 #define MDIO_AN_EEE_ADV		60	/* EEE advertisement */
@@ -91,6 +92,10 @@
 #define MDIO_CTRL1_SPEED10G		(MDIO_CTRL1_SPEEDSELEXT | 0x00)
 /* 10PASS-TS/2BASE-TL */
 #define MDIO_CTRL1_SPEED10P2B		(MDIO_CTRL1_SPEEDSELEXT | 0x04)
+/* 2.5 Gb/s */
+#define MDIO_CTRL1_SPEED2_5G		(MDIO_CTRL1_SPEEDSELEXT | 0x18)
+/* 5 Gb/s */
+#define MDIO_CTRL1_SPEED5G		(MDIO_CTRL1_SPEEDSELEXT | 0x1c)
 
 /* Status register 1. */
 #define MDIO_STAT1_LPOWERABLE		0x0002	/* Low-power ability */
@@ -111,6 +116,8 @@
 #define MDIO_PMA_SPEED_100		0x0020	/* 100M capable */
 #define MDIO_PMA_SPEED_10		0x0040	/* 10M capable */
 #define MDIO_PCS_SPEED_10P2B		0x0002	/* 10PASS-TS/2BASE-TL capable */
+#define MDIO_PCS_SPEED_2_5G		0x0040	/* 2.5G capable */
+#define MDIO_PCS_SPEED_5G		0x0080	/* 5G capable */
 
 /* Device present registers. */
 #define MDIO_DEVS_PRESENT(devad)	(1 << (devad))
@@ -150,6 +157,8 @@
 #define MDIO_PMA_CTRL2_1000BKX		0x000d	/* 1000BASE-KX type */
 #define MDIO_PMA_CTRL2_100BTX		0x000e	/* 100BASE-TX type */
 #define MDIO_PMA_CTRL2_10BT		0x000f	/* 10BASE-T type */
+#define MDIO_PMA_CTRL2_2_5GBT		0x0030  /* 2.5GBaseT type */
+#define MDIO_PMA_CTRL2_5GBT		0x0031  /* 5GBaseT type */
 #define MDIO_PCS_CTRL2_TYPE		0x0003	/* PCS type selection */
 #define MDIO_PCS_CTRL2_10GBR		0x0000	/* 10GBASE-R type */
 #define MDIO_PCS_CTRL2_10GBX		0x0001	/* 10GBASE-X type */
@@ -203,6 +212,7 @@
 #define MDIO_PMA_EXTABLE_1000BKX	0x0040	/* 1000BASE-KX ability */
 #define MDIO_PMA_EXTABLE_100BTX		0x0080	/* 100BASE-TX ability */
 #define MDIO_PMA_EXTABLE_10BT		0x0100	/* 10BASE-T ability */
+#define MDIO_PMA_EXTABLE_NBT		0x4000  /* 2.5/5GBASE-T ability */
 
 /* PHY XGXS lane state register. */
 #define MDIO_PHYXS_LNSTAT_SYNC0		0x0001
@@ -239,9 +249,13 @@
 #define MDIO_PCS_10GBRT_STAT2_BER	0x3f00
 
 /* AN 10GBASE-T control register. */
+#define MDIO_AN_10GBT_CTRL_ADV2_5G	0x0080	/* Advertise 2.5GBASE-T */
+#define MDIO_AN_10GBT_CTRL_ADV5G	0x0100	/* Advertise 5GBASE-T */
 #define MDIO_AN_10GBT_CTRL_ADV10G	0x1000	/* Advertise 10GBASE-T */
 
 /* AN 10GBASE-T status register. */
+#define MDIO_AN_10GBT_STAT_LP2_5G	0x0020  /* LP is 2.5GBT capable */
+#define MDIO_AN_10GBT_STAT_LP5G		0x0040  /* LP is 5GBT capable */
 #define MDIO_AN_10GBT_STAT_LPTRR	0x0200	/* LP training reset req. */
 #define MDIO_AN_10GBT_STAT_LPLTABLE	0x0400	/* LP loop timing ability */
 #define MDIO_AN_10GBT_STAT_LP10G	0x0800	/* LP is 10GBT capable */
@@ -270,6 +284,10 @@
 #define MDIO_EEE_10GKX4		0x0020	/* 10G KX4 EEE cap */
 #define MDIO_EEE_10GKR		0x0040	/* 10G KR EEE cap */
 
+/* 2.5G/5G Extended abilities register. */
+#define MDIO_PMA_NG_EXTABLE_2_5GBT	0x0001	/* 2.5GBASET ability */
+#define MDIO_PMA_NG_EXTABLE_5GBT	0x0002	/* 5GBASET ability */
+
 /* LASI RX_ALARM control/status registers. */
 #define MDIO_PMA_LASI_RX_PHYXSLFLT	0x0001	/* PHY XS RX local fault */
 #define MDIO_PMA_LASI_RX_PCSLFLT	0x0008	/* PCS RX local fault */
-- 
2.39.2


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

* [PATCH 5/5] net: phy: marvell10g: Adapt Marvell 10G PHY driver from Linux
  2023-03-19 17:08 [PATCH 1/5] net: phy: marvell: Import and use marvell_phy.h from Linux Marek Vasut
                   ` (2 preceding siblings ...)
  2023-03-19 17:08 ` [PATCH 4/5] net: phy: Add MDIO PCS 2.5G and 5G speed macros " Marek Vasut
@ 2023-03-19 17:08 ` Marek Vasut
  2023-04-01 18:51   ` Ramon Fried
  2023-04-01 18:49 ` [PATCH 1/5] net: phy: marvell: Import and use marvell_phy.h " Ramon Fried
  4 siblings, 1 reply; 10+ messages in thread
From: Marek Vasut @ 2023-03-19 17:08 UTC (permalink / raw)
  To: u-boot
  Cc: Marek Vasut, Ariel D'Alessandro, Marek Behún,
	Joe Hershberger, Michael Trimarchi, Nate Drude, Ramon Fried,
	Simon Glass, Stefan Roese, Tim Harvey, Vladimir Oltean

Pull Marvell 10G PHY driver from Linux 6.1.y as of commit
d6d29292640d3 ("net: phy: marvell10g: select host interface configuration")
and heavily adapt to match U-Boot PHY framework. Support for
hwmon is removed as is much other functionality which could
not be tested, this results in much simpler driver which can
only bring the PHY up and set MAC type.

Signed-off-by: Marek Vasut <marek.vasut+renesas@mailbox.org>
---
Cc: "Ariel D'Alessandro" <ariel.dalessandro@collabora.com>
Cc: "Marek Behún" <kabel@kernel.org>
Cc: Joe Hershberger <joe.hershberger@ni.com>
Cc: Marek Vasut <marek.vasut+renesas@mailbox.org>
Cc: Michael Trimarchi <michael@amarulasolutions.com>
Cc: Nate Drude <nate.d@variscite.com>
Cc: Ramon Fried <rfried.dev@gmail.com>
Cc: Simon Glass <sjg@chromium.org>
Cc: Stefan Roese <sr@denx.de>
Cc: Tim Harvey <tharvey@gateworks.com>
Cc: Vladimir Oltean <vladimir.oltean@nxp.com>
---
 drivers/net/phy/Kconfig      |   5 +
 drivers/net/phy/Makefile     |   1 +
 drivers/net/phy/marvell10g.c | 605 +++++++++++++++++++++++++++++++++++
 3 files changed, 611 insertions(+)
 create mode 100644 drivers/net/phy/marvell10g.c

diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig
index 6806e3c0903..24158776f52 100644
--- a/drivers/net/phy/Kconfig
+++ b/drivers/net/phy/Kconfig
@@ -174,6 +174,11 @@ config PHY_LXT
 config PHY_MARVELL
 	bool "Marvell Ethernet PHYs support"
 
+config PHY_MARVELL_10G
+	bool "Marvell Alaska 10Gbit PHYs"
+	help
+	  Support for the Marvell Alaska MV88X3310 and compatible PHYs.
+
 config PHY_MESON_GXL
 	bool "Amlogic Meson GXL Internal PHY support"
 
diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile
index 963d96e2bcb..85d17f109cd 100644
--- a/drivers/net/phy/Makefile
+++ b/drivers/net/phy/Makefile
@@ -20,6 +20,7 @@ obj-$(CONFIG_PHY_DAVICOM) += davicom.o
 obj-$(CONFIG_PHY_ET1011C) += et1011c.o
 obj-$(CONFIG_PHY_LXT) += lxt.o
 obj-$(CONFIG_PHY_MARVELL) += marvell.o
+obj-$(CONFIG_PHY_MARVELL_10G) += marvell10g.o
 obj-$(CONFIG_PHY_MICREL_KSZ8XXX) += micrel_ksz8xxx.o
 obj-$(CONFIG_PHY_MICREL_KSZ90X1) += micrel_ksz90x1.o
 obj-$(CONFIG_PHY_MESON_GXL) += meson-gxl.o
diff --git a/drivers/net/phy/marvell10g.c b/drivers/net/phy/marvell10g.c
new file mode 100644
index 00000000000..9e64672f5ca
--- /dev/null
+++ b/drivers/net/phy/marvell10g.c
@@ -0,0 +1,605 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Marvell 10G 88x3310 PHY driver
+ *
+ * Based upon the ID registers, this PHY appears to be a mixture of IPs
+ * from two different companies.
+ *
+ * There appears to be several different data paths through the PHY which
+ * are automatically managed by the PHY.  The following has been determined
+ * via observation and experimentation for a setup using single-lane Serdes:
+ *
+ *       SGMII PHYXS -- BASE-T PCS -- 10G PMA -- AN -- Copper (for <= 1G)
+ *  10GBASE-KR PHYXS -- BASE-T PCS -- 10G PMA -- AN -- Copper (for 10G)
+ *  10GBASE-KR PHYXS -- BASE-R PCS -- Fiber
+ *
+ * With XAUI, observation shows:
+ *
+ *        XAUI PHYXS -- <appropriate PCS as above>
+ *
+ * and no switching of the host interface mode occurs.
+ *
+ * If both the fiber and copper ports are connected, the first to gain
+ * link takes priority and the other port is completely locked out.
+ */
+#include <common.h>
+#include <console.h>
+#include <dm/device_compat.h>
+#include <dm/devres.h>
+#include <errno.h>
+#include <linux/bitfield.h>
+#include <linux/bitops.h>
+#include <linux/compat.h>
+#include <linux/delay.h>
+#include <linux/iopoll.h>
+#include <marvell_phy.h>
+#include <phy.h>
+
+#define MV_PHY_ALASKA_NBT_QUIRK_MASK	0xfffffffe
+#define MV_PHY_ALASKA_NBT_QUIRK_REV	(MARVELL_PHY_ID_88X3310 | 0xa)
+
+#define MV_VERSION(a, b, c, d) ((a) << 24 | (b) << 16 | (c) << 8 | (d))
+
+enum {
+	MV_PMA_FW_VER0		= 0xc011,
+	MV_PMA_FW_VER1		= 0xc012,
+	MV_PMA_21X0_PORT_CTRL	= 0xc04a,
+	MV_PMA_21X0_PORT_CTRL_SWRST				= BIT(15),
+	MV_PMA_21X0_PORT_CTRL_MACTYPE_MASK			= 0x7,
+	MV_PMA_21X0_PORT_CTRL_MACTYPE_USXGMII			= 0x0,
+	MV_PMA_2180_PORT_CTRL_MACTYPE_DXGMII			= 0x1,
+	MV_PMA_2180_PORT_CTRL_MACTYPE_QXGMII			= 0x2,
+	MV_PMA_21X0_PORT_CTRL_MACTYPE_5GBASER			= 0x4,
+	MV_PMA_21X0_PORT_CTRL_MACTYPE_5GBASER_NO_SGMII_AN	= 0x5,
+	MV_PMA_21X0_PORT_CTRL_MACTYPE_10GBASER_RATE_MATCH	= 0x6,
+	MV_PMA_BOOT		= 0xc050,
+	MV_PMA_BOOT_FATAL	= BIT(0),
+
+	MV_PCS_BASE_T		= 0x0000,
+	MV_PCS_BASE_R		= 0x1000,
+	MV_PCS_1000BASEX	= 0x2000,
+
+	MV_PCS_CSCR1		= 0x8000,
+	MV_PCS_CSCR1_ED_MASK	= 0x0300,
+	MV_PCS_CSCR1_ED_OFF	= 0x0000,
+	MV_PCS_CSCR1_ED_RX	= 0x0200,
+	MV_PCS_CSCR1_ED_NLP	= 0x0300,
+	MV_PCS_CSCR1_MDIX_MASK	= 0x0060,
+	MV_PCS_CSCR1_MDIX_MDI	= 0x0000,
+	MV_PCS_CSCR1_MDIX_MDIX	= 0x0020,
+	MV_PCS_CSCR1_MDIX_AUTO	= 0x0060,
+
+	MV_PCS_DSC1		= 0x8003,
+	MV_PCS_DSC1_ENABLE	= BIT(9),
+	MV_PCS_DSC1_10GBT	= 0x01c0,
+	MV_PCS_DSC1_1GBR	= 0x0038,
+	MV_PCS_DSC1_100BTX	= 0x0007,
+	MV_PCS_DSC2		= 0x8004,
+	MV_PCS_DSC2_2P5G	= 0xf000,
+	MV_PCS_DSC2_5G		= 0x0f00,
+
+	MV_PCS_CSSR1		= 0x8008,
+	MV_PCS_CSSR1_SPD1_MASK	= 0xc000,
+	MV_PCS_CSSR1_SPD1_SPD2	= 0xc000,
+	MV_PCS_CSSR1_SPD1_1000	= 0x8000,
+	MV_PCS_CSSR1_SPD1_100	= 0x4000,
+	MV_PCS_CSSR1_SPD1_10	= 0x0000,
+	MV_PCS_CSSR1_DUPLEX_FULL = BIT(13),
+	MV_PCS_CSSR1_RESOLVED	= BIT(11),
+	MV_PCS_CSSR1_MDIX	= BIT(6),
+	MV_PCS_CSSR1_SPD2_MASK	= 0x000c,
+	MV_PCS_CSSR1_SPD2_5000	= 0x0008,
+	MV_PCS_CSSR1_SPD2_2500	= 0x0004,
+	MV_PCS_CSSR1_SPD2_10000	= 0x0000,
+
+	/* Temperature read register (88E2110 only) */
+	MV_PCS_TEMP		= 0x8042,
+
+	/* Number of ports on the device */
+	MV_PCS_PORT_INFO	= 0xd00d,
+	MV_PCS_PORT_INFO_NPORTS_MASK	= 0x0380,
+	MV_PCS_PORT_INFO_NPORTS_SHIFT	= 7,
+
+	/* SerDes reinitialization 88E21X0 */
+	MV_AN_21X0_SERDES_CTRL2	= 0x800f,
+	MV_AN_21X0_SERDES_CTRL2_AUTO_INIT_DIS	= BIT(13),
+	MV_AN_21X0_SERDES_CTRL2_RUN_INIT	= BIT(15),
+
+	/* These registers appear at 0x800X and 0xa00X - the 0xa00X control
+	 * registers appear to set themselves to the 0x800X when AN is
+	 * restarted, but status registers appear readable from either.
+	 */
+	MV_AN_CTRL1000		= 0x8000, /* 1000base-T control register */
+	MV_AN_STAT1000		= 0x8001, /* 1000base-T status register */
+
+	/* Vendor2 MMD registers */
+	MV_V2_PORT_CTRL		= 0xf001,
+	MV_V2_PORT_CTRL_PWRDOWN					= BIT(11),
+	MV_V2_33X0_PORT_CTRL_SWRST				= BIT(15),
+	MV_V2_33X0_PORT_CTRL_MACTYPE_MASK			= 0x7,
+	MV_V2_33X0_PORT_CTRL_MACTYPE_RXAUI			= 0x0,
+	MV_V2_3310_PORT_CTRL_MACTYPE_XAUI_RATE_MATCH		= 0x1,
+	MV_V2_3340_PORT_CTRL_MACTYPE_RXAUI_NO_SGMII_AN		= 0x1,
+	MV_V2_33X0_PORT_CTRL_MACTYPE_RXAUI_RATE_MATCH		= 0x2,
+	MV_V2_3310_PORT_CTRL_MACTYPE_XAUI			= 0x3,
+	MV_V2_33X0_PORT_CTRL_MACTYPE_10GBASER			= 0x4,
+	MV_V2_33X0_PORT_CTRL_MACTYPE_10GBASER_NO_SGMII_AN	= 0x5,
+	MV_V2_33X0_PORT_CTRL_MACTYPE_10GBASER_RATE_MATCH	= 0x6,
+	MV_V2_33X0_PORT_CTRL_MACTYPE_USXGMII			= 0x7,
+	MV_V2_PORT_INTR_STS		= 0xf040,
+	MV_V2_PORT_INTR_MASK		= 0xf043,
+	MV_V2_PORT_INTR_STS_WOL_EN	= BIT(8),
+	MV_V2_MAGIC_PKT_WORD0		= 0xf06b,
+	MV_V2_MAGIC_PKT_WORD1		= 0xf06c,
+	MV_V2_MAGIC_PKT_WORD2		= 0xf06d,
+	/* Wake on LAN registers */
+	MV_V2_WOL_CTRL			= 0xf06e,
+	MV_V2_WOL_CTRL_CLEAR_STS	= BIT(15),
+	MV_V2_WOL_CTRL_MAGIC_PKT_EN	= BIT(0),
+	/* Temperature control/read registers (88X3310 only) */
+	MV_V2_TEMP_CTRL		= 0xf08a,
+	MV_V2_TEMP_CTRL_MASK	= 0xc000,
+	MV_V2_TEMP_CTRL_SAMPLE	= 0x0000,
+	MV_V2_TEMP_CTRL_DISABLE	= 0xc000,
+	MV_V2_TEMP		= 0xf08c,
+	MV_V2_TEMP_UNKNOWN	= 0x9600, /* unknown function */
+};
+
+struct mv3310_chip {
+	bool (*has_downshift)(struct phy_device *phydev);
+	int (*test_supported_interfaces)(struct phy_device *phydev);
+	int (*get_mactype)(struct phy_device *phydev);
+	int (*set_mactype)(struct phy_device *phydev, int mactype);
+	int (*select_mactype)(struct phy_device *phydev);
+	int (*init_interface)(struct phy_device *phydev, int mactype);
+};
+
+struct mv3310_priv {
+	DECLARE_BITMAP(supported_interfaces, PHY_INTERFACE_MODE_MAX);
+
+	u32 firmware_ver;
+	bool has_downshift;
+	bool rate_match;
+};
+
+static const struct mv3310_chip *to_mv3310_chip(struct phy_device *phydev)
+{
+	return (const struct mv3310_chip *)phydev->drv->data;
+}
+
+static int mv3310_power_down(struct phy_device *phydev)
+{
+	return phy_set_bits_mmd(phydev, MDIO_MMD_VEND2, MV_V2_PORT_CTRL,
+				MV_V2_PORT_CTRL_PWRDOWN);
+}
+
+static int mv3310_power_up(struct phy_device *phydev)
+{
+	struct mv3310_priv *priv = (struct mv3310_priv *)phydev->priv;
+	int ret;
+
+	ret = phy_clear_bits_mmd(phydev, MDIO_MMD_VEND2, MV_V2_PORT_CTRL,
+				 MV_V2_PORT_CTRL_PWRDOWN);
+
+	if (phydev->drv->uid != MARVELL_PHY_ID_88X3310 ||
+	    priv->firmware_ver < 0x00030000)
+		return ret;
+
+	return phy_set_bits_mmd(phydev, MDIO_MMD_VEND2, MV_V2_PORT_CTRL,
+				MV_V2_33X0_PORT_CTRL_SWRST);
+}
+
+static int mv3310_reset(struct phy_device *phydev, u32 unit)
+{
+	int val, err;
+
+	err = phy_modify_mmd(phydev, MDIO_MMD_PCS, unit + MDIO_CTRL1,
+			     MDIO_CTRL1_RESET, MDIO_CTRL1_RESET);
+	if (err < 0)
+		return err;
+
+	return phy_read_mmd_poll_timeout(phydev, MDIO_MMD_PCS,
+					 unit + MDIO_CTRL1, val,
+					 !(val & MDIO_CTRL1_RESET),
+					 5000, 100000, true);
+}
+
+static int mv3310_set_downshift(struct phy_device *phydev)
+{
+	struct mv3310_priv *priv = (struct mv3310_priv *)phydev->priv;
+	const u8 ds = 1;
+	u16 val;
+	int err;
+
+	if (!priv->has_downshift)
+		return -EOPNOTSUPP;
+
+	val = FIELD_PREP(MV_PCS_DSC2_2P5G, ds);
+	val |= FIELD_PREP(MV_PCS_DSC2_5G, ds);
+	err = phy_modify_mmd(phydev, MDIO_MMD_PCS, MV_PCS_DSC2,
+			     MV_PCS_DSC2_2P5G | MV_PCS_DSC2_5G, val);
+	if (err < 0)
+		return err;
+
+	val = MV_PCS_DSC1_ENABLE;
+	val |= FIELD_PREP(MV_PCS_DSC1_10GBT, ds);
+	val |= FIELD_PREP(MV_PCS_DSC1_1GBR, ds);
+	val |= FIELD_PREP(MV_PCS_DSC1_100BTX, ds);
+
+	return phy_modify_mmd(phydev, MDIO_MMD_PCS, MV_PCS_DSC1,
+			      MV_PCS_DSC1_ENABLE | MV_PCS_DSC1_10GBT |
+			      MV_PCS_DSC1_1GBR | MV_PCS_DSC1_100BTX, val);
+}
+
+static int mv3310_set_edpd(struct phy_device *phydev)
+{
+	int err;
+
+	err = phy_modify_mmd_changed(phydev, MDIO_MMD_PCS, MV_PCS_CSCR1,
+				     MV_PCS_CSCR1_ED_MASK,
+				     MV_PCS_CSCR1_ED_NLP);
+	if (err > 0)
+		err = mv3310_reset(phydev, MV_PCS_BASE_T);
+
+	return err;
+}
+
+static int mv3310_probe(struct phy_device *phydev)
+{
+	const struct mv3310_chip *chip = to_mv3310_chip(phydev);
+	struct mv3310_priv *priv;
+	u32 mmd_mask = MDIO_DEVS_PMAPMD | MDIO_DEVS_AN;
+	int ret;
+
+	if (!phydev->is_c45 ||
+	    (phydev->mmds & mmd_mask) != mmd_mask)
+		return -ENODEV;
+
+	ret = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, MV_PMA_BOOT);
+	if (ret < 0)
+		return ret;
+
+	if (ret & MV_PMA_BOOT_FATAL) {
+		dev_warn(phydev->dev,
+			 "PHY failed to boot firmware, status=%04x\n", ret);
+		return -ENODEV;
+	}
+
+	priv = devm_kzalloc(phydev->dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	phydev->priv = priv;
+
+	ret = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, MV_PMA_FW_VER0);
+	if (ret < 0)
+		return ret;
+
+	priv->firmware_ver = ret << 16;
+
+	ret = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, MV_PMA_FW_VER1);
+	if (ret < 0)
+		return ret;
+
+	priv->firmware_ver |= ret;
+
+	dev_info(phydev->dev, "Firmware version %u.%u.%u.%u\n",
+		 priv->firmware_ver >> 24, (priv->firmware_ver >> 16) & 255,
+		 (priv->firmware_ver >> 8) & 255, priv->firmware_ver & 255);
+
+	if (chip->has_downshift)
+		priv->has_downshift = chip->has_downshift(phydev);
+
+	/* Powering down the port when not in use saves about 600mW */
+	ret = mv3310_power_down(phydev);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+static int mv2110_get_mactype(struct phy_device *phydev)
+{
+	int mactype;
+
+	mactype = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, MV_PMA_21X0_PORT_CTRL);
+	if (mactype < 0)
+		return mactype;
+
+	return mactype & MV_PMA_21X0_PORT_CTRL_MACTYPE_MASK;
+}
+
+static int mv2110_set_mactype(struct phy_device *phydev, int mactype)
+{
+	int err, val;
+
+	mactype &= MV_PMA_21X0_PORT_CTRL_MACTYPE_MASK;
+	err = phy_modify_mmd(phydev, MDIO_MMD_PMAPMD, MV_PMA_21X0_PORT_CTRL,
+			     MV_PMA_21X0_PORT_CTRL_SWRST |
+			     MV_PMA_21X0_PORT_CTRL_MACTYPE_MASK,
+			     MV_PMA_21X0_PORT_CTRL_SWRST | mactype);
+	if (err)
+		return err;
+
+	err = phy_set_bits_mmd(phydev, MDIO_MMD_AN, MV_AN_21X0_SERDES_CTRL2,
+			       MV_AN_21X0_SERDES_CTRL2_AUTO_INIT_DIS |
+			       MV_AN_21X0_SERDES_CTRL2_RUN_INIT);
+	if (err)
+		return err;
+
+	err = phy_read_mmd_poll_timeout(phydev, MDIO_MMD_AN,
+					MV_AN_21X0_SERDES_CTRL2, val,
+					!(val &
+					  MV_AN_21X0_SERDES_CTRL2_RUN_INIT),
+					5000, 100000, true);
+	if (err)
+		return err;
+
+	return phy_clear_bits_mmd(phydev, MDIO_MMD_AN, MV_AN_21X0_SERDES_CTRL2,
+				  MV_AN_21X0_SERDES_CTRL2_AUTO_INIT_DIS);
+}
+
+static int mv2110_select_mactype(struct phy_device *phydev)
+{
+	if (phydev->interface == PHY_INTERFACE_MODE_USXGMII)
+		return MV_PMA_21X0_PORT_CTRL_MACTYPE_USXGMII;
+	else if (phydev->interface == PHY_INTERFACE_MODE_SGMII &&
+		 !(phydev->interface == PHY_INTERFACE_MODE_10GBASER))
+		return MV_PMA_21X0_PORT_CTRL_MACTYPE_5GBASER;
+	else if (phydev->interface == PHY_INTERFACE_MODE_10GBASER)
+		return MV_PMA_21X0_PORT_CTRL_MACTYPE_10GBASER_RATE_MATCH;
+	else
+		return -1;
+}
+
+static int mv3310_get_mactype(struct phy_device *phydev)
+{
+	int mactype;
+
+	mactype = phy_read_mmd(phydev, MDIO_MMD_VEND2, MV_V2_PORT_CTRL);
+	if (mactype < 0)
+		return mactype;
+
+	return mactype & MV_V2_33X0_PORT_CTRL_MACTYPE_MASK;
+}
+
+static int mv3310_set_mactype(struct phy_device *phydev, int mactype)
+{
+	int ret;
+
+	mactype &= MV_V2_33X0_PORT_CTRL_MACTYPE_MASK;
+	ret = phy_modify_mmd_changed(phydev, MDIO_MMD_VEND2, MV_V2_PORT_CTRL,
+				     MV_V2_33X0_PORT_CTRL_MACTYPE_MASK,
+				     mactype);
+	if (ret <= 0)
+		return ret;
+
+	return phy_set_bits_mmd(phydev, MDIO_MMD_VEND2, MV_V2_PORT_CTRL,
+				MV_V2_33X0_PORT_CTRL_SWRST);
+}
+
+static int mv3310_select_mactype(struct phy_device *phydev)
+{
+	if (phydev->interface == PHY_INTERFACE_MODE_USXGMII)
+		return MV_V2_33X0_PORT_CTRL_MACTYPE_USXGMII;
+	else if (phydev->interface == PHY_INTERFACE_MODE_SGMII &&
+		 phydev->interface == PHY_INTERFACE_MODE_10GBASER)
+		return MV_V2_33X0_PORT_CTRL_MACTYPE_10GBASER;
+	else if (phydev->interface == PHY_INTERFACE_MODE_SGMII &&
+		 phydev->interface == PHY_INTERFACE_MODE_RXAUI)
+		return MV_V2_33X0_PORT_CTRL_MACTYPE_RXAUI;
+	else if (phydev->interface == PHY_INTERFACE_MODE_SGMII &&
+		 phydev->interface == PHY_INTERFACE_MODE_XAUI)
+		return MV_V2_3310_PORT_CTRL_MACTYPE_XAUI;
+	else if (phydev->interface == PHY_INTERFACE_MODE_10GBASER)
+		return MV_V2_33X0_PORT_CTRL_MACTYPE_10GBASER_RATE_MATCH;
+	else if (phydev->interface == PHY_INTERFACE_MODE_RXAUI)
+		return MV_V2_33X0_PORT_CTRL_MACTYPE_RXAUI_RATE_MATCH;
+	else if (phydev->interface == PHY_INTERFACE_MODE_XAUI)
+		return MV_V2_3310_PORT_CTRL_MACTYPE_XAUI_RATE_MATCH;
+	else if (phydev->interface == PHY_INTERFACE_MODE_SGMII)
+		return MV_V2_33X0_PORT_CTRL_MACTYPE_10GBASER;
+	else
+		return -1;
+}
+
+static int mv2110_init_interface(struct phy_device *phydev, int mactype)
+{
+	struct mv3310_priv *priv = (struct mv3310_priv *)phydev->priv;
+
+	priv->rate_match = false;
+
+	if (mactype == MV_PMA_21X0_PORT_CTRL_MACTYPE_10GBASER_RATE_MATCH)
+		priv->rate_match = true;
+
+	return 0;
+}
+
+static int mv3310_init_interface(struct phy_device *phydev, int mactype)
+{
+	struct mv3310_priv *priv = (struct mv3310_priv *)phydev->priv;
+
+	priv->rate_match = false;
+
+	if (mactype != MV_V2_3340_PORT_CTRL_MACTYPE_RXAUI_NO_SGMII_AN)
+		return 0;
+
+	if (mactype == MV_V2_33X0_PORT_CTRL_MACTYPE_10GBASER_RATE_MATCH ||
+	    mactype == MV_V2_33X0_PORT_CTRL_MACTYPE_RXAUI_RATE_MATCH ||
+	    mactype == MV_V2_3310_PORT_CTRL_MACTYPE_XAUI_RATE_MATCH)
+		priv->rate_match = true;
+
+	return 0;
+}
+
+static int mv3310_config_init(struct phy_device *phydev)
+{
+	const struct mv3310_chip *chip = to_mv3310_chip(phydev);
+	int err, mactype;
+
+	/* Check that the PHY interface type is compatible */
+	err = chip->test_supported_interfaces(phydev);
+	if (err)
+		return err;
+
+	/* Power up so reset works */
+	err = mv3310_power_up(phydev);
+	if (err)
+		return err;
+
+	/* If host provided host supported interface modes, try to select the
+	 * best one
+	 */
+	mactype = chip->select_mactype(phydev);
+	if (mactype >= 0) {
+		dev_info(phydev->dev, "Changing MACTYPE to %i\n",
+			 mactype);
+		err = chip->set_mactype(phydev, mactype);
+		if (err)
+			return err;
+	}
+
+	mactype = chip->get_mactype(phydev);
+	if (mactype < 0)
+		return mactype;
+
+	err = chip->init_interface(phydev, mactype);
+	if (err) {
+		dev_err(phydev->dev, "MACTYPE configuration invalid\n");
+		return err;
+	}
+
+	/* Enable EDPD mode - saving 600mW */
+	err = mv3310_set_edpd(phydev);
+	if (err)
+		return err;
+
+	/* Allow downshift */
+	err = mv3310_set_downshift(phydev);
+	if (err && err != -EOPNOTSUPP)
+		return err;
+
+	return 0;
+}
+
+static int mv3310_config(struct phy_device *phydev)
+{
+	int err;
+
+	err = mv3310_probe(phydev);
+	if (!err)
+		err = mv3310_config_init(phydev);
+
+	return err;
+}
+
+static int mv3310_get_number_of_ports(struct phy_device *phydev)
+{
+	int ret;
+
+	ret = phy_read_mmd(phydev, MDIO_MMD_PCS, MV_PCS_PORT_INFO);
+	if (ret < 0)
+		return ret;
+
+	ret &= MV_PCS_PORT_INFO_NPORTS_MASK;
+	ret >>= MV_PCS_PORT_INFO_NPORTS_SHIFT;
+
+	return ret + 1;
+}
+
+static int mv3310_match_phy_device(struct phy_device *phydev)
+{
+	if ((phydev->phy_id & MARVELL_PHY_ID_MASK) != MARVELL_PHY_ID_88X3310)
+		return 0;
+
+	return mv3310_get_number_of_ports(phydev) == 1;
+}
+
+static int mv211x_match_phy_device(struct phy_device *phydev, bool has_5g)
+{
+	int val;
+
+	if ((phydev->phy_id & MARVELL_PHY_ID_MASK) != MARVELL_PHY_ID_88E2110)
+		return 0;
+
+	val = phy_read_mmd(phydev, MDIO_MMD_PCS, MDIO_SPEED);
+	if (val < 0)
+		return val;
+
+	return !!(val & MDIO_PCS_SPEED_5G) == has_5g;
+}
+
+static int mv2110_match_phy_device(struct phy_device *phydev)
+{
+	return mv211x_match_phy_device(phydev, true);
+}
+
+static bool mv3310_has_downshift(struct phy_device *phydev)
+{
+	struct mv3310_priv *priv = (struct mv3310_priv *)phydev->priv;
+
+	/* Fails to downshift with firmware older than v0.3.5.0 */
+	return priv->firmware_ver >= MV_VERSION(0, 3, 5, 0);
+}
+
+#define mv_test_bit(iface, phydev)	\
+	({ if ((phydev)->interface & (iface)) return 0; })
+
+static int mv3310_mv3340_test_supported_interfaces(struct phy_device *phydev)
+{
+	mv_test_bit(PHY_INTERFACE_MODE_SGMII, phydev);
+	mv_test_bit(PHY_INTERFACE_MODE_2500BASEX, phydev);
+	mv_test_bit(PHY_INTERFACE_MODE_5GBASER, phydev);
+	if (mv3310_match_phy_device(phydev))
+		mv_test_bit(PHY_INTERFACE_MODE_XAUI, phydev);
+	mv_test_bit(PHY_INTERFACE_MODE_RXAUI, phydev);
+	mv_test_bit(PHY_INTERFACE_MODE_10GBASER, phydev);
+	mv_test_bit(PHY_INTERFACE_MODE_USXGMII, phydev);
+	return -ENODEV;
+}
+
+static int mv2110_mv2111_test_supported_interfaces(struct phy_device *phydev)
+{
+	mv_test_bit(PHY_INTERFACE_MODE_SGMII, phydev);
+	mv_test_bit(PHY_INTERFACE_MODE_2500BASEX, phydev);
+	if (mv2110_match_phy_device(phydev))
+		mv_test_bit(PHY_INTERFACE_MODE_5GBASER, phydev);
+	mv_test_bit(PHY_INTERFACE_MODE_10GBASER, phydev);
+	mv_test_bit(PHY_INTERFACE_MODE_USXGMII, phydev);
+	return -ENODEV;
+}
+
+static const struct mv3310_chip mv3310_mv3340_type = {
+	.has_downshift = mv3310_has_downshift,
+	.test_supported_interfaces = mv3310_mv3340_test_supported_interfaces,
+	.get_mactype = mv3310_get_mactype,
+	.set_mactype = mv3310_set_mactype,
+	.select_mactype = mv3310_select_mactype,
+	.init_interface = mv3310_init_interface,
+};
+
+static const struct mv3310_chip mv2110_mv2111_type = {
+	.test_supported_interfaces = mv2110_mv2111_test_supported_interfaces,
+	.get_mactype = mv2110_get_mactype,
+	.set_mactype = mv2110_set_mactype,
+	.select_mactype = mv2110_select_mactype,
+	.init_interface = mv2110_init_interface,
+};
+
+U_BOOT_PHY_DRIVER(mv88e3310_mv88e3340) = {
+	.name		= "mv88x3310",
+	.uid		= MARVELL_PHY_ID_88X3310,
+	.mask		= MARVELL_PHY_ID_MASK,
+	.features	= PHY_10G_FEATURES,
+	.data		= (ulong)&mv3310_mv3340_type,
+	.config		= mv3310_config,
+};
+
+U_BOOT_PHY_DRIVER(mv88e2110_mv88e2111) = {
+	.name		= "mv88e2110",
+	.uid		= MARVELL_PHY_ID_88E2110,
+	.mask		= MARVELL_PHY_ID_MASK,
+	.features	= PHY_10G_FEATURES,
+	.data		= (ulong)&mv2110_mv2111_type,
+	.config		= mv3310_config,
+};
-- 
2.39.2


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

* Re: [PATCH 1/5] net: phy: marvell: Import and use marvell_phy.h from Linux
  2023-03-19 17:08 [PATCH 1/5] net: phy: marvell: Import and use marvell_phy.h from Linux Marek Vasut
                   ` (3 preceding siblings ...)
  2023-03-19 17:08 ` [PATCH 5/5] net: phy: marvell10g: Adapt Marvell 10G PHY driver " Marek Vasut
@ 2023-04-01 18:49 ` Ramon Fried
  4 siblings, 0 replies; 10+ messages in thread
From: Ramon Fried @ 2023-04-01 18:49 UTC (permalink / raw)
  To: Marek Vasut
  Cc: u-boot, Ariel D'Alessandro, Marek Behún,
	Joe Hershberger, Michael Trimarchi, Nate Drude, Simon Glass,
	Stefan Roese, Tim Harvey, Vladimir Oltean

On Sun, Mar 19, 2023 at 7:08 PM Marek Vasut
<marek.vasut+renesas@mailbox.org> wrote:
>
> Import marvell_phy.h from Linux 5.14.y as of commit
> a5de4be0aaaa6 ("net: phy: marvell10g: fix differentiation of 88X3310 from 88X3340")
> and use it in marvell PHY driver instead of current ad-hoc macros.
> Two of the PHY IDs are unknown to Linux, 88E1149S and 88E1680, for
> those two, only sync the length of the hexadecimal number to 8 digits.
>
> No functional change.
>
> Signed-off-by: Marek Vasut <marek.vasut+renesas@mailbox.org>
> ---
> Cc: "Ariel D'Alessandro" <ariel.dalessandro@collabora.com>
> Cc: "Marek Behún" <kabel@kernel.org>
> Cc: Joe Hershberger <joe.hershberger@ni.com>
> Cc: Marek Vasut <marek.vasut+renesas@mailbox.org>
> Cc: Michael Trimarchi <michael@amarulasolutions.com>
> Cc: Nate Drude <nate.d@variscite.com>
> Cc: Ramon Fried <rfried.dev@gmail.com>
> Cc: Simon Glass <sjg@chromium.org>
> Cc: Stefan Roese <sr@denx.de>
> Cc: Tim Harvey <tharvey@gateworks.com>
> Cc: Vladimir Oltean <vladimir.oltean@nxp.com>
> ---
>  drivers/net/phy/marvell.c | 45 +++++++++++++++++++------------------
>  include/marvell_phy.h     | 47 +++++++++++++++++++++++++++++++++++++++
>  2 files changed, 70 insertions(+), 22 deletions(-)
>  create mode 100644 include/marvell_phy.h
>
> diff --git a/drivers/net/phy/marvell.c b/drivers/net/phy/marvell.c
> index 8992be6e89e..0a90f710dfe 100644
> --- a/drivers/net/phy/marvell.c
> +++ b/drivers/net/phy/marvell.c
> @@ -7,6 +7,7 @@
>   */
>  #include <common.h>
>  #include <errno.h>
> +#include <marvell_phy.h>
>  #include <phy.h>
>  #include <linux/bitops.h>
>  #include <linux/delay.h>
> @@ -695,8 +696,8 @@ static int m88e1680_config(struct phy_device *phydev)
>
>  U_BOOT_PHY_DRIVER(m88e1011s) = {
>         .name = "Marvell 88E1011S",
> -       .uid = 0x1410c60,
> -       .mask = 0xffffff0,
> +       .uid = MARVELL_PHY_ID_88E1101,
> +       .mask = MARVELL_PHY_ID_MASK,
>         .features = PHY_GBIT_FEATURES,
>         .config = &m88e1011s_config,
>         .startup = &m88e1011s_startup,
> @@ -705,8 +706,8 @@ U_BOOT_PHY_DRIVER(m88e1011s) = {
>
>  U_BOOT_PHY_DRIVER(m88e1111s) = {
>         .name = "Marvell 88E1111S",
> -       .uid = 0x1410cc0,
> -       .mask = 0xffffff0,
> +       .uid = MARVELL_PHY_ID_88E1111,
> +       .mask = MARVELL_PHY_ID_MASK,
>         .features = PHY_GBIT_FEATURES,
>         .config = &m88e1111s_config,
>         .startup = &m88e1011s_startup,
> @@ -715,8 +716,8 @@ U_BOOT_PHY_DRIVER(m88e1111s) = {
>
>  U_BOOT_PHY_DRIVER(m88e1118) = {
>         .name = "Marvell 88E1118",
> -       .uid = 0x1410e10,
> -       .mask = 0xffffff0,
> +       .uid = MARVELL_PHY_ID_88E1118,
> +       .mask = MARVELL_PHY_ID_MASK,
>         .features = PHY_GBIT_FEATURES,
>         .config = &m88e1118_config,
>         .startup = &m88e1118_startup,
> @@ -725,8 +726,8 @@ U_BOOT_PHY_DRIVER(m88e1118) = {
>
>  U_BOOT_PHY_DRIVER(m88e1118r) = {
>         .name = "Marvell 88E1118R",
> -       .uid = 0x1410e40,
> -       .mask = 0xffffff0,
> +       .uid = MARVELL_PHY_ID_88E1116R,
> +       .mask = MARVELL_PHY_ID_MASK,
>         .features = PHY_GBIT_FEATURES,
>         .config = &m88e1118_config,
>         .startup = &m88e1118_startup,
> @@ -735,8 +736,8 @@ U_BOOT_PHY_DRIVER(m88e1118r) = {
>
>  U_BOOT_PHY_DRIVER(m88e1121r) = {
>         .name = "Marvell 88E1121R",
> -       .uid = 0x1410cb0,
> -       .mask = 0xffffff0,
> +       .uid = MARVELL_PHY_ID_88E1121R,
> +       .mask = MARVELL_PHY_ID_MASK,
>         .features = PHY_GBIT_FEATURES,
>         .config = &m88e1121_config,
>         .startup = &genphy_startup,
> @@ -745,8 +746,8 @@ U_BOOT_PHY_DRIVER(m88e1121r) = {
>
>  U_BOOT_PHY_DRIVER(m88e1145) = {
>         .name = "Marvell 88E1145",
> -       .uid = 0x1410cd0,
> -       .mask = 0xffffff0,
> +       .uid = MARVELL_PHY_ID_88E1145,
> +       .mask = MARVELL_PHY_ID_MASK,
>         .features = PHY_GBIT_FEATURES,
>         .config = &m88e1145_config,
>         .startup = &m88e1145_startup,
> @@ -755,8 +756,8 @@ U_BOOT_PHY_DRIVER(m88e1145) = {
>
>  U_BOOT_PHY_DRIVER(m88e1149s) = {
>         .name = "Marvell 88E1149S",
> -       .uid = 0x1410ca0,
> -       .mask = 0xffffff0,
> +       .uid = 0x01410ca0,
> +       .mask = MARVELL_PHY_ID_MASK,
>         .features = PHY_GBIT_FEATURES,
>         .config = &m88e1149_config,
>         .startup = &m88e1011s_startup,
> @@ -765,8 +766,8 @@ U_BOOT_PHY_DRIVER(m88e1149s) = {
>
>  U_BOOT_PHY_DRIVER(m88e1240) = {
>         .name = "Marvell 88E1240",
> -       .uid = 0x1410e30,
> -       .mask = 0xffffff0,
> +       .uid = MARVELL_PHY_ID_88E1240,
> +       .mask = MARVELL_PHY_ID_MASK,
>         .features = PHY_GBIT_FEATURES,
>         .config = &m88e1240_config,
>         .startup = &m88e1011s_startup,
> @@ -775,8 +776,8 @@ U_BOOT_PHY_DRIVER(m88e1240) = {
>
>  U_BOOT_PHY_DRIVER(m88e151x) = {
>         .name = "Marvell 88E151x",
> -       .uid = 0x1410dd0,
> -       .mask = 0xffffff0,
> +       .uid = MARVELL_PHY_ID_88E1510,
> +       .mask = MARVELL_PHY_ID_MASK,
>         .features = PHY_GBIT_FEATURES,
>         .config = &m88e151x_config,
>         .startup = &m88e1011s_startup,
> @@ -787,8 +788,8 @@ U_BOOT_PHY_DRIVER(m88e151x) = {
>
>  U_BOOT_PHY_DRIVER(m88e1310) = {
>         .name = "Marvell 88E1310",
> -       .uid = 0x01410e90,
> -       .mask = 0xffffff0,
> +       .uid = MARVELL_PHY_ID_88E1318S,
> +       .mask = MARVELL_PHY_ID_MASK,
>         .features = PHY_GBIT_FEATURES,
>         .config = &m88e1310_config,
>         .startup = &m88e1011s_startup,
> @@ -797,8 +798,8 @@ U_BOOT_PHY_DRIVER(m88e1310) = {
>
>  U_BOOT_PHY_DRIVER(m88e1680) = {
>         .name = "Marvell 88E1680",
> -       .uid = 0x1410ed0,
> -       .mask = 0xffffff0,
> +       .uid = 0x01410ed0,
> +       .mask = MARVELL_PHY_ID_MASK,
>         .features = PHY_GBIT_FEATURES,
>         .config = &m88e1680_config,
>         .startup = &genphy_startup,
> diff --git a/include/marvell_phy.h b/include/marvell_phy.h
> new file mode 100644
> index 00000000000..0f06c2287b5
> --- /dev/null
> +++ b/include/marvell_phy.h
> @@ -0,0 +1,47 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +#ifndef _MARVELL_PHY_H
> +#define _MARVELL_PHY_H
> +
> +/* Mask used for ID comparisons */
> +#define MARVELL_PHY_ID_MASK            0xfffffff0
> +
> +/* Known PHY IDs */
> +#define MARVELL_PHY_ID_88E1101         0x01410c60
> +#define MARVELL_PHY_ID_88E1112         0x01410c90
> +#define MARVELL_PHY_ID_88E1111         0x01410cc0
> +#define MARVELL_PHY_ID_88E1118         0x01410e10
> +#define MARVELL_PHY_ID_88E1121R                0x01410cb0
> +#define MARVELL_PHY_ID_88E1145         0x01410cd0
> +#define MARVELL_PHY_ID_88E1149R                0x01410e50
> +#define MARVELL_PHY_ID_88E1240         0x01410e30
> +#define MARVELL_PHY_ID_88E1318S                0x01410e90
> +#define MARVELL_PHY_ID_88E1340S                0x01410dc0
> +#define MARVELL_PHY_ID_88E1116R                0x01410e40
> +#define MARVELL_PHY_ID_88E1510         0x01410dd0
> +#define MARVELL_PHY_ID_88E1540         0x01410eb0
> +#define MARVELL_PHY_ID_88E1545         0x01410ea0
> +#define MARVELL_PHY_ID_88E1548P                0x01410ec0
> +#define MARVELL_PHY_ID_88E3016         0x01410e60
> +#define MARVELL_PHY_ID_88X3310         0x002b09a0
> +#define MARVELL_PHY_ID_88E2110         0x002b09b0
> +#define MARVELL_PHY_ID_88X2222         0x01410f10
> +
> +/* Marvel 88E1111 in Finisar SFP module with modified PHY ID */
> +#define MARVELL_PHY_ID_88E1111_FINISAR 0x01ff0cc0
> +
> +/* These Ethernet switch families contain embedded PHYs, but they do
> + * not have a model ID. So the switch driver traps reads to the ID2
> + * register and returns the switch family ID
> + */
> +#define MARVELL_PHY_ID_88E6341_FAMILY  0x01410f41
> +#define MARVELL_PHY_ID_88E6390_FAMILY  0x01410f90
> +#define MARVELL_PHY_ID_88E6393_FAMILY  0x002b0b9b
> +
> +#define MARVELL_PHY_FAMILY_ID(id)      ((id) >> 4)
> +
> +/* struct phy_device dev_flags definitions */
> +#define MARVELL_PHY_M1145_FLAGS_RESISTANCE     0x00000001
> +#define MARVELL_PHY_M1118_DNS323_LEDS          0x00000002
> +#define MARVELL_PHY_LED0_LINK_LED1_ACTIVE      0x00000004
> +
> +#endif /* _MARVELL_PHY_H */
> --
> 2.39.2
>
Reviewed-by: Ramon Fried <rfried.dev@gmail.com>

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

* Re: [PATCH 2/5] net: phy: Add phy_modify_mmd() and phy_modify_mmd_changed() from Linux
  2023-03-19 17:08 ` [PATCH 2/5] net: phy: Add phy_modify_mmd() and phy_modify_mmd_changed() " Marek Vasut
@ 2023-04-01 18:49   ` Ramon Fried
  0 siblings, 0 replies; 10+ messages in thread
From: Ramon Fried @ 2023-04-01 18:49 UTC (permalink / raw)
  To: Marek Vasut
  Cc: u-boot, Ariel D'Alessandro, Marek Behún,
	Joe Hershberger, Michael Trimarchi, Nate Drude, Simon Glass,
	Stefan Roese, Tim Harvey, Vladimir Oltean

On Sun, Mar 19, 2023 at 7:08 PM Marek Vasut
<marek.vasut+renesas@mailbox.org> wrote:
>
> Add phy_modify_mmd()/phy_modify_mmd_changed() from Linux 5.1.y as of commit
> b8554d4f7288f ("net: phy: add register modifying helpers returning 1 on change")
> This is used by the upcoming Marvell 10G PHY driver.
>
> Signed-off-by: Marek Vasut <marek.vasut+renesas@mailbox.org>
> ---
> Cc: "Ariel D'Alessandro" <ariel.dalessandro@collabora.com>
> Cc: "Marek Behún" <kabel@kernel.org>
> Cc: Joe Hershberger <joe.hershberger@ni.com>
> Cc: Marek Vasut <marek.vasut+renesas@mailbox.org>
> Cc: Michael Trimarchi <michael@amarulasolutions.com>
> Cc: Nate Drude <nate.d@variscite.com>
> Cc: Ramon Fried <rfried.dev@gmail.com>
> Cc: Simon Glass <sjg@chromium.org>
> Cc: Stefan Roese <sr@denx.de>
> Cc: Tim Harvey <tharvey@gateworks.com>
> Cc: Vladimir Oltean <vladimir.oltean@nxp.com>
> ---
>  drivers/net/phy/phy.c | 54 +++++++++++++++++++++++++++++++++++++++++++
>  include/phy.h         |  4 ++++
>  2 files changed, 58 insertions(+)
>
> diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c
> index f720d0a7920..0eeb0cb3a85 100644
> --- a/drivers/net/phy/phy.c
> +++ b/drivers/net/phy/phy.c
> @@ -1158,6 +1158,60 @@ int phy_clear_bits_mmd(struct phy_device *phydev, int devad, u32 regnum, u16 val
>         return 0;
>  }
>
> +/**
> + * phy_modify_mmd_changed - Function for modifying a register on MMD
> + * @phydev: the phy_device struct
> + * @devad: the MMD containing register to modify
> + * @regnum: register number to modify
> + * @mask: bit mask of bits to clear
> + * @set: new value of bits set in mask to write to @regnum
> + *
> + * NOTE: MUST NOT be called from interrupt context,
> + * because the bus read/write functions may wait for an interrupt
> + * to conclude the operation.
> + *
> + * Returns negative errno, 0 if there was no change, and 1 in case of change
> + */
> +int phy_modify_mmd_changed(struct phy_device *phydev, int devad, u32 regnum,
> +                          u16 mask, u16 set)
> +{
> +       int new, ret;
> +
> +       ret = phy_read_mmd(phydev, devad, regnum);
> +       if (ret < 0)
> +               return ret;
> +
> +       new = (ret & ~mask) | set;
> +       if (new == ret)
> +               return 0;
> +
> +       ret = phy_write_mmd(phydev, devad, regnum, new);
> +
> +       return ret < 0 ? ret : 1;
> +}
> +
> +/**
> + * phy_modify_mmd - Convenience function for modifying a register on MMD
> + * @phydev: the phy_device struct
> + * @devad: the MMD containing register to modify
> + * @regnum: register number to modify
> + * @mask: bit mask of bits to clear
> + * @set: new value of bits set in mask to write to @regnum
> + *
> + * NOTE: MUST NOT be called from interrupt context,
> + * because the bus read/write functions may wait for an interrupt
> + * to conclude the operation.
> + */
> +int phy_modify_mmd(struct phy_device *phydev, int devad, u32 regnum,
> +                  u16 mask, u16 set)
> +{
> +       int ret;
> +
> +       ret = phy_modify_mmd_changed(phydev, devad, regnum, mask, set);
> +
> +       return ret < 0 ? ret : 0;
> +}
> +
>  bool phy_interface_is_ncsi(void)
>  {
>  #ifdef CONFIG_PHY_NCSI
> diff --git a/include/phy.h b/include/phy.h
> index 4a9de461152..34675b2c9c0 100644
> --- a/include/phy.h
> +++ b/include/phy.h
> @@ -289,6 +289,10 @@ int phy_read_mmd(struct phy_device *phydev, int devad, int regnum);
>  int phy_write_mmd(struct phy_device *phydev, int devad, int regnum, u16 val);
>  int phy_set_bits_mmd(struct phy_device *phydev, int devad, u32 regnum, u16 val);
>  int phy_clear_bits_mmd(struct phy_device *phydev, int devad, u32 regnum, u16 val);
> +int phy_modify_mmd_changed(struct phy_device *phydev, int devad, u32 regnum,
> +                          u16 mask, u16 set);
> +int phy_modify_mmd(struct phy_device *phydev, int devad, u32 regnum,
> +                  u16 mask, u16 set);
>
>  int phy_startup(struct phy_device *phydev);
>  int phy_config(struct phy_device *phydev);
> --
> 2.39.2
>
Reviewed-by: Ramon Fried <rfried.dev@gmail.com>

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

* Re: [PATCH 3/5] net: phy: Add phy_read_mmd_poll_timeout() from Linux
  2023-03-19 17:08 ` [PATCH 3/5] net: phy: Add phy_read_mmd_poll_timeout() " Marek Vasut
@ 2023-04-01 18:50   ` Ramon Fried
  0 siblings, 0 replies; 10+ messages in thread
From: Ramon Fried @ 2023-04-01 18:50 UTC (permalink / raw)
  To: Marek Vasut
  Cc: u-boot, Ariel D'Alessandro, Marek Behún,
	Joe Hershberger, Michael Trimarchi, Nate Drude, Simon Glass,
	Stefan Roese, Tim Harvey, Vladimir Oltean

On Sun, Mar 19, 2023 at 7:08 PM Marek Vasut
<marek.vasut+renesas@mailbox.org> wrote:
>
> Add phy_read_mmd_poll_timeout() from Linux 5.7.y as of commit
> bd971ff0b7392 ("net: phy: introduce phy_read_mmd_poll_timeout macro")
> This is used by the upcoming Marvell 10G PHY driver.
>
> Signed-off-by: Marek Vasut <marek.vasut+renesas@mailbox.org>
> ---
> Cc: "Ariel D'Alessandro" <ariel.dalessandro@collabora.com>
> Cc: "Marek Behún" <kabel@kernel.org>
> Cc: Joe Hershberger <joe.hershberger@ni.com>
> Cc: Marek Vasut <marek.vasut+renesas@mailbox.org>
> Cc: Michael Trimarchi <michael@amarulasolutions.com>
> Cc: Nate Drude <nate.d@variscite.com>
> Cc: Ramon Fried <rfried.dev@gmail.com>
> Cc: Simon Glass <sjg@chromium.org>
> Cc: Stefan Roese <sr@denx.de>
> Cc: Tim Harvey <tharvey@gateworks.com>
> Cc: Vladimir Oltean <vladimir.oltean@nxp.com>
> ---
>  include/phy.h | 31 +++++++++++++++++++++++++++++++
>  1 file changed, 31 insertions(+)
>
> diff --git a/include/phy.h b/include/phy.h
> index 34675b2c9c0..a837fed7235 100644
> --- a/include/phy.h
> +++ b/include/phy.h
> @@ -282,6 +282,37 @@ static inline ofnode phy_get_ofnode(struct phy_device *phydev)
>                 return dev_ofnode(phydev->dev);
>  }
>
> +/**
> + * phy_read_mmd_poll_timeout - Periodically poll a PHY register until a
> + *                             condition is met or a timeout occurs
> + *
> + * @phydev: The phy_device struct
> + * @devaddr: The MMD to read from
> + * @regnum: The register on the MMD to read
> + * @val: Variable to read the register into
> + * @cond: Break condition (usually involving @val)
> + * @sleep_us: Maximum time to sleep between reads in us (0
> + *            tight-loops).  Should be less than ~20ms since usleep_range
> + *            is used (see Documentation/timers/timers-howto.rst).
> + * @timeout_us: Timeout in us, 0 means never timeout
> + * @sleep_before_read: if it is true, sleep @sleep_us before read.
> + * Returns 0 on success and -ETIMEDOUT upon a timeout. In either
> + * case, the last read value at @args is stored in @val. Must not
> + * be called from atomic context if sleep_us or timeout_us are used.
> + */
> +#define phy_read_mmd_poll_timeout(phydev, devaddr, regnum, val, cond, \
> +                                 sleep_us, timeout_us, sleep_before_read) \
> +({ \
> +       int __ret = read_poll_timeout(phy_read_mmd, val, (cond) || val < 0, \
> +                                 sleep_us, timeout_us, \
> +                                 phydev, devaddr, regnum); \
> +       if (val <  0) \
> +               __ret = val; \
> +       if (__ret) \
> +               dev_err(phydev->dev, "%s failed: %d\n", __func__, __ret); \
> +       __ret; \
> +})
> +
>  int phy_read(struct phy_device *phydev, int devad, int regnum);
>  int phy_write(struct phy_device *phydev, int devad, int regnum, u16 val);
>  void phy_mmd_start_indirect(struct phy_device *phydev, int devad, int regnum);
> --
> 2.39.2
>
Reviewed-by: Ramon Fried <rfried.dev@gmail.com>

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

* Re: [PATCH 4/5] net: phy: Add MDIO PCS 2.5G and 5G speed macros from Linux
  2023-03-19 17:08 ` [PATCH 4/5] net: phy: Add MDIO PCS 2.5G and 5G speed macros " Marek Vasut
@ 2023-04-01 18:50   ` Ramon Fried
  0 siblings, 0 replies; 10+ messages in thread
From: Ramon Fried @ 2023-04-01 18:50 UTC (permalink / raw)
  To: Marek Vasut
  Cc: u-boot, Ariel D'Alessandro, Marek Behún,
	Joe Hershberger, Michael Trimarchi, Nate Drude, Simon Glass,
	Stefan Roese, Tim Harvey, Vladimir Oltean

On Sun, Mar 19, 2023 at 7:08 PM Marek Vasut
<marek.vasut+renesas@mailbox.org> wrote:
>
> Add MDIO PCS 2.5G and 5G speed macros from Linux 5.1.y as of commit
> 7fd8afa8933a0 ("net: phy: Add generic support for 2.5GBaseT and 5GBaseT")
> This is used by the upcoming Marvell 10G PHY driver.
>
> Signed-off-by: Marek Vasut <marek.vasut+renesas@mailbox.org>
> ---
> Cc: "Ariel D'Alessandro" <ariel.dalessandro@collabora.com>
> Cc: "Marek Behún" <kabel@kernel.org>
> Cc: Joe Hershberger <joe.hershberger@ni.com>
> Cc: Marek Vasut <marek.vasut+renesas@mailbox.org>
> Cc: Michael Trimarchi <michael@amarulasolutions.com>
> Cc: Nate Drude <nate.d@variscite.com>
> Cc: Ramon Fried <rfried.dev@gmail.com>
> Cc: Simon Glass <sjg@chromium.org>
> Cc: Stefan Roese <sr@denx.de>
> Cc: Tim Harvey <tharvey@gateworks.com>
> Cc: Vladimir Oltean <vladimir.oltean@nxp.com>
> ---
>  include/linux/mdio.h | 18 ++++++++++++++++++
>  1 file changed, 18 insertions(+)
>
> diff --git a/include/linux/mdio.h b/include/linux/mdio.h
> index 6e821d906fb..b7c845155e4 100644
> --- a/include/linux/mdio.h
> +++ b/include/linux/mdio.h
> @@ -44,6 +44,7 @@
>  #define MDIO_AN_ADVERTISE      16      /* AN advertising (base page) */
>  #define MDIO_AN_LPA            19      /* AN LP abilities (base page) */
>  #define MDIO_PCS_EEE_ABLE      20      /* EEE Capability register */
> +#define MDIO_PMA_NG_EXTABLE    21      /* 2.5G/5G PMA/PMD extended ability */
>  #define MDIO_PCS_EEE_WK_ERR    22      /* EEE wake error counter */
>  #define MDIO_PHYXS_LNSTAT      24      /* PHY XGXS lane state */
>  #define MDIO_AN_EEE_ADV                60      /* EEE advertisement */
> @@ -91,6 +92,10 @@
>  #define MDIO_CTRL1_SPEED10G            (MDIO_CTRL1_SPEEDSELEXT | 0x00)
>  /* 10PASS-TS/2BASE-TL */
>  #define MDIO_CTRL1_SPEED10P2B          (MDIO_CTRL1_SPEEDSELEXT | 0x04)
> +/* 2.5 Gb/s */
> +#define MDIO_CTRL1_SPEED2_5G           (MDIO_CTRL1_SPEEDSELEXT | 0x18)
> +/* 5 Gb/s */
> +#define MDIO_CTRL1_SPEED5G             (MDIO_CTRL1_SPEEDSELEXT | 0x1c)
>
>  /* Status register 1. */
>  #define MDIO_STAT1_LPOWERABLE          0x0002  /* Low-power ability */
> @@ -111,6 +116,8 @@
>  #define MDIO_PMA_SPEED_100             0x0020  /* 100M capable */
>  #define MDIO_PMA_SPEED_10              0x0040  /* 10M capable */
>  #define MDIO_PCS_SPEED_10P2B           0x0002  /* 10PASS-TS/2BASE-TL capable */
> +#define MDIO_PCS_SPEED_2_5G            0x0040  /* 2.5G capable */
> +#define MDIO_PCS_SPEED_5G              0x0080  /* 5G capable */
>
>  /* Device present registers. */
>  #define MDIO_DEVS_PRESENT(devad)       (1 << (devad))
> @@ -150,6 +157,8 @@
>  #define MDIO_PMA_CTRL2_1000BKX         0x000d  /* 1000BASE-KX type */
>  #define MDIO_PMA_CTRL2_100BTX          0x000e  /* 100BASE-TX type */
>  #define MDIO_PMA_CTRL2_10BT            0x000f  /* 10BASE-T type */
> +#define MDIO_PMA_CTRL2_2_5GBT          0x0030  /* 2.5GBaseT type */
> +#define MDIO_PMA_CTRL2_5GBT            0x0031  /* 5GBaseT type */
>  #define MDIO_PCS_CTRL2_TYPE            0x0003  /* PCS type selection */
>  #define MDIO_PCS_CTRL2_10GBR           0x0000  /* 10GBASE-R type */
>  #define MDIO_PCS_CTRL2_10GBX           0x0001  /* 10GBASE-X type */
> @@ -203,6 +212,7 @@
>  #define MDIO_PMA_EXTABLE_1000BKX       0x0040  /* 1000BASE-KX ability */
>  #define MDIO_PMA_EXTABLE_100BTX                0x0080  /* 100BASE-TX ability */
>  #define MDIO_PMA_EXTABLE_10BT          0x0100  /* 10BASE-T ability */
> +#define MDIO_PMA_EXTABLE_NBT           0x4000  /* 2.5/5GBASE-T ability */
>
>  /* PHY XGXS lane state register. */
>  #define MDIO_PHYXS_LNSTAT_SYNC0                0x0001
> @@ -239,9 +249,13 @@
>  #define MDIO_PCS_10GBRT_STAT2_BER      0x3f00
>
>  /* AN 10GBASE-T control register. */
> +#define MDIO_AN_10GBT_CTRL_ADV2_5G     0x0080  /* Advertise 2.5GBASE-T */
> +#define MDIO_AN_10GBT_CTRL_ADV5G       0x0100  /* Advertise 5GBASE-T */
>  #define MDIO_AN_10GBT_CTRL_ADV10G      0x1000  /* Advertise 10GBASE-T */
>
>  /* AN 10GBASE-T status register. */
> +#define MDIO_AN_10GBT_STAT_LP2_5G      0x0020  /* LP is 2.5GBT capable */
> +#define MDIO_AN_10GBT_STAT_LP5G                0x0040  /* LP is 5GBT capable */
>  #define MDIO_AN_10GBT_STAT_LPTRR       0x0200  /* LP training reset req. */
>  #define MDIO_AN_10GBT_STAT_LPLTABLE    0x0400  /* LP loop timing ability */
>  #define MDIO_AN_10GBT_STAT_LP10G       0x0800  /* LP is 10GBT capable */
> @@ -270,6 +284,10 @@
>  #define MDIO_EEE_10GKX4                0x0020  /* 10G KX4 EEE cap */
>  #define MDIO_EEE_10GKR         0x0040  /* 10G KR EEE cap */
>
> +/* 2.5G/5G Extended abilities register. */
> +#define MDIO_PMA_NG_EXTABLE_2_5GBT     0x0001  /* 2.5GBASET ability */
> +#define MDIO_PMA_NG_EXTABLE_5GBT       0x0002  /* 5GBASET ability */
> +
>  /* LASI RX_ALARM control/status registers. */
>  #define MDIO_PMA_LASI_RX_PHYXSLFLT     0x0001  /* PHY XS RX local fault */
>  #define MDIO_PMA_LASI_RX_PCSLFLT       0x0008  /* PCS RX local fault */
> --
> 2.39.2
>
Reviewed-by: Ramon Fried <rfried.dev@gmail.com>

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

* Re: [PATCH 5/5] net: phy: marvell10g: Adapt Marvell 10G PHY driver from Linux
  2023-03-19 17:08 ` [PATCH 5/5] net: phy: marvell10g: Adapt Marvell 10G PHY driver " Marek Vasut
@ 2023-04-01 18:51   ` Ramon Fried
  0 siblings, 0 replies; 10+ messages in thread
From: Ramon Fried @ 2023-04-01 18:51 UTC (permalink / raw)
  To: Marek Vasut
  Cc: u-boot, Ariel D'Alessandro, Marek Behún,
	Joe Hershberger, Michael Trimarchi, Nate Drude, Simon Glass,
	Stefan Roese, Tim Harvey, Vladimir Oltean

On Sun, Mar 19, 2023 at 7:08 PM Marek Vasut
<marek.vasut+renesas@mailbox.org> wrote:
>
> Pull Marvell 10G PHY driver from Linux 6.1.y as of commit
> d6d29292640d3 ("net: phy: marvell10g: select host interface configuration")
> and heavily adapt to match U-Boot PHY framework. Support for
> hwmon is removed as is much other functionality which could
> not be tested, this results in much simpler driver which can
> only bring the PHY up and set MAC type.
>
> Signed-off-by: Marek Vasut <marek.vasut+renesas@mailbox.org>
> ---
> Cc: "Ariel D'Alessandro" <ariel.dalessandro@collabora.com>
> Cc: "Marek Behún" <kabel@kernel.org>
> Cc: Joe Hershberger <joe.hershberger@ni.com>
> Cc: Marek Vasut <marek.vasut+renesas@mailbox.org>
> Cc: Michael Trimarchi <michael@amarulasolutions.com>
> Cc: Nate Drude <nate.d@variscite.com>
> Cc: Ramon Fried <rfried.dev@gmail.com>
> Cc: Simon Glass <sjg@chromium.org>
> Cc: Stefan Roese <sr@denx.de>
> Cc: Tim Harvey <tharvey@gateworks.com>
> Cc: Vladimir Oltean <vladimir.oltean@nxp.com>
> ---
>  drivers/net/phy/Kconfig      |   5 +
>  drivers/net/phy/Makefile     |   1 +
>  drivers/net/phy/marvell10g.c | 605 +++++++++++++++++++++++++++++++++++
>  3 files changed, 611 insertions(+)
>  create mode 100644 drivers/net/phy/marvell10g.c
>
> diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig
> index 6806e3c0903..24158776f52 100644
> --- a/drivers/net/phy/Kconfig
> +++ b/drivers/net/phy/Kconfig
> @@ -174,6 +174,11 @@ config PHY_LXT
>  config PHY_MARVELL
>         bool "Marvell Ethernet PHYs support"
>
> +config PHY_MARVELL_10G
> +       bool "Marvell Alaska 10Gbit PHYs"
> +       help
> +         Support for the Marvell Alaska MV88X3310 and compatible PHYs.
> +
>  config PHY_MESON_GXL
>         bool "Amlogic Meson GXL Internal PHY support"
>
> diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile
> index 963d96e2bcb..85d17f109cd 100644
> --- a/drivers/net/phy/Makefile
> +++ b/drivers/net/phy/Makefile
> @@ -20,6 +20,7 @@ obj-$(CONFIG_PHY_DAVICOM) += davicom.o
>  obj-$(CONFIG_PHY_ET1011C) += et1011c.o
>  obj-$(CONFIG_PHY_LXT) += lxt.o
>  obj-$(CONFIG_PHY_MARVELL) += marvell.o
> +obj-$(CONFIG_PHY_MARVELL_10G) += marvell10g.o
>  obj-$(CONFIG_PHY_MICREL_KSZ8XXX) += micrel_ksz8xxx.o
>  obj-$(CONFIG_PHY_MICREL_KSZ90X1) += micrel_ksz90x1.o
>  obj-$(CONFIG_PHY_MESON_GXL) += meson-gxl.o
> diff --git a/drivers/net/phy/marvell10g.c b/drivers/net/phy/marvell10g.c
> new file mode 100644
> index 00000000000..9e64672f5ca
> --- /dev/null
> +++ b/drivers/net/phy/marvell10g.c
> @@ -0,0 +1,605 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * Marvell 10G 88x3310 PHY driver
> + *
> + * Based upon the ID registers, this PHY appears to be a mixture of IPs
> + * from two different companies.
> + *
> + * There appears to be several different data paths through the PHY which
> + * are automatically managed by the PHY.  The following has been determined
> + * via observation and experimentation for a setup using single-lane Serdes:
> + *
> + *       SGMII PHYXS -- BASE-T PCS -- 10G PMA -- AN -- Copper (for <= 1G)
> + *  10GBASE-KR PHYXS -- BASE-T PCS -- 10G PMA -- AN -- Copper (for 10G)
> + *  10GBASE-KR PHYXS -- BASE-R PCS -- Fiber
> + *
> + * With XAUI, observation shows:
> + *
> + *        XAUI PHYXS -- <appropriate PCS as above>
> + *
> + * and no switching of the host interface mode occurs.
> + *
> + * If both the fiber and copper ports are connected, the first to gain
> + * link takes priority and the other port is completely locked out.
> + */
> +#include <common.h>
> +#include <console.h>
> +#include <dm/device_compat.h>
> +#include <dm/devres.h>
> +#include <errno.h>
> +#include <linux/bitfield.h>
> +#include <linux/bitops.h>
> +#include <linux/compat.h>
> +#include <linux/delay.h>
> +#include <linux/iopoll.h>
> +#include <marvell_phy.h>
> +#include <phy.h>
> +
> +#define MV_PHY_ALASKA_NBT_QUIRK_MASK   0xfffffffe
> +#define MV_PHY_ALASKA_NBT_QUIRK_REV    (MARVELL_PHY_ID_88X3310 | 0xa)
> +
> +#define MV_VERSION(a, b, c, d) ((a) << 24 | (b) << 16 | (c) << 8 | (d))
> +
> +enum {
> +       MV_PMA_FW_VER0          = 0xc011,
> +       MV_PMA_FW_VER1          = 0xc012,
> +       MV_PMA_21X0_PORT_CTRL   = 0xc04a,
> +       MV_PMA_21X0_PORT_CTRL_SWRST                             = BIT(15),
> +       MV_PMA_21X0_PORT_CTRL_MACTYPE_MASK                      = 0x7,
> +       MV_PMA_21X0_PORT_CTRL_MACTYPE_USXGMII                   = 0x0,
> +       MV_PMA_2180_PORT_CTRL_MACTYPE_DXGMII                    = 0x1,
> +       MV_PMA_2180_PORT_CTRL_MACTYPE_QXGMII                    = 0x2,
> +       MV_PMA_21X0_PORT_CTRL_MACTYPE_5GBASER                   = 0x4,
> +       MV_PMA_21X0_PORT_CTRL_MACTYPE_5GBASER_NO_SGMII_AN       = 0x5,
> +       MV_PMA_21X0_PORT_CTRL_MACTYPE_10GBASER_RATE_MATCH       = 0x6,
> +       MV_PMA_BOOT             = 0xc050,
> +       MV_PMA_BOOT_FATAL       = BIT(0),
> +
> +       MV_PCS_BASE_T           = 0x0000,
> +       MV_PCS_BASE_R           = 0x1000,
> +       MV_PCS_1000BASEX        = 0x2000,
> +
> +       MV_PCS_CSCR1            = 0x8000,
> +       MV_PCS_CSCR1_ED_MASK    = 0x0300,
> +       MV_PCS_CSCR1_ED_OFF     = 0x0000,
> +       MV_PCS_CSCR1_ED_RX      = 0x0200,
> +       MV_PCS_CSCR1_ED_NLP     = 0x0300,
> +       MV_PCS_CSCR1_MDIX_MASK  = 0x0060,
> +       MV_PCS_CSCR1_MDIX_MDI   = 0x0000,
> +       MV_PCS_CSCR1_MDIX_MDIX  = 0x0020,
> +       MV_PCS_CSCR1_MDIX_AUTO  = 0x0060,
> +
> +       MV_PCS_DSC1             = 0x8003,
> +       MV_PCS_DSC1_ENABLE      = BIT(9),
> +       MV_PCS_DSC1_10GBT       = 0x01c0,
> +       MV_PCS_DSC1_1GBR        = 0x0038,
> +       MV_PCS_DSC1_100BTX      = 0x0007,
> +       MV_PCS_DSC2             = 0x8004,
> +       MV_PCS_DSC2_2P5G        = 0xf000,
> +       MV_PCS_DSC2_5G          = 0x0f00,
> +
> +       MV_PCS_CSSR1            = 0x8008,
> +       MV_PCS_CSSR1_SPD1_MASK  = 0xc000,
> +       MV_PCS_CSSR1_SPD1_SPD2  = 0xc000,
> +       MV_PCS_CSSR1_SPD1_1000  = 0x8000,
> +       MV_PCS_CSSR1_SPD1_100   = 0x4000,
> +       MV_PCS_CSSR1_SPD1_10    = 0x0000,
> +       MV_PCS_CSSR1_DUPLEX_FULL = BIT(13),
> +       MV_PCS_CSSR1_RESOLVED   = BIT(11),
> +       MV_PCS_CSSR1_MDIX       = BIT(6),
> +       MV_PCS_CSSR1_SPD2_MASK  = 0x000c,
> +       MV_PCS_CSSR1_SPD2_5000  = 0x0008,
> +       MV_PCS_CSSR1_SPD2_2500  = 0x0004,
> +       MV_PCS_CSSR1_SPD2_10000 = 0x0000,
> +
> +       /* Temperature read register (88E2110 only) */
> +       MV_PCS_TEMP             = 0x8042,
> +
> +       /* Number of ports on the device */
> +       MV_PCS_PORT_INFO        = 0xd00d,
> +       MV_PCS_PORT_INFO_NPORTS_MASK    = 0x0380,
> +       MV_PCS_PORT_INFO_NPORTS_SHIFT   = 7,
> +
> +       /* SerDes reinitialization 88E21X0 */
> +       MV_AN_21X0_SERDES_CTRL2 = 0x800f,
> +       MV_AN_21X0_SERDES_CTRL2_AUTO_INIT_DIS   = BIT(13),
> +       MV_AN_21X0_SERDES_CTRL2_RUN_INIT        = BIT(15),
> +
> +       /* These registers appear at 0x800X and 0xa00X - the 0xa00X control
> +        * registers appear to set themselves to the 0x800X when AN is
> +        * restarted, but status registers appear readable from either.
> +        */
> +       MV_AN_CTRL1000          = 0x8000, /* 1000base-T control register */
> +       MV_AN_STAT1000          = 0x8001, /* 1000base-T status register */
> +
> +       /* Vendor2 MMD registers */
> +       MV_V2_PORT_CTRL         = 0xf001,
> +       MV_V2_PORT_CTRL_PWRDOWN                                 = BIT(11),
> +       MV_V2_33X0_PORT_CTRL_SWRST                              = BIT(15),
> +       MV_V2_33X0_PORT_CTRL_MACTYPE_MASK                       = 0x7,
> +       MV_V2_33X0_PORT_CTRL_MACTYPE_RXAUI                      = 0x0,
> +       MV_V2_3310_PORT_CTRL_MACTYPE_XAUI_RATE_MATCH            = 0x1,
> +       MV_V2_3340_PORT_CTRL_MACTYPE_RXAUI_NO_SGMII_AN          = 0x1,
> +       MV_V2_33X0_PORT_CTRL_MACTYPE_RXAUI_RATE_MATCH           = 0x2,
> +       MV_V2_3310_PORT_CTRL_MACTYPE_XAUI                       = 0x3,
> +       MV_V2_33X0_PORT_CTRL_MACTYPE_10GBASER                   = 0x4,
> +       MV_V2_33X0_PORT_CTRL_MACTYPE_10GBASER_NO_SGMII_AN       = 0x5,
> +       MV_V2_33X0_PORT_CTRL_MACTYPE_10GBASER_RATE_MATCH        = 0x6,
> +       MV_V2_33X0_PORT_CTRL_MACTYPE_USXGMII                    = 0x7,
> +       MV_V2_PORT_INTR_STS             = 0xf040,
> +       MV_V2_PORT_INTR_MASK            = 0xf043,
> +       MV_V2_PORT_INTR_STS_WOL_EN      = BIT(8),
> +       MV_V2_MAGIC_PKT_WORD0           = 0xf06b,
> +       MV_V2_MAGIC_PKT_WORD1           = 0xf06c,
> +       MV_V2_MAGIC_PKT_WORD2           = 0xf06d,
> +       /* Wake on LAN registers */
> +       MV_V2_WOL_CTRL                  = 0xf06e,
> +       MV_V2_WOL_CTRL_CLEAR_STS        = BIT(15),
> +       MV_V2_WOL_CTRL_MAGIC_PKT_EN     = BIT(0),
> +       /* Temperature control/read registers (88X3310 only) */
> +       MV_V2_TEMP_CTRL         = 0xf08a,
> +       MV_V2_TEMP_CTRL_MASK    = 0xc000,
> +       MV_V2_TEMP_CTRL_SAMPLE  = 0x0000,
> +       MV_V2_TEMP_CTRL_DISABLE = 0xc000,
> +       MV_V2_TEMP              = 0xf08c,
> +       MV_V2_TEMP_UNKNOWN      = 0x9600, /* unknown function */
> +};
> +
> +struct mv3310_chip {
> +       bool (*has_downshift)(struct phy_device *phydev);
> +       int (*test_supported_interfaces)(struct phy_device *phydev);
> +       int (*get_mactype)(struct phy_device *phydev);
> +       int (*set_mactype)(struct phy_device *phydev, int mactype);
> +       int (*select_mactype)(struct phy_device *phydev);
> +       int (*init_interface)(struct phy_device *phydev, int mactype);
> +};
> +
> +struct mv3310_priv {
> +       DECLARE_BITMAP(supported_interfaces, PHY_INTERFACE_MODE_MAX);
> +
> +       u32 firmware_ver;
> +       bool has_downshift;
> +       bool rate_match;
> +};
> +
> +static const struct mv3310_chip *to_mv3310_chip(struct phy_device *phydev)
> +{
> +       return (const struct mv3310_chip *)phydev->drv->data;
> +}
> +
> +static int mv3310_power_down(struct phy_device *phydev)
> +{
> +       return phy_set_bits_mmd(phydev, MDIO_MMD_VEND2, MV_V2_PORT_CTRL,
> +                               MV_V2_PORT_CTRL_PWRDOWN);
> +}
> +
> +static int mv3310_power_up(struct phy_device *phydev)
> +{
> +       struct mv3310_priv *priv = (struct mv3310_priv *)phydev->priv;
> +       int ret;
> +
> +       ret = phy_clear_bits_mmd(phydev, MDIO_MMD_VEND2, MV_V2_PORT_CTRL,
> +                                MV_V2_PORT_CTRL_PWRDOWN);
> +
> +       if (phydev->drv->uid != MARVELL_PHY_ID_88X3310 ||
> +           priv->firmware_ver < 0x00030000)
> +               return ret;
> +
> +       return phy_set_bits_mmd(phydev, MDIO_MMD_VEND2, MV_V2_PORT_CTRL,
> +                               MV_V2_33X0_PORT_CTRL_SWRST);
> +}
> +
> +static int mv3310_reset(struct phy_device *phydev, u32 unit)
> +{
> +       int val, err;
> +
> +       err = phy_modify_mmd(phydev, MDIO_MMD_PCS, unit + MDIO_CTRL1,
> +                            MDIO_CTRL1_RESET, MDIO_CTRL1_RESET);
> +       if (err < 0)
> +               return err;
> +
> +       return phy_read_mmd_poll_timeout(phydev, MDIO_MMD_PCS,
> +                                        unit + MDIO_CTRL1, val,
> +                                        !(val & MDIO_CTRL1_RESET),
> +                                        5000, 100000, true);
> +}
> +
> +static int mv3310_set_downshift(struct phy_device *phydev)
> +{
> +       struct mv3310_priv *priv = (struct mv3310_priv *)phydev->priv;
> +       const u8 ds = 1;
> +       u16 val;
> +       int err;
> +
> +       if (!priv->has_downshift)
> +               return -EOPNOTSUPP;
> +
> +       val = FIELD_PREP(MV_PCS_DSC2_2P5G, ds);
> +       val |= FIELD_PREP(MV_PCS_DSC2_5G, ds);
> +       err = phy_modify_mmd(phydev, MDIO_MMD_PCS, MV_PCS_DSC2,
> +                            MV_PCS_DSC2_2P5G | MV_PCS_DSC2_5G, val);
> +       if (err < 0)
> +               return err;
> +
> +       val = MV_PCS_DSC1_ENABLE;
> +       val |= FIELD_PREP(MV_PCS_DSC1_10GBT, ds);
> +       val |= FIELD_PREP(MV_PCS_DSC1_1GBR, ds);
> +       val |= FIELD_PREP(MV_PCS_DSC1_100BTX, ds);
> +
> +       return phy_modify_mmd(phydev, MDIO_MMD_PCS, MV_PCS_DSC1,
> +                             MV_PCS_DSC1_ENABLE | MV_PCS_DSC1_10GBT |
> +                             MV_PCS_DSC1_1GBR | MV_PCS_DSC1_100BTX, val);
> +}
> +
> +static int mv3310_set_edpd(struct phy_device *phydev)
> +{
> +       int err;
> +
> +       err = phy_modify_mmd_changed(phydev, MDIO_MMD_PCS, MV_PCS_CSCR1,
> +                                    MV_PCS_CSCR1_ED_MASK,
> +                                    MV_PCS_CSCR1_ED_NLP);
> +       if (err > 0)
> +               err = mv3310_reset(phydev, MV_PCS_BASE_T);
> +
> +       return err;
> +}
> +
> +static int mv3310_probe(struct phy_device *phydev)
> +{
> +       const struct mv3310_chip *chip = to_mv3310_chip(phydev);
> +       struct mv3310_priv *priv;
> +       u32 mmd_mask = MDIO_DEVS_PMAPMD | MDIO_DEVS_AN;
> +       int ret;
> +
> +       if (!phydev->is_c45 ||
> +           (phydev->mmds & mmd_mask) != mmd_mask)
> +               return -ENODEV;
> +
> +       ret = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, MV_PMA_BOOT);
> +       if (ret < 0)
> +               return ret;
> +
> +       if (ret & MV_PMA_BOOT_FATAL) {
> +               dev_warn(phydev->dev,
> +                        "PHY failed to boot firmware, status=%04x\n", ret);
> +               return -ENODEV;
> +       }
> +
> +       priv = devm_kzalloc(phydev->dev, sizeof(*priv), GFP_KERNEL);
> +       if (!priv)
> +               return -ENOMEM;
> +
> +       phydev->priv = priv;
> +
> +       ret = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, MV_PMA_FW_VER0);
> +       if (ret < 0)
> +               return ret;
> +
> +       priv->firmware_ver = ret << 16;
> +
> +       ret = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, MV_PMA_FW_VER1);
> +       if (ret < 0)
> +               return ret;
> +
> +       priv->firmware_ver |= ret;
> +
> +       dev_info(phydev->dev, "Firmware version %u.%u.%u.%u\n",
> +                priv->firmware_ver >> 24, (priv->firmware_ver >> 16) & 255,
> +                (priv->firmware_ver >> 8) & 255, priv->firmware_ver & 255);
> +
> +       if (chip->has_downshift)
> +               priv->has_downshift = chip->has_downshift(phydev);
> +
> +       /* Powering down the port when not in use saves about 600mW */
> +       ret = mv3310_power_down(phydev);
> +       if (ret)
> +               return ret;
> +
> +       return 0;
> +}
> +
> +static int mv2110_get_mactype(struct phy_device *phydev)
> +{
> +       int mactype;
> +
> +       mactype = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, MV_PMA_21X0_PORT_CTRL);
> +       if (mactype < 0)
> +               return mactype;
> +
> +       return mactype & MV_PMA_21X0_PORT_CTRL_MACTYPE_MASK;
> +}
> +
> +static int mv2110_set_mactype(struct phy_device *phydev, int mactype)
> +{
> +       int err, val;
> +
> +       mactype &= MV_PMA_21X0_PORT_CTRL_MACTYPE_MASK;
> +       err = phy_modify_mmd(phydev, MDIO_MMD_PMAPMD, MV_PMA_21X0_PORT_CTRL,
> +                            MV_PMA_21X0_PORT_CTRL_SWRST |
> +                            MV_PMA_21X0_PORT_CTRL_MACTYPE_MASK,
> +                            MV_PMA_21X0_PORT_CTRL_SWRST | mactype);
> +       if (err)
> +               return err;
> +
> +       err = phy_set_bits_mmd(phydev, MDIO_MMD_AN, MV_AN_21X0_SERDES_CTRL2,
> +                              MV_AN_21X0_SERDES_CTRL2_AUTO_INIT_DIS |
> +                              MV_AN_21X0_SERDES_CTRL2_RUN_INIT);
> +       if (err)
> +               return err;
> +
> +       err = phy_read_mmd_poll_timeout(phydev, MDIO_MMD_AN,
> +                                       MV_AN_21X0_SERDES_CTRL2, val,
> +                                       !(val &
> +                                         MV_AN_21X0_SERDES_CTRL2_RUN_INIT),
> +                                       5000, 100000, true);
> +       if (err)
> +               return err;
> +
> +       return phy_clear_bits_mmd(phydev, MDIO_MMD_AN, MV_AN_21X0_SERDES_CTRL2,
> +                                 MV_AN_21X0_SERDES_CTRL2_AUTO_INIT_DIS);
> +}
> +
> +static int mv2110_select_mactype(struct phy_device *phydev)
> +{
> +       if (phydev->interface == PHY_INTERFACE_MODE_USXGMII)
> +               return MV_PMA_21X0_PORT_CTRL_MACTYPE_USXGMII;
> +       else if (phydev->interface == PHY_INTERFACE_MODE_SGMII &&
> +                !(phydev->interface == PHY_INTERFACE_MODE_10GBASER))
> +               return MV_PMA_21X0_PORT_CTRL_MACTYPE_5GBASER;
> +       else if (phydev->interface == PHY_INTERFACE_MODE_10GBASER)
> +               return MV_PMA_21X0_PORT_CTRL_MACTYPE_10GBASER_RATE_MATCH;
> +       else
> +               return -1;
> +}
> +
> +static int mv3310_get_mactype(struct phy_device *phydev)
> +{
> +       int mactype;
> +
> +       mactype = phy_read_mmd(phydev, MDIO_MMD_VEND2, MV_V2_PORT_CTRL);
> +       if (mactype < 0)
> +               return mactype;
> +
> +       return mactype & MV_V2_33X0_PORT_CTRL_MACTYPE_MASK;
> +}
> +
> +static int mv3310_set_mactype(struct phy_device *phydev, int mactype)
> +{
> +       int ret;
> +
> +       mactype &= MV_V2_33X0_PORT_CTRL_MACTYPE_MASK;
> +       ret = phy_modify_mmd_changed(phydev, MDIO_MMD_VEND2, MV_V2_PORT_CTRL,
> +                                    MV_V2_33X0_PORT_CTRL_MACTYPE_MASK,
> +                                    mactype);
> +       if (ret <= 0)
> +               return ret;
> +
> +       return phy_set_bits_mmd(phydev, MDIO_MMD_VEND2, MV_V2_PORT_CTRL,
> +                               MV_V2_33X0_PORT_CTRL_SWRST);
> +}
> +
> +static int mv3310_select_mactype(struct phy_device *phydev)
> +{
> +       if (phydev->interface == PHY_INTERFACE_MODE_USXGMII)
> +               return MV_V2_33X0_PORT_CTRL_MACTYPE_USXGMII;
> +       else if (phydev->interface == PHY_INTERFACE_MODE_SGMII &&
> +                phydev->interface == PHY_INTERFACE_MODE_10GBASER)
> +               return MV_V2_33X0_PORT_CTRL_MACTYPE_10GBASER;
> +       else if (phydev->interface == PHY_INTERFACE_MODE_SGMII &&
> +                phydev->interface == PHY_INTERFACE_MODE_RXAUI)
> +               return MV_V2_33X0_PORT_CTRL_MACTYPE_RXAUI;
> +       else if (phydev->interface == PHY_INTERFACE_MODE_SGMII &&
> +                phydev->interface == PHY_INTERFACE_MODE_XAUI)
> +               return MV_V2_3310_PORT_CTRL_MACTYPE_XAUI;
> +       else if (phydev->interface == PHY_INTERFACE_MODE_10GBASER)
> +               return MV_V2_33X0_PORT_CTRL_MACTYPE_10GBASER_RATE_MATCH;
> +       else if (phydev->interface == PHY_INTERFACE_MODE_RXAUI)
> +               return MV_V2_33X0_PORT_CTRL_MACTYPE_RXAUI_RATE_MATCH;
> +       else if (phydev->interface == PHY_INTERFACE_MODE_XAUI)
> +               return MV_V2_3310_PORT_CTRL_MACTYPE_XAUI_RATE_MATCH;
> +       else if (phydev->interface == PHY_INTERFACE_MODE_SGMII)
> +               return MV_V2_33X0_PORT_CTRL_MACTYPE_10GBASER;
> +       else
> +               return -1;
> +}
> +
> +static int mv2110_init_interface(struct phy_device *phydev, int mactype)
> +{
> +       struct mv3310_priv *priv = (struct mv3310_priv *)phydev->priv;
> +
> +       priv->rate_match = false;
> +
> +       if (mactype == MV_PMA_21X0_PORT_CTRL_MACTYPE_10GBASER_RATE_MATCH)
> +               priv->rate_match = true;
> +
> +       return 0;
> +}
> +
> +static int mv3310_init_interface(struct phy_device *phydev, int mactype)
> +{
> +       struct mv3310_priv *priv = (struct mv3310_priv *)phydev->priv;
> +
> +       priv->rate_match = false;
> +
> +       if (mactype != MV_V2_3340_PORT_CTRL_MACTYPE_RXAUI_NO_SGMII_AN)
> +               return 0;
> +
> +       if (mactype == MV_V2_33X0_PORT_CTRL_MACTYPE_10GBASER_RATE_MATCH ||
> +           mactype == MV_V2_33X0_PORT_CTRL_MACTYPE_RXAUI_RATE_MATCH ||
> +           mactype == MV_V2_3310_PORT_CTRL_MACTYPE_XAUI_RATE_MATCH)
> +               priv->rate_match = true;
> +
> +       return 0;
> +}
> +
> +static int mv3310_config_init(struct phy_device *phydev)
> +{
> +       const struct mv3310_chip *chip = to_mv3310_chip(phydev);
> +       int err, mactype;
> +
> +       /* Check that the PHY interface type is compatible */
> +       err = chip->test_supported_interfaces(phydev);
> +       if (err)
> +               return err;
> +
> +       /* Power up so reset works */
> +       err = mv3310_power_up(phydev);
> +       if (err)
> +               return err;
> +
> +       /* If host provided host supported interface modes, try to select the
> +        * best one
> +        */
> +       mactype = chip->select_mactype(phydev);
> +       if (mactype >= 0) {
> +               dev_info(phydev->dev, "Changing MACTYPE to %i\n",
> +                        mactype);
> +               err = chip->set_mactype(phydev, mactype);
> +               if (err)
> +                       return err;
> +       }
> +
> +       mactype = chip->get_mactype(phydev);
> +       if (mactype < 0)
> +               return mactype;
> +
> +       err = chip->init_interface(phydev, mactype);
> +       if (err) {
> +               dev_err(phydev->dev, "MACTYPE configuration invalid\n");
> +               return err;
> +       }
> +
> +       /* Enable EDPD mode - saving 600mW */
> +       err = mv3310_set_edpd(phydev);
> +       if (err)
> +               return err;
> +
> +       /* Allow downshift */
> +       err = mv3310_set_downshift(phydev);
> +       if (err && err != -EOPNOTSUPP)
> +               return err;
> +
> +       return 0;
> +}
> +
> +static int mv3310_config(struct phy_device *phydev)
> +{
> +       int err;
> +
> +       err = mv3310_probe(phydev);
> +       if (!err)
> +               err = mv3310_config_init(phydev);
> +
> +       return err;
> +}
> +
> +static int mv3310_get_number_of_ports(struct phy_device *phydev)
> +{
> +       int ret;
> +
> +       ret = phy_read_mmd(phydev, MDIO_MMD_PCS, MV_PCS_PORT_INFO);
> +       if (ret < 0)
> +               return ret;
> +
> +       ret &= MV_PCS_PORT_INFO_NPORTS_MASK;
> +       ret >>= MV_PCS_PORT_INFO_NPORTS_SHIFT;
> +
> +       return ret + 1;
> +}
> +
> +static int mv3310_match_phy_device(struct phy_device *phydev)
> +{
> +       if ((phydev->phy_id & MARVELL_PHY_ID_MASK) != MARVELL_PHY_ID_88X3310)
> +               return 0;
> +
> +       return mv3310_get_number_of_ports(phydev) == 1;
> +}
> +
> +static int mv211x_match_phy_device(struct phy_device *phydev, bool has_5g)
> +{
> +       int val;
> +
> +       if ((phydev->phy_id & MARVELL_PHY_ID_MASK) != MARVELL_PHY_ID_88E2110)
> +               return 0;
> +
> +       val = phy_read_mmd(phydev, MDIO_MMD_PCS, MDIO_SPEED);
> +       if (val < 0)
> +               return val;
> +
> +       return !!(val & MDIO_PCS_SPEED_5G) == has_5g;
> +}
> +
> +static int mv2110_match_phy_device(struct phy_device *phydev)
> +{
> +       return mv211x_match_phy_device(phydev, true);
> +}
> +
> +static bool mv3310_has_downshift(struct phy_device *phydev)
> +{
> +       struct mv3310_priv *priv = (struct mv3310_priv *)phydev->priv;
> +
> +       /* Fails to downshift with firmware older than v0.3.5.0 */
> +       return priv->firmware_ver >= MV_VERSION(0, 3, 5, 0);
> +}
> +
> +#define mv_test_bit(iface, phydev)     \
> +       ({ if ((phydev)->interface & (iface)) return 0; })
> +
> +static int mv3310_mv3340_test_supported_interfaces(struct phy_device *phydev)
> +{
> +       mv_test_bit(PHY_INTERFACE_MODE_SGMII, phydev);
> +       mv_test_bit(PHY_INTERFACE_MODE_2500BASEX, phydev);
> +       mv_test_bit(PHY_INTERFACE_MODE_5GBASER, phydev);
> +       if (mv3310_match_phy_device(phydev))
> +               mv_test_bit(PHY_INTERFACE_MODE_XAUI, phydev);
> +       mv_test_bit(PHY_INTERFACE_MODE_RXAUI, phydev);
> +       mv_test_bit(PHY_INTERFACE_MODE_10GBASER, phydev);
> +       mv_test_bit(PHY_INTERFACE_MODE_USXGMII, phydev);
> +       return -ENODEV;
> +}
> +
> +static int mv2110_mv2111_test_supported_interfaces(struct phy_device *phydev)
> +{
> +       mv_test_bit(PHY_INTERFACE_MODE_SGMII, phydev);
> +       mv_test_bit(PHY_INTERFACE_MODE_2500BASEX, phydev);
> +       if (mv2110_match_phy_device(phydev))
> +               mv_test_bit(PHY_INTERFACE_MODE_5GBASER, phydev);
> +       mv_test_bit(PHY_INTERFACE_MODE_10GBASER, phydev);
> +       mv_test_bit(PHY_INTERFACE_MODE_USXGMII, phydev);
> +       return -ENODEV;
> +}
> +
> +static const struct mv3310_chip mv3310_mv3340_type = {
> +       .has_downshift = mv3310_has_downshift,
> +       .test_supported_interfaces = mv3310_mv3340_test_supported_interfaces,
> +       .get_mactype = mv3310_get_mactype,
> +       .set_mactype = mv3310_set_mactype,
> +       .select_mactype = mv3310_select_mactype,
> +       .init_interface = mv3310_init_interface,
> +};
> +
> +static const struct mv3310_chip mv2110_mv2111_type = {
> +       .test_supported_interfaces = mv2110_mv2111_test_supported_interfaces,
> +       .get_mactype = mv2110_get_mactype,
> +       .set_mactype = mv2110_set_mactype,
> +       .select_mactype = mv2110_select_mactype,
> +       .init_interface = mv2110_init_interface,
> +};
> +
> +U_BOOT_PHY_DRIVER(mv88e3310_mv88e3340) = {
> +       .name           = "mv88x3310",
> +       .uid            = MARVELL_PHY_ID_88X3310,
> +       .mask           = MARVELL_PHY_ID_MASK,
> +       .features       = PHY_10G_FEATURES,
> +       .data           = (ulong)&mv3310_mv3340_type,
> +       .config         = mv3310_config,
> +};
> +
> +U_BOOT_PHY_DRIVER(mv88e2110_mv88e2111) = {
> +       .name           = "mv88e2110",
> +       .uid            = MARVELL_PHY_ID_88E2110,
> +       .mask           = MARVELL_PHY_ID_MASK,
> +       .features       = PHY_10G_FEATURES,
> +       .data           = (ulong)&mv2110_mv2111_type,
> +       .config         = mv3310_config,
> +};
> --
> 2.39.2
>
Reviewed-by: Ramon Fried <rfried.dev@gmail.com>

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

end of thread, other threads:[~2023-04-01 18:51 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-03-19 17:08 [PATCH 1/5] net: phy: marvell: Import and use marvell_phy.h from Linux Marek Vasut
2023-03-19 17:08 ` [PATCH 2/5] net: phy: Add phy_modify_mmd() and phy_modify_mmd_changed() " Marek Vasut
2023-04-01 18:49   ` Ramon Fried
2023-03-19 17:08 ` [PATCH 3/5] net: phy: Add phy_read_mmd_poll_timeout() " Marek Vasut
2023-04-01 18:50   ` Ramon Fried
2023-03-19 17:08 ` [PATCH 4/5] net: phy: Add MDIO PCS 2.5G and 5G speed macros " Marek Vasut
2023-04-01 18:50   ` Ramon Fried
2023-03-19 17:08 ` [PATCH 5/5] net: phy: marvell10g: Adapt Marvell 10G PHY driver " Marek Vasut
2023-04-01 18:51   ` Ramon Fried
2023-04-01 18:49 ` [PATCH 1/5] net: phy: marvell: Import and use marvell_phy.h " Ramon Fried

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).