Blackfin: add support for the on-chip MAC status interrupts

This patch provides infrastructure for MAC Wake-On-Lan and PHYINT use in
phylib.  New Interrupts added:

IRQ_MAC_PHYINT   /* PHY_INT Interrupt */
IRQ_MAC_MMCINT   /* MMC Counter Interrupt */
IRQ_MAC_RXFSINT  /* RX Frame-Status Interrupt */
IRQ_MAC_TXFSINT  /* TX Frame-Status Interrupt */
IRQ_MAC_WAKEDET  /* Wake-Up Interrupt */
IRQ_MAC_RXDMAERR /* RX DMA Direction Error Interrupt */
IRQ_MAC_TXDMAERR /* TX DMA Direction Error Interrupt */
IRQ_MAC_STMDONE  /* Station Mgt. Transfer Done Interrupt */

On BF537/6 the implementation is not straight forward since there are now
two chained chained_handlers.  A cleaner approach would have been to add
latter IRQs to the demux of IRQ_GENERIC_ERROR.

Signed-off-by: Michael Hennerich <michael.hennerich@analog.com>
Signed-off-by: Mike Frysinger <vapier@gentoo.org>
This commit is contained in:
Michael Hennerich 2010-02-19 15:09:10 +00:00 committed by Mike Frysinger
parent b274080145
commit aec59c9113
4 changed files with 166 additions and 7 deletions

View File

@ -151,7 +151,16 @@
#define GPIO_IRQ_BASE IRQ_PF0
#define NR_MACH_IRQS (IRQ_PH15 + 1)
#define IRQ_MAC_PHYINT 119 /* PHY_INT Interrupt */
#define IRQ_MAC_MMCINT 120 /* MMC Counter Interrupt */
#define IRQ_MAC_RXFSINT 121 /* RX Frame-Status Interrupt */
#define IRQ_MAC_TXFSINT 122 /* TX Frame-Status Interrupt */
#define IRQ_MAC_WAKEDET 123 /* Wake-Up Interrupt */
#define IRQ_MAC_RXDMAERR 124 /* RX DMA Direction Error Interrupt */
#define IRQ_MAC_TXDMAERR 125 /* TX DMA Direction Error Interrupt */
#define IRQ_MAC_STMDONE 126 /* Station Mgt. Transfer Done Interrupt */
#define NR_MACH_IRQS (IRQ_MAC_STMDONE + 1)
#define NR_IRQS (NR_MACH_IRQS + NR_SPARE_IRQS)
#define IVG7 7

View File

@ -151,7 +151,16 @@
#define GPIO_IRQ_BASE IRQ_PF0
#define NR_MACH_IRQS (IRQ_PH15 + 1)
#define IRQ_MAC_PHYINT 119 /* PHY_INT Interrupt */
#define IRQ_MAC_MMCINT 120 /* MMC Counter Interrupt */
#define IRQ_MAC_RXFSINT 121 /* RX Frame-Status Interrupt */
#define IRQ_MAC_TXFSINT 122 /* TX Frame-Status Interrupt */
#define IRQ_MAC_WAKEDET 123 /* Wake-Up Interrupt */
#define IRQ_MAC_RXDMAERR 124 /* RX DMA Direction Error Interrupt */
#define IRQ_MAC_TXDMAERR 125 /* TX DMA Direction Error Interrupt */
#define IRQ_MAC_STMDONE 126 /* Station Mgt. Transfer Done Interrupt */
#define NR_MACH_IRQS (IRQ_MAC_STMDONE + 1)
#define NR_IRQS (NR_MACH_IRQS + NR_SPARE_IRQS)
#define IVG7 7

View File

@ -134,7 +134,16 @@
#define GPIO_IRQ_BASE IRQ_PF0
#define NR_MACH_IRQS (IRQ_PH15 + 1)
#define IRQ_MAC_PHYINT 98 /* PHY_INT Interrupt */
#define IRQ_MAC_MMCINT 99 /* MMC Counter Interrupt */
#define IRQ_MAC_RXFSINT 100 /* RX Frame-Status Interrupt */
#define IRQ_MAC_TXFSINT 101 /* TX Frame-Status Interrupt */
#define IRQ_MAC_WAKEDET 102 /* Wake-Up Interrupt */
#define IRQ_MAC_RXDMAERR 103 /* RX DMA Direction Error Interrupt */
#define IRQ_MAC_TXDMAERR 104 /* TX DMA Direction Error Interrupt */
#define IRQ_MAC_STMDONE 105 /* Station Mgt. Transfer Done Interrupt */
#define NR_MACH_IRQS (IRQ_MAC_STMDONE + 1)
#define NR_IRQS (NR_MACH_IRQS + NR_SPARE_IRQS)
#define IVG7 7

View File

