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:
Tomasz Lauda 2018-09-20 17:00:35 +02:00
parent f9a491f405
commit ffa13fcc4d
17 changed files with 48 additions and 32 deletions

View File

@ -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);

View File

@ -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));

View File

@ -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));

View File

@ -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));

View File

@ -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");

View File

@ -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));

View File

@ -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)

View File

@ -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);
}

View File

@ -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));

View File

@ -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);

View File

@ -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 */

View File

@ -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 */

View File

@ -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 */

View File

@ -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 */

View File

@ -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 */

View File

@ -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)

View File

@ -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 */