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:
Andy Ross 2022-06-06 07:49:27 -07:00 committed by Carles Cufí
commit 12eda76939
5 changed files with 71 additions and 1 deletions

View file

@ -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

View file

@ -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

View file

@ -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
View 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;
}

View file

@ -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