@ -325,7 +325,6 @@ static int error_int_mask;
static void bfin_generic_error_mask_irq(unsigned int irq)
{
error_int_mask &= ~(1L << (irq - IRQ_PPI_ERROR));
if (!error_int_mask)
bfin_internal_mask_irq(IRQ_GENERIC_ERROR);
}
@ -416,6 +415,127 @@ static void bfin_demux_error_irq(unsigned int int_err_irq,
}
#endif /* BF537_GENERIC_ERROR_INT_DEMUX */
#if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE)
static int mac_stat_int_mask;
static void bfin_mac_status_ack_irq(unsigned int irq)
{
switch (irq) {
case IRQ_MAC_MMCINT:
bfin_write_EMAC_MMC_TIRQS(
bfin_read_EMAC_MMC_TIRQE() &
bfin_read_EMAC_MMC_TIRQS());
bfin_write_EMAC_MMC_RIRQS(
bfin_read_EMAC_MMC_RIRQE() &
bfin_read_EMAC_MMC_RIRQS());
break;
case IRQ_MAC_RXFSINT:
bfin_write_EMAC_RX_STKY(
bfin_read_EMAC_RX_IRQE() &
bfin_read_EMAC_RX_STKY());
break;
case IRQ_MAC_TXFSINT:
bfin_write_EMAC_TX_STKY(
bfin_read_EMAC_TX_IRQE() &
bfin_read_EMAC_TX_STKY());
break;
case IRQ_MAC_WAKEDET:
bfin_write_EMAC_WKUP_CTL(
bfin_read_EMAC_WKUP_CTL() | MPKS | RWKS);
break;
default:
/* These bits are W1C */
bfin_write_EMAC_SYSTAT(1L << (irq - IRQ_MAC_PHYINT));
break;
}
}
static void bfin_mac_status_mask_irq(unsigned int irq)
{
mac_stat_int_mask &= ~(1L << (irq - IRQ_MAC_PHYINT));
#ifdef BF537_GENERIC_ERROR_INT_DEMUX
switch (irq) {
case IRQ_MAC_PHYINT:
bfin_write_EMAC_SYSCTL(bfin_read_EMAC_SYSCTL() & ~PHYIE);
break;
default:
break;
}
#else
if (!mac_stat_int_mask)
bfin_internal_mask_irq(IRQ_MAC_ERROR);
#endif
bfin_mac_status_ack_irq(irq);
}
static void bfin_mac_status_unmask_irq(unsigned int irq)
{
#ifdef BF537_GENERIC_ERROR_INT_DEMUX
switch (irq) {
case IRQ_MAC_PHYINT:
bfin_write_EMAC_SYSCTL(bfin_read_EMAC_SYSCTL() | PHYIE);
break;
default:
break;
}
#else
if (!mac_stat_int_mask)
bfin_internal_unmask_irq(IRQ_MAC_ERROR);
#endif
mac_stat_int_mask |= 1L << (irq - IRQ_MAC_PHYINT);
}
#ifdef CONFIG_PM
int bfin_mac_status_set_wake(unsigned int irq, unsigned int state)
{
#ifdef BF537_GENERIC_ERROR_INT_DEMUX
return bfin_internal_set_wake(IRQ_GENERIC_ERROR, state);
#else
return bfin_internal_set_wake(IRQ_MAC_ERROR, state);
#endif
}
#endif
static struct irq_chip bfin_mac_status_irqchip = {
.name = "MACST",
.ack = bfin_ack_noop,
.mask_ack = bfin_mac_status_mask_irq,
.mask = bfin_mac_status_mask_irq,
.unmask = bfin_mac_status_unmask_irq,
#ifdef CONFIG_PM
.set_wake = bfin_mac_status_set_wake,
#endif
};
static void bfin_demux_mac_status_irq(unsigned int int_err_irq,
struct irq_desc *inta_desc)
{
int i, irq = 0;
u32 status = bfin_read_EMAC_SYSTAT();
for (i = 0; i < (IRQ_MAC_STMDONE - IRQ_MAC_PHYINT); i++)
if (status & (1L << i)) {
irq = IRQ_MAC_PHYINT + i;
break;
}
if (irq) {
if (mac_stat_int_mask & (1L << (irq - IRQ_MAC_PHYINT))) {
bfin_handle_irq(irq);
} else {
bfin_mac_status_ack_irq(irq);
pr_debug("IRQ %d:"
" MASKED MAC ERROR INTERRUPT ASSERTED\n",
irq);
}
} else
printk(KERN_ERR
"%s : %s : LINE %d :\nIRQ ?: MAC ERROR"
" INTERRUPT ASSERTED BUT NO SOURCE FOUND\n",
__func__, __FILE__, __LINE__);
}
#endif
static inline void bfin_set_irq_handler(unsigned irq, irq_flow_handler_t handle)
{
#ifdef CONFIG_IPIPE
@ -1070,7 +1190,11 @@ int __init init_arch_irq(void)
set_irq_chained_handler(irq, bfin_demux_error_irq);
break;
#endif
#if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE)
case IRQ_MAC_ERROR:
set_irq_chained_handler(irq, bfin_demux_mac_status_irq);
break;
#endif
#ifdef CONFIG_SMP
case IRQ_SUPPLE_0:
case IRQ_SUPPLE_1:
@ -1111,14 +1235,22 @@ int __init init_arch_irq(void)
for (irq = IRQ_PPI_ERROR; irq <= IRQ_UART1_ERROR; irq++)
set_irq_chip_and_handler(irq, &bfin_generic_error_irqchip,
handle_level_irq);
#if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE)
set_irq_chained_handler(IRQ_MAC_ERROR, bfin_demux_mac_status_irq);
#endif
#endif
#if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE)
for (irq = IRQ_MAC_PHYINT; irq <= IRQ_MAC_STMDONE; irq++)
set_irq_chip_and_handler(irq, &bfin_mac_status_irqchip,
handle_level_irq);
#endif
/* if configured as edge, then will be changed to do_edge_IRQ */
for (irq = GPIO_IRQ_BASE; irq < NR_MACH_IRQS; irq++)
for (irq = GPIO_IRQ_BASE;
irq < (GPIO_IRQ_BASE + MAX_BLACKFIN_GPIOS); irq++)
set_irq_chip_and_handler(irq, &bfin_gpio_irqchip,
handle_level_irq);
bfin_write_IMASK(0);
CSYNC();
ilat = bfin_read_ILAT();