diff --git a/src/arch/xtensa/drivers/idc.c b/src/arch/xtensa/drivers/idc.c index 6f5d9d7d0949..d9029ccac8e9 100644 --- a/src/arch/xtensa/drivers/idc.c +++ b/src/arch/xtensa/drivers/idc.c @@ -50,9 +50,11 @@ static struct idc **idc_get(void) */ void idc_enable_interrupts(int target_core, int source_core) { + struct idc *idc = *idc_get(); + idc_write(IPC_IDCCTL, target_core, IPC_IDCCTL_IDCTBIE(source_core)); - platform_interrupt_unmask(PLATFORM_IDC_INTERRUPT(target_core), 0); + interrupt_unmask(idc->irq, target_core); } /** @@ -347,11 +349,15 @@ int arch_idc_init(void) SOF_TASK_PRI_IDC, idc_do_cmd, *idc, core, 0); /* configure interrupt */ - ret = interrupt_register(PLATFORM_IDC_INTERRUPT(core), IRQ_AUTO_UNMASK, - idc_irq_handler, *idc); + (*idc)->irq = interrupt_get_irq(PLATFORM_IDC_INTERRUPT, + PLATFORM_IDC_INTERRUPT_NAME); + if ((*idc)->irq < 0) + return (*idc)->irq; + ret = interrupt_register((*idc)->irq, IRQ_AUTO_UNMASK, idc_irq_handler, + *idc); if (ret < 0) return ret; - interrupt_enable(PLATFORM_IDC_INTERRUPT(core)); + interrupt_enable((*idc)->irq, *idc); /* enable BUSY and DONE (only for master core) interrupts */ idc_write(IPC_IDCCTL, core, @@ -373,8 +379,8 @@ void idc_free(void) trace_idc("idc_free()"); /* disable and unregister interrupt */ - interrupt_disable(PLATFORM_IDC_INTERRUPT(core)); - interrupt_unregister(PLATFORM_IDC_INTERRUPT(core)); + interrupt_disable(idc->irq, idc); + interrupt_unregister(idc->irq, idc); /* clear BUSY bits */ for (i = 0; i < PLATFORM_CORE_COUNT; i++) { diff --git a/src/arch/xtensa/include/arch/drivers/interrupt.h b/src/arch/xtensa/include/arch/drivers/interrupt.h index 9a8240ce30b5..21d950dbcde6 100644 --- a/src/arch/xtensa/include/arch/drivers/interrupt.h +++ b/src/arch/xtensa/include/arch/drivers/interrupt.h @@ -10,16 +10,19 @@ #ifndef __ARCH_DRIVERS_INTERRUPT_H__ #define __ARCH_DRIVERS_INTERRUPT_H__ -#include #include #include #include #include +extern char irq_name_level2[]; +extern char irq_name_level3[]; +extern char irq_name_level4[]; +extern char irq_name_level5[]; + static inline int arch_interrupt_register(int irq, void (*handler)(void *arg), void *arg) { - irq = SOF_IRQ_NUMBER(irq); xthal_set_intclear(0x1 << irq); _xtos_set_interrupt_handler_arg(irq, handler, arg); return 0; @@ -27,7 +30,6 @@ static inline int arch_interrupt_register(int irq, static inline void arch_interrupt_unregister(int irq) { - irq = SOF_IRQ_NUMBER(irq); _xtos_set_interrupt_handler_arg(irq, NULL, NULL); } @@ -53,13 +55,11 @@ static inline uint32_t arch_interrupt_get_level(void) static inline void arch_interrupt_set(int irq) { - irq = SOF_IRQ_NUMBER(irq); xthal_set_intset(0x1 << irq); } static inline void arch_interrupt_clear(int irq) { - irq = SOF_IRQ_NUMBER(irq); xthal_set_intclear(0x1 << irq); } diff --git a/src/arch/xtensa/include/arch/drivers/timer.h b/src/arch/xtensa/include/arch/drivers/timer.h index 51199121d043..daa9275a6de3 100644 --- a/src/arch/xtensa/include/arch/drivers/timer.h +++ b/src/arch/xtensa/include/arch/drivers/timer.h @@ -13,10 +13,18 @@ #include #include +struct timer_irq { + int logical_irq; + void *irq_arg; +}; + struct timer { uint32_t id; - uint32_t irq; + int irq; + const char *irq_name; + unsigned int core; void *timer_data; /* used by core */ + struct timer_irq *tirq; /* dynamic non-cacheable IRQ data */ uint32_t hitime; /* high end of 64bit timer */ uint32_t hitimeout; uint32_t lowtimeout; diff --git a/src/arch/xtensa/include/arch/schedule/task.h b/src/arch/xtensa/include/arch/schedule/task.h index 36cdf32cfd19..9c4e5c26aff6 100644 --- a/src/arch/xtensa/include/arch/schedule/task.h +++ b/src/arch/xtensa/include/arch/schedule/task.h @@ -18,13 +18,12 @@ #include #include -#include /** \brief IRQ task data. */ struct irq_task { spinlock_t lock; /**< lock */ struct list_item list; /**< list of tasks */ - uint32_t irq; /**< IRQ level */ + int irq; /**< IRQ level */ }; struct task; @@ -63,11 +62,6 @@ int arch_allocate_tasks(void); */ void arch_free_tasks(void); -/** - * \brief Assigns IRQ tasks to interrupts. - */ -int arch_assign_tasks(void); - #endif /* __ARCH_SCHEDULE_TASK_H__ */ #else diff --git a/src/arch/xtensa/init.c b/src/arch/xtensa/init.c index cdee7b10b289..6f962f1bf4e0 100644 --- a/src/arch/xtensa/init.c +++ b/src/arch/xtensa/init.c @@ -87,7 +87,6 @@ int arch_init(struct sof *sof) { initialize_pointers_per_core(); register_exceptions(); - arch_assign_tasks(); return 0; } diff --git a/src/arch/xtensa/schedule/task.c b/src/arch/xtensa/schedule/task.c index e99a59793c74..3176cc1b667e 100644 --- a/src/arch/xtensa/schedule/task.c +++ b/src/arch/xtensa/schedule/task.c @@ -48,29 +48,32 @@ struct irq_task **task_irq_high_get(void) return &ctx->irq_high_task; } -/** - * \brief Retrieves task IRQ level. - * \param[in,out] task Task data. - * \return IRQ level. - */ -static uint32_t task_get_irq(struct task *task) +static struct irq_task *task_get_irq_task(struct task *task) { - uint32_t irq; - switch (task->priority) { +#ifdef CONFIG_TASK_HAVE_PRIORITY_MEDIUM case SOF_TASK_PRI_MED + 1 ... SOF_TASK_PRI_LOW: - irq = PLATFORM_IRQ_TASK_LOW; - break; + return *task_irq_low_get(); case SOF_TASK_PRI_HIGH ... SOF_TASK_PRI_MED - 1: - irq = PLATFORM_IRQ_TASK_HIGH; - break; + return *task_irq_high_get(); case SOF_TASK_PRI_MED: + return *task_irq_med_get(); +#elif CONFIG_TASK_HAVE_PRIORITY_LOW + case SOF_TASK_PRI_MED ... SOF_TASK_PRI_LOW: + return *task_irq_low_get(); + case SOF_TASK_PRI_HIGH ... SOF_TASK_PRI_MED - 1: + return *task_irq_high_get(); +#else + case SOF_TASK_PRI_HIGH ... SOF_TASK_PRI_LOW: + return *task_irq_high_get(); +#endif default: - irq = PLATFORM_IRQ_TASK_MED; - break; + trace_error(TRACE_CLASS_IRQ, + "task_get_irq_task() error: task priority %d", + task->priority); } - return irq; + return NULL; } /** @@ -79,39 +82,12 @@ static uint32_t task_get_irq(struct task *task) */ static int task_set_data(struct task *task) { - struct list_item *dst = NULL; - struct irq_task *irq_task; - uint32_t flags; + struct irq_task *irq_task = task_get_irq_task(task); + struct list_item *dst; + unsigned long flags; - switch (task->priority) { -#if CONFIG_TASK_HAVE_PRIORITY_MEDIUM - case SOF_TASK_PRI_MED + 1 ... SOF_TASK_PRI_LOW: - irq_task = *task_irq_low_get(); - break; - case SOF_TASK_PRI_HIGH ... SOF_TASK_PRI_MED - 1: - irq_task = *task_irq_high_get(); - break; - case SOF_TASK_PRI_MED: - irq_task = *task_irq_med_get(); - break; -#elif CONFIG_TASK_HAVE_PRIORITY_LOW - case SOF_TASK_PRI_MED ... SOF_TASK_PRI_LOW: - irq_task = *task_irq_low_get(); - break; - case SOF_TASK_PRI_HIGH ... SOF_TASK_PRI_MED - 1: - irq_task = *task_irq_high_get(); - break; -#else - case SOF_TASK_PRI_HIGH ... SOF_TASK_PRI_LOW: - irq_task = *task_irq_high_get(); - break; -#endif - default: - trace_error(TRACE_CLASS_IRQ, - "task_set_data() error: task priority %d", - task->priority); + if (!irq_task) return -EINVAL; - } dst = &irq_task->list; spin_lock_irq(&irq_task->lock, flags); @@ -165,22 +141,26 @@ static void _irq_task(void *arg) int arch_run_task(struct task *task) { - uint32_t irq; + struct irq_task *irq_task = task_get_irq_task(task); int ret; + if (!irq_task) + return -EINVAL; + ret = task_set_data(task); if (ret < 0) return ret; - irq = task_get_irq(task); - interrupt_set(irq); + interrupt_set(irq_task->irq); return 0; } int arch_allocate_tasks(void) { + int ret; + #if CONFIG_TASK_HAVE_PRIORITY_LOW /* irq low */ struct irq_task **low = task_irq_low_get(); @@ -188,7 +168,15 @@ int arch_allocate_tasks(void) list_init(&((*low)->list)); spinlock_init(&((*low)->lock)); - (*low)->irq = PLATFORM_IRQ_TASK_LOW; + (*low)->irq = interrupt_get_irq(PLATFORM_IRQ_TASK_LOW, + PLATFORM_IRQ_TASK_LOW_NAME); + if ((*low)->irq < 0) + return (*low)->irq; + + ret = interrupt_register((*low)->irq, IRQ_AUTO_UNMASK, _irq_task, low); + if (ret < 0) + return ret; + interrupt_enable((*low)->irq, low); #endif #if CONFIG_TASK_HAVE_PRIORITY_MEDIUM @@ -198,7 +186,15 @@ int arch_allocate_tasks(void) list_init(&((*med)->list)); spinlock_init(&((*med)->lock)); - (*med)->irq = PLATFORM_IRQ_TASK_MED; + (*med)->irq = interrupt_get_irq(PLATFORM_IRQ_TASK_MED, + PLATFORM_IRQ_TASK_MED_NAME); + if ((*med)->irq < 0) + return (*med)->irq; + + ret = interrupt_register((*med)->irq, IRQ_AUTO_UNMASK, _irq_task, med); + if (ret < 0) + return ret; + interrupt_enable((*med)->irq, med); #endif /* irq high */ @@ -207,7 +203,16 @@ int arch_allocate_tasks(void) list_init(&((*high)->list)); spinlock_init(&((*high)->lock)); - (*high)->irq = PLATFORM_IRQ_TASK_HIGH; + (*high)->irq = interrupt_get_irq(PLATFORM_IRQ_TASK_HIGH, + PLATFORM_IRQ_TASK_HIGH_NAME); + if ((*high)->irq < 0) + return (*high)->irq; + + ret = interrupt_register((*high)->irq, IRQ_AUTO_UNMASK, _irq_task, + high); + if (ret < 0) + return ret; + interrupt_enable((*high)->irq, high); return 0; } @@ -222,8 +227,8 @@ void arch_free_tasks(void) struct irq_task **low = task_irq_low_get(); spin_lock_irq(&(*low)->lock, flags); - interrupt_disable(PLATFORM_IRQ_TASK_LOW); - interrupt_unregister(PLATFORM_IRQ_TASK_LOW); + interrupt_disable((*low)->irq, low); + interrupt_unregister((*low)->irq, low); list_item_del(&(*low)->list); spin_unlock_irq(&(*low)->lock, flags); #endif @@ -233,8 +238,8 @@ void arch_free_tasks(void) struct irq_task **med = task_irq_med_get(); spin_lock_irq(&(*med)->lock, flags); - interrupt_disable(PLATFORM_IRQ_TASK_MED); - interrupt_unregister(PLATFORM_IRQ_TASK_MED); + interrupt_disable((*med)->irq, med); + interrupt_unregister((*med)->irq, med); list_item_del(&(*med)->list); spin_unlock_irq(&(*med)->lock, flags); #endif @@ -243,32 +248,8 @@ void arch_free_tasks(void) struct irq_task **high = task_irq_high_get(); spin_lock_irq(&(*high)->lock, flags); - interrupt_disable(PLATFORM_IRQ_TASK_HIGH); - interrupt_unregister(PLATFORM_IRQ_TASK_HIGH); + interrupt_disable((*high)->irq, high); + interrupt_unregister((*high)->irq, high); list_item_del(&(*high)->list); spin_unlock_irq(&(*high)->lock, flags); } - -int arch_assign_tasks(void) -{ -#if CONFIG_TASK_HAVE_PRIORITY_LOW - /* irq low */ - interrupt_register(PLATFORM_IRQ_TASK_LOW, IRQ_AUTO_UNMASK, _irq_task, - task_irq_low_get()); - interrupt_enable(PLATFORM_IRQ_TASK_LOW); -#endif - -#if CONFIG_TASK_HAVE_PRIORITY_MEDIUM - /* irq medium */ - interrupt_register(PLATFORM_IRQ_TASK_MED, IRQ_AUTO_UNMASK, _irq_task, - task_irq_med_get()); - interrupt_enable(PLATFORM_IRQ_TASK_MED); -#endif - - /* irq high */ - interrupt_register(PLATFORM_IRQ_TASK_HIGH, IRQ_AUTO_UNMASK, _irq_task, - task_irq_high_get()); - interrupt_enable(PLATFORM_IRQ_TASK_HIGH); - - return 0; -} diff --git a/src/drivers/dw/dma.c b/src/drivers/dw/dma.c index 76dc4eeabd26..f9f0aeefc220 100644 --- a/src/drivers/dw/dma.c +++ b/src/drivers/dw/dma.c @@ -61,6 +61,9 @@ struct dw_dma_chan_data { uint32_t cfg_lo; uint32_t cfg_hi; bool irq_disabled; +#if !CONFIG_DMA_AGGREGATED_IRQ + int irq; +#endif /* pointer data */ struct dw_dma_ptr_data ptr_data; @@ -71,14 +74,15 @@ struct dw_dma_chan_data { void *cb_data; /* callback type */ int cb_type; + + struct dma *dma; }; /* private data for DW DMA engine */ struct dma_pdata { struct dw_dma_chan_data chan[DW_MAX_CHAN]; #if CONFIG_DMA_AGGREGATED_IRQ - /**< bitmask of channels with registered IRQs per core */ - uint32_t mask_irq_channels[PLATFORM_CORE_COUNT]; + int irq; #endif }; @@ -153,8 +157,9 @@ static void dw_dma_interrupt_unmask(struct dma *dma, unsigned int channel) static void dw_dma_interrupt_clear(struct dma *dma, unsigned int channel) { const struct dma_pdata *p = dma_get_drvdata(dma); + const struct dw_dma_chan_data *chan = p->chan + channel; - if (p->chan[channel].irq_disabled) { + if (chan->irq_disabled) { tracev_dwdma("dw_dma_interrupt_mask(): dma %d channel %d " "not working in irq mode", dma->plat_data.id, channel); @@ -169,8 +174,11 @@ static void dw_dma_interrupt_clear(struct dma *dma, unsigned int channel) dw_write(dma, DW_CLEAR_ERR, DW_CHAN(channel)); /* clear platform interrupt */ - platform_interrupt_clear(dma_irq(dma, cpu_get_id()), - DW_CHAN(channel)); +#if CONFIG_DMA_AGGREGATED_IRQ + interrupt_clear_mask(p->irq, DW_CHAN(channel)); +#else + interrupt_clear_mask(chan->irq, DW_CHAN(channel)); +#endif } /* allocate next free DMA channel */ @@ -1050,7 +1058,8 @@ static int dw_dma_copy(struct dma *dma, unsigned int channel, int bytes, /* interrupt handler for DMA */ static void dw_dma_irq_handler(void *data) { - struct dma *dma = data; + struct dw_dma_chan_data *chan = data; + struct dma *dma = chan->dma; struct dma_pdata *p = dma_get_drvdata(dma); uint32_t status_intr; uint32_t status_err; @@ -1070,7 +1079,7 @@ static void dw_dma_irq_handler(void *data) #if CONFIG_HW_LLI #if CONFIG_DMA_AGGREGATED_IRQ /* skip if channel is not registered on this core */ - mask = p->mask_irq_channels[cpu_get_id()]; + mask = BIT(chan - p->chan); #else mask = ~0; #endif @@ -1090,9 +1099,10 @@ static void dw_dma_irq_handler(void *data) dw_write(dma, DW_CLEAR_ERR, status_err); } +#if CONFIG_DMA_AGGREGATED_IRQ /* clear platform and DSP interrupt */ - platform_interrupt_clear(dma_irq(dma, cpu_get_id()), - status_src | status_err); + interrupt_clear_mask(p->irq, status_src | status_err); +#endif for (i = 0; i < dma->plat_data.channels; i++) { /* skip if channel is not running */ @@ -1110,38 +1120,37 @@ static inline int dw_dma_interrupt_register(struct dma *dma, unsigned int channel) { struct dma_pdata *p = dma_get_drvdata(dma); - uint32_t irq = dma_chan_irq(dma, cpu_get_id(), channel); -#if CONFIG_DMA_AGGREGATED_IRQ - int cpu = cpu_get_id(); -#endif + struct dw_dma_chan_data *chan = p->chan + channel; + uint32_t irq = dma_chan_irq(dma, channel); + int logical_irq = interrupt_get_irq(irq, dma_irq_name(dma)); int ret; - if (p->chan[channel].irq_disabled) { + if (chan->irq_disabled) { tracev_dwdma("dw_dma_interrupt_register(): dma %d channel %d " "not working in irq mode", dma->plat_data.id, channel); return 0; } -#if CONFIG_DMA_AGGREGATED_IRQ - if (!p->mask_irq_channels[cpu]) { -#endif - ret = interrupt_register(irq, IRQ_AUTO_UNMASK, - dw_dma_irq_handler, dma); - if (ret < 0) { - trace_dwdma_error("dw_dma_interrupt_register() error: " - "dma %d channel %d failed to " - "allocate IRQ", dma->plat_data.id, - channel); - return ret; - } + if (logical_irq < 0) + return logical_irq; - interrupt_enable(irq); #if CONFIG_DMA_AGGREGATED_IRQ + p->irq = logical_irq; +#else + chan->irq = logical_irq; +#endif + ret = interrupt_register(logical_irq, IRQ_AUTO_UNMASK, + dw_dma_irq_handler, chan); + if (ret < 0) { + trace_dwdma_error("dw_dma_interrupt_register() error: " + "dma %d channel %d failed to " + "allocate IRQ", dma->plat_data.id, + channel); + return ret; } - p->mask_irq_channels[cpu] |= BIT(channel); -#endif + interrupt_enable(logical_irq, chan); return 0; } @@ -1150,12 +1159,10 @@ static inline void dw_dma_interrupt_unregister(struct dma *dma, unsigned int channel) { struct dma_pdata *p = dma_get_drvdata(dma); - uint32_t irq = dma_chan_irq(dma, cpu_get_id(), channel); -#if CONFIG_DMA_AGGREGATED_IRQ - int cpu = cpu_get_id(); -#endif + struct dw_dma_chan_data *chan = p->chan + channel; + int logical_irq; - if (p->chan[channel].irq_disabled) { + if (chan->irq_disabled) { tracev_dwdma("dw_dma_interrupt_unregister(): dma %d channel %d" " not working in irq mode", dma->plat_data.id, channel); @@ -1163,15 +1170,12 @@ static inline void dw_dma_interrupt_unregister(struct dma *dma, } #if CONFIG_DMA_AGGREGATED_IRQ - p->mask_irq_channels[cpu] &= ~BIT(channel); - - if (!p->mask_irq_channels[cpu]) { -#endif - interrupt_disable(irq); - interrupt_unregister(irq); -#if CONFIG_DMA_AGGREGATED_IRQ - } + logical_irq = p->irq; +#else + logical_irq = chan->irq; #endif + interrupt_disable(logical_irq, chan); + interrupt_unregister(logical_irq, chan); } static int dw_dma_setup(struct dma *dma) @@ -1224,6 +1228,7 @@ static int dw_dma_setup(struct dma *dma) static int dw_dma_probe(struct dma *dma) { + struct dw_dma_chan_data *chan; struct dma_pdata *dw_pdata; int ret; int i; @@ -1251,8 +1256,11 @@ static int dw_dma_probe(struct dma *dma) return ret; /* init work */ - for (i = 0; i < dma->plat_data.channels; i++) - dw_pdata->chan[i].status = COMP_STATE_INIT; + for (i = 0, chan = dw_pdata->chan; i < dma->plat_data.channels; + i++, chan++) { + chan->status = COMP_STATE_INIT; + chan->dma = dma; + } /* init number of channels draining */ atomic_init(&dma->num_channels_busy, 0); diff --git a/src/drivers/imx/interrupt.c b/src/drivers/imx/interrupt.c index 8dbcf2eb4c59..023c22e53619 100644 --- a/src/drivers/imx/interrupt.c +++ b/src/drivers/imx/interrupt.c @@ -5,17 +5,11 @@ // Author: Daniel Baluta #include -#include #include void platform_interrupt_init(void) {} -struct irq_desc *platform_irq_get_parent(uint32_t irq) -{ - return NULL; -} - -void platform_interrupt_set(int irq) +void platform_interrupt_set(uint32_t irq) { arch_interrupt_set(irq); } @@ -30,5 +24,5 @@ uint32_t platform_interrupt_get_enabled(void) return 0; } -void platform_interrupt_mask(uint32_t irq, uint32_t mask) {} -void platform_interrupt_unmask(uint32_t irq, uint32_t mask) {} +void interrupt_mask(uint32_t irq, unsigned int cpu) {} +void interrupt_unmask(uint32_t irq, unsigned int cpu) {} diff --git a/src/drivers/imx/ipc.c b/src/drivers/imx/ipc.c index 69efe7e615fd..73e03deb0776 100644 --- a/src/drivers/imx/ipc.c +++ b/src/drivers/imx/ipc.c @@ -193,8 +193,8 @@ int platform_ipc_init(struct ipc *ipc) /* configure interrupt */ interrupt_register(PLATFORM_IPC_INTERRUPT, IRQ_AUTO_UNMASK, - irq_handler, NULL); - interrupt_enable(PLATFORM_IPC_INTERRUPT); + irq_handler, _ipc); + interrupt_enable(PLATFORM_IPC_INTERRUPT, _ipc); /* enable GP #0 for Host -> DSP message notification * enable GP #1 for DSP -> Host message notification diff --git a/src/drivers/imx/timer.c b/src/drivers/imx/timer.c index 48edf1930a05..d9d2cc5a48cb 100644 --- a/src/drivers/imx/timer.c +++ b/src/drivers/imx/timer.c @@ -74,9 +74,12 @@ void platform_dai_wallclock(struct comp_dev *dai, uint64_t *wallclock) int timer_register(struct timer *timer, void(*handler)(void *arg), void *arg) { + struct timer_irq *tirq = timer->tirq; + switch (timer->id) { case TIMER0: case TIMER1: + tirq->irq_arg = arg; return arch_timer_register(timer, handler, arg); default: return -EINVAL; @@ -85,15 +88,21 @@ int timer_register(struct timer *timer, void(*handler)(void *arg), void *arg) void timer_unregister(struct timer *timer) { - interrupt_unregister(timer->irq); + struct timer_irq *tirq = timer->tirq; + + interrupt_unregister(timer->irq, tirq->irq_arg); } void timer_enable(struct timer *timer) { - interrupt_enable(timer->irq); + struct timer_irq *tirq = timer->tirq; + + interrupt_enable(timer->irq, tirq->irq_arg); } void timer_disable(struct timer *timer) { - interrupt_disable(timer->irq); + struct timer_irq *tirq = timer->tirq; + + interrupt_disable(timer->irq, tirq->irq_arg); } diff --git a/src/drivers/intel/baytrail/interrupt.c b/src/drivers/intel/baytrail/interrupt.c index 304e5a1c66f3..35b433cbdefe 100644 --- a/src/drivers/intel/baytrail/interrupt.c +++ b/src/drivers/intel/baytrail/interrupt.c @@ -8,17 +8,11 @@ #include #include -#include #include void platform_interrupt_init(void) {} -struct irq_desc *platform_irq_get_parent(uint32_t irq) -{ - return NULL; -} - -void platform_interrupt_set(int irq) +void platform_interrupt_set(uint32_t irq) { arch_interrupt_set(irq); } @@ -27,42 +21,50 @@ void platform_interrupt_set(int irq) void platform_interrupt_clear(uint32_t irq, uint32_t mask) { switch (irq) { + case IRQ_NUM_EXT_PMC: + case IRQ_NUM_EXT_IA: + case IRQ_NUM_SOFTWARE2: + case IRQ_NUM_SOFTWARE3: + case IRQ_NUM_SOFTWARE4: + case IRQ_NUM_SOFTWARE5: + arch_interrupt_clear(irq); + break; case IRQ_NUM_EXT_SSP0: shim_write(SHIM_PISR, mask << 3); - interrupt_clear(irq); + arch_interrupt_clear(irq); break; case IRQ_NUM_EXT_SSP1: shim_write(SHIM_PISR, mask << 4); - interrupt_clear(irq); + arch_interrupt_clear(irq); break; case IRQ_NUM_EXT_SSP2: shim_write(SHIM_PISR, mask << 5); - interrupt_clear(irq); + arch_interrupt_clear(irq); break; case IRQ_NUM_EXT_DMAC0: shim_write(SHIM_PISR, mask << 16); - interrupt_clear(irq); + arch_interrupt_clear(irq); break; case IRQ_NUM_EXT_DMAC1: shim_write(SHIM_PISR, mask << 24); - interrupt_clear(irq); + arch_interrupt_clear(irq); break; #if defined CONFIG_CHERRYTRAIL case IRQ_NUM_EXT_DMAC2: shim_write(SHIM_PISRH, mask << 0); - interrupt_clear(irq); + arch_interrupt_clear(irq); break; case IRQ_NUM_EXT_SSP3: shim_write(SHIM_PISRH, mask << 8); - interrupt_clear(irq); + arch_interrupt_clear(irq); break; case IRQ_NUM_EXT_SSP4: shim_write(SHIM_PISRH, mask << 9); - interrupt_clear(irq); + arch_interrupt_clear(irq); break; case IRQ_NUM_EXT_SSP5: shim_write(SHIM_PISRH, mask << 10); - interrupt_clear(irq); + arch_interrupt_clear(irq); break; #endif default: @@ -76,36 +78,36 @@ uint32_t platform_interrupt_get_enabled(void) return shim_read(SHIM_PIMR); } -void platform_interrupt_mask(uint32_t irq, uint32_t mask) +void interrupt_mask(uint32_t irq, unsigned int cpu) { switch (irq) { case IRQ_NUM_EXT_SSP0: - shim_write(SHIM_PIMR, mask << 3); + shim_write(SHIM_PIMR, 1 << 3); break; case IRQ_NUM_EXT_SSP1: - shim_write(SHIM_PIMR, mask << 4); + shim_write(SHIM_PIMR, 1 << 4); break; case IRQ_NUM_EXT_SSP2: - shim_write(SHIM_PIMR, mask << 5); + shim_write(SHIM_PIMR, 1 << 5); break; case IRQ_NUM_EXT_DMAC0: - shim_write(SHIM_PIMR, mask << 16); + shim_write(SHIM_PIMR, 1 << 16); break; case IRQ_NUM_EXT_DMAC1: - shim_write(SHIM_PIMR, mask << 24); + shim_write(SHIM_PIMR, 1 << 24); break; #if defined CONFIG_CHERRYTRAIL case IRQ_NUM_EXT_DMAC2: - shim_write(SHIM_PIMRH, mask << 8); + shim_write(SHIM_PIMRH, 1 << 8); break; case IRQ_NUM_EXT_SSP3: - shim_write(SHIM_PIMRH, mask << 0); + shim_write(SHIM_PIMRH, 1 << 0); break; case IRQ_NUM_EXT_SSP4: - shim_write(SHIM_PIMRH, mask << 1); + shim_write(SHIM_PIMRH, 1 << 1); break; case IRQ_NUM_EXT_SSP5: - shim_write(SHIM_PIMRH, mask << 2); + shim_write(SHIM_PIMRH, 1 << 2); break; #endif default: @@ -113,36 +115,36 @@ void platform_interrupt_mask(uint32_t irq, uint32_t mask) } } -void platform_interrupt_unmask(uint32_t irq, uint32_t mask) +void interrupt_unmask(uint32_t irq, unsigned int cpu) { switch (irq) { case IRQ_NUM_EXT_SSP0: - shim_write(SHIM_PIMR, shim_read(SHIM_PIMR) & ~(mask << 3)); + shim_write(SHIM_PIMR, shim_read(SHIM_PIMR) & ~(1 << 3)); break; case IRQ_NUM_EXT_SSP1: - shim_write(SHIM_PIMR, shim_read(SHIM_PIMR) & ~(mask << 4)); + shim_write(SHIM_PIMR, shim_read(SHIM_PIMR) & ~(1 << 4)); break; case IRQ_NUM_EXT_SSP2: - shim_write(SHIM_PIMR, shim_read(SHIM_PIMR) & ~(mask << 5)); + shim_write(SHIM_PIMR, shim_read(SHIM_PIMR) & ~(1 << 5)); break; case IRQ_NUM_EXT_DMAC0: - shim_write(SHIM_PIMR, shim_read(SHIM_PIMR) & ~(mask << 16)); + shim_write(SHIM_PIMR, shim_read(SHIM_PIMR) & ~(1 << 16)); break; case IRQ_NUM_EXT_DMAC1: - shim_write(SHIM_PIMR, shim_read(SHIM_PIMR) & ~(mask << 24)); + shim_write(SHIM_PIMR, shim_read(SHIM_PIMR) & ~(1 << 24)); break; #if defined CONFIG_CHERRYTRAIL case IRQ_NUM_EXT_DMAC2: - shim_write(SHIM_PIMRH, shim_read(SHIM_PIMRH) & ~(mask << 8)); + shim_write(SHIM_PIMRH, shim_read(SHIM_PIMRH) & ~(1 << 8)); break; case IRQ_NUM_EXT_SSP3: - shim_write(SHIM_PIMRH, shim_read(SHIM_PIMRH) & ~(mask << 0)); + shim_write(SHIM_PIMRH, shim_read(SHIM_PIMRH) & ~(1 << 0)); break; case IRQ_NUM_EXT_SSP4: - shim_write(SHIM_PIMRH, shim_read(SHIM_PIMRH) & ~(mask << 1)); + shim_write(SHIM_PIMRH, shim_read(SHIM_PIMRH) & ~(1 << 1)); break; case IRQ_NUM_EXT_SSP5: - shim_write(SHIM_PIMRH, shim_read(SHIM_PIMRH) & ~(mask << 2)); + shim_write(SHIM_PIMRH, shim_read(SHIM_PIMRH) & ~(1 << 2)); break; #endif default: diff --git a/src/drivers/intel/baytrail/ipc.c b/src/drivers/intel/baytrail/ipc.c index 01c4bb565174..b23ac4f71e31 100644 --- a/src/drivers/intel/baytrail/ipc.c +++ b/src/drivers/intel/baytrail/ipc.c @@ -18,7 +18,6 @@ #include #include #include -#include #include extern struct ipc *_ipc; @@ -217,8 +216,8 @@ int platform_ipc_init(struct ipc *ipc) /* configure interrupt */ interrupt_register(PLATFORM_IPC_INTERRUPT, IRQ_AUTO_UNMASK, - irq_handler, NULL); - interrupt_enable(PLATFORM_IPC_INTERRUPT); + irq_handler, ipc); + interrupt_enable(PLATFORM_IPC_INTERRUPT, ipc); /* Unmask Busy and Done interrupts */ imrd = shim_read(SHIM_IMRD); diff --git a/src/drivers/intel/baytrail/timer.c b/src/drivers/intel/baytrail/timer.c index 599cd7067a3e..84c2dd607209 100644 --- a/src/drivers/intel/baytrail/timer.c +++ b/src/drivers/intel/baytrail/timer.c @@ -202,6 +202,10 @@ static int platform_timer_register(struct timer *timer, int timer_register(struct timer *timer, void(*handler)(void *arg), void *arg) { + struct timer_irq *tirq = timer->tirq; + + tirq->irq_arg = arg; + switch (timer->id) { case TIMER0: case TIMER1: @@ -216,15 +220,21 @@ int timer_register(struct timer *timer, void(*handler)(void *arg), void *arg) void timer_unregister(struct timer *timer) { - interrupt_unregister(timer->irq); + struct timer_irq *tirq = timer->tirq; + + interrupt_unregister(timer->irq, tirq->irq_arg); } void timer_enable(struct timer *timer) { - interrupt_enable(timer->irq); + struct timer_irq *tirq = timer->tirq; + + interrupt_enable(timer->irq, tirq->irq_arg); } void timer_disable(struct timer *timer) { - interrupt_disable(timer->irq); + struct timer_irq *tirq = timer->tirq; + + interrupt_disable(timer->irq, tirq->irq_arg); } diff --git a/src/drivers/intel/cavs/dmic.c b/src/drivers/intel/cavs/dmic.c index 122c82664360..46d649dc8aa7 100644 --- a/src/drivers/intel/cavs/dmic.c +++ b/src/drivers/intel/cavs/dmic.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -1499,13 +1500,11 @@ static void dmic_irq_handler(void *data) if (val1 & OUTSTAT1_ROR_BIT) trace_dmic_error("dmic_irq_handler() error: " "full fifo B or PDM overrrun"); - - /* clear IRQ */ - platform_interrupt_clear(dmic_irq(dai), 1); } static int dmic_probe(struct dai *dai) { + int irq = dmic_irq(dai); struct dmic_pdata *dmic; int ret; @@ -1527,7 +1526,14 @@ static int dmic_probe(struct dai *dai) dmic->state = COMP_STATE_READY; /* register our IRQ handler */ - ret = interrupt_register(dmic_irq(dai), IRQ_AUTO_UNMASK, + dmic->irq = interrupt_get_irq(irq, dmic_irq_name(dai)); + if (dmic->irq < 0) { + ret = dmic->irq; + rfree(dmic); + return ret; + } + + ret = interrupt_register(dmic->irq, IRQ_AUTO_UNMASK, dmic_irq_handler, dai); if (ret < 0) { trace_dmic_error("dmic failed to allocate IRQ"); @@ -1540,19 +1546,20 @@ static int dmic_probe(struct dai *dai) /* Disable dynamic clock gating for dmic before touching any reg */ pm_runtime_get_sync(DMIC_CLK, dai->index); - platform_interrupt_unmask(dmic_irq(dai), 1); - interrupt_enable(dmic_irq(dai)); + interrupt_unmask(dmic->irq, cpu_get_id()); + interrupt_enable(dmic->irq, dai); return 0; } static int dmic_remove(struct dai *dai) { + struct dmic_pdata *dmic = dai_get_drvdata(dai); int i; - interrupt_disable(dmic_irq(dai)); - platform_interrupt_mask(dmic_irq(dai), 0); - interrupt_unregister(dmic_irq(dai)); + interrupt_disable(dmic->irq, dai); + interrupt_mask(dmic->irq, cpu_get_id()); + interrupt_unregister(dmic->irq, dai); pm_runtime_put_sync(DMIC_CLK, dai->index); /* Disable DMIC power */ diff --git a/src/drivers/intel/cavs/interrupt.c b/src/drivers/intel/cavs/interrupt.c index e5186258a2d3..61d2d00ebcfc 100644 --- a/src/drivers/intel/cavs/interrupt.c +++ b/src/drivers/intel/cavs/interrupt.c @@ -9,10 +9,10 @@ #include #include -#include #include #include #include +#include #include #include @@ -23,66 +23,79 @@ */ #define LVL2_MAX_TRIES 1000 +char irq_name_level2[] = "level2"; +char irq_name_level3[] = "level3"; +char irq_name_level4[] = "level4"; +char irq_name_level5[] = "level5"; + /* * The level2 handler attempts to try and fairly service interrupt sources by * servicing on first come first served basis. If two or more IRQs arrive at the * same time then they are serviced in order of ascending status bit. */ static inline void irq_lvl2_handler(void *data, int level, uint32_t ilxsd, - uint32_t ilxmsd, uint32_t ilxmcd) + uint32_t ilxmsd) { - struct irq_desc *parent = (struct irq_desc *)data; + struct irq_desc *parent = data; + struct irq_cascade_desc *cascade = container_of(parent, + struct irq_cascade_desc, desc); struct irq_desc *child = NULL; + int core = cpu_get_id(); struct list_item *clist; uint32_t status; - uint32_t i = 0; uint32_t tries = LVL2_MAX_TRIES; /* read active interrupt status */ status = irq_read(ilxsd); + if (!status) + return; /* handle each child */ - while (irq_read(ilxsd)) { + for (;;) { + unsigned int bit = ffs(status) - 1; + bool handled = false; - /* are all IRQs serviced from last status ? */ - if (status == 0x0) { - /* yes, so reload the new status and service again */ - status = irq_read(ilxsd); - i = 0; - tries--; - } + status &= ~(1 << bit); - /* any devices continually interrupting / can't be cleared ? */ - if (!tries) { - tries = LVL2_MAX_TRIES; - trace_irq_error("irq_lvl2_handler() error: " - "IRQ storm at level %d status %08X", - level, irq_read(ilxsd)); - } - - /* any IRQ for this child bit ? */ - if ((status & 0x1) == 0) - goto next; + spin_lock(&cascade->lock); /* get child if any and run handler */ - list_for_item(clist, &parent->child[i]) { + list_for_item(clist, &cascade->child[bit].list) { child = container_of(clist, struct irq_desc, irq_list); - if (child && child->handler) { + if (child->handler && (child->cpu_mask & 1 << core)) { child->handler(child->handler_arg); - } else { - /* nobody cared ? */ - trace_irq_error("irq_lvl2_handler() error: " - "nobody cared level %d bit %d", - level, i); - /* now mask it */ - irq_write(ilxmcd, 0x1 << i); + handled = true; } } -next: - status >>= 1; - i++; + spin_unlock(&cascade->lock); + + if (!handled) { + /* nobody cared ? */ + trace_irq_error("irq_lvl2_handler() error: " + "nobody cared level %d bit %d", + level, bit); + /* now mask it */ + irq_write(ilxmsd, 0x1 << bit); + } + + /* are all IRQs serviced from last status ? */ + if (status) + continue; + + /* yes, so reload the new status and service again */ + status = irq_read(ilxsd); + if (!status) + break; + + /* any devices continually interrupting / can't be cleared ? */ + if (!--tries) { + tries = LVL2_MAX_TRIES; + trace_irq_error("irq_lvl2_handler() error: " + "IRQ storm at level %d status %08X", + level, irq_read(ilxsd)); + } } } @@ -90,8 +103,7 @@ static inline void irq_lvl2_handler(void *data, int level, uint32_t ilxsd, irq_lvl2_handler(data, \ IRQ_NUM_EXT_LEVEL##n, \ REG_IRQ_IL##n##SD(core), \ - REG_IRQ_IL##n##MSD(core), \ - REG_IRQ_IL##n##MCD(core)) + REG_IRQ_IL##n##MSD(core)) static void irq_lvl2_level2_handler(void *data) { @@ -113,108 +125,117 @@ static void irq_lvl2_level5_handler(void *data) IRQ_LVL2_HANDLER(5); } -/* DSP internal interrupts */ -static struct irq_desc dsp_irq[PLATFORM_CORE_COUNT][4] = { - {{IRQ_NUM_EXT_LEVEL2, irq_lvl2_level2_handler, }, - {IRQ_NUM_EXT_LEVEL3, irq_lvl2_level3_handler, }, - {IRQ_NUM_EXT_LEVEL4, irq_lvl2_level4_handler, }, - {IRQ_NUM_EXT_LEVEL5, irq_lvl2_level5_handler, } }, -#if PLATFORM_CORE_COUNT > 1 - {{IRQ_NUM_EXT_LEVEL2, irq_lvl2_level2_handler, }, - {IRQ_NUM_EXT_LEVEL3, irq_lvl2_level3_handler, }, - {IRQ_NUM_EXT_LEVEL4, irq_lvl2_level4_handler, }, - {IRQ_NUM_EXT_LEVEL5, irq_lvl2_level5_handler, } }, -#endif -#if PLATFORM_CORE_COUNT > 2 - {{IRQ_NUM_EXT_LEVEL2, irq_lvl2_level2_handler, }, - {IRQ_NUM_EXT_LEVEL3, irq_lvl2_level3_handler, }, - {IRQ_NUM_EXT_LEVEL4, irq_lvl2_level4_handler, }, - {IRQ_NUM_EXT_LEVEL5, irq_lvl2_level5_handler, } }, -#endif -#if PLATFORM_CORE_COUNT > 3 - {{IRQ_NUM_EXT_LEVEL2, irq_lvl2_level2_handler, }, - {IRQ_NUM_EXT_LEVEL3, irq_lvl2_level3_handler, }, - {IRQ_NUM_EXT_LEVEL4, irq_lvl2_level4_handler, }, - {IRQ_NUM_EXT_LEVEL5, irq_lvl2_level5_handler, } }, -#endif -}; +uint32_t platform_interrupt_get_enabled(void) +{ + return 0; +} -struct irq_desc *platform_irq_get_parent(uint32_t irq) +void interrupt_mask(uint32_t irq, unsigned int cpu) { - int core = SOF_IRQ_CPU(irq); + struct irq_cascade_desc *cascade = interrupt_get_parent(irq); - switch (SOF_IRQ_NUMBER(irq)) { - case IRQ_NUM_EXT_LEVEL2: - return &dsp_irq[core][0]; - case IRQ_NUM_EXT_LEVEL3: - return &dsp_irq[core][1]; - case IRQ_NUM_EXT_LEVEL4: - return &dsp_irq[core][2]; - case IRQ_NUM_EXT_LEVEL5: - return &dsp_irq[core][3]; - default: - return NULL; - } + if (cascade && cascade->ops->mask) + cascade->ops->mask(&cascade->desc, irq - cascade->irq_base, + cpu); } -uint32_t platform_interrupt_get_enabled(void) +void interrupt_unmask(uint32_t irq, unsigned int cpu) { - return 0; + struct irq_cascade_desc *cascade = interrupt_get_parent(irq); + + if (cascade && cascade->ops->unmask) + cascade->ops->unmask(&cascade->desc, irq - cascade->irq_base, + cpu); } -void platform_interrupt_mask(uint32_t irq, uint32_t mask) +static void irq_mask(struct irq_desc *desc, uint32_t irq, unsigned int core) { - int core = SOF_IRQ_CPU(irq); - /* mask external interrupt bit */ - switch (SOF_IRQ_NUMBER(irq)) { + switch (desc->irq) { case IRQ_NUM_EXT_LEVEL5: - irq_write(REG_IRQ_IL5MSD(core), 1 << SOF_IRQ_BIT(irq)); + irq_write(REG_IRQ_IL5MSD(core), 1 << irq); break; case IRQ_NUM_EXT_LEVEL4: - irq_write(REG_IRQ_IL4MSD(core), 1 << SOF_IRQ_BIT(irq)); + irq_write(REG_IRQ_IL4MSD(core), 1 << irq); break; case IRQ_NUM_EXT_LEVEL3: - irq_write(REG_IRQ_IL3MSD(core), 1 << SOF_IRQ_BIT(irq)); + irq_write(REG_IRQ_IL3MSD(core), 1 << irq); break; case IRQ_NUM_EXT_LEVEL2: - irq_write(REG_IRQ_IL2MSD(core), 1 << SOF_IRQ_BIT(irq)); - break; - default: + irq_write(REG_IRQ_IL2MSD(core), 1 << irq); break; } } -void platform_interrupt_unmask(uint32_t irq, uint32_t mask) +static void irq_unmask(struct irq_desc *desc, uint32_t irq, unsigned int core) { - int core = SOF_IRQ_CPU(irq); - /* unmask external interrupt bit */ - switch (SOF_IRQ_NUMBER(irq)) { + switch (desc->irq) { case IRQ_NUM_EXT_LEVEL5: - irq_write(REG_IRQ_IL5MCD(core), 1 << SOF_IRQ_BIT(irq)); + irq_write(REG_IRQ_IL5MCD(core), 1 << irq); break; case IRQ_NUM_EXT_LEVEL4: - irq_write(REG_IRQ_IL4MCD(core), 1 << SOF_IRQ_BIT(irq)); + irq_write(REG_IRQ_IL4MCD(core), 1 << irq); break; case IRQ_NUM_EXT_LEVEL3: - irq_write(REG_IRQ_IL3MCD(core), 1 << SOF_IRQ_BIT(irq)); + irq_write(REG_IRQ_IL3MCD(core), 1 << irq); break; case IRQ_NUM_EXT_LEVEL2: - irq_write(REG_IRQ_IL2MCD(core), 1 << SOF_IRQ_BIT(irq)); - break; - default: + irq_write(REG_IRQ_IL2MCD(core), 1 << irq); break; } } +static const struct irq_cascade_ops irq_ops = { + .mask = irq_mask, + .unmask = irq_unmask, +}; + +/* DSP internal interrupts */ +static const struct irq_cascade_tmpl dsp_irq[] = { + { + .name = irq_name_level2, + .irq = IRQ_NUM_EXT_LEVEL2, + .handler = irq_lvl2_level2_handler, + .ops = &irq_ops, + .global_mask = false, + }, { + .name = irq_name_level3, + .irq = IRQ_NUM_EXT_LEVEL3, + .handler = irq_lvl2_level3_handler, + .ops = &irq_ops, + .global_mask = false, + }, { + .name = irq_name_level4, + .irq = IRQ_NUM_EXT_LEVEL4, + .handler = irq_lvl2_level4_handler, + .ops = &irq_ops, + .global_mask = false, + }, { + .name = irq_name_level5, + .irq = IRQ_NUM_EXT_LEVEL5, + .handler = irq_lvl2_level5_handler, + .ops = &irq_ops, + .global_mask = false, + }, +}; + +void platform_interrupt_set(uint32_t irq) +{ + if (interrupt_is_dsp_direct(irq)) + arch_interrupt_set(irq); +} + void platform_interrupt_clear(uint32_t irq, uint32_t mask) { + if (interrupt_is_dsp_direct(irq)) + arch_interrupt_clear(irq); } +/* Called on each core: from platform_init() and from slave_core_init() */ void platform_interrupt_init(void) { - int i, j; + int i; int core = cpu_get_id(); /* mask all external IRQs by default */ @@ -223,9 +244,9 @@ void platform_interrupt_init(void) irq_write(REG_IRQ_IL4MSD(core), REG_IRQ_IL4MD_ALL); irq_write(REG_IRQ_IL5MSD(core), REG_IRQ_IL5MD_ALL); - for (i = 0; i < ARRAY_SIZE(dsp_irq[core]); i++) { - spinlock_init(&dsp_irq[core][i].lock); - for (j = 0; j < PLATFORM_IRQ_CHILDREN; j++) - list_init(&dsp_irq[core][i].child[j]); - } + if (core != PLATFORM_MASTER_CORE_ID) + return; + + for (i = 0; i < ARRAY_SIZE(dsp_irq); i++) + interrupt_cascade_register(dsp_irq + i); } diff --git a/src/drivers/intel/cavs/ipc.c b/src/drivers/intel/cavs/ipc.c index 671935819e36..75cc5d86a4c1 100644 --- a/src/drivers/intel/cavs/ipc.c +++ b/src/drivers/intel/cavs/ipc.c @@ -231,6 +231,8 @@ void ipc_platform_send_msg(struct ipc *ipc) int platform_ipc_init(struct ipc *ipc) { + int irq; + _ipc = ipc; ipc_set_drvdata(_ipc, NULL); @@ -240,9 +242,12 @@ int platform_ipc_init(struct ipc *ipc) ipc_process_task, _ipc, 0, 0); /* configure interrupt */ - interrupt_register(PLATFORM_IPC_INTERRUPT, IRQ_AUTO_UNMASK, - ipc_irq_handler, NULL); - interrupt_enable(PLATFORM_IPC_INTERRUPT); + irq = interrupt_get_irq(PLATFORM_IPC_INTERRUPT, + PLATFORM_IPC_INTERRUPT_NAME); + if (irq < 0) + return irq; + interrupt_register(irq, IRQ_AUTO_UNMASK, ipc_irq_handler, ipc); + interrupt_enable(irq, ipc); /* enable IPC interrupts from host */ ipc_write(IPC_DIPCCTL, IPC_DIPCCTL_IPCIDIE | IPC_DIPCCTL_IPCTBIE); diff --git a/src/drivers/intel/cavs/timer.c b/src/drivers/intel/cavs/timer.c index cbca6f704673..dd78802704ab 100644 --- a/src/drivers/intel/cavs/timer.c +++ b/src/drivers/intel/cavs/timer.c @@ -95,15 +95,22 @@ 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) { + struct timer_irq *tirq = timer->tirq; int err; /* register timer interrupt */ - err = interrupt_register(timer->irq, IRQ_MANUAL_UNMASK, handler, arg); + tirq->logical_irq = interrupt_get_irq(timer->irq, timer->irq_name); + if (tirq->logical_irq < 0) + return tirq->logical_irq; + err = interrupt_register(tirq->logical_irq, IRQ_MANUAL_UNMASK, handler, + arg); if (err < 0) return err; + tirq->irq_arg = arg; + /* enable timer interrupt */ - interrupt_enable(timer->irq); + interrupt_enable(tirq->logical_irq, arg); /* disable timer interrupt on core level */ timer_disable(timer); @@ -113,34 +120,56 @@ static int platform_timer_register(struct timer *timer, int timer_register(struct timer *timer, void(*handler)(void *arg), void *arg) { + struct timer_irq *tirq = timer->tirq; + int ret; + switch (timer->id) { case TIMER0: case TIMER1: case TIMER2: - return arch_timer_register(timer, handler, arg); + ret = arch_timer_register(timer, handler, arg); + if (ret < 0) + return ret; + /* + * Actually this isn't needed for arch_interrupt_register(), + * since arch_interrupt_unregister() doesn't support interrupt + * sharing and thus doesn't need the handler argument to locate + * the handler, do it just for uniformity + */ + tirq->irq_arg = arg; + break; case TIMER3: - return platform_timer_register(timer, handler, arg); + ret = platform_timer_register(timer, handler, arg); + if (ret < 0) + return ret; + break; default: return -EINVAL; } + + return ret; } static void platform_timer_unregister(struct timer *timer) { + struct timer_irq *tirq = timer->tirq; + /* disable timer interrupt */ - interrupt_disable(timer->irq); + interrupt_disable(tirq->logical_irq, tirq->irq_arg); /* unregister timer interrupt */ - interrupt_unregister(timer->irq); + interrupt_unregister(tirq->logical_irq, tirq->irq_arg); } void timer_unregister(struct timer *timer) { + struct timer_irq *tirq = timer->tirq; + switch (timer->id) { case TIMER0: case TIMER1: case TIMER2: - interrupt_unregister(timer->irq); + interrupt_unregister(tirq->logical_irq, tirq->irq_arg); break; case TIMER3: platform_timer_unregister(timer); @@ -150,28 +179,32 @@ void timer_unregister(struct timer *timer) void timer_enable(struct timer *timer) { + struct timer_irq *tirq = timer->tirq; + switch (timer->id) { case TIMER0: case TIMER1: case TIMER2: - interrupt_enable(timer->irq); + interrupt_enable(tirq->logical_irq, tirq->irq_arg); break; case TIMER3: - platform_interrupt_unmask(timer->irq, 0); + interrupt_unmask(tirq->logical_irq, timer->core); break; } } void timer_disable(struct timer *timer) { + struct timer_irq *tirq = timer->tirq; + switch (timer->id) { case TIMER0: case TIMER1: case TIMER2: - interrupt_disable(timer->irq); + interrupt_disable(tirq->logical_irq, tirq->irq_arg); break; case TIMER3: - platform_interrupt_mask(timer->irq, 0); + interrupt_mask(tirq->logical_irq, timer->core); break; } } diff --git a/src/drivers/intel/haswell/interrupt.c b/src/drivers/intel/haswell/interrupt.c index 3f37fc5ace9a..aa76f5f1721b 100644 --- a/src/drivers/intel/haswell/interrupt.c +++ b/src/drivers/intel/haswell/interrupt.c @@ -8,18 +8,11 @@ #include #include -#include #include void platform_interrupt_init(void) {} -/* haswell does not support child IRQs */ -struct irq_desc *platform_irq_get_parent(uint32_t irq) -{ - return NULL; -} - -void platform_interrupt_set(int irq) +void platform_interrupt_set(uint32_t irq) { arch_interrupt_set(irq); } @@ -32,7 +25,10 @@ void platform_interrupt_clear(uint32_t irq, uint32_t mask) case IRQ_NUM_EXT_DMAC1: case IRQ_NUM_EXT_SSP0: case IRQ_NUM_EXT_SSP1: - interrupt_clear(irq); + case IRQ_NUM_EXT_IA: + case IRQ_NUM_SOFTWARE1: + case IRQ_NUM_SOFTWARE2: + arch_interrupt_clear(irq); break; default: break; @@ -45,7 +41,7 @@ uint32_t platform_interrupt_get_enabled(void) return shim_read(SHIM_IMRD); } -void platform_interrupt_mask(uint32_t irq, uint32_t mask) +void interrupt_mask(uint32_t irq, unsigned int cpu) { switch (irq) { case IRQ_NUM_EXT_SSP0: @@ -65,7 +61,7 @@ void platform_interrupt_mask(uint32_t irq, uint32_t mask) } } -void platform_interrupt_unmask(uint32_t irq, uint32_t mask) +void interrupt_unmask(uint32_t irq, unsigned int cpu) { switch (irq) { case IRQ_NUM_EXT_SSP0: diff --git a/src/drivers/intel/haswell/ipc.c b/src/drivers/intel/haswell/ipc.c index 2345c8dd17d8..9d84caa319c0 100644 --- a/src/drivers/intel/haswell/ipc.c +++ b/src/drivers/intel/haswell/ipc.c @@ -18,7 +18,6 @@ #include #include #include -#include #include extern struct ipc *_ipc; @@ -207,8 +206,8 @@ int platform_ipc_init(struct ipc *ipc) /* configure interrupt */ interrupt_register(PLATFORM_IPC_INTERRUPT, IRQ_AUTO_UNMASK, - irq_handler, NULL); - interrupt_enable(PLATFORM_IPC_INTERRUPT); + irq_handler, ipc); + interrupt_enable(PLATFORM_IPC_INTERRUPT, ipc); /* Unmask Busy and Done interrupts */ imrd = shim_read(SHIM_IMRD); diff --git a/src/drivers/intel/haswell/timer.c b/src/drivers/intel/haswell/timer.c index f66969702ba2..03be80c3d0f5 100644 --- a/src/drivers/intel/haswell/timer.c +++ b/src/drivers/intel/haswell/timer.c @@ -76,6 +76,10 @@ void platform_dai_wallclock(struct comp_dev *dai, uint64_t *wallclock) int timer_register(struct timer *timer, void(*handler)(void *arg), void *arg) { + struct timer_irq *tirq = timer->tirq; + + tirq->irq_arg = arg; + switch (timer->id) { case TIMER0: case TIMER1: @@ -88,15 +92,21 @@ int timer_register(struct timer *timer, void(*handler)(void *arg), void *arg) void timer_unregister(struct timer *timer) { - interrupt_unregister(timer->irq); + struct timer_irq *tirq = timer->tirq; + + interrupt_unregister(timer->irq, tirq->irq_arg); } void timer_enable(struct timer *timer) { - interrupt_enable(timer->irq); + struct timer_irq *tirq = timer->tirq; + + interrupt_enable(timer->irq, tirq->irq_arg); } void timer_disable(struct timer *timer) { - interrupt_disable(timer->irq); + struct timer_irq *tirq = timer->tirq; + + interrupt_disable(timer->irq, tirq->irq_arg); } diff --git a/src/drivers/intel/pmc-ipc.c b/src/drivers/intel/pmc-ipc.c index 9dc2bf85e7a2..ccbbcc557da6 100644 --- a/src/drivers/intel/pmc-ipc.c +++ b/src/drivers/intel/pmc-ipc.c @@ -13,7 +13,6 @@ #include #include #include -#include #include /* private data for IPC */ @@ -139,8 +138,8 @@ int platform_ipc_pmc_init(void) /* configure interrupt */ interrupt_register(IRQ_NUM_EXT_PMC, IRQ_AUTO_UNMASK, irq_handler, - NULL); - interrupt_enable(IRQ_NUM_EXT_PMC); + _pmc); + interrupt_enable(IRQ_NUM_EXT_PMC, _pmc); /* Unmask Busy and Done interrupts */ imrlpesc = shim_read(SHIM_IMRLPESC); diff --git a/src/drivers/interrupt.c b/src/drivers/interrupt.c index 4c88dd8a6b9a..a3d67721912a 100644 --- a/src/drivers/interrupt.c +++ b/src/drivers/interrupt.c @@ -7,192 +7,402 @@ #include #include -#include #include +#include #include #include +#include #include #include #include #include -static int irq_register_child(struct irq_desc *parent, int irq, int unmask, - void (*handler)(void *arg), void *arg) +static spinlock_t cascade_lock; +static union { + struct { + struct irq_cascade_desc *list; + int last_irq; + } __aligned(PLATFORM_DCACHE_ALIGN); + uint8_t bytes[PLATFORM_DCACHE_ALIGN]; +} cascade_root; + +static int interrupt_register_internal(uint32_t irq, int unmask, + void (*handler)(void *arg), + void *arg, struct irq_desc *desc); +static void interrupt_unregister_internal(uint32_t irq, const void *arg, + struct irq_desc *desc); + +int interrupt_cascade_register(const struct irq_cascade_tmpl *tmpl) { - int ret = 0; - struct irq_desc *child; + struct irq_cascade_desc **cascade; + unsigned long flags; + unsigned int i; + int ret; - if (parent == NULL) + if (!tmpl->name || !tmpl->ops) return -EINVAL; - spin_lock(&parent->lock); + spin_lock_irq(&cascade_lock, flags); - /* init child from run-time, may be registered and unregistered - * many times at run-time - */ - child = rzalloc(RZONE_SYS_RUNTIME, SOF_MEM_CAPS_RAM, - sizeof(struct irq_desc)); - if (!child) { - ret = -ENOMEM; - goto finish; + dcache_invalidate_region(&cascade_root, sizeof(cascade_root)); + + for (cascade = &cascade_root.list; *cascade; + cascade = &(*cascade)->next) { + if (!rstrcmp((*cascade)->name, tmpl->name)) { + ret = -EEXIST; + trace_error(TRACE_CLASS_IRQ, + "error: cascading IRQ controller name duplication!"); + goto unlock; + } } - child->enabled_count = 0; - child->handler = handler; - child->handler_arg = arg; - child->id = SOF_IRQ_ID(irq); - child->unmask = unmask; + *cascade = rzalloc(RZONE_SYS | RZONE_FLAG_UNCACHED, SOF_MEM_CAPS_RAM, + sizeof(**cascade)); + + spinlock_init(&(*cascade)->lock); + for (i = 0; i < PLATFORM_IRQ_CHILDREN; i++) + list_init(&(*cascade)->child[i].list); + + (*cascade)->name = tmpl->name; + (*cascade)->ops = tmpl->ops; + (*cascade)->global_mask = tmpl->global_mask; + (*cascade)->irq_base = cascade_root.last_irq + 1; + (*cascade)->desc.irq = tmpl->irq; + (*cascade)->desc.handler = tmpl->handler; + (*cascade)->desc.handler_arg = &(*cascade)->desc; + (*cascade)->desc.cpu_mask = 1 << cpu_get_id(); + + cascade_root.last_irq += ARRAY_SIZE((*cascade)->child); + dcache_writeback_region(&cascade_root, sizeof(cascade_root)); + + ret = 0; + +unlock: + spin_unlock_irq(&cascade_lock, flags); + + return ret; +} - list_item_append(&child->irq_list, &parent->child[SOF_IRQ_BIT(irq)]); +int interrupt_get_irq(unsigned int irq, const char *name) +{ + struct irq_cascade_desc *cascade; + unsigned long flags; + int ret = -ENODEV; - /* do we need to register parent ? */ - if (parent->num_children == 0) { - ret = arch_interrupt_register(parent->irq, - parent->handler, parent); + if (!name || name[0] == '\0') + return irq; + + /* If a name is specified, irq must be <= PLATFORM_IRQ_CHILDREN */ + if (irq >= PLATFORM_IRQ_CHILDREN) { + trace_error(TRACE_CLASS_IRQ, + "error: IRQ %d invalid as a child interrupt!"); + return -EINVAL; } - /* increment number of children */ - parent->num_children++; + spin_lock_irq(&cascade_lock, flags); + + dcache_invalidate_region(&cascade_root, sizeof(cascade_root)); + + for (cascade = cascade_root.list; cascade; cascade = cascade->next) + /* .name is non-volatile */ + if (!rstrcmp(name, cascade->name)) { + ret = cascade->irq_base + irq; + break; + } + + spin_unlock_irq(&cascade_lock, flags); -finish: - spin_unlock(&parent->lock); return ret; } -static void irq_unregister_child(struct irq_desc *parent, int irq) +struct irq_cascade_desc *interrupt_get_parent(uint32_t irq) { - struct irq_desc *child; - struct list_item *clist; - struct list_item *tlist; + struct irq_cascade_desc *cascade, *c = NULL; + unsigned long flags; - spin_lock(&parent->lock); + if (irq < PLATFORM_IRQ_CHILDREN) + return NULL; - /* does child already exist ? */ - if (list_is_empty(&parent->child[SOF_IRQ_BIT(irq)])) - goto finish; + spin_lock_irq(&cascade_lock, flags); - list_for_item_safe(clist, tlist, &parent->child[SOF_IRQ_BIT(irq)]) { - child = container_of(clist, struct irq_desc, irq_list); + dcache_invalidate_region(&cascade_root, sizeof(cascade_root)); - if (SOF_IRQ_ID(irq) == child->id) { - list_item_del(&child->irq_list); - parent->num_children--; - rfree(child); + for (cascade = cascade_root.list; cascade; cascade = cascade->next) + if (irq >= cascade->irq_base && + irq < cascade->irq_base + PLATFORM_IRQ_CHILDREN) { + c = cascade; + break; + } + + spin_unlock_irq(&cascade_lock, flags); + + return c; +} + +void interrupt_init(void) +{ + cascade_root.last_irq = PLATFORM_IRQ_CHILDREN - 1; + dcache_writeback_region(&cascade_root, sizeof(cascade_root)); + spinlock_init(&cascade_lock); +} + +static int irq_register_child(struct irq_cascade_desc *cascade, int irq, + int unmask, void (*handler)(void *arg), void *arg, + struct irq_desc *desc) +{ + unsigned int core = cpu_get_id(); + struct irq_desc *child, *parent = &cascade->desc; + struct list_item *list, *head; + int hw_irq, ret = 0; + + hw_irq = irq - cascade->irq_base; + + if (hw_irq < 0 || cascade->irq_base + PLATFORM_IRQ_CHILDREN <= irq) + return -EINVAL; + + head = &cascade->child[hw_irq].list; + + list_for_item(list, head) { + child = container_of(list, struct irq_desc, irq_list); + + if (child->handler_arg == arg) { + trace_error(TRACE_CLASS_IRQ, + "error: IRQ 0x%x handler argument re-used!", + irq); + return -EEXIST; + } + + if (child->unmask != unmask) { + trace_error(TRACE_CLASS_IRQ, + "error: IRQ 0x%x flags differ!", irq); + return -EINVAL; } } - /* - * unregister the root interrupt if the this l2 is - * the last registered one. - */ - if (parent->num_children == 0) - arch_interrupt_unregister(parent->irq); + if (!desc) { + /* init child from run-time, may be registered and unregistered + * many times at run-time + */ + child = rzalloc(RZONE_SYS_RUNTIME | RZONE_FLAG_UNCACHED, + SOF_MEM_CAPS_RAM, sizeof(struct irq_desc)); + if (!child) + return -ENOMEM; + + child->handler = handler; + child->handler_arg = arg; + child->irq = irq; + } else { + child = desc; + child->cpu_mask = 0; + } + + child->unmask = unmask; + + list_item_append(&child->irq_list, head); -finish: - spin_unlock(&parent->lock); + /* do we need to register parent on this CPU? */ + if (!cascade->num_children[core]) + ret = interrupt_register_internal(parent->irq, IRQ_AUTO_UNMASK, + parent->handler, parent, + parent); + + /* increment number of children */ + if (!ret) + cascade->num_children[core]++; + + return ret; } -static uint32_t irq_enable_child(struct irq_desc *parent, int irq) +static void irq_unregister_child(struct irq_cascade_desc *cascade, int irq, + const void *arg, struct irq_desc *desc) { - struct irq_desc *child; - struct list_item *clist; + struct irq_desc *child, *parent = &cascade->desc; + int hw_irq = irq - cascade->irq_base; + struct list_item *list, *head = &cascade->child[hw_irq].list; + unsigned int core = cpu_get_id(); - spin_lock(&parent->lock); + list_for_item(list, head) { + child = container_of(list, struct irq_desc, irq_list); - /* enable the parent interrupt */ - if (parent->enabled_count == 0) - arch_interrupt_enable_mask(1 << SOF_IRQ_NUMBER(irq)); + if (child->handler_arg == arg) { + list_item_del(&child->irq_list); + cascade->num_children[core]--; + if (!desc) + rfree(child); + + /* + * unregister the root interrupt if this l2 is the last + * registered child. + */ + if (!cascade->num_children[core]) + interrupt_unregister_internal(parent->irq, + parent, parent); + + break; + } + } +} - list_for_item(clist, &parent->child[SOF_IRQ_BIT(irq)]) { - child = container_of(clist, struct irq_desc, irq_list); +static uint32_t irq_enable_child(struct irq_cascade_desc *cascade, int irq, + void *arg) +{ + int hw_irq = irq - cascade->irq_base; + unsigned int core = cpu_get_id(); + struct irq_child *child; + unsigned int child_idx; + struct list_item *list; + unsigned long flags; - if ((SOF_IRQ_ID(irq) == child->id) && - !child->enabled_count) { - child->enabled_count = 1; - parent->enabled_count++; + /* + * Locking is child to parent: when called recursively we are already + * holding the child's lock and then also taking the parent's lock. The + * same holds for the interrupt_(un)register() paths. + */ + spin_lock_irq(&cascade->lock, flags); + + child = cascade->child + hw_irq; + child_idx = cascade->global_mask ? 0 : core; - /* enable the child interrupt */ - platform_interrupt_unmask(irq, 0); + list_for_item(list, &child->list) { + struct irq_desc *d = container_of(list, + struct irq_desc, irq_list); + + if (d->handler_arg == arg) { + d->cpu_mask |= 1 << core; + break; } } - spin_unlock(&parent->lock); - return 0; + if (!child->enable_count[child_idx]++) { + /* enable the parent interrupt */ + if (!cascade->enable_count[core]++) + interrupt_enable(cascade->desc.irq, + cascade->desc.handler_arg); + /* enable the child interrupt */ + interrupt_unmask(irq, core); + } + + spin_unlock_irq(&cascade->lock, flags); + + return 0; } -static uint32_t irq_disable_child(struct irq_desc *parent, int irq) +static uint32_t irq_disable_child(struct irq_cascade_desc *cascade, int irq, + void *arg) { - struct irq_desc *child; - struct list_item *clist; + int hw_irq = irq - cascade->irq_base; + unsigned int core = cpu_get_id(); + struct irq_child *child; + unsigned int child_idx; + struct list_item *list; + unsigned long flags; - spin_lock(&parent->lock); + spin_lock_irq(&cascade->lock, flags); - list_for_item(clist, &parent->child[SOF_IRQ_BIT(irq)]) { - child = container_of(clist, struct irq_desc, irq_list); + child = cascade->child + hw_irq; + child_idx = cascade->global_mask ? 0 : core; - if ((SOF_IRQ_ID(irq) == child->id) && - child->enabled_count) { - child->enabled_count = 0; - parent->enabled_count--; + list_for_item(list, &child->list) { + struct irq_desc *d = container_of(list, + struct irq_desc, irq_list); - /* disable the child interrupt */ - platform_interrupt_mask(irq, 0); + if (d->handler_arg == arg) { + d->cpu_mask &= ~(1 << core); + break; } } - if (parent->enabled_count == 0) - arch_interrupt_disable_mask(1 << SOF_IRQ_NUMBER(irq)); + if (!child->enable_count[child_idx]) { + trace_error(TRACE_CLASS_IRQ, + "error: IRQ %x unbalanced interrupt_disable()", + irq); + } else if (!--child->enable_count[child_idx]) { + /* disable the child interrupt */ + interrupt_mask(irq, core); + + /* disable the parent interrupt */ + if (!--cascade->enable_count[core]) + interrupt_disable(cascade->desc.irq, + cascade->desc.handler_arg); + } + + spin_unlock_irq(&cascade->lock, flags); - spin_unlock(&parent->lock); return 0; } int interrupt_register(uint32_t irq, int unmask, void (*handler)(void *arg), void *arg) { - struct irq_desc *parent; + return interrupt_register_internal(irq, unmask, handler, arg, NULL); +} + +static int interrupt_register_internal(uint32_t irq, int unmask, + void (*handler)(void *arg), + void *arg, struct irq_desc *desc) +{ + struct irq_cascade_desc *cascade; + /* Avoid a bogus compiler warning */ + unsigned long flags = 0; + int ret; /* no parent means we are registering DSP internal IRQ */ - parent = platform_irq_get_parent(irq); - if (parent == NULL) + cascade = interrupt_get_parent(irq); + if (!cascade) return arch_interrupt_register(irq, handler, arg); - else - return irq_register_child(parent, irq, unmask, handler, arg); + + spin_lock_irq(&cascade->lock, flags); + ret = irq_register_child(cascade, irq, unmask, handler, arg, desc); + spin_unlock_irq(&cascade->lock, flags); + + return ret; +} + +void interrupt_unregister(uint32_t irq, const void *arg) +{ + interrupt_unregister_internal(irq, arg, NULL); } -void interrupt_unregister(uint32_t irq) +static void interrupt_unregister_internal(uint32_t irq, const void *arg, + struct irq_desc *desc) { - struct irq_desc *parent; + struct irq_cascade_desc *cascade; + /* Avoid a bogus compiler warning */ + unsigned long flags = 0; /* no parent means we are unregistering DSP internal IRQ */ - parent = platform_irq_get_parent(irq); - if (parent == NULL) + cascade = interrupt_get_parent(irq); + if (!cascade) { arch_interrupt_unregister(irq); - else - irq_unregister_child(parent, irq); + return; + } + + spin_lock_irq(&cascade->lock, flags); + irq_unregister_child(cascade, irq, arg, desc); + spin_unlock_irq(&cascade->lock, flags); } -uint32_t interrupt_enable(uint32_t irq) +uint32_t interrupt_enable(uint32_t irq, void *arg) { - struct irq_desc *parent; + struct irq_cascade_desc *cascade; /* no parent means we are enabling DSP internal IRQ */ - parent = platform_irq_get_parent(irq); - if (parent == NULL) - return arch_interrupt_enable_mask(1 << irq); - else - return irq_enable_child(parent, irq); + cascade = interrupt_get_parent(irq); + if (cascade) + return irq_enable_child(cascade, irq, arg); + + return arch_interrupt_enable_mask(1 << irq); } -uint32_t interrupt_disable(uint32_t irq) +uint32_t interrupt_disable(uint32_t irq, void *arg) { - struct irq_desc *parent; + struct irq_cascade_desc *cascade; /* no parent means we are disabling DSP internal IRQ */ - parent = platform_irq_get_parent(irq); - if (parent == NULL) - return arch_interrupt_disable_mask(1 << irq); - else - return irq_disable_child(parent, irq); + cascade = interrupt_get_parent(irq); + if (cascade) + return irq_disable_child(cascade, irq, arg); + + return arch_interrupt_disable_mask(1 << irq); } diff --git a/src/include/sof/common.h b/src/include/sof/common.h index 61fa8ecb80bf..23c59a44bb6e 100644 --- a/src/include/sof/common.h +++ b/src/include/sof/common.h @@ -29,6 +29,8 @@ #define __aligned(x) __attribute__((__aligned__(x))) +#define ffs(i) __builtin_ffs(i) + /* count number of var args */ #define PP_NARG(...) (sizeof((unsigned int[]){0, ##__VA_ARGS__}) \ / sizeof(unsigned int) - 1) diff --git a/src/include/sof/drivers/dmic.h b/src/include/sof/drivers/dmic.h index 6328162df3f4..df7e17c836e6 100644 --- a/src/include/sof/drivers/dmic.h +++ b/src/include/sof/drivers/dmic.h @@ -307,8 +307,8 @@ #define FIR_COEF_A(x) SET_BITS(19, 0, x) #define FIR_COEF_B(x) SET_BITS(19, 0, x) -#define dmic_irq(dmic) \ - dmic->plat_data.irq +#define dmic_irq(dmic) dmic->plat_data.irq +#define dmic_irq_name(dmic) dmic->plat_data.irq_name /* DMIC private data */ struct dmic_pdata { @@ -319,6 +319,7 @@ struct dmic_pdata { int32_t startcount; int32_t gain; int32_t gain_coef; + int irq; }; extern const struct dai_driver dmic_driver; diff --git a/src/include/sof/drivers/idc.h b/src/include/sof/drivers/idc.h index 995a2f173cad..a5673241776b 100644 --- a/src/include/sof/drivers/idc.h +++ b/src/include/sof/drivers/idc.h @@ -98,6 +98,7 @@ struct idc { uint32_t done_bit_mask; /**< done interrupt mask */ struct idc_msg received_msg; /**< received message */ struct task idc_task; /**< IDC processing task */ + int irq; }; #endif /* __SOF_DRIVERS_IDC_H__ */ diff --git a/src/include/sof/drivers/interrupt.h b/src/include/sof/drivers/interrupt.h index 040faad5ce22..f85cf66b6a73 100644 --- a/src/include/sof/drivers/interrupt.h +++ b/src/include/sof/drivers/interrupt.h @@ -10,11 +10,12 @@ #include #include -#include +#include #include #include #include #include +#include #include #define trace_irq(__e) trace_event(TRACE_CLASS_IRQ, __e) @@ -24,52 +25,132 @@ #define IRQ_MANUAL_UNMASK 0 #define IRQ_AUTO_UNMASK 1 -struct irq_desc { - /* irq must be first for constructor */ - int irq; /* logical IRQ number */ - - /* handler is optional for constructor */ - void (*handler)(void *arg); - void *handler_arg; +/** + * \brief child IRQ descriptor for cascading IRQ controllers. + */ +struct irq_child { + int enable_count[PLATFORM_CORE_COUNT]; /**< IRQ enable counter */ + struct list_item list; /**< head for IRQ descriptors, + * sharing this interrupt + */ +}; - /* whether irq should be automatically unmasked */ - int unmask; +/** + * \brief interrupt client descriptor + */ +struct irq_desc { + int irq; /**< virtual IRQ number */ + void (*handler)(void *arg); /**< interrupt handler function */ + void *handler_arg; /**< interrupt handler argument */ + int unmask; /**< whether irq should be + * automatically unmasked + */ + uint32_t cpu_mask; /**< a mask of CPUs on which this + * interrupt is enabled + */ + struct list_item irq_list; /**< to link to other irq_desc */ +}; - /* to identify interrupt with the same IRQ */ - int id; - spinlock_t lock; - uint32_t enabled_count; +/** + * \brief cascading IRQ controller operations. + */ +struct irq_cascade_ops { + void (*mask)(struct irq_desc *desc, uint32_t irq, + unsigned int cpu); /**< mask */ + void (*unmask)(struct irq_desc *desc, uint32_t irq, + unsigned int cpu); /**< unmask */ +}; - /* to link to other irq_desc */ - struct list_item irq_list; +/** + * \brief cascading interrupt controller descriptor. + */ +struct irq_cascade_desc { + const char *name; /**< name of the + * controller + */ + int irq_base; /**< first virtual IRQ + * number, assigned to + * this controller + */ + const struct irq_cascade_ops *ops; /**< cascading interrupt + * controller driver + * operations + */ + struct irq_desc desc; /**< the interrupt, that + * this controller is + * generating + */ + struct irq_cascade_desc *next; /**< link to the global + * list of interrupt + * controllers + */ + bool global_mask; /**< the controller + * cannot mask input + * interrupts per core + */ + spinlock_t lock; /**< protect child + * lists, enable and + * child counters + */ + int enable_count[PLATFORM_CORE_COUNT]; /**< enabled child + * interrupt counter + */ + unsigned int num_children[PLATFORM_CORE_COUNT]; /**< number of children + */ + struct irq_child child[PLATFORM_IRQ_CHILDREN]; /**< array of child + * lists - one per + * multiplexed IRQ + */ +}; - uint32_t num_children; - struct list_item child[PLATFORM_IRQ_CHILDREN]; +/* A descriptor for cascading interrupt controller template */ +struct irq_cascade_tmpl { + const char *name; + const struct irq_cascade_ops *ops; + int irq; + void (*handler)(void *arg); + bool global_mask; }; 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); +void interrupt_unregister(uint32_t irq, const void *arg); +uint32_t interrupt_enable(uint32_t irq, void *arg); +uint32_t interrupt_disable(uint32_t irq, void *arg); void platform_interrupt_init(void); -struct irq_desc *platform_irq_get_parent(uint32_t irq); -void platform_interrupt_set(int irq); +void platform_interrupt_set(uint32_t irq); void platform_interrupt_clear(uint32_t irq, uint32_t mask); uint32_t platform_interrupt_get_enabled(void); -void platform_interrupt_mask(uint32_t irq, uint32_t mask); -void platform_interrupt_unmask(uint32_t irq, uint32_t mask); +void interrupt_mask(uint32_t irq, unsigned int cpu); +void interrupt_unmask(uint32_t irq, unsigned int cpu); + +/* + * On platforms, supporting cascading interrupts cascaded interrupt numbers + * are greater than or equal to PLATFORM_IRQ_CHILDREN + */ +#define interrupt_is_dsp_direct(irq) (!PLATFORM_IRQ_CHILDREN || \ + irq < PLATFORM_IRQ_CHILDREN) + +void interrupt_init(void); +int interrupt_cascade_register(const struct irq_cascade_tmpl *tmpl); +struct irq_cascade_desc *interrupt_get_parent(uint32_t irq); +int interrupt_get_irq(unsigned int irq, const char *cascade); static inline void interrupt_set(int irq) { - arch_interrupt_set(SOF_IRQ_NUMBER(irq)); + platform_interrupt_set(irq); +} + +static inline void interrupt_clear_mask(int irq, uint32_t mask) +{ + platform_interrupt_clear(irq, mask); } static inline void interrupt_clear(int irq) { - arch_interrupt_clear(SOF_IRQ_NUMBER(irq)); + interrupt_clear_mask(irq, 1); } static inline uint32_t interrupt_global_disable(void) diff --git a/src/include/sof/drivers/spi.h b/src/include/sof/drivers/spi.h index dbf0b52b41cb..1af887100a98 100644 --- a/src/include/sof/drivers/spi.h +++ b/src/include/sof/drivers/spi.h @@ -27,7 +27,6 @@ struct spi_plat_fifo_data { struct spi_platform_data { uint32_t base; - uint32_t irq; struct spi_plat_fifo_data fifo[2]; enum spi_type type; }; diff --git a/src/include/sof/drivers/timer.h b/src/include/sof/drivers/timer.h index 6194652eb28e..a30a399821f1 100644 --- a/src/include/sof/drivers/timer.h +++ b/src/include/sof/drivers/timer.h @@ -24,6 +24,8 @@ struct timesource_data { uint64_t (*timer_get)(struct timer *t); }; +extern struct timesource_data platform_generic_queue[]; + int timer_register(struct timer *timer, void (*handler)(void *arg), void *arg); void timer_unregister(struct timer *timer); diff --git a/src/include/sof/lib/dai.h b/src/include/sof/lib/dai.h index 88abce42ff26..04376a023a7f 100644 --- a/src/include/sof/lib/dai.h +++ b/src/include/sof/lib/dai.h @@ -100,7 +100,8 @@ struct dai_plat_fifo_data { */ struct dai_plat_data { uint32_t base; - uint32_t irq; + int irq; + const char *irq_name; uint32_t flags; struct dai_plat_fifo_data fifo[2]; }; diff --git a/src/include/sof/lib/dma.h b/src/include/sof/lib/dma.h index 8f4b93f0a4c1..bbc7b5372e43 100644 --- a/src/include/sof/lib/dma.h +++ b/src/include/sof/lib/dma.h @@ -19,7 +19,6 @@ #include #include #include -#include #include #include #include @@ -176,7 +175,8 @@ struct dma_plat_data { uint32_t devs; /* bitmask of supported devs */ uint32_t base; uint32_t channels; - uint32_t irq; + int irq; + const char *irq_name; uint32_t chan_size; void *drv_plat_data; }; @@ -223,8 +223,10 @@ void dma_put(struct dma *dma); dma->private #define dma_base(dma) \ dma->plat_data.base -#define dma_irq(dma, cpu) \ - (dma->plat_data.irq + (cpu << SOF_IRQ_CPU_SHIFT)) +#define dma_irq(dma) \ + dma->plat_data.irq +#define dma_irq_name(dma) \ + dma->plat_data.irq_name #define dma_chan_size(dma) \ dma->plat_data.chan_size #define dma_chan_base(dma, chan) \ diff --git a/src/include/sof/schedule/ll_schedule.h b/src/include/sof/schedule/ll_schedule.h index 94979fba9853..0951cbd00ed2 100644 --- a/src/include/sof/schedule/ll_schedule.h +++ b/src/include/sof/schedule/ll_schedule.h @@ -13,7 +13,6 @@ #ifndef __SOF_SCHEDULE_LL_SCHEDULE_H__ #define __SOF_SCHEDULE_LL_SCHEDULE_H__ -#include #include #include #include @@ -38,6 +37,4 @@ struct ll_task_pdata { uint32_t flags; }; -extern struct timesource_data platform_generic_queue[]; - #endif /* __SOF_SCHEDULE_LL_SCHEDULE_H__ */ diff --git a/src/init/init.c b/src/init/init.c index b513ae40902a..81dfb5b6c12c 100644 --- a/src/init/init.c +++ b/src/init/init.c @@ -10,6 +10,7 @@ */ #include +#include #include #include #include @@ -29,6 +30,8 @@ int master_core_init(struct sof *sof) { int err; + interrupt_init(); + /* init architecture */ trace_point(TRACE_BOOT_ARCH); err = arch_init(sof); diff --git a/src/platform/apollolake/include/platform/drivers/interrupt.h b/src/platform/apollolake/include/platform/drivers/interrupt.h index d75e2a69b00d..7472693e3ffb 100644 --- a/src/platform/apollolake/include/platform/drivers/interrupt.h +++ b/src/platform/apollolake/include/platform/drivers/interrupt.h @@ -11,8 +11,6 @@ #ifndef __PLATFORM_DRIVERS_INTERRUPT_H__ #define __PLATFORM_DRIVERS_INTERRUPT_H__ -#include - #define PLATFORM_IRQ_CHILDREN 32 /* IRQ numbers - wrt Tensilica DSP */ @@ -66,52 +64,31 @@ #define IRQ_BIT_LVL5_SSP(x) (0 + x) /* Level 2 Peripheral IRQ mappings */ -#define IRQ_EXT_HP_GPDMA_LVL2(xcpu) \ - SOF_IRQ(IRQ_BIT_LVL2_HP_GP_DMA0(0), 2, xcpu, IRQ_NUM_EXT_LEVEL2) -#define IRQ_EXT_IDC_LVL2(xcpu) \ - SOF_IRQ(IRQ_BIT_LVL2_IDC, 2, xcpu, IRQ_NUM_EXT_LEVEL2) -#define IRQ_EXT_IPC_LVL2(xcpu) \ - SOF_IRQ(IRQ_BIT_LVL2_HOST_IPC, 2, xcpu, IRQ_NUM_EXT_LEVEL2) -#define IRQ_EXT_TSTAMP1_LVL2(xcpu) \ - SOF_IRQ(IRQ_BIT_LVL2_WALL_CLK1, 2, xcpu, IRQ_NUM_EXT_LEVEL2) -#define IRQ_EXT_TSTAMP0_LVL2(xcpu) \ - SOF_IRQ(IRQ_BIT_LVL2_WALL_CLK0, 2, xcpu, IRQ_NUM_EXT_LEVEL2) -#define IRQ_EXT_MERR_LVL2(xcpu) \ - SOF_IRQ(IRQ_BIT_LVL2_L2_MEMERR, 2, xcpu, IRQ_NUM_EXT_LEVEL2) -#define IRQ_EXT_L2CACHE_LVL2(xcpu) \ - SOF_IRQ(IRQ_BIT_LVL2_L2_CACHE, 2, xcpu, IRQ_NUM_EXT_LEVEL2) -#define IRQ_EXT_SHA256_LVL2(xcpu) \ - SOF_IRQ(IRQ_BIT_LVL2_SHA256, 2, xcpu, IRQ_NUM_EXT_LEVEL2) +#define IRQ_EXT_HP_GPDMA_LVL2 IRQ_BIT_LVL2_HP_GP_DMA0(0) +#define IRQ_EXT_IDC_LVL2 IRQ_BIT_LVL2_IDC +#define IRQ_EXT_IPC_LVL2 IRQ_BIT_LVL2_HOST_IPC +#define IRQ_EXT_TSTAMP1_LVL2 IRQ_BIT_LVL2_WALL_CLK1 +#define IRQ_EXT_TSTAMP0_LVL2 IRQ_BIT_LVL2_WALL_CLK0 +#define IRQ_EXT_MERR_LVL2 IRQ_BIT_LVL2_L2_MEMERR +#define IRQ_EXT_L2CACHE_LVL2 IRQ_BIT_LVL2_L2_CACHE +#define IRQ_EXT_SHA256_LVL2 IRQ_BIT_LVL2_SHA256 /* Level 3 Peripheral IRQ mappings */ -#define IRQ_EXT_CODE_DMA_LVL3(xcpu) \ - SOF_IRQ(IRQ_BIT_LVL3_CODE_LOADER, 3, xcpu, IRQ_NUM_EXT_LEVEL3) -#define IRQ_EXT_HOST_DMA_IN_LVL3(xcpu, channel) \ - SOF_IRQ(IRQ_BIT_LVL3_HOST_STREAM_IN(channel), 3, xcpu, \ - IRQ_NUM_EXT_LEVEL3) -#define IRQ_EXT_HOST_DMA_OUT_LVL3(xcpu, channel) \ - SOF_IRQ(IRQ_BIT_LVL3_HOST_STREAM_OUT(channel), 3, xcpu, \ - IRQ_NUM_EXT_LEVEL3) +#define IRQ_EXT_CODE_DMA_LVL3 IRQ_BIT_LVL3_CODE_LOADER +#define IRQ_EXT_HOST_DMA_IN_LVL3(channel) IRQ_BIT_LVL3_HOST_STREAM_IN(channel) +#define IRQ_EXT_HOST_DMA_OUT_LVL3(channel) IRQ_BIT_LVL3_HOST_STREAM_OUT(channel) /* Level 4 Peripheral IRQ mappings */ -#define IRQ_EXT_LINK_DMA_IN_LVL4(xcpu, channel) \ - SOF_IRQ(IRQ_BIT_LVL4_LINK_STREAM_IN(channel), 4, xcpu, \ - IRQ_NUM_EXT_LEVEL4) -#define IRQ_EXT_LINK_DMA_OUT_LVL4(xcpu, channel) \ - SOF_IRQ(IRQ_BIT_LVL4_LINK_STREAM_OUT(channel), 4, xcpu, \ - IRQ_NUM_EXT_LEVEL4) +#define IRQ_EXT_LINK_DMA_IN_LVL4(channel) IRQ_BIT_LVL4_LINK_STREAM_IN(channel) +#define IRQ_EXT_LINK_DMA_OUT_LVL4(channel) IRQ_BIT_LVL4_LINK_STREAM_OUT(channel) /* Level 5 Peripheral IRQ mappings */ -#define IRQ_EXT_LP_GPDMA0_LVL5(xcpu, channel) \ - SOF_IRQ(IRQ_BIT_LVL5_LP_GP_DMA0(channel), 5, xcpu, IRQ_NUM_EXT_LEVEL5) -#define IRQ_EXT_LP_GPDMA1_LVL5(xcpu, channel) \ - SOF_IRQ(IRQ_BIT_LVL5_LP_GP_DMA1(channel), 5, xcpu, IRQ_NUM_EXT_LEVEL5) +#define IRQ_EXT_LP_GPDMA0_LVL5(channel) IRQ_BIT_LVL5_LP_GP_DMA0(channel) +#define IRQ_EXT_LP_GPDMA1_LVL5(channel) IRQ_BIT_LVL5_LP_GP_DMA1(channel) -#define IRQ_EXT_SSPx_LVL5(x, xcpu) \ - SOF_IRQ(IRQ_BIT_LVL5_SSP(x), 5, xcpu, IRQ_NUM_EXT_LEVEL5) +#define IRQ_EXT_SSPx_LVL5(x) IRQ_BIT_LVL5_SSP(x) -#define IRQ_EXT_DMIC_LVL5(x, xcpu) \ - SOF_IRQ(IRQ_BIT_LVL5_DMIC(x), 5, xcpu, IRQ_NUM_EXT_LEVEL5) +#define IRQ_EXT_DMIC_LVL5(x) IRQ_BIT_LVL5_DMIC(x) /* IRQ Masks */ diff --git a/src/platform/apollolake/include/platform/drivers/timer.h b/src/platform/apollolake/include/platform/drivers/timer.h index ea6a0b0f77b2..09711cc99916 100644 --- a/src/platform/apollolake/include/platform/drivers/timer.h +++ b/src/platform/apollolake/include/platform/drivers/timer.h @@ -19,8 +19,8 @@ #define TIMER0 IRQ_NUM_TIMER1 #define TIMER1 IRQ_NUM_TIMER2 #define TIMER2 IRQ_NUM_TIMER3 -#define TIMER3 IRQ_EXT_TSTAMP0_LVL2(0) -#define TIMER4 IRQ_EXT_TSTAMP1_LVL2(0) +#define TIMER3 IRQ_EXT_TSTAMP0_LVL2 +#define TIMER4 IRQ_EXT_TSTAMP1_LVL2 #endif /* __PLATFORM_DRIVERS_TIMER_H__ */ diff --git a/src/platform/apollolake/include/platform/lib/dma.h b/src/platform/apollolake/include/platform/lib/dma.h index 08c833ea47fd..3c9109b3d8cd 100644 --- a/src/platform/apollolake/include/platform/lib/dma.h +++ b/src/platform/apollolake/include/platform/lib/dma.h @@ -11,8 +11,6 @@ #ifndef __PLATFORM_LIB_DMA_H__ #define __PLATFORM_LIB_DMA_H__ -#include - /* available DMACs */ #define DMA_GP_LP_DMAC0 0 #define DMA_GP_LP_DMAC1 1 @@ -49,8 +47,7 @@ #define DMA_HANDSHAKE_SSP5_TX 12 #define DMA_HANDSHAKE_SSP5_RX 13 -#define dma_chan_irq(dma, cpu, chan) \ - (dma_irq(dma, cpu) + (channel << SOF_IRQ_BIT_SHIFT)) +#define dma_chan_irq(dma, chan) (dma_irq(dma) + channel) int dmac_init(void); diff --git a/src/platform/apollolake/include/platform/platform.h b/src/platform/apollolake/include/platform/platform.h index 2ab8f20193d3..0ec725e285fd 100644 --- a/src/platform/apollolake/include/platform/platform.h +++ b/src/platform/apollolake/include/platform/platform.h @@ -21,6 +21,7 @@ #include #include #include +#include #include struct timer; @@ -39,17 +40,23 @@ struct timer; #define PLATFORM_PAGE_TABLE_SIZE 256 /* IDC Interrupt */ -#define PLATFORM_IDC_INTERRUPT(x) IRQ_EXT_IDC_LVL2(x) +#define PLATFORM_IDC_INTERRUPT IRQ_EXT_IDC_LVL2 +#define PLATFORM_IDC_INTERRUPT_NAME irq_name_level2 /* IPC Interrupt */ -#define PLATFORM_IPC_INTERRUPT IRQ_EXT_IPC_LVL2(0) +#define PLATFORM_IPC_INTERRUPT IRQ_BIT_LVL2_HOST_IPC +#define PLATFORM_IPC_INTERRUPT_NAME irq_name_level2 /* pipeline IRQ */ -#define PLATFORM_SCHEDULE_IRQ IRQ_NUM_SOFTWARE4 +#define PLATFORM_SCHEDULE_IRQ IRQ_NUM_SOFTWARE4 +#define PLATFORM_SCHEDULE_IRQ_NAME NULL #define PLATFORM_IRQ_TASK_HIGH IRQ_NUM_SOFTWARE3 +#define PLATFORM_IRQ_TASK_HIGH_NAME NULL #define PLATFORM_IRQ_TASK_MED IRQ_NUM_SOFTWARE2 +#define PLATFORM_IRQ_TASK_MED_NAME NULL #define PLATFORM_IRQ_TASK_LOW IRQ_NUM_SOFTWARE1 +#define PLATFORM_IRQ_TASK_LOW_NAME NULL #define PLATFORM_SCHEDULE_COST 200 diff --git a/src/platform/baytrail/include/platform/lib/dma.h b/src/platform/baytrail/include/platform/lib/dma.h index ebe16b802c96..b9e8539d5cdd 100644 --- a/src/platform/baytrail/include/platform/lib/dma.h +++ b/src/platform/baytrail/include/platform/lib/dma.h @@ -38,7 +38,7 @@ #define DMA_HANDSHAKE_SSP6_RX 12 #define DMA_HANDSHAKE_SSP6_TX 13 -#define dma_chan_irq(dma, cpu, chan) dma_irq(dma, cpu) +#define dma_chan_irq(dma, chan) dma_irq(dma) int dmac_init(void); diff --git a/src/platform/baytrail/include/platform/platform.h b/src/platform/baytrail/include/platform/platform.h index 65f24cabeb16..d9f8d7f41802 100644 --- a/src/platform/baytrail/include/platform/platform.h +++ b/src/platform/baytrail/include/platform/platform.h @@ -24,6 +24,7 @@ #include #include #include +#include #include struct timer; @@ -44,6 +45,7 @@ struct timer; /* IPC Interrupt */ #define PLATFORM_IPC_INTERRUPT IRQ_NUM_EXT_IA +#define PLATFORM_IPC_INTERRUPT_NAME NULL /* Host page size */ #define HOST_PAGE_SIZE 4096 @@ -51,10 +53,14 @@ struct timer; /* pipeline IRQ */ #define PLATFORM_SCHEDULE_IRQ IRQ_NUM_SOFTWARE5 +#define PLATFORM_SCHEDULE_IRQ_NAME NULL #define PLATFORM_IRQ_TASK_HIGH IRQ_NUM_SOFTWARE4 +#define PLATFORM_IRQ_TASK_HIGH_NAME NULL #define PLATFORM_IRQ_TASK_MED IRQ_NUM_SOFTWARE3 +#define PLATFORM_IRQ_TASK_MED_NAME NULL #define PLATFORM_IRQ_TASK_LOW IRQ_NUM_SOFTWARE2 +#define PLATFORM_IRQ_TASK_LOW_NAME NULL #define PLATFORM_SCHEDULE_COST 200 diff --git a/src/platform/cannonlake/include/platform/drivers/interrupt.h b/src/platform/cannonlake/include/platform/drivers/interrupt.h index 76004e405a0c..262f2b8dd88d 100644 --- a/src/platform/cannonlake/include/platform/drivers/interrupt.h +++ b/src/platform/cannonlake/include/platform/drivers/interrupt.h @@ -12,8 +12,6 @@ #ifndef __PLATFORM_DRIVERS_INTERRUPT_H__ #define __PLATFORM_DRIVERS_INTERRUPT_H__ -#include - #define PLATFORM_IRQ_CHILDREN 32 /* IRQ numbers - wrt Tensilica DSP */ @@ -67,52 +65,31 @@ #define IRQ_BIT_LVL5_SSP(x) (0 + x) /* Priority 2 Peripheral IRQ mappings */ -#define IRQ_EXT_HP_GPDMA_LVL2(xcpu) \ - SOF_IRQ(IRQ_BIT_LVL2_HP_GP_DMA0(0), 2, xcpu, IRQ_NUM_EXT_LEVEL2) -#define IRQ_EXT_IDC_LVL2(xcpu) \ - SOF_IRQ(IRQ_BIT_LVL2_IDC, 2, xcpu, IRQ_NUM_EXT_LEVEL2) -#define IRQ_EXT_IPC_LVL2(xcpu) \ - SOF_IRQ(IRQ_BIT_LVL2_HOST_IPC, 2, xcpu, IRQ_NUM_EXT_LEVEL2) -#define IRQ_EXT_TSTAMP1_LVL2(xcpu) \ - SOF_IRQ(IRQ_BIT_LVL2_WALL_CLK1, 2, xcpu, IRQ_NUM_EXT_LEVEL2) -#define IRQ_EXT_TSTAMP0_LVL2(xcpu) \ - SOF_IRQ(IRQ_BIT_LVL2_WALL_CLK0, 2, xcpu, IRQ_NUM_EXT_LEVEL2) -#define IRQ_EXT_MERR_LVL2(xcpu) \ - SOF_IRQ(IRQ_BIT_LVL2_L2_MEMERR, 2, xcpu, IRQ_NUM_EXT_LEVEL2) -#define IRQ_EXT_L2CACHE_LVL2(xcpu) \ - SOF_IRQ(IRQ_BIT_LVL2_L2_CACHE, 2, xcpu, IRQ_NUM_EXT_LEVEL2) -#define IRQ_EXT_SHA256_LVL2(xcpu) \ - SOF_IRQ(IRQ_BIT_LVL2_SHA256, 2, xcpu, IRQ_NUM_EXT_LEVEL2) +#define IRQ_EXT_HP_GPDMA_LVL2 IRQ_BIT_LVL2_HP_GP_DMA0(0) +#define IRQ_EXT_IDC_LVL2 IRQ_BIT_LVL2_IDC +#define IRQ_EXT_IPC_LVL2 IRQ_BIT_LVL2_HOST_IPC +#define IRQ_EXT_TSTAMP1_LVL2 IRQ_BIT_LVL2_WALL_CLK1 +#define IRQ_EXT_TSTAMP0_LVL2 IRQ_BIT_LVL2_WALL_CLK0 +#define IRQ_EXT_MERR_LVL2 IRQ_BIT_LVL2_L2_MEMERR +#define IRQ_EXT_L2CACHE_LVL2 IRQ_BIT_LVL2_L2_CACHE +#define IRQ_EXT_SHA256_LVL2 IRQ_BIT_LVL2_SHA256 /* Priority 3 Peripheral IRQ mappings */ -#define IRQ_EXT_CODE_DMA_LVL3(xcpu) \ - SOF_IRQ(IRQ_BIT_LVL3_CODE_LOADER, 3, xcpu, IRQ_NUM_EXT_LEVEL3) -#define IRQ_EXT_HOST_DMA_IN_LVL3(xcpu, channel) \ - SOF_IRQ(IRQ_BIT_LVL3_HOST_STREAM_IN(channel), 3, xcpu, \ - IRQ_NUM_EXT_LEVEL3) -#define IRQ_EXT_HOST_DMA_OUT_LVL3(xcpu, channel) \ - SOF_IRQ(IRQ_BIT_LVL3_HOST_STREAM_OUT(channel), 3, xcpu, \ - IRQ_NUM_EXT_LEVEL3) +#define IRQ_EXT_CODE_DMA_LVL3 IRQ_BIT_LVL3_CODE_LOADER +#define IRQ_EXT_HOST_DMA_IN_LVL3(channel) IRQ_BIT_LVL3_HOST_STREAM_IN(channel) +#define IRQ_EXT_HOST_DMA_OUT_LVL3(channel) IRQ_BIT_LVL3_HOST_STREAM_OUT(channel) /* Priority 4 Peripheral IRQ mappings */ -#define IRQ_EXT_LINK_DMA_IN_LVL4(xcpu, channel) \ - SOF_IRQ(IRQ_BIT_LVL4_LINK_STREAM_IN(channel), 4, xcpu, \ - IRQ_NUM_EXT_LEVEL4) -#define IRQ_EXT_LINK_DMA_OUT_LVL4(xcpu, channel) \ - SOF_IRQ(IRQ_BIT_LVL4_LINK_STREAM_OUT(channel), 4, xcpu, \ - IRQ_NUM_EXT_LEVEL4) +#define IRQ_EXT_LINK_DMA_IN_LVL4(channel) IRQ_BIT_LVL4_LINK_STREAM_IN(channel) +#define IRQ_EXT_LINK_DMA_OUT_LVL4(channel) IRQ_BIT_LVL4_LINK_STREAM_OUT(channel) /* Priority 5 Peripheral IRQ mappings */ -#define IRQ_EXT_LP_GPDMA0_LVL5(xcpu, channel) \ - SOF_ID_IRQ(0, IRQ_BIT_LVL5_LP_GP_DMA0, 5, xcpu, IRQ_NUM_EXT_LEVEL5) -#define IRQ_EXT_LP_GPDMA1_LVL5(xcpu, channel) \ - SOF_ID_IRQ(1, IRQ_BIT_LVL5_LP_GP_DMA0, 5, xcpu, IRQ_NUM_EXT_LEVEL5) +#define IRQ_EXT_LP_GPDMA0_LVL5(channel) IRQ_BIT_LVL5_LP_GP_DMA0 +#define IRQ_EXT_LP_GPDMA1_LVL5(channel) IRQ_BIT_LVL5_LP_GP_DMA0 -#define IRQ_EXT_SSPx_LVL5(x, xcpu) \ - SOF_IRQ(IRQ_BIT_LVL5_SSP(x), 5, xcpu, IRQ_NUM_EXT_LEVEL5) +#define IRQ_EXT_SSPx_LVL5(x) IRQ_BIT_LVL5_SSP(x) -#define IRQ_EXT_DMIC_LVL5(x, xcpu) \ - SOF_IRQ(IRQ_BIT_LVL5_DMIC(x), 5, xcpu, IRQ_NUM_EXT_LEVEL5) +#define IRQ_EXT_DMIC_LVL5(x) IRQ_BIT_LVL5_DMIC(x) /* IRQ Masks */ diff --git a/src/platform/cannonlake/include/platform/drivers/timer.h b/src/platform/cannonlake/include/platform/drivers/timer.h index 92a49cebc7ef..cf4ea48174af 100644 --- a/src/platform/cannonlake/include/platform/drivers/timer.h +++ b/src/platform/cannonlake/include/platform/drivers/timer.h @@ -20,8 +20,8 @@ #define TIMER0 IRQ_NUM_TIMER1 #define TIMER1 IRQ_NUM_TIMER2 #define TIMER2 IRQ_NUM_TIMER3 -#define TIMER3 IRQ_EXT_TSTAMP0_LVL2(0) -#define TIMER4 IRQ_EXT_TSTAMP1_LVL2(0) +#define TIMER3 IRQ_EXT_TSTAMP0_LVL2 +#define TIMER4 IRQ_EXT_TSTAMP1_LVL2 #endif /* __PLATFORM_DRIVERS_TIMER_H__ */ diff --git a/src/platform/cannonlake/include/platform/lib/dma.h b/src/platform/cannonlake/include/platform/lib/dma.h index 4e88bdf95bcc..3768296b9b4b 100644 --- a/src/platform/cannonlake/include/platform/lib/dma.h +++ b/src/platform/cannonlake/include/platform/lib/dma.h @@ -48,7 +48,7 @@ #define DMA_HANDSHAKE_SSP5_TX 12 #define DMA_HANDSHAKE_SSP5_RX 13 -#define dma_chan_irq(dma, cpu, chan) dma_irq(dma, cpu) +#define dma_chan_irq(dma, chan) dma_irq(dma) int dmac_init(void); diff --git a/src/platform/cannonlake/include/platform/platform.h b/src/platform/cannonlake/include/platform/platform.h index 5b593f1bf90e..85498857f5f5 100644 --- a/src/platform/cannonlake/include/platform/platform.h +++ b/src/platform/cannonlake/include/platform/platform.h @@ -22,6 +22,7 @@ #include #include #include +#include #include struct timer; @@ -49,17 +50,23 @@ struct timer; #define PLATFORM_PAGE_TABLE_SIZE 256 /* IDC Interrupt */ -#define PLATFORM_IDC_INTERRUPT(x) IRQ_EXT_IDC_LVL2(x) +#define PLATFORM_IDC_INTERRUPT IRQ_EXT_IDC_LVL2 +#define PLATFORM_IDC_INTERRUPT_NAME irq_name_level2 /* IPC Interrupt */ -#define PLATFORM_IPC_INTERRUPT IRQ_EXT_IPC_LVL2(0) +#define PLATFORM_IPC_INTERRUPT IRQ_EXT_IPC_LVL2 +#define PLATFORM_IPC_INTERRUPT_NAME irq_name_level2 /* pipeline IRQ */ #define PLATFORM_SCHEDULE_IRQ IRQ_NUM_SOFTWARE4 +#define PLATFORM_SCHEDULE_IRQ_NAME NULL #define PLATFORM_IRQ_TASK_HIGH IRQ_NUM_SOFTWARE3 +#define PLATFORM_IRQ_TASK_HIGH_NAME NULL #define PLATFORM_IRQ_TASK_MED IRQ_NUM_SOFTWARE2 +#define PLATFORM_IRQ_TASK_MED_NAME NULL #define PLATFORM_IRQ_TASK_LOW IRQ_NUM_SOFTWARE1 +#define PLATFORM_IRQ_TASK_LOW_NAME NULL #define PLATFORM_SCHEDULE_COST 200 diff --git a/src/platform/haswell/include/platform/lib/dma.h b/src/platform/haswell/include/platform/lib/dma.h index 87fad497a44e..526eb9c9bb15 100644 --- a/src/platform/haswell/include/platform/lib/dma.h +++ b/src/platform/haswell/include/platform/lib/dma.h @@ -32,7 +32,7 @@ #define DMA_HANDSHAKE_OBFF_10 14 #define DMA_HANDSHAKE_OBFF_11 15 -#define dma_chan_irq(dma, cpu, chan) dma_irq(dma, cpu) +#define dma_chan_irq(dma, chan) dma_irq(dma) int dmac_init(void); diff --git a/src/platform/haswell/include/platform/platform.h b/src/platform/haswell/include/platform/platform.h index cb1fe58ba860..24bd4bb75a8c 100644 --- a/src/platform/haswell/include/platform/platform.h +++ b/src/platform/haswell/include/platform/platform.h @@ -20,6 +20,7 @@ #include #include #include +#include #include struct timer; @@ -40,6 +41,7 @@ struct timer; /* IPC Interrupt */ #define PLATFORM_IPC_INTERRUPT IRQ_NUM_EXT_IA +#define PLATFORM_IPC_INTERRUPT_NAME NULL /* Host page size */ #define HOST_PAGE_SIZE 4096 @@ -47,10 +49,14 @@ struct timer; /* pipeline IRQ */ #define PLATFORM_SCHEDULE_IRQ IRQ_NUM_SOFTWARE2 +#define PLATFORM_SCHEDULE_IRQ_NAME NULL #define PLATFORM_IRQ_TASK_HIGH IRQ_NUM_SOFTWARE2 +#define PLATFORM_IRQ_TASK_HIGH_NAME NULL #define PLATFORM_IRQ_TASK_MED IRQ_NUM_SOFTWARE1 +#define PLATFORM_IRQ_TASK_MED_NAME NULL #define PLATFORM_IRQ_TASK_LOW IRQ_NUM_SOFTWARE1 +#define PLATFORM_IRQ_TASK_LOW_NAME NULL #define PLATFORM_SCHEDULE_COST 200 diff --git a/src/platform/icelake/include/platform/drivers/interrupt.h b/src/platform/icelake/include/platform/drivers/interrupt.h index 76004e405a0c..262f2b8dd88d 100644 --- a/src/platform/icelake/include/platform/drivers/interrupt.h +++ b/src/platform/icelake/include/platform/drivers/interrupt.h @@ -12,8 +12,6 @@ #ifndef __PLATFORM_DRIVERS_INTERRUPT_H__ #define __PLATFORM_DRIVERS_INTERRUPT_H__ -#include - #define PLATFORM_IRQ_CHILDREN 32 /* IRQ numbers - wrt Tensilica DSP */ @@ -67,52 +65,31 @@ #define IRQ_BIT_LVL5_SSP(x) (0 + x) /* Priority 2 Peripheral IRQ mappings */ -#define IRQ_EXT_HP_GPDMA_LVL2(xcpu) \ - SOF_IRQ(IRQ_BIT_LVL2_HP_GP_DMA0(0), 2, xcpu, IRQ_NUM_EXT_LEVEL2) -#define IRQ_EXT_IDC_LVL2(xcpu) \ - SOF_IRQ(IRQ_BIT_LVL2_IDC, 2, xcpu, IRQ_NUM_EXT_LEVEL2) -#define IRQ_EXT_IPC_LVL2(xcpu) \ - SOF_IRQ(IRQ_BIT_LVL2_HOST_IPC, 2, xcpu, IRQ_NUM_EXT_LEVEL2) -#define IRQ_EXT_TSTAMP1_LVL2(xcpu) \ - SOF_IRQ(IRQ_BIT_LVL2_WALL_CLK1, 2, xcpu, IRQ_NUM_EXT_LEVEL2) -#define IRQ_EXT_TSTAMP0_LVL2(xcpu) \ - SOF_IRQ(IRQ_BIT_LVL2_WALL_CLK0, 2, xcpu, IRQ_NUM_EXT_LEVEL2) -#define IRQ_EXT_MERR_LVL2(xcpu) \ - SOF_IRQ(IRQ_BIT_LVL2_L2_MEMERR, 2, xcpu, IRQ_NUM_EXT_LEVEL2) -#define IRQ_EXT_L2CACHE_LVL2(xcpu) \ - SOF_IRQ(IRQ_BIT_LVL2_L2_CACHE, 2, xcpu, IRQ_NUM_EXT_LEVEL2) -#define IRQ_EXT_SHA256_LVL2(xcpu) \ - SOF_IRQ(IRQ_BIT_LVL2_SHA256, 2, xcpu, IRQ_NUM_EXT_LEVEL2) +#define IRQ_EXT_HP_GPDMA_LVL2 IRQ_BIT_LVL2_HP_GP_DMA0(0) +#define IRQ_EXT_IDC_LVL2 IRQ_BIT_LVL2_IDC +#define IRQ_EXT_IPC_LVL2 IRQ_BIT_LVL2_HOST_IPC +#define IRQ_EXT_TSTAMP1_LVL2 IRQ_BIT_LVL2_WALL_CLK1 +#define IRQ_EXT_TSTAMP0_LVL2 IRQ_BIT_LVL2_WALL_CLK0 +#define IRQ_EXT_MERR_LVL2 IRQ_BIT_LVL2_L2_MEMERR +#define IRQ_EXT_L2CACHE_LVL2 IRQ_BIT_LVL2_L2_CACHE +#define IRQ_EXT_SHA256_LVL2 IRQ_BIT_LVL2_SHA256 /* Priority 3 Peripheral IRQ mappings */ -#define IRQ_EXT_CODE_DMA_LVL3(xcpu) \ - SOF_IRQ(IRQ_BIT_LVL3_CODE_LOADER, 3, xcpu, IRQ_NUM_EXT_LEVEL3) -#define IRQ_EXT_HOST_DMA_IN_LVL3(xcpu, channel) \ - SOF_IRQ(IRQ_BIT_LVL3_HOST_STREAM_IN(channel), 3, xcpu, \ - IRQ_NUM_EXT_LEVEL3) -#define IRQ_EXT_HOST_DMA_OUT_LVL3(xcpu, channel) \ - SOF_IRQ(IRQ_BIT_LVL3_HOST_STREAM_OUT(channel), 3, xcpu, \ - IRQ_NUM_EXT_LEVEL3) +#define IRQ_EXT_CODE_DMA_LVL3 IRQ_BIT_LVL3_CODE_LOADER +#define IRQ_EXT_HOST_DMA_IN_LVL3(channel) IRQ_BIT_LVL3_HOST_STREAM_IN(channel) +#define IRQ_EXT_HOST_DMA_OUT_LVL3(channel) IRQ_BIT_LVL3_HOST_STREAM_OUT(channel) /* Priority 4 Peripheral IRQ mappings */ -#define IRQ_EXT_LINK_DMA_IN_LVL4(xcpu, channel) \ - SOF_IRQ(IRQ_BIT_LVL4_LINK_STREAM_IN(channel), 4, xcpu, \ - IRQ_NUM_EXT_LEVEL4) -#define IRQ_EXT_LINK_DMA_OUT_LVL4(xcpu, channel) \ - SOF_IRQ(IRQ_BIT_LVL4_LINK_STREAM_OUT(channel), 4, xcpu, \ - IRQ_NUM_EXT_LEVEL4) +#define IRQ_EXT_LINK_DMA_IN_LVL4(channel) IRQ_BIT_LVL4_LINK_STREAM_IN(channel) +#define IRQ_EXT_LINK_DMA_OUT_LVL4(channel) IRQ_BIT_LVL4_LINK_STREAM_OUT(channel) /* Priority 5 Peripheral IRQ mappings */ -#define IRQ_EXT_LP_GPDMA0_LVL5(xcpu, channel) \ - SOF_ID_IRQ(0, IRQ_BIT_LVL5_LP_GP_DMA0, 5, xcpu, IRQ_NUM_EXT_LEVEL5) -#define IRQ_EXT_LP_GPDMA1_LVL5(xcpu, channel) \ - SOF_ID_IRQ(1, IRQ_BIT_LVL5_LP_GP_DMA0, 5, xcpu, IRQ_NUM_EXT_LEVEL5) +#define IRQ_EXT_LP_GPDMA0_LVL5(channel) IRQ_BIT_LVL5_LP_GP_DMA0 +#define IRQ_EXT_LP_GPDMA1_LVL5(channel) IRQ_BIT_LVL5_LP_GP_DMA0 -#define IRQ_EXT_SSPx_LVL5(x, xcpu) \ - SOF_IRQ(IRQ_BIT_LVL5_SSP(x), 5, xcpu, IRQ_NUM_EXT_LEVEL5) +#define IRQ_EXT_SSPx_LVL5(x) IRQ_BIT_LVL5_SSP(x) -#define IRQ_EXT_DMIC_LVL5(x, xcpu) \ - SOF_IRQ(IRQ_BIT_LVL5_DMIC(x), 5, xcpu, IRQ_NUM_EXT_LEVEL5) +#define IRQ_EXT_DMIC_LVL5(x) IRQ_BIT_LVL5_DMIC(x) /* IRQ Masks */ diff --git a/src/platform/icelake/include/platform/drivers/timer.h b/src/platform/icelake/include/platform/drivers/timer.h index 92a49cebc7ef..cf4ea48174af 100644 --- a/src/platform/icelake/include/platform/drivers/timer.h +++ b/src/platform/icelake/include/platform/drivers/timer.h @@ -20,8 +20,8 @@ #define TIMER0 IRQ_NUM_TIMER1 #define TIMER1 IRQ_NUM_TIMER2 #define TIMER2 IRQ_NUM_TIMER3 -#define TIMER3 IRQ_EXT_TSTAMP0_LVL2(0) -#define TIMER4 IRQ_EXT_TSTAMP1_LVL2(0) +#define TIMER3 IRQ_EXT_TSTAMP0_LVL2 +#define TIMER4 IRQ_EXT_TSTAMP1_LVL2 #endif /* __PLATFORM_DRIVERS_TIMER_H__ */ diff --git a/src/platform/icelake/include/platform/lib/dma.h b/src/platform/icelake/include/platform/lib/dma.h index 4e88bdf95bcc..3768296b9b4b 100644 --- a/src/platform/icelake/include/platform/lib/dma.h +++ b/src/platform/icelake/include/platform/lib/dma.h @@ -48,7 +48,7 @@ #define DMA_HANDSHAKE_SSP5_TX 12 #define DMA_HANDSHAKE_SSP5_RX 13 -#define dma_chan_irq(dma, cpu, chan) dma_irq(dma, cpu) +#define dma_chan_irq(dma, chan) dma_irq(dma) int dmac_init(void); diff --git a/src/platform/icelake/include/platform/platform.h b/src/platform/icelake/include/platform/platform.h index 0de5514e2ff7..48dbe9a846d4 100644 --- a/src/platform/icelake/include/platform/platform.h +++ b/src/platform/icelake/include/platform/platform.h @@ -22,6 +22,7 @@ #include #include #include +#include #include struct timer; @@ -49,17 +50,23 @@ struct timer; #define PLATFORM_PAGE_TABLE_SIZE 256 /* IDC Interrupt */ -#define PLATFORM_IDC_INTERRUPT(x) IRQ_EXT_IDC_LVL2(x) +#define PLATFORM_IDC_INTERRUPT IRQ_EXT_IDC_LVL2 +#define PLATFORM_IDC_INTERRUPT_NAME irq_name_level2 /* IPC Interrupt */ -#define PLATFORM_IPC_INTERRUPT IRQ_EXT_IPC_LVL2(0) +#define PLATFORM_IPC_INTERRUPT IRQ_EXT_IPC_LVL2 +#define PLATFORM_IPC_INTERRUPT_NAME irq_name_level2 /* pipeline IRQ */ #define PLATFORM_SCHEDULE_IRQ IRQ_NUM_SOFTWARE4 +#define PLATFORM_SCHEDULE_IRQ_NAME NULL #define PLATFORM_IRQ_TASK_HIGH IRQ_NUM_SOFTWARE3 +#define PLATFORM_IRQ_TASK_HIGH_NAME NULL #define PLATFORM_IRQ_TASK_MED IRQ_NUM_SOFTWARE2 +#define PLATFORM_IRQ_TASK_MED_NAME NULL #define PLATFORM_IRQ_TASK_LOW IRQ_NUM_SOFTWARE1 +#define PLATFORM_IRQ_TASK_LOW_NAME NULL #define PLATFORM_SCHEDULE_COST 200 diff --git a/src/platform/imx8/include/platform/platform.h b/src/platform/imx8/include/platform/platform.h index d73b27255051..8470d99a2b9a 100644 --- a/src/platform/imx8/include/platform/platform.h +++ b/src/platform/imx8/include/platform/platform.h @@ -15,6 +15,7 @@ #include #include #include +#include #include struct timer; @@ -25,18 +26,23 @@ struct timer; #define PLATFORM_WORKQ_DEFAULT_TIMEOUT 1000 /* IPC Interrupt */ -#define PLATFORM_IPC_INTERRUPT IRQ_NUM_MU +#define PLATFORM_IPC_INTERRUPT IRQ_NUM_MU +#define PLATFORM_IPC_INTERRUPT_NAME NULL /* Host page size */ #define HOST_PAGE_SIZE 4096 #define PLATFORM_PAGE_TABLE_SIZE 256 /* pipeline IRQ */ -#define PLATFORM_SCHEDULE_IRQ IRQ_NUM_SOFTWARE0 - -#define PLATFORM_IRQ_TASK_HIGH IRQ_NUM_SOFTWARE1 -#define PLATFORM_IRQ_TASK_MED IRQ_NUM_SOFTWARE1 -#define PLATFORM_IRQ_TASK_LOW IRQ_NUM_SOFTWARE1 +#define PLATFORM_SCHEDULE_IRQ IRQ_NUM_SOFTWARE0 +#define PLATFORM_SCHEDULE_IRQ_NAME NULL + +#define PLATFORM_IRQ_TASK_HIGH IRQ_NUM_SOFTWARE1 +#define PLATFORM_IRQ_TASK_HIGH_NAME NULL +#define PLATFORM_IRQ_TASK_MED IRQ_NUM_SOFTWARE1 +#define PLATFORM_IRQ_TASK_MED_NAME NULL +#define PLATFORM_IRQ_TASK_LOW IRQ_NUM_SOFTWARE1 +#define PLATFORM_IRQ_TASK_LOW_NAME NULL #define PLATFORM_SCHEDULE_COST 200 diff --git a/src/platform/intel/cavs/lib/dai.c b/src/platform/intel/cavs/lib/dai.c index 82729b4ae515..de1e56722927 100644 --- a/src/platform/intel/cavs/lib/dai.c +++ b/src/platform/intel/cavs/lib/dai.c @@ -42,7 +42,8 @@ static struct dai dmic[2] = { .index = 0, .plat_data = { .base = DMIC_BASE, - .irq = IRQ_EXT_DMIC_LVL5(0, 0), + .irq = IRQ_EXT_DMIC_LVL5(0), + .irq_name = irq_name_level5, .fifo[SOF_IPC_STREAM_PLAYBACK] = { .offset = 0, /* No playback */ .handshake = 0, @@ -59,7 +60,8 @@ static struct dai dmic[2] = { .index = 1, .plat_data = { .base = DMIC_BASE, - .irq = IRQ_EXT_DMIC_LVL5(1, 0), + .irq = IRQ_EXT_DMIC_LVL5(1), + .irq_name = irq_name_level5, .fifo[SOF_IPC_STREAM_PLAYBACK] = { .offset = 0, /* No playback */ .handshake = 0, @@ -108,7 +110,8 @@ int dai_init(void) ssp[i].index = i; ssp[i].drv = &ssp_driver; ssp[i].plat_data.base = SSP_BASE(i); - ssp[i].plat_data.irq = IRQ_EXT_SSPx_LVL5(i, 0); + ssp[i].plat_data.irq = IRQ_EXT_SSPx_LVL5(i); + ssp[i].plat_data.irq_name = irq_name_level5; ssp[i].plat_data.fifo[SOF_IPC_STREAM_PLAYBACK].offset = SSP_BASE(i) + SSDR; ssp[i].plat_data.fifo[SOF_IPC_STREAM_PLAYBACK].handshake = diff --git a/src/platform/intel/cavs/lib/dma.c b/src/platform/intel/cavs/lib/dma.c index a744d4fb8a0f..49247e77cecf 100644 --- a/src/platform/intel/cavs/lib/dma.c +++ b/src/platform/intel/cavs/lib/dma.c @@ -107,7 +107,7 @@ static struct dw_drv_plat_data dmac1 = { }; #if CONFIG_SUECREEK -struct dma dma[CAVS_PLATFORM_NUM_DMACS] = { +static struct dma dma[CAVS_PLATFORM_NUM_DMACS] = { { /* LP GP DMAC 0 */ .plat_data = { .id = DMA_GP_LP_DMAC0, @@ -117,7 +117,8 @@ struct dma dma[CAVS_PLATFORM_NUM_DMACS] = { .devs = DMA_DEV_SSP | DMA_DEV_SSI | DMA_DEV_DMIC, .base = LP_GP_DMA_BASE(0), .channels = 8, - .irq = IRQ_EXT_LP_GPDMA0_LVL5(0, 0), + .irq = IRQ_EXT_LP_GPDMA0_LVL5(0), + .irq_name = irq_name_level5, .drv_plat_data = &dmac0, }, .ops = &dw_dma_ops, @@ -131,7 +132,8 @@ struct dma dma[CAVS_PLATFORM_NUM_DMACS] = { .devs = DMA_DEV_SSP | DMA_DEV_DMIC, .base = LP_GP_DMA_BASE(1), .channels = 8, - .irq = IRQ_EXT_LP_GPDMA1_LVL5(0, 0), + .irq = IRQ_EXT_LP_GPDMA1_LVL5(0), + .irq_name = irq_name_level5, .drv_plat_data = &dmac1, }, .ops = &dw_dma_ops, @@ -145,7 +147,8 @@ struct dma dma[CAVS_PLATFORM_NUM_DMACS] = { .devs = DMA_DEV_SSP | DMA_DEV_DMIC, .base = LP_GP_DMA_BASE(1), .channels = 8, - .irq = IRQ_EXT_LP_GPDMA1_LVL5(0, 0), + .irq = IRQ_EXT_LP_GPDMA1_LVL5(0), + .irq_name = irq_name_level5, .drv_plat_data = &dmac1, }, .ops = &dw_dma_ops, @@ -153,7 +156,7 @@ struct dma dma[CAVS_PLATFORM_NUM_DMACS] = { }; #else -struct dma dma[CAVS_PLATFORM_NUM_DMACS] = { +static struct dma dma[CAVS_PLATFORM_NUM_DMACS] = { { /* Low Power GP DMAC 0 */ .plat_data = { .id = DMA_GP_LP_DMAC0, @@ -164,7 +167,8 @@ struct dma dma[CAVS_PLATFORM_NUM_DMACS] = { DMA_DEV_SOUNDWIRE, .base = LP_GP_DMA_BASE(0), .channels = 8, - .irq = IRQ_EXT_LP_GPDMA0_LVL5(0, 0), + .irq = IRQ_EXT_LP_GPDMA0_LVL5(0), + .irq_name = irq_name_level5, .drv_plat_data = &dmac0, }, .ops = &dw_dma_ops, @@ -179,7 +183,8 @@ struct dma dma[CAVS_PLATFORM_NUM_DMACS] = { DMA_DEV_SOUNDWIRE, .base = LP_GP_DMA_BASE(1), .channels = 8, - .irq = IRQ_EXT_LP_GPDMA1_LVL5(0, 0), + .irq = IRQ_EXT_LP_GPDMA1_LVL5(0), + .irq_name = irq_name_level5, .drv_plat_data = &dmac1, }, .ops = &dw_dma_ops, @@ -192,7 +197,8 @@ struct dma dma[CAVS_PLATFORM_NUM_DMACS] = { .devs = DMA_DEV_HOST, .base = GTW_HOST_IN_STREAM_BASE(0), .channels = 7, - .irq = IRQ_EXT_HOST_DMA_IN_LVL3(0, 0), + .irq = IRQ_EXT_HOST_DMA_IN_LVL3(0), + .irq_name = irq_name_level3, .chan_size = GTW_HOST_IN_STREAM_SIZE, }, .ops = &hda_host_dma_ops, @@ -205,7 +211,8 @@ struct dma dma[CAVS_PLATFORM_NUM_DMACS] = { .devs = DMA_DEV_HOST, .base = GTW_HOST_OUT_STREAM_BASE(0), .channels = DMAC_HOST_OUT_CHANNELS_COUNT, - .irq = IRQ_EXT_HOST_DMA_OUT_LVL3(0, 0), + .irq = IRQ_EXT_HOST_DMA_OUT_LVL3(0), + .irq_name = irq_name_level3, .chan_size = GTW_HOST_OUT_STREAM_SIZE, }, .ops = &hda_host_dma_ops, @@ -218,7 +225,8 @@ struct dma dma[CAVS_PLATFORM_NUM_DMACS] = { .devs = DMA_DEV_HDA, .base = GTW_LINK_IN_STREAM_BASE(0), .channels = DMAC_LINK_IN_CHANNELS_COUNT, - .irq = IRQ_EXT_LINK_DMA_IN_LVL4(0, 0), + .irq = IRQ_EXT_LINK_DMA_IN_LVL4(0), + .irq_name = irq_name_level4, .chan_size = GTW_LINK_IN_STREAM_SIZE, }, .ops = &hda_link_dma_ops, @@ -231,7 +239,8 @@ struct dma dma[CAVS_PLATFORM_NUM_DMACS] = { .devs = DMA_DEV_HDA, .base = GTW_LINK_OUT_STREAM_BASE(0), .channels = DMAC_LINK_OUT_CHANNELS_COUNT, - .irq = IRQ_EXT_LINK_DMA_OUT_LVL4(0, 0), + .irq = IRQ_EXT_LINK_DMA_OUT_LVL4(0), + .irq_name = irq_name_level4, .chan_size = GTW_LINK_OUT_STREAM_SIZE, }, .ops = &hda_link_dma_ops, diff --git a/src/platform/intel/cavs/platform.c b/src/platform/intel/cavs/platform.c index 90ba5ea2b031..964695770bf6 100644 --- a/src/platform/intel/cavs/platform.c +++ b/src/platform/intel/cavs/platform.c @@ -130,7 +130,9 @@ struct timesource_data platform_generic_queue[] = { { .timer = { .id = TIMER3, /* external timer */ - .irq = IRQ_EXT_TSTAMP0_LVL2(0), + .irq = IRQ_EXT_TSTAMP0_LVL2, + .irq_name = irq_name_level2, + .core = 0, }, .clk = CLK_SSP, .notifier = NOTIFIER_ID_SSP_FREQ, @@ -141,7 +143,9 @@ struct timesource_data platform_generic_queue[] = { { .timer = { .id = TIMER3, /* external timer */ - .irq = IRQ_EXT_TSTAMP0_LVL2(1), + .irq = IRQ_EXT_TSTAMP0_LVL2, + .irq_name = irq_name_level2, + .core = 1, }, .clk = CLK_SSP, .notifier = NOTIFIER_ID_SSP_FREQ, @@ -153,7 +157,9 @@ struct timesource_data platform_generic_queue[] = { { .timer = { .id = TIMER3, /* external timer */ - .irq = IRQ_EXT_TSTAMP0_LVL2(2), + .irq = IRQ_EXT_TSTAMP0_LVL2, + .irq_name = irq_name_level2, + .core = 2, }, .clk = CLK_SSP, .notifier = NOTIFIER_ID_SSP_FREQ, @@ -164,7 +170,9 @@ struct timesource_data platform_generic_queue[] = { { .timer = { .id = TIMER3, /* external timer */ - .irq = IRQ_EXT_TSTAMP0_LVL2(3), + .irq = IRQ_EXT_TSTAMP0_LVL2, + .irq_name = irq_name_level2, + .core = 3, }, .clk = CLK_SSP, .notifier = NOTIFIER_ID_SSP_FREQ, @@ -288,7 +296,6 @@ struct timer *platform_timer = static struct spi_platform_data spi = { .base = DW_SPI_SLAVE_BASE, - .irq = IRQ_EXT_LP_GPDMA0_LVL5(0, 0), .type = SOF_SPI_INTEL_SLAVE, .fifo[SPI_DIR_RX] = { .handshake = DMA_HANDSHAKE_SSI_RX, diff --git a/src/platform/suecreek/include/platform/drivers/interrupt.h b/src/platform/suecreek/include/platform/drivers/interrupt.h index cf865f08e9fb..a89b2d656db5 100644 --- a/src/platform/suecreek/include/platform/drivers/interrupt.h +++ b/src/platform/suecreek/include/platform/drivers/interrupt.h @@ -69,52 +69,31 @@ #define IRQ_BIT_LVL5_SSP(x) (0 + x) /* Priority 2 Peripheral IRQ mappings */ -#define IRQ_EXT_HP_GPDMA_LVL2(xcpu) \ - SOF_IRQ(IRQ_BIT_LVL2_HP_GP_DMA0(0), 2, xcpu, IRQ_NUM_EXT_LEVEL2) -#define IRQ_EXT_IDC_LVL2(xcpu) \ - SOF_IRQ(IRQ_BIT_LVL2_IDC, 2, xcpu, IRQ_NUM_EXT_LEVEL2) -#define IRQ_EXT_IPC_LVL2(xcpu) \ - SOF_IRQ(IRQ_BIT_LVL2_HOST_IPC, 2, xcpu, IRQ_NUM_EXT_LEVEL2) -#define IRQ_EXT_TSTAMP1_LVL2(xcpu) \ - SOF_IRQ(IRQ_BIT_LVL2_WALL_CLK1, 2, xcpu, IRQ_NUM_EXT_LEVEL2) -#define IRQ_EXT_TSTAMP0_LVL2(xcpu) \ - SOF_IRQ(IRQ_BIT_LVL2_WALL_CLK0, 2, xcpu, IRQ_NUM_EXT_LEVEL2) -#define IRQ_EXT_MERR_LVL2(xcpu) \ - SOF_IRQ(IRQ_BIT_LVL2_L2_MEMERR, 2, xcpu, IRQ_NUM_EXT_LEVEL2) -#define IRQ_EXT_L2CACHE_LVL2(xcpu) \ - SOF_IRQ(IRQ_BIT_LVL2_L2_CACHE, 2, xcpu, IRQ_NUM_EXT_LEVEL2) -#define IRQ_EXT_SHA256_LVL2(xcpu) \ - SOF_IRQ(IRQ_BIT_LVL2_SHA256, 2, xcpu, IRQ_NUM_EXT_LEVEL2) +#define IRQ_EXT_HP_GPDMA_LVL2 IRQ_BIT_LVL2_HP_GP_DMA0(0) +#define IRQ_EXT_IDC_LVL2 IRQ_BIT_LVL2_IDC +#define IRQ_EXT_IPC_LVL2 IRQ_BIT_LVL2_HOST_IPC +#define IRQ_EXT_TSTAMP1_LVL2 IRQ_BIT_LVL2_WALL_CLK1 +#define IRQ_EXT_TSTAMP0_LVL2 IRQ_BIT_LVL2_WALL_CLK0 +#define IRQ_EXT_MERR_LVL2 IRQ_BIT_LVL2_L2_MEMERR +#define IRQ_EXT_L2CACHE_LVL2 IRQ_BIT_LVL2_L2_CACHE +#define IRQ_EXT_SHA256_LVL2 IRQ_BIT_LVL2_SHA256 /* Priority 3 Peripheral IRQ mappings */ -#define IRQ_EXT_CODE_DMA_LVL3(xcpu) \ - SOF_IRQ(IRQ_BIT_LVL3_CODE_LOADER, 3, xcpu, IRQ_NUM_EXT_LEVEL3) -#define IRQ_EXT_HOST_DMA_IN_LVL3(xcpu, channel) \ - SOF_IRQ(IRQ_BIT_LVL3_HOST_STREAM_IN(channel), 3, xcpu, \ - IRQ_NUM_EXT_LEVEL3) -#define IRQ_EXT_HOST_DMA_OUT_LVL3(xcpu, channel) \ - SOF_IRQ(IRQ_BIT_LVL3_HOST_STREAM_OUT(channel), 3, xcpu, \ - IRQ_NUM_EXT_LEVEL3) +#define IRQ_EXT_CODE_DMA_LVL3 IRQ_BIT_LVL3_CODE_LOADER +#define IRQ_EXT_HOST_DMA_IN_LVL3(channel) IRQ_BIT_LVL3_HOST_STREAM_IN(channel) +#define IRQ_EXT_HOST_DMA_OUT_LVL3(channel) IRQ_BIT_LVL3_HOST_STREAM_OUT(channel) /* Priority 4 Peripheral IRQ mappings */ -#define IRQ_EXT_LINK_DMA_IN_LVL4(xcpu, channel) \ - SOF_IRQ(IRQ_BIT_LVL4_LINK_STREAM_IN(channel), 4, xcpu, \ - IRQ_NUM_EXT_LEVEL4) -#define IRQ_EXT_LINK_DMA_OUT_LVL4(xcpu, channel) \ - SOF_IRQ(IRQ_BIT_LVL4_LINK_STREAM_OUT(channel), 4, xcpu, \ - IRQ_NUM_EXT_LEVEL4) +#define IRQ_EXT_LINK_DMA_IN_LVL4(channel) IRQ_BIT_LVL4_LINK_STREAM_IN(channel) +#define IRQ_EXT_LINK_DMA_OUT_LVL4(channel) IRQ_BIT_LVL4_LINK_STREAM_OUT(channel) /* Priority 5 Peripheral IRQ mappings */ -#define IRQ_EXT_LP_GPDMA0_LVL5(xcpu, channel) \ - SOF_ID_IRQ(0, IRQ_BIT_LVL5_LP_GP_DMA0, 5, xcpu, IRQ_NUM_EXT_LEVEL5) -#define IRQ_EXT_LP_GPDMA1_LVL5(xcpu, channel) \ - SOF_ID_IRQ(1, IRQ_BIT_LVL5_LP_GP_DMA0, 5, xcpu, IRQ_NUM_EXT_LEVEL5) +#define IRQ_EXT_LP_GPDMA0_LVL5(channel) IRQ_BIT_LVL5_LP_GP_DMA0 +#define IRQ_EXT_LP_GPDMA1_LVL5(channel) IRQ_BIT_LVL5_LP_GP_DMA0 -#define IRQ_EXT_SSPx_LVL5(x, xcpu) \ - SOF_IRQ(IRQ_BIT_LVL5_SSP(x), 5, xcpu, IRQ_NUM_EXT_LEVEL5) +#define IRQ_EXT_SSPx_LVL5(x) IRQ_BIT_LVL5_SSP(x) -#define IRQ_EXT_DMIC_LVL5(x, xcpu) \ - SOF_IRQ(IRQ_BIT_LVL5_DMIC(x), 5, xcpu, IRQ_NUM_EXT_LEVEL5) +#define IRQ_EXT_DMIC_LVL5(x) IRQ_BIT_LVL5_DMIC(x) /* IRQ Masks */ diff --git a/src/platform/suecreek/include/platform/drivers/timer.h b/src/platform/suecreek/include/platform/drivers/timer.h index 92a49cebc7ef..cf4ea48174af 100644 --- a/src/platform/suecreek/include/platform/drivers/timer.h +++ b/src/platform/suecreek/include/platform/drivers/timer.h @@ -20,8 +20,8 @@ #define TIMER0 IRQ_NUM_TIMER1 #define TIMER1 IRQ_NUM_TIMER2 #define TIMER2 IRQ_NUM_TIMER3 -#define TIMER3 IRQ_EXT_TSTAMP0_LVL2(0) -#define TIMER4 IRQ_EXT_TSTAMP1_LVL2(0) +#define TIMER3 IRQ_EXT_TSTAMP0_LVL2 +#define TIMER4 IRQ_EXT_TSTAMP1_LVL2 #endif /* __PLATFORM_DRIVERS_TIMER_H__ */ diff --git a/src/platform/suecreek/include/platform/lib/dma.h b/src/platform/suecreek/include/platform/lib/dma.h index 057a578fe773..b14ab58e6fde 100644 --- a/src/platform/suecreek/include/platform/lib/dma.h +++ b/src/platform/suecreek/include/platform/lib/dma.h @@ -37,7 +37,7 @@ #define DMA_HANDSHAKE_SSI_TX 26 #define DMA_HANDSHAKE_SSI_RX 27 -#define dma_chan_irq(dma, cpu, chan) dma_irq(dma, cpu) +#define dma_chan_irq(dma, chan) dma_irq(dma) int dmac_init(void); diff --git a/src/platform/suecreek/include/platform/platform.h b/src/platform/suecreek/include/platform/platform.h index eb03024be2ad..83c8fa9d1a15 100644 --- a/src/platform/suecreek/include/platform/platform.h +++ b/src/platform/suecreek/include/platform/platform.h @@ -22,6 +22,7 @@ #include #include #include +#include #include struct timer; @@ -49,17 +50,19 @@ struct timer; #define PLATFORM_PAGE_TABLE_SIZE 256 /* IDC Interrupt */ -#define PLATFORM_IDC_INTERRUPT(x) IRQ_EXT_IDC_LVL2(x) - -/* IPC Interrupt */ -#define PLATFORM_IPC_INTERRUPT IRQ_EXT_IPC_LVL2(0) +#define PLATFORM_IDC_INTERRUPT IRQ_EXT_IDC_LVL2 +#define PLATFORM_IDC_INTERRUPT_NAME irq_name_level2 /* pipeline IRQ */ -#define PLATFORM_SCHEDULE_IRQ IRQ_NUM_SOFTWARE4 +#define PLATFORM_SCHEDULE_IRQ IRQ_NUM_SOFTWARE4 +#define PLATFORM_SCHEDULE_IRQ_NAME NULL #define PLATFORM_IRQ_TASK_HIGH IRQ_NUM_SOFTWARE3 +#define PLATFORM_IRQ_TASK_HIGH_NAME NULL #define PLATFORM_IRQ_TASK_MED IRQ_NUM_SOFTWARE2 +#define PLATFORM_IRQ_TASK_MED_NAME NULL #define PLATFORM_IRQ_TASK_LOW IRQ_NUM_SOFTWARE1 +#define PLATFORM_IRQ_TASK_LOW_NAME NULL #define PLATFORM_SCHEDULE_COST 200 diff --git a/src/schedule/edf_schedule.c b/src/schedule/edf_schedule.c index 696a2aa15b30..7d335d17c4c6 100644 --- a/src/schedule/edf_schedule.c +++ b/src/schedule/edf_schedule.c @@ -27,6 +27,7 @@ struct edf_schedule_data { struct list_item list; /* list of tasks in priority queue */ struct list_item idle_list; /* list of queued idle tasks */ uint32_t clock; + int irq; }; #define SLOT_ALIGN_TRIES 10 @@ -172,7 +173,7 @@ static struct task *sch_edf(void) tracev_edf_sch("sch_edf()"); - interrupt_clear(PLATFORM_SCHEDULE_IRQ); + interrupt_clear(sch->irq); while (!list_is_empty(&sch->list)) { spin_lock_irq(&sch->lock, flags); @@ -406,7 +407,7 @@ static void schedule_edf(void) */ /* the scheduler is run in IRQ context */ - interrupt_set(PLATFORM_SCHEDULE_IRQ); + interrupt_set(sch->irq); } /* Initialise the scheduler */ @@ -428,9 +429,12 @@ static int edf_scheduler_init(void) sch->clock = PLATFORM_SCHED_CLOCK; /* configure scheduler interrupt */ - interrupt_register(PLATFORM_SCHEDULE_IRQ, IRQ_AUTO_UNMASK, - edf_scheduler_run, NULL); - interrupt_enable(PLATFORM_SCHEDULE_IRQ); + sch->irq = interrupt_get_irq(PLATFORM_SCHEDULE_IRQ, + PLATFORM_SCHEDULE_IRQ_NAME); + if (sch->irq < 0) + return sch->irq; + interrupt_register(sch->irq, IRQ_AUTO_UNMASK, edf_scheduler_run, sch); + interrupt_enable(sch->irq, sch); /* allocate arch tasks */ int tasks_result = allocate_tasks(); @@ -448,8 +452,8 @@ static void edf_scheduler_free(void) spin_lock_irq(&sch->lock, flags); /* disable and unregister scheduler interrupt */ - interrupt_disable(PLATFORM_SCHEDULE_IRQ); - interrupt_unregister(PLATFORM_SCHEDULE_IRQ); + interrupt_disable(sch->irq, sch); + interrupt_unregister(sch->irq, sch); /* free arch tasks */ arch_free_tasks(); diff --git a/src/schedule/ll_schedule.c b/src/schedule/ll_schedule.c index 686f6ac45a5e..fdfb4112b5c1 100644 --- a/src/schedule/ll_schedule.c +++ b/src/schedule/ll_schedule.c @@ -58,6 +58,7 @@ struct ll_queue_shared_context { /* registered timers */ struct timer *timers[PLATFORM_CORE_COUNT]; + struct timer_irq tirq[PLATFORM_CORE_COUNT]; }; static struct ll_queue_shared_context *ll_shared_ctx; @@ -527,9 +528,6 @@ static struct ll_schedule_data *work_new_queue(struct timesource_data *ts) queue->notifier.id = ts->notifier; notifier_register(&queue->notifier); - /* register system timer */ - timer_register(&queue->ts->timer, queue_run, queue); - return queue; } @@ -545,14 +543,28 @@ static int ll_scheduler_init(void) sch_data->ll_sch_data = work_new_queue(ts); - if (cpu_get_id() == PLATFORM_MASTER_CORE_ID) { + if (cpu == PLATFORM_MASTER_CORE_ID) { + unsigned int i; + ll_shared_ctx = rzalloc(RZONE_SYS | RZONE_FLAG_UNCACHED, SOF_MEM_CAPS_RAM, sizeof(*ll_shared_ctx)); + + for (i = 0, ts = platform_generic_queue; + i < PLATFORM_CORE_COUNT; i++, ts++) { + ts->timer.tirq = ll_shared_ctx->tirq + i; + dcache_writeback_region(&ts->timer.tirq, + sizeof(ts->timer.tirq)); + } + atomic_init(&ll_shared_ctx->total_num_work, 0); atomic_init(&ll_shared_ctx->timer_clients, 0); } + /* register system timer */ + timer_register(&platform_generic_queue[cpu].timer, queue_run, + sch_data->ll_sch_data); + return ret; }