ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
Loading...
Searching...
No Matches
trustzone_init.c
Go to the documentation of this file.
1
57
58#include "trustzone_init.h"
59
60#include <stdint.h>
61
62#ifdef RA8_TRUSTZONE_ENABLE
63
64/* =============================================================================
65 * SAU register addresses (System Control Space, secure alias)
66 * =============================================================================
67 */
68
69typedef enum : uintptr_t {
70 k_ra8_sau_ctrl_addr = 0xE000EDD0UL,
71 k_ra8_sau_type_addr = 0xE000EDD4UL,
72 k_ra8_sau_rnr_addr = 0xE000EDD8UL,
73 k_ra8_sau_rbar_addr = 0xE000EDDCUL,
74 k_ra8_sau_rlar_addr = 0xE000EDE0UL,
75 k_ra8_sfsr_addr = 0xE000EDE4UL,
76} ra8_tz_sau_addr_t;
77
82typedef enum : uint32_t {
83 k_ra8_sau_ctrl_enable = 1UL << 0,
84 k_ra8_sau_ctrl_allns = 1UL << 1,
85} ra8_tz_sau_ctrl_bit_t;
86
91typedef enum : uint32_t {
92 k_ra8_sau_rlar_enable = 1UL << 0,
93 k_ra8_sau_rlar_nsc = 1UL << 1,
94} ra8_tz_sau_rlar_bit_t;
95
104typedef enum : uint32_t {
105 k_ra8_tz_ns_mram_base = 0x02080000UL,
106 k_ra8_tz_ns_mram_limit = 0x020FFFE0UL,
107 k_ra8_tz_ns_sram_base = 0x22100000UL,
108 k_ra8_tz_ns_sram_limit = 0x221FFFE0UL,
109 k_ra8_tz_ns_sdram_base = 0x6A000000UL,
110 k_ra8_tz_ns_sdram_limit = 0x6BFFFFE0UL,
111 k_ra8_tz_nsc_veneer_base = 0x10000000UL,
112 k_ra8_tz_nsc_veneer_lim = 0x100FFFE0UL,
113} ra8_tz_partition_t;
114
115/* =============================================================================
116 * Internal helpers
117 * =============================================================================
118 */
119
120static inline void internal_dsb(void)
121{
122 __asm__ volatile("dsb 0xF" ::: "memory");
123}
124
125static inline void internal_isb(void)
126{
127 __asm__ volatile("isb 0xF" ::: "memory");
128}
129
130/* SAU (RNR / RBAR / RLAR / TYPE / CTRL) is an Arm v8-M architectural block in
131 * the PPB window, described by the Arm v8-M Architecture Reference Manual and
132 * not by the RA8D2 Hardware User's Manual -- a HUM citation here would name a
133 * chapter that does not describe these registers. Route every access through
134 * one named accessor rather than casting at each use, exactly as ra8_scb_reg
135 * does for the System Control Block. */
136static inline volatile uint32_t* internal_sau_reg(uintptr_t addr)
137{
138 return (volatile uint32_t*)addr;
139}
140
141static void internal_write32(uintptr_t addr, uint32_t value)
142{
143 *internal_sau_reg(addr) = value;
144}
145
146static uint32_t internal_read32(uintptr_t addr)
147{
148 return *internal_sau_reg(addr);
149}
150
159static void internal_sau_set_region(uint32_t region, uint32_t base, uint32_t limit, bool is_nsc)
160{
161 internal_write32(k_ra8_sau_rnr_addr, region);
162 internal_write32(k_ra8_sau_rbar_addr, base);
163 uint32_t rlar = limit | (uint32_t)k_ra8_sau_rlar_enable;
164 if (is_nsc) {
165 rlar |= (uint32_t)k_ra8_sau_rlar_nsc;
166 }
167 internal_write32(k_ra8_sau_rlar_addr, rlar);
168}
169
170/* =============================================================================
171 * Public entry point
172 * =============================================================================
173 */
174
175#endif /* RA8_TRUSTZONE_ENABLE */
176
178{
179#ifdef RA8_TRUSTZONE_ENABLE
180 /* Sanity check: SAU_TYPE.SREGION must report >= 4 implemented
181 * regions for our partition to fit. The Cortex-M85 always has 8,
182 * but a chip-specific override could trim the count. */
183 const uint32_t sau_type = internal_read32(k_ra8_sau_type_addr);
184 if ((sau_type & 0xFFU) < 4U) {
185 /* Refuse to bring up TrustZone on an SAU we cannot use. The
186 * caller will see SAU_CTRL.ENABLE clear and fall back to the
187 * single-world model. */
188 return;
189 }
190
191 /* Region 0: NS upper MRAM */
193 (uint32_t)k_ra8_tz_ns_mram_base,
194 (uint32_t)k_ra8_tz_ns_mram_limit,
195 /*is_nsc=*/false);
196
197 /* Region 1: NS upper SRAM */
199 (uint32_t)k_ra8_tz_ns_sram_base,
200 (uint32_t)k_ra8_tz_ns_sram_limit,
201 /*is_nsc=*/false);
202
203 /* Region 2: NS upper SDRAM */
205 (uint32_t)k_ra8_tz_ns_sdram_base,
206 (uint32_t)k_ra8_tz_ns_sdram_limit,
207 /*is_nsc=*/false);
208
209 /* Region 3: NSC veneer alias ( will place .gnu.sgstubs
210 * here via the linker script). */
212 (uint32_t)k_ra8_tz_nsc_veneer_base,
213 (uint32_t)k_ra8_tz_nsc_veneer_lim,
214 /*is_nsc=*/true);
215
216 /* Enable the SAU. Leave ALLNS clear: anything we have not
217 * explicitly carved out stays secure (default-deny). */
218 internal_dsb();
219 internal_write32(k_ra8_sau_ctrl_addr, (uint32_t)k_ra8_sau_ctrl_enable);
220 internal_dsb();
221 internal_isb();
222#endif
223}
@ k_ra8_sfsr_addr
SecureFault Status Register.
void ra8_trustzone_init(void)
Programme + enable the SAU per the partition.
static void internal_dsb(void)
Emit a Data Synchronisation Barrier (no-op on host).
static void internal_write32(uintptr_t addr, uint32_t value)
Write a 32-bit MMIO register (or capture on host).
static uint32_t internal_read32(uintptr_t addr)
Read a 32-bit MMIO register (or canned host value).
static void internal_sau_set_region(uint8_t region, uint32_t base, uint32_t limit, bool is_nsc)
Programme one SAU region via RNR/RBAR/RLAR.
static void internal_isb(void)
Emit an Instruction Synchronisation Barrier (no-op on host).