[PATCH net-next] net: phy: micrel: Add support for lan9645x internal phy

Jens Emil Schulz Østergaard posted 1 patch 2 weeks ago
There is a newer version of this series
drivers/net/phy/micrel.c   | 142 +++++++++++++++++++++++++++++++++++++++++++++
include/linux/micrel_phy.h |   1 +
2 files changed, 143 insertions(+)
[PATCH net-next] net: phy: micrel: Add support for lan9645x internal phy
Posted by Jens Emil Schulz Østergaard 2 weeks ago
LAN9645X is a family of switch chips with 5 internal copper phys. The
internal PHY is based on parts of LAN8832. This 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.

Add support for the internal PHY of the lan9645x chip family.

Reviewed-by: Steen Hegelund <Steen.Hegelund@microchip.com>
Reviewed-by: Daniel Machon <daniel.machon@microchip.com>
Signed-off-by: Jens Emil Schulz Østergaard <jensemil.schulzostergaard@microchip.com>
---
 drivers/net/phy/micrel.c   | 142 +++++++++++++++++++++++++++++++++++++++++++++
 include/linux/micrel_phy.h |   1 +
 2 files changed, 143 insertions(+)

diff --git a/drivers/net/phy/micrel.c b/drivers/net/phy/micrel.c
index 225d4adf28be..7f47f7987067 100644
--- a/drivers/net/phy/micrel.c
+++ b/drivers/net/phy/micrel.c
@@ -6502,6 +6502,132 @@ static void lan8842_get_phy_stats(struct phy_device *phydev,
 	stats->tx_errors = priv->phy_stats.tx_errors;
 }
 
+#define LAN9645X_DAC_ICAS_AMP_POWER_DOWN	0x47
+#define LAN9645X_BTRX_QBIAS_POWER_DOWN		0x46
+#define LAN9645X_TX_LOW_I_CH_CD_POWER_MGMT	0x45
+#define LAN9645X_TX_LOW_I_CH_B_POWER_MGMT	0x44
+#define LAN9645X_TX_LOW_I_CH_A_POWER_MGMT	0x43
+
+static const struct lanphy_reg_data force_dac_tx_errata[] = {
+	/* Force channel A/B/C/D TX on */
+	{ LAN8814_PAGE_POWER_REGS,
+	  LAN9645X_DAC_ICAS_AMP_POWER_DOWN,
+	  0 },
+	/* Force channel A/B/C/D QBias on */
+	{ LAN8814_PAGE_POWER_REGS,
+	  LAN9645X_BTRX_QBIAS_POWER_DOWN,
+	  0xaa },
+	/* tx low I on channel C/D overwrite */
+	{ LAN8814_PAGE_POWER_REGS,
+	  LAN9645X_TX_LOW_I_CH_CD_POWER_MGMT,
+	  0xbfff },
+	/* channel B low I overwrite */
+	{ LAN8814_PAGE_POWER_REGS,
+	  LAN9645X_TX_LOW_I_CH_B_POWER_MGMT,
+	  0xabbf },
+	/* channel A low I overwrite */
+	{ LAN8814_PAGE_POWER_REGS,
+	  LAN9645X_TX_LOW_I_CH_A_POWER_MGMT,
+	  0xbd3f },
+};
+
+static int lan9645x_config_init(struct phy_device *phydev)
+{
+	int ret;
+
+	/* Apply erratas. */
+	ret = lan8842_erratas(phydev);
+	if (ret < 0)
+		return ret;
+
+	return lanphy_write_reg_data(phydev, force_dac_tx_errata,
+				     ARRAY_SIZE(force_dac_tx_errata));
+}
+
+static int lan9645x_suspend(struct phy_device *phydev)
+{
+	int aneg_en_state, ret;
+
+	/* Software workaround from design to handle SPD. SPD will stop AFE
+	 * clock from AFE port, which makes the system MAC fifo unable to flush.
+	 * The workaround is to restart ANEG and wait for flush, before issuing
+	 * software power down.
+	 */
+	aneg_en_state = phy_read(phydev, MII_BMCR) & BMCR_ANENABLE;
+
+	ret = phy_restart_aneg(phydev);
+	if (ret)
+		return ret;
+
+	/* Allow time for system FIFO flush data */
+	usleep_range(8 * USEC_PER_MSEC, 12 * USEC_PER_MSEC);
+
+	ret = genphy_suspend(phydev);
+	if (ret)
+		return ret;
+
+	if (!aneg_en_state)
+		return phy_modify(phydev, MII_BMCR, BMCR_ANENABLE, 0);
+
+	return 0;
+}
+
+static int lan9645x_config_intr(struct phy_device *phydev)
+{
+	int err;
+
+	/* enable / disable interrupts */
+	if (phydev->interrupts == PHY_INTERRUPT_ENABLED) {
+		/* This is an internal PHY of lan9645x and is not possible to
+		 * change the polarity of irq sources in the OIC (CPU_INTR)
+		 * found in lan9645x. Therefore change the polarity of the
+		 * interrupt in the PHY from being active low instead of active
+		 * high.
+		 */
+		phy_write(phydev, LAN8804_CONTROL,
+			  LAN8804_CONTROL_INTR_POLARITY);
+
+		/* By default interrupt buffer is open-drain in which case the
+		 * interrupt can be active only low. Therefore change the
+		 * interrupt buffer to be push-pull to be able to change
+		 * interrupt polarity.
+		 */
+		phy_write(phydev, LAN8804_OUTPUT_CONTROL,
+			  LAN8804_OUTPUT_CONTROL_INTR_BUFFER);
+
+		err = lan8814_ack_interrupt(phydev);
+		if (err)
+			return err;
+
+		err = phy_write(phydev, LAN8814_INTC,
+				LAN8814_INT_LINK | LAN8814_INT_FLF);
+	} else {
+		err = phy_write(phydev, LAN8814_INTC, 0);
+		if (err)
+			return err;
+
+		err = lan8814_ack_interrupt(phydev);
+	}
+
+	return err;
+}
+
+static irqreturn_t lan9645x_handle_interrupt(struct phy_device *phydev)
+{
+	int status;
+
+	status = phy_read(phydev, LAN8814_INTS);
+	if (status < 0) {
+		phy_error(phydev);
+		return IRQ_NONE;
+	}
+
+	if (status & (LAN8814_INT_LINK | LAN8814_INT_FLF))
+		phy_trigger_machine(phydev);
+
+	return IRQ_HANDLED;
+}
+
 static struct phy_driver ksphy_driver[] = {
 {
 	PHY_ID_MATCH_MODEL(PHY_ID_KS8737),
@@ -6740,6 +6866,21 @@ static struct phy_driver ksphy_driver[] = {
 	.set_tunable	= lan8842_set_tunable,
 	.cable_test_start	= lan8814_cable_test_start,
 	.cable_test_get_status	= ksz886x_cable_test_get_status,
+}, {
+	PHY_ID_MATCH_MODEL(PHY_ID_LAN9645X),
+	.name		= "Microchip LAN9645X Gigabit PHY",
+	.config_init	= lan9645x_config_init,
+	.driver_data	= &ksz9021_type,
+	.probe		= kszphy_probe,
+	.soft_reset	= genphy_soft_reset,
+	.suspend	= lan9645x_suspend,
+	.resume		= genphy_resume,
+	.config_intr	= lan9645x_config_intr,
+	.handle_interrupt = lan9645x_handle_interrupt,
+	.get_tunable	= lan8842_get_tunable,
+	.set_tunable	= lan8842_set_tunable,
+	.get_phy_stats	= lan8842_get_phy_stats,
+	.update_stats	= lan8842_update_stats,
 }, {
 	PHY_ID_MATCH_MODEL(PHY_ID_KSZ9131),
 	.name		= "Microchip KSZ9131 Gigabit PHY",
@@ -6838,6 +6979,7 @@ static const struct mdio_device_id __maybe_unused micrel_tbl[] = {
 	{ PHY_ID_MATCH_MODEL(PHY_ID_LAN8804) },
 	{ PHY_ID_MATCH_MODEL(PHY_ID_LAN8841) },
 	{ PHY_ID_MATCH_MODEL(PHY_ID_LAN8842) },
+	{ PHY_ID_MATCH_MODEL(PHY_ID_LAN9645X) },
 	{ }
 };
 
diff --git a/include/linux/micrel_phy.h b/include/linux/micrel_phy.h
index ca691641788b..9c6f9817383f 100644
--- a/include/linux/micrel_phy.h
+++ b/include/linux/micrel_phy.h
@@ -33,6 +33,7 @@
 #define PHY_ID_LAN8804		0x00221670
 #define PHY_ID_LAN8841		0x00221650
 #define PHY_ID_LAN8842		0x002216C0
+#define PHY_ID_LAN9645X		0x002216D0
 
 #define PHY_ID_KSZ886X		0x00221430
 #define PHY_ID_KSZ8863		0x00221435

---
base-commit: cbe8e6bef6a3b4b895b47ea56f5952f1936aacb6
change-id: 20260114-phy_micrel_add_support_for_lan9645x_internal_phy-6ef9a782cb8b

Best regards,
-- 
Jens Emil Schulz Østergaard <jensemil.schulzostergaard@microchip.com>

Re: [PATCH net-next] net: phy: micrel: Add support for lan9645x internal phy
Posted by Andrew Lunn 2 weeks ago
> +static int lan9645x_config_intr(struct phy_device *phydev)
> +{
> +	int err;
> +
> +	/* enable / disable interrupts */
> +	if (phydev->interrupts == PHY_INTERRUPT_ENABLED) {
> +		/* This is an internal PHY of lan9645x and is not possible to
> +		 * change the polarity of irq sources in the OIC (CPU_INTR)
> +		 * found in lan9645x. Therefore change the polarity of the
> +		 * interrupt in the PHY from being active low instead of active
> +		 * high.
> +		 */
> +		phy_write(phydev, LAN8804_CONTROL,
> +			  LAN8804_CONTROL_INTR_POLARITY);
> +
> +		/* By default interrupt buffer is open-drain in which case the
> +		 * interrupt can be active only low. Therefore change the
> +		 * interrupt buffer to be push-pull to be able to change
> +		 * interrupt polarity.
> +		 */

It is not stated here, but i assume that there are multiple of these
PHYs in the switch, and each PHY has its own independent connection to
the parent interrupt controller? There is no interrupt sharing going
on, which is common with discreet PHYs.

	Andrew
Re: [PATCH net-next] net: phy: micrel: Add support for lan9645x internal phy
Posted by Jens Emil Schulz Ostergaard 1 week, 3 days ago
Hi Andrew,

On Fri, 2026-01-23 at 17:11 +0100, Andrew Lunn wrote:
> > +static int lan9645x_config_intr(struct phy_device *phydev)
> > +{
> > +     int err;
> > +
> > +     /* enable / disable interrupts */
> > +     if (phydev->interrupts == PHY_INTERRUPT_ENABLED) {
> > +             /* This is an internal PHY of lan9645x and is not possible to
> > +              * change the polarity of irq sources in the OIC (CPU_INTR)
> > +              * found in lan9645x. Therefore change the polarity of the
> > +              * interrupt in the PHY from being active low instead of active
> > +              * high.
> > +              */
> > +             phy_write(phydev, LAN8804_CONTROL,
> > +                       LAN8804_CONTROL_INTR_POLARITY);
> > +
> > +             /* By default interrupt buffer is open-drain in which case the
> > +              * interrupt can be active only low. Therefore change the
> > +              * interrupt buffer to be push-pull to be able to change
> > +              * interrupt polarity.
> > +              */
> 
> It is not stated here, but i assume that there are multiple of these
> PHYs in the switch, and each PHY has its own independent connection to
> the parent interrupt controller? There is no interrupt sharing going
> on, which is common with discreet PHYs.
> 
>         Andrew

Yes you are right, there are 5 of these PHYs in the chip, each with their
on connection to the interrupt controller. It is similar to lan966x,
which has two internal PHYs of an older generation.

Thanks,
Emil
Re: [PATCH net-next] net: phy: micrel: Add support for lan9645x internal phy
Posted by Oleksij Rempel 2 weeks ago
Hi Jens,

On Fri, Jan 23, 2026 at 08:50:55AM +0100, Jens Emil Schulz Østergaard wrote:
> LAN9645X is a family of switch chips with 5 internal copper phys. The
> internal PHY is based on parts of LAN8832. This 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.
> 
> Add support for the internal PHY of the lan9645x chip family.

Looks like interesting switch for our use cases :)

> Reviewed-by: Steen Hegelund <Steen.Hegelund@microchip.com>
> Reviewed-by: Daniel Machon <daniel.machon@microchip.com>
> Signed-off-by: Jens Emil Schulz Østergaard <jensemil.schulzostergaard@microchip.com>
> ---
>  drivers/net/phy/micrel.c   | 142 +++++++++++++++++++++++++++++++++++++++++++++
>  include/linux/micrel_phy.h |   1 +
>  2 files changed, 143 insertions(+)
> 
> diff --git a/drivers/net/phy/micrel.c b/drivers/net/phy/micrel.c
> index 225d4adf28be..7f47f7987067 100644
> --- a/drivers/net/phy/micrel.c
> +++ b/drivers/net/phy/micrel.c
> @@ -6502,6 +6502,132 @@ static void lan8842_get_phy_stats(struct phy_device *phydev,
>  	stats->tx_errors = priv->phy_stats.tx_errors;
>  }
>  
> +#define LAN9645X_DAC_ICAS_AMP_POWER_DOWN	0x47
> +#define LAN9645X_BTRX_QBIAS_POWER_DOWN		0x46
> +#define LAN9645X_TX_LOW_I_CH_CD_POWER_MGMT	0x45
> +#define LAN9645X_TX_LOW_I_CH_B_POWER_MGMT	0x44
> +#define LAN9645X_TX_LOW_I_CH_A_POWER_MGMT	0x43

> +static const struct lanphy_reg_data force_dac_tx_errata[] = {
> +	/* Force channel A/B/C/D TX on */
> +	{ LAN8814_PAGE_POWER_REGS,
> +	  LAN9645X_DAC_ICAS_AMP_POWER_DOWN,
> +	  0 },
> +	/* Force channel A/B/C/D QBias on */
> +	{ LAN8814_PAGE_POWER_REGS,
> +	  LAN9645X_BTRX_QBIAS_POWER_DOWN,
> +	  0xaa },
> +	/* tx low I on channel C/D overwrite */
> +	{ LAN8814_PAGE_POWER_REGS,
> +	  LAN9645X_TX_LOW_I_CH_CD_POWER_MGMT,
> +	  0xbfff },
> +	/* channel B low I overwrite */
> +	{ LAN8814_PAGE_POWER_REGS,
> +	  LAN9645X_TX_LOW_I_CH_B_POWER_MGMT,
> +	  0xabbf },
> +	/* channel A low I overwrite */
> +	{ LAN8814_PAGE_POWER_REGS,
> +	  LAN9645X_TX_LOW_I_CH_A_POWER_MGMT,
> +	  0xbd3f },
> +};

It looks like this erratum not publicly documented. At least not here:
https://ww1.microchip.com/downloads/aemDocuments/documents/UNG/ProductDocuments/Errata/LAN9645xS-LAN9645xF-Errata-DS80001187.pdf

re there more information about it? Can it be described in the comment?

> +
> +static int lan9645x_config_init(struct phy_device *phydev)
> +{
> +	int ret;
> +
> +	/* Apply erratas. */
> +	ret = lan8842_erratas(phydev);
> +	if (ret < 0)
> +		return ret;
> +
> +	return lanphy_write_reg_data(phydev, force_dac_tx_errata,
> +				     ARRAY_SIZE(force_dac_tx_errata));
> +}
> +
> +static int lan9645x_suspend(struct phy_device *phydev)
> +{
> +	int aneg_en_state, ret;
> +
> +	/* Software workaround from design to handle SPD. SPD will stop AFE
> +	 * clock from AFE port, which makes the system MAC fifo unable to flush.
> +	 * The workaround is to restart ANEG and wait for flush, before issuing
> +	 * software power down.
> +	 */
> +	aneg_en_state = phy_read(phydev, MII_BMCR) & BMCR_ANENABLE;
> +
> +	ret = phy_restart_aneg(phydev);
> +	if (ret)
> +		return ret;
> +
> +	/* Allow time for system FIFO flush data */
> +	usleep_range(8 * USEC_PER_MSEC, 12 * USEC_PER_MSEC);

MAC and PHY power management are not always fully coupled (implementation
specific), are there other ways to sync them with each other, except of
unconditional sleep in the PHY driver. I expect that someone making
changes on the MAC driver may miss this nuance.

Best Regards,
Oleksij
-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |
Re: [PATCH net-next] net: phy: micrel: Add support for lan9645x internal phy
Posted by Jens Emil Schulz Ostergaard 2 weeks ago
Hi Oleksij,

On Fri, 2026-01-23 at 10:55 +0100, Oleksij Rempel wrote:
> 
> Hi Jens,
> 
> On Fri, Jan 23, 2026 at 08:50:55AM +0100, Jens Emil Schulz Østergaard wrote:
> > LAN9645X is a family of switch chips with 5 internal copper phys. The
> > internal PHY is based on parts of LAN8832. This 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.
> > 
> > Add support for the internal PHY of the lan9645x chip family.
> 
> Looks like interesting switch for our use cases :)
> 
> > Reviewed-by: Steen Hegelund <Steen.Hegelund@microchip.com>
> > Reviewed-by: Daniel Machon <daniel.machon@microchip.com>
> > Signed-off-by: Jens Emil Schulz Østergaard <jensemil.schulzostergaard@microchip.com>
> > ---
> >  drivers/net/phy/micrel.c   | 142 +++++++++++++++++++++++++++++++++++++++++++++
> >  include/linux/micrel_phy.h |   1 +
> >  2 files changed, 143 insertions(+)
> > 
> > diff --git a/drivers/net/phy/micrel.c b/drivers/net/phy/micrel.c
> > index 225d4adf28be..7f47f7987067 100644
> > --- a/drivers/net/phy/micrel.c
> > +++ b/drivers/net/phy/micrel.c
> > @@ -6502,6 +6502,132 @@ static void lan8842_get_phy_stats(struct phy_device *phydev,
> >       stats->tx_errors = priv->phy_stats.tx_errors;
> >  }
> > 
> > +#define LAN9645X_DAC_ICAS_AMP_POWER_DOWN     0x47
> > +#define LAN9645X_BTRX_QBIAS_POWER_DOWN               0x46
> > +#define LAN9645X_TX_LOW_I_CH_CD_POWER_MGMT   0x45
> > +#define LAN9645X_TX_LOW_I_CH_B_POWER_MGMT    0x44
> > +#define LAN9645X_TX_LOW_I_CH_A_POWER_MGMT    0x43
> 
> > +static const struct lanphy_reg_data force_dac_tx_errata[] = {
> > +     /* Force channel A/B/C/D TX on */
> > +     { LAN8814_PAGE_POWER_REGS,
> > +       LAN9645X_DAC_ICAS_AMP_POWER_DOWN,
> > +       0 },
> > +     /* Force channel A/B/C/D QBias on */
> > +     { LAN8814_PAGE_POWER_REGS,
> > +       LAN9645X_BTRX_QBIAS_POWER_DOWN,
> > +       0xaa },
> > +     /* tx low I on channel C/D overwrite */
> > +     { LAN8814_PAGE_POWER_REGS,
> > +       LAN9645X_TX_LOW_I_CH_CD_POWER_MGMT,
> > +       0xbfff },
> > +     /* channel B low I overwrite */
> > +     { LAN8814_PAGE_POWER_REGS,
> > +       LAN9645X_TX_LOW_I_CH_B_POWER_MGMT,
> > +       0xabbf },
> > +     /* channel A low I overwrite */
> > +     { LAN8814_PAGE_POWER_REGS,
> > +       LAN9645X_TX_LOW_I_CH_A_POWER_MGMT,
> > +       0xbd3f },
> > +};
> 
> It looks like this erratum not publicly documented. At least not here:
> https://ww1.microchip.com/downloads/aemDocuments/documents/UNG/ProductDocuments/Errata/LAN9645xS-
> LAN9645xF-Errata-DS80001187.pdf
> 
> re there more information about it? Can it be described in the comment?
> 

You are right, I think they ought to be documented in the official erratas
list with a more thorough description. I will get a hold of the right
people and ask them to add it.

> > +
> > +static int lan9645x_config_init(struct phy_device *phydev)
> > +{
> > +     int ret;
> > +
> > +     /* Apply erratas. */
> > +     ret = lan8842_erratas(phydev);
> > +     if (ret < 0)
> > +             return ret;
> > +
> > +     return lanphy_write_reg_data(phydev, force_dac_tx_errata,
> > +                                  ARRAY_SIZE(force_dac_tx_errata));
> > +}
> > +
> > +static int lan9645x_suspend(struct phy_device *phydev)
> > +{
> > +     int aneg_en_state, ret;
> > +
> > +     /* Software workaround from design to handle SPD. SPD will stop AFE
> > +      * clock from AFE port, which makes the system MAC fifo unable to flush.
> > +      * The workaround is to restart ANEG and wait for flush, before issuing
> > +      * software power down.
> > +      */
> > +     aneg_en_state = phy_read(phydev, MII_BMCR) & BMCR_ANENABLE;
> > +
> > +     ret = phy_restart_aneg(phydev);
> > +     if (ret)
> > +             return ret;
> > +
> > +     /* Allow time for system FIFO flush data */
> > +     usleep_range(8 * USEC_PER_MSEC, 12 * USEC_PER_MSEC);
> 
> MAC and PHY power management are not always fully coupled (implementation
> specific), are there other ways to sync them with each other, except of
> unconditional sleep in the PHY driver. I expect that someone making
> changes on the MAC driver may miss this nuance.
> 

The MAC side will be handled in a yet-to-be-sent DSA driver, which is also
authored by my team.

During development I was seeing issues where SPD sometimes causing
interference on neighbouring PHYs. The PHY team came up with the tx dac
errata and the aneg restart workaround as a solution.

To my knowledge there was no alternative workaround, but I have reached out
to the PHY team to make sure. If there is a better way to fix these issues,
I will add it in the next version.

> Best Regards,
> Oleksij
> --
> Pengutronix e.K.                           |                             |
> Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
> 31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
> Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

Thank you for the comments,

Emil
Re: [PATCH net-next] net: phy: micrel: Add support for lan9645x internal phy
Posted by Maxime Chevallier 2 weeks ago
Hi Jens,

On 23/01/2026 08:50, Jens Emil Schulz Østergaard wrote:
> LAN9645X is a family of switch chips with 5 internal copper phys. The
> internal PHY is based on parts of LAN8832. This 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.
> 
> Add support for the internal PHY of the lan9645x chip family.
> 
> Reviewed-by: Steen Hegelund <Steen.Hegelund@microchip.com>
> Reviewed-by: Daniel Machon <daniel.machon@microchip.com>
> Signed-off-by: Jens Emil Schulz Østergaard <jensemil.schulzostergaard@microchip.com>
> ---

[...]

> +static int lan9645x_config_intr(struct phy_device *phydev)
> +{
> +	int err;
> +
> +	/* enable / disable interrupts */
> +	if (phydev->interrupts == PHY_INTERRUPT_ENABLED) {
> +		/* This is an internal PHY of lan9645x and is not possible to
> +		 * change the polarity of irq sources in the OIC (CPU_INTR)
> +		 * found in lan9645x. Therefore change the polarity of the
> +		 * interrupt in the PHY from being active low instead of active
> +		 * high.
> +		 */
> +		phy_write(phydev, LAN8804_CONTROL,
> +			  LAN8804_CONTROL_INTR_POLARITY);
> +
> +		/* By default interrupt buffer is open-drain in which case the
> +		 * interrupt can be active only low. Therefore change the
> +		 * interrupt buffer to be push-pull to be able to change
> +		 * interrupt polarity.
> +		 */
> +		phy_write(phydev, LAN8804_OUTPUT_CONTROL,
> +			  LAN8804_OUTPUT_CONTROL_INTR_BUFFER);

Small nit from me, you're missing error checks on the 2 above reads.

Thanks,

Maxime

Re: [PATCH net-next] net: phy: micrel: Add support for lan9645x internal phy
Posted by Jens Emil Schulz Ostergaard 2 weeks ago
Hi Maxime,

On Fri, 2026-01-23 at 09:57 +0100, Maxime Chevallier wrote:
> 
> Hi Jens,
> 
> On 23/01/2026 08:50, Jens Emil Schulz Østergaard wrote:
> > LAN9645X is a family of switch chips with 5 internal copper phys.
> > The
> > internal PHY is based on parts of LAN8832. This 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.
> > 
> > Add support for the internal PHY of the lan9645x chip family.
> > 
> > Reviewed-by: Steen Hegelund <Steen.Hegelund@microchip.com>
> > Reviewed-by: Daniel Machon <daniel.machon@microchip.com>
> > Signed-off-by: Jens Emil Schulz Østergaard
> > <jensemil.schulzostergaard@microchip.com>
> > ---
> 
> [...]
> 
> > +static int lan9645x_config_intr(struct phy_device *phydev)
> > +{
> > +     int err;
> > +
> > +     /* enable / disable interrupts */
> > +     if (phydev->interrupts == PHY_INTERRUPT_ENABLED) {
> > +             /* This is an internal PHY of lan9645x and is not
> > possible to
> > +              * change the polarity of irq sources in the OIC
> > (CPU_INTR)
> > +              * found in lan9645x. Therefore change the polarity
> > of the
> > +              * interrupt in the PHY from being active low instead
> > of active
> > +              * high.
> > +              */
> > +             phy_write(phydev, LAN8804_CONTROL,
> > +                       LAN8804_CONTROL_INTR_POLARITY);
> > +
> > +             /* By default interrupt buffer is open-drain in which
> > case the
> > +              * interrupt can be active only low. Therefore change
> > the
> > +              * interrupt buffer to be push-pull to be able to
> > change
> > +              * interrupt polarity.
> > +              */
> > +             phy_write(phydev, LAN8804_OUTPUT_CONTROL,
> > +                       LAN8804_OUTPUT_CONTROL_INTR_BUFFER);
> 
> Small nit from me, you're missing error checks on the 2 above reads.
> 
> Thanks,
> 
> Maxime
> 

Thank you, I will add error checks in the next version.

Thanks,

Emil