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