From a278fa029aaf4eacab4de83cd98f87744a2d8271 Mon Sep 17 00:00:00 2001 From: Kai Vehmanen Date: Thu, 18 Apr 2024 12:36:50 +0300 Subject: [PATCH 1/7] ipc4: base_fw_platform: fix typo in doxygen Fix spelling in platform_basefw_hw_config() documentation. Signed-off-by: Kai Vehmanen --- src/include/ipc4/base_fw_platform.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/include/ipc4/base_fw_platform.h b/src/include/ipc4/base_fw_platform.h index d653b1997d50..de82bc1e1929 100644 --- a/src/include/ipc4/base_fw_platform.h +++ b/src/include/ipc4/base_fw_platform.h @@ -17,7 +17,7 @@ * \brief Platform specific routine to add data tuples to HW_CONFIG * structure sent to host via IPC. * \param[out] data_offset data offset after tuples added - * \parma[in] data pointer where to add new entries + * \param[in] data pointer where to add new entries * \return 0 if successful, error code otherwise. */ int platform_basefw_hw_config(uint32_t *data_offset, char *data); From 6132fe19daf82cfa6f0771c94ed940dc1b52a745 Mon Sep 17 00:00:00 2001 From: Kai Vehmanen Date: Fri, 12 Apr 2024 12:03:47 +0300 Subject: [PATCH 2/7] audio: base_fw: add platform layer to fw_config data Some of the IPC4 FW_CONFIG fields are platform specific and cannot be filled with generic code. Handle this data by adding a call to platform_basefw_fw_config() and add an implementation for all current platforms with IPC4 support. Signed-off-by: Kai Vehmanen --- src/audio/base_fw.c | 16 ++++++---------- src/include/ipc4/base_fw_platform.h | 9 +++++++++ src/platform/intel/ace/lib/base_fw_platform.c | 18 ++++++++++++++++++ src/platform/posix/base_fw_platform.c | 7 +++++++ 4 files changed, 40 insertions(+), 10 deletions(-) diff --git a/src/audio/base_fw.c b/src/audio/base_fw.c index daeaf7927ee0..8f781884c9c0 100644 --- a/src/audio/base_fw.c +++ b/src/audio/base_fw.c @@ -59,6 +59,7 @@ static int basefw_config(uint32_t *data_offset, char *data) uint16_t version[4] = {SOF_MAJOR, SOF_MINOR, SOF_MICRO, SOF_BUILD}; struct sof_tlv *tuple = (struct sof_tlv *)data; struct ipc4_scheduler_config sche_cfg; + uint32_t plat_data_offset = 0; uint32_t log_bytes_size = 0; tlv_value_set(tuple, IPC4_FW_VERSION_FW_CFG, sizeof(version), version); @@ -74,15 +75,6 @@ static int basefw_config(uint32_t *data_offset, char *data) IPC4_SLOW_CLOCK_FREQ_HZ_FW_CFG, clock_get_freq(CPU_LOWEST_FREQ_IDX)); - tuple = tlv_next(tuple); - tlv_value_uint32_set(tuple, IPC4_SLOW_CLOCK_FREQ_HZ_FW_CFG, IPC4_ALH_CAVS_1_8); - - tuple = tlv_next(tuple); - tlv_value_uint32_set(tuple, IPC4_UAOL_SUPPORT, 0); - - tuple = tlv_next(tuple); - tlv_value_uint32_set(tuple, IPC4_ALH_SUPPORT_LEVEL_FW_CFG, IPC4_ALH_CAVS_1_8); - tuple = tlv_next(tuple); tlv_value_uint32_set(tuple, IPC4_DL_MAILBOX_BYTES_FW_CFG, MAILBOX_HOSTBOX_SIZE); @@ -137,7 +129,11 @@ static int basefw_config(uint32_t *data_offset, char *data) IS_ENABLED(CONFIG_ADSP_IMR_CONTEXT_SAVE)); tuple = tlv_next(tuple); - *data_offset = (int)((char *)tuple - data); + + /* add platform specific tuples */ + platform_basefw_fw_config(&plat_data_offset, (char *)tuple); + + *data_offset = (int)((char *)tuple - data) + plat_data_offset; return 0; } diff --git a/src/include/ipc4/base_fw_platform.h b/src/include/ipc4/base_fw_platform.h index de82bc1e1929..efd0a63ea50f 100644 --- a/src/include/ipc4/base_fw_platform.h +++ b/src/include/ipc4/base_fw_platform.h @@ -13,6 +13,15 @@ #ifndef __SOF_IPC4_BASE_FW_PLATFORM_H__ #define __SOF_IPC4_BASE_FW_PLATFORM_H__ +/** + * \brief Platform specific routine to add data tuples to FW_CONFIG + * structure sent to host via IPC. + * \param[out] data_offset data offset after tuples added + * \param[in] data pointer where to add new entries + * \return 0 if successful, error code otherwise. + */ +int platform_basefw_fw_config(uint32_t *data_offset, char *data); + /** * \brief Platform specific routine to add data tuples to HW_CONFIG * structure sent to host via IPC. diff --git a/src/platform/intel/ace/lib/base_fw_platform.c b/src/platform/intel/ace/lib/base_fw_platform.c index 47dd97b809e3..0722c049e14a 100644 --- a/src/platform/intel/ace/lib/base_fw_platform.c +++ b/src/platform/intel/ace/lib/base_fw_platform.c @@ -9,6 +9,24 @@ #include #include +int platform_basefw_fw_config(uint32_t *data_offset, char *data) +{ + struct sof_tlv *tuple = (struct sof_tlv *)data; + + tlv_value_uint32_set(tuple, IPC4_SLOW_CLOCK_FREQ_HZ_FW_CFG, IPC4_ALH_CAVS_1_8); + + tuple = tlv_next(tuple); + tlv_value_uint32_set(tuple, IPC4_UAOL_SUPPORT, 0); + + tuple = tlv_next(tuple); + tlv_value_uint32_set(tuple, IPC4_ALH_SUPPORT_LEVEL_FW_CFG, IPC4_ALH_CAVS_1_8); + + tuple = tlv_next(tuple); + *data_offset = (int)((char *)tuple - data); + + return 0; +} + int platform_basefw_hw_config(uint32_t *data_offset, char *data) { struct sof_tlv *tuple = (struct sof_tlv *)data; diff --git a/src/platform/posix/base_fw_platform.c b/src/platform/posix/base_fw_platform.c index 16981e6ff2a7..7092039b7f13 100644 --- a/src/platform/posix/base_fw_platform.c +++ b/src/platform/posix/base_fw_platform.c @@ -8,6 +8,13 @@ #include #include +int platform_basefw_fw_config(uint32_t *data_offset, char *data) +{ + *data_offset = 0; + + return 0; +} + int platform_basefw_hw_config(uint32_t *data_offset, char *data) { *data_offset = 0; From 0bd75c03addaf8485e7df68b31a6a7c29b9b7ea3 Mon Sep 17 00:00:00 2001 From: Kai Vehmanen Date: Thu, 18 Apr 2024 14:37:00 +0300 Subject: [PATCH 3/7] ipc4: base_fw: add support for get/set large config extensions Add support to handle platform specific extensions with platform_basefw_get_large_config() and platform_basefw_set_large_config(). These functions are called when get/set handled is called with a parameter type not handled in generic code. Signed-off-by: Kai Vehmanen --- src/audio/base_fw.c | 6 ++-- src/include/ipc4/base_fw_platform.h | 30 +++++++++++++++++++ src/platform/intel/ace/lib/base_fw_platform.c | 20 +++++++++++++ src/platform/posix/base_fw_platform.c | 21 +++++++++++++ 4 files changed, 75 insertions(+), 2 deletions(-) diff --git a/src/audio/base_fw.c b/src/audio/base_fw.c index 8f781884c9c0..498246a93499 100644 --- a/src/audio/base_fw.c +++ b/src/audio/base_fw.c @@ -664,7 +664,8 @@ static int basefw_get_large_config(struct comp_dev *dev, break; } - return -EINVAL; + return platform_basefw_get_large_config(dev, param_id, first_block, last_block, + data_offset, data); }; static int basefw_set_large_config(struct comp_dev *dev, @@ -693,7 +694,8 @@ static int basefw_set_large_config(struct comp_dev *dev, break; } - return IPC4_UNKNOWN_MESSAGE_TYPE; + return platform_basefw_set_large_config(dev, param_id, first_block, last_block, + data_offset, data); }; static const struct comp_driver comp_basefw = { diff --git a/src/include/ipc4/base_fw_platform.h b/src/include/ipc4/base_fw_platform.h index efd0a63ea50f..4fb7f70fd7fc 100644 --- a/src/include/ipc4/base_fw_platform.h +++ b/src/include/ipc4/base_fw_platform.h @@ -13,6 +13,12 @@ #ifndef __SOF_IPC4_BASE_FW_PLATFORM_H__ #define __SOF_IPC4_BASE_FW_PLATFORM_H__ +#include +#include +#include + +struct comp_dev; + /** * \brief Platform specific routine to add data tuples to FW_CONFIG * structure sent to host via IPC. @@ -38,4 +44,28 @@ int platform_basefw_hw_config(uint32_t *data_offset, char *data); */ struct sof_man_fw_desc *platform_base_fw_get_manifest(void); +/** + * \brief Implement platform specific parameter for basefw module. + * This function is called for parameters not handled by + * generic base_fw code. + */ +int platform_basefw_get_large_config(struct comp_dev *dev, + uint32_t param_id, + bool first_block, + bool last_block, + uint32_t *data_offset, + char *data); + +/** + * \brief Implement platform specific parameter for basefw module. + * This function is called for parameters not handled by + * generic base_fw code. + */ +int platform_basefw_set_large_config(struct comp_dev *dev, + uint32_t param_id, + bool first_block, + bool last_block, + uint32_t data_offset, + const char *data); + #endif /* __SOF_IPC4_BASE_FW_PLATFORM_H__ */ diff --git a/src/platform/intel/ace/lib/base_fw_platform.c b/src/platform/intel/ace/lib/base_fw_platform.c index 0722c049e14a..81ed85ef5d54 100644 --- a/src/platform/intel/ace/lib/base_fw_platform.c +++ b/src/platform/intel/ace/lib/base_fw_platform.c @@ -57,3 +57,23 @@ struct sof_man_fw_desc *platform_base_fw_get_manifest(void) return desc; } + +int platform_basefw_get_large_config(struct comp_dev *dev, + uint32_t param_id, + bool first_block, + bool last_block, + uint32_t *data_offset, + char *data) +{ + return -EINVAL; +} + +int platform_basefw_set_large_config(struct comp_dev *dev, + uint32_t param_id, + bool first_block, + bool last_block, + uint32_t data_offset, + const char *data) +{ + return IPC4_UNKNOWN_MESSAGE_TYPE; +} diff --git a/src/platform/posix/base_fw_platform.c b/src/platform/posix/base_fw_platform.c index 7092039b7f13..4ec98d952855 100644 --- a/src/platform/posix/base_fw_platform.c +++ b/src/platform/posix/base_fw_platform.c @@ -6,6 +6,7 @@ #include #include +#include #include int platform_basefw_fw_config(uint32_t *data_offset, char *data) @@ -28,3 +29,23 @@ struct sof_man_fw_desc *platform_base_fw_get_manifest(void) return desc; } + +int platform_basefw_get_large_config(struct comp_dev *dev, + uint32_t param_id, + bool first_block, + bool last_block, + uint32_t *data_offset, + char *data) +{ + return -EINVAL; +} + +int platform_basefw_set_large_config(struct comp_dev *dev, + uint32_t param_id, + bool first_block, + bool last_block, + uint32_t data_offset, + const char *data) +{ + return IPC4_UNKNOWN_MESSAGE_TYPE; +} From c5cfc774dac33cc06d3e1a442d00a501b3a8a2e6 Mon Sep 17 00:00:00 2001 From: Kai Vehmanen Date: Thu, 18 Apr 2024 14:47:01 +0300 Subject: [PATCH 4/7] audio: base_fw: move L1_EXIT control to platform specific code Move the Intel specific L1_EXIT control handling from base_fw.c to Intel specific platform code. Signed-off-by: Kai Vehmanen --- src/audio/base_fw.c | 41 --------------- src/platform/intel/ace/lib/base_fw_platform.c | 52 +++++++++++++++++++ 2 files changed, 52 insertions(+), 41 deletions(-) diff --git a/src/audio/base_fw.c b/src/audio/base_fw.c index 498246a93499..9eb32f7a20a3 100644 --- a/src/audio/base_fw.c +++ b/src/audio/base_fw.c @@ -17,9 +17,6 @@ #include #include #include -#if defined(CONFIG_SOC_SERIES_INTEL_ADSP_ACE) -#include -#endif #include #include #include @@ -475,42 +472,6 @@ static int basefw_libraries_info_get(uint32_t *data_offset, char *data) return 0; } -static int fw_config_set_force_l1_exit(const struct sof_tlv *tlv) -{ -#if defined(CONFIG_SOC_SERIES_INTEL_ADSP_ACE) - const uint32_t force = tlv->value[0]; - - if (force) { - tr_info(&basefw_comp_tr, "FW config set force dmi l0 state"); - intel_adsp_force_dmi_l0_state(); - } else { - tr_info(&basefw_comp_tr, "FW config set allow dmi l1 state"); - intel_adsp_allow_dmi_l1_state(); - } - - return 0; -#else - return IPC4_UNAVAILABLE; -#endif -} - -static int basefw_set_fw_config(bool first_block, - bool last_block, - uint32_t data_offset, - const char *data) -{ - const struct sof_tlv *tlv = (const struct sof_tlv *)data; - - switch (tlv->type) { - case IPC4_DMI_FORCE_L1_EXIT: - return fw_config_set_force_l1_exit(tlv); - default: - break; - } - tr_warn(&basefw_comp_tr, "returning success for Set FW_CONFIG without handling it"); - return 0; -} - int schedulers_info_get(uint32_t *data_off_size, char *data, uint32_t core_id) @@ -676,8 +637,6 @@ static int basefw_set_large_config(struct comp_dev *dev, const char *data) { switch (param_id) { - case IPC4_FW_CONFIG: - return basefw_set_fw_config(first_block, last_block, data_offset, data); case IPC4_PERF_MEASUREMENTS_STATE: return set_perf_meas_state(data); case IPC4_SYSTEM_TIME: diff --git a/src/platform/intel/ace/lib/base_fw_platform.c b/src/platform/intel/ace/lib/base_fw_platform.c index 81ed85ef5d54..62beebcf0826 100644 --- a/src/platform/intel/ace/lib/base_fw_platform.c +++ b/src/platform/intel/ace/lib/base_fw_platform.c @@ -4,11 +4,20 @@ // // Author: Kai Vehmanen +#include + #include #include #include + +#if defined(CONFIG_SOC_SERIES_INTEL_ADSP_ACE) +#include +#endif + #include +LOG_MODULE_REGISTER(basefw_platform, CONFIG_SOF_LOG_LEVEL); + int platform_basefw_fw_config(uint32_t *data_offset, char *data) { struct sof_tlv *tuple = (struct sof_tlv *)data; @@ -68,6 +77,42 @@ int platform_basefw_get_large_config(struct comp_dev *dev, return -EINVAL; } +static int fw_config_set_force_l1_exit(const struct sof_tlv *tlv) +{ +#if defined(CONFIG_SOC_SERIES_INTEL_ADSP_ACE) + const uint32_t force = tlv->value[0]; + + if (force) { + tr_info(&basefw_comp_tr, "FW config set force dmi l0 state"); + intel_adsp_force_dmi_l0_state(); + } else { + tr_info(&basefw_comp_tr, "FW config set allow dmi l1 state"); + intel_adsp_allow_dmi_l1_state(); + } + + return 0; +#else + return IPC4_UNAVAILABLE; +#endif +} + +static int basefw_set_fw_config(bool first_block, + bool last_block, + uint32_t data_offset, + const char *data) +{ + const struct sof_tlv *tlv = (const struct sof_tlv *)data; + + switch (tlv->type) { + case IPC4_DMI_FORCE_L1_EXIT: + return fw_config_set_force_l1_exit(tlv); + default: + break; + } + tr_warn(&basefw_comp_tr, "returning success for Set FW_CONFIG without handling it"); + return 0; +} + int platform_basefw_set_large_config(struct comp_dev *dev, uint32_t param_id, bool first_block, @@ -75,5 +120,12 @@ int platform_basefw_set_large_config(struct comp_dev *dev, uint32_t data_offset, const char *data) { + switch (param_id) { + case IPC4_FW_CONFIG: + return basefw_set_fw_config(first_block, last_block, data_offset, data); + default: + break; + } + return IPC4_UNKNOWN_MESSAGE_TYPE; } From 9ea8bc94896dd32f395a50e1cb9a8c661d075891 Mon Sep 17 00:00:00 2001 From: Kai Vehmanen Date: Thu, 18 Apr 2024 14:57:16 +0300 Subject: [PATCH 5/7] audio: base_fw: move IPC4_MEMORY_STATE_INFO_GET code to platform The implementation for IPC4_MEMORY_STATE_INFO_GET requires reading direct register contents to fill out the structure, so this is by definition platform specific code. Move this to platform implementation. Signed-off-by: Kai Vehmanen --- src/audio/base_fw.c | 86 ------------------- src/platform/intel/ace/lib/base_fw_platform.c | 83 ++++++++++++++++++ 2 files changed, 83 insertions(+), 86 deletions(-) diff --git a/src/audio/base_fw.c b/src/audio/base_fw.c index 9eb32f7a20a3..7ea70de77d2f 100644 --- a/src/audio/base_fw.c +++ b/src/audio/base_fw.c @@ -36,11 +36,6 @@ #endif #include -/* TODO: Remove platform-specific code, see https://github.com/thesofproject/sof/issues/7549 */ -#if defined(CONFIG_SOC_SERIES_INTEL_ADSP_ACE) || defined(CONFIG_INTEL_ADSP_CAVS) -# define INTEL_ADSP 1 -#endif - LOG_MODULE_REGISTER(basefw, CONFIG_SOF_LOG_LEVEL); /* 0e398c32-5ade-ba4b-93b1-c50432280ee4 */ @@ -166,85 +161,6 @@ static int basefw_hw_config(uint32_t *data_offset, char *data) return 0; } -/* There are two types of sram memory : high power mode sram and - * low power mode sram. This function retures memory size in page - * , memory bank power and usage status of each sram to host driver - */ -static int basefw_mem_state_info(uint32_t *data_offset, char *data) -{ - struct sof_tlv *tuple = (struct sof_tlv *)data; - struct ipc4_sram_state_info info; - uint32_t *tuple_data; - uint32_t index; - uint32_t size; - uint16_t *ptr; - int i; - - /* set hpsram */ - info.free_phys_mem_pages = SRAM_BANK_SIZE * PLATFORM_HPSRAM_EBB_COUNT / HOST_PAGE_SIZE; - info.ebb_state_dword_count = SOF_DIV_ROUND_UP(PLATFORM_HPSRAM_EBB_COUNT, 32); - info.page_alloc_struct.page_alloc_count = PLATFORM_HPSRAM_EBB_COUNT; - size = sizeof(info) + info.ebb_state_dword_count * sizeof(uint32_t) + - info.page_alloc_struct.page_alloc_count * sizeof(uint32_t); - size = ALIGN(size, 4); - /* size is also saved as tuple length */ - tuple_data = rballoc(0, SOF_MEM_CAPS_RAM, size); - - /* save memory info in data array since info length is variable */ - index = 0; - tuple_data[index++] = info.free_phys_mem_pages; - tuple_data[index++] = info.ebb_state_dword_count; - for (i = 0; i < info.ebb_state_dword_count; i++) { -#ifdef INTEL_ADSP - tuple_data[index + i] = io_reg_read(SHIM_HSPGCTL(i)); -#else - tuple_data[index + i] = 0; -#endif - } - index += info.ebb_state_dword_count; - - tuple_data[index++] = info.page_alloc_struct.page_alloc_count; - /* TLB is not supported now, so all pages are marked as occupied - * TODO: add page-size allocator and TLB support - */ - ptr = (uint16_t *)(tuple_data + index); - for (i = 0; i < info.page_alloc_struct.page_alloc_count; i++) - ptr[i] = 0xfff; - - tlv_value_set(tuple, IPC4_HPSRAM_STATE, size, tuple_data); - - /* set lpsram */ - info.free_phys_mem_pages = 0; - info.ebb_state_dword_count = SOF_DIV_ROUND_UP(PLATFORM_LPSRAM_EBB_COUNT, 32); - info.page_alloc_struct.page_alloc_count = PLATFORM_LPSRAM_EBB_COUNT; - size = sizeof(info) + info.ebb_state_dword_count * sizeof(uint32_t) + - info.page_alloc_struct.page_alloc_count * sizeof(uint32_t); - size = ALIGN(size, 4); - - index = 0; - tuple_data[index++] = info.free_phys_mem_pages; - tuple_data[index++] = info.ebb_state_dword_count; -#ifdef INTEL_ADSP - tuple_data[index++] = io_reg_read(LSPGCTL); -#else - tuple_data[index++] = 0; -#endif - tuple_data[index++] = info.page_alloc_struct.page_alloc_count; - ptr = (uint16_t *)(tuple_data + index); - for (i = 0; i < info.page_alloc_struct.page_alloc_count; i++) - ptr[i] = 0xfff; - - tuple = tlv_next(tuple); - tlv_value_set(tuple, IPC4_LPSRAM_STATE, size, tuple_data); - - /* calculate total tuple size */ - tuple = tlv_next(tuple); - *data_offset = (int)((char *)tuple - data); - - rfree(tuple_data); - return 0; -} - static log_timestamp_t basefw_get_timestamp(void) { return sof_cycle_get_64() + global_cycle_delta; @@ -589,8 +505,6 @@ static int basefw_get_large_config(struct comp_dev *dev, return basefw_config(data_offset, data); case IPC4_HW_CONFIG_GET: return basefw_hw_config(data_offset, data); - case IPC4_MEMORY_STATE_INFO_GET: - return basefw_mem_state_info(data_offset, data); case IPC4_SYSTEM_TIME: return basefw_get_system_time(data_offset, data); case IPC4_EXTENDED_SYSTEM_TIME: diff --git a/src/platform/intel/ace/lib/base_fw_platform.c b/src/platform/intel/ace/lib/base_fw_platform.c index 62beebcf0826..da2d8e4f4c0f 100644 --- a/src/platform/intel/ace/lib/base_fw_platform.c +++ b/src/platform/intel/ace/lib/base_fw_platform.c @@ -67,6 +67,77 @@ struct sof_man_fw_desc *platform_base_fw_get_manifest(void) return desc; } +/* There are two types of sram memory : high power mode sram and + * low power mode sram. This function retures memory size in page + * , memory bank power and usage status of each sram to host driver + */ +static int basefw_mem_state_info(uint32_t *data_offset, char *data) +{ + struct sof_tlv *tuple = (struct sof_tlv *)data; + struct ipc4_sram_state_info info; + uint32_t *tuple_data; + uint32_t index; + uint32_t size; + uint16_t *ptr; + int i; + + /* set hpsram */ + info.free_phys_mem_pages = SRAM_BANK_SIZE * PLATFORM_HPSRAM_EBB_COUNT / HOST_PAGE_SIZE; + info.ebb_state_dword_count = SOF_DIV_ROUND_UP(PLATFORM_HPSRAM_EBB_COUNT, 32); + info.page_alloc_struct.page_alloc_count = PLATFORM_HPSRAM_EBB_COUNT; + size = sizeof(info) + info.ebb_state_dword_count * sizeof(uint32_t) + + info.page_alloc_struct.page_alloc_count * sizeof(uint32_t); + size = ALIGN(size, 4); + /* size is also saved as tuple length */ + tuple_data = rballoc(0, SOF_MEM_CAPS_RAM, size); + + /* save memory info in data array since info length is variable */ + index = 0; + tuple_data[index++] = info.free_phys_mem_pages; + tuple_data[index++] = info.ebb_state_dword_count; + for (i = 0; i < info.ebb_state_dword_count; i++) { + tuple_data[index + i] = io_reg_read(SHIM_HSPGCTL(i)); + } + index += info.ebb_state_dword_count; + + tuple_data[index++] = info.page_alloc_struct.page_alloc_count; + /* TLB is not supported now, so all pages are marked as occupied + * TODO: add page-size allocator and TLB support + */ + ptr = (uint16_t *)(tuple_data + index); + for (i = 0; i < info.page_alloc_struct.page_alloc_count; i++) + ptr[i] = 0xfff; + + tlv_value_set(tuple, IPC4_HPSRAM_STATE, size, tuple_data); + + /* set lpsram */ + info.free_phys_mem_pages = 0; + info.ebb_state_dword_count = SOF_DIV_ROUND_UP(PLATFORM_LPSRAM_EBB_COUNT, 32); + info.page_alloc_struct.page_alloc_count = PLATFORM_LPSRAM_EBB_COUNT; + size = sizeof(info) + info.ebb_state_dword_count * sizeof(uint32_t) + + info.page_alloc_struct.page_alloc_count * sizeof(uint32_t); + size = ALIGN(size, 4); + + index = 0; + tuple_data[index++] = info.free_phys_mem_pages; + tuple_data[index++] = info.ebb_state_dword_count; + tuple_data[index++] = io_reg_read(LSPGCTL); + tuple_data[index++] = info.page_alloc_struct.page_alloc_count; + ptr = (uint16_t *)(tuple_data + index); + for (i = 0; i < info.page_alloc_struct.page_alloc_count; i++) + ptr[i] = 0xfff; + + tuple = tlv_next(tuple); + tlv_value_set(tuple, IPC4_LPSRAM_STATE, size, tuple_data); + + /* calculate total tuple size */ + tuple = tlv_next(tuple); + *data_offset = (int)((char *)tuple - data); + + rfree(tuple_data); + return 0; +} + int platform_basefw_get_large_config(struct comp_dev *dev, uint32_t param_id, bool first_block, @@ -74,6 +145,18 @@ int platform_basefw_get_large_config(struct comp_dev *dev, uint32_t *data_offset, char *data) { + /* We can use extended param id for both extended and standard param id */ + union ipc4_extended_param_id extended_param_id; + + extended_param_id.full = param_id; + + switch (extended_param_id.part.parameter_type) { + case IPC4_MEMORY_STATE_INFO_GET: + return basefw_mem_state_info(data_offset, data); + default: + break; + } + return -EINVAL; } From a24452d7f0ad15619fc4644876f2418f29a4fd61 Mon Sep 17 00:00:00 2001 From: Kai Vehmanen Date: Thu, 18 Apr 2024 16:37:21 +0300 Subject: [PATCH 6/7] audio: base_fw: move IPC4_EXTENDED_SYSTEM_TIME to platform code Move implementation of IPC4_EXTENDED_SYSTEM_TIME from generic to platform specific code. The implementation depends on specific ART counter that is not available on all platforms, so it is better to handle this in platform specific code. Signed-off-by: Kai Vehmanen --- src/audio/base_fw.c | 77 ++----------------- src/include/ipc4/base_fw.h | 2 + src/platform/intel/ace/lib/base_fw_platform.c | 76 +++++++++++++++++- 3 files changed, 82 insertions(+), 73 deletions(-) diff --git a/src/audio/base_fw.c b/src/audio/base_fw.c index 7ea70de77d2f..413f6a7d46b2 100644 --- a/src/audio/base_fw.c +++ b/src/audio/base_fw.c @@ -30,10 +30,6 @@ #include "adsp_debug_window.h" #endif -#if CONFIG_ACE_V1X_ART_COUNTER || CONFIG_ACE_V1X_RTC_COUNTER -#include -#include -#endif #include LOG_MODULE_REGISTER(basefw, CONFIG_SOF_LOG_LEVEL); @@ -161,6 +157,11 @@ static int basefw_hw_config(uint32_t *data_offset, char *data) return 0; } +struct ipc4_system_time_info *basefw_get_system_time_info(void) +{ + return &global_system_time_info; +} + static log_timestamp_t basefw_get_timestamp(void) { return sof_cycle_get_64() + global_cycle_delta; @@ -215,63 +216,6 @@ static uint32_t basefw_get_system_time(uint32_t *data_offset, char *data) return IPC4_SUCCESS; } -static uint32_t basefw_get_ext_system_time(uint32_t *data_offset, char *data) -{ -#if CONFIG_ACE_V1X_ART_COUNTER && CONFIG_ACE_V1X_RTC_COUNTER - struct ipc4_ext_system_time *ext_system_time = (struct ipc4_ext_system_time *)(data); - struct ipc4_ext_system_time ext_system_time_data = {0}; - - uint64_t host_time = ((uint64_t)global_system_time_info.host_time.val_u << 32) - | (uint64_t)global_system_time_info.host_time.val_l; - uint64_t dsp_time = ((uint64_t)global_system_time_info.dsp_time.val_u << 32) - | (uint64_t)global_system_time_info.dsp_time.val_l; - - if (host_time == 0 || dsp_time == 0) - return IPC4_INVALID_RESOURCE_STATE; - - uint64_t art = 0; - uint64_t wallclk = 0; - uint64_t rtc = 0; - - const struct device *dev = DEVICE_DT_GET(DT_NODELABEL(ace_art_counter)); - - if (!dev) { - LOG_DBG("board: ART counter device binding failed"); - return IPC4_MOD_NOT_INITIALIZED; - } - - counter_get_value_64(dev, &art); - - wallclk = sof_cycle_get_64(); - ext_system_time_data.art_l = (uint32_t)art; - ext_system_time_data.art_u = (uint32_t)(art >> 32); - uint64_t delta = (wallclk - dsp_time) / (CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC / 1000000); - - uint64_t new_host_time = (host_time + delta); - - ext_system_time_data.utc_l = (uint32_t)new_host_time; - ext_system_time_data.utc_u = (uint32_t)(new_host_time >> 32); - - dev = DEVICE_DT_GET(DT_NODELABEL(ace_rtc_counter)); - - if (!dev) { - LOG_DBG("board: RTC counter device binding failed"); - return IPC4_MOD_NOT_INITIALIZED; - } - - counter_get_value_64(dev, &rtc); - ext_system_time_data.rtc_l = (uint32_t)rtc; - ext_system_time_data.rtc_u = (uint32_t)(rtc >> 32); - - memcpy_s(ext_system_time, sizeof(ext_system_time), &ext_system_time_data, - sizeof(ext_system_time)); - *data_offset = sizeof(struct ipc4_ext_system_time); - - return IPC4_SUCCESS; -#endif - return IPC4_UNAVAILABLE; -} - static int basefw_register_kcps(bool first_block, bool last_block, uint32_t data_offset_or_size, @@ -489,8 +433,6 @@ static int basefw_get_large_config(struct comp_dev *dev, extended_param_id.full = param_id; - uint32_t ret = -EINVAL; - switch (extended_param_id.part.parameter_type) { case IPC4_PERF_MEASUREMENTS_STATE: case IPC4_GLOBAL_PERF_DATA: @@ -507,15 +449,6 @@ static int basefw_get_large_config(struct comp_dev *dev, return basefw_hw_config(data_offset, data); case IPC4_SYSTEM_TIME: return basefw_get_system_time(data_offset, data); - case IPC4_EXTENDED_SYSTEM_TIME: - ret = basefw_get_ext_system_time(data_offset, data); - if (ret == IPC4_UNAVAILABLE) { - tr_warn(&basefw_comp_tr, "returning success for get host EXTENDED_SYSTEM_TIME without handling it"); - return 0; - } else { - return ret; - } - break; case IPC4_POWER_STATE_INFO_GET: return basefw_power_state_info_get(data_offset, data); case IPC4_SCHEDULERS_INFO_GET: diff --git a/src/include/ipc4/base_fw.h b/src/include/ipc4/base_fw.h index 576672f3a1be..913f44a4fd06 100644 --- a/src/include/ipc4/base_fw.h +++ b/src/include/ipc4/base_fw.h @@ -726,4 +726,6 @@ struct schedulers_info { struct scheduler_props scheduler_info[]; } __packed __aligned(4); +struct ipc4_system_time_info *basefw_get_system_time_info(void); + #endif /* __SOF_IPC4_BASE_FW_H__ */ diff --git a/src/platform/intel/ace/lib/base_fw_platform.c b/src/platform/intel/ace/lib/base_fw_platform.c index da2d8e4f4c0f..828845a4ea65 100644 --- a/src/platform/intel/ace/lib/base_fw_platform.c +++ b/src/platform/intel/ace/lib/base_fw_platform.c @@ -14,6 +14,11 @@ #include #endif +#if CONFIG_ACE_V1X_ART_COUNTER || CONFIG_ACE_V1X_RTC_COUNTER +#include +#include +#endif + #include LOG_MODULE_REGISTER(basefw_platform, CONFIG_SOF_LOG_LEVEL); @@ -138,6 +143,63 @@ static int basefw_mem_state_info(uint32_t *data_offset, char *data) return 0; } +static uint32_t basefw_get_ext_system_time(uint32_t *data_offset, char *data) +{ +#if CONFIG_ACE_V1X_ART_COUNTER && CONFIG_ACE_V1X_RTC_COUNTER + struct ipc4_ext_system_time *ext_system_time = (struct ipc4_ext_system_time *)(data); + struct ipc4_ext_system_time ext_system_time_data = {0}; + struct ipc4_system_time_info *time_info = basefw_get_system_time_info(); + uint64_t host_time = ((uint64_t)time_info->host_time.val_u << 32) + | (uint64_t)time_info->host_time.val_l; + uint64_t dsp_time = ((uint64_t)time_info->dsp_time.val_u << 32) + | (uint64_t)time_info->dsp_time.val_l; + + if (host_time == 0 || dsp_time == 0) + return IPC4_INVALID_RESOURCE_STATE; + + uint64_t art = 0; + uint64_t wallclk = 0; + uint64_t rtc = 0; + + const struct device *dev = DEVICE_DT_GET(DT_NODELABEL(ace_art_counter)); + + if (!dev) { + LOG_DBG("board: ART counter device binding failed"); + return IPC4_MOD_NOT_INITIALIZED; + } + + counter_get_value_64(dev, &art); + + wallclk = sof_cycle_get_64(); + ext_system_time_data.art_l = (uint32_t)art; + ext_system_time_data.art_u = (uint32_t)(art >> 32); + uint64_t delta = (wallclk - dsp_time) / (CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC / 1000000); + + uint64_t new_host_time = (host_time + delta); + + ext_system_time_data.utc_l = (uint32_t)new_host_time; + ext_system_time_data.utc_u = (uint32_t)(new_host_time >> 32); + + dev = DEVICE_DT_GET(DT_NODELABEL(ace_rtc_counter)); + + if (!dev) { + LOG_DBG("board: RTC counter device binding failed"); + return IPC4_MOD_NOT_INITIALIZED; + } + + counter_get_value_64(dev, &rtc); + ext_system_time_data.rtc_l = (uint32_t)rtc; + ext_system_time_data.rtc_u = (uint32_t)(rtc >> 32); + + memcpy_s(ext_system_time, sizeof(ext_system_time), &ext_system_time_data, + sizeof(ext_system_time)); + *data_offset = sizeof(struct ipc4_ext_system_time); + + return IPC4_SUCCESS; +#endif + return IPC4_UNAVAILABLE; +} + int platform_basefw_get_large_config(struct comp_dev *dev, uint32_t param_id, bool first_block, @@ -150,14 +212,26 @@ int platform_basefw_get_large_config(struct comp_dev *dev, extended_param_id.full = param_id; + uint32_t ret = -EINVAL; + switch (extended_param_id.part.parameter_type) { case IPC4_MEMORY_STATE_INFO_GET: return basefw_mem_state_info(data_offset, data); + case IPC4_EXTENDED_SYSTEM_TIME: + ret = basefw_get_ext_system_time(data_offset, data); + if (ret == IPC4_UNAVAILABLE) { + tr_warn(&basefw_comp_tr, + "returning success for get host EXTENDED_SYSTEM_TIME without handling it"); + return 0; + } else { + return ret; + } + break; default: break; } - return -EINVAL; + return ret; } static int fw_config_set_force_l1_exit(const struct sof_tlv *tlv) From 09bf0bc1feae787d702b24c1668998b1780cebc2 Mon Sep 17 00:00:00 2001 From: Kai Vehmanen Date: Thu, 18 Apr 2024 16:40:29 +0300 Subject: [PATCH 7/7] audio: base_fw: add missing copyright statement to banner Add missing copyright statement to file header. Signed-off-by: Kai Vehmanen --- src/audio/base_fw.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/audio/base_fw.c b/src/audio/base_fw.c index 413f6a7d46b2..7261e0c775eb 100644 --- a/src/audio/base_fw.c +++ b/src/audio/base_fw.c @@ -1,5 +1,7 @@ // SPDX-License-Identifier: BSD-3-Clause // +// Copyright(c) 2024 Intel Corporation. +// #include #include