diff --git a/arch/arm/src/sam34/sam_emac.c b/arch/arm/src/sam34/sam_emac.c index 5073db1d68d..cbca247c60d 100644 --- a/arch/arm/src/sam34/sam_emac.c +++ b/arch/arm/src/sam34/sam_emac.c @@ -383,6 +383,9 @@ static void sam_phydump(struct sam_emac_s *priv); # define sam_phydump(priv) #endif +#if defined(CONFIG_NETDEV_PHY_IOCTL) && defined(CONFIG_ARCH_PHY_INTERRUPT) +static int sam_phyintenable(struct sam_emac_s *priv); +#endif static int sam_phywait(struct sam_emac_s *priv); static int sam_phyreset(struct sam_emac_s *priv); static int sam_phyfind(struct sam_emac_s *priv, uint8_t *phyaddr); @@ -1810,7 +1813,14 @@ static int sam_ioctl(struct net_driver_s *dev, int cmd, long arg) case SIOCMIINOTIFY: /* Set up for PHY event notifications */ { struct mii_iotcl_notify_s *req = (struct mii_iotcl_notify_s *)((uintptr_t)arg); + ret = phy_notify_subscribe(dev->d_ifname, req->pid, req->signo, req->arg); + if (ret == OK) + { + /* Enable PHY link up/down interrupts */ + + ret = sam_phyintenable(priv); + } } break; #endif @@ -1923,6 +1933,49 @@ static void sam_phydump(struct sam_emac_s *priv) } #endif +/**************************************************************************** + * Function: sam_phyintenable + * + * Description: + * Enable link up/down PHY interrupts + * + * Parameters: + * priv - A reference to the private driver state structure + * + * Returned Value: + * OK on success; Negated errno (-ETIMEDOUT) on failure. + * + ****************************************************************************/ + +#if defined(CONFIG_NETDEV_PHY_IOCTL) && defined(CONFIG_ARCH_PHY_INTERRUPT) +static int sam_phyintenable(struct sam_emac_s *priv) +{ +#if defined(CONFIG_ETH0_PHY_KSZ8051) || defined(CONFIG_ETH0_PHY_KSZ8081) + uint32_t regval; + int ret; + + /* Enable management port */ + + regval = sam_getreg(priv, SAM_EMAC_NCR); + sam_putreg(priv, SAM_EMAC_NCR, regval | EMAC_NCR_MPE); + + /* 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) */ + + sam_putreg(priv, SAM_EMAC_NCR, regval); + return ret; + +#else +# warning Missing logic + return -ENOSYS; +#endif +} +#endif + /**************************************************************************** * Function: sam_phywait * diff --git a/arch/arm/src/sama5/sam_emaca.c b/arch/arm/src/sama5/sam_emaca.c index 61da3490f94..2cb0400ba5e 100644 --- a/arch/arm/src/sama5/sam_emaca.c +++ b/arch/arm/src/sama5/sam_emaca.c @@ -388,6 +388,9 @@ static void sam_phydump(struct sam_emac_s *priv); # define sam_phydump(priv) #endif +#if defined(CONFIG_NETDEV_PHY_IOCTL) && defined(CONFIG_ARCH_PHY_INTERRUPT) +static int sam_phyintenable(struct sam_emac_s *priv); +#endif static int sam_phywait(struct sam_emac_s *priv); static int sam_phyreset(struct sam_emac_s *priv); static int sam_phyfind(struct sam_emac_s *priv, uint8_t *phyaddr); @@ -1851,7 +1854,14 @@ static int sam_ioctl(struct net_driver_s *dev, int cmd, long arg) case SIOCMIINOTIFY: /* Set up for PHY event notifications */ { struct mii_iotcl_notify_s *req = (struct mii_iotcl_notify_s *)((uintptr_t)arg); + ret = phy_notify_subscribe(dev->d_ifname, req->pid, req->signo, req->arg); + if (ret == OK) + { + /* Enable PHY link up/down interrupts */ + + ret = sam_phyintenable(priv); + } } break; #endif @@ -1964,6 +1974,49 @@ static void sam_phydump(struct sam_emac_s *priv) } #endif +/**************************************************************************** + * Function: sam_phyintenable + * + * Description: + * Enable link up/down PHY interrupts + * + * Parameters: + * priv - A reference to the private driver state structure + * + * Returned Value: + * OK on success; Negated errno (-ETIMEDOUT) on failure. + * + ****************************************************************************/ + +#if defined(CONFIG_NETDEV_PHY_IOCTL) && defined(CONFIG_ARCH_PHY_INTERRUPT) +static int sam_phyintenable(struct sam_emac_s *priv) +{ +#if defined(SAMA5_EMAC_PHY_KSZ8051) || defined(SAMA5_EMAC_PHY_KSZ8081) + uint32_t regval; + int ret; + + /* Enable management port */ + + regval = sam_getreg(priv, SAM_EMAC_NCR); + sam_putreg(priv, SAM_EMAC_NCR, regval | EMAC_NCR_MPE); + + /* 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) */ + + sam_putreg(priv, SAM_EMAC_NCR, regval); + return ret; + +#else +# warning Missing logic + return -ENOSYS; +#endif +} +#endif + /**************************************************************************** * Function: sam_phywait * diff --git a/arch/arm/src/sama5/sam_emacb.c b/arch/arm/src/sama5/sam_emacb.c index 428251d8fb6..0161ccd6fad 100644 --- a/arch/arm/src/sama5/sam_emacb.c +++ b/arch/arm/src/sama5/sam_emacb.c @@ -411,6 +411,9 @@ struct sam_emac_s /* Used to track transmit and receive descriptors */ uint8_t phyaddr; /* PHY address (pre-defined by pins on reset) */ +#if defined(CONFIG_NETDEV_PHY_IOCTL) && defined(CONFIG_ARCH_PHY_INTERRUPT) + uint8_t phytype; /* See SAMA5_EMAC0/1_PHY_TYPE definitions */ +#endif uint16_t txhead; /* Circular buffer head index */ uint16_t txtail; /* Circular buffer tail index */ uint16_t rxndx; /* RX index for current processing RX descriptor */ @@ -502,6 +505,9 @@ static bool sam_is100hdx(struct sam_emac_s *priv, uint16_t physr); static bool sam_is10fdx(struct sam_emac_s *priv, uint16_t physr); static bool sam_is100fdx(struct sam_emac_s *priv, uint16_t physr); +#if defined(CONFIG_NETDEV_PHY_IOCTL) && defined(CONFIG_ARCH_PHY_INTERRUPT) +static int sam_phyintenable(struct sam_emac_s *priv); +#endif static int sam_phywait(struct sam_emac_s *priv); static int sam_phyreset(struct sam_emac_s *priv); static int sam_phyfind(struct sam_emac_s *priv, uint8_t *phyaddr); @@ -2226,7 +2232,14 @@ static int sam_ioctl(struct net_driver_s *dev, int cmd, long arg) case SIOCMIINOTIFY: /* Set up for PHY event notifications */ { struct mii_iotcl_notify_s *req = (struct mii_iotcl_notify_s *)((uintptr_t)arg); + ret = phy_notify_subscribe(dev->d_ifname, req->pid, req->signo, req->arg); + if (ret == OK) + { + /* Enable PHY link up/down interrupts */ + + ret = sam_phyintenable(priv); + } } break; #endif @@ -2429,6 +2442,57 @@ static bool sam_is100fdx(struct sam_emac_s *priv, uint16_t physr) return (physr & mask) == match; } +/**************************************************************************** + * Function: sam_phyintenable + * + * Description: + * Enable link up/down PHY interrupts + * + * Parameters: + * priv - A reference to the private driver state structure + * + * Returned Value: + * OK on success; Negated errno (-ETIMEDOUT) on failure. + * + ****************************************************************************/ + +#if defined(CONFIG_NETDEV_PHY_IOCTL) && defined(CONFIG_ARCH_PHY_INTERRUPT) +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; + int ret; + + /* Does this MAC support a KSZ80x1 PHY? */ + + if (priv->phytype == SAMA5_PHY_KSZ8051 || priv->phytype == SAMA5_PHY_KSZ8081) + { + /* Enable management port */ + + regval = sam_getreg(priv, SAM_EMAC_NCR_OFFSET); + sam_putreg(priv, SAM_EMAC_NCR_OFFSET, regval | EMAC_NCR_MPE); + + /* 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) */ + + sam_putreg(priv, SAM_EMAC_NCR_OFFSET, regval); + } + else +#endif + { + ndbg("ERROR: Unsupported PHY type: %d\n", priv->phytype); + ret = -ENOSYS; + } + + return ret; +} +#endif + /**************************************************************************** * Function: sam_phywait * @@ -3634,21 +3698,32 @@ int sam_emac_initialize(int intf) { struct sam_emac_s *priv; const struct sam_emacattr_s *attr; +#if defined(CONFIG_NETDEV_PHY_IOCTL) && defined(CONFIG_ARCH_PHY_INTERRUPT) + uint8_t phytype; +#endif int ret; #if defined(CONFIG_SAMA5_EMAC0) if (intf == EMAC0_INTF) { - priv = &g_emac0; - attr = &g_emac0_attr; + priv = &g_emac0; + attr = &g_emac0_attr; + +#if defined(CONFIG_NETDEV_PHY_IOCTL) && defined(CONFIG_ARCH_PHY_INTERRUPT) + phytype = SAMA5_EMAC0_PHY_TYPE; +#endif } else #endif #if defined(CONFIG_SAMA5_EMAC1) if (intf == EMAC1_INTF) { - priv = &g_emac1; - attr = &g_emac1_attr; + priv = &g_emac1; + attr = &g_emac1_attr; + +#if defined(CONFIG_NETDEV_PHY_IOCTL) && defined(CONFIG_ARCH_PHY_INTERRUPT) + phytype = SAMA5_EMAC1_PHY_TYPE; +#endif } else #endif @@ -3670,7 +3745,11 @@ int sam_emac_initialize(int intf) #endif #ifdef CONFIG_NETDEV_PHY_IOCTL priv->dev.d_ioctl = sam_ioctl; /* Support PHY ioctl() calls */ +#ifdef CONFIG_ARCH_PHY_INTERRUPT + priv->phytype = phytype; /* Type of PHY on port */ #endif +#endif + priv->dev.d_private = priv; /* Used to recover private state from dev */ /* Create a watchdog for timing polling for and timing of transmissions */ diff --git a/arch/arm/src/sama5/sam_ethernet.h b/arch/arm/src/sama5/sam_ethernet.h index c2a88349f7f..23bfa713a1a 100644 --- a/arch/arm/src/sama5/sam_ethernet.h +++ b/arch/arm/src/sama5/sam_ethernet.h @@ -49,6 +49,14 @@ /************************************************************************************ * Pre-processor Definitions ************************************************************************************/ +/* Understood PHY types */ + +#define SAMA5_PHY_DM9161 0 +#define SAMA5_PHY_LAN8700 1 +#define SAMA5_PHY_KSZ8051 2 +#define SAMA5_PHY_KSZ8081 3 +#define SAMA5_PHY_KSZ90x1 4 + /* Definitions for use with sam_phy_boardinitialize */ #if defined(CONFIG_SAMA5_HAVE_EMACA) @@ -84,25 +92,39 @@ #if defined(CONFIG_SAMA5_GMAC_ISETH0) # if defined(CONFIG_ETH0_PHY_DM9161) -# define SAMA5_GMAC_PHY_DM9161 1 +# define SAMA5_GMAC_PHY_DM9161 1 +# define SAMA5_GMAC_PHY_TYPE SAMA5_PHY_DM9161 # elif defined(CONFIG_ETH0_PHY_LAN8700) # define SAMA5_GMAC_PHY_LAN8700 1 +# define SAMA5_GMAC_PHY_TYPE SAMA5_PHY_LAN8700 # elif defined(CONFIG_ETH0_PHY_KSZ8051) # define SAMA5_GMAC_PHY_KSZ8051 1 +# define SAMA5_GMAC_PHY_TYPE SAMA5_PHY_KSZ8051 +# elif defined(CONFIG_ETH0_PHY_KSZ8081) +# define SAMA5_GMAC_PHY_KSZ8081 1 +# define SAMA5_GMAC_PHY_TYPE SAMA5_PHY_KSZ8081 # elif defined(CONFIG_ETH0_PHY_KSZ90x1) # define SAMA5_GMAC_PHY_KSZ90x1 1 +# define SAMA5_GMAC_PHY_TYPE SAMA5_PHY_KSZ90x1 # else # error ETH0 PHY unrecognized # endif #elif defined(CONFIG_SAMA5_GMAC) # if defined(CONFIG_ETH1_PHY_DM9161) -# define SAMA5_GMAC_PHY_DM9161 1 +# define SAMA5_GMAC_PHY_DM9161 1 +# define SAMA5_GMAC_PHY_TYPE SAMA5_PHY_DM9161 # elif defined(CONFIG_ETH1_PHY_LAN8700) # define SAMA5_GMAC_PHY_LAN8700 1 +# define SAMA5_GMAC_PHY_TYPE SAMA5_PHY_LAN8700 # elif defined(CONFIG_ETH1_PHY_KSZ8051) # define SAMA5_GMAC_PHY_KSZ8051 1 +# define SAMA5_GMAC_PHY_TYPE SAMA5_PHY_KSZ8051 +# elif defined(CONFIG_ETH1_PHY_KSZ8081) +# define SAMA5_GMAC_PHY_KSZ8081 1 +# define SAMA5_GMAC_PHY_TYPE SAMA5_PHY_KSZ8081 # elif defined(CONFIG_ETH1_PHY_KSZ90x1) # define SAMA5_GMAC_PHY_KSZ90x1 1 +# define SAMA5_GMAC_PHY_TYPE SAMA5_PHY_KSZ90x1 # else # error ETH1 PHY unrecognized # endif @@ -110,29 +132,39 @@ #if defined(CONFIG_SAMA5_EMAC_ISETH0) # if defined(CONFIG_ETH0_PHY_DM9161) -# define SAMA5_EMAC_PHY_DM9161 1 +# define SAMA5_EMAC_PHY_DM9161 1 +# define SAMA5_EMAC_PHY_TYPE SAMA5_PHY_DM9161 # elif defined(CONFIG_ETH0_PHY_LAN8700) # define SAMA5_EMAC_PHY_LAN8700 1 +# define SAMA5_EMAC_PHY_TYPE SAMA5_PHY_LAN8700 # elif defined(CONFIG_ETH0_PHY_KSZ8051) # define SAMA5_EMAC_PHY_KSZ8051 1 +# define SAMA5_EMAC_PHY_TYPE SAMA5_PHY_KSZ8051 # elif defined(CONFIG_ETH0_PHY_KSZ8081) # define SAMA5_EMAC_PHY_KSZ8081 1 +# define SAMA5_EMAC_PHY_TYPE SAMA5_PHY_KSZ8081 # elif defined(CONFIG_ETH0_PHY_KSZ90x1) # define SAMA5_EMAC_PHY_KSZ90x1 1 +# define SAMA5_EMAC_PHY_TYPE SAMA5_PHY_KSZ90x1 # else # error ETH0 PHY unrecognized # endif #elif defined(CONFIG_SAMA5_EMACA) # if defined(CONFIG_ETH1_PHY_DM9161) -# define SAMA5_EMAC_PHY_DM9161 1 +# define SAMA5_EMAC_PHY_DM9161 1 +# define SAMA5_EMAC_PHY_TYPE SAMA5_PHY_DM9161 # elif defined(CONFIG_ETH1_PHY_LAN8700) # define SAMA5_EMAC_PHY_LAN8700 1 +# define SAMA5_EMAC_PHY_TYPE SAMA5_PHY_LAN8700 # elif defined(CONFIG_ETH1_PHY_KSZ8051) # define SAMA5_EMAC_PHY_KSZ8051 1 +# define SAMA5_EMAC_PHY_TYPE SAMA5_PHY_KSZ8051 # elif defined(CONFIG_ETH1_PHY_KSZ8081) # define SAMA5_EMAC_PHY_KSZ8081 1 +# define SAMA5_EMAC_PHY_TYPE SAMA5_PHY_KSZ8081 # elif defined(CONFIG_ETH1_PHY_KSZ90x1) # define SAMA5_EMAC_PHY_KSZ90x1 1 +# define SAMA5_EMAC_PHY_TYPE SAMA5_PHY_KSZ90x1 # else # error ETH1 PHY unrecognized # endif @@ -140,29 +172,39 @@ #if defined(CONFIG_SAMA5_EMAC0_ISETH0) # if defined(CONFIG_ETH0_PHY_DM9161) -# define SAMA5_EMAC0_PHY_DM9161 1 +# define SAMA5_EMAC0_PHY_DM9161 1 +# define SAMA5_EMAC0_PHY_TYPE SAMA5_PHY_DM9161 # elif defined(CONFIG_ETH0_PHY_LAN8700) # define SAMA5_EMAC0_PHY_LAN8700 1 +# define SAMA5_EMAC0_PHY_TYPE SAMA5_PHY_LAN8700 # elif defined(CONFIG_ETH0_PHY_KSZ8051) # define SAMA5_EMAC0_PHY_KSZ8051 1 +# define SAMA5_EMAC0_PHY_TYPE SAMA5_PHY_KSZ8051 # elif defined(CONFIG_ETH0_PHY_KSZ8081) # define SAMA5_EMAC0_PHY_KSZ8081 1 +# define SAMA5_EMAC0_PHY_TYPE SAMA5_PHY_KSZ8081 # elif defined(CONFIG_ETH0_PHY_KSZ90x1) # define SAMA5_EMAC0_PHY_KSZ90x1 1 +# define SAMA5_EMAC0_PHY_TYPE SAMA5_PHY_KSZ90x1 # else # error ETH0 PHY unrecognized # endif #elif defined(CONFIG_SAMA5_EMAC0) # if defined(CONFIG_ETH1_PHY_DM9161) -# define SAMA5_EMAC0_PHY_DM9161 1 +# define SAMA5_EMAC0_PHY_DM9161 1 +# define SAMA5_EMAC0_PHY_TYPE SAMA5_PHY_DM9161 # elif defined(CONFIG_ETH1_PHY_LAN8700) # define SAMA5_EMAC0_PHY_LAN8700 1 +# define SAMA5_EMAC0_PHY_TYPE SAMA5_PHY_LAN8700 # elif defined(CONFIG_ETH1_PHY_KSZ8051) # define SAMA5_EMAC0_PHY_KSZ8051 1 +# define SAMA5_EMAC0_PHY_TYPE SAMA5_PHY_KSZ8051 # elif defined(CONFIG_ETH0_PHY_KSZ8081) # define SAMA5_EMAC0_PHY_KSZ8081 1 +# define SAMA5_EMAC0_PHY_TYPE SAMA5_PHY_KSZ8081 # elif defined(CONFIG_ETH1_PHY_KSZ90x1) # define SAMA5_EMAC0_PHY_KSZ90x1 1 +# define SAMA5_EMAC0_PHY_TYPE SAMA5_PHY_KSZ90x1 # else # error ETH1 PHY unrecognized # endif @@ -170,29 +212,39 @@ #if defined(CONFIG_SAMA5_EMAC1_ISETH0) # if defined(CONFIG_ETH0_PHY_DM9161) -# define SAMA5_EMAC1_PHY_DM9161 1 +# define SAMA5_EMAC1_PHY_DM9161 1 +# define SAMA5_EMAC1_PHY_TYPE SAMA5_PHY_DM9161 # elif defined(CONFIG_ETH0_PHY_LAN8700) # define SAMA5_EMAC1_PHY_LAN8700 1 +# define SAMA5_EMAC1_PHY_TYPE SAMA5_PHY_LAN8700 # elif defined(CONFIG_ETH0_PHY_KSZ8051) # define SAMA5_EMAC1_PHY_KSZ8051 1 +# define SAMA5_EMAC1_PHY_TYPE SAMA5_PHY_KSZ8051 # elif defined(CONFIG_ETH0_PHY_KSZ8081) # define SAMA5_EMAC1_PHY_KSZ8081 1 +# define SAMA5_EMAC1_PHY_TYPE SAMA5_PHY_KSZ8081 # elif defined(CONFIG_ETH0_PHY_KSZ90x1) # define SAMA5_EMAC1_PHY_KSZ90x1 1 +# define SAMA5_EMAC1_PHY_TYPE SAMA5_PHY_KSZ90x1 # else # error ETH0 PHY unrecognized # endif #elif defined(CONFIG_SAMA5_EMAC1) # if defined(CONFIG_ETH1_PHY_DM9161) -# define SAMA5_EMAC1_PHY_DM9161 1 +# define SAMA5_EMAC1_PHY_DM9161 1 +# define SAMA5_EMAC1_PHY_TYPE SAMA5_PHY_DM9161 # elif defined(CONFIG_ETH1_PHY_LAN8700) # define SAMA5_EMAC1_PHY_LAN8700 1 +# define SAMA5_EMAC1_PHY_TYPE SAMA5_PHY_LAN8700 # elif defined(CONFIG_ETH1_PHY_KSZ8051) # define SAMA5_EMAC1_PHY_KSZ8051 1 +# define SAMA5_EMAC1_PHY_TYPE SAMA5_PHY_KSZ8051 # elif defined(CONFIG_ETH0_PHY_KSZ8081) # define SAMA5_EMAC1_PHY_KSZ8081 1 +# define SAMA5_EMAC1_PHY_TYPE SAMA5_PHY_KSZ8081 # elif defined(CONFIG_ETH1_PHY_KSZ90x1) # define SAMA5_EMAC1_PHY_KSZ90x1 1 +# define SAMA5_EMAC1_PHY_TYPE SAMA5_PHY_KSZ90x1 # else # error ETH1 PHY unrecognized # endif diff --git a/arch/arm/src/sama5/sam_gmac.c b/arch/arm/src/sama5/sam_gmac.c index 5f72bae2683..251e7e8e9eb 100644 --- a/arch/arm/src/sama5/sam_gmac.c +++ b/arch/arm/src/sama5/sam_gmac.c @@ -313,6 +313,9 @@ static void sam_phydump(struct sam_gmac_s *priv); # define sam_phydump(priv) #endif +#if defined(CONFIG_NETDEV_PHY_IOCTL) && defined(CONFIG_ARCH_PHY_INTERRUPT) +static int sam_phyintenable(struct sam_emac_s *priv); +#endif static void sam_enablemdio(struct sam_gmac_s *priv); static void sam_disablemdio(struct sam_gmac_s *priv); static int sam_phywait(struct sam_gmac_s *priv); @@ -1806,7 +1809,14 @@ static int sam_ioctl(struct net_driver_s *dev, int cmd, long arg) case SIOCMIINOTIFY: /* Set up for PHY event notifications */ { struct mii_iotcl_notify_s *req = (struct mii_iotcl_notify_s *)((uintptr_t)arg); + ret = phy_notify_subscribe(dev->d_ifname, req->pid, req->signo, req->arg); + if (ret == OK) + { + /* Enable PHY link up/down interrupts */ + + ret = sam_phyintenable(priv); + } } break; #endif @@ -1840,6 +1850,7 @@ static int sam_ioctl(struct net_driver_s *dev, int cmd, long arg) case SIOCSMIIREG: /* Set register in MII PHY */ { struct mii_ioctl_data_s *req = (struct mii_ioctl_data_s *)((uintptr_t)arg); + /* Enable the management port */ sam_enablemdio(priv); @@ -1908,6 +1919,49 @@ static void sam_phydump(struct sam_gmac_s *priv) } #endif +/**************************************************************************** + * Function: sam_phyintenable + * + * Description: + * Enable link up/down PHY interrupts + * + * Parameters: + * priv - A reference to the private driver state structure + * + * Returned Value: + * OK on success; Negated errno (-ETIMEDOUT) on failure. + * + ****************************************************************************/ + +#if defined(CONFIG_NETDEV_PHY_IOCTL) && defined(CONFIG_ARCH_PHY_INTERRUPT) +static int sam_phyintenable(struct sam_emac_s *priv) +{ +#if defined(SAMA5_GMAC_PHY_KSZ90x1) + int ret; + + /* Enable the management port */ + + sam_enablemdio(priv); + + /* Write to the requested register */ + + /* Enable link up/down interrupts */ + + ret = sam_phywrite(priv, priv->phyaddr, GMII_KSZ90x1_ICS, + (GMII_KSZ90x1_INT_LDEN | GMII_KSZ90x1_INT_LUEN)); + + /* Disable the management port */ + + sam_disablemdio(priv); + return ret; + +#else +# warning Missing logic + return -ENOSYS; +#endif +} +#endif + /**************************************************************************** * Function: sam_enablemdio * diff --git a/arch/arm/src/stm32/stm32_eth.c b/arch/arm/src/stm32/stm32_eth.c index 4b83ceac3e1..8b944db77f5 100644 --- a/arch/arm/src/stm32/stm32_eth.c +++ b/arch/arm/src/stm32/stm32_eth.c @@ -669,6 +669,9 @@ static void stm32_rxdescinit(FAR struct stm32_ethmac_s *priv); /* PHY Initialization */ +#if defined(CONFIG_NETDEV_PHY_IOCTL) && defined(CONFIG_ARCH_PHY_INTERRUPT) +static int stm32_phyintenable(FAR struct stm32_ethmac_s *priv); +#endif static int stm32_phyread(uint16_t phydevaddr, uint16_t phyregaddr, uint16_t *value); static int stm32_phywrite(uint16_t phydevaddr, uint16_t phyregaddr, uint16_t value); #ifdef CONFIG_ETH0_PHY_DM9161 @@ -2511,6 +2514,9 @@ static void stm32_rxdescinit(FAR struct stm32_ethmac_s *priv) #ifdef CONFIG_NETDEV_PHY_IOCTL static int stm32_ioctl(struct net_driver_s *dev, int cmd, long arg) { +#ifdef CONFIG_ARCH_PHY_INTERRUPT + FAR struct stm32_ethmac_s *priv = (FAR struct stm32_ethmac_s *)dev->d_private; +#endif int ret; switch (cmd) @@ -2519,7 +2525,14 @@ static int stm32_ioctl(struct net_driver_s *dev, int cmd, long arg) case SIOCMIINOTIFY: /* Set up for PHY event notifications */ { struct mii_iotcl_notify_s *req = (struct mii_iotcl_notify_s *)((uintptr_t)arg); + ret = phy_notify_subscribe(dev->d_ifname, req->pid, req->signo, req->arg); + if (ret == OK) + { + /* Enable PHY link up/down interrupts */ + + ret = stm32_phyintenable(priv); + } } break; #endif @@ -2555,6 +2568,28 @@ static int stm32_ioctl(struct net_driver_s *dev, int cmd, long arg) } #endif /* CONFIG_NETDEV_PHY_IOCTL */ +/**************************************************************************** + * Function: stm32_phyintenable + * + * Description: + * Enable link up/down PHY interrupts + * + * Parameters: + * priv - A reference to the private driver state structure + * + * Returned Value: + * OK on success; Negated errno (-ETIMEDOUT) on failure. + * + ****************************************************************************/ + +#if defined(CONFIG_NETDEV_PHY_IOCTL) && defined(CONFIG_ARCH_PHY_INTERRUPT) +static int stm32_phyintenable(struct stm32_ethmac_s *priv) +{ +#warning Missing logic + return -ENOSYS; +} +#endif + /**************************************************************************** * Function: stm32_phyread *