From: Stefan Eichenberger <eichest@gmail.com>
To: netdev@vger.kernel.org, andrew@lunn.ch, hkallweit1@gmail.com,
linux@armlinux.org.uk, francesco.dolcini@toradex.com
Cc: davem@davemloft.net, edumazet@google.com, kuba@kernel.org,
pabeni@redhat.com, eichest@gmail.com
Subject: [PATCH net-next v2 4/4] net: phy: marvell-88q2xxx: add driver for the Marvell 88Q2110 PHY
Date: Mon, 10 Jul 2023 22:59:00 +0200 [thread overview]
Message-ID: <20230710205900.52894-5-eichest@gmail.com> (raw)
In-Reply-To: <20230710205900.52894-1-eichest@gmail.com>
Add a driver for the Marvell 88Q2110. This driver is minimalistic, but
already allows to detect the link, switch between 100BASE-T1 and
1000BASE-T1 and switch between master and slave mode. Autonegotiation
supported by the PHY is not yet implemented.
Signed-off-by: Stefan Eichenberger <eichest@gmail.com>
---
drivers/net/phy/Kconfig | 6 ++
drivers/net/phy/Makefile | 1 +
drivers/net/phy/marvell-88q2xxx.c | 149 ++++++++++++++++++++++++++++++
3 files changed, 156 insertions(+)
create mode 100644 drivers/net/phy/marvell-88q2xxx.c
diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig
index 78e6981650d94..87b8238587173 100644
--- a/drivers/net/phy/Kconfig
+++ b/drivers/net/phy/Kconfig
@@ -217,6 +217,12 @@ config MARVELL_10G_PHY
help
Support for the Marvell Alaska MV88X3310 and compatible PHYs.
+config MARVELL_88Q2XXX_PHY
+ tristate "Marvell 88Q2XXX PHY"
+ help
+ Support for the Marvell 88Q2XXX 100/1000BASE-T1 Automotive Ethernet
+ PHYs.
+
config MARVELL_88X2222_PHY
tristate "Marvell 88X2222 PHY"
help
diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile
index 2fe51ea83babe..35142780fc9da 100644
--- a/drivers/net/phy/Makefile
+++ b/drivers/net/phy/Makefile
@@ -66,6 +66,7 @@ obj-$(CONFIG_LSI_ET1011C_PHY) += et1011c.o
obj-$(CONFIG_LXT_PHY) += lxt.o
obj-$(CONFIG_MARVELL_10G_PHY) += marvell10g.o
obj-$(CONFIG_MARVELL_PHY) += marvell.o
+obj-$(CONFIG_MARVELL_88Q2XXX_PHY) += marvell-88q2xxx.o
obj-$(CONFIG_MARVELL_88X2222_PHY) += marvell-88x2222.o
obj-$(CONFIG_MAXLINEAR_GPHY) += mxl-gpy.o
obj-$(CONFIG_MEDIATEK_GE_PHY) += mediatek-ge.o
diff --git a/drivers/net/phy/marvell-88q2xxx.c b/drivers/net/phy/marvell-88q2xxx.c
new file mode 100644
index 0000000000000..a073124c33f5e
--- /dev/null
+++ b/drivers/net/phy/marvell-88q2xxx.c
@@ -0,0 +1,149 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Marvell 88Q2XXX automotive 100BASE-T1/1000BASE-T1 PHY driver
+ */
+#include <linux/ethtool_netlink.h>
+#include <linux/marvell_phy.h>
+#include <linux/phy.h>
+
+#define MARVELL_PHY_ID_88Q2110 0x002b0981
+
+static int mv88q2xxx_soft_reset(struct phy_device *phydev)
+{
+ return phy_write_mmd(phydev, MDIO_MMD_PCS,
+ MDIO_PCS_1000BT1_CTRL, MDIO_PCS_1000BT1_CTRL_RESET);
+}
+
+static int mv88q2xxx_read_link(struct phy_device *phydev)
+{
+ u16 ret1, ret2;
+
+ /* 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.
+ */
+ if (phydev->speed == SPEED_1000) {
+ /* Read twice to clear the latched status */
+ ret1 = phy_read_mmd(phydev, MDIO_MMD_PCS, MDIO_PCS_1000BT1_STAT);
+ ret1 = phy_read_mmd(phydev, MDIO_MMD_PCS, MDIO_PCS_1000BT1_STAT);
+ /* Read vendor specific Auto-Negotiation status register to get
+ * local and remote receiver status
+ */
+ ret2 = phy_read_mmd(phydev, MDIO_MMD_AN, 0x8001);
+ } else {
+ /* Read vendor specific status registers, the registers are not
+ * documented but they can be found in the Software
+ * Initialization Guide
+ */
+ ret1 = phy_read_mmd(phydev, MDIO_MMD_PCS, 0x8109);
+ ret2 = phy_read_mmd(phydev, MDIO_MMD_PCS, 0x8108);
+ }
+
+ /* Check the link status according to Software Initialization Guide */
+ return (0x0 != (ret1 & 0x0004)) && (0x0 != (ret2 & 0x3000)) ? 1 : 0;
+}
+
+static int mv88q2xxx_read_status(struct phy_device *phydev)
+{
+ int ret;
+
+ phydev->link = mv88q2xxx_read_link(phydev);
+
+ ret = genphy_c45_read_pma(phydev);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static int mv88q2xxx_config_aneg(struct phy_device *phydev)
+{
+ int ret;
+
+ ret = genphy_c45_config_aneg(phydev);
+ if (ret)
+ return ret;
+
+ ret = mv88q2xxx_soft_reset(phydev);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+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);
+}
+
+static int mv88q2xxx_probe(struct phy_device *phydev)
+{
+ return 0;
+}
+
+static int mv88q2xxxx_get_sqi(struct phy_device *phydev)
+{
+ u16 value;
+
+ if (phydev->speed == SPEED_100) {
+ /* Read the SQI from the vendor specific receiver status
+ * register
+ */
+ value = (phy_read_mmd(phydev, MDIO_MMD_PCS, 0x8230) >> 12) & 0x0F;
+ } else {
+ /* Read from vendor specific registers, they are not documented
+ * but can be found in the Software Initialization Guide. Only
+ * revisions >= A0 are supported.
+ */
+ phy_modify_mmd(phydev, MDIO_MMD_PCS, 0xFC5D, 0x00FF, 0x00AC);
+ value = phy_read_mmd(phydev, MDIO_MMD_PCS, 0xfc88) & 0x0F;
+ }
+
+ return value;
+}
+
+static int mv88q2xxxx_get_sqi_max(struct phy_device *phydev)
+{
+ return 15;
+}
+
+static struct phy_driver mv88q2xxx_driver[] = {
+ {
+ .phy_id = MARVELL_PHY_ID_88Q2110,
+ .phy_id_mask = MARVELL_PHY_ID_MASK,
+ .features = PHY_GBIT_T1_FEATURES,
+ .name = "mv88q2110",
+ .probe = mv88q2xxx_probe,
+ .soft_reset = mv88q2xxx_soft_reset,
+ .config_init = mv88q2xxx_config_init,
+ .read_status = mv88q2xxx_read_status,
+ .config_aneg = mv88q2xxx_config_aneg,
+ .set_loopback = genphy_c45_loopback,
+ .get_sqi = mv88q2xxxx_get_sqi,
+ .get_sqi_max = mv88q2xxxx_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 },
+ { /*sentinel*/ }
+};
+MODULE_DEVICE_TABLE(mdio, mv88q2xxx_tbl);
+
+MODULE_DESCRIPTION("Marvell 88Q2XXX 100/1000BASE-T1 Automotive Ethernet PHY driver");
+MODULE_LICENSE("GPL");
--
2.39.2
next prev parent reply other threads:[~2023-07-10 20:59 UTC|newest]
Thread overview: 18+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-07-10 20:58 [PATCH net-next v2 0/4] Add a driver for the Marvell 88Q2110 PHY Stefan Eichenberger
2023-07-10 20:58 ` [PATCH net-next v2 1/4] net: phy: add the link modes for 1000BASE-T1 Ethernet PHY Stefan Eichenberger
2023-07-10 21:10 ` Andrew Lunn
2023-07-13 14:10 ` Stefan Eichenberger
2023-07-13 15:18 ` Andrew Lunn
2023-07-14 3:51 ` Stefan Eichenberger
2023-07-14 4:05 ` Andrew Lunn
2023-07-10 20:58 ` [PATCH net-next v2 2/4] net: phy: add registers to support 1000BASE-T1 Stefan Eichenberger
2023-07-10 20:58 ` [PATCH net-next v2 3/4] net: phy: c45: add support for 1000BASE-T1 Stefan Eichenberger
2023-07-10 21:14 ` Francesco Dolcini
2023-07-10 20:59 ` Stefan Eichenberger [this message]
2023-07-10 21:20 ` [PATCH net-next v2 4/4] net: phy: marvell-88q2xxx: add driver for the Marvell 88Q2110 PHY Andrew Lunn
2023-07-13 9:42 ` Stefan Eichenberger
2023-07-13 10:14 ` Russell King (Oracle)
2023-07-13 11:41 ` Stefan Eichenberger
2023-07-10 21:26 ` Francesco Dolcini
2023-07-10 21:40 ` Andrew Lunn
2023-07-13 7:00 ` Russell King (Oracle)
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20230710205900.52894-5-eichest@gmail.com \
--to=eichest@gmail.com \
--cc=andrew@lunn.ch \
--cc=davem@davemloft.net \
--cc=edumazet@google.com \
--cc=francesco.dolcini@toradex.com \
--cc=hkallweit1@gmail.com \
--cc=kuba@kernel.org \
--cc=linux@armlinux.org.uk \
--cc=netdev@vger.kernel.org \
--cc=pabeni@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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).