blob: 68d3a5b89674b8b61c58c03a828836f04d35b280 [file] [log] [blame]
Yann Gautier36a1e4b2019-01-17 14:52:47 +01001/*
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +02002 * Copyright (c) 2017-2022, 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
24#define OTP_ACCESS_SIZE (round_up(OTP_MAX_SIZE, __WORD_BIT) / __WORD_BIT)
25
26static uint32_t otp_nsec_access[OTP_ACCESS_SIZE] __unused;
27
28static uint32_t bsec_power_safmem(bool power);
29
30/* BSEC access protection */
31static spinlock_t bsec_spinlock;
32static uintptr_t bsec_base;
33
34static void bsec_lock(void)
35{
Yann Gautierf540a592019-05-22 19:13:51 +020036 if (stm32mp_lock_available()) {
Yann Gautier36a1e4b2019-01-17 14:52:47 +010037 spin_lock(&bsec_spinlock);
38 }
39}
40
41static void bsec_unlock(void)
42{
Yann Gautierf540a592019-05-22 19:13:51 +020043 if (stm32mp_lock_available()) {
Yann Gautier36a1e4b2019-01-17 14:52:47 +010044 spin_unlock(&bsec_spinlock);
45 }
46}
47
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +020048static bool is_otp_invalid_mode(void)
49{
50 bool ret = ((bsec_get_status() & BSEC_MODE_INVALID) == BSEC_MODE_INVALID);
51
52 if (ret) {
53 ERROR("OTP mode is OTP-INVALID\n");
54 }
55
56 return ret;
57}
58
59#if defined(IMAGE_BL32)
Yann Gautier36a1e4b2019-01-17 14:52:47 +010060static int bsec_get_dt_node(struct dt_node_info *info)
61{
62 int node;
63
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +020064 node = dt_get_node(info, -1, DT_BSEC_COMPAT);
Yann Gautier36a1e4b2019-01-17 14:52:47 +010065 if (node < 0) {
66 return -FDT_ERR_NOTFOUND;
67 }
68
69 return node;
70}
71
Yann Gautier36a1e4b2019-01-17 14:52:47 +010072static void enable_non_secure_access(uint32_t otp)
73{
74 otp_nsec_access[otp / __WORD_BIT] |= BIT(otp % __WORD_BIT);
75
76 if (bsec_shadow_register(otp) != BSEC_OK) {
77 panic();
78 }
79}
80
81static bool non_secure_can_access(uint32_t otp)
82{
83 return (otp_nsec_access[otp / __WORD_BIT] &
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +020084 BIT(otp % __WORD_BIT)) != 0U;
Yann Gautier36a1e4b2019-01-17 14:52:47 +010085}
86
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +020087static void bsec_dt_otp_nsec_access(void *fdt, int bsec_node)
Yann Gautier36a1e4b2019-01-17 14:52:47 +010088{
89 int bsec_subnode;
90
91 fdt_for_each_subnode(bsec_subnode, fdt, bsec_node) {
92 const fdt32_t *cuint;
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +020093 uint32_t otp;
Yann Gautier36a1e4b2019-01-17 14:52:47 +010094 uint32_t i;
95 uint32_t size;
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +020096 uint32_t offset;
97 uint32_t length;
Yann Gautier36a1e4b2019-01-17 14:52:47 +010098
99 cuint = fdt_getprop(fdt, bsec_subnode, "reg", NULL);
100 if (cuint == NULL) {
101 panic();
102 }
103
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +0200104 offset = fdt32_to_cpu(*cuint);
105 cuint++;
106 length = fdt32_to_cpu(*cuint);
107
108 otp = offset / sizeof(uint32_t);
109
110 if (otp < STM32MP1_UPPER_OTP_START) {
111 unsigned int otp_end = round_up(offset + length,
112 sizeof(uint32_t)) /
113 sizeof(uint32_t);
114
115 if (otp_end > STM32MP1_UPPER_OTP_START) {
116 /*
117 * OTP crosses Lower/Upper boundary, consider
118 * only the upper part.
119 */
120 otp = STM32MP1_UPPER_OTP_START;
121 length -= (STM32MP1_UPPER_OTP_START *
122 sizeof(uint32_t)) - offset;
123 offset = STM32MP1_UPPER_OTP_START *
124 sizeof(uint32_t);
125
126 WARN("OTP crosses Lower/Upper boundary\n");
127 } else {
128 continue;
129 }
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100130 }
131
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +0200132 if ((fdt_getprop(fdt, bsec_subnode,
133 "st,non-secure-otp", NULL)) == NULL) {
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100134 continue;
135 }
136
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +0200137 if (((offset % sizeof(uint32_t)) != 0U) ||
138 ((length % sizeof(uint32_t)) != 0U)) {
139 ERROR("Unaligned non-secure OTP\n");
140 panic();
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100141 }
142
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +0200143 size = length / sizeof(uint32_t);
144
145 for (i = otp; i < (otp + size); i++) {
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100146 enable_non_secure_access(i);
147 }
148 }
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +0200149}
150
151static void bsec_late_init(void)
152{
153 void *fdt;
154 int node;
155 struct dt_node_info bsec_info;
156
157 if (fdt_get_address(&fdt) == 0) {
158 panic();
159 }
160
161 node = bsec_get_dt_node(&bsec_info);
162 if (node < 0) {
163 panic();
164 }
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100165
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +0200166 assert(bsec_base == bsec_info.base);
167
168 bsec_dt_otp_nsec_access(fdt, node);
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100169}
170#endif
171
172static uint32_t otp_bank_offset(uint32_t otp)
173{
174 assert(otp <= STM32MP1_OTP_MAX_ID);
175
176 return ((otp & ~BSEC_OTP_MASK) >> BSEC_OTP_BANK_SHIFT) *
177 sizeof(uint32_t);
178}
179
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +0200180/*
181 * bsec_check_error: check BSEC error status.
182 * otp: OTP number.
183 * check_disturbed: check only error (false),
184 * or error and disturbed status (true).
185 * return value: BSEC_OK if no error.
186 */
187static uint32_t bsec_check_error(uint32_t otp, bool check_disturbed)
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100188{
189 uint32_t bit = BIT(otp & BSEC_OTP_MASK);
190 uint32_t bank = otp_bank_offset(otp);
191
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100192 if ((mmio_read_32(bsec_base + BSEC_ERROR_OFF + bank) & bit) != 0U) {
193 return BSEC_ERROR;
194 }
195
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +0200196 if (!check_disturbed) {
197 return BSEC_OK;
198 }
199
200 if ((mmio_read_32(bsec_base + BSEC_DISTURBED_OFF + bank) & bit) != 0U) {
201 return BSEC_DISTURBED;
202 }
203
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100204 return BSEC_OK;
205}
206
207/*
208 * bsec_probe: initialize BSEC driver.
209 * return value: BSEC_OK if no error.
210 */
211uint32_t bsec_probe(void)
212{
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +0200213 bsec_base = BSEC_BASE;
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100214
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +0200215 if (is_otp_invalid_mode()) {
216 return BSEC_ERROR;
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100217 }
218
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +0200219 if ((((bsec_get_version() & BSEC_IPVR_MSK) != BSEC_IP_VERSION_1_1) &&
220 ((bsec_get_version() & BSEC_IPVR_MSK) != BSEC_IP_VERSION_2_0)) ||
221 (bsec_get_id() != BSEC_IP_ID_2)) {
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100222 panic();
223 }
224
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100225#if defined(IMAGE_BL32)
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +0200226 bsec_late_init();
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100227#endif
228 return BSEC_OK;
229}
230
231/*
232 * bsec_get_base: return BSEC base address.
233 */
234uint32_t bsec_get_base(void)
235{
236 return bsec_base;
237}
238
239/*
240 * bsec_set_config: enable and configure BSEC.
241 * cfg: pointer to param structure used to set register.
242 * return value: BSEC_OK if no error.
243 */
244uint32_t bsec_set_config(struct bsec_config *cfg)
245{
246 uint32_t value;
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +0200247 uint32_t result;
248
249 if (is_otp_invalid_mode()) {
250 return BSEC_ERROR;
251 }
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100252
253 value = ((((uint32_t)cfg->freq << BSEC_CONF_FRQ_SHIFT) &
254 BSEC_CONF_FRQ_MASK) |
255 (((uint32_t)cfg->pulse_width << BSEC_CONF_PRG_WIDTH_SHIFT) &
256 BSEC_CONF_PRG_WIDTH_MASK) |
257 (((uint32_t)cfg->tread << BSEC_CONF_TREAD_SHIFT) &
258 BSEC_CONF_TREAD_MASK));
259
260 bsec_lock();
261
262 mmio_write_32(bsec_base + BSEC_OTP_CONF_OFF, value);
263
264 bsec_unlock();
265
266 result = bsec_power_safmem((bool)cfg->power &
267 BSEC_CONF_POWER_UP_MASK);
268 if (result != BSEC_OK) {
269 return result;
270 }
271
272 value = ((((uint32_t)cfg->upper_otp_lock << UPPER_OTP_LOCK_SHIFT) &
273 UPPER_OTP_LOCK_MASK) |
274 (((uint32_t)cfg->den_lock << DENREG_LOCK_SHIFT) &
275 DENREG_LOCK_MASK) |
276 (((uint32_t)cfg->prog_lock << GPLOCK_LOCK_SHIFT) &
277 GPLOCK_LOCK_MASK));
278
279 bsec_lock();
280
281 mmio_write_32(bsec_base + BSEC_OTP_LOCK_OFF, value);
282
283 bsec_unlock();
284
285 return BSEC_OK;
286}
287
288/*
289 * bsec_get_config: return config parameters set in BSEC registers.
290 * cfg: config param return.
291 * return value: BSEC_OK if no error.
292 */
293uint32_t bsec_get_config(struct bsec_config *cfg)
294{
295 uint32_t value;
296
297 if (cfg == NULL) {
298 return BSEC_INVALID_PARAM;
299 }
300
301 value = mmio_read_32(bsec_base + BSEC_OTP_CONF_OFF);
302 cfg->power = (uint8_t)((value & BSEC_CONF_POWER_UP_MASK) >>
303 BSEC_CONF_POWER_UP_SHIFT);
304 cfg->freq = (uint8_t)((value & BSEC_CONF_FRQ_MASK) >>
305 BSEC_CONF_FRQ_SHIFT);
306 cfg->pulse_width = (uint8_t)((value & BSEC_CONF_PRG_WIDTH_MASK) >>
307 BSEC_CONF_PRG_WIDTH_SHIFT);
308 cfg->tread = (uint8_t)((value & BSEC_CONF_TREAD_MASK) >>
309 BSEC_CONF_TREAD_SHIFT);
310
311 value = mmio_read_32(bsec_base + BSEC_OTP_LOCK_OFF);
312 cfg->upper_otp_lock = (uint8_t)((value & UPPER_OTP_LOCK_MASK) >>
313 UPPER_OTP_LOCK_SHIFT);
314 cfg->den_lock = (uint8_t)((value & DENREG_LOCK_MASK) >>
315 DENREG_LOCK_SHIFT);
316 cfg->prog_lock = (uint8_t)((value & GPLOCK_LOCK_MASK) >>
317 GPLOCK_LOCK_SHIFT);
318
319 return BSEC_OK;
320}
321
322/*
323 * bsec_shadow_register: copy SAFMEM OTP to BSEC data.
324 * otp: OTP number.
325 * return value: BSEC_OK if no error.
326 */
327uint32_t bsec_shadow_register(uint32_t otp)
328{
329 uint32_t result;
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +0200330 bool value;
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100331 bool power_up = false;
332
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +0200333 if (is_otp_invalid_mode()) {
334 return BSEC_ERROR;
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100335 }
336
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +0200337 result = bsec_read_sr_lock(otp, &value);
338 if (result != BSEC_OK) {
339 ERROR("BSEC: %u Sticky-read bit read Error %u\n", otp, result);
340 return result;
341 }
342
343 if (value) {
344 VERBOSE("BSEC: OTP %u is locked and will not be refreshed\n",
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100345 otp);
346 }
347
348 if ((bsec_get_status() & BSEC_MODE_PWR_MASK) == 0U) {
349 result = bsec_power_safmem(true);
350
351 if (result != BSEC_OK) {
352 return result;
353 }
354
355 power_up = true;
356 }
357
358 bsec_lock();
359
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100360 mmio_write_32(bsec_base + BSEC_OTP_CTRL_OFF, otp | BSEC_READ);
361
362 while ((bsec_get_status() & BSEC_MODE_BUSY_MASK) != 0U) {
363 ;
364 }
365
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +0200366 result = bsec_check_error(otp, true);
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100367
368 bsec_unlock();
369
370 if (power_up) {
371 if (bsec_power_safmem(false) != BSEC_OK) {
372 panic();
373 }
374 }
375
376 return result;
377}
378
379/*
380 * bsec_read_otp: read an OTP data value.
381 * val: read value.
382 * otp: OTP number.
383 * return value: BSEC_OK if no error.
384 */
385uint32_t bsec_read_otp(uint32_t *val, uint32_t otp)
386{
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +0200387 if (is_otp_invalid_mode()) {
388 return BSEC_ERROR;
389 }
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100390
391 if (otp > STM32MP1_OTP_MAX_ID) {
392 return BSEC_INVALID_PARAM;
393 }
394
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100395 *val = mmio_read_32(bsec_base + BSEC_OTP_DATA_OFF +
396 (otp * sizeof(uint32_t)));
397
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +0200398 return BSEC_OK;
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100399}
400
401/*
402 * bsec_write_otp: write value in BSEC data register.
403 * val: value to write.
404 * otp: OTP number.
405 * return value: BSEC_OK if no error.
406 */
407uint32_t bsec_write_otp(uint32_t val, uint32_t otp)
408{
409 uint32_t result;
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +0200410 bool value;
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100411
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +0200412 if (is_otp_invalid_mode()) {
413 return BSEC_ERROR;
414 }
415
416 result = bsec_read_sw_lock(otp, &value);
417 if (result != BSEC_OK) {
418 ERROR("BSEC: %u Sticky-write bit read Error %u\n", otp, result);
419 return result;
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100420 }
421
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +0200422 if (value) {
423 VERBOSE("BSEC: OTP %u is locked and write will be ignored\n",
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100424 otp);
425 }
426
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +0200427 /* Ensure integrity of each register access sequence */
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100428 bsec_lock();
429
430 mmio_write_32(bsec_base + BSEC_OTP_DATA_OFF +
431 (otp * sizeof(uint32_t)), val);
432
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100433 bsec_unlock();
434
435 return result;
436}
437
438/*
439 * bsec_program_otp: program a bit in SAFMEM after the prog.
440 * The OTP data is not refreshed.
441 * val: value to program.
442 * otp: OTP number.
443 * return value: BSEC_OK if no error.
444 */
445uint32_t bsec_program_otp(uint32_t val, uint32_t otp)
446{
447 uint32_t result;
448 bool power_up = false;
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +0200449 bool sp_lock;
450 bool perm_lock;
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100451
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +0200452 if (is_otp_invalid_mode()) {
453 return BSEC_ERROR;
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100454 }
455
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +0200456 result = bsec_read_sp_lock(otp, &sp_lock);
457 if (result != BSEC_OK) {
458 ERROR("BSEC: %u Sticky-prog bit read Error %u\n", otp, result);
459 return result;
460 }
461
462 result = bsec_read_permanent_lock(otp, &perm_lock);
463 if (result != BSEC_OK) {
464 ERROR("BSEC: %u permanent bit read Error %u\n", otp, result);
465 return result;
466 }
467
468 if (sp_lock || perm_lock) {
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100469 WARN("BSEC: OTP locked, prog will be ignored\n");
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +0200470 return BSEC_PROG_FAIL;
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100471 }
472
473 if ((mmio_read_32(bsec_base + BSEC_OTP_LOCK_OFF) &
474 BIT(BSEC_LOCK_PROGRAM)) != 0U) {
475 WARN("BSEC: GPLOCK activated, prog will be ignored\n");
476 }
477
478 if ((bsec_get_status() & BSEC_MODE_PWR_MASK) == 0U) {
479 result = bsec_power_safmem(true);
480
481 if (result != BSEC_OK) {
482 return result;
483 }
484
485 power_up = true;
486 }
487
488 bsec_lock();
489
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100490 mmio_write_32(bsec_base + BSEC_OTP_WRDATA_OFF, val);
491
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100492 mmio_write_32(bsec_base + BSEC_OTP_CTRL_OFF, otp | BSEC_WRITE);
493
494 while ((bsec_get_status() & BSEC_MODE_BUSY_MASK) != 0U) {
495 ;
496 }
497
498 if ((bsec_get_status() & BSEC_MODE_PROGFAIL_MASK) != 0U) {
499 result = BSEC_PROG_FAIL;
500 } else {
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +0200501 result = bsec_check_error(otp, true);
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100502 }
503
504 bsec_unlock();
505
506 if (power_up) {
507 if (bsec_power_safmem(false) != BSEC_OK) {
508 panic();
509 }
510 }
511
512 return result;
513}
514
515/*
516 * bsec_permanent_lock_otp: permanent lock of OTP in SAFMEM.
517 * otp: OTP number.
518 * return value: BSEC_OK if no error.
519 */
520uint32_t bsec_permanent_lock_otp(uint32_t otp)
521{
522 uint32_t result;
523 bool power_up = false;
524 uint32_t data;
525 uint32_t addr;
526
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +0200527 if (is_otp_invalid_mode()) {
528 return BSEC_ERROR;
529 }
530
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100531 if (otp > STM32MP1_OTP_MAX_ID) {
532 return BSEC_INVALID_PARAM;
533 }
534
535 if ((bsec_get_status() & BSEC_MODE_PWR_MASK) == 0U) {
536 result = bsec_power_safmem(true);
537
538 if (result != BSEC_OK) {
539 return result;
540 }
541
542 power_up = true;
543 }
544
545 if (otp < STM32MP1_UPPER_OTP_START) {
546 addr = otp >> ADDR_LOWER_OTP_PERLOCK_SHIFT;
547 data = DATA_LOWER_OTP_PERLOCK_BIT <<
548 ((otp & DATA_LOWER_OTP_PERLOCK_MASK) << 1U);
549 } else {
550 addr = (otp >> ADDR_UPPER_OTP_PERLOCK_SHIFT) + 2U;
551 data = DATA_UPPER_OTP_PERLOCK_BIT <<
552 (otp & DATA_UPPER_OTP_PERLOCK_MASK);
553 }
554
555 bsec_lock();
556
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100557 mmio_write_32(bsec_base + BSEC_OTP_WRDATA_OFF, data);
558
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100559 mmio_write_32(bsec_base + BSEC_OTP_CTRL_OFF,
560 addr | BSEC_WRITE | BSEC_LOCK);
561
562 while ((bsec_get_status() & BSEC_MODE_BUSY_MASK) != 0U) {
563 ;
564 }
565
566 if ((bsec_get_status() & BSEC_MODE_PROGFAIL_MASK) != 0U) {
567 result = BSEC_PROG_FAIL;
568 } else {
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +0200569 result = bsec_check_error(otp, false);
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100570 }
571
572 bsec_unlock();
573
574 if (power_up) {
575 if (bsec_power_safmem(false) != BSEC_OK) {
576 panic();
577 }
578 }
579
580 return result;
581}
582
583/*
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +0200584 * bsec_write_debug_conf: write value in debug feature.
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100585 * to enable/disable debug service.
586 * val: value to write.
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +0200587 * return value: none.
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100588 */
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +0200589void bsec_write_debug_conf(uint32_t val)
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100590{
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +0200591 if (is_otp_invalid_mode()) {
592 return;
593 }
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100594
595 bsec_lock();
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +0200596 mmio_write_32(bsec_base + BSEC_DEN_OFF, val & BSEC_DEN_ALL_MSK);
597 bsec_unlock();
598}
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100599
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +0200600/*
601 * bsec_read_debug_conf: return debug configuration register value.
602 */
603uint32_t bsec_read_debug_conf(void)
604{
605 return mmio_read_32(bsec_base + BSEC_DEN_OFF);
606}
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100607
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +0200608/*
609 * bsec_write_scratch: write value in scratch register.
610 * val: value to write.
611 * return value: none.
612 */
613void bsec_write_scratch(uint32_t val)
614{
615#if defined(IMAGE_BL32)
616 if (is_otp_invalid_mode()) {
617 return;
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100618 }
619
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +0200620 bsec_lock();
621 mmio_write_32(bsec_base + BSEC_SCRATCH_OFF, val);
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100622 bsec_unlock();
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +0200623#else
624 mmio_write_32(BSEC_BASE + BSEC_SCRATCH_OFF, val);
625#endif
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100626}
627
628/*
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +0200629 * bsec_read_scratch: return scratch register value.
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100630 */
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +0200631uint32_t bsec_read_scratch(void)
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100632{
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +0200633 return mmio_read_32(bsec_base + BSEC_SCRATCH_OFF);
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100634}
635
636/*
637 * bsec_get_status: return status register value.
638 */
639uint32_t bsec_get_status(void)
640{
641 return mmio_read_32(bsec_base + BSEC_OTP_STATUS_OFF);
642}
643
644/*
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +0200645 * bsec_get_hw_conf: return hardware configuration register value.
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100646 */
647uint32_t bsec_get_hw_conf(void)
648{
649 return mmio_read_32(bsec_base + BSEC_IPHW_CFG_OFF);
650}
651
652/*
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +0200653 * bsec_get_version: return BSEC version register value.
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100654 */
655uint32_t bsec_get_version(void)
656{
657 return mmio_read_32(bsec_base + BSEC_IPVR_OFF);
658}
659
660/*
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +0200661 * bsec_get_id: return BSEC ID register value.
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100662 */
663uint32_t bsec_get_id(void)
664{
665 return mmio_read_32(bsec_base + BSEC_IP_ID_OFF);
666}
667
668/*
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +0200669 * bsec_get_magic_id: return BSEC magic number register value.
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100670 */
671uint32_t bsec_get_magic_id(void)
672{
673 return mmio_read_32(bsec_base + BSEC_IP_MAGIC_ID_OFF);
674}
675
676/*
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +0200677 * bsec_set_sr_lock: set shadow-read lock.
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100678 * otp: OTP number.
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +0200679 * return value: BSEC_OK if no error.
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100680 */
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +0200681uint32_t bsec_set_sr_lock(uint32_t otp)
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100682{
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100683 uint32_t bank = otp_bank_offset(otp);
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100684 uint32_t otp_mask = BIT(otp & BSEC_OTP_MASK);
685
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +0200686 if (is_otp_invalid_mode()) {
687 return BSEC_ERROR;
688 }
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100689
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +0200690 if (otp > STM32MP1_OTP_MAX_ID) {
691 return BSEC_INVALID_PARAM;
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100692 }
693
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +0200694 bsec_lock();
695 mmio_write_32(bsec_base + BSEC_SRLOCK_OFF + bank, otp_mask);
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100696 bsec_unlock();
697
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +0200698 return BSEC_OK;
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100699}
700
701/*
702 * bsec_read_sr_lock: read shadow-read lock.
703 * otp: OTP number.
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +0200704 * value: read value (true or false).
705 * return value: BSEC_OK if no error.
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100706 */
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +0200707uint32_t bsec_read_sr_lock(uint32_t otp, bool *value)
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100708{
709 uint32_t bank = otp_bank_offset(otp);
710 uint32_t otp_mask = BIT(otp & BSEC_OTP_MASK);
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +0200711 uint32_t bank_value;
712
713 if (otp > STM32MP1_OTP_MAX_ID) {
714 return BSEC_INVALID_PARAM;
715 }
716
717 bank_value = mmio_read_32(bsec_base + BSEC_SRLOCK_OFF + bank);
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100718
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +0200719 *value = ((bank_value & otp_mask) != 0U);
720
721 return BSEC_OK;
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100722}
723
724/*
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +0200725 * bsec_set_sw_lock: set shadow-write lock.
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100726 * otp: OTP number.
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +0200727 * return value: BSEC_OK if no error.
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100728 */
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +0200729uint32_t bsec_set_sw_lock(uint32_t otp)
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100730{
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100731 uint32_t bank = otp_bank_offset(otp);
732 uint32_t otp_mask = BIT(otp & BSEC_OTP_MASK);
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100733
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +0200734 if (is_otp_invalid_mode()) {
735 return BSEC_ERROR;
736 }
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100737
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +0200738 if (otp > STM32MP1_OTP_MAX_ID) {
739 return BSEC_INVALID_PARAM;
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100740 }
741
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +0200742 bsec_lock();
743 mmio_write_32(bsec_base + BSEC_SWLOCK_OFF + bank, otp_mask);
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100744 bsec_unlock();
745
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +0200746 return BSEC_OK;
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100747}
748
749/*
750 * bsec_read_sw_lock: read shadow-write lock.
751 * otp: OTP number.
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +0200752 * value: read value (true or false).
753 * return value: BSEC_OK if no error.
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100754 */
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +0200755uint32_t bsec_read_sw_lock(uint32_t otp, bool *value)
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100756{
757 uint32_t bank = otp_bank_offset(otp);
758 uint32_t otp_mask = BIT(otp & BSEC_OTP_MASK);
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +0200759 uint32_t bank_value;
760
761 if (otp > STM32MP1_OTP_MAX_ID) {
762 return BSEC_INVALID_PARAM;
763 }
764
765 bank_value = mmio_read_32(bsec_base + BSEC_SWLOCK_OFF + bank);
766
767 *value = ((bank_value & otp_mask) != 0U);
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100768
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +0200769 return BSEC_OK;
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100770}
771
772/*
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +0200773 * bsec_set_sp_lock: set shadow-program lock.
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100774 * otp: OTP number.
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +0200775 * return value: BSEC_OK if no error.
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100776 */
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +0200777uint32_t bsec_set_sp_lock(uint32_t otp)
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100778{
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100779 uint32_t bank = otp_bank_offset(otp);
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100780 uint32_t otp_mask = BIT(otp & BSEC_OTP_MASK);
781
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +0200782 if (is_otp_invalid_mode()) {
783 return BSEC_ERROR;
784 }
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100785
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +0200786 if (otp > STM32MP1_OTP_MAX_ID) {
787 return BSEC_INVALID_PARAM;
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100788 }
789
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +0200790 bsec_lock();
791 mmio_write_32(bsec_base + BSEC_SPLOCK_OFF + bank, otp_mask);
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100792 bsec_unlock();
793
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +0200794 return BSEC_OK;
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100795}
796
797/*
798 * bsec_read_sp_lock: read shadow-program lock.
799 * otp: OTP number.
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +0200800 * value: read value (true or false).
801 * return value: BSEC_OK if no error.
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100802 */
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +0200803uint32_t bsec_read_sp_lock(uint32_t otp, bool *value)
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100804{
805 uint32_t bank = otp_bank_offset(otp);
806 uint32_t otp_mask = BIT(otp & BSEC_OTP_MASK);
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +0200807 uint32_t bank_value;
808
809 if (otp > STM32MP1_OTP_MAX_ID) {
810 return BSEC_INVALID_PARAM;
811 }
812
813 bank_value = mmio_read_32(bsec_base + BSEC_SPLOCK_OFF + bank);
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100814
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +0200815 *value = ((bank_value & otp_mask) != 0U);
816
817 return BSEC_OK;
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100818}
819
820/*
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +0200821 * bsec_read_permanent_lock: Read permanent lock status.
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100822 * otp: OTP number.
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +0200823 * value: read value (true or false).
824 * return value: BSEC_OK if no error.
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100825 */
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +0200826uint32_t bsec_read_permanent_lock(uint32_t otp, bool *value)
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100827{
828 uint32_t bank = otp_bank_offset(otp);
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +0200829 uint32_t otp_mask = BIT(otp & BSEC_OTP_MASK);
830 uint32_t bank_value;
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100831
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +0200832 if (otp > STM32MP1_OTP_MAX_ID) {
833 return BSEC_INVALID_PARAM;
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100834 }
835
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +0200836 bank_value = mmio_read_32(bsec_base + BSEC_WRLOCK_OFF + bank);
837
838 *value = ((bank_value & otp_mask) != 0U);
839
840 return BSEC_OK;
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100841}
842
843/*
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +0200844 * bsec_otp_lock: Lock Upper OTP or Global Programming or Debug Enable.
845 * service: Service to lock, see header file.
846 * return value: BSEC_OK if no error.
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100847 */
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +0200848uint32_t bsec_otp_lock(uint32_t service)
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100849{
850 uintptr_t reg = bsec_base + BSEC_OTP_LOCK_OFF;
851
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +0200852 if (is_otp_invalid_mode()) {
853 return BSEC_ERROR;
854 }
855
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100856 switch (service) {
857 case BSEC_LOCK_UPPER_OTP:
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +0200858 mmio_write_32(reg, BIT(BSEC_LOCK_UPPER_OTP));
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100859 break;
860 case BSEC_LOCK_DEBUG:
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +0200861 mmio_write_32(reg, BIT(BSEC_LOCK_DEBUG));
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100862 break;
863 case BSEC_LOCK_PROGRAM:
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +0200864 mmio_write_32(reg, BIT(BSEC_LOCK_PROGRAM));
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100865 break;
866 default:
867 return BSEC_INVALID_PARAM;
868 }
869
870 return BSEC_OK;
871}
872
873/*
874 * bsec_power_safmem: Activate or deactivate SAFMEM power.
875 * power: true to power up, false to power down.
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +0200876 * return value: BSEC_OK if no error.
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100877 */
878static uint32_t bsec_power_safmem(bool power)
879{
880 uint32_t register_val;
881 uint32_t timeout = BSEC_TIMEOUT_VALUE;
882
883 bsec_lock();
884
885 register_val = mmio_read_32(bsec_base + BSEC_OTP_CONF_OFF);
886
887 if (power) {
888 register_val |= BSEC_CONF_POWER_UP_MASK;
889 } else {
890 register_val &= ~BSEC_CONF_POWER_UP_MASK;
891 }
892
893 mmio_write_32(bsec_base + BSEC_OTP_CONF_OFF, register_val);
894
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100895 if (power) {
896 while (((bsec_get_status() & BSEC_MODE_PWR_MASK) == 0U) &&
897 (timeout != 0U)) {
898 timeout--;
899 }
900 } else {
901 while (((bsec_get_status() & BSEC_MODE_PWR_MASK) != 0U) &&
902 (timeout != 0U)) {
903 timeout--;
904 }
905 }
906
907 bsec_unlock();
908
909 if (timeout == 0U) {
910 return BSEC_TIMEOUT;
911 }
912
913 return BSEC_OK;
914}
915
916/*
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +0200917 * bsec_shadow_read_otp: Load OTP from SAFMEM and provide its value.
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100918 * otp_value: read value.
919 * word: OTP number.
920 * return value: BSEC_OK if no error.
921 */
922uint32_t bsec_shadow_read_otp(uint32_t *otp_value, uint32_t word)
923{
924 uint32_t result;
925
926 result = bsec_shadow_register(word);
927 if (result != BSEC_OK) {
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +0200928 ERROR("BSEC: %u Shadowing Error %u\n", word, result);
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100929 return result;
930 }
931
932 result = bsec_read_otp(otp_value, word);
933 if (result != BSEC_OK) {
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +0200934 ERROR("BSEC: %u Read Error %u\n", word, result);
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100935 }
936
937 return result;
938}
939
940/*
941 * bsec_check_nsec_access_rights: check non-secure access rights to target OTP.
942 * otp: OTP number.
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +0200943 * return value: BSEC_OK if authorized access.
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100944 */
945uint32_t bsec_check_nsec_access_rights(uint32_t otp)
946{
947#if defined(IMAGE_BL32)
948 if (otp > STM32MP1_OTP_MAX_ID) {
949 return BSEC_INVALID_PARAM;
950 }
951
952 if (otp >= STM32MP1_UPPER_OTP_START) {
Nicolas Le Bayon97287cd2019-05-20 18:35:02 +0200953 if (!non_secure_can_access(otp)) {
954 return BSEC_ERROR;
Yann Gautier36a1e4b2019-01-17 14:52:47 +0100955 }
956 }
957#endif
958
959 return BSEC_OK;
960}
961