Skip to content
Merged
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;
Comment on lines +52 to +53
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This usage of the CLAIM register is not standardized, but instead a bespoke solution that we made. Should we leave CLAIM configuration out here? It could always be added later if necessary.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Given this is in a nordic specific file I feel this is ok, we aren't providing a general jlink script to configure coresight peripherals here

__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
select EXPERIMENTAL if MCUBOOT

Expand Down Expand Up @@ -68,11 +67,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
28 changes: 24 additions & 4 deletions soc/nordic/nrf54h/soc.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,9 @@
#include <soc/nrfx_coredep.h>
#include <soc_lrcconf.h>
#include <dmm.h>
#include <uicr/uicr.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 @@ -168,10 +170,26 @@ 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);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this also be invoked by PM state changes, if I'm not misunderstanding?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In a final solution it can be, right now this will just force on tdd and leave it at that, hence preventing having to reconfigure all the coresight peripherals after a sleep etc, because JLink couldn't handle this.
This can be done when we have the coresight peripherals controlled from the application core but that'll need more time while this allows ETM over TPIU as a static state and is useful like this as is, just not power efficient

__ASSERT(err_tdd == 0, "err_tdd was %d", err_tdd);

UICR_GPIO_PIN_CNF_CTRLSEL_SET(NRF_P7, 3, GPIO_PIN_CNF_CTRLSEL_TND);
UICR_GPIO_PIN_CNF_CTRLSEL_SET(NRF_P7, 4, GPIO_PIN_CNF_CTRLSEL_TND);
UICR_GPIO_PIN_CNF_CTRLSEL_SET(NRF_P7, 5, GPIO_PIN_CNF_CTRLSEL_TND);
UICR_GPIO_PIN_CNF_CTRLSEL_SET(NRF_P7, 6, GPIO_PIN_CNF_CTRLSEL_TND);
UICR_GPIO_PIN_CNF_CTRLSEL_SET(NRF_P7, 7, GPIO_PIN_CNF_CTRLSEL_TND);

#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 Down Expand Up @@ -210,8 +228,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