99#include <ipc4/logging.h>
1010#include <sof_versions.h>
1111
12+ #if CONFIG_ACE_V1X_ART_COUNTER || CONFIG_ACE_V1X_RTC_COUNTER
13+ #include <zephyr/device.h>
14+ #include <zephyr/drivers/counter.h>
15+ #endif
16+
1217LOG_MODULE_REGISTER (basefw , CONFIG_SOF_LOG_LEVEL );
1318
1419/* 0e398c32-5ade-ba4b-93b1-c50432280ee4 */
1520DECLARE_SOF_RT_UUID ("basefw" , basefw_comp_uuid , 0xe398c32 , 0x5ade , 0xba4b ,
1621 0x93 , 0xb1 , 0xc5 , 0x04 , 0x32 , 0x28 , 0x0e , 0xe4 );
1722DECLARE_TR_CTX (basefw_comp_tr , SOF_UUID (basefw_comp_uuid ), LOG_LEVEL_INFO );
1823
24+ static struct ipc4_system_time_info global_system_time_info ;
25+
1926static inline void set_tuple (struct ipc4_tuple * tuple , uint32_t type , uint32_t length , void * data )
2027{
2128 tuple -> type = type ;
@@ -228,13 +235,103 @@ static int basefw_mem_state_info(uint32_t *data_offset, char *data)
228235 return 0 ;
229236}
230237
238+ static uint32_t basefw_set_system_time (uint32_t param_id ,
239+ bool first_block ,
240+ bool last_block ,
241+ uint32_t data_offset ,
242+ char * data )
243+ {
244+ /* TODO: configurate time to logging subsystem */
245+ if (!(first_block && last_block ))
246+ return IPC4_INVALID_REQUEST ;
247+
248+ global_system_time_info .host_time .val_l = ((struct ipc4_system_time * )data )-> val_l ;
249+ global_system_time_info .host_time .val_u = ((struct ipc4_system_time * )data )-> val_u ;
250+
251+ uint64_t current_dsp_time = sof_cycle_get_64 ();
252+
253+ global_system_time_info .dsp_time .val_l = (uint32_t )(current_dsp_time );
254+ global_system_time_info .dsp_time .val_u = (uint32_t )(current_dsp_time >> 32 );
255+
256+ return IPC4_SUCCESS ;
257+ }
258+
259+ static uint32_t basefw_get_system_time (uint32_t * data_offset , char * data )
260+ {
261+ struct ipc4_system_time * system_time = (struct ipc4_system_time * )data ;
262+
263+ system_time -> val_l = global_system_time_info .host_time .val_l ;
264+ system_time -> val_u = global_system_time_info .host_time .val_u ;
265+ * data_offset = sizeof (struct ipc4_system_time );
266+ return IPC4_SUCCESS ;
267+ }
268+
269+ static uint32_t basefw_get_ext_system_time (uint32_t * data_offset , char * data )
270+ {
271+ #if CONFIG_ACE_V1X_ART_COUNTER && CONFIG_ACE_V1X_RTC_COUNTER
272+ struct ipc4_ext_system_time * ext_system_time = (struct ipc4_ext_system_time * )(data );
273+ struct ipc4_ext_system_time ext_system_time_data = {0 };
274+
275+ uint64_t host_time = ((uint64_t )global_system_time_info .host_time .val_u << 32 )
276+ | (uint64_t )global_system_time_info .host_time .val_l ;
277+ uint64_t dsp_time = ((uint64_t )global_system_time_info .dsp_time .val_u << 32 )
278+ | (uint64_t )global_system_time_info .dsp_time .val_l ;
279+
280+ if (host_time == 0 || dsp_time == 0 )
281+ return IPC4_INVALID_RESOURCE_STATE ;
282+
283+ uint64_t art = 0 ;
284+ uint64_t wallclk = 0 ;
285+ uint64_t rtc = 0 ;
286+
287+ const struct device * dev = DEVICE_DT_GET (DT_NODELABEL (ace_art_counter ));
288+
289+ if (!dev ) {
290+ LOG_DBG ("board: ART counter device binding failed" );
291+ return IPC4_MOD_NOT_INITIALIZED ;
292+ }
293+
294+ counter_get_value_64 (dev , & art );
295+
296+ wallclk = sof_cycle_get_64 ();
297+ ext_system_time_data .art_l = (uint32_t )art ;
298+ ext_system_time_data .art_u = (uint32_t )(art >> 32 );
299+ uint64_t delta = (wallclk - dsp_time ) / (CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC / 1000000 );
300+
301+ uint64_t new_host_time = (host_time + delta );
302+
303+ ext_system_time_data .utc_l = (uint32_t )new_host_time ;
304+ ext_system_time_data .utc_u = (uint32_t )(new_host_time >> 32 );
305+
306+ dev = DEVICE_DT_GET (DT_NODELABEL (ace_rtc_counter ));
307+
308+ if (!dev ) {
309+ LOG_DBG ("board: RTC counter device binding failed" );
310+ return IPC4_MOD_NOT_INITIALIZED ;
311+ }
312+
313+ counter_get_value_64 (dev , & rtc );
314+ ext_system_time_data .rtc_l = (uint32_t )rtc ;
315+ ext_system_time_data .rtc_u = (uint32_t )(rtc >> 32 );
316+
317+ memcpy_s (ext_system_time , sizeof (ext_system_time ), & ext_system_time_data ,
318+ sizeof (ext_system_time ));
319+ * data_offset = sizeof (struct ipc4_ext_system_time );
320+
321+ return IPC4_SUCCESS ;
322+ #endif
323+ return IPC4_UNAVAILABLE ;
324+ }
325+
231326static int basefw_get_large_config (struct comp_dev * dev ,
232327 uint32_t param_id ,
233328 bool first_block ,
234329 bool last_block ,
235330 uint32_t * data_offset ,
236331 char * data )
237332{
333+ uint32_t ret = - EINVAL ;
334+
238335 switch (param_id ) {
239336 case IPC4_PERF_MEASUREMENTS_STATE :
240337 case IPC4_GLOBAL_PERF_DATA :
@@ -251,6 +348,16 @@ static int basefw_get_large_config(struct comp_dev *dev,
251348 return basefw_hw_config (data_offset , data );
252349 case IPC4_MEMORY_STATE_INFO_GET :
253350 return basefw_mem_state_info (data_offset , data );
351+ case IPC4_SYSTEM_TIME :
352+ return basefw_get_system_time (data_offset , data );
353+ case IPC4_EXTENDED_SYSTEM_TIME :
354+ ret = basefw_get_ext_system_time (data_offset , data );
355+ if (ret == IPC4_UNAVAILABLE ) {
356+ tr_warn (& basefw_comp_tr , "returning success for get host EXTENDED_SYSTEM_TIME without handling it" );
357+ return 0 ;
358+ } else {
359+ return ret ;
360+ }
254361 /* TODO: add more support */
255362 case IPC4_DSP_RESOURCE_STATE :
256363 case IPC4_NOTIFICATION_MASK :
@@ -283,8 +390,8 @@ static int basefw_set_large_config(struct comp_dev *dev,
283390 tr_warn (& basefw_comp_tr , "returning success for Set FW_CONFIG without handling it" );
284391 return 0 ;
285392 case IPC4_SYSTEM_TIME :
286- tr_warn ( & basefw_comp_tr , "returning success for Set SYSTEM_TIME without handling it" );
287- return 0 ;
393+ return basefw_set_system_time ( param_id , first_block ,
394+ last_block , data_offset , data ) ;
288395 case IPC4_ENABLE_LOGS :
289396 return ipc4_logging_enable_logs (first_block , last_block , data_offset , data );
290397 default :
0 commit comments