diff --git a/kernel/spec-nic.h b/kernel/spec-nic.h index c0239b601178f51b231b3fa7704e44c3b4ae5a35..ddb20cd5eeb590f4545c790a30225bd8c0c74d91 100644 --- a/kernel/spec-nic.h +++ b/kernel/spec-nic.h @@ -50,7 +50,9 @@ #define WRN_WRC_DEFAULT_NAME "fmc/wr_nic_dio-wrc.bin" /* the various interrupt sources for the VIC */ -#define WRN_VIC_MASK_NIC 0x0002 +#define WRN_VIC_MASK_TXTSU 0x0001 +#define WRN_VIC_MASK_NIC 0x0002 +#define WRN_VIC_MASK_DIO 0x0004 /* This is somehow generic, but I find no better place at this time */ #ifndef SET_HI32 diff --git a/kernel/wr-dio.h b/kernel/wr-dio.h index 1d999cbf17ebe4958effce0d3067490adcc8e4ce..4c0e5b624ab6704f773c6bf81823fc0e32173362 100644 --- a/kernel/wr-dio.h +++ b/kernel/wr-dio.h @@ -11,6 +11,7 @@ #define __WR_DIO_H__ /* This should be included by both the kernel and the tools */ +#ifdef __KERNEL__ #include "wbgen-regs/wr-dio-regs.h" /* For GPIO we have no wb-gen header */ @@ -26,6 +27,10 @@ struct wrn_gpio_block { #define WRN_GPIO_OE_N(bit) (1 << ((4 * (bit)) + 1)) #define WRN_GPIO_TERM(bit) (1 << ((4 * (bit)) + 2)) +extern irqreturn_t wrn_dio_interrupt(struct fmc_device *fmc); + +#endif /* __KERNEL__ */ + enum wr_dio_cmd_name { WR_DIO_CMD_PULSE, WR_DIO_CMD_STAMP, diff --git a/kernel/wr-nic-dio.c b/kernel/wr-nic-dio.c index 143c4e5cf09909c59269bfe649bcfa8b2a9674c0..a7ab0c36fb910dd13feccbecae3b32286b299260 100644 --- a/kernel/wr-nic-dio.c +++ b/kernel/wr-nic-dio.c @@ -11,6 +11,7 @@ #include <linux/fmc.h> #include <linux/fmc-sdb.h> #include <linux/ktime.h> +#include <linux/platform_device.h> #include <asm/uaccess.h> #include "spec-nic.h" #include "wr_nic/wr-nic.h" @@ -321,3 +322,14 @@ out: } return ret; } + +irqreturn_t wrn_dio_interrupt(struct fmc_device *fmc) +{ + struct platform_device *pdev = fmc->mezzanine_data; + struct wrn_drvdata *drvdata = pdev->dev.platform_data; + struct DIO_WB __iomem *dio = drvdata->wrdio_base; + + printk("%s: %x %x\n", __func__, readl(&dio->EIC_IMR), + readl(&dio->EIC_ISR)); + return IRQ_NONE; +} diff --git a/kernel/wr-nic-eth.c b/kernel/wr-nic-eth.c index 10c40e3c56cec0f7ff4ce29ff80252af3d0533db..7861ce474dce09fd4d7bbb418ce18229bfc8c471 100644 --- a/kernel/wr-nic-eth.c +++ b/kernel/wr-nic-eth.c @@ -15,6 +15,7 @@ #include <linux/fmc-sdb.h> #include "spec.h" #include "spec-nic.h" +#include "wr-dio.h" #include "wr_nic/wr-nic.h" #include "wbgen-regs/vic-regs.h" @@ -58,15 +59,15 @@ irqreturn_t wrn_handler(int irq, void *dev_id) drvdata = pdev->dev.platform_data; vic = (typeof(vic))drvdata->vic_base; - mask = readl(&vic->RISR); - while (mask & WRN_VIC_MASK_NIC) { - ret = wrn_interrupt(irq, drvdata->wrn); - mask = readl(&vic->RISR); + while ( (mask = readl(&vic->RISR)) ) { + if (mask & WRN_VIC_MASK_NIC) + ret = wrn_interrupt(irq, drvdata->wrn); + if (mask & WRN_VIC_MASK_TXTSU) + ret = wrn_tstamp_interrupt(irq, drvdata->wrn); + if (mask & WRN_VIC_MASK_DIO) + ret = wrn_dio_interrupt(fmc /* different arg! */); + writel(mask, &vic->EOIR); } - writel(WRN_VIC_MASK_NIC, &vic->EOIR); - - if (mask) - printk("%s: irq %i (mask %x)\n", __func__, irq, mask); fmc->op->irq_ack(fmc); /* after ack, disable and re-enable the irq, so to force an edge */