soc: intel_adsp: enable DfTTS-based time stamping on ACE platforms

This patch enables time stamping controlled by DSP Timers / Time Stamping
logic on ACE1.5 / ACE2.0 platforms.

Signed-off-by: Tomasz Lissowski <tomasz.lissowski@intel.com>
This commit is contained in:
Tomasz Lissowski 2024-01-09 09:00:55 +01:00 committed by Carles Cufí
commit 042cb6ac4e
5 changed files with 148 additions and 0 deletions

View file

@ -11,6 +11,7 @@ zephyr_library_sources(
power_down.S
power.c
boot.c
timestamp.c
)
zephyr_include_directories(include)

View file

@ -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 <stdint.h>
/* 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_ */

View file

@ -8,6 +8,8 @@
#ifndef _ASMLANGUAGE
#include <zephyr/sys/util.h>
/**
* 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 */

View file

@ -8,6 +8,8 @@
#ifndef _ASMLANGUAGE
#include <zephyr/sys/util.h>
/**
* 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 */

View file

@ -0,0 +1,96 @@
/*
* Copyright (c) 2023 Intel Corporation
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <stdint.h>
#include <zephyr/spinlock.h>
#include <zephyr/devicetree.h>
#include <adsp_shim.h>
#include <adsp_timestamp.h>
#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;
}