[Sound-open-firmware] [PATCH 3/7] cnl-interrupt: refine interrupt setting for change in irq_desc

Liam Girdwood liam.r.girdwood at linux.intel.com
Mon May 7 15:01:34 CEST 2018


On Fri, 2018-05-04 at 16:14 +0800, Rander Wang wrote:
> (1)Add core id check in interrupt register setting.
> (2)Check child list in interrupt function
> (3)Extend root irq_desc to support 4 core on cnl.
> (4)Refine macro for interrupt setting
> 
> Signed-off-by: Rander Wang <rander.wang at linux.intel.com>
> Signed-off-by: Liam Girdwood <liam.r.girdwood at linux.intel.com>
> ---
>  src/platform/cannonlake/dma.c                      |   2 +-
>  .../cannonlake/include/platform/interrupt.h        |  16 +-
>  src/platform/cannonlake/include/platform/memory.h  |   2 +-
>  .../cannonlake/include/platform/platform.h         |   2 +
>  src/platform/cannonlake/interrupt.c                | 220 +++++++++++++-------
> -
>  5 files changed, 150 insertions(+), 92 deletions(-)
> 
> diff --git a/src/platform/cannonlake/dma.c b/src/platform/cannonlake/dma.c
> index b606d1e..3f9d6cb 100644
> --- a/src/platform/cannonlake/dma.c
> +++ b/src/platform/cannonlake/dma.c
> @@ -125,7 +125,7 @@ static struct dma dma[] = {
>  		.id		= DMA_GP_LP_DMAC1,
>  		.base		= LP_GP_DMA_BASE(1),
>  		.channels	= 8,
> -		.irq = IRQ_EXT_LP_GPDMA0_LVL5(0, 0),
> +		.irq = IRQ_EXT_LP_GPDMA1_LVL5(0, 0),
>  		.drv_plat_data	= &dmac1,
>  	},
>  	.ops		= &dw_dma_ops,
> diff --git a/src/platform/cannonlake/include/platform/interrupt.h
> b/src/platform/cannonlake/include/platform/interrupt.h
> index 03857a7..b14cfdf 100644
> --- a/src/platform/cannonlake/include/platform/interrupt.h
> +++ b/src/platform/cannonlake/include/platform/interrupt.h
> @@ -88,7 +88,7 @@
>  #define IRQ_BIT_LVL5_DMIC		6
>  #define IRQ_BIT_LVL5_SSP(x)		(0 + x)
>  
> -/* Level 2 Peripheral IRQ mappings */
> +/* 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) \
> @@ -106,7 +106,7 @@
>  #define IRQ_EXT_SHA256_LVL2(xcpu) \
>  	SOF_IRQ(IRQ_BIT_LVL2_SHA256, 2, xcpu, IRQ_NUM_EXT_LEVEL2)
>  
> -/* Level 3 Peripheral IRQ mappings */
> +/* 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) \
> @@ -114,17 +114,17 @@
>  #define IRQ_EXT_HOST_DMA_OUT_LVL3(xcpu, channel) \
>  	SOF_IRQ(IRQ_BIT_LVL3_HOST_STREAM_OUT(channel), 3, xcpu,
> IRQ_NUM_EXT_LEVEL3)
>  
> -/* Level 4 Peripheral IRQ mappings */
> +/* 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)
>  
> -/* Level 5 Peripheral IRQ mappings */
> +/* Priority 5 Peripheral IRQ mappings */
>  #define IRQ_EXT_LP_GPDMA0_LVL5(xcpu, channel) \
> -	SOF_IRQ(IRQ_BIT_LVL5_LP_GP_DMA0, 5, xcpu, IRQ_NUM_EXT_LEVEL5)
> -#define IRQ_EXT_LP_GPDMA1_LVL4(xcpu, channel) \
> -	SOF_IRQ(IRQ_BIT_LVL5_LP_GP_DMA1, 4, xcpu, IRQ_NUM_EXT_LEVEL4)
> +	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_SSP0_LVL5(xcpu) \
>  	SOF_IRQ(IRQ_BIT_LVL5_SSP(0), 5, xcpu, IRQ_NUM_EXT_LEVEL5)
>  #define IRQ_EXT_SSP1_LVL5(xcpu) \
> @@ -161,7 +161,7 @@
>  
>  void platform_interrupt_init(void);
>  
> -struct irq_parent *platform_irq_get_parent(uint32_t irq);
> +struct irq_desc *platform_irq_get_parent(uint32_t irq);
>  void platform_interrupt_set(int irq);
>  void platform_interrupt_clear(uint32_t irq, uint32_t mask);
>  uint32_t platform_interrupt_get_enabled(void);
> diff --git a/src/platform/cannonlake/include/platform/memory.h
> b/src/platform/cannonlake/include/platform/memory.h
> index c7f4750..67f574a 100644
> --- a/src/platform/cannonlake/include/platform/memory.h
> +++ b/src/platform/cannonlake/include/platform/memory.h
> @@ -240,7 +240,7 @@
>  #define SOF_TEXT_SIZE		0x18000
>  
>  /* initialized data */
> -#define SOF_DATA_SIZE		0x18000
> +#define SOF_DATA_SIZE		0x19000
>  
>  /* bss data */
>  #define SOF_BSS_DATA_SIZE		0x8000
> diff --git a/src/platform/cannonlake/include/platform/platform.h
> b/src/platform/cannonlake/include/platform/platform.h
> index c5bf42a..3d262b4 100644
> --- a/src/platform/cannonlake/include/platform/platform.h
> +++ b/src/platform/cannonlake/include/platform/platform.h
> @@ -42,6 +42,8 @@ struct sof;
>  #define PLATFORM_SSP_COUNT 3
>  #define MAX_GPDMA_COUNT 2
>  
> +#define MAX_CORE_COUNT 4
> +
>  /* Host page size */
>  #define HOST_PAGE_SIZE		4096
>  #define PLATFORM_PAGE_TABLE_SIZE	256
> diff --git a/src/platform/cannonlake/interrupt.c
> b/src/platform/cannonlake/interrupt.c
> index 8c47e14..e9ef4e7 100644
> --- a/src/platform/cannonlake/interrupt.c
> +++ b/src/platform/cannonlake/interrupt.c
> @@ -39,19 +39,22 @@
>  #include <stdint.h>
>  #include <stdlib.h>
>  
> -static void parent_level2_handler(void *data)
> +static void irq_lvl2_level2_handler(void *data)
>  {
> -	struct irq_parent *parent = (struct irq_parent *)data;
> -	struct irq_child * child = NULL;
> +	struct irq_desc *parent = (struct irq_desc *)data;
> +	struct irq_desc *child = NULL;
> +	struct list_item *clist;
>  	uint32_t status;
>  	uint32_t i = 0;
> +	uint32_t unmask = 0;
> +	int core = xthal_get_prid();
>  
>  	/* mask the parent IRQ */
>  	arch_interrupt_disable_mask(1 << IRQ_NUM_EXT_LEVEL2);
>  
>  	/* mask all child interrupts */
> -	status = irq_read(REG_IRQ_IL2SD(0));
> -	irq_write(REG_IRQ_IL2MSD(0), status);
> +	status = irq_read(REG_IRQ_IL2SD(core));
> +	irq_write(REG_IRQ_IL2MSD(core), status);
>  
>  	/* handle each child */
>  	while (status) {
> @@ -61,17 +64,22 @@ static void parent_level2_handler(void *data)
>  			goto next;
>  
>  		/* get child if any and run handler */
> -		child = parent->child[i];
> -		if (child && child->handler) {
> -			child->handler(child->handler_arg);
> -
> -			/* unmask this bit i interrupt */
> -			irq_write(REG_IRQ_IL2MCD(0), 0x1 << i);
> -		} else {
> -			/* nobody cared ? */
> -			trace_irq_error("nbc");
> +		list_for_item(clist, &parent->child[i]) {
> +			child = container_of(clist, struct irq_desc,
> irq_list);
> +
> +			if (child && child->handler) {
> +				child->handler(child->handler_arg);
> +				unmask = 1;
> +			} else {
> +				/* nobody cared ? */
> +				trace_irq_error("nbc");
> +			}
>  		}
>  
> +		/* unmask this bit i interrupt */
> +		if (unmask)
> +			irq_write(REG_IRQ_IL2MCD(core), 0x1 << i);
> +
>  next:
>  		status >>= 1;
>  		i++;
> @@ -82,19 +90,22 @@ next:
>  	arch_interrupt_enable_mask(1 << IRQ_NUM_EXT_LEVEL2);
>  }
>  
> -static void parent_level3_handler(void *data)
> +static void irq_lvl2_level3_handler(void *data)
>  {
> -	struct irq_parent *parent = (struct irq_parent *)data;
> -	struct irq_child * child = NULL;
> +	struct irq_desc *parent = (struct irq_desc *)data;
> +	struct irq_desc *child = NULL;
> +	struct list_item *clist;
>  	uint32_t status;
>  	uint32_t i = 0;
> +	uint32_t unmask = 0;
> +	int core = xthal_get_prid();
>  
>  	/* mask the parent IRQ */
>  	arch_interrupt_disable_mask(1 << IRQ_NUM_EXT_LEVEL3);
>  
>  	/* mask all child interrupts */
> -	status = irq_read(REG_IRQ_IL3SD(0));
> -	irq_write(REG_IRQ_IL3MSD(0), status);
> +	status = irq_read(REG_IRQ_IL3SD(core));
> +	irq_write(REG_IRQ_IL3MSD(core), status);
>  
>  	/* handle each child */
>  	while (status) {
> @@ -104,17 +115,22 @@ static void parent_level3_handler(void *data)
>  			goto next;
>  
>  		/* get child if any and run handler */
> -		child = parent->child[i];
> -		if (child && child->handler) {
> -			child->handler(child->handler_arg);
> -
> -			/* unmask this bit i interrupt */
> -			irq_write(REG_IRQ_IL3MCD(0), 0x1 << i);
> -		} else {
> -			/* nobody cared ? */
> -			trace_irq_error("nbc");
> +		list_for_item(clist, &parent->child[i]) {
> +			child = container_of(clist, struct irq_desc,
> irq_list);
> +
> +			if (child && child->handler) {
> +				child->handler(child->handler_arg);
> +				unmask = 1;
> +			} else {
> +				/* nobody cared ? */
> +				trace_irq_error("nbc");
> +			}
>  		}
>  
> +		/* unmask this bit i interrupt */
> +		if (unmask)
> +			irq_write(REG_IRQ_IL3MCD(core), 0x1 << i);
> +
>  next:
>  		status >>= 1;
>  		i++;
> @@ -125,19 +141,22 @@ next:
>  	arch_interrupt_enable_mask(1 << IRQ_NUM_EXT_LEVEL3);
>  }
>  
> -static void parent_level4_handler(void *data)
> +static void irq_lvl2_level4_handler(void *data)
>  {
> -	struct irq_parent *parent = (struct irq_parent *)data;
> -	struct irq_child * child = NULL;
> +	struct irq_desc *parent = (struct irq_desc *)data;
> +	struct irq_desc *child = NULL;
> +	struct list_item *clist;
>  	uint32_t status;
>  	uint32_t i = 0;
> +	uint32_t unmask = 0;
> +	int core = xthal_get_prid();


We cant call this directly in "generic" code. Can you send a separate patch that
 wraps this as a static inline or better still does inline assembly (as a static
inline).

Liam


More information about the Sound-open-firmware mailing list