Skip to content

drivers: firmware: nrf_ironside: Add TDD #92340

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
169 changes: 169 additions & 0 deletions boards/nordic/nrf54h20dk/support/nrf54h20_cpuapp.JLinkScript
Original file line number Diff line number Diff line change
@@ -1,6 +1,175 @@
__constant U32 _CPUCONF_ADDR = 0x52011000;
__constant U32 _CPUCONF_CPUWAIT_OFFSET = 0x50C;

// ATBFUNNEL
__constant U32 _ATBFUNNEL211_ADDR = 0xBF04D000;
__constant U32 _ATBFUNNEL212_ADDR = 0xBF04E000;
__constant U32 _ATBFUNNEL_CTRLREG_OFFSET = 0x0;
__constant U32 _HOLDTIME_4 = 0x300;
__constant U32 _ENS0 = 0x1;
__constant U32 _ENS1 = 0x2;
__constant U32 _ENS2 = 0x4;

// ATBREPLICATOR
__constant U32 _ATBREPLICATOR212_ADDR = 0xBF04A000;
__constant U32 _ATBREPLICATOR213_ADDR = 0xBF04B000;
__constant U32 _ATBREPLICATOR_IDFILTER0_OFFSET = 0x0;
__constant U32 _ATBREPLICATOR_IDFILTER1_OFFSET = 0x4;
__constant U32 _ID_NONE = 0xFFFFFFFF;
__constant U32 _ID1x = 0xFFFFFFFD;

// TSGEN
__constant U32 _TSGEN_ADDR = 0xBF041000;
__constant U32 _TSGEN_CNTCR_OFFSET = 0x0;
__constant U32 _TSGEN_CNTFID0_OFFSET = 0x20;
// Clock rate = TDD Freq. / 8
__constant U32 _TS_CLOCKRATE = 40000000;

// CTI
__constant U32 _CTI210_ADDR = 0xBF046000;
__constant U32 _CTICONTROL_OFFSET = 0x0;
__constant U32 _CTIOUTEN_OFFSET = 0xA0;
__constant U32 _CTIGATE_OFFSET = 0x140;
__constant U32 _TPIU_FLUSH_TRIG = 0x2;

// TPIU
__constant U32 _TPIU_ADDR = 0xBF043000;
__constant U32 _CURRENTPORTSIZE_OFFSET = 0x4;
__constant U32 _FFCR_OFFSET = 0x304;
__constant U32 _FSCR_OFFSET = 0x308;
__constant U32 _ENFCONT = 0x02;
__constant U32 _FONFLIN = 0x10;
__constant U32 _ENFTC = 0x1;
__constant U32 _TPIU_SYNC_FRAME_COUNT = 0x8;
__constant U32 _CURRENTPORTSIZE_4 = 0x8;

// TDDCONF
__constant U32 _TDDCONF_ADDR = 0xBF001000;
__constant U32 _TRACEPORTSPEED_OFFSET = 0x408;
__constant U32 _SPEED80MHZ = 0x0;

// CoreSight general
__constant U32 _CORESIGHT_CLAIMSET_OFFSET = 0xFA0;
__constant U32 _CORESIGHT_CLAIMCLR_OFFSET = 0xFA4;
__constant U32 _CORESIGHT_LAR_OFFSET = 0xFB0;
__constant U32 _CORESIGHT_UNLOCK_KEY = 0xC5ACCE55;

// GPIO P7
__constant U32 _P7_ADDR = 0x5F938E00;
__constant U32 _PIN_CNF3_OFFSET = 0x8C;
__constant U32 _PIN_CNF4_OFFSET = 0x90;
__constant U32 _PIN_CNF5_OFFSET = 0x94;
__constant U32 _PIN_CNF6_OFFSET = 0x98;
__constant U32 _PIN_CNF7_OFFSET = 0x9C;
__constant U32 _PIN_CNF_TPIU_CLOCK_VALUE = 0x80000503;
__constant U32 _PIN_CNF_TPIU_DATA_VALUE = 0x00000503;

// Settings
__constant U32 _DEBUGGER_CLAIM_MASK = 0x2;

// Used to check if we have already set up tracing
int _needCoresightSetup = 1;

// Unlock a CoreSight peripheral
void _CSUnlock(U32 addr)
{
JLINK_MEM_WriteU32(addr + _CORESIGHT_LAR_OFFSET, _CORESIGHT_UNLOCK_KEY);
}

// Lock a CoreSight peripheral
void _CSLock(U32 addr)
{
JLINK_MEM_WriteU32(addr + _CORESIGHT_LAR_OFFSET, 0);
}

