Skip to content

Commit 9bcae70

Browse files
committed
[nrf fromlist] soc: nordic: Add UICR.RECOVERY.PERIPHCONF configuration support
Add support for configuring the UICR.RECOVERY.PERIPHCONF field. Upstream PR #: 91826 Signed-off-by: Sebastian Bøe <[email protected]>
1 parent 929cdb0 commit 9bcae70

File tree

5 files changed

+98
-13
lines changed

5 files changed

+98
-13
lines changed

boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20-memory_map.dtsi

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,5 +166,9 @@
166166
periphconf_partition: partition@1ae000 {
167167
reg = <0x1ae000 DT_SIZE_K(8)>;
168168
};
169+
170+
periphconf_recovery_partition: partition@1b0000 {
171+
reg = <0x1b0000 DT_SIZE_K(8)>;
172+
};
169173
};
170174
};

scripts/west_commands/runners/nrf_common.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -404,6 +404,15 @@ def program_hex(self):
404404
core='Application',
405405
)
406406

407+
if self.build_conf.getboolean("CONFIG_NRF_HALTIUM_UICR_RECOVERY_PERIPHCONF"):
408+
self.op_program(
409+
str(zephyr_build_dir / 'periphconf_recovery.hex'),
410+
'ERASE_NONE',
411+
None,
412+
defer=True,
413+
core='Application',
414+
)
415+
407416
if not self.erase and regtool_generated_uicr:
408417
self.exec_op('erase', core=core, kind='uicr')
409418
else:

soc/nordic/common/uicr/CMakeLists.txt

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,15 @@ if(CONFIG_NRF_HALTIUM_GENERATE_UICR)
2020
list(APPEND optional_byproducts ${periphconf_hex_file})
2121
endif()
2222

23+
set(out_periphconf_recovery_hex_arg)
24+
if(CONFIG_NRF_HALTIUM_UICR_RECOVERY_PERIPHCONF)
25+
set(periphconf_recovery_hex_file ${PROJECT_BINARY_DIR}/periphconf_recovery.hex)
26+
set(out_periphconf_recovery_hex_arg
27+
--out-periphconf-recovery-hex ${periphconf_recovery_hex_file}
28+
)
29+
list(APPEND optional_byproducts ${periphconf_recovery_hex_file})
30+
endif()
31+
2332
set(uicr_hex_file ${PROJECT_BINARY_DIR}/uicr.hex)
2433
set_property(GLOBAL APPEND PROPERTY extra_post_build_commands
2534
COMMAND ${CMAKE_COMMAND} -E env PYTHONPATH=${ZEPHYR_BASE}/scripts/dts/python-devicetree/src
@@ -28,6 +37,7 @@ if(CONFIG_NRF_HALTIUM_GENERATE_UICR)
2837
--in-edt-pickle ${EDT_PICKLE}
2938
${in_periphconf_elf_arg}
3039
${out_periphconf_hex_arg}
40+
${out_periphconf_recovery_hex_arg}
3141
--out-uicr-hex ${uicr_hex_file}
3242
)
3343
set_property(GLOBAL APPEND PROPERTY extra_post_build_byproducts

soc/nordic/common/uicr/Kconfig

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,14 @@ config NRF_HALTIUM_UICR_RECOVERY_SIZE4KB
6060
help
6161
Size of the recovery firmware partition in 4KB blocks.
6262

63+
config NRF_HALTIUM_UICR_RECOVERY_PERIPHCONF
64+
bool "Recovery firmware global domain peripheral configuration"
65+
help
66+
Generates a blob containing static global domain peripheral initialization
67+
values extracted from recovery firmware build artifacts, and configures
68+
UICR.RECOVERY.PERIPHCONF to point at the blob. The initialization values
69+
are then loaded ahead of the recovery firmware boot.
70+
6371
endif # NRF_HALTIUM_UICR_RECOVERY
6472

6573
endif

soc/nordic/common/uicr/gen_uicr.py

Lines changed: 67 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,9 @@
2525
UICR_NODELABEL = "uicr"
2626
# Nodelabel of the PERIPHCONF devicetree node, used to extract its location from the devicetree.
2727
PERIPHCONF_NODELABEL = "periphconf_partition"
28+
# Nodelabel of the PERIPHCONF_RECOVERY devicetree node, used to extract its location
29+
# from the devicetree.
30+
PERIPHCONF_RECOVERY_NODELABEL = "periphconf_recovery_partition"
2831

2932
# Common values for representing enabled/disabled in the UICR format.
3033
ENABLED_VALUE = 0xFFFF_FFFF
@@ -67,13 +70,23 @@ class Protectedmem(c.LittleEndianStructure):
6770
]
6871

6972

73+
class Periphconf(c.LittleEndianStructure):
74+
_pack_ = 1
75+
_fields_ = [
76+
("ENABLE", c.c_uint32),
77+
("ADDRESS", c.c_uint32),
78+
("MAXCOUNT", c.c_uint32),
79+
]
80+
81+
7082
class Recovery(c.LittleEndianStructure):
7183
_pack_ = 1
7284
_fields_ = [
7385
("ENABLE", c.c_uint32),
7486
("PROCESSOR", c.c_uint32),
7587
("INITSVTOR", c.c_uint32),
7688
("SIZE4KB", c.c_uint32),
89+
("PERIPHCONF", Periphconf),
7790
]
7891

7992

@@ -87,15 +100,6 @@ class Its(c.LittleEndianStructure):
87100
]
88101

89102

90-
class Periphconf(c.LittleEndianStructure):
91-
_pack_ = 1
92-
_fields_ = [
93-
("ENABLE", c.c_uint32),
94-
("ADDRESS", c.c_uint32),
95-
("MAXCOUNT", c.c_uint32),
96-
]
97-
98-
99103
class Mpcconf(c.LittleEndianStructure):
100104
_pack_ = 1
101105
_fields_ = [
@@ -115,11 +119,13 @@ class Uicr(c.LittleEndianStructure):
115119
("APPROTECT", Approtect),
116120
("ERASEPROTECT", c.c_uint32),
117121
("PROTECTEDMEM", Protectedmem),
118-
("RECOVERY", Recovery),
122+
("RESERVED2", c.c_uint32 * 4),
119123
("ITS", Its),
120-
("RESERVED2", c.c_uint32 * 7),
124+
("RESERVED3", c.c_uint32 * 7),
121125
("PERIPHCONF", Periphconf),
122126
("MPCCONF", Mpcconf),
127+
("RESERVED4", c.c_uint32),
128+
("RECOVERY", Recovery),
123129
]
124130

125131

@@ -169,6 +175,12 @@ def main() -> None:
169175
type=argparse.FileType("w", encoding="utf-8"),
170176
help="Path to write the generated PERIPHCONF HEX file to",
171177
)
178+
parser.add_argument(
179+
"--out-periphconf-recovery-hex",
180+
default=None,
181+
type=argparse.FileType("w", encoding="utf-8"),
182+
help="Path to write the generated PERIPHCONF_RECOVERY HEX file to",
183+
)
172184
args = parser.parse_args()
173185

174186
try:
@@ -196,6 +208,36 @@ def main() -> None:
196208
padding_len = periphconf_size - len(periphconf_combined)
197209
periphconf_final = periphconf_combined + bytes([0xFF for _ in range(padding_len)])
198210

211+
# Handle recovery periphconf partition if enabled
212+
periphconf_recovery_address = None
213+
periphconf_recovery_size = None
214+
periphconf_recovery_final = None
215+
216+
if kconfig.get("CONFIG_NRF_HALTIUM_UICR_RECOVERY_PERIPHCONF") == "y":
217+
try:
218+
periphconf_recovery_partition = edt.label2node[PERIPHCONF_RECOVERY_NODELABEL]
219+
except LookupError as e:
220+
raise ScriptError(
221+
"Failed to find a PERIPHCONF_RECOVERY partition in the devicetree. "
222+
f"Expected a DT node with label '{PERIPHCONF_RECOVERY_NODELABEL}'. "
223+
"This is required when "
224+
"CONFIG_NRF_HALTIUM_UICR_RECOVERY_PERIPHCONF is enabled."
225+
) from e
226+
227+
flash_base_address_recovery = periphconf_recovery_partition.flash_controller.regs[
228+
0
229+
].addr
230+
periphconf_recovery_address = (
231+
flash_base_address_recovery + periphconf_recovery_partition.regs[0].addr
232+
)
233+
periphconf_recovery_size = periphconf_recovery_partition.regs[0].size
234+
235+
# Create a copy of the periphconf data for recovery at different location
236+
padding_len_recovery = periphconf_recovery_size - len(periphconf_combined)
237+
periphconf_recovery_final = periphconf_combined + bytes(
238+
[0xFF for _ in range(padding_len_recovery)]
239+
)
240+
199241
if kconfig.get("CONFIG_NRF_HALTIUM_UICR_PERIPHCONF") == "y":
200242
uicr.PERIPHCONF.ENABLE = ENABLED_VALUE
201243
uicr.PERIPHCONF.ADDRESS = periphconf_address
@@ -222,6 +264,11 @@ def main() -> None:
222264
size4kb = int(kconfig.get("CONFIG_NRF_HALTIUM_UICR_RECOVERY_SIZE4KB"), 0)
223265
uicr.RECOVERY.SIZE4KB = size4kb
224266

267+
if kconfig.get("CONFIG_NRF_HALTIUM_UICR_RECOVERY_PERIPHCONF") == "y":
268+
uicr.RECOVERY.PERIPHCONF.ENABLE = ENABLED_VALUE
269+
uicr.RECOVERY.PERIPHCONF.ADDRESS = periphconf_recovery_address
270+
uicr.RECOVERY.PERIPHCONF.MAXCOUNT = math.floor(periphconf_recovery_size / 8)
271+
225272
try:
226273
uicr_node = edt.label2node[UICR_NODELABEL]
227274
except LookupError as e:
@@ -240,6 +287,13 @@ def main() -> None:
240287
periphconf_hex.frombytes(periphconf_final, offset=periphconf_address)
241288
periphconf_hex.write_hex_file(args.out_periphconf_hex)
242289

290+
if args.out_periphconf_recovery_hex is not None and periphconf_recovery_final is not None:
291+
periphconf_recovery_hex = IntelHex()
292+
periphconf_recovery_hex.frombytes(
293+
periphconf_recovery_final, offset=periphconf_recovery_address
294+
)
295+
periphconf_recovery_hex.write_hex_file(args.out_periphconf_recovery_hex)
296+
243297
except ScriptError as e:
244298
print(f"Error: {e!s}")
245299
sys.exit(1)
@@ -268,8 +322,8 @@ def extract_and_combine_periphconfs(elf_files: list[argparse.FileType]) -> bytes
268322
unique_values = {e.value for e in entries}
269323
if len(unique_values) > 1:
270324
raise ScriptError(
271-
f"PERIPHCONF has conflicting values for register 0x{regptr:09_x}: "
272-
+ ", ".join([f"0x{val:09_x}" for val in unique_values])
325+
f"PERIPHCONF has conflicting values for register "
326+
f"0x{regptr:09_x}: " + ", ".join([f"0x{val:09_x}" for val in unique_values])
273327
)
274328
deduplicated_periphconf.append(entries[0])
275329

0 commit comments

Comments
 (0)