[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20240530102436.226189-2-enguerrand.de-ribaucourt@savoirfairelinux.com>
Date: Thu, 30 May 2024 10:24:32 +0000
From: Enguerrand de Ribaucourt <enguerrand.de-ribaucourt@...oirfairelinux.com>
To: netdev@...r.kernel.org
Cc: andrew@...n.ch,
hkallweit1@...il.com,
linux@...linux.org.uk,
woojung.huh@...rochip.com,
embedded-discuss@...ts.savoirfairelinux.net,
Enguerrand de Ribaucourt <enguerrand.de-ribaucourt@...oirfairelinux.com>
Subject: [PATCH v3 1/5] net: phy: micrel: add Microchip KSZ 9897 Switch PHY support
There is a DSA driver for microchip,ksz9897 which can be controlled
through SPI or I2C. This patch adds support for it's CPU ports PHYs to
also allow network access to the switch's CPU port.
The CPU ports PHYs of the KSZ9897 are not documented in the datasheet.
They weirdly use the same PHY ID as the KSZ8081, which is a different
PHY and that driver isn't compatible with KSZ9897. Before this patch,
the KSZ8081 driver was used for the CPU ports of the KSZ9897 but the
link would never come up.
A new driver for the KSZ9897 is added, based on the compatible KSZ87XX.
I could not test if Gigabit Ethernet works, but the link comes up and
can successfully allow packets to be sent and received with DSA tags.
To resolve the KSZ8081/KSZ9897 phy_id conflicts, I could not find any
stable register to distinguish them. The crude solution is to check if a
KSZ9897 DSA switch is present in the devicetree. A discussion to find
better alternatives had been opened with the Microchip team, with no
response yet.
See https://lore.kernel.org/all/20220207174532.362781-1-enguerrand.de-ribaucourt@savoirfairelinux.com/
Signed-off-by: Enguerrand de Ribaucourt <enguerrand.de-ribaucourt@...oirfairelinux.com>
---
drivers/net/phy/micrel.c | 46 +++++++++++++++++++++++++++++++++++++---
1 file changed, 43 insertions(+), 3 deletions(-)
diff --git a/drivers/net/phy/micrel.c b/drivers/net/phy/micrel.c
index 13e30ea7eec5..99322a3c3869 100644
--- a/drivers/net/phy/micrel.c
+++ b/drivers/net/phy/micrel.c
@@ -16,7 +16,7 @@
* ksz8081, ksz8091,
* ksz8061,
* Switch : ksz8873, ksz886x
- * ksz9477, lan8804
+ * ksz9477, ksz9897, lan8804
*/
#include <linux/bitfield.h>
@@ -769,6 +769,38 @@ static int ksz8051_match_phy_device(struct phy_device *phydev)
return ksz8051_ksz8795_match_phy_device(phydev, true);
}
+static int ksz8081_ksz9897_match_phy_device(struct phy_device *phydev,
+ const bool ksz_8081)
+{
+ /* KSZ8081 and KSZ9897 CPU port share the same exact PHY ID. Despite driver
+ * differences. None of the PHY registers allow to distinguish them
+ * accurately. The driver initialization order may also start with the PHY
+ * matching before the DSA switch node is attached to the CPU port. We fall
+ * back to looking up if any KSZ9897 is present in the devicetree.
+ */
+ struct device_node *node;
+
+ if (!phy_id_compare(phydev->phy_id, PHY_ID_KSZ8081, MICREL_PHY_ID_MASK))
+ return 0;
+
+ node = of_find_compatible_node(NULL, NULL, "microchip,ksz9897");
+
+ if (ksz_8081)
+ return node == NULL;
+ else
+ return node != NULL;
+}
+
+static int ksz8081_match_phy_device(struct phy_device *phydev)
+{
+ return ksz8081_ksz9897_match_phy_device(phydev, true);
+}
+
+static int ksz9897_match_phy_device(struct phy_device *phydev)
+{
+ return ksz8081_ksz9897_match_phy_device(phydev, false);
+}
+
static int ksz8081_config_init(struct phy_device *phydev)
{
/* KSZPHY_OMSO_FACTORY_TEST is set at de-assertion of the reset line
@@ -5300,9 +5332,7 @@ static struct phy_driver ksphy_driver[] = {
.suspend = kszphy_suspend,
.resume = kszphy_resume,
}, {
- .phy_id = PHY_ID_KSZ8081,
.name = "Micrel KSZ8081 or KSZ8091",
- .phy_id_mask = MICREL_PHY_ID_MASK,
.flags = PHY_POLL_CABLE_TEST,
/* PHY_BASIC_FEATURES */
.driver_data = &ksz8081_type,
@@ -5316,6 +5346,7 @@ static struct phy_driver ksphy_driver[] = {
.get_sset_count = kszphy_get_sset_count,
.get_strings = kszphy_get_strings,
.get_stats = kszphy_get_stats,
+ .match_phy_device = ksz8081_match_phy_device,
.suspend = kszphy_suspend,
.resume = kszphy_resume,
.cable_test_start = ksz886x_cable_test_start,
@@ -5486,6 +5517,15 @@ static struct phy_driver ksphy_driver[] = {
.suspend = genphy_suspend,
.resume = genphy_resume,
.get_features = ksz9477_get_features,
+}, {
+ .name = "Microchip KSZ9897 Switch",
+ /* PHY_BASIC_FEATURES */
+ .config_init = kszphy_config_init,
+ .config_aneg = ksz8873mll_config_aneg,
+ .read_status = ksz8873mll_read_status,
+ .match_phy_device = ksz9897_match_phy_device,
+ .suspend = genphy_suspend,
+ .resume = genphy_resume,
} };
module_phy_driver(ksphy_driver);
--
2.34.1
Powered by blists - more mailing lists