blob: a6e52209483073ccf5e860522d6ac12803636783 [file] [log] [blame]
Yann Gautier36a1e4b2019-01-17 14:52:47 +01001/*
Patrick Delaunaye720b5b2022-12-14 13:45:04 +01002 * Copyright (c) 2017-2024, STMicroelectronics - All Rights Reserved
Yann Gautier36a1e4b2019-01-17 14:52:47 +01003 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7#include <assert.h>
8#include <limits.h>
9
Yann Gautier36a1e4b2019-01-17 14:52:47 +010010#include <arch_helpers.h>
11#include <common/debug.h>
12#include <drivers/st/bsec.h>
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +020013#include <drivers/st/bsec2_reg.h>
Yann Gautier36a1e4b2019-01-17 14:52:47 +010014#include <lib/mmio.h>
15#include <lib/spinlock.h>
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +020016#include <libfdt.h>
17
18#include <platform_def.h>
Yann Gautier36a1e4b2019-01-17 14:52:47 +010019
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +020020#define BSEC_IP_VERSION_1_1 U(0x11)
21#define BSEC_IP_VERSION_2_0 U(0x20)
22#define BSEC_IP_ID_2 U(0x100032)
Yann Gautier36a1e4b2019-01-17 14:52:47 +010023
Patrick Delaunaye720b5b2022-12-14 13:45:04 +010024/*
25 * IP configuration
26 */
27#define BSEC_OTP_MASK GENMASK(4, 0)
28#define BSEC_OTP_BANK_SHIFT 5
29#define BSEC_TIMEOUT_VALUE U(0xFFFF)
30
Yann Gautier36a1e4b2019-01-17 14:52:47 +010031#define OTP_ACCESS_SIZE (round_up(OTP_MAX_SIZE, __WORD_BIT) / __WORD_BIT)
32
Patrick Delaunaye720b5b2022-12-14 13:45:04 +010033static uint32_t otp_nsec_access[OTP_ACCESS_SIZE] __maybe_unused;
Yann Gautier36a1e4b2019-01-17 14:52:47 +010034
Patrick Delaunaye720b5b2022-12-14 13:45:04 +010035static uint32_t bsec_shadow_register(uint32_t otp);
Yann Gautier36a1e4b2019-01-17 14:52:47 +010036static uint32_t bsec_power_safmem(bool power);
Patrick Delaunaye720b5b2022-12-14 13:45:04 +010037static uint32_t bsec_get_version(void);
38static uint32_t bsec_get_id(void);
39static uint32_t bsec_get_status(void);
40static uint32_t bsec_read_permanent_lock(uint32_t otp, bool *value);
Yann Gautier36a1e4b2019-01-17 14:52:47 +010041
42/* BSEC access protection */
43static spinlock_t bsec_spinlock;
Yann Gautier36a1e4b2019-01-17 14:52:47 +010044
45static void bsec_lock(void)
46{
Yann Gautierf540a592019-05-22 19:13:51 +020047 if (stm32mp_lock_available()) {
Yann Gautier36a1e4b2019-01-17 14:52:47 +010048 spin_lock(&bsec_spinlock);
49 }
50}
51
52static void bsec_unlock(void)
53{
Yann Gautierf540a592019-05-22 19:13:51 +020054 if (stm32mp_lock_available()) {
Yann Gautier36a1e4b2019-01-17 14:52:47 +010055 spin_unlock(&bsec_spinlock);
56 }
57}
58
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +020059static bool is_otp_invalid_mode(void)
60{
Patrick Delaunaye720b5b2022-12-14 13:45:04 +010061 bool ret = ((bsec_get_status() & BSEC_OTP_STATUS_INVALID) == BSEC_OTP_STATUS_INVALID);
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +020062
63 if (ret) {
64 ERROR("OTP mode is OTP-INVALID\n");
65 }
66
67 return ret;
68}
69
70#if defined(IMAGE_BL32)
Yann Gautier36a1e4b2019-01-17 14:52:47 +010071static int bsec_get_dt_node(struct dt_node_info *info)
72{
73 int node;
74
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +020075 node = dt_get_node(info, -1, DT_BSEC_COMPAT);
Yann Gautier36a1e4b2019-01-17 14:52:47 +010076 if (node < 0) {
77 return -FDT_ERR_NOTFOUND;
78 }
79
80 return node;
81}
82
Yann Gautier36a1e4b2019-01-17 14:52:47 +010083static void enable_non_secure_access(uint32_t otp)
84{
85 otp_nsec_access[otp / __WORD_BIT] |= BIT(otp % __WORD_BIT);
86
87 if (bsec_shadow_register(otp) != BSEC_OK) {
88 panic();
89 }
90}
91
92static bool non_secure_can_access(uint32_t otp)
93{
94 return (otp_nsec_access[otp / __WORD_BIT] &
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +020095 BIT(otp % __WORD_BIT)) != 0U;
Yann Gautier36a1e4b2019-01-17 14:52:47 +010096}
97
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +020098static void bsec_dt_otp_nsec_access(void *fdt, int bsec_node)
Yann Gautier36a1e4b2019-01-17 14:52:47 +010099{
100 int bsec_subnode;
101
102 fdt_for_each_subnode(bsec_subnode, fdt, bsec_node) {
103 const fdt32_t *cuint;
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +0200104 uint32_t otp;
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100105 uint32_t i;
106 uint32_t size;
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +0200107 uint32_t offset;
108 uint32_t length;
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100109
110 cuint = fdt_getprop(fdt, bsec_subnode, "reg", NULL);
111 if (cuint == NULL) {
112 panic();
113 }
114
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +0200115 offset = fdt32_to_cpu(*cuint);
116 cuint++;
117 length = fdt32_to_cpu(*cuint);
118
119 otp = offset / sizeof(uint32_t);
120
121 if (otp < STM32MP1_UPPER_OTP_START) {
122 unsigned int otp_end = round_up(offset + length,
123 sizeof(uint32_t)) /
124 sizeof(uint32_t);
125
126 if (otp_end > STM32MP1_UPPER_OTP_START) {
127 /*
128 * OTP crosses Lower/Upper boundary, consider
129 * only the upper part.
130 */
131 otp = STM32MP1_UPPER_OTP_START;
132 length -= (STM32MP1_UPPER_OTP_START *
133 sizeof(uint32_t)) - offset;
134 offset = STM32MP1_UPPER_OTP_START *
135 sizeof(uint32_t);
136
137 WARN("OTP crosses Lower/Upper boundary\n");
138 } else {
139 continue;
140 }
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100141 }
142
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +0200143 if ((fdt_getprop(fdt, bsec_subnode,
144 "st,non-secure-otp", NULL)) == NULL) {
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100145 continue;
146 }
147
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +0200148 if (((offset % sizeof(uint32_t)) != 0U) ||
149 ((length % sizeof(uint32_t)) != 0U)) {
150 ERROR("Unaligned non-secure OTP\n");
151 panic();
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100152 }
153
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +0200154 size = length / sizeof(uint32_t);
155
156 for (i = otp; i < (otp + size); i++) {
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100157 enable_non_secure_access(i);
158 }
159 }
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +0200160}
161
162static void bsec_late_init(void)
163{
164 void *fdt;
165 int node;
166 struct dt_node_info bsec_info;
167
168 if (fdt_get_address(&fdt) == 0) {
169 panic();
170 }
171
172 node = bsec_get_dt_node(&bsec_info);
173 if (node < 0) {
174 panic();
175 }
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100176
Patrick Delaunaye720b5b2022-12-14 13:45:04 +0100177 assert(bsec_info.base == BSEC_BASE);
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +0200178
179 bsec_dt_otp_nsec_access(fdt, node);
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100180}
181#endif
182
183static uint32_t otp_bank_offset(uint32_t otp)
184{
185 assert(otp <= STM32MP1_OTP_MAX_ID);
186
187 return ((otp & ~BSEC_OTP_MASK) >> BSEC_OTP_BANK_SHIFT) *
188 sizeof(uint32_t);
189}
190
Patrick Delaunaye720b5b2022-12-14 13:45:04 +0100191static uint32_t otp_bit_mask(uint32_t otp)
192{
193 return BIT(otp & BSEC_OTP_MASK);
194}
195
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +0200196/*
197 * bsec_check_error: check BSEC error status.
198 * otp: OTP number.
199 * check_disturbed: check only error (false),
200 * or error and disturbed status (true).
201 * return value: BSEC_OK if no error.
202 */
203static uint32_t bsec_check_error(uint32_t otp, bool check_disturbed)
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100204{
Patrick Delaunaye720b5b2022-12-14 13:45:04 +0100205 uint32_t bit = otp_bit_mask(otp);
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100206 uint32_t bank = otp_bank_offset(otp);
207
Patrick Delaunaye720b5b2022-12-14 13:45:04 +0100208 if ((mmio_read_32(BSEC_BASE + BSEC_ERROR_OFF + bank) & bit) != 0U) {
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100209 return BSEC_ERROR;
210 }
211
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +0200212 if (!check_disturbed) {
213 return BSEC_OK;
214 }
215
Patrick Delaunaye720b5b2022-12-14 13:45:04 +0100216 if ((mmio_read_32(BSEC_BASE + BSEC_DISTURBED_OFF + bank) & bit) != 0U) {
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +0200217 return BSEC_DISTURBED;
218 }
219
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100220 return BSEC_OK;
221}
222
223/*
224 * bsec_probe: initialize BSEC driver.
225 * return value: BSEC_OK if no error.
226 */
227uint32_t bsec_probe(void)
228{
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +0200229 if (is_otp_invalid_mode()) {
230 return BSEC_ERROR;
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100231 }
232
Patrick Delaunaye720b5b2022-12-14 13:45:04 +0100233 if (((bsec_get_version() != BSEC_IP_VERSION_1_1) &&
234 (bsec_get_version() != BSEC_IP_VERSION_2_0)) ||
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +0200235 (bsec_get_id() != BSEC_IP_ID_2)) {
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100236 panic();
237 }
238
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100239#if defined(IMAGE_BL32)
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +0200240 bsec_late_init();
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100241#endif
242 return BSEC_OK;
243}
244
245/*
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100246 * bsec_shadow_register: copy SAFMEM OTP to BSEC data.
247 * otp: OTP number.
248 * return value: BSEC_OK if no error.
249 */
Patrick Delaunaye720b5b2022-12-14 13:45:04 +0100250static uint32_t bsec_shadow_register(uint32_t otp)
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100251{
252 uint32_t result;
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +0200253 bool value;
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100254 bool power_up = false;
255
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +0200256 if (is_otp_invalid_mode()) {
257 return BSEC_ERROR;
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100258 }
259
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +0200260 result = bsec_read_sr_lock(otp, &value);
261 if (result != BSEC_OK) {
262 ERROR("BSEC: %u Sticky-read bit read Error %u\n", otp, result);
263 return result;
264 }
265
266 if (value) {
267 VERBOSE("BSEC: OTP %u is locked and will not be refreshed\n",
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100268 otp);
269 }
270
Patrick Delaunaye720b5b2022-12-14 13:45:04 +0100271 if ((bsec_get_status() & BSEC_OTP_STATUS_PWRON) == 0U) {
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100272 result = bsec_power_safmem(true);
273
274 if (result != BSEC_OK) {
275 return result;
276 }
277
278 power_up = true;
279 }
280
281 bsec_lock();
282
Patrick Delaunaye720b5b2022-12-14 13:45:04 +0100283 mmio_write_32(BSEC_BASE + BSEC_OTP_CTRL_OFF, otp | BSEC_READ);
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100284
Patrick Delaunaye720b5b2022-12-14 13:45:04 +0100285 while ((bsec_get_status() & BSEC_OTP_STATUS_BUSY) != 0U) {
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100286 ;
287 }
288
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +0200289 result = bsec_check_error(otp, true);
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100290
291 bsec_unlock();
292
293 if (power_up) {
294 if (bsec_power_safmem(false) != BSEC_OK) {
295 panic();
296 }
297 }
298
299 return result;
300}
301
302/*
303 * bsec_read_otp: read an OTP data value.
304 * val: read value.
305 * otp: OTP number.
306 * return value: BSEC_OK if no error.
307 */
308uint32_t bsec_read_otp(uint32_t *val, uint32_t otp)
309{
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +0200310 if (is_otp_invalid_mode()) {
311 return BSEC_ERROR;
312 }
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100313
314 if (otp > STM32MP1_OTP_MAX_ID) {
315 return BSEC_INVALID_PARAM;
316 }
317
Patrick Delaunaye720b5b2022-12-14 13:45:04 +0100318 *val = mmio_read_32(BSEC_BASE + BSEC_OTP_DATA_OFF +
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100319 (otp * sizeof(uint32_t)));
320
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +0200321 return BSEC_OK;
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100322}
323
324/*
325 * bsec_write_otp: write value in BSEC data register.
326 * val: value to write.
327 * otp: OTP number.
328 * return value: BSEC_OK if no error.
329 */
330uint32_t bsec_write_otp(uint32_t val, uint32_t otp)
331{
332 uint32_t result;
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +0200333 bool value;
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100334
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +0200335 if (is_otp_invalid_mode()) {
336 return BSEC_ERROR;
337 }
338
339 result = bsec_read_sw_lock(otp, &value);
340 if (result != BSEC_OK) {
341 ERROR("BSEC: %u Sticky-write bit read Error %u\n", otp, result);
342 return result;
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100343 }
344
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +0200345 if (value) {
346 VERBOSE("BSEC: OTP %u is locked and write will be ignored\n",
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100347 otp);
348 }
349
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +0200350 /* Ensure integrity of each register access sequence */
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100351 bsec_lock();
352
Patrick Delaunaye720b5b2022-12-14 13:45:04 +0100353 mmio_write_32(BSEC_BASE + BSEC_OTP_DATA_OFF +
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100354 (otp * sizeof(uint32_t)), val);
355
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100356 bsec_unlock();
357
358 return result;
359}
360
361/*
362 * bsec_program_otp: program a bit in SAFMEM after the prog.
363 * The OTP data is not refreshed.
364 * val: value to program.
365 * otp: OTP number.
366 * return value: BSEC_OK if no error.
367 */
368uint32_t bsec_program_otp(uint32_t val, uint32_t otp)
369{
370 uint32_t result;
371 bool power_up = false;
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +0200372 bool sp_lock;
373 bool perm_lock;
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100374
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +0200375 if (is_otp_invalid_mode()) {
376 return BSEC_ERROR;
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100377 }
378
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +0200379 result = bsec_read_sp_lock(otp, &sp_lock);
380 if (result != BSEC_OK) {
381 ERROR("BSEC: %u Sticky-prog bit read Error %u\n", otp, result);
382 return result;
383 }
384
385 result = bsec_read_permanent_lock(otp, &perm_lock);
386 if (result != BSEC_OK) {
387 ERROR("BSEC: %u permanent bit read Error %u\n", otp, result);
388 return result;
389 }
390
391 if (sp_lock || perm_lock) {
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100392 WARN("BSEC: OTP locked, prog will be ignored\n");
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +0200393 return BSEC_PROG_FAIL;
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100394 }
395
Patrick Delaunaye720b5b2022-12-14 13:45:04 +0100396 if ((mmio_read_32(BSEC_BASE + BSEC_OTP_LOCK_OFF) & GPLOCK_LOCK_MASK) != 0U) {
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100397 WARN("BSEC: GPLOCK activated, prog will be ignored\n");
398 }
399
Patrick Delaunaye720b5b2022-12-14 13:45:04 +0100400 if ((bsec_get_status() & BSEC_OTP_STATUS_PWRON) == 0U) {
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100401 result = bsec_power_safmem(true);
402
403 if (result != BSEC_OK) {
404 return result;
405 }
406
407 power_up = true;
408 }
409
410 bsec_lock();
411
Patrick Delaunaye720b5b2022-12-14 13:45:04 +0100412 mmio_write_32(BSEC_BASE + BSEC_OTP_WRDATA_OFF, val);
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100413
Patrick Delaunaye720b5b2022-12-14 13:45:04 +0100414 mmio_write_32(BSEC_BASE + BSEC_OTP_CTRL_OFF, otp | BSEC_WRITE);
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100415
Patrick Delaunaye720b5b2022-12-14 13:45:04 +0100416 while ((bsec_get_status() & BSEC_OTP_STATUS_BUSY) != 0U) {
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100417 ;
418 }
419
Patrick Delaunaye720b5b2022-12-14 13:45:04 +0100420 if ((bsec_get_status() & BSEC_OTP_STATUS_PROGFAIL) != 0U) {
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100421 result = BSEC_PROG_FAIL;
422 } else {
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +0200423 result = bsec_check_error(otp, true);
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100424 }
425
426 bsec_unlock();
427
428 if (power_up) {
429 if (bsec_power_safmem(false) != BSEC_OK) {
430 panic();
431 }
432 }
433
434 return result;
435}
436
437/*
438 * bsec_permanent_lock_otp: permanent lock of OTP in SAFMEM.
439 * otp: OTP number.
440 * return value: BSEC_OK if no error.
441 */
Patrick Delaunaye720b5b2022-12-14 13:45:04 +0100442#if defined(IMAGE_BL32)
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100443uint32_t bsec_permanent_lock_otp(uint32_t otp)
444{
445 uint32_t result;
446 bool power_up = false;
447 uint32_t data;
448 uint32_t addr;
449
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +0200450 if (is_otp_invalid_mode()) {
451 return BSEC_ERROR;
452 }
453
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100454 if (otp > STM32MP1_OTP_MAX_ID) {
455 return BSEC_INVALID_PARAM;
456 }
457
Patrick Delaunaye720b5b2022-12-14 13:45:04 +0100458 if ((bsec_get_status() & BSEC_OTP_STATUS_PWRON) == 0U) {
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100459 result = bsec_power_safmem(true);
460
461 if (result != BSEC_OK) {
462 return result;
463 }
464
465 power_up = true;
466 }
467
468 if (otp < STM32MP1_UPPER_OTP_START) {
469 addr = otp >> ADDR_LOWER_OTP_PERLOCK_SHIFT;
470 data = DATA_LOWER_OTP_PERLOCK_BIT <<
471 ((otp & DATA_LOWER_OTP_PERLOCK_MASK) << 1U);
472 } else {
473 addr = (otp >> ADDR_UPPER_OTP_PERLOCK_SHIFT) + 2U;
474 data = DATA_UPPER_OTP_PERLOCK_BIT <<
475 (otp & DATA_UPPER_OTP_PERLOCK_MASK);
476 }
477
478 bsec_lock();
479
Patrick Delaunaye720b5b2022-12-14 13:45:04 +0100480 mmio_write_32(BSEC_BASE + BSEC_OTP_WRDATA_OFF, data);
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100481
Patrick Delaunaye720b5b2022-12-14 13:45:04 +0100482 mmio_write_32(BSEC_BASE + BSEC_OTP_CTRL_OFF,
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100483 addr | BSEC_WRITE | BSEC_LOCK);
484
Patrick Delaunaye720b5b2022-12-14 13:45:04 +0100485 while ((bsec_get_status() & BSEC_OTP_STATUS_BUSY) != 0U) {
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100486 ;
487 }
488
Patrick Delaunaye720b5b2022-12-14 13:45:04 +0100489 if ((bsec_get_status() & BSEC_OTP_STATUS_PROGFAIL) != 0U) {
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100490 result = BSEC_PROG_FAIL;
491 } else {
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +0200492 result = bsec_check_error(otp, false);
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100493 }
494
495 bsec_unlock();
496
497 if (power_up) {
498 if (bsec_power_safmem(false) != BSEC_OK) {
499 panic();
500 }
501 }
502
503 return result;
504}
Patrick Delaunaye720b5b2022-12-14 13:45:04 +0100505#endif
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100506
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +0200507/*
508 * bsec_read_debug_conf: return debug configuration register value.
509 */
510uint32_t bsec_read_debug_conf(void)
511{
Patrick Delaunaye720b5b2022-12-14 13:45:04 +0100512 return mmio_read_32(BSEC_BASE + BSEC_DEN_OFF);
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +0200513}
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100514
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +0200515/*
516 * bsec_write_scratch: write value in scratch register.
517 * val: value to write.
518 * return value: none.
519 */
520void bsec_write_scratch(uint32_t val)
521{
522#if defined(IMAGE_BL32)
523 if (is_otp_invalid_mode()) {
524 return;
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100525 }
526
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +0200527 bsec_lock();
Patrick Delaunaye720b5b2022-12-14 13:45:04 +0100528 mmio_write_32(BSEC_BASE + BSEC_SCRATCH_OFF, val);
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100529 bsec_unlock();
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +0200530#else
531 mmio_write_32(BSEC_BASE + BSEC_SCRATCH_OFF, val);
532#endif
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100533}
534
535/*
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100536 * bsec_get_status: return status register value.
537 */
Patrick Delaunaye720b5b2022-12-14 13:45:04 +0100538static uint32_t bsec_get_status(void)
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100539{
Patrick Delaunaye720b5b2022-12-14 13:45:04 +0100540 return mmio_read_32(BSEC_BASE + BSEC_OTP_STATUS_OFF);
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100541}
542
543/*
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +0200544 * bsec_get_version: return BSEC version register value.
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100545 */
Patrick Delaunaye720b5b2022-12-14 13:45:04 +0100546static uint32_t bsec_get_version(void)
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100547{
Patrick Delaunaye720b5b2022-12-14 13:45:04 +0100548 return mmio_read_32(BSEC_BASE + BSEC_IPVR_OFF) & BSEC_IPVR_MSK;
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100549}
550
551/*
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +0200552 * bsec_get_id: return BSEC ID register value.
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100553 */
Patrick Delaunaye720b5b2022-12-14 13:45:04 +0100554static uint32_t bsec_get_id(void)
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100555{
Patrick Delaunaye720b5b2022-12-14 13:45:04 +0100556 return mmio_read_32(BSEC_BASE + BSEC_IP_ID_OFF);
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100557}
558
559/*
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +0200560 * bsec_set_sr_lock: set shadow-read lock.
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100561 * otp: OTP number.
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +0200562 * return value: BSEC_OK if no error.
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100563 */
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +0200564uint32_t bsec_set_sr_lock(uint32_t otp)
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100565{
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100566 uint32_t bank = otp_bank_offset(otp);
Patrick Delaunaye720b5b2022-12-14 13:45:04 +0100567 uint32_t otp_mask = otp_bit_mask(otp);
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100568
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +0200569 if (is_otp_invalid_mode()) {
570 return BSEC_ERROR;
571 }
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100572
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +0200573 if (otp > STM32MP1_OTP_MAX_ID) {
574 return BSEC_INVALID_PARAM;
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100575 }
576
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +0200577 bsec_lock();
Patrick Delaunaye720b5b2022-12-14 13:45:04 +0100578 mmio_write_32(BSEC_BASE + BSEC_SRLOCK_OFF + bank, otp_mask);
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100579 bsec_unlock();
580
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +0200581 return BSEC_OK;
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100582}
583
584/*
585 * bsec_read_sr_lock: read shadow-read lock.
586 * otp: OTP number.
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +0200587 * value: read value (true or false).
588 * return value: BSEC_OK if no error.
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100589 */
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +0200590uint32_t bsec_read_sr_lock(uint32_t otp, bool *value)
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100591{
592 uint32_t bank = otp_bank_offset(otp);
Patrick Delaunaye720b5b2022-12-14 13:45:04 +0100593 uint32_t otp_mask = otp_bit_mask(otp);
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +0200594 uint32_t bank_value;
595
596 if (otp > STM32MP1_OTP_MAX_ID) {
597 return BSEC_INVALID_PARAM;
598 }
599
Patrick Delaunaye720b5b2022-12-14 13:45:04 +0100600 bank_value = mmio_read_32(BSEC_BASE + BSEC_SRLOCK_OFF + bank);
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100601
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +0200602 *value = ((bank_value & otp_mask) != 0U);
603
604 return BSEC_OK;
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100605}
606
607/*
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +0200608 * bsec_set_sw_lock: set shadow-write lock.
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100609 * otp: OTP number.
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +0200610 * return value: BSEC_OK if no error.
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100611 */
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +0200612uint32_t bsec_set_sw_lock(uint32_t otp)
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100613{
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100614 uint32_t bank = otp_bank_offset(otp);
Patrick Delaunaye720b5b2022-12-14 13:45:04 +0100615 uint32_t otp_mask = otp_bit_mask(otp);
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100616
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +0200617 if (is_otp_invalid_mode()) {
618 return BSEC_ERROR;
619 }
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100620
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +0200621 if (otp > STM32MP1_OTP_MAX_ID) {
622 return BSEC_INVALID_PARAM;
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100623 }
624
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +0200625 bsec_lock();
Patrick Delaunaye720b5b2022-12-14 13:45:04 +0100626 mmio_write_32(BSEC_BASE + BSEC_SWLOCK_OFF + bank, otp_mask);
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100627 bsec_unlock();
628
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +0200629 return BSEC_OK;
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100630}
631
632/*
633 * bsec_read_sw_lock: read shadow-write lock.
634 * otp: OTP number.
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +0200635 * value: read value (true or false).
636 * return value: BSEC_OK if no error.
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100637 */
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +0200638uint32_t bsec_read_sw_lock(uint32_t otp, bool *value)
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100639{
640 uint32_t bank = otp_bank_offset(otp);
641 uint32_t otp_mask = BIT(otp & BSEC_OTP_MASK);
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +0200642 uint32_t bank_value;
643
644 if (otp > STM32MP1_OTP_MAX_ID) {
645 return BSEC_INVALID_PARAM;
646 }
647
Patrick Delaunaye720b5b2022-12-14 13:45:04 +0100648 bank_value = mmio_read_32(BSEC_BASE + BSEC_SWLOCK_OFF + bank);
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +0200649
650 *value = ((bank_value & otp_mask) != 0U);
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100651
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +0200652 return BSEC_OK;
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100653}
654
655/*
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +0200656 * bsec_set_sp_lock: set shadow-program lock.
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100657 * otp: OTP number.
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +0200658 * return value: BSEC_OK if no error.
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100659 */
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +0200660uint32_t bsec_set_sp_lock(uint32_t otp)
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100661{
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100662 uint32_t bank = otp_bank_offset(otp);
Patrick Delaunaye720b5b2022-12-14 13:45:04 +0100663 uint32_t otp_mask = otp_bit_mask(otp);
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100664
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +0200665 if (is_otp_invalid_mode()) {
666 return BSEC_ERROR;
667 }
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100668
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +0200669 if (otp > STM32MP1_OTP_MAX_ID) {
670 return BSEC_INVALID_PARAM;
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100671 }
672
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +0200673 bsec_lock();
Patrick Delaunaye720b5b2022-12-14 13:45:04 +0100674 mmio_write_32(BSEC_BASE + BSEC_SPLOCK_OFF + bank, otp_mask);
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100675 bsec_unlock();
676
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +0200677 return BSEC_OK;
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100678}
679
680/*
681 * bsec_read_sp_lock: read shadow-program lock.
682 * otp: OTP number.
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +0200683 * value: read value (true or false).
684 * return value: BSEC_OK if no error.
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100685 */
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +0200686uint32_t bsec_read_sp_lock(uint32_t otp, bool *value)
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100687{
688 uint32_t bank = otp_bank_offset(otp);
689 uint32_t otp_mask = BIT(otp & BSEC_OTP_MASK);
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +0200690 uint32_t bank_value;
691
692 if (otp > STM32MP1_OTP_MAX_ID) {
693 return BSEC_INVALID_PARAM;
694 }
695
Patrick Delaunaye720b5b2022-12-14 13:45:04 +0100696 bank_value = mmio_read_32(BSEC_BASE + BSEC_SPLOCK_OFF + bank);
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100697
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +0200698 *value = ((bank_value & otp_mask) != 0U);
699
700 return BSEC_OK;
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100701}
702
703/*
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +0200704 * bsec_read_permanent_lock: Read permanent lock status.
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100705 * otp: OTP number.
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +0200706 * value: read value (true or false).
707 * return value: BSEC_OK if no error.
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100708 */
Patrick Delaunaye720b5b2022-12-14 13:45:04 +0100709static uint32_t bsec_read_permanent_lock(uint32_t otp, bool *value)
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100710{
711 uint32_t bank = otp_bank_offset(otp);
Patrick Delaunaye720b5b2022-12-14 13:45:04 +0100712 uint32_t otp_mask = otp_bit_mask(otp);
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +0200713 uint32_t bank_value;
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100714
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +0200715 if (otp > STM32MP1_OTP_MAX_ID) {
716 return BSEC_INVALID_PARAM;
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100717 }
718
Patrick Delaunaye720b5b2022-12-14 13:45:04 +0100719 bank_value = mmio_read_32(BSEC_BASE + BSEC_WRLOCK_OFF + bank);
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +0200720
721 *value = ((bank_value & otp_mask) != 0U);
722
723 return BSEC_OK;
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100724}
725
726/*
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100727 * bsec_power_safmem: Activate or deactivate SAFMEM power.
728 * power: true to power up, false to power down.
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +0200729 * return value: BSEC_OK if no error.
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100730 */
731static uint32_t bsec_power_safmem(bool power)
732{
733 uint32_t register_val;
734 uint32_t timeout = BSEC_TIMEOUT_VALUE;
735
736 bsec_lock();
737
Patrick Delaunaye720b5b2022-12-14 13:45:04 +0100738 register_val = mmio_read_32(BSEC_BASE + BSEC_OTP_CONF_OFF);
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100739
740 if (power) {
741 register_val |= BSEC_CONF_POWER_UP_MASK;
742 } else {
743 register_val &= ~BSEC_CONF_POWER_UP_MASK;
744 }
745
Patrick Delaunaye720b5b2022-12-14 13:45:04 +0100746 mmio_write_32(BSEC_BASE + BSEC_OTP_CONF_OFF, register_val);
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100747
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100748 if (power) {
Patrick Delaunaye720b5b2022-12-14 13:45:04 +0100749 while (((bsec_get_status() & BSEC_OTP_STATUS_PWRON) == 0U) &&
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100750 (timeout != 0U)) {
751 timeout--;
752 }
753 } else {
Patrick Delaunaye720b5b2022-12-14 13:45:04 +0100754 while (((bsec_get_status() & BSEC_OTP_STATUS_PWRON) != 0U) &&
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100755 (timeout != 0U)) {
756 timeout--;
757 }
758 }
759
760 bsec_unlock();
761
762 if (timeout == 0U) {
763 return BSEC_TIMEOUT;
764 }
765
766 return BSEC_OK;
767}
768
769/*
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +0200770 * bsec_shadow_read_otp: Load OTP from SAFMEM and provide its value.
Patrick Delaunaye720b5b2022-12-14 13:45:04 +0100771 * val: read value.
772 * otp: OTP number.
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100773 * return value: BSEC_OK if no error.
774 */
Patrick Delaunaye720b5b2022-12-14 13:45:04 +0100775uint32_t bsec_shadow_read_otp(uint32_t *val, uint32_t otp)
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100776{
777 uint32_t result;
778
Patrick Delaunaye720b5b2022-12-14 13:45:04 +0100779 result = bsec_shadow_register(otp);
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100780 if (result != BSEC_OK) {
Patrick Delaunaye720b5b2022-12-14 13:45:04 +0100781 ERROR("BSEC: %u Shadowing Error %u\n", otp, result);
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100782 return result;
783 }
784
Patrick Delaunaye720b5b2022-12-14 13:45:04 +0100785 result = bsec_read_otp(val, otp);
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100786 if (result != BSEC_OK) {
Patrick Delaunaye720b5b2022-12-14 13:45:04 +0100787 ERROR("BSEC: %u Read Error %u\n", otp, result);
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100788 }
789
790 return result;
791}
792
Patrick Delaunaye720b5b2022-12-14 13:45:04 +0100793#if defined(IMAGE_BL32)
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100794/*
795 * bsec_check_nsec_access_rights: check non-secure access rights to target OTP.
796 * otp: OTP number.
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +0200797 * return value: BSEC_OK if authorized access.
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100798 */
799uint32_t bsec_check_nsec_access_rights(uint32_t otp)
800{
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100801 if (otp > STM32MP1_OTP_MAX_ID) {
802 return BSEC_INVALID_PARAM;
803 }
804
805 if (otp >= STM32MP1_UPPER_OTP_START) {
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +0200806 if (!non_secure_can_access(otp)) {
807 return BSEC_ERROR;
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100808 }
809 }
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100810
811 return BSEC_OK;
812}
Patrick Delaunaye720b5b2022-12-14 13:45:04 +0100813#endif
814
815uint32_t bsec_get_secure_state(void)
816{
817 uint32_t status = bsec_get_status();
818 uint32_t result = BSEC_STATE_INVALID;
819 uint32_t otp_enc_id __maybe_unused;
820 uint32_t otp_bit_len __maybe_unused;
821 int res __maybe_unused;
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100822
Patrick Delaunaye720b5b2022-12-14 13:45:04 +0100823 if ((status & BSEC_OTP_STATUS_INVALID) != 0U) {
824 result = BSEC_STATE_INVALID;
825 } else {
826 if ((status & BSEC_OTP_STATUS_SECURE) != 0U) {
Yann Gautier3e334752023-02-01 15:04:30 +0100827 if (stm32mp_check_closed_device() == STM32MP_CHIP_SEC_CLOSED) {
Patrick Delaunaye720b5b2022-12-14 13:45:04 +0100828 result = BSEC_STATE_SEC_CLOSED;
829 } else {
830 result = BSEC_STATE_SEC_OPEN;
831 }
832 } else {
833 /* OTP modes OPEN1 and OPEN2 are not supported */
834 result = BSEC_STATE_INVALID;
835 }
836 }
837
838 return result;
839}