Change the way PHY interrupts work: disable automatically. Then we have to re-subscribe each time after the interrupt fires

This commit is contained in:
Gregory Nutt 2014-08-17 16:51:56 -06:00
parent b84210d10d
commit b4d98da404
3 changed files with 207 additions and 27 deletions

View File

@ -108,6 +108,43 @@ static xcpt_t g_gmac_handler;
* Private Functions
************************************************************************************/
/************************************************************************************
* Name: sam_emac_phy_enable and sam_gmac_enable
************************************************************************************/
#ifdef CONFIG_SAMA5_PIOE_IRQ
#ifdef CONFIG_SAMA5_EMACA
static void sam_emac_phy_enable(bool enable)
{
phydbg("IRQ%d: enable=%d\n", IRQ_INT_ETH1, enable);
if (enable)
{
sam_pioirqenable(IRQ_INT_ETH1);
}
else
{
sam_pioirqdisable(IRQ_INT_ETH1);
}
}
#endif
#ifdef CONFIG_SAMA5_GMAC
static void sam_gmac_phy_enable(bool enable)
{
phydbg("IRQ%d: enable=%d\n", IRQ_INT_ETH0, enable);
if (enable)
{
sam_pioirqenable(IRQ_INT_ETH0);
}
else
{
sam_pioirqdisable(IRQ_INT_ETH0);
}
}
#endif
#endif
/************************************************************************************
* Public Functions
************************************************************************************/
@ -174,6 +211,10 @@ void weak_function sam_netinitialize(void)
* NULL. If handler is NULL, then the interrupt is detached and disabled
* instead.
*
* The PHY interrupt is always disabled upon return. The caller must
* call back through the enable function point to control the state of
* the interrupt.
*
* This interrupt may or may not be available on a given platform depending
* on how the network hardware architecture is implemented. In a typical
* case, the PHY interrupt is provided to board-level logic as a GPIO
@ -187,16 +228,20 @@ void weak_function sam_netinitialize(void)
*
* Typical usage:
* a. OS service logic (not application logic*) attaches to the PHY
* PHY interrupt.
* b. When the PHY interrupt occurs, work should be scheduled on the
* worker thread (or perhaps a dedicated application thread).
* PHY interrupt and enables the PHY interrupt.
* b. When the PHY interrupt occurs: (1) the interrupt should be
* disabled and () work should be scheduled on the worker thread (or
* perhaps a dedicated application thread).
* c. That worker thread should use the SIOCGMIIPHY, SIOCGMIIREG,
* and SIOCSMIIREG ioctl calls** to communicate with the PHY,
* determine what network event took place (Link Up/Down?), and
* take the appropriate actions.
* d. It should then interact the the PHY to clear any pending
* interrupts, then re-enable the PHY interrupt.
*
* * This is an OS internal interface and should not be used from
* application space.
* application space. Rather applications should use the SIOCMIISIG
* ioctl to receive a signal when a PHY event occurs.
* ** This interrupt is really of no use if the Ethernet MAC driver
* does not support these ioctl calls.
*
@ -208,6 +253,8 @@ void weak_function sam_netinitialize(void)
* asserts an interrupt. Must reside in OS space, but can
* signal tasks in user space. A value of NULL can be passed
* in order to detach and disable the PHY interrupt.
* enable - A function pointer that be unsed to enable or disable the
* PHY interrupt.
*
* Returned Value:
* The previous PHY interrupt handler address is returned. This allows you
@ -218,12 +265,13 @@ void weak_function sam_netinitialize(void)
****************************************************************************/
#ifdef CONFIG_SAMA5_PIOE_IRQ
xcpt_t arch_phy_irq(FAR const char *intf, xcpt_t handler)
xcpt_t arch_phy_irq(FAR const char *intf, xcpt_t handler, phy_enable_t *enable)
{
irqstate_t flags;
xcpt_t *phandler;
xcpt_t oldhandler;
pio_pinset_t pinset;
phy_enable_t enabler;
int irq;
DEBUGASSERT(intf);
@ -243,6 +291,7 @@ xcpt_t arch_phy_irq(FAR const char *intf, xcpt_t handler)
phandler = &g_emac_handler;
pinset = PIO_INT_ETH1;
irq = IRQ_INT_ETH1;
enabler = sam_emac_phy_enable;
}
else
#endif
@ -253,6 +302,7 @@ xcpt_t arch_phy_irq(FAR const char *intf, xcpt_t handler)
phandler = &g_gmac_handler;
pinset = PIO_INT_ETH0;
irq = IRQ_INT_ETH0;
enabler = sam_gmac_phy_enable;
}
else
#endif
@ -279,15 +329,25 @@ xcpt_t arch_phy_irq(FAR const char *intf, xcpt_t handler)
phydbg("Configure pin: %08x\n", pinset);
sam_pioirq(pinset);
phydbg("Enable IRQ: %d\n", irq);
phydbg("Attach IRQ%d\n", irq);
(void)irq_attach(irq, handler);
sam_pioirqenable(irq);
}
else
{
phydbg("Disable IRQ: %d\n", irq);
phydbg("Detach IRQ%d\n", irq);
(void)irq_detach(irq);
sam_pioirqdisable(irq);
enabler = NULL;
}
/* Return with the interrupt disabled in either case */
sam_pioirqdisable(irq);
/* Return the enabling function pointer */
if (enable)
{
*enable = enabler;
}
/* Return the old button handler (so that it can be restored) */

