Commit 90973d2c authored by Federico Vaga's avatar Federico Vaga

Revert "WIP drv: interrupts are completely handled by external IRQ controllers"

This reverts commit 265c63476db166c69724c66a30df7e6c6ef1873a.
parent aaccb157
...@@ -354,13 +354,14 @@ int zfad_fsm_command(struct fa_dev *fa, uint32_t command) ...@@ -354,13 +354,14 @@ int zfad_fsm_command(struct fa_dev *fa, uint32_t command)
} }
dev_dbg(fa->msgdev, "FSM START Command, Enable interrupts\n"); dev_dbg(fa->msgdev, "FSM START Command, Enable interrupts\n");
/*FIXME enable interrupts ?*/ fa_enable_irqs(fa);
fa_writel(fa, fa->fa_adc_csr_base, fa_writel(fa, fa->fa_adc_csr_base,
&zfad_regs[ZFA_CTL_RST_TRG_STA], 1); &zfad_regs[ZFA_CTL_RST_TRG_STA], 1);
} else { } else {
dev_dbg(fa->msgdev, "FSM STOP Command, Disable interrupts\n"); dev_dbg(fa->msgdev, "FSM STOP Command, Disable interrupts\n");
fa->enable_auto_start = 0; fa->enable_auto_start = 0;
/*FIXME disable interrupts ?*/ fa_disable_irqs(fa);
} }
fa_writel(fa, fa->fa_adc_csr_base, &zfad_regs[ZFA_CTL_FMS_CMD], fa_writel(fa, fa->fa_adc_csr_base, &zfad_regs[ZFA_CTL_FMS_CMD],
......
...@@ -14,6 +14,28 @@ ...@@ -14,6 +14,28 @@
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include "fmc-adc-100m14b4cha.h" #include "fmc-adc-100m14b4cha.h"
#include "fa-spec.h"
/*
* fat_get_irq_status
* @fa: adc descriptor
* @irq_status: destination of irq status
*
* Get irq and clear the register. To clear an interrupt we have to write 1
* on the handled interrupt. We handle all interrupt so we clear all interrupts
*/
static void fa_get_irq_status(struct fa_dev *fa, uint32_t *irq_status)
{
/* Get current interrupts status */
*irq_status = fa_readl(fa, fa->fa_irq_adc_base, &zfad_regs[ZFA_IRQ_ADC_SRC]);
dev_dbg(fa->msgdev,
"IRQ fired an interrupt. IRQ status register: 0x%x\n",
*irq_status);
if (*irq_status)
/* Clear current interrupts status */
fa_writel(fa, fa->fa_irq_adc_base, &zfad_regs[ZFA_IRQ_ADC_SRC],
*irq_status);
}
/* /*
* fa_irq_handler * fa_irq_handler
...@@ -34,37 +56,44 @@ irqreturn_t fa_irq_handler(int irq, void *arg) ...@@ -34,37 +56,44 @@ irqreturn_t fa_irq_handler(int irq, void *arg)
{ {
struct fa_dev *fa = arg; struct fa_dev *fa = arg;
struct zio_cset *cset = fa->zdev->cset; struct zio_cset *cset = fa->zdev->cset;
uint32_t status;
unsigned long flags; unsigned long flags;
struct zfad_block *zfad_block; struct zfad_block *zfad_block;
/* irq to handle */ /* irq to handle */
/* TODO check if it is our interrupt */ fa_get_irq_status(fa, &status);
/* if (!status) */ if (!status)
/* return IRQ_NONE; /\* No interrupt fired by this mezzanine *\/ */ return IRQ_NONE; /* No interrupt fired by this mezzanine */
dev_dbg(fa->msgdev, "Handle ADC interrupts\n"); dev_dbg(fa->msgdev, "Handle ADC interrupts\n");
/* if (status & FA_IRQ_ADC_ACQ_END) {
* Acquiring samples is a critical section /*
* protected against any concurrent abbort trigger. * Acquiring samples is a critical section
* This is done by raising the flag CSET_BUSY at ACQ_END * protected against any concurrent abbort trigger.
* and lowered it at the end of DMA_END. * This is done by raising the flag CSET_BUSY at ACQ_END
*/ * and lowered it at the end of DMA_END.
spin_lock_irqsave(&cset->lock, flags); */
zfad_block = cset->interleave->priv_d; spin_lock_irqsave(&cset->lock, flags);
/* Check first if any concurrent trigger stop */ zfad_block = cset->interleave->priv_d;
/* has deleted zio blocks. In such a case */ /* Check first if any concurrent trigger stop */
/* the flag is not raised and nothing is done */ /* has deleted zio blocks. In such a case */
if (zfad_block != NULL && (cset->ti->flags & ZIO_TI_ARMED)) /* the flag is not raised and nothing is done */
cset->flags |= ZIO_CSET_HW_BUSY; if (zfad_block != NULL && (cset->ti->flags & ZIO_TI_ARMED))
spin_unlock_irqrestore(&cset->lock, flags); cset->flags |= ZIO_CSET_HW_BUSY;
if (cset->flags & ZIO_CSET_HW_BUSY) { spin_unlock_irqrestore(&cset->lock, flags);
/* Job deferred to the workqueue: */ if (cset->flags & ZIO_CSET_HW_BUSY) {
/* Start DMA and ack irq on the carrier */ /* Job deferred to the workqueue: */
queue_work(fa_workqueue, &fa->irq_work); /* Start DMA and ack irq on the carrier */
/* register the core firing the IRQ in order to */ queue_work(fa_workqueue, &fa->irq_work);
/* check right IRQ seq.: ACQ_END followed by DMA_END */ /* register the core firing the IRQ in order to */
fa->last_irq_core_src = irq; /* check right IRQ seq.: ACQ_END followed by DMA_END */
fa->last_irq_core_src = irq;
}
} else { /* unexpected interrupt we have to ack anyway */
dev_err(fa->msgdev,
"%s unexpected interrupt 0x%x\n",
__func__, status);
} }
return IRQ_HANDLED; return IRQ_HANDLED;
...@@ -90,17 +119,48 @@ int fa_setup_irqs(struct fa_dev *fa) ...@@ -90,17 +119,48 @@ int fa_setup_irqs(struct fa_dev *fa)
/* workqueue is required to execute DMA transaction */ /* workqueue is required to execute DMA transaction */
INIT_WORK(&fa->irq_work, fa_irq_work); INIT_WORK(&fa->irq_work, fa_irq_work);
/* set IRQ sources to listen */
fa->irq_src = FA_IRQ_SRC_ACQ;
return err; return err;
} }
int fa_free_irqs(struct fa_dev *fa) int fa_free_irqs(struct fa_dev *fa)
{ {
/*
* When we unload the driver the FPGA is still running so it may
* rises interrupts. Disable IRQs in order to prevent spurious
* interrupt when the driver is not there to handle them.
*/
fa_disable_irqs(fa);
/* Release ADC IRQs */ /* Release ADC IRQs */
free_irq(platform_get_irq(fa->pdev, ADC_IRQ_TRG), fa); free_irq(platform_get_irq(fa->pdev, ADC_IRQ_TRG), fa);
return 0; return 0;
} }
int fa_enable_irqs(struct fa_dev *fa)
{
dev_dbg(fa->msgdev, "Enable interrupts\n");
fa_writel(fa, fa->fa_irq_adc_base,
&zfad_regs[ZFA_IRQ_ADC_ENABLE_MASK],
FA_IRQ_ADC_ACQ_END);
return 0;
}
int fa_disable_irqs(struct fa_dev *fa)
{
dev_dbg(fa->msgdev, "Disable interrupts\n");
fa_writel(fa, fa->fa_irq_adc_base,
&zfad_regs[ZFA_IRQ_ADC_DISABLE_MASK],
FA_IRQ_ADC_ACQ_END);
return 0;
}
int fa_ack_irq(struct fa_dev *fa, int irq_id) int fa_ack_irq(struct fa_dev *fa, int irq_id)
{ {
return 0; return 0;
......
...@@ -94,6 +94,16 @@ const struct zfa_field_desc zfad_regs[] = { ...@@ -94,6 +94,16 @@ const struct zfa_field_desc zfad_regs[] = {
[ZFA_CH4_THRES] = {0x214, 0x0000FFFF, 1}, [ZFA_CH4_THRES] = {0x214, 0x0000FFFF, 1},
[ZFA_CH4_DLY] = {0x218, 0xFFFFFFFF, 0}, [ZFA_CH4_DLY] = {0x218, 0xFFFFFFFF, 0},
/* IRQ */
[ZFA_IRQ_ADC_DISABLE_MASK] = {0x00, 0x00000003, 0},
[ZFA_IRQ_ADC_ENABLE_MASK] = {0x04, 0x00000003, 0},
[ZFA_IRQ_ADC_MASK_STATUS] = {0x08, 0x00000003, 0},
[ZFA_IRQ_ADC_SRC] = {0x0C, 0x00000003, 0},
[ZFA_IRQ_VIC_CTRL] = {0x00, 0x000FFFFF, 0},
[ZFA_IRQ_VIC_ENABLE_MASK] = {0x08, 0x00000003, 0},
[ZFA_IRQ_VIC_DISABLE_MASK] = {0x0C, 0x00000003, 0},
[ZFA_IRQ_VIC_MASK_STATUS] = {0x10, 0x00000003, 0},
/* UTC */ /* UTC */
[ZFA_UTC_SECONDS] = {0x00, ~0x0, 0}, [ZFA_UTC_SECONDS] = {0x00, ~0x0, 0},
[ZFA_UTC_COARSE] = {0x04, ~0x0, 0}, [ZFA_UTC_COARSE] = {0x04, ~0x0, 0},
......
...@@ -298,6 +298,15 @@ enum zfadc_dregs_enum { ...@@ -298,6 +298,15 @@ enum zfadc_dregs_enum {
/* Other options */ /* Other options */
ZFA_MULT_MAX_SAMP, ZFA_MULT_MAX_SAMP,
/* end:declaration block requiring some order */ /* end:declaration block requiring some order */
/* two wishbone core for IRQ: VIC, ADC */
ZFA_IRQ_ADC_DISABLE_MASK,
ZFA_IRQ_ADC_ENABLE_MASK,
ZFA_IRQ_ADC_MASK_STATUS,
ZFA_IRQ_ADC_SRC,
ZFA_IRQ_VIC_CTRL,
ZFA_IRQ_VIC_DISABLE_MASK,
ZFA_IRQ_VIC_ENABLE_MASK,
ZFA_IRQ_VIC_MASK_STATUS,
/* UTC core */ /* UTC core */
ZFA_UTC_SECONDS, ZFA_UTC_SECONDS,
ZFA_UTC_COARSE, ZFA_UTC_COARSE,
...@@ -344,6 +353,23 @@ enum fa_sw_param_id { ...@@ -344,6 +353,23 @@ enum fa_sw_param_id {
ZFA_SW_PARAM_COMMON_LAST, ZFA_SW_PARAM_COMMON_LAST,
}; };
/*
* Bit pattern used in order to factorize code between SVEC and SPEC
* Depending of the carrier, ADC may have to listen vaious IRQ sources
* SVEC: only ACQ irq source (end DMA irq is manged by vmebus driver)
* SPEC: ACQ and DMA irq source
*/
enum fa_irq_src {
FA_IRQ_SRC_ACQ = 0x1,
FA_IRQ_SRC_DMA = 0x2,
};
/* adc IRQ values */
enum fa_irq_adc {
FA_IRQ_ADC_NONE = 0x0,
FA_IRQ_ADC_ACQ_END = 0x2,
};
/* Carrier-specific operations (gateware does not fully decouple /* Carrier-specific operations (gateware does not fully decouple
carrier specific stuff, such as DMA or resets, from carrier specific stuff, such as DMA or resets, from
mezzanine-specific operations). */ mezzanine-specific operations). */
...@@ -578,6 +604,8 @@ extern void fa_trig_exit(void); ...@@ -578,6 +604,8 @@ extern void fa_trig_exit(void);
extern void zfat_irq_trg_fire(struct zio_cset *cset); extern void zfat_irq_trg_fire(struct zio_cset *cset);
extern int fa_setup_irqs(struct fa_dev *fa); extern int fa_setup_irqs(struct fa_dev *fa);
extern int fa_free_irqs(struct fa_dev *fa); extern int fa_free_irqs(struct fa_dev *fa);
extern int fa_enable_irqs(struct fa_dev *fa);
extern int fa_disable_irqs(struct fa_dev *fa);
/* Functions exported by onewire.c */ /* Functions exported by onewire.c */
extern int fa_onewire_init(struct fa_dev *fa); extern int fa_onewire_init(struct fa_dev *fa);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment