Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

audio: base_fw: move platform specific code from base_fw.c #9060

Merged
222 changes: 14 additions & 208 deletions src/audio/base_fw.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
// SPDX-License-Identifier: BSD-3-Clause
//
// Copyright(c) 2024 Intel Corporation.
//

#include <sof/audio/component.h>
#include <sof/lib/memory.h>
Expand All @@ -17,9 +19,6 @@
#include <sof/lib_manager.h>
#include <rtos/init.h>
#include <platform/lib/clk.h>
#if defined(CONFIG_SOC_SERIES_INTEL_ADSP_ACE)
#include <intel_adsp_hda.h>
#endif
#include <sof/audio/module_adapter/module/generic.h>
#include <sof/schedule/dp_schedule.h>
#include <sof/schedule/ll_schedule.h>
Expand All @@ -33,17 +32,8 @@
#include "adsp_debug_window.h"
#endif

#if CONFIG_ACE_V1X_ART_COUNTER || CONFIG_ACE_V1X_RTC_COUNTER
#include <zephyr/device.h>
#include <zephyr/drivers/counter.h>
#endif
#include <zephyr/logging/log_ctrl.h>

/* 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 */
Expand All @@ -59,6 +49,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);
Expand All @@ -74,15 +65,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);

Expand Down Expand Up @@ -137,7 +119,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;
}
Expand Down Expand Up @@ -173,83 +159,9 @@ 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 ipc4_system_time_info *basefw_get_system_time_info(void)
{
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;
return &global_system_time_info;
}

static log_timestamp_t basefw_get_timestamp(void)
Expand Down Expand Up @@ -306,63 +218,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,
Expand Down Expand Up @@ -479,42 +334,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)
Expand Down Expand Up @@ -616,8 +435,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:
Expand All @@ -632,19 +449,8 @@ 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:
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:
Expand All @@ -668,7 +474,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,
Expand All @@ -679,8 +486,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:
Expand All @@ -697,7 +502,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 = {
Expand Down
2 changes: 2 additions & 0 deletions src/include/ipc4/base_fw.h
Original file line number Diff line number Diff line change
Expand Up @@ -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__ */
41 changes: 40 additions & 1 deletion src/include/ipc4/base_fw_platform.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,26 @@
#ifndef __SOF_IPC4_BASE_FW_PLATFORM_H__
#define __SOF_IPC4_BASE_FW_PLATFORM_H__

#include <errno.h>
#include <stdbool.h>
#include <stdint.h>

struct comp_dev;

/**
* \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.
* \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);
Expand All @@ -29,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__ */
Loading
Loading