View File

@ -108,6 +108,43 @@ static xcpt_t g_gmac_handler;
* Private Functions
************************************************************************************/
/************************************************************************************
* Name: sam_emac_phy_enable and sam_gmac_enable
************************************************************************************/
#ifdef CONFIG_SAMA5_PIOE_IRQ
#ifdef CONFIG_SAMA5_EMACA
static void sam_emac_phy_enable(bool enable)
{
phydbg("IRQ%d: enable=%d\n", IRQ_INT_ETH1, enable);
if (enable)
{
sam_pioirqenable(IRQ_INT_ETH1);
}
else
{
sam_pioirqdisable(IRQ_INT_ETH1);
}
}
#endif
#ifdef CONFIG_SAMA5_GMAC
static void sam_gmac_phy_enable(bool enable)
{
phydbg("IRQ%d: enable=%d\n", IRQ_INT_ETH0, enable);
if (enable)
{
sam_pioirqenable(IRQ_INT_ETH0);
}
else
{
sam_pioirqdisable(IRQ_INT_ETH0);
}
}
#endif
#endif
/************************************************************************************
* Public Functions
************************************************************************************/
@ -174,6 +211,10 @@ void weak_function sam_netinitialize(void)
* NULL. If handler is NULL, then the interrupt is detached and disabled
* instead.
*
* The PHY interrupt is always disabled upon return. The caller must
* call back through the enable function point to control the state of
* the interrupt.
*
* This interrupt may or may not be available on a given platform depending
* on how the network hardware architecture is implemented. In a typical
* case, the PHY interrupt is provided to board-level logic as a GPIO
@ -187,16 +228,20 @@ void weak_function sam_netinitialize(void)
*
* Typical usage:
* a. OS service logic (not application logic*) attaches to the PHY
* PHY interrupt.
* b. When the PHY interrupt occurs, work should be scheduled on the
* worker thread (or perhaps a dedicated application thread).
* PHY interrupt and enables the PHY interrupt.
* b. When the PHY interrupt occurs: (1) the interrupt should be
* disabled and () work should be scheduled on the worker thread (or
* perhaps a dedicated application thread).
* c. That worker thread should use the SIOCGMIIPHY, SIOCGMIIREG,
* and SIOCSMIIREG ioctl calls** to communicate with the PHY,
* determine what network event took place (Link Up/Down?), and
* take the appropriate actions.
* d. It should then interact the the PHY to clear any pending
* interrupts, then re-enable the PHY interrupt.
*
* * This is an OS internal interface and should not be used from
* application space.
* application space. Rather applications should use the SIOCMIISIG
* ioctl to receive a signal when a PHY event occurs.
* ** This interrupt is really of no use if the Ethernet MAC driver
* does not support these ioctl calls.
*
@ -208,6 +253,8 @@ void weak_function sam_netinitialize(void)
* asserts an interrupt. Must reside in OS space, but can
* signal tasks in user space. A value of NULL can be passed
* in order to detach and disable the PHY interrupt.
* enable - A function pointer that be unsed to enable or disable the
* PHY interrupt.
*
* Returned Value:
* The previous PHY interrupt handler address is returned. This allows you
@ -218,12 +265,13 @@ void weak_function sam_netinitialize(void)
****************************************************************************/
#ifdef CONFIG_SAMA5_PIOE_IRQ
xcpt_t arch_phy_irq(FAR const char *intf, xcpt_t handler)
xcpt_t arch_phy_irq(FAR const char *intf, xcpt_t handler, phy_enable_t *enable)
{
irqstate_t flags;
xcpt_t *phandler;
xcpt_t oldhandler;
pio_pinset_t pinset;
phy_enable_t enabler;
int irq;
DEBUGASSERT(intf);
@ -243,6 +291,7 @@ xcpt_t arch_phy_irq(FAR const char *intf, xcpt_t handler)
phandler = &g_emac_handler;
pinset = PIO_INT_ETH1;
irq = IRQ_INT_ETH1;
enabler = sam_emac_phy_enable;
}
else
#endif
@ -253,6 +302,7 @@ xcpt_t arch_phy_irq(FAR const char *intf, xcpt_t handler)
phandler = &g_gmac_handler;
pinset = PIO_INT_ETH0;
irq = IRQ_INT_ETH0;
enabler = sam_gmac_phy_enable;
}
else
#endif
@ -279,15 +329,25 @@ xcpt_t arch_phy_irq(FAR const char *intf, xcpt_t handler)
phydbg("Configure pin: %08x\n", pinset);
sam_pioirq(pinset);
phydbg("Enable IRQ: %d\n", irq);
phydbg("Attach IRQ%d\n", irq);
(void)irq_attach(irq, handler);
sam_pioirqenable(irq);
}
else
{
phydbg("Disable IRQ: %d\n", irq);
phydbg("Detach IRQ%d\n", irq);
(void)irq_detach(irq);
sam_pioirqdisable(irq);
enabler = NULL;
}
/* Return with the interrupt disabled in either case */
sam_pioirqdisable(irq);
/* Return the enabling function pointer */
if (enable)
{
*enable = enabler;
}
/* Return the old button handler (so that it can be restored) */

