mirror of https://github.com/thesofproject/sof.git
interrupt: add possibility for manual irq unmasking
Adds possibility for interrupt handler to decide, whether it wants to manually handle unmasking irq or have it done automatically. Signed-off-by: Tomasz Lauda <tomasz.lauda@linux.intel.com>
This commit is contained in:
parent
f9a491f405
commit
ffa13fcc4d
|
@ -244,17 +244,17 @@ static inline void arch_free_tasks(void)
|
|||
static inline int arch_assign_tasks(void)
|
||||
{
|
||||
/* irq low */
|
||||
interrupt_register(PLATFORM_IRQ_TASK_LOW, _irq_task,
|
||||
interrupt_register(PLATFORM_IRQ_TASK_LOW, IRQ_AUTO_UNMASK, _irq_task,
|
||||
task_irq_low_get());
|
||||
interrupt_enable(PLATFORM_IRQ_TASK_LOW);
|
||||
|
||||
/* irq medium */
|
||||
interrupt_register(PLATFORM_IRQ_TASK_MED, _irq_task,
|
||||
interrupt_register(PLATFORM_IRQ_TASK_MED, IRQ_AUTO_UNMASK, _irq_task,
|
||||
task_irq_med_get());
|
||||
interrupt_enable(PLATFORM_IRQ_TASK_MED);
|
||||
|
||||
/* irq high */
|
||||
interrupt_register(PLATFORM_IRQ_TASK_HIGH, _irq_task,
|
||||
interrupt_register(PLATFORM_IRQ_TASK_HIGH, IRQ_AUTO_UNMASK, _irq_task,
|
||||
task_irq_high_get());
|
||||
interrupt_enable(PLATFORM_IRQ_TASK_HIGH);
|
||||
|
||||
|
|
|
@ -307,7 +307,7 @@ static inline void arch_idc_init(void)
|
|||
(*idc)->done_bit_mask = idc_get_done_bit_mask(core);
|
||||
|
||||
/* configure interrupt */
|
||||
interrupt_register(PLATFORM_IDC_INTERRUPT(core),
|
||||
interrupt_register(PLATFORM_IDC_INTERRUPT(core), IRQ_AUTO_UNMASK,
|
||||
idc_irq_handler, *idc);
|
||||
interrupt_enable(PLATFORM_IDC_INTERRUPT(core));
|
||||
|
||||
|
|
|
@ -617,12 +617,14 @@ static int ssp_probe(struct dai *dai)
|
|||
*/
|
||||
if (ssp_irq(dai) >= IRQ_CHT_SSP_OFFSET)
|
||||
interrupt_register(ssp_irq(dai) - IRQ_CHT_SSP_OFFSET,
|
||||
ssp_irq_handler, dai);
|
||||
IRQ_AUTO_UNMASK, ssp_irq_handler, dai);
|
||||
else
|
||||
interrupt_register(ssp_irq(dai), ssp_irq_handler, dai);
|
||||
interrupt_register(ssp_irq(dai), IRQ_AUTO_UNMASK,
|
||||
ssp_irq_handler, dai);
|
||||
#else
|
||||
/* register our IRQ handler */
|
||||
interrupt_register(ssp_irq(dai), ssp_irq_handler, dai);
|
||||
interrupt_register(ssp_irq(dai), IRQ_AUTO_UNMASK, ssp_irq_handler,
|
||||
dai);
|
||||
#endif
|
||||
platform_interrupt_unmask(ssp_irq(dai), 1);
|
||||
interrupt_enable(ssp_irq(dai));
|
||||
|
|
|
@ -1460,7 +1460,8 @@ static int dmic_probe(struct dai *dai)
|
|||
dmic->state = COMP_STATE_READY;
|
||||
|
||||
/* register our IRQ handler */
|
||||
interrupt_register(dmic_irq(dai), dmic_irq_handler, dai);
|
||||
interrupt_register(dmic_irq(dai), IRQ_AUTO_UNMASK, dmic_irq_handler,
|
||||
dai);
|
||||
|
||||
platform_interrupt_unmask(dmic_irq(dai), 1);
|
||||
interrupt_enable(dmic_irq(dai));
|
||||
|
|
|
@ -43,11 +43,8 @@
|
|||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
static inline void irq_lvl2_handler(void *data,
|
||||
int level,
|
||||
uint32_t ilxsd,
|
||||
uint32_t ilxmsd,
|
||||
uint32_t ilxmcd)
|
||||
static inline void irq_lvl2_handler(void *data, int level, uint32_t ilxsd,
|
||||
uint32_t ilxmsd, uint32_t ilxmcd)
|
||||
{
|
||||
struct irq_desc *parent = (struct irq_desc *)data;
|
||||
struct irq_desc *child = NULL;
|
||||
|
@ -75,7 +72,7 @@ static inline void irq_lvl2_handler(void *data,
|
|||
|
||||
if (child && child->handler) {
|
||||
child->handler(child->handler_arg);
|
||||
unmask = 1;
|
||||
unmask = child->unmask;
|
||||
} else {
|
||||
/* nobody cared ? */
|
||||
trace_irq_error("nbc");
|
||||
|
|
|
@ -881,7 +881,8 @@ static int ssp_probe(struct dai *dai)
|
|||
ssp->state[DAI_DIR_CAPTURE] = COMP_STATE_READY;
|
||||
|
||||
/* register our IRQ handler */
|
||||
interrupt_register(ssp_irq(dai), ssp_irq_handler, dai);
|
||||
interrupt_register(ssp_irq(dai), IRQ_AUTO_UNMASK, ssp_irq_handler,
|
||||
dai);
|
||||
platform_interrupt_unmask(ssp_irq(dai), 1);
|
||||
interrupt_enable(ssp_irq(dai));
|
||||
|
||||
|
|
|
@ -118,7 +118,7 @@ void platform_dai_wallclock(struct comp_dev *dai, uint64_t *wallclock)
|
|||
static int platform_timer_register(struct timer *timer,
|
||||
void (*handler)(void *arg), void *arg)
|
||||
{
|
||||
return interrupt_register(timer->irq, handler, arg);
|
||||
return interrupt_register(timer->irq, IRQ_AUTO_UNMASK, handler, arg);
|
||||
}
|
||||
|
||||
int timer_register(struct timer *timer, void(*handler)(void *arg), void *arg)
|
||||
|
|
|
@ -1139,7 +1139,8 @@ static inline void dw_dma_interrupt_register(struct dma *dma, int channel)
|
|||
uint32_t irq = dma_irq(dma, cpu_get_id()) +
|
||||
(channel << SOF_IRQ_BIT_SHIFT);
|
||||
|
||||
interrupt_register(irq, dw_dma_irq_handler, &p->chan[channel].id);
|
||||
interrupt_register(irq, IRQ_AUTO_UNMASK, dw_dma_irq_handler,
|
||||
&p->chan[channel].id);
|
||||
interrupt_enable(irq);
|
||||
}
|
||||
|
||||
|
@ -1307,7 +1308,7 @@ static inline void dw_dma_interrupt_register(struct dma *dma, int channel)
|
|||
{
|
||||
uint32_t irq = dma_irq(dma, cpu_get_id());
|
||||
|
||||
interrupt_register(irq, dw_dma_irq_handler, dma);
|
||||
interrupt_register(irq, IRQ_AUTO_UNMASK, dw_dma_irq_handler, dma);
|
||||
interrupt_enable(irq);
|
||||
}
|
||||
|
||||
|
|
|
@ -510,7 +510,8 @@ static int ssp_probe(struct dai *dai)
|
|||
|
||||
|
||||
/* register our IRQ handler */
|
||||
interrupt_register(ssp_irq(dai), ssp_irq_handler, dai);
|
||||
interrupt_register(ssp_irq(dai), IRQ_AUTO_UNMASK, ssp_irq_handler,
|
||||
dai);
|
||||
|
||||
platform_interrupt_unmask(ssp_irq(dai), 1);
|
||||
interrupt_enable(ssp_irq(dai));
|
||||
|
|
|
@ -43,6 +43,9 @@
|
|||
#define trace_irq(__e) trace_event(TRACE_CLASS_IRQ, __e)
|
||||
#define trace_irq_error(__e) trace_error(TRACE_CLASS_IRQ, __e)
|
||||
|
||||
#define IRQ_MANUAL_UNMASK 0
|
||||
#define IRQ_AUTO_UNMASK 1
|
||||
|
||||
struct irq_desc {
|
||||
/* irq must be first for constructor */
|
||||
int irq; /* logical IRQ number */
|
||||
|
@ -51,6 +54,9 @@ struct irq_desc {
|
|||
void (*handler)(void *arg);
|
||||
void *handler_arg;
|
||||
|
||||
/* whether irq should be automatically unmasked */
|
||||
int unmask;
|
||||
|
||||
/* to identify interrupt with the same IRQ */
|
||||
int id;
|
||||
spinlock_t lock;
|
||||
|
@ -63,8 +69,8 @@ struct irq_desc {
|
|||
struct list_item child[PLATFORM_IRQ_CHILDREN];
|
||||
};
|
||||
|
||||
int interrupt_register(uint32_t irq,
|
||||
void(*handler)(void *arg), void *arg);
|
||||
int interrupt_register(uint32_t irq, int unmask, void(*handler)(void *arg),
|
||||
void *arg);
|
||||
void interrupt_unregister(uint32_t irq);
|
||||
uint32_t interrupt_enable(uint32_t irq);
|
||||
uint32_t interrupt_disable(uint32_t irq);
|
||||
|
|
|
@ -215,7 +215,8 @@ int platform_ipc_init(struct ipc *ipc)
|
|||
iipc->pm_prepare_D3 = 0;
|
||||
|
||||
/* configure interrupt */
|
||||
interrupt_register(PLATFORM_IPC_INTERRUPT, irq_handler, NULL);
|
||||
interrupt_register(PLATFORM_IPC_INTERRUPT, IRQ_AUTO_UNMASK,
|
||||
irq_handler, NULL);
|
||||
interrupt_enable(PLATFORM_IPC_INTERRUPT);
|
||||
|
||||
/* enable IPC interrupts from host */
|
||||
|
|
|
@ -237,7 +237,8 @@ int platform_ipc_init(struct ipc *ipc)
|
|||
iipc->pm_prepare_D3 = 0;
|
||||
|
||||
/* configure interrupt */
|
||||
interrupt_register(PLATFORM_IPC_INTERRUPT, irq_handler, NULL);
|
||||
interrupt_register(PLATFORM_IPC_INTERRUPT, IRQ_AUTO_UNMASK,
|
||||
irq_handler, NULL);
|
||||
interrupt_enable(PLATFORM_IPC_INTERRUPT);
|
||||
|
||||
/* Unmask Busy and Done interrupts */
|
||||
|
|
|
@ -216,7 +216,8 @@ int platform_ipc_init(struct ipc *ipc)
|
|||
iipc->pm_prepare_D3 = 0;
|
||||
|
||||
/* configure interrupt */
|
||||
interrupt_register(PLATFORM_IPC_INTERRUPT, irq_handler, NULL);
|
||||
interrupt_register(PLATFORM_IPC_INTERRUPT, IRQ_AUTO_UNMASK,
|
||||
irq_handler, NULL);
|
||||
interrupt_enable(PLATFORM_IPC_INTERRUPT);
|
||||
|
||||
/* enable IPC interrupts from host */
|
||||
|
|
|
@ -232,7 +232,8 @@ int platform_ipc_init(struct ipc *ipc)
|
|||
iipc->pm_prepare_D3 = 0;
|
||||
|
||||
/* configure interrupt */
|
||||
interrupt_register(PLATFORM_IPC_INTERRUPT, irq_handler, NULL);
|
||||
interrupt_register(PLATFORM_IPC_INTERRUPT, IRQ_AUTO_UNMASK,
|
||||
irq_handler, NULL);
|
||||
interrupt_enable(PLATFORM_IPC_INTERRUPT);
|
||||
|
||||
/* Unmask Busy and Done interrupts */
|
||||
|
|
|
@ -173,7 +173,8 @@ int platform_ipc_pmc_init(void)
|
|||
sizeof(struct intel_ipc_pmc_data));
|
||||
|
||||
/* configure interrupt */
|
||||
interrupt_register(IRQ_NUM_EXT_PMC, irq_handler, NULL);
|
||||
interrupt_register(IRQ_NUM_EXT_PMC, IRQ_AUTO_UNMASK, irq_handler,
|
||||
NULL);
|
||||
interrupt_enable(IRQ_NUM_EXT_PMC);
|
||||
|
||||
/* Unmask Busy and Done interrupts */
|
||||
|
|
|
@ -38,13 +38,13 @@
|
|||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
static int irq_register_child(struct irq_desc *parent, int irq,
|
||||
static int irq_register_child(struct irq_desc *parent, int irq, int unmask,
|
||||
void (*handler)(void *arg), void *arg);
|
||||
static void irq_unregister_child(struct irq_desc *parent, int irq);
|
||||
static uint32_t irq_enable_child(struct irq_desc *parent, int irq);
|
||||
static uint32_t irq_disable_child(struct irq_desc *parent, int irq);
|
||||
|
||||
static int irq_register_child(struct irq_desc *parent, int irq,
|
||||
static int irq_register_child(struct irq_desc *parent, int irq, int unmask,
|
||||
void (*handler)(void *arg), void *arg)
|
||||
{
|
||||
int ret = 0;
|
||||
|
@ -67,6 +67,7 @@ static int irq_register_child(struct irq_desc *parent, int irq,
|
|||
child->handler = handler;
|
||||
child->handler_arg = arg;
|
||||
child->id = SOF_IRQ_ID(irq);
|
||||
child->unmask = unmask;
|
||||
|
||||
list_item_append(&child->irq_list, &parent->child[SOF_IRQ_BIT(irq)]);
|
||||
|
||||
|
@ -171,8 +172,8 @@ static uint32_t irq_disable_child(struct irq_desc *parent, int irq)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int interrupt_register(uint32_t irq,
|
||||
void (*handler)(void *arg), void *arg)
|
||||
int interrupt_register(uint32_t irq, int unmask, void (*handler)(void *arg),
|
||||
void *arg)
|
||||
{
|
||||
struct irq_desc *parent;
|
||||
|
||||
|
@ -181,7 +182,7 @@ int interrupt_register(uint32_t irq,
|
|||
if (parent == NULL)
|
||||
return arch_interrupt_register(irq, handler, arg);
|
||||
else
|
||||
return irq_register_child(parent, irq, handler, arg);
|
||||
return irq_register_child(parent, irq, unmask, handler, arg);
|
||||
}
|
||||
|
||||
void interrupt_unregister(uint32_t irq)
|
||||
|
|
|
@ -409,7 +409,8 @@ int scheduler_init(struct sof *sof)
|
|||
work_init(&((*sch)->work), sch_work, *sch, WORK_ASYNC);
|
||||
|
||||
/* configure scheduler interrupt */
|
||||
interrupt_register(PLATFORM_SCHEDULE_IRQ, scheduler_run, NULL);
|
||||
interrupt_register(PLATFORM_SCHEDULE_IRQ, IRQ_AUTO_UNMASK,
|
||||
scheduler_run, NULL);
|
||||
interrupt_enable(PLATFORM_SCHEDULE_IRQ);
|
||||
|
||||
/* allocate arch tasks */
|
||||
|
|
Loading…
Reference in New Issue