// Set claim bits in the CoreSight peripheral to indicate to the firmware that it
// has been configured by the host debugger
void _CSClaim(U32 addr)
{
JLINK_MEM_WriteU32(addr + _CORESIGHT_CLAIMSET_OFFSET, _DEBUGGER_CLAIM_MASK);
}

// Set up CoreSight and other necessary configuration so to enable ETM -> TPIU tracing.
int _SetupETMTPIUTrace(void)
{
// Set up ATB funnels/replicators to route ApplicationDomain ETM to TPIU
_CSUnlock(_ATBFUNNEL212_ADDR);
JLINK_MEM_WriteU32(_ATBFUNNEL212_ADDR + _ATBFUNNEL_CTRLREG_OFFSET, _HOLDTIME_4 | _ENS0);
_CSClaim(_ATBFUNNEL212_ADDR);
_CSLock(_ATBFUNNEL212_ADDR);

_CSUnlock(_ATBREPLICATOR212_ADDR);
JLINK_MEM_WriteU32(_ATBREPLICATOR212_ADDR + _ATBREPLICATOR_IDFILTER0_OFFSET, _ID_NONE);
JLINK_MEM_WriteU32(_ATBREPLICATOR212_ADDR + _ATBREPLICATOR_IDFILTER1_OFFSET, _ID1x);
_CSLock(_ATBREPLICATOR212_ADDR);
_CSClaim(_ATBREPLICATOR212_ADDR);
_CSLock(_ATBREPLICATOR212_ADDR);

_CSUnlock(_ATBFUNNEL211_ADDR);
JLINK_MEM_WriteU32(_ATBFUNNEL211_ADDR + _ATBFUNNEL_CTRLREG_OFFSET, _HOLDTIME_4 | _ENS0);
_CSClaim(_ATBFUNNEL211_ADDR);
_CSLock(_ATBFUNNEL211_ADDR);

_CSUnlock(_ATBREPLICATOR213_ADDR);
JLINK_MEM_WriteU32(_ATBREPLICATOR213_ADDR + _ATBREPLICATOR_IDFILTER0_OFFSET, _ID1x);
JLINK_MEM_WriteU32(_ATBREPLICATOR213_ADDR + _ATBREPLICATOR_IDFILTER1_OFFSET, _ID_NONE);
_CSClaim(_ATBREPLICATOR213_ADDR);
_CSLock(_ATBREPLICATOR213_ADDR);

// Configure timestamp generator for the correct clock rate
JLINK_MEM_WriteU32(_TSGEN_ADDR + _TSGEN_CNTFID0_OFFSET, _TS_CLOCKRATE);
JLINK_MEM_WriteU32(_TSGEN_ADDR + _TSGEN_CNTCR_OFFSET, 1);
_CSClaim(_TSGEN_ADDR);

// Configure CTI1 for TPIU formatter flushing
_CSUnlock(_CTI210_ADDR);
JLINK_MEM_WriteU32(_CTI210_ADDR + _CTIOUTEN_OFFSET, _TPIU_FLUSH_TRIG);
JLINK_MEM_WriteU32(_CTI210_ADDR + _CTIGATE_OFFSET, _TPIU_FLUSH_TRIG);
JLINK_MEM_WriteU32(_CTI210_ADDR + _CTICONTROL_OFFSET, 1);
_CSClaim(_CTI210_ADDR);
_CSLock(_CTI210_ADDR);

// Configure TPIU for port size 4, continuous formatting
_CSUnlock(_TPIU_ADDR);
JLINK_MEM_WriteU32(_TPIU_ADDR + _CURRENTPORTSIZE_OFFSET, _CURRENTPORTSIZE_4);
JLINK_MEM_WriteU32(_TPIU_ADDR + _FFCR_OFFSET, _ENFCONT | _FONFLIN | _ENFTC);
JLINK_MEM_WriteU32(_TPIU_ADDR + _FSCR_OFFSET, _TPIU_SYNC_FRAME_COUNT);
_CSClaim(_TPIU_ADDR);
_CSLock(_TPIU_ADDR);

// Configure the trace pins
JLINK_MEM_WriteU32(_P7_ADDR + _PIN_CNF3_OFFSET, _PIN_CNF_TPIU_CLOCK_VALUE);
JLINK_MEM_WriteU32(_P7_ADDR + _PIN_CNF4_OFFSET, _PIN_CNF_TPIU_DATA_VALUE);
JLINK_MEM_WriteU32(_P7_ADDR + _PIN_CNF5_OFFSET, _PIN_CNF_TPIU_DATA_VALUE);
JLINK_MEM_WriteU32(_P7_ADDR + _PIN_CNF6_OFFSET, _PIN_CNF_TPIU_DATA_VALUE);
JLINK_MEM_WriteU32(_P7_ADDR + _PIN_CNF7_OFFSET, _PIN_CNF_TPIU_DATA_VALUE);

return 0;
}

