From 2ac781c60c908d6ed3b95dc8e5c2fc8db6284f68 Mon Sep 17 00:00:00 2001 From: Iuliana Prodan Date: Fri, 23 Jul 2021 17:18:07 +0300 Subject: [PATCH 1/5] zephyr: intel: remove zephyr_ll from mandatory files Remove zephyr_ll.c from mandatory files for building SOF with Zephyr and include it where necessary: in CAVS 1.5, CAVS 1.8, CAVS 2.0 and CAVS 2.5. While here, add ll_schedule for BROADWELL and BAYTRAIL when building SOF with Zephyr. Signed-off-by: Iuliana Prodan --- zephyr/CMakeLists.txt | 31 ++++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/zephyr/CMakeLists.txt b/zephyr/CMakeLists.txt index 88f1180ff9f2..d56afb3526a7 100644 --- a/zephyr/CMakeLists.txt +++ b/zephyr/CMakeLists.txt @@ -113,6 +113,11 @@ if (CONFIG_SOC_SERIES_INTEL_ADSP_BAYTRAIL) ${SOF_SRC_PATH}/schedule/dma_multi_chan_domain.c ) + # SOF core infrastructure - runs on top of Zephyr + zephyr_library_sources( + ${SOF_SRC_PATH}/schedule/ll_schedule.c + ) + set(PLATFORM "baytrail") endif() @@ -123,6 +128,11 @@ if (CONFIG_SOC_SERIES_INTEL_ADSP_BROADWELL) ${SOF_DRIVERS_PATH}/intel/haswell/ssp.c ) + # SOF core infrastructure - runs on top of Zephyr + zephyr_library_sources( + ${SOF_SRC_PATH}/schedule/ll_schedule.c + ) + set(PLATFORM "haswell") endif() @@ -177,6 +187,11 @@ if (CONFIG_SOC_SERIES_INTEL_CAVS_V15) ${SOF_PLATFORM_PATH}/apollolake/lib/clk.c ) + # SOF core infrastructure - runs on top of Zephyr + zephyr_library_sources( + ${SOF_SRC_PATH}/schedule/zephyr_ll.c + ) + set_source_files_properties(${SOF_PLATFORM_PATH}/apollolake/lib/power_down.S PROPERTIES COMPILE_FLAGS -DASSEMBLY) set(PLATFORM "apollolake") @@ -239,6 +254,11 @@ if (CONFIG_SOC_SERIES_INTEL_CAVS_V18) #${SOF_PLATFORM_PATH}/intel/cavs/lps_pic_restore_vector.S ) + # SOF core infrastructure - runs on top of Zephyr + zephyr_library_sources( + ${SOF_SRC_PATH}/schedule/zephyr_ll.c + ) + zephyr_library_sources_ifdef(CONFIG_CAVS_LPS ${SOF_PLATFORM_PATH}/intel/cavs/lps_wait.c ) @@ -302,6 +322,11 @@ if (CONFIG_SOC_SERIES_INTEL_CAVS_V20) #${SOF_PLATFORM_PATH}/intel/cavs/lps_pic_restore_vector.S ) + # SOF core infrastructure - runs on top of Zephyr + zephyr_library_sources( + ${SOF_SRC_PATH}/schedule/zephyr_ll.c + ) + zephyr_library_sources_ifdef(CONFIG_CAVS_LPS ${SOF_PLATFORM_PATH}/intel/cavs/lps_wait.c ) @@ -368,6 +393,11 @@ if (CONFIG_SOC_SERIES_INTEL_CAVS_V25) #${SOF_PLATFORM_PATH}/intel/cavs/lps_pic_restore_vector.S ) + # SOF core infrastructure - runs on top of Zephyr + zephyr_library_sources( + ${SOF_SRC_PATH}/schedule/zephyr_ll.c + ) + zephyr_library_sources_ifdef(CONFIG_CAVS_LPS ${SOF_PLATFORM_PATH}/intel/cavs/lps_wait.c ) @@ -479,7 +509,6 @@ zephyr_library_sources( ${SOF_SRC_PATH}/schedule/schedule.c ${SOF_SRC_PATH}/schedule/dma_single_chan_domain.c ${SOF_SRC_PATH}/schedule/dma_multi_chan_domain.c - ${SOF_SRC_PATH}/schedule/zephyr_ll.c ${SOF_SRC_PATH}/schedule/zephyr.c # Bridge wrapper between SOF and Zephyr APIs - Will shrink over time. From fedcc4c1cad19d4e91d4e03b9eb4089b1c2d4ab6 Mon Sep 17 00:00:00 2001 From: Iuliana Prodan Date: Wed, 21 Jul 2021 16:51:58 +0300 Subject: [PATCH 2/5] zephyr: imx: use ll_schedule instead of zephyr_ll For now, zephyr_ll is limited to timer_domain. For i.MX we use dma_domain, so keep the ll_schedule from SOF, until we extend the zephyr_ll for DMA_IRQ. Signed-off-by: Iuliana Prodan --- src/include/sof/schedule/ll_schedule.h | 2 +- zephyr/CMakeLists.txt | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/include/sof/schedule/ll_schedule.h b/src/include/sof/schedule/ll_schedule.h index 441d71db5d03..8379f4c9fd06 100644 --- a/src/include/sof/schedule/ll_schedule.h +++ b/src/include/sof/schedule/ll_schedule.h @@ -34,7 +34,7 @@ struct ll_task_pdata { uint16_t skip_cnt; /**< how many times the task was skipped for execution */ }; -#ifndef __ZEPHYR__ +#if !defined(__ZEPHYR__) || defined(CONFIG_IMX) int scheduler_init_ll(struct ll_schedule_domain *domain); int schedule_task_init_ll(struct task *task, diff --git a/zephyr/CMakeLists.txt b/zephyr/CMakeLists.txt index d56afb3526a7..43d8b1a3197d 100644 --- a/zephyr/CMakeLists.txt +++ b/zephyr/CMakeLists.txt @@ -430,6 +430,11 @@ if (CONFIG_SOC_SERIES_NXP_IMX8) ${SOF_PLATFORM_PATH}/imx8/lib/memory.c ) + # SOF core infrastructure - runs on top of Zephyr + zephyr_library_sources( + ${SOF_SRC_PATH}/schedule/ll_schedule.c + ) + set(PLATFORM "imx8") endif() From c01772ed8b99a9b34d128e25daca81d24476f3b0 Mon Sep 17 00:00:00 2001 From: Iuliana Prodan Date: Fri, 23 Jul 2021 18:23:18 +0300 Subject: [PATCH 3/5] zephyr: imx: enable second level interrupts handling On i.MX the DMA interrupts are routed via IRQ_STEER. In order for this to work we need to: - make any second level interrupts handling go through interrupt-irqsteer.c; - use first level interrupt handling from wrapper.c. TODO: Implement a driver for the IRQ_STEER in Zephyr, to replace the legacy code (interrupt-irqsteer.c). Signed-off-by: Iuliana Prodan --- src/drivers/imx/interrupt-irqsteer.c | 4 +++ src/drivers/interrupt.c | 54 +++++++++++++++++++++++++++- src/include/sof/drivers/interrupt.h | 11 ++++++ src/platform/imx8/platform.c | 5 +++ src/schedule/dma_multi_chan_domain.c | 15 ++++++++ zephyr/CMakeLists.txt | 2 ++ zephyr/wrapper.c | 46 ++++++++++++------------ 7 files changed, 114 insertions(+), 23 deletions(-) diff --git a/src/drivers/imx/interrupt-irqsteer.c b/src/drivers/imx/interrupt-irqsteer.c index 269eb72e757b..51adefea3952 100644 --- a/src/drivers/imx/interrupt-irqsteer.c +++ b/src/drivers/imx/interrupt-irqsteer.c @@ -95,6 +95,10 @@ DECLARE_TR_CTX(irq_i_tr, SOF_UUID(irq_imx_uuid), LOG_LEVEL_INFO); #define IRQSTR_INT_BIT(irq) ((irq) % 32) #define IRQSTR_INT_MASK(irq) (1 << IRQSTR_INT_BIT(irq)) +#if defined(__ZEPHYR__) +#define interrupt_get_irq mux_interrupt_get_irq +#endif + /* HW register access helper methods */ static inline void irqstr_write(uint32_t reg, uint32_t value) diff --git a/src/drivers/interrupt.c b/src/drivers/interrupt.c index bae8c8de1faa..60c7d7b103df 100644 --- a/src/drivers/interrupt.c +++ b/src/drivers/interrupt.c @@ -27,6 +27,21 @@ DECLARE_SOF_UUID("irq", irq_uuid, 0x1862d39a, 0x3a84, 0x4d64, DECLARE_TR_CTX(irq_tr, SOF_UUID(irq_uuid), LOG_LEVEL_INFO); +/* For i.MX, when building SOF with Zephyr, we use wrapper.c, + * interrupt.c and interrupt-irqsteer.c which causes name + * collisions. + * In order to avoid this and make any second level interrupt + * handling go through interrupt-irqsteer.c define macros to + * rename the duplicated functions. + */ +#if defined(__ZEPHYR__) && defined(CONFIG_IMX) +#define interrupt_get_irq mux_interrupt_get_irq +#define interrupt_register mux_interrupt_register +#define interrupt_unregister mux_interrupt_unregister +#define interrupt_enable mux_interrupt_enable +#define interrupt_disable mux_interrupt_disable +#endif + static SHARED_DATA struct cascade_root cascade_root; static int interrupt_register_internal(uint32_t irq, void (*handler)(void *arg), @@ -361,8 +376,18 @@ static int interrupt_register_internal(uint32_t irq, void (*handler)(void *arg), /* no parent means we are registering DSP internal IRQ */ cascade = interrupt_get_parent(irq); - if (!cascade) + if (!cascade) { +#if defined(__ZEPHYR__) && defined(CONFIG_IMX) +/* undefine the macro so that interrupt_register() + * is resolved to the one from wrapper.c + */ +#undef interrupt_register + + return interrupt_register(irq, handler, arg); +#else return arch_interrupt_register(irq, handler, arg); +#endif + } spin_lock_irq(&cascade->lock, flags); ret = irq_register_child(cascade, irq, handler, arg, desc); @@ -386,7 +411,16 @@ static void interrupt_unregister_internal(uint32_t irq, const void *arg, /* no parent means we are unregistering DSP internal IRQ */ cascade = interrupt_get_parent(irq); if (!cascade) { +#if defined(__ZEPHYR__) && defined(CONFIG_IMX) +/* undefine the macro so that interrupt_unregister() + * is resolved to the one from wrapper.c + */ +#undef interrupt_unregister + + interrupt_unregister(irq, arg); +#else arch_interrupt_unregister(irq); +#endif return; } @@ -404,7 +438,16 @@ uint32_t interrupt_enable(uint32_t irq, void *arg) if (cascade) return irq_enable_child(cascade, irq, arg); +#if defined(__ZEPHYR__) && defined(CONFIG_IMX) +/* undefine the macro so that interrupt_enable() + * is resolved to the one from wrapper.c + */ +#undef interrupt_enable + + return interrupt_enable(irq, arg); +#else return arch_interrupt_enable_mask(1 << irq); +#endif } uint32_t interrupt_disable(uint32_t irq, void *arg) @@ -416,5 +459,14 @@ uint32_t interrupt_disable(uint32_t irq, void *arg) if (cascade) return irq_disable_child(cascade, irq, arg); +#if defined(__ZEPHYR__) && defined(CONFIG_IMX) +/* undefine the macro so that interrupt_disable() + * is resolved to the one from wrapper.c + */ +#undef interrupt_disable + + return interrupt_disable(irq, arg); +#else return arch_interrupt_disable_mask(1 << irq); +#endif } diff --git a/src/include/sof/drivers/interrupt.h b/src/include/sof/drivers/interrupt.h index e1a86de4ad9c..cdefd2849681 100644 --- a/src/include/sof/drivers/interrupt.h +++ b/src/include/sof/drivers/interrupt.h @@ -119,6 +119,17 @@ static inline struct cascade_root *cascade_root_get(void) return sof_get()->cascade_root; } +/* For i.MX, while building SOF with Zephyr use the interrupt_* + * functions from second level interrupt handling and IRQ_STEER. + */ +#if defined(__ZEPHYR__) && defined(CONFIG_IMX) +int mux_interrupt_get_irq(unsigned int irq, const char *cascade); +int mux_interrupt_register(uint32_t irq, void(*handler)(void *arg), void *arg); +void mux_interrupt_unregister(uint32_t irq, const void *arg); +uint32_t mux_interrupt_enable(uint32_t irq, void *arg); +uint32_t mux_interrupt_disable(uint32_t irq, void *arg); +#endif + int interrupt_register(uint32_t irq, void(*handler)(void *arg), void *arg); void interrupt_unregister(uint32_t irq, const void *arg); uint32_t interrupt_enable(uint32_t irq, void *arg); diff --git a/src/platform/imx8/platform.c b/src/platform/imx8/platform.c index 19b062d1f8e9..4e2c6bdf198f 100644 --- a/src/platform/imx8/platform.c +++ b/src/platform/imx8/platform.c @@ -156,6 +156,11 @@ int platform_init(struct sof *sof) sof->platform_timer = &timer; sof->cpu_timers = &timer; +#ifdef __ZEPHYR__ + /* initialize cascade interrupts before any usage */ + interrupt_init(sof); +#endif + platform_interrupt_init(); platform_clock_init(sof); scheduler_init_edf(); diff --git a/src/schedule/dma_multi_chan_domain.c b/src/schedule/dma_multi_chan_domain.c index cfc7443a981c..33f9cb463e2d 100644 --- a/src/schedule/dma_multi_chan_domain.c +++ b/src/schedule/dma_multi_chan_domain.c @@ -23,6 +23,21 @@ #include #include +/* For i.MX, when building SOF with Zephyr, we use wrapper.c, + * interrupt.c and interrupt-irqsteer.c which causes name + * collisions. + * In order to avoid this and make any second level interrupt + * handling go through interrupt-irqsteer.c define macros to + * rename the duplicated functions. + */ +#if defined(__ZEPHYR__) && defined(CONFIG_IMX) +#define interrupt_get_irq mux_interrupt_get_irq +#define interrupt_register mux_interrupt_register +#define interrupt_unregister mux_interrupt_unregister +#define interrupt_enable mux_interrupt_enable +#define interrupt_disable mux_interrupt_disable +#endif + struct dma_domain_data { int irq; struct pipeline_task *task; diff --git a/zephyr/CMakeLists.txt b/zephyr/CMakeLists.txt index 43d8b1a3197d..c684fc052738 100644 --- a/zephyr/CMakeLists.txt +++ b/zephyr/CMakeLists.txt @@ -419,6 +419,7 @@ if (CONFIG_SOC_SERIES_NXP_IMX8) ${SOF_DRIVERS_PATH}/imx/sai.c ${SOF_DRIVERS_PATH}/imx/ipc.c ${SOF_DRIVERS_PATH}/imx/esai.c + ${SOF_DRIVERS_PATH}/imx/interrupt-irqsteer.c ) # Platform sources @@ -433,6 +434,7 @@ if (CONFIG_SOC_SERIES_NXP_IMX8) # SOF core infrastructure - runs on top of Zephyr zephyr_library_sources( ${SOF_SRC_PATH}/schedule/ll_schedule.c + ${SOF_SRC_PATH}/drivers/interrupt.c ) set(PLATFORM "imx8") diff --git a/zephyr/wrapper.c b/zephyr/wrapper.c index cd39a1173a68..cf4a6b3292d0 100644 --- a/zephyr/wrapper.c +++ b/zephyr/wrapper.c @@ -255,28 +255,6 @@ void heap_trace_all(int force) const char irq_name_level2[] = "level2"; const char irq_name_level5[] = "level5"; -/* - * CAVS IRQs are multilevel whereas BYT and BDW are DSP level only. - * - * For i.MX we use the IRQ_STEER - */ -int interrupt_get_irq(unsigned int irq, const char *cascade) -{ -#if CONFIG_SOC_SERIES_INTEL_ADSP_BAYTRAIL ||\ - CONFIG_SOC_SERIES_INTEL_ADSP_BROADWELL || \ - CONFIG_IMX || \ - CONFIG_LIBRARY - return irq; -#else - if (cascade == irq_name_level2) - return SOC_AGGREGATE_IRQ(irq, IRQ_NUM_EXT_LEVEL2); - if (cascade == irq_name_level5) - return SOC_AGGREGATE_IRQ(irq, IRQ_NUM_EXT_LEVEL5); - - return SOC_AGGREGATE_IRQ(0, irq); -#endif -} - int interrupt_register(uint32_t irq, void(*handler)(void *arg), void *arg) { #ifdef CONFIG_DYNAMIC_INTERRUPTS @@ -319,6 +297,29 @@ uint32_t interrupt_disable(uint32_t irq, void *arg) } #endif +/* + * i.MX uses the IRQ_STEER + */ +#if !CONFIG_IMX +/* + * CAVS IRQs are multilevel whereas BYT and BDW are DSP level only. + */ +int interrupt_get_irq(unsigned int irq, const char *cascade) +{ +#if CONFIG_SOC_SERIES_INTEL_ADSP_BAYTRAIL ||\ + CONFIG_SOC_SERIES_INTEL_ADSP_BROADWELL || \ + CONFIG_LIBRARY + return irq; +#else + if (cascade == irq_name_level2) + return SOC_AGGREGATE_IRQ(irq, IRQ_NUM_EXT_LEVEL2); + if (cascade == irq_name_level5) + return SOC_AGGREGATE_IRQ(irq, IRQ_NUM_EXT_LEVEL5); + + return SOC_AGGREGATE_IRQ(0, irq); +#endif +} + void interrupt_mask(uint32_t irq, unsigned int cpu) { /* TODO: how do we mask on other cores with Zephyr APIs */ @@ -343,6 +344,7 @@ void platform_interrupt_clear(uint32_t irq, uint32_t mask) { /* handled by zephyr - needed for linkage */ } +#endif /* * Timers. From 86c66f7bba8cde8c31713ec861023b57ff707d95 Mon Sep 17 00:00:00 2001 From: Iuliana Prodan Date: Tue, 20 Jul 2021 22:24:43 +0300 Subject: [PATCH 4/5] zephyr: wrapper: add notifier_register(ipc_send_queued_msg) for SOF_SCHEDULE_LL_DMA In XTOS SOF, ipc_send_queued_msg() is run by task_main_primary_core(). In Zephyr we need to schedule ipc_send_queued_msg() using a notifier triggered by the periodic ll_scheduler. This is similar to commit c194125b83c2 ("zephyr: add notifier_register(ipc_send_queued_msg) in task_main_start()") For i.MX we need to use this temporary fix for SOF_SCHEDULE_LL_DMA, also. Signed-off-by: Iuliana Prodan --- zephyr/wrapper.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/zephyr/wrapper.c b/zephyr/wrapper.c index cf4a6b3292d0..9128d6371afb 100644 --- a/zephyr/wrapper.c +++ b/zephyr/wrapper.c @@ -611,8 +611,14 @@ int task_main_start(struct sof *sof) /* init pipeline position offsets */ pipeline_posn_init(sof); +#if defined(CONFIG_IMX) +#define SOF_IPC_QUEUED_DOMAIN SOF_SCHEDULE_LL_DMA +#else +#define SOF_IPC_QUEUED_DOMAIN SOF_SCHEDULE_LL_TIMER +#endif + /* Temporary fix for issue #4356 */ - (void)notifier_register(NULL, scheduler_get_data(SOF_SCHEDULE_LL_TIMER), + (void)notifier_register(NULL, scheduler_get_data(SOF_IPC_QUEUED_DOMAIN), NOTIFIER_ID_LL_POST_RUN, ipc_send_queued_callback, 0); From 111a1e51d3d2fcdc6009a6a8ec642133f15da9c0 Mon Sep 17 00:00:00 2001 From: Iuliana Prodan Date: Mon, 26 Jul 2021 17:28:10 +0300 Subject: [PATCH 5/5] xtensa-build-zephyr: add imx8 platform Add imx8 platform for local testing. TODO: Update xtensa-build-zephyr.sh when Zephyr repo is updated with imx8 support. Signed-off-by: Iuliana Prodan --- scripts/xtensa-build-zephyr.sh | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/scripts/xtensa-build-zephyr.sh b/scripts/xtensa-build-zephyr.sh index 1ed7e1e88af8..6c70202cb0c9 100755 --- a/scripts/xtensa-build-zephyr.sh +++ b/scripts/xtensa-build-zephyr.sh @@ -114,6 +114,10 @@ build() PLAT_CONFIG='intel_adsp_cavs25' RIMAGE_KEY=modules/audio/sof/keys/otc_private_key_3k.pem ;; + imx8) + PLAT_CONFIG='nxp_adsp_imx8' + RIMAGE_KEY='' # no key needed for imx8 + ;; *) echo "Unsupported platform: $platform" exit 1