arch/xtensa: Add CCOUNT-based timing API
Expose the Xtenesa CCOUNT timing register (the lowest level CPU cycle counter) using the arch_timing_*() API. This is the simplest possible way to get this working. Future work might focus on moving the rate configuration into devicetree in a standard way, integrating with the platform clock driver on intel_adsp such that the reported cycle rate tracks runtime changes (though IIRC this is not a SOF requirement), and adding better test coverage to the timing layer, which right now isn't exercised anywhere but in benchmarks. Signed-off-by: Andy Ross <andrew.j.ross@intel.com>
This commit is contained in:
parent
8246d88bd3
commit
12eda76939
5 changed files with 71 additions and 1 deletions
|
@ -123,6 +123,7 @@ config XTENSA
|
||||||
select USE_SWITCH
|
select USE_SWITCH
|
||||||
select USE_SWITCH_SUPPORTED
|
select USE_SWITCH_SUPPORTED
|
||||||
select IRQ_OFFLOAD_NESTED if IRQ_OFFLOAD
|
select IRQ_OFFLOAD_NESTED if IRQ_OFFLOAD
|
||||||
|
select ARCH_HAS_TIMING_FUNCTIONS
|
||||||
imply ATOMIC_OPERATIONS_ARCH
|
imply ATOMIC_OPERATIONS_ARCH
|
||||||
help
|
help
|
||||||
Xtensa architecture
|
Xtensa architecture
|
||||||
|
|
|
@ -87,4 +87,11 @@ config XTENSA_UNCACHED_REGION
|
||||||
As for XTENSA_CACHED_REGION, this specifies which 512M
|
As for XTENSA_CACHED_REGION, this specifies which 512M
|
||||||
region (0-7) contains the "uncached" mapping.
|
region (0-7) contains the "uncached" mapping.
|
||||||
|
|
||||||
|
config XTENSA_CCOUNT_HZ
|
||||||
|
int "CCOUNT cycle rate"
|
||||||
|
default 1000000
|
||||||
|
help
|
||||||
|
Rate in HZ of the Xtensa core as measured by the value of
|
||||||
|
the CCOUNT register.
|
||||||
|
|
||||||
endmenu
|
endmenu
|
||||||
|
|
|
@ -19,7 +19,7 @@ zephyr_library_sources_ifdef(CONFIG_THREAD_LOCAL_STORAGE tls.c)
|
||||||
zephyr_library_sources_ifdef(CONFIG_XTENSA_ENABLE_BACKTRACE xtensa_backtrace.c)
|
zephyr_library_sources_ifdef(CONFIG_XTENSA_ENABLE_BACKTRACE xtensa_backtrace.c)
|
||||||
zephyr_library_sources_ifdef(CONFIG_XTENSA_ENABLE_BACKTRACE debug_helpers_asm.S)
|
zephyr_library_sources_ifdef(CONFIG_XTENSA_ENABLE_BACKTRACE debug_helpers_asm.S)
|
||||||
zephyr_library_sources_ifdef(CONFIG_DEBUG_COREDUMP coredump.c)
|
zephyr_library_sources_ifdef(CONFIG_DEBUG_COREDUMP coredump.c)
|
||||||
|
zephyr_library_sources_ifdef(CONFIG_TIMING_FUNCTIONS timing.c)
|
||||||
zephyr_library_sources_ifdef(CONFIG_GDBSTUB gdbstub.c)
|
zephyr_library_sources_ifdef(CONFIG_GDBSTUB gdbstub.c)
|
||||||
|
|
||||||
if("${ZEPHYR_TOOLCHAIN_VARIANT}" STREQUAL "xcc")
|
if("${ZEPHYR_TOOLCHAIN_VARIANT}" STREQUAL "xcc")
|
||||||
|
|
58
arch/xtensa/core/timing.c
Normal file
58
arch/xtensa/core/timing.c
Normal file
|
@ -0,0 +1,58 @@
|
||||||
|
/* Copyright (c) 2022 Intel Corporation
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
#include <zephyr.h>
|
||||||
|
|
||||||
|
void arch_timing_init(void)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void arch_timing_start(void)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void arch_timing_stop(void)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t arch_timing_freq_get(void)
|
||||||
|
{
|
||||||
|
return CONFIG_XTENSA_CCOUNT_HZ;
|
||||||
|
}
|
||||||
|
|
||||||
|
timing_t arch_timing_counter_get(void)
|
||||||
|
{
|
||||||
|
uint32_t ccount;
|
||||||
|
|
||||||
|
__asm__ volatile ("rsr %0, CCOUNT" : "=r"(ccount));
|
||||||
|
|
||||||
|
return ccount;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t arch_timing_cycles_get(volatile timing_t *const start,
|
||||||
|
volatile timing_t *const end)
|
||||||
|
{
|
||||||
|
int64_t dt = (int64_t) (*end - *start);
|
||||||
|
|
||||||
|
if (dt < 0) {
|
||||||
|
dt += 0x100000000ULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (uint64_t) dt;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t arch_timing_cycles_to_ns(uint64_t cycles)
|
||||||
|
{
|
||||||
|
return cycles * (1000000000ULL / CONFIG_XTENSA_CCOUNT_HZ);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t arch_timing_cycles_to_ns_avg(uint64_t cycles, uint32_t count)
|
||||||
|
{
|
||||||
|
/* Why is this an arch API? This is just math! */
|
||||||
|
return cycles / (uint64_t) count;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t arch_timing_freq_get_mhz(void)
|
||||||
|
{
|
||||||
|
return arch_timing_freq_get() / 1000000ULL;
|
||||||
|
}
|
|
@ -27,4 +27,8 @@ config I2S_CAVS
|
||||||
default y
|
default y
|
||||||
depends on I2S
|
depends on I2S
|
||||||
|
|
||||||
|
config XTENSA_CCOUNT_HZ
|
||||||
|
default 400000000 if SOC_SERIES_INTEL_CAVS_V25
|
||||||
|
default 200000000
|
||||||
|
|
||||||
endif # INTEL_ADSP_CAVS
|
endif # INTEL_ADSP_CAVS
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue