diff mbox series

[v3,1/5] net: phy: micrel: add Microchip KSZ 9897 Switch PHY support

Message ID 20240530102436.226189-2-enguerrand.de-ribaucourt@savoirfairelinux.com (mailing list archive)
State Superseded
Delegated to: Netdev Maintainers
Headers show
Series Add Microchip KSZ 9897 Switch CPU PHY + Errata | expand

Checks

Context Check Description
netdev/series_format warning Target tree name not specified in the subject
netdev/tree_selection success Guessed tree name to be net-next
netdev/ynl success Generated files up to date; no warnings/errors; no diff in generated;
netdev/fixes_present success Fixes tag not required for -next series
netdev/header_inline success No static functions without inline keyword in header files
netdev/build_32bit success Errors and warnings before: 902 this patch: 902
netdev/build_tools success No tools touched, skip
netdev/cc_maintainers warning 3 maintainers not CCed: pabeni@redhat.com kuba@kernel.org edumazet@google.com
netdev/build_clang success Errors and warnings before: 906 this patch: 906
netdev/verify_signedoff success Signed-off-by tag matches author and committer
netdev/deprecated_api success None detected
netdev/check_selftest success No net selftest shell script
netdev/verify_fixes success No Fixes tag
netdev/build_allmodconfig_warn success Errors and warnings before: 906 this patch: 906
netdev/checkpatch warning CHECK: Comparison to NULL could be written "!node" CHECK: Comparison to NULL could be written "node" WARNING: line length of 82 exceeds 80 columns WARNING: line length of 83 exceeds 80 columns
netdev/build_clang_rust success No Rust files in patch. Skipping build
netdev/kdoc success Errors and warnings before: 0 this patch: 0
netdev/source_inline success Was 0 now: 0

Commit Message

Enguerrand de Ribaucourt May 30, 2024, 10:24 a.m. UTC
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@savoirfairelinux.com>
---
 drivers/net/phy/micrel.c | 46 +++++++++++++++++++++++++++++++++++++---
 1 file changed, 43 insertions(+), 3 deletions(-)

Comments

Andrew Lunn May 30, 2024, 1:26 p.m. UTC | #1
On Thu, May 30, 2024 at 10:24:32AM +0000, Enguerrand de Ribaucourt wrote:
> 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.

A better solution it to use:

      - pattern: "^ethernet-phy-id[a-f0-9]{4}\\.[a-f0-9]{4}$"
        description:
          If the PHY reports an incorrect ID (or none at all) then the
          compatible list may contain an entry with the correct PHY ID
          in the above form.

If there is no official ID for this PHY, you can ask Microchip to
allocate one. Or just pick the highest free ID in Microchips range.

	Andrew
diff mbox series

Patch

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