int ConfigTargetSettings(void)
{
JLINK_ExecCommand("CORESIGHT_AddAP = Index=0 Type=AHB-AP");
CORESIGHT_IndexAHBAPToUse = 0;

// Adjust trace sample delay to compensate for timing when using 320MHz
JLINK_ExecCommand("TraceSampleAdjust TD = 1000");

return 0;
}

int OnTraceStart(void)
{
// Set up CoreSight if not already configured
if (_needCoresightSetup) {
_SetupETMTPIUTrace();
_needCoresightSetup = 0;
}

return 0;
}


int SetupTarget(void)
{
JLINK_TARGET_Halt();
Expand Down
1 change: 1 addition & 0 deletions drivers/firmware/nrf_ironside/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,6 @@ zephyr_library_sources_ifdef(CONFIG_NRF_IRONSIDE_CALL call.c)

zephyr_library_sources_ifdef(CONFIG_NRF_IRONSIDE_BOOT_REPORT boot_report.c)
zephyr_library_sources_ifdef(CONFIG_NRF_IRONSIDE_CPUCONF_SERVICE cpuconf.c)
zephyr_library_sources_ifdef(CONFIG_NRF_IRONSIDE_TDD_SERVICE tdd.c)
zephyr_library_sources_ifdef(CONFIG_NRF_IRONSIDE_UPDATE_SERVICE update.c)
zephyr_library_sources_ifdef(CONFIG_NRF_IRONSIDE_DVFS_SERVICE dvfs.c)
6 changes: 6 additions & 0 deletions drivers/firmware/nrf_ironside/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,12 @@ config NRF_IRONSIDE_CPUCONF_SERVICE
help
Service used to boot local domain cores.

config NRF_IRONSIDE_TDD_SERVICE
bool "IRONside tdd service"
select NRF_IRONSIDE_CALL
help
Service used to control the trace and debug domain.

config NRF_IRONSIDE_UPDATE_SERVICE
bool "IRONside update service"
select NRF_IRONSIDE_CALL
Expand Down
28 changes: 28 additions & 0 deletions drivers/firmware/nrf_ironside/tdd.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/*
* Copyright (c) 2025 Nordic Semiconductor ASA
* SPDX-License-Identifier: Apache-2.0
*/

#include <zephyr/drivers/firmware/nrf_ironside/tdd.h>
#include <zephyr/drivers/firmware/nrf_ironside/call.h>

int ironside_se_tdd_configure(const enum ironside_se_tdd_config config)
{
int err;
struct ironside_call_buf *const buf = ironside_call_alloc();

buf->id = IRONSIDE_SE_CALL_ID_TDD_V0;
buf->args[IRONSIDE_SE_TDD_SERVICE_REQ_CONFIG_IDX] = (uint32_t)config;

ironside_call_dispatch(buf);

if (buf->status == IRONSIDE_CALL_STATUS_RSP_SUCCESS) {
err = buf->args[IRONSIDE_SE_TDD_SERVICE_RSP_RETCODE_IDX];
} else {
err = buf->status;
}

ironside_call_release(buf);

return err;
}
38 changes: 38 additions & 0 deletions include/zephyr/drivers/firmware/nrf_ironside/tdd.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/*
* Copyright (c) 2025 Nordic Semiconductor ASA
* SPDX-License-Identifier: Apache-2.0
*/

#ifndef ZEPHYR_INCLUDE_ZEPHYR_DRIVERS_FIRMWARE_NRF_IRONSIDE_TDD_H_
#define ZEPHYR_INCLUDE_ZEPHYR_DRIVERS_FIRMWARE_NRF_IRONSIDE_TDD_H_

#include <zephyr/drivers/firmware/nrf_ironside/call.h>

#include <nrfx.h>

#define IRONSIDE_SE_TDD_SERVICE_ERROR_INVALID_CONFIG (1)

#define IRONSIDE_SE_CALL_ID_TDD_V0 4

#define IRONSIDE_SE_TDD_SERVICE_REQ_CONFIG_IDX 0
#define IRONSIDE_SE_TDD_SERVICE_RSP_RETCODE_IDX 0

enum ironside_se_tdd_config {
RESERVED0 = 0, /* Reserved */
/** Turn off the TDD */
IRONSIDE_SE_TDD_CONFIG_OFF = 1,
/** Turn on the TDD with default configuration */
IRONSIDE_SE_TDD_CONFIG_ON_DEFAULT = 2,
};

/**
* @brief Control the Trace and Debug Domain (TDD).
*
* @param config The configuration to be applied.
*
* @retval 0 on success.
* @retval -IRONSIDE_SE_TDD_ERROR_EINVAL on invalid argument.
*/
int ironside_se_tdd_configure(const enum ironside_se_tdd_config config);

#endif /* ZEPHYR_INCLUDE_ZEPHYR_DRIVERS_FIRMWARE_NRF_IRONSIDE_TDD_H_ */
13 changes: 12 additions & 1 deletion soc/nordic/nrf54h/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ config SOC_SERIES_NRF54HX
select HAS_NRFX
select HAS_NORDIC_DRIVERS
select SOC_EARLY_INIT_HOOK if ARM
select SOC_LATE_INIT_HOOK if SOC_NRF54H20_CPURAD_ENABLE
select NRF_PLATFORM_HALTIUM

config SOC_NRF54H20_CPUAPP_COMMON
Expand Down Expand Up @@ -67,11 +66,23 @@ config SOC_NRF54H20_CPURAD_COMMON
select HAS_PM
select HAS_POWEROFF

config SOC_NRF54H20_TDD_ENABLE
bool "Power and configure the trace and debug domain (TDD)"
depends on SOC_NRF54H20_CPUAPP
select NRF_IRONSIDE_TDD_SERVICE
select SOC_LATE_INIT_HOOK
help
This will at application boot time request that the trace and
debug domain (TDD) is powered up and configured.
This allows configuring the coresight peripherals from
the application domain.

config SOC_NRF54H20_CPURAD_ENABLE
bool "Boot the nRF54H20 Radio core"
default y if NRF_802154_SER_HOST
depends on SOC_NRF54H20_CPUAPP
select NRF_IRONSIDE_CPUCONF_SERVICE
select SOC_LATE_INIT_HOOK
help
This will at application boot time enable clock to the
Radiocore, and also power will be requested to the Radiocore
Expand Down
20 changes: 16 additions & 4 deletions soc/nordic/nrf54h/soc.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#include <soc_lrcconf.h>
#include <dmm.h>
#include <zephyr/drivers/firmware/nrf_ironside/cpuconf.h>
#include <zephyr/drivers/firmware/nrf_ironside/tdd.h>

LOG_MODULE_REGISTER(soc, CONFIG_SOC_LOG_LEVEL);

Expand Down Expand Up @@ -161,10 +162,19 @@ void soc_early_init_hook(void)
}
}

