Port the change on cnl to apl
Signed-off-by: Rander Wang rander.wang@linux.intel.com
--- V2: get core id in a generic way
test on CNL & APL & BYT, pass SOF: master 85ae8e74181f kernel: v4.14 2cd03d26b66f8fee2 SOF-tools: master 56e26dd528b6c77 --- .../apollolake/include/platform/interrupt.h | 2 +- src/platform/apollolake/include/platform/memory.h | 4 +- .../apollolake/include/platform/platform.h | 10 + src/platform/apollolake/interrupt.c | 210 +++++++++++++-------- 4 files changed, 141 insertions(+), 85 deletions(-)
diff --git a/src/platform/apollolake/include/platform/interrupt.h b/src/platform/apollolake/include/platform/interrupt.h index 8e29deb..6778661 100644 --- a/src/platform/apollolake/include/platform/interrupt.h +++ b/src/platform/apollolake/include/platform/interrupt.h @@ -164,7 +164,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/apollolake/include/platform/memory.h b/src/platform/apollolake/include/platform/memory.h index c71d8c6..6b3f21f 100644 --- a/src/platform/apollolake/include/platform/memory.h +++ b/src/platform/apollolake/include/platform/memory.h @@ -171,7 +171,7 @@ #define SOF_TEXT_SIZE 0x19000
/* initialized data */ -#define SOF_DATA_SIZE 0x18000 +#define SOF_DATA_SIZE 0x19000
/* bss data */ #define SOF_BSS_DATA_SIZE 0x2800 @@ -180,7 +180,7 @@ #define HEAP_SYSTEM_BASE \ (SOF_TEXT_BASE + SOF_TEXT_SIZE +\ SOF_DATA_SIZE + SOF_BSS_DATA_SIZE) -#define HEAP_SYSTEM_SIZE 0x3200 +#define HEAP_SYSTEM_SIZE 0x5000
#define HEAP_RUNTIME_BASE (HEAP_SYSTEM_BASE + HEAP_SYSTEM_SIZE) #define HEAP_RUNTIME_SIZE \ diff --git a/src/platform/apollolake/include/platform/platform.h b/src/platform/apollolake/include/platform/platform.h index d57b880..409422c 100644 --- a/src/platform/apollolake/include/platform/platform.h +++ b/src/platform/apollolake/include/platform/platform.h @@ -39,6 +39,8 @@
struct sof;
+#define MAX_CORE_COUNT 2 + /* Host page size */ #define HOST_PAGE_SIZE 4096 #define PLATFORM_PAGE_TABLE_SIZE 256 @@ -130,6 +132,14 @@ struct sof;
extern struct timer *platform_timer;
+static inline int platform_get_core_id(void) +{ + int prid; + + __asm__("rsr.prid %0" : "=a"(prid)); + return prid; +} + /* * APIs declared here are defined for every platform and IPC mechanism. */ diff --git a/src/platform/apollolake/interrupt.c b/src/platform/apollolake/interrupt.c index d4af079..9ec36e7 100644 --- a/src/platform/apollolake/interrupt.c +++ b/src/platform/apollolake/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 = platform_get_core_id();
/* 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 = platform_get_core_id();
/* 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 = platform_get_core_id();
/* mask the parent IRQ */ arch_interrupt_disable_mask(1 << IRQ_NUM_EXT_LEVEL4);
/* mask all child interrupts */ - status = irq_read(REG_IRQ_IL4SD(0)); - irq_write(REG_IRQ_IL4MSD(0), status); + status = irq_read(REG_IRQ_IL4SD(core)); + irq_write(REG_IRQ_IL4MSD(core), status);
/* handle each child */ while (status) { @@ -147,17 +166,22 @@ static void parent_level4_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_IL4MCD(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_IL4MCD(core), 0x1 << i); + next: status >>= 1; i++; @@ -168,19 +192,22 @@ next: arch_interrupt_enable_mask(1 << IRQ_NUM_EXT_LEVEL4); }
-static void parent_level5_handler(void *data) +static void irq_lvl2_level5_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 = platform_get_core_id();
/* mask the parent IRQ */ arch_interrupt_disable_mask(1 << IRQ_NUM_EXT_LEVEL5);
/* mask all child interrupts */ - status = irq_read(REG_IRQ_IL5SD(0)); - irq_write(REG_IRQ_IL5MSD(0), status); + status = irq_read(REG_IRQ_IL5SD(core)); + irq_write(REG_IRQ_IL5MSD(core), status);
/* handle each child */ while (status) { @@ -190,17 +217,22 @@ static void parent_level5_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_IL5MCD(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_IL5MCD(core), 0x1 << i); + next: status >>= 1; i++; @@ -212,24 +244,31 @@ next: }
/* DSP internal interrupts */ -static struct irq_parent dsp_irq[4] = { - {IRQ_NUM_EXT_LEVEL2, parent_level2_handler, }, - {IRQ_NUM_EXT_LEVEL3, parent_level3_handler, }, - {IRQ_NUM_EXT_LEVEL4, parent_level4_handler, }, - {IRQ_NUM_EXT_LEVEL5, parent_level5_handler, }, +static struct irq_desc dsp_irq[MAX_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, } }, + + {{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, } }, };
-struct irq_parent *platform_irq_get_parent(uint32_t irq) +struct irq_desc *platform_irq_get_parent(uint32_t irq) { + int core = platform_get_core_id(); + switch (SOF_IRQ_NUMBER(irq)) { case IRQ_NUM_EXT_LEVEL2: - return &dsp_irq[0]; + return &dsp_irq[core][0]; case IRQ_NUM_EXT_LEVEL3: - return &dsp_irq[1]; + return &dsp_irq[core][1]; case IRQ_NUM_EXT_LEVEL4: - return &dsp_irq[2]; + return &dsp_irq[core][2]; case IRQ_NUM_EXT_LEVEL5: - return &dsp_irq[3]; + return &dsp_irq[core][3]; default: return NULL; } @@ -242,19 +281,21 @@ uint32_t platform_interrupt_get_enabled(void)
void platform_interrupt_mask(uint32_t irq, uint32_t mask) { + int core = platform_get_core_id(); + /* mask external interrupt bit */ switch (SOF_IRQ_NUMBER(irq)) { case IRQ_NUM_EXT_LEVEL5: - irq_write(REG_IRQ_IL5MSD(0), 1 << SOF_IRQ_BIT(irq)); + irq_write(REG_IRQ_IL5MSD(core), 1 << SOF_IRQ_BIT(irq)); break; case IRQ_NUM_EXT_LEVEL4: - irq_write(REG_IRQ_IL4MSD(0), 1 << SOF_IRQ_BIT(irq)); + irq_write(REG_IRQ_IL4MSD(core), 1 << SOF_IRQ_BIT(irq)); break; case IRQ_NUM_EXT_LEVEL3: - irq_write(REG_IRQ_IL3MSD(0), 1 << SOF_IRQ_BIT(irq)); + irq_write(REG_IRQ_IL3MSD(core), 1 << SOF_IRQ_BIT(irq)); break; case IRQ_NUM_EXT_LEVEL2: - irq_write(REG_IRQ_IL2MSD(0), 1 << SOF_IRQ_BIT(irq)); + irq_write(REG_IRQ_IL2MSD(core), 1 << SOF_IRQ_BIT(irq)); break; default: break; @@ -264,19 +305,21 @@ void platform_interrupt_mask(uint32_t irq, uint32_t mask)
void platform_interrupt_unmask(uint32_t irq, uint32_t mask) { + int core = platform_get_core_id(); + /* unmask external interrupt bit */ switch (SOF_IRQ_NUMBER(irq)) { case IRQ_NUM_EXT_LEVEL5: - irq_write(REG_IRQ_IL5MCD(0), 1 << SOF_IRQ_BIT(irq)); + irq_write(REG_IRQ_IL5MCD(core), 1 << SOF_IRQ_BIT(irq)); break; case IRQ_NUM_EXT_LEVEL4: - irq_write(REG_IRQ_IL4MCD(0), 1 << SOF_IRQ_BIT(irq)); + irq_write(REG_IRQ_IL4MCD(core), 1 << SOF_IRQ_BIT(irq)); break; case IRQ_NUM_EXT_LEVEL3: - irq_write(REG_IRQ_IL3MCD(0), 1 << SOF_IRQ_BIT(irq)); + irq_write(REG_IRQ_IL3MCD(core), 1 << SOF_IRQ_BIT(irq)); break; case IRQ_NUM_EXT_LEVEL2: - irq_write(REG_IRQ_IL2MCD(0), 1 << SOF_IRQ_BIT(irq)); + irq_write(REG_IRQ_IL2MCD(core), 1 << SOF_IRQ_BIT(irq)); break; default: break; @@ -290,15 +333,18 @@ void platform_interrupt_clear(uint32_t irq, uint32_t mask)
void platform_interrupt_init(void) { - int i; + int i, j; + int core = platform_get_core_id();
/* mask all external IRQs by default */ - irq_write(REG_IRQ_IL2MSD(0), REG_IRQ_IL2MD_ALL); - irq_write(REG_IRQ_IL3MSD(0), REG_IRQ_IL3MD_ALL); - irq_write(REG_IRQ_IL4MSD(0), REG_IRQ_IL4MD_ALL); - irq_write(REG_IRQ_IL5MSD(0), REG_IRQ_IL5MD_ALL); - - for (i = 0; i < ARRAY_SIZE(dsp_irq); i++) { - spinlock_init(&dsp_irq[i].lock); + irq_write(REG_IRQ_IL2MSD(core), REG_IRQ_IL2MD_ALL); + irq_write(REG_IRQ_IL3MSD(core), REG_IRQ_IL3MD_ALL); + 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]); } }