From nobody Sat Oct 4 19:18:41 2025 Received: from esa.microchip.iphmx.com (esa.microchip.iphmx.com [68.232.153.233]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id CFA152E88A5; Thu, 14 Aug 2025 08:31:35 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=68.232.153.233 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1755160297; cv=none; b=czhkWTkRP0qfn+6zU8yDb5XSv2b93dqzgY6RhJtv55G4e4gHD5XB7oeAPLq1EjkHN3x24W+Y8Ii22My64dm2VEll2yMmtcYeHVB5piApcvXeRJ9MGBEPwHmGzYeh7GE3bSlw2phxf+80gMwb0jAdD3fVgARrrHnPMh7w5+GXEgw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1755160297; c=relaxed/simple; bh=95/oBxMbh4tDShmsSKqzklc4IQcXB1rEkailnUFNZuE=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=bUQoc51jYedA4mG4ooxxFUgGwolqCfdjwJfllPoGwl4dE85MOWJUKzoqOspQVQU31Sx99WUZixtU8cbP2N42PWlSels6yt4VQHk3VwlgrXQ8Z/urm17N5Q1mcmH1no2fhi/e5BFF/ba8SmJN4mOC6fj+m30NVw5c5h9SvMkUPHk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=microchip.com; spf=pass smtp.mailfrom=microchip.com; dkim=pass (2048-bit key) header.d=microchip.com header.i=@microchip.com header.b=vXyHmYM8; arc=none smtp.client-ip=68.232.153.233 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=microchip.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=microchip.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=microchip.com header.i=@microchip.com header.b="vXyHmYM8" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=microchip.com; i=@microchip.com; q=dns/txt; s=mchp; t=1755160295; x=1786696295; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=95/oBxMbh4tDShmsSKqzklc4IQcXB1rEkailnUFNZuE=; b=vXyHmYM88+M5clMxILmTvf2Bj46hNBlCyZJxRhxJ7wPdEtEOzwq6dsyA FxyoHLLeEc+WRjUChA84cY7eG/v/BFitwf+/snW9cYtZJjawB+B0TeMt/ 34THxxU8su1+TzPH5TNY1Cat8dhjbMxbtU27j4a7BO66Bz2M32xKAdIHa zXHCPOii2fitzzUoh/xKaWuFQJd7NYnPN1ba3AX7DD0QL/tahXYEFhg4e W0qE1/WQxLZrXjWh69lHQ533S8qMUPxdrbhJQWooNQg86b3jeU1X4jbNo NYMgIZ1JHlQJQiwKYGUMvixIuFsKrQ4VIW2PGv0/QMjWbNbqZUVBx6yJm A==; X-CSE-ConnectionGUID: sG1idv10QAqjPnfZxhk11w== X-CSE-MsgGUID: F40BrHPFQlaoSBuHoUT2Wg== X-IronPort-AV: E=Sophos;i="6.17,287,1747724400"; d="scan'208";a="45178592" X-Amp-Result: SKIPPED(no attachment in message) Received: from unknown (HELO email.microchip.com) ([170.129.1.10]) by esa3.microchip.iphmx.com with ESMTP/TLS/ECDHE-RSA-AES128-GCM-SHA256; 14 Aug 2025 01:31:32 -0700 Received: from chn-vm-ex03.mchp-main.com (10.10.85.151) by chn-vm-ex01.mchp-main.com (10.10.85.143) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2507.44; Thu, 14 Aug 2025 01:31:20 -0700 Received: from DEN-DL-M31836.microchip.com (10.10.85.11) by chn-vm-ex03.mchp-main.com (10.10.85.151) with Microsoft SMTP Server id 15.1.2507.44 via Frontend Transport; Thu, 14 Aug 2025 01:31:18 -0700 From: Horatiu Vultur To: , , , , , , , , , CC: , , Horatiu Vultur Subject: [PATCH net-next v4 4/4] net: phy: micrel: Add support for lan8842 Date: Thu, 14 Aug 2025 10:26:24 +0200 Message-ID: <20250814082624.696952-5-horatiu.vultur@microchip.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20250814082624.696952-1-horatiu.vultur@microchip.com> References: <20250814082624.696952-1-horatiu.vultur@microchip.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" The LAN8842 is a low-power, single port triple-speed (10BASE-T/ 100BASE-TX/ 1000BASE-T) ethernet physical layer transceiver (PHY) that supports transmission and reception of data on standard CAT-5, as well as CAT-5e and CAT-6, Unshielded Twisted Pair (UTP) cables. The LAN8842 supports industry-standard SGMII (Serial Gigabit Media Independent Interface) providing chip-to-chip connection to a Gigabit Ethernet MAC using a single serialized link (differential pair) in each direction. There are 2 variants of the lan8842. The one that supports timestamping (lan8842) and one that doesn't have timestamping (lan8832). Signed-off-by: Horatiu Vultur --- drivers/net/phy/micrel.c | 203 +++++++++++++++++++++++++++++++++++++ include/linux/micrel_phy.h | 1 + 2 files changed, 204 insertions(+) diff --git a/drivers/net/phy/micrel.c b/drivers/net/phy/micrel.c index c621ed465d2e5..f57cb46341928 100644 --- a/drivers/net/phy/micrel.c +++ b/drivers/net/phy/micrel.c @@ -448,6 +448,17 @@ struct kszphy_priv { struct kszphy_phy_stats phy_stats; }; =20 +struct lan8842_phy_stats { + u64 rx_packets; + u64 rx_errors; + u64 tx_packets; + u64 tx_errors; +}; + +struct lan8842_priv { + struct lan8842_phy_stats phy_stats; +}; + static const struct kszphy_type lan8814_type =3D { .led_mode_reg =3D ~LAN8814_LED_CTRL_1, .cable_diag_reg =3D LAN8814_CABLE_DIAG, @@ -5768,6 +5779,184 @@ static int ksz9131_resume(struct phy_device *phydev) return kszphy_resume(phydev); } =20 +#define LAN8842_SELF_TEST 14 /* 0x0e */ +#define LAN8842_SELF_TEST_RX_CNT_ENA BIT(8) +#define LAN8842_SELF_TEST_TX_CNT_ENA BIT(4) + +static int lan8842_probe(struct phy_device *phydev) +{ + struct lan8842_priv *priv; + int ret; + + priv =3D devm_kzalloc(&phydev->mdio.dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + phydev->priv =3D priv; + + /* Similar to lan8814 this PHY has a pin which needs to be pulled down + * to enable to pass any traffic through it. Therefore use the same + * function as lan8814 + */ + ret =3D lan8814_release_coma_mode(phydev); + if (ret) + return ret; + + /* Enable to count the RX and TX packets */ + ret =3D lanphy_write_page_reg(phydev, LAN8814_PAGE_PCS_DIGITAL, + LAN8842_SELF_TEST, + LAN8842_SELF_TEST_RX_CNT_ENA | + LAN8842_SELF_TEST_TX_CNT_ENA); + if (ret < 0) + return ret; + + return 0; +} + +#define LAN8842_SGMII_AUTO_ANEG_ENA 69 /* 0x45 */ +#define LAN8842_FLF 15 /* 0x0e */ +#define LAN8842_FLF_ENA BIT(1) +#define LAN8842_FLF_ENA_LINK_DOWN BIT(0) + +static int lan8842_config_init(struct phy_device *phydev) +{ + int ret; + + /* Reset the PHY */ + ret =3D lanphy_modify_page_reg(phydev, LAN8814_PAGE_COMMON_REGS, + LAN8814_QSGMII_SOFT_RESET, + LAN8814_QSGMII_SOFT_RESET_BIT, + LAN8814_QSGMII_SOFT_RESET_BIT); + if (ret < 0) + return ret; + + /* Disable ANEG with QSGMII PCS Host side + * It has the same address as lan8814 + */ + ret =3D lanphy_modify_page_reg(phydev, LAN8814_PAGE_PORT_REGS, + LAN8814_QSGMII_PCS1G_ANEG_CONFIG, + LAN8814_QSGMII_PCS1G_ANEG_CONFIG_ANEG_ENA, + 0); + if (ret < 0) + return ret; + + /* Disable also the SGMII_AUTO_ANEG_ENA, this will determine what is the + * PHY autoneg with the other end and then will update the host side + */ + ret =3D lanphy_write_page_reg(phydev, LAN8814_PAGE_COMMON_REGS, + LAN8842_SGMII_AUTO_ANEG_ENA, 0); + if (ret < 0) + return ret; + + /* To allow the PHY to control the LEDs the GPIOs of the PHY should have + * a function mode and not the GPIO. Apparently by default the value is + * GPIO and not function even though the datasheet it says that it is + * function. Therefore set this value. + */ + return lanphy_write_page_reg(phydev, LAN8814_PAGE_COMMON_REGS, + LAN8814_GPIO_EN2, 0); +} + +#define LAN8842_INTR_CTRL_REG 52 /* 0x34 */ + +static int lan8842_config_intr(struct phy_device *phydev) +{ + int err; + + lanphy_write_page_reg(phydev, LAN8814_PAGE_COMMON_REGS, + LAN8842_INTR_CTRL_REG, + LAN8814_INTR_CTRL_REG_INTR_ENABLE); + + /* enable / disable interrupts */ + if (phydev->interrupts =3D=3D PHY_INTERRUPT_ENABLED) { + err =3D lan8814_ack_interrupt(phydev); + if (err) + return err; + + err =3D phy_write(phydev, LAN8814_INTC, LAN8814_INT_LINK); + } else { + err =3D phy_write(phydev, LAN8814_INTC, 0); + if (err) + return err; + + err =3D lan8814_ack_interrupt(phydev); + } + + return err; +} + +static irqreturn_t lan8842_handle_interrupt(struct phy_device *phydev) +{ + int ret =3D IRQ_NONE; + int irq_status; + + irq_status =3D phy_read(phydev, LAN8814_INTS); + if (irq_status < 0) { + phy_error(phydev); + return IRQ_NONE; + } + + if (irq_status & LAN8814_INT_LINK) { + phy_trigger_machine(phydev); + ret =3D IRQ_HANDLED; + } + + return ret; +} + +static u64 lan8842_get_stat(struct phy_device *phydev, int count, int *reg= s) +{ + int val; + u64 ret =3D 0; + + for (int j =3D 0; j < count; ++j) { + val =3D lanphy_read_page_reg(phydev, LAN8814_PAGE_PCS_DIGITAL, + regs[j]); + if (val < 0) + return U64_MAX; + + ret <<=3D 16; + ret +=3D val; + } + return ret; +} + +static int lan8842_update_stats(struct phy_device *phydev) +{ + struct lan8842_priv *priv =3D phydev->priv; + int rx_packets_regs[] =3D {88, 61, 60}; + int rx_errors_regs[] =3D {63, 62}; + int tx_packets_regs[] =3D {89, 85, 84}; + int tx_errors_regs[] =3D {87, 86}; + + priv->phy_stats.rx_packets =3D lan8842_get_stat(phydev, + ARRAY_SIZE(rx_packets_regs), + rx_packets_regs); + priv->phy_stats.rx_errors =3D lan8842_get_stat(phydev, + ARRAY_SIZE(rx_errors_regs), + rx_errors_regs); + priv->phy_stats.tx_packets =3D lan8842_get_stat(phydev, + ARRAY_SIZE(tx_packets_regs), + tx_packets_regs); + priv->phy_stats.tx_errors =3D lan8842_get_stat(phydev, + ARRAY_SIZE(tx_errors_regs), + tx_errors_regs); + + return 0; +} + +static void lan8842_get_phy_stats(struct phy_device *phydev, + struct ethtool_eth_phy_stats *eth_stats, + struct ethtool_phy_stats *stats) +{ + struct lan8842_priv *priv =3D phydev->priv; + + stats->rx_packets =3D priv->phy_stats.rx_packets; + stats->rx_errors =3D priv->phy_stats.rx_errors; + stats->tx_packets =3D priv->phy_stats.tx_packets; + stats->tx_errors =3D priv->phy_stats.tx_errors; +} + static struct phy_driver ksphy_driver[] =3D { { PHY_ID_MATCH_MODEL(PHY_ID_KS8737), @@ -5987,6 +6176,19 @@ static struct phy_driver ksphy_driver[] =3D { .resume =3D lan8841_resume, .cable_test_start =3D lan8814_cable_test_start, .cable_test_get_status =3D ksz886x_cable_test_get_status, +}, { + PHY_ID_MATCH_MODEL(PHY_ID_LAN8842), + .name =3D "Microchip LAN8842 Gigabit PHY", + .flags =3D PHY_POLL_CABLE_TEST, + .driver_data =3D &lan8814_type, + .probe =3D lan8842_probe, + .config_init =3D lan8842_config_init, + .config_intr =3D lan8842_config_intr, + .handle_interrupt =3D lan8842_handle_interrupt, + .get_phy_stats =3D lan8842_get_phy_stats, + .update_stats =3D lan8842_update_stats, + .cable_test_start =3D lan8814_cable_test_start, + .cable_test_get_status =3D ksz886x_cable_test_get_status, }, { PHY_ID_MATCH_MODEL(PHY_ID_KSZ9131), .name =3D "Microchip KSZ9131 Gigabit PHY", @@ -6082,6 +6284,7 @@ static const struct mdio_device_id __maybe_unused mic= rel_tbl[] =3D { { PHY_ID_MATCH_MODEL(PHY_ID_LAN8814) }, { PHY_ID_MATCH_MODEL(PHY_ID_LAN8804) }, { PHY_ID_MATCH_MODEL(PHY_ID_LAN8841) }, + { PHY_ID_MATCH_MODEL(PHY_ID_LAN8842) }, { } }; =20 diff --git a/include/linux/micrel_phy.h b/include/linux/micrel_phy.h index 9af01bdd86d26..ca691641788b8 100644 --- a/include/linux/micrel_phy.h +++ b/include/linux/micrel_phy.h @@ -32,6 +32,7 @@ #define PHY_ID_LAN8814 0x00221660 #define PHY_ID_LAN8804 0x00221670 #define PHY_ID_LAN8841 0x00221650 +#define PHY_ID_LAN8842 0x002216C0 =20 #define PHY_ID_KSZ886X 0x00221430 #define PHY_ID_KSZ8863 0x00221435 --=20 2.34.1