diff --git a/soc/xtensa/intel_adsp/ace/CMakeLists.txt b/soc/xtensa/intel_adsp/ace/CMakeLists.txt index a5aa90b59d0..28626787c5e 100644 --- a/soc/xtensa/intel_adsp/ace/CMakeLists.txt +++ b/soc/xtensa/intel_adsp/ace/CMakeLists.txt @@ -11,6 +11,7 @@ zephyr_library_sources( power_down.S power.c boot.c + timestamp.c ) zephyr_include_directories(include) diff --git a/soc/xtensa/intel_adsp/ace/include/adsp_timestamp.h b/soc/xtensa/intel_adsp/ace/include/adsp_timestamp.h new file mode 100644 index 00000000000..4c7796a5ae4 --- /dev/null +++ b/soc/xtensa/intel_adsp/ace/include/adsp_timestamp.h @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2023 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_SOC_INTEL_ADSP_ACE_TIMESTAMP_H_ +#define ZEPHYR_SOC_INTEL_ADSP_ACE_TIMESTAMP_H_ + +#include + +/* Captured timestamp data - contains a copy of all DfTTS snapshot registers. */ +struct intel_adsp_timestamp { + uint32_t iscs; /* copy of DfISCS register */ + uint64_t lscs; /* copy of DfLSCS register */ + uint64_t dwccs; /* copy of DfDWCCS register */ + uint64_t artcs; /* copy of DfARTCS register */ + uint32_t lwccs; /* copy of DfLWCCS register */ +}; + +/* + * @brief Perform timestamping process using DfTTS logic. + * + * @param tsctrl Value to be applied to DfTSCTRL register to control timestamping logic + * @param timestamp Captured timestamp data + */ +int intel_adsp_get_timestamp(uint32_t tsctrl, struct intel_adsp_timestamp *timestamp); + +#endif /* ZEPHYR_SOC_INTEL_ADSP_ACE_TIMESTAMP_H_ */ diff --git a/soc/xtensa/intel_adsp/ace/include/intel_ace15_mtpm/adsp_shim.h b/soc/xtensa/intel_adsp/ace/include/intel_ace15_mtpm/adsp_shim.h index 56997ee84d1..521dc4e5fb1 100644 --- a/soc/xtensa/intel_adsp/ace/include/intel_ace15_mtpm/adsp_shim.h +++ b/soc/xtensa/intel_adsp/ace/include/intel_ace15_mtpm/adsp_shim.h @@ -8,6 +8,8 @@ #ifndef _ASMLANGUAGE +#include + /** * DfPMCCH * Power Management / Clock Control (HST) Registers @@ -138,6 +140,15 @@ struct ace_dfpmccu { #define ADSP_SHIM_DSPWCTCS_TTIE(c) BIT(8 + (c)) +#define ADSP_SHIM_TSCTRL_NTK BIT(31) +#define ADSP_SHIM_TSCTRL_IONTE BIT(30) +#define ADSP_SHIM_TSCTRL_DMATS GENMASK(13, 12) +#define ADSP_SHIM_TSCTRL_CLNKS GENMASK(11, 10) +#define ADSP_SHIM_TSCTRL_HHTSE BIT(7) +#define ADSP_SHIM_TSCTRL_LWCS BIT(6) +#define ADSP_SHIM_TSCTRL_ODTS BIT(5) +#define ADSP_SHIM_TSCTRL_CDMAS GENMASK(4, 0) + #endif /* _ASMLANGUAGE */ #define ACE_CLKCTL_WOVCRO BIT(21) /* Request WOVCRO clock */ diff --git a/soc/xtensa/intel_adsp/ace/include/intel_ace20_lnl/adsp_shim.h b/soc/xtensa/intel_adsp/ace/include/intel_ace20_lnl/adsp_shim.h index f7661317062..f640a0a9f59 100644 --- a/soc/xtensa/intel_adsp/ace/include/intel_ace20_lnl/adsp_shim.h +++ b/soc/xtensa/intel_adsp/ace/include/intel_ace20_lnl/adsp_shim.h @@ -8,6 +8,8 @@ #ifndef _ASMLANGUAGE +#include + /** * DfPMCCH * Power Management / Clock Control (HST) Registers @@ -138,6 +140,15 @@ struct ace_dfpmccu { #define ADSP_SHIM_DSPWCTCS_TTIE(c) BIT(8 + (c)) +#define ADSP_SHIM_TSCTRL_NTK BIT(31) +#define ADSP_SHIM_TSCTRL_IONTE BIT(30) +#define ADSP_SHIM_TSCTRL_DMATS GENMASK(13, 12) +#define ADSP_SHIM_TSCTRL_CLNKS GENMASK(11, 10) +#define ADSP_SHIM_TSCTRL_HHTSE BIT(7) +#define ADSP_SHIM_TSCTRL_LWCS BIT(6) +#define ADSP_SHIM_TSCTRL_ODTS BIT(5) +#define ADSP_SHIM_TSCTRL_CDMAS GENMASK(4, 0) + #endif /* _ASMLANGUAGE */ #define ACE_CLKCTL_WOVCRO BIT(4) /* Request WOVCRO clock */ diff --git a/soc/xtensa/intel_adsp/ace/timestamp.c b/soc/xtensa/intel_adsp/ace/timestamp.c new file mode 100644 index 00000000000..7f3168d87f4 --- /dev/null +++ b/soc/xtensa/intel_adsp/ace/timestamp.c @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2023 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include + +#define TTS_BASE_ADDR DT_REG_ADDR(DT_NODELABEL(tts)) + +#define TSCTRL_ADDR (TTS_BASE_ADDR + ADSP_TSCTRL_OFFSET) +#define ISCS_ADDR (TTS_BASE_ADDR + ADSP_ISCS_OFFSET) +#define LSCS_ADDR (TTS_BASE_ADDR + ADSP_LSCS_OFFSET) +#define DWCCS_ADDR (TTS_BASE_ADDR + ADSP_DWCCS_OFFSET) +#define ARTCS_ADDR (TTS_BASE_ADDR + ADSP_ARTCS_OFFSET) +#define LWCCS_ADDR (TTS_BASE_ADDR + ADSP_LWCCS_OFFSET) + +/* Copies the bit-field specified by mask from src to dest */ +#define BITS_COPY(dest, src, mask) ((dest) = ((dest) & ~(mask)) | ((src) & (mask))) + +static struct k_spinlock lock; + +int intel_adsp_get_timestamp(uint32_t tsctrl, struct intel_adsp_timestamp *timestamp) +{ + uint32_t trigger_mask = ADSP_SHIM_TSCTRL_HHTSE | ADSP_SHIM_TSCTRL_ODTS; + uint32_t trigger_bits = tsctrl & trigger_mask; + uint32_t tsctrl_temp; + k_spinlock_key_t key; + int ret = 0; + + /* Exactly one trigger bit must be set in a valid request */ + if (POPCOUNT(trigger_bits) != 1) { + return -EINVAL; + } + + key = k_spin_lock(&lock); + + tsctrl_temp = sys_read32(TSCTRL_ADDR); + + /* Abort if any timestamp capture in progress */ + if (tsctrl_temp & trigger_mask) { + ret = -EBUSY; + goto out; + } + + /* Clear NTK (RW/1C) bit if needed */ + if (tsctrl_temp & ADSP_SHIM_TSCTRL_NTK) { + sys_write32(tsctrl_temp, TSCTRL_ADDR); + tsctrl_temp &= ~ADSP_SHIM_TSCTRL_NTK; + } + + /* Setup the timestamping logic according to request */ + BITS_COPY(tsctrl_temp, tsctrl, ADSP_SHIM_TSCTRL_IONTE); + BITS_COPY(tsctrl_temp, tsctrl, ADSP_SHIM_TSCTRL_DMATS); + BITS_COPY(tsctrl_temp, tsctrl, ADSP_SHIM_TSCTRL_CLNKS); + BITS_COPY(tsctrl_temp, tsctrl, ADSP_SHIM_TSCTRL_LWCS); + BITS_COPY(tsctrl_temp, tsctrl, ADSP_SHIM_TSCTRL_CDMAS); + sys_write32(tsctrl_temp, TSCTRL_ADDR); + + /* Start new timestamp capture by setting one of mutually exclusive + * trigger bits. + */ + tsctrl_temp |= trigger_bits; + sys_write32(tsctrl_temp, TSCTRL_ADDR); + + /* Wait for timestamp capture to complete */ + while (1) { + tsctrl_temp = sys_read32(TSCTRL_ADDR); + if (tsctrl_temp & ADSP_SHIM_TSCTRL_NTK) { + break; + } + } + + /* Copy the timestamp data from HW registers to the snapshot buffer + * provided by caller. As NTK bit is high at this stage, the timestamp + * data in HW is guaranteed to be valid and static. + */ + timestamp->iscs = sys_read32(ISCS_ADDR); + timestamp->lscs = sys_read64(LSCS_ADDR); + timestamp->dwccs = sys_read64(DWCCS_ADDR); + timestamp->artcs = sys_read64(ARTCS_ADDR); + timestamp->lwccs = sys_read32(LWCCS_ADDR); + + /* Clear NTK (RW/1C) bit */ + tsctrl_temp |= ADSP_SHIM_TSCTRL_NTK; + sys_write32(tsctrl_temp, TSCTRL_ADDR); + +out: + k_spin_unlock(&lock, key); + + return ret; +}