#if defined(CONFIG_SOC_NRF54H20_CPURAD_ENABLE)
#if defined(CONFIG_SOC_LATE_INIT_HOOK)

void soc_late_init_hook(void)
{
int err;
#if defined(CONFIG_SOC_NRF54H20_TDD_ENABLE)
int err_tdd;

err_tdd = ironside_se_tdd_configure(IRONSIDE_SE_TDD_CONFIG_ON_DEFAULT);
__ASSERT(err_tdd == 0, "err_tdd was %d", err_tdd);
#endif

#if defined(CONFIG_SOC_NRF54H20_CPURAD_ENABLE)
int err_cpuconf;

/* The msg will be used for communication prior to IPC
* communication being set up. But at this moment no such
Expand All @@ -181,8 +191,10 @@ void soc_late_init_hook(void)
/* Don't wait as this is not yet supported. */
bool cpu_wait = false;

err = ironside_cpuconf(NRF_PROCESSOR_RADIOCORE, radiocore_address, cpu_wait, msg, msg_size);
__ASSERT(err == 0, "err was %d", err);
err_cpuconf = ironside_cpuconf(NRF_PROCESSOR_RADIOCORE, radiocore_address, cpu_wait, msg,
msg_size);
__ASSERT(err_cpuconf == 0, "err_cpuconf was %d", err_cpuconf);
#endif
}
#endif

Expand Down
3 changes: 2 additions & 1 deletion tests/kernel/interrupt/src/nested_irq.c
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,8 @@
*/
#define IRQ0_PRIO IRQ_DEFAULT_PRIORITY
#define IRQ1_PRIO 0x0
#elif defined(CONFIG_SOC_SERIES_NRF54LX) && defined(CONFIG_RISCV_CORE_NORDIC_VPR)
#elif (defined(CONFIG_SOC_SERIES_NRF54LX) || defined(CONFIG_SOC_NRF54H20_CPUFLPR)) && \
defined(CONFIG_RISCV_CORE_NORDIC_VPR)
#define IRQ0_LINE 16
#define IRQ1_LINE 17

Expand Down