diff --git a/arch/arm/src/sam34/sam_emac.c b/arch/arm/src/sam34/sam_emac.c index 5073db1d68..cbca247c60 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 61da3490f9..2cb0400ba5 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 428251d8fb..0161ccd6fa 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 c2a88349f7..23bfa713a1 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 5f72bae268..251e7e8e9e 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 4b83ceac3e..8b944db77f 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 * diff --git a/drivers/net/phy_notify.c b/drivers/net/phy_notify.c index 29b68c3d8f..430811444e 100644 --- a/drivers/net/phy_notify.c +++ b/drivers/net/phy_notify.c @@ -255,7 +255,7 @@ static int phy_handler(FAR struct phy_notify_s *client) int errcode = errno; DEBUGASSERT(errcode > 0); - ndbg("ERROR: sigqueue failed: %d\n", errcode); + nlldbg("ERROR: sigqueue failed: %d\n", errcode); UNUSED(errcode); } diff --git a/include/nuttx/net/gmii.h b/include/nuttx/net/gmii.h index 729047dc23..c8b924d841 100644 --- a/include/nuttx/net/gmii.h +++ b/include/nuttx/net/gmii.h @@ -73,7 +73,7 @@ /* Extended Registers: Registers 16-31 may be used for vendor specific abilities */ -/* Micrel KSZ9021/31 Vendor Specific Register Addresses */ +/* Micrel KSZ9021/31 Vendor Specific Register Addresses **************************************/ #define GMII_KSZ90x1_RLPBK 17 /* Remote loopback, LED mode */ #define GMII_KSZ90x1_LINKMD 18 /* LinkMD(c) cable diagnostic */ @@ -269,6 +269,28 @@ /* Extend Register - Data Write Register (16-bit data value) */ /* Extend Register - Data Read Register (16-bit data value) */ +/* Micrel KSZ9021/31 Vendor Specific Register Bit Definitions ********************************/ + +/* KSZ8021/31 Register 27: Interrupt control/status */ + +#define GMII_KSZ90x1_INT_JEN (1 << 15) /* Jabber interrupt enable */ +#define GMII_KSZ90x1_INT_REEN (1 << 14) /* Receive error interrupt enable */ +#define GMII_KSZ90x1_INT_PREN (1 << 13) /* Page received interrupt enable */ +#define GMII_KSZ90x1_INT_PDFEN (1 << 12) /* Parallel detect fault interrupt enable */ +#define GMII_KSZ90x1_INT_LPAEN (1 << 11) /* Link partner acknowledge interrupt enable */ +#define GMII_KSZ90x1_INT_LDEN (1 << 10) /* Link down fault interrupt enable */ +#define GMII_KSZ90x1_INT_RFEN (1 << 9) /* Remote fault interrupt enable */ +#define GMII_KSZ90x1_INT_LUEN (1 << 8) /* Link up interrupt enable */ + +#define GMII_KSZ90x1_INT_J (1 << 7) /* Jabber interrupt */ +#define GMII_KSZ90x1_INT_RE (1 << 6) /* Receive error interrupt */ +#define GMII_KSZ90x1_INT_PR (1 << 5) /* Page received interrupt */ +#define GMII_KSZ90x1_INT_PDF (1 << 4) /* Parallel detect fault interrupt */ +#define GMII_KSZ90x1_INT_LPA (1 << 3) /* Link partner acknowledge interrupt */ +#define GMII_KSZ90x1_INT_LD (1 << 2) /* Link down fault interrupt */ +#define GMII_KSZ90x1_INT_RF (1 << 1) /* Remote fault interrupt */ +#define GMII_KSZ90x1_INT_LU (1 << 0) /* Link up interrupt */ + /********************************************************************************************* * Type Definitions *********************************************************************************************/ diff --git a/include/nuttx/net/mii.h b/include/nuttx/net/mii.h index 47726c14e4..1d9ad1f9ea 100644 --- a/include/nuttx/net/mii.h +++ b/include/nuttx/net/mii.h @@ -487,6 +487,26 @@ /* Bits 5-15: Reserved */ #define KSZ8081_DRCTRL_PLLOFF (1 << 4) /* Bit 4: Turn PLL off in EDPD mode */ /* Bits 0-3: Reserved */ +/* KSZ8051/81 Register 0x1b: Interrupt control/status */ + +#define MII_KSZ80x1_INT_JEN (1 << 15) /* Jabber interrupt enable */ +#define MII_KSZ80x1_INT_REEN (1 << 14) /* Receive error interrupt enable */ +#define MII_KSZ80x1_INT_PREN (1 << 13) /* Page received interrupt enable */ +#define MII_KSZ80x1_INT_PDFEN (1 << 12) /* Parallel detect fault interrupt enable */ +#define MII_KSZ80x1_INT_LPAEN (1 << 11) /* Link partner acknowledge interrupt enable */ +#define MII_KSZ80x1_INT_LDEN (1 << 10) /* Link down fault interrupt enable */ +#define MII_KSZ80x1_INT_RFEN (1 << 9) /* Remote fault interrupt enable */ +#define MII_KSZ80x1_INT_LUEN (1 << 8) /* Link up interrupt enable */ + +#define MII_KSZ80x1_INT_J (1 << 7) /* Jabber interrupt */ +#define MII_KSZ80x1_INT_RE (1 << 6) /* Receive error interrupt */ +#define MII_KSZ80x1_INT_PR (1 << 5) /* Page received interrupt */ +#define MII_KSZ80x1_INT_PDF (1 << 4) /* Parallel detect fault interrupt */ +#define MII_KSZ80x1_INT_LPA (1 << 3) /* Link partner acknowledge interrupt */ +#define MII_KSZ80x1_INT_LD (1 << 2) /* Link down fault interrupt */ +#define MII_KSZ80x1_INT_RF (1 << 1) /* Remote fault interrupt */ +#define MII_KSZ80x1_INT_LU (1 << 0) /* Link up interrupt */ + /* KSZ8051/81 Register 0x1e: PHY Control 1 */ /* Bits 10-15: Reserved */ #define MII_PHYCTRL1_ENPAUSE (1 << 9) /* Bit 9: Enable pause */