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)
}
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,
&zfad_regs[ZFA_CTL_RST_TRG_STA], 1);
} else {
dev_dbg(fa->msgdev, "FSM STOP Command, Disable interrupts\n");
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],
......
......@@ -14,6 +14,28 @@
#include <linux/interrupt.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
......@@ -34,37 +56,44 @@ irqreturn_t fa_irq_handler(int irq, void *arg)
{
struct fa_dev *fa = arg;
struct zio_cset *cset = fa->zdev->cset;
uint32_t status;
unsigned long flags;
struct zfad_block *zfad_block;
/* irq to handle */
/* TODO check if it is our interrupt */
/* if (!status) */
/* return IRQ_NONE; /\* No interrupt fired by this mezzanine *\/ */
fa_get_irq_status(fa, &status);
if (!status)
return IRQ_NONE; /* No interrupt fired by this mezzanine */
dev_dbg(fa->msgdev, "Handle ADC interrupts\n");
/*
* Acquiring samples is a critical section
* protected against any concurrent abbort trigger.
* 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;
/* Check first if any concurrent trigger stop */
/* has deleted zio blocks. In such a case */
/* the flag is not raised and nothing is done */
if (zfad_block != NULL && (cset->ti->flags & ZIO_TI_ARMED))
cset->flags |= ZIO_CSET_HW_BUSY;
spin_unlock_irqrestore(&cset->lock, flags);
if (cset->flags & ZIO_CSET_HW_BUSY) {
/* Job deferred to the workqueue: */
/* Start DMA and ack irq on the carrier */
queue_work(fa_workqueue, &fa->irq_work);
/* register the core firing the IRQ in order to */
/* check right IRQ seq.: ACQ_END followed by DMA_END */
fa->last_irq_core_src = irq;
if (status & FA_IRQ_ADC_ACQ_END) {
/*
* Acquiring samples is a critical section
* protected against any concurrent abbort trigger.
* 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;
/* Check first if any concurrent trigger stop */
/* has deleted zio blocks. In such a case */
/* the flag is not raised and nothing is done */
if (zfad_block != NULL && (cset->ti->flags & ZIO_TI_ARMED))
cset->flags |= ZIO_CSET_HW_BUSY;
spin_unlock_irqrestore(&cset->lock, flags);
if (cset->flags & ZIO_CSET_HW_BUSY) {
/* Job deferred to the workqueue: */
/* Start DMA and ack irq on the carrier */
queue_work(fa_workqueue, &fa->irq_work);
/* register the core firing the IRQ in order to */
/* 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;
......@@ -90,17 +119,48 @@ int fa_setup_irqs(struct fa_dev *fa)
/* workqueue is required to execute DMA transaction */
INIT_WORK(&fa->irq_work, fa_irq_work);
/* set IRQ sources to listen */
fa->irq_src = FA_IRQ_SRC_ACQ;
return err;
}
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 */
free_irq(platform_get_irq(fa->pdev, ADC_IRQ_TRG), fa);
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)
{
return 0;
......
......@@ -94,6 +94,16 @@ const struct zfa_field_desc zfad_regs[] = {
[ZFA_CH4_THRES] = {0x214, 0x0000FFFF, 1},
[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 */
[ZFA_UTC_SECONDS] = {0x00, ~0x0, 0},
[ZFA_UTC_COARSE] = {0x04, ~0x0, 0},
......
......@@ -298,6 +298,15 @@ enum zfadc_dregs_enum {
/* Other options */
ZFA_MULT_MAX_SAMP,
/* 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 */
ZFA_UTC_SECONDS,
ZFA_UTC_COARSE,
......@@ -344,6 +353,23 @@ enum fa_sw_param_id {
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 stuff, such as DMA or resets, from
mezzanine-specific operations). */
......@@ -578,6 +604,8 @@ extern void fa_trig_exit(void);
extern void zfat_irq_trg_fire(struct zio_cset *cset);
extern int fa_setup_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 */
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