View File

@ -108,6 +108,43 @@ static xcpt_t g_emac1_handler;
* Private Functions
************************************************************************************/
/************************************************************************************
* Name: sam_emac_phy_enable and sam_gmac_enable
************************************************************************************/
#ifdef CONFIG_SAMA5_PIOE_IRQ
#ifdef CONFIG_SAMA5_EMAC0
static void sam_emac0_phy_enable(bool enable)
{
phydbg("IRQ%d: enable=%d\n", IRQ_INT_ETH0, enable);
if (enable)
{
sam_pioirqenable(IRQ_INT_ETH0);
}
else
{
sam_pioirqdisable(IRQ_INT_ETH0);
}
}
#endif
#ifdef CONFIG_SAMA5_EMAC1
static void sam_emac1_phy_enable(bool enable)
{
phydbg("IRQ%d: enable=%d\n", IRQ_INT_ETH1, enable);
if (enable)
{
sam_pioirqenable(IRQ_INT_ETH1);
}
else
{
sam_pioirqdisable(IRQ_INT_ETH1);
}
}
#endif
#endif
/************************************************************************************
* Public Functions
************************************************************************************/
@ -143,6 +180,10 @@ void weak_function sam_netinitialize(void)
* NULL. If handler is NULL, then the interrupt is detached and disabled
* instead.
*
* The PHY interrupt is always disabled upon return. The caller must
* call back through the enable function point to control the state of
* the interrupt.
*
* This interrupt may or may not be available on a given platform depending
* on how the network hardware architecture is implemented. In a typical
* case, the PHY interrupt is provided to board-level logic as a GPIO
@ -156,16 +197,20 @@ void weak_function sam_netinitialize(void)
*
* Typical usage:
* a. OS service logic (not application logic*) attaches to the PHY
* PHY interrupt.
* b. When the PHY interrupt occurs, work should be scheduled on the
* worker thread (or perhaps a dedicated application thread).
* PHY interrupt and enables the PHY interrupt.
* b. When the PHY interrupt occurs: (1) the interrupt should be
* disabled and () work should be scheduled on the worker thread (or
* perhaps a dedicated application thread).
* c. That worker thread should use the SIOCGMIIPHY, SIOCGMIIREG,
* and SIOCSMIIREG ioctl calls** to communicate with the PHY,
* determine what network event took place (Link Up/Down?), and
* take the appropriate actions.
* d. It should then interact the the PHY to clear any pending
* interrupts, then re-enable the PHY interrupt.
*
* * This is an OS internal interface and should not be used from
* application space.
* application space. Rather applications should use the SIOCMIISIG
* ioctl to receive a signal when a PHY event occurs.
* ** This interrupt is really of no use if the Ethernet MAC driver
* does not support these ioctl calls.
*
@ -177,6 +222,8 @@ void weak_function sam_netinitialize(void)
* asserts an interrupt. Must reside in OS space, but can
* signal tasks in user space. A value of NULL can be passed
* in order to detach and disable the PHY interrupt.
* enable - A function pointer that be unsed to enable or disable the
* PHY interrupt.
*
* Returned Value:
* The previous PHY interrupt handler address is returned. This allows you
@ -187,12 +234,13 @@ void weak_function sam_netinitialize(void)
****************************************************************************/
#ifdef CONFIG_SAMA5_PIOE_IRQ
xcpt_t arch_phy_irq(FAR const char *intf, xcpt_t handler)
xcpt_t arch_phy_irq(FAR const char *intf, xcpt_t handler, phy_enable_t *enable)
{
irqstate_t flags;
xcpt_t *phandler;
xcpt_t oldhandler;
pio_pinset_t pinset;
phy_enable_t enabler;
int irq;
DEBUGASSERT(intf);
@ -212,6 +260,7 @@ xcpt_t arch_phy_irq(FAR const char *intf, xcpt_t handler)
phandler = &g_emac0_handler;
pinset = PIO_INT_ETH0;
irq = IRQ_INT_ETH0;
enabler = sam_emac0_phy_enable;
}
else
#endif
@ -222,6 +271,7 @@ xcpt_t arch_phy_irq(FAR const char *intf, xcpt_t handler)
phandler = &g_emac1_handler;
pinset = PIO_INT_ETH1;
irq = IRQ_INT_ETH1;
enabler = sam_emac1_phy_enable;
}
else
#endif
@ -248,15 +298,25 @@ xcpt_t arch_phy_irq(FAR const char *intf, xcpt_t handler)
phydbg("Configure pin: %08x\n", pinset);
sam_pioirq(pinset);
phydbg("Enable IRQ: %d\n", irq);
phydbg("Attach IRQ%d\n", irq);
(void)irq_attach(irq, handler);
sam_pioirqenable(irq);
}
else
{
phydbg("Disable IRQ: %d\n", irq);
phydbg("Detach IRQ%d\n", irq);
(void)irq_detach(irq);
sam_pioirqdisable(irq);
enabler = NULL;
}
/* Return with the interrupt disabled in either case */
sam_pioirqdisable(irq);
/* Return the enabling function pointer */
if (enable)
{
*enable = enabler;
}
/* Return the old button handler (so that it can be restored) */