diff --git a/arch/arm/src/sam34/sam_emac.c b/arch/arm/src/sam34/sam_emac.c index cbca247c60d..747fd08d33b 100644 --- a/arch/arm/src/sam34/sam_emac.c +++ b/arch/arm/src/sam34/sam_emac.c @@ -1937,7 +1937,12 @@ static void sam_phydump(struct sam_emac_s *priv) * Function: sam_phyintenable * * Description: - * Enable link up/down PHY interrupts + * Enable link up/down PHY interrupts. The interrupt protocol is like this: + * + * - Interrupt status is cleared when the interrupt is enabled. + * - Interrupt occurs. Interrupt is disabled (at the processor level) when + * is received. + * - Interrupt status is cleared when the interrupt is re-enabled. * * Parameters: * priv - A reference to the private driver state structure @@ -1952,6 +1957,7 @@ static int sam_phyintenable(struct sam_emac_s *priv) { #if defined(CONFIG_ETH0_PHY_KSZ8051) || defined(CONFIG_ETH0_PHY_KSZ8081) uint32_t regval; + uint16_t phyval; int ret; /* Enable management port */ @@ -1959,10 +1965,18 @@ static int sam_phyintenable(struct sam_emac_s *priv) regval = sam_getreg(priv, SAM_EMAC_NCR); sam_putreg(priv, SAM_EMAC_NCR, regval | EMAC_NCR_MPE); - /* Enable link up/down interrupts */ + /* Read the interrupt status register in order to clear any pending + * interrupts + */ - ret = sam_phywrite(priv, priv->phyaddr, MII_KSZ8081_INT, - (MII_KSZ80x1_INT_LDEN | MII_KSZ80x1_INT_LUEN)); + ret = sam_phyread(priv, priv->phyaddr, MII_KSZ8081_INT, &phyval); + if (ret == OK) + { + /* Enable link up/down interrupts */ + + ret = sam_phywrite(priv, priv->phyaddr, MII_KSZ8081_INT, + (MII_KSZ80x1_INT_LDEN | MII_KSZ80x1_INT_LUEN)); + } /* Disable management port (probably) */ diff --git a/arch/arm/src/sama5/sam_emaca.c b/arch/arm/src/sama5/sam_emaca.c index 2cb0400ba5e..701b3464e7b 100644 --- a/arch/arm/src/sama5/sam_emaca.c +++ b/arch/arm/src/sama5/sam_emaca.c @@ -1978,7 +1978,12 @@ static void sam_phydump(struct sam_emac_s *priv) * Function: sam_phyintenable * * Description: - * Enable link up/down PHY interrupts + * Enable link up/down PHY interrupts. The interrupt protocol is like this: + * + * - Interrupt status is cleared when the interrupt is enabled. + * - Interrupt occurs. Interrupt is disabled (at the processor level) when + * is received. + * - Interrupt status is cleared when the interrupt is re-enabled. * * Parameters: * priv - A reference to the private driver state structure @@ -1993,6 +1998,7 @@ static int sam_phyintenable(struct sam_emac_s *priv) { #if defined(SAMA5_EMAC_PHY_KSZ8051) || defined(SAMA5_EMAC_PHY_KSZ8081) uint32_t regval; + uint16_t phyval; int ret; /* Enable management port */ @@ -2000,10 +2006,18 @@ static int sam_phyintenable(struct sam_emac_s *priv) regval = sam_getreg(priv, SAM_EMAC_NCR); sam_putreg(priv, SAM_EMAC_NCR, regval | EMAC_NCR_MPE); - /* Enable link up/down interrupts */ + /* Read the interrupt status register in order to clear any pending + * interrupts + */ - ret = sam_phywrite(priv, priv->phyaddr, MII_KSZ8081_INT, - (MII_KSZ80x1_INT_LDEN | MII_KSZ80x1_INT_LUEN)); + ret = sam_phyread(priv, priv->phyaddr, MII_KSZ8081_INT, &phyval); + if (ret == OK) + { + /* Enable link up/down interrupts */ + + ret = sam_phywrite(priv, priv->phyaddr, MII_KSZ8081_INT, + (MII_KSZ80x1_INT_LDEN | MII_KSZ80x1_INT_LUEN)); + } /* Disable management port (probably) */ diff --git a/arch/arm/src/sama5/sam_emacb.c b/arch/arm/src/sama5/sam_emacb.c index 0161ccd6fad..a149ccba0f0 100644 --- a/arch/arm/src/sama5/sam_emacb.c +++ b/arch/arm/src/sama5/sam_emacb.c @@ -2446,7 +2446,12 @@ static bool sam_is100fdx(struct sam_emac_s *priv, uint16_t physr) * Function: sam_phyintenable * * Description: - * Enable link up/down PHY interrupts + * Enable link up/down PHY interrupts. The interrupt protocol is like this: + * + * - Interrupt status is cleared when the interrupt is enabled. + * - Interrupt occurs. Interrupt is disabled (at the processor level) when + * is received. + * - Interrupt status is cleared when the interrupt is re-enabled. * * Parameters: * priv - A reference to the private driver state structure @@ -2462,6 +2467,7 @@ static int sam_phyintenable(struct sam_emac_s *priv) #if defined(SAMA5_EMAC0_PHY_KSZ8051) || defined(SAMA5_EMAC0_PHY_KSZ8081) || \ defined(SAMA5_EMAC1_PHY_KSZ8051) || defined(SAMA5_EMAC1_PHY_KSZ8081) uint32_t regval; + uint16_t phyval; int ret; /* Does this MAC support a KSZ80x1 PHY? */ @@ -2473,10 +2479,18 @@ static int sam_phyintenable(struct sam_emac_s *priv) regval = sam_getreg(priv, SAM_EMAC_NCR_OFFSET); sam_putreg(priv, SAM_EMAC_NCR_OFFSET, regval | EMAC_NCR_MPE); - /* Enable link up/down interrupts */ + /* Read the interrupt status register in order to clear any pending + * interrupts + */ - ret = sam_phywrite(priv, priv->phyaddr, MII_KSZ8081_INT, - (MII_KSZ80x1_INT_LDEN | MII_KSZ80x1_INT_LUEN)); + ret = sam_phyread(priv, priv->phyaddr, MII_KSZ8081_INT, &phyval); + if (ret == OK) + { + /* Enable link up/down interrupts */ + + ret = sam_phywrite(priv, priv->phyaddr, MII_KSZ8081_INT, + (MII_KSZ80x1_INT_LDEN | MII_KSZ80x1_INT_LUEN)); + } /* Disable management port (probably) */ diff --git a/arch/arm/src/sama5/sam_gmac.c b/arch/arm/src/sama5/sam_gmac.c index 251e7e8e9eb..dc78bb7c26b 100644 --- a/arch/arm/src/sama5/sam_gmac.c +++ b/arch/arm/src/sama5/sam_gmac.c @@ -1923,7 +1923,12 @@ static void sam_phydump(struct sam_gmac_s *priv) * Function: sam_phyintenable * * Description: - * Enable link up/down PHY interrupts + * Enable link up/down PHY interrupts. The interrupt protocol is like this: + * + * - Interrupt status is cleared when the interrupt is enabled. + * - Interrupt occurs. Interrupt is disabled (at the processor level) when + * is received. + * - Interrupt status is cleared when the interrupt is re-enabled. * * Parameters: * priv - A reference to the private driver state structure @@ -1937,18 +1942,25 @@ static void sam_phydump(struct sam_gmac_s *priv) static int sam_phyintenable(struct sam_emac_s *priv) { #if defined(SAMA5_GMAC_PHY_KSZ90x1) + uint16_t phyval; int ret; /* Enable the management port */ sam_enablemdio(priv); - /* Write to the requested register */ + /* Read the interrupt status register in order to clear any pending + * interrupts + */ - /* Enable link up/down interrupts */ + ret = sam_phyread(priv, priv->phyaddr, GMII_KSZ90x1_ICS, &phyval); + if (ret == OK) + { + /* Enable link up/down interrupts */ - ret = sam_phywrite(priv, priv->phyaddr, GMII_KSZ90x1_ICS, - (GMII_KSZ90x1_INT_LDEN | GMII_KSZ90x1_INT_LUEN)); + ret = sam_phywrite(priv, priv->phyaddr, GMII_KSZ90x1_ICS, + (GMII_KSZ90x1_INT_LDEN | GMII_KSZ90x1_INT_LUEN)); + } /* Disable the management port */ diff --git a/arch/arm/src/stm32/stm32_eth.c b/arch/arm/src/stm32/stm32_eth.c index 8b944db77f5..a4d894fc8fb 100644 --- a/arch/arm/src/stm32/stm32_eth.c +++ b/arch/arm/src/stm32/stm32_eth.c @@ -2572,7 +2572,12 @@ static int stm32_ioctl(struct net_driver_s *dev, int cmd, long arg) * Function: stm32_phyintenable * * Description: - * Enable link up/down PHY interrupts + * Enable link up/down PHY interrupts. The interrupt protocol is like this: + * + * - Interrupt status is cleared when the interrupt is enabled. + * - Interrupt occurs. Interrupt is disabled (at the processor level) when + * is received. + * - Interrupt status is cleared when the interrupt is re-enabled. * * Parameters: * priv - A reference to the private driver state structure