1ae6542f6SNicolas Le Bayon /*
2*6fede181SPatrick Delaunay * Copyright (c) 2024-2025, STMicroelectronics - All Rights Reserved
3ae6542f6SNicolas Le Bayon *
4ae6542f6SNicolas Le Bayon * SPDX-License-Identifier: BSD-3-Clause
5ae6542f6SNicolas Le Bayon */
6ae6542f6SNicolas Le Bayon
7ae6542f6SNicolas Le Bayon #include <assert.h>
8ae6542f6SNicolas Le Bayon #include <limits.h>
9ae6542f6SNicolas Le Bayon
10ae6542f6SNicolas Le Bayon #include <arch_helpers.h>
11ae6542f6SNicolas Le Bayon #include <common/debug.h>
12ae6542f6SNicolas Le Bayon #include <drivers/st/bsec.h>
13ae6542f6SNicolas Le Bayon #include <drivers/st/bsec3_reg.h>
14ae6542f6SNicolas Le Bayon #include <drivers/st/stm32mp_reset.h>
15ae6542f6SNicolas Le Bayon #include <lib/mmio.h>
16ae6542f6SNicolas Le Bayon #include <lib/spinlock.h>
17ae6542f6SNicolas Le Bayon #include <libfdt.h>
18ae6542f6SNicolas Le Bayon
19ae6542f6SNicolas Le Bayon #include <platform_def.h>
20ae6542f6SNicolas Le Bayon
21ae6542f6SNicolas Le Bayon #define BSEC_IP_VERSION_1_0 U(0x10)
22ae6542f6SNicolas Le Bayon #define BSEC_IP_ID_3 U(0x100033)
23ae6542f6SNicolas Le Bayon
24ae6542f6SNicolas Le Bayon #define MAX_NB_TRIES U(3)
25ae6542f6SNicolas Le Bayon
26ae6542f6SNicolas Le Bayon /*
27ae6542f6SNicolas Le Bayon * IP configuration
28ae6542f6SNicolas Le Bayon */
29ae6542f6SNicolas Le Bayon #define BSEC_OTP_MASK GENMASK_32(4, 0)
30ae6542f6SNicolas Le Bayon #define BSEC_OTP_BANK_SHIFT U(5)
31ae6542f6SNicolas Le Bayon #define BSEC_TIMEOUT_VALUE U(0x800000) /* ~7sec @1.2GHz */
32ae6542f6SNicolas Le Bayon
otp_bank(uint32_t otp)33ae6542f6SNicolas Le Bayon static uint32_t otp_bank(uint32_t otp)
34ae6542f6SNicolas Le Bayon {
35ae6542f6SNicolas Le Bayon if (otp > STM32MP2_OTP_MAX_ID) {
36ae6542f6SNicolas Le Bayon panic();
37ae6542f6SNicolas Le Bayon }
38ae6542f6SNicolas Le Bayon
39ae6542f6SNicolas Le Bayon return (otp & ~BSEC_OTP_MASK) >> BSEC_OTP_BANK_SHIFT;
40ae6542f6SNicolas Le Bayon }
41ae6542f6SNicolas Le Bayon
otp_bit_mask(uint32_t otp)42ae6542f6SNicolas Le Bayon static uint32_t otp_bit_mask(uint32_t otp)
43ae6542f6SNicolas Le Bayon {
44ae6542f6SNicolas Le Bayon return BIT(otp & BSEC_OTP_MASK);
45ae6542f6SNicolas Le Bayon }
46ae6542f6SNicolas Le Bayon
47ae6542f6SNicolas Le Bayon /*
48ae6542f6SNicolas Le Bayon * bsec_get_status: return status register value.
49ae6542f6SNicolas Le Bayon */
bsec_get_status(void)50ae6542f6SNicolas Le Bayon static uint32_t bsec_get_status(void)
51ae6542f6SNicolas Le Bayon {
52ae6542f6SNicolas Le Bayon return mmio_read_32(BSEC_BASE + BSEC_OTPSR);
53ae6542f6SNicolas Le Bayon }
54ae6542f6SNicolas Le Bayon
55ae6542f6SNicolas Le Bayon /*
56ae6542f6SNicolas Le Bayon * bsec_get_version: return BSEC version.
57ae6542f6SNicolas Le Bayon */
bsec_get_version(void)58ae6542f6SNicolas Le Bayon static uint32_t bsec_get_version(void)
59ae6542f6SNicolas Le Bayon {
60ae6542f6SNicolas Le Bayon return mmio_read_32(BSEC_BASE + BSEC_VERR) & BSEC_VERR_MASK;
61ae6542f6SNicolas Le Bayon }
62ae6542f6SNicolas Le Bayon
63ae6542f6SNicolas Le Bayon /*
64ae6542f6SNicolas Le Bayon * bsec_get_id: return BSEC ID.
65ae6542f6SNicolas Le Bayon */
bsec_get_id(void)66ae6542f6SNicolas Le Bayon static uint32_t bsec_get_id(void)
67ae6542f6SNicolas Le Bayon {
68ae6542f6SNicolas Le Bayon return mmio_read_32(BSEC_BASE + BSEC_IPIDR);
69ae6542f6SNicolas Le Bayon }
70ae6542f6SNicolas Le Bayon
is_fuse_shadowed(uint32_t otp)71ae6542f6SNicolas Le Bayon static bool is_fuse_shadowed(uint32_t otp)
72ae6542f6SNicolas Le Bayon {
73ae6542f6SNicolas Le Bayon uint32_t bank = otp_bank(otp);
74ae6542f6SNicolas Le Bayon uint32_t otp_mask = otp_bit_mask(otp);
75ae6542f6SNicolas Le Bayon uint32_t bank_value;
76ae6542f6SNicolas Le Bayon
77ae6542f6SNicolas Le Bayon bank_value = mmio_read_32(BSEC_BASE + BSEC_SFSR(bank));
78ae6542f6SNicolas Le Bayon
79ae6542f6SNicolas Le Bayon if ((bank_value & otp_mask) != 0U) {
80ae6542f6SNicolas Le Bayon return true;
81ae6542f6SNicolas Le Bayon }
82ae6542f6SNicolas Le Bayon
83ae6542f6SNicolas Le Bayon return false;
84ae6542f6SNicolas Le Bayon }
85ae6542f6SNicolas Le Bayon
poll_otp_status_busy(void)86ae6542f6SNicolas Le Bayon static void poll_otp_status_busy(void)
87ae6542f6SNicolas Le Bayon {
88ae6542f6SNicolas Le Bayon uint32_t timeout = BSEC_TIMEOUT_VALUE;
89ae6542f6SNicolas Le Bayon
90ae6542f6SNicolas Le Bayon while (((bsec_get_status() & BSEC_OTPSR_BUSY) != 0U) && (timeout != 0U)) {
91ae6542f6SNicolas Le Bayon timeout--;
92ae6542f6SNicolas Le Bayon }
93ae6542f6SNicolas Le Bayon
94ae6542f6SNicolas Le Bayon if ((bsec_get_status() & BSEC_OTPSR_BUSY) != 0U) {
95ae6542f6SNicolas Le Bayon ERROR("BSEC timeout\n");
96ae6542f6SNicolas Le Bayon panic();
97ae6542f6SNicolas Le Bayon }
98ae6542f6SNicolas Le Bayon }
99ae6542f6SNicolas Le Bayon
check_read_error(uint32_t otp)100ae6542f6SNicolas Le Bayon static uint32_t check_read_error(uint32_t otp)
101ae6542f6SNicolas Le Bayon {
102ae6542f6SNicolas Le Bayon uint32_t status = bsec_get_status();
103ae6542f6SNicolas Le Bayon
104ae6542f6SNicolas Le Bayon if ((status & BSEC_OTPSR_SECF) != 0U) {
105ae6542f6SNicolas Le Bayon VERBOSE("BSEC read %u single error correction detected\n", otp);
106ae6542f6SNicolas Le Bayon }
107ae6542f6SNicolas Le Bayon
108ae6542f6SNicolas Le Bayon if ((status & BSEC_OTPSR_PPLF) != 0U) {
109ae6542f6SNicolas Le Bayon VERBOSE("BSEC read %u permanent programming lock detected.\n", otp);
110ae6542f6SNicolas Le Bayon }
111ae6542f6SNicolas Le Bayon
112ae6542f6SNicolas Le Bayon if ((status & BSEC_OTPSR_PPLMF) != 0U) {
113ae6542f6SNicolas Le Bayon ERROR("BSEC read %u error 0x%x\n", otp, status);
114ae6542f6SNicolas Le Bayon return BSEC_ERROR;
115ae6542f6SNicolas Le Bayon }
116ae6542f6SNicolas Le Bayon
117ae6542f6SNicolas Le Bayon if ((status & (BSEC_OTPSR_DISTURBF | BSEC_OTPSR_DEDF | BSEC_OTPSR_AMEF)) != 0U) {
118ae6542f6SNicolas Le Bayon ERROR("BSEC read %u error 0x%x with invalid FVR\n", otp, status);
119ae6542f6SNicolas Le Bayon return BSEC_RETRY;
120ae6542f6SNicolas Le Bayon }
121ae6542f6SNicolas Le Bayon
122ae6542f6SNicolas Le Bayon return BSEC_OK;
123ae6542f6SNicolas Le Bayon }
124ae6542f6SNicolas Le Bayon
check_program_error(uint32_t otp)125ae6542f6SNicolas Le Bayon static uint32_t check_program_error(uint32_t otp)
126ae6542f6SNicolas Le Bayon {
127ae6542f6SNicolas Le Bayon uint32_t status = bsec_get_status();
128ae6542f6SNicolas Le Bayon
129ae6542f6SNicolas Le Bayon if ((status & BSEC_OTPSR_PROGFAIL) != 0U) {
130ae6542f6SNicolas Le Bayon ERROR("BSEC program %u error 0x%x\n", otp, status);
131ae6542f6SNicolas Le Bayon return BSEC_RETRY;
132ae6542f6SNicolas Le Bayon }
133ae6542f6SNicolas Le Bayon
134ae6542f6SNicolas Le Bayon return BSEC_OK;
135ae6542f6SNicolas Le Bayon }
136ae6542f6SNicolas Le Bayon
check_reset_error(void)137ae6542f6SNicolas Le Bayon static void check_reset_error(void)
138ae6542f6SNicolas Le Bayon {
139ae6542f6SNicolas Le Bayon uint32_t status = bsec_get_status();
140ae6542f6SNicolas Le Bayon
141ae6542f6SNicolas Le Bayon /* check initial status reporting */
142ae6542f6SNicolas Le Bayon if ((status & BSEC_OTPSR_BUSY) != 0U) {
143ae6542f6SNicolas Le Bayon VERBOSE("BSEC reset and busy when OTPSR read\n");
144ae6542f6SNicolas Le Bayon }
145ae6542f6SNicolas Le Bayon if ((status & BSEC_OTPSR_HIDEUP) != 0U) {
146ae6542f6SNicolas Le Bayon VERBOSE("BSEC upper fuse are not accessible (HIDEUP)\n");
147ae6542f6SNicolas Le Bayon }
148ae6542f6SNicolas Le Bayon if ((status & BSEC_OTPSR_OTPSEC) != 0U) {
149ae6542f6SNicolas Le Bayon VERBOSE("BSEC reset single error correction detected\n");
150ae6542f6SNicolas Le Bayon }
151ae6542f6SNicolas Le Bayon if ((status & BSEC_OTPSR_OTPNVIR) == 0U) {
152ae6542f6SNicolas Le Bayon VERBOSE("BSEC reset first fuse word 0 is detected zero\n");
153ae6542f6SNicolas Le Bayon }
154ae6542f6SNicolas Le Bayon if ((status & BSEC_OTPSR_OTPERR) != 0U) {
155ae6542f6SNicolas Le Bayon ERROR("BSEC reset critical error 0x%x\n", status);
156ae6542f6SNicolas Le Bayon panic();
157ae6542f6SNicolas Le Bayon }
158*6fede181SPatrick Delaunay if ((status & BSEC_OTPSR_INIT_DONE) != BSEC_OTPSR_INIT_DONE) {
159ae6542f6SNicolas Le Bayon ERROR("BSEC reset critical error 0x%x\n", status);
160ae6542f6SNicolas Le Bayon panic();
161ae6542f6SNicolas Le Bayon }
162ae6542f6SNicolas Le Bayon }
163ae6542f6SNicolas Le Bayon
is_bsec_write_locked(void)164ae6542f6SNicolas Le Bayon static bool is_bsec_write_locked(void)
165ae6542f6SNicolas Le Bayon {
166ae6542f6SNicolas Le Bayon return (mmio_read_32(BSEC_BASE + BSEC_LOCKR) & BSEC_LOCKR_GWLOCK_MASK) != 0U;
167ae6542f6SNicolas Le Bayon }
168ae6542f6SNicolas Le Bayon
169ae6542f6SNicolas Le Bayon /*
170ae6542f6SNicolas Le Bayon * bsec_probe: initialize BSEC driver.
171ae6542f6SNicolas Le Bayon * return value: BSEC_OK if no error.
172ae6542f6SNicolas Le Bayon */
bsec_probe(void)173ae6542f6SNicolas Le Bayon uint32_t bsec_probe(void)
174ae6542f6SNicolas Le Bayon {
175ae6542f6SNicolas Le Bayon uint32_t version = bsec_get_version();
176ae6542f6SNicolas Le Bayon uint32_t id = bsec_get_id();
177ae6542f6SNicolas Le Bayon
178ae6542f6SNicolas Le Bayon if ((version != BSEC_IP_VERSION_1_0) || (id != BSEC_IP_ID_3)) {
179cf237f8dSYann Gautier EARLY_ERROR("%s: version = 0x%x, id = 0x%x\n", __func__, version, id);
180ae6542f6SNicolas Le Bayon panic();
181ae6542f6SNicolas Le Bayon }
182ae6542f6SNicolas Le Bayon
183ae6542f6SNicolas Le Bayon check_reset_error();
184ae6542f6SNicolas Le Bayon
185ae6542f6SNicolas Le Bayon return BSEC_OK;
186ae6542f6SNicolas Le Bayon }
187ae6542f6SNicolas Le Bayon
188ae6542f6SNicolas Le Bayon /*
189ae6542f6SNicolas Le Bayon * bsec_shadow_register: copy SAFMEM OTP to BSEC data.
190ae6542f6SNicolas Le Bayon * otp: OTP number.
191ae6542f6SNicolas Le Bayon * return value: BSEC_OK if no error.
192ae6542f6SNicolas Le Bayon */
bsec_shadow_register(uint32_t otp)193ae6542f6SNicolas Le Bayon static uint32_t bsec_shadow_register(uint32_t otp)
194ae6542f6SNicolas Le Bayon {
195ae6542f6SNicolas Le Bayon uint32_t result;
196ae6542f6SNicolas Le Bayon uint32_t i;
197ae6542f6SNicolas Le Bayon bool value;
198ae6542f6SNicolas Le Bayon
199ae6542f6SNicolas Le Bayon result = bsec_read_sr_lock(otp, &value);
200ae6542f6SNicolas Le Bayon if (result != BSEC_OK) {
201ae6542f6SNicolas Le Bayon WARN("BSEC: %u Sticky-read bit read Error %u\n", otp, result);
202ae6542f6SNicolas Le Bayon } else if (value) {
203ae6542f6SNicolas Le Bayon VERBOSE("BSEC: OTP %u is locked and will not be refreshed\n", otp);
204ae6542f6SNicolas Le Bayon }
205ae6542f6SNicolas Le Bayon
206ae6542f6SNicolas Le Bayon for (i = 0U; i < MAX_NB_TRIES; i++) {
207ae6542f6SNicolas Le Bayon mmio_write_32(BSEC_BASE + BSEC_OTPCR, otp);
208ae6542f6SNicolas Le Bayon
209ae6542f6SNicolas Le Bayon poll_otp_status_busy();
210ae6542f6SNicolas Le Bayon
211ae6542f6SNicolas Le Bayon result = check_read_error(otp);
212ae6542f6SNicolas Le Bayon if (result != BSEC_RETRY) {
213ae6542f6SNicolas Le Bayon break;
214ae6542f6SNicolas Le Bayon }
215ae6542f6SNicolas Le Bayon }
216ae6542f6SNicolas Le Bayon
217ae6542f6SNicolas Le Bayon return result;
218ae6542f6SNicolas Le Bayon }
219ae6542f6SNicolas Le Bayon
220ae6542f6SNicolas Le Bayon /*
221ae6542f6SNicolas Le Bayon * bsec_write_otp: write a value in shadow OTP.
222ae6542f6SNicolas Le Bayon * val: value to program.
223ae6542f6SNicolas Le Bayon * otp: OTP number.
224ae6542f6SNicolas Le Bayon * return value: BSEC_OK if no error.
225ae6542f6SNicolas Le Bayon */
bsec_write_otp(uint32_t val,uint32_t otp)226ae6542f6SNicolas Le Bayon uint32_t bsec_write_otp(uint32_t val, uint32_t otp)
227ae6542f6SNicolas Le Bayon {
228ae6542f6SNicolas Le Bayon bool state;
229ae6542f6SNicolas Le Bayon uint32_t result;
230ae6542f6SNicolas Le Bayon
231ae6542f6SNicolas Le Bayon if (otp > STM32MP2_OTP_MAX_ID) {
232ae6542f6SNicolas Le Bayon panic();
233ae6542f6SNicolas Le Bayon }
234ae6542f6SNicolas Le Bayon
235ae6542f6SNicolas Le Bayon if (!is_fuse_shadowed(otp)) {
236ae6542f6SNicolas Le Bayon return BSEC_ERROR;
237ae6542f6SNicolas Le Bayon }
238ae6542f6SNicolas Le Bayon
239ae6542f6SNicolas Le Bayon if (is_bsec_write_locked()) {
240ae6542f6SNicolas Le Bayon return BSEC_WRITE_LOCKED;
241ae6542f6SNicolas Le Bayon }
242ae6542f6SNicolas Le Bayon
243ae6542f6SNicolas Le Bayon result = bsec_read_sw_lock(otp, &state);
244ae6542f6SNicolas Le Bayon if (result != BSEC_OK) {
245ae6542f6SNicolas Le Bayon WARN("Shadow register is SW locked\n");
246ae6542f6SNicolas Le Bayon return result;
247ae6542f6SNicolas Le Bayon }
248ae6542f6SNicolas Le Bayon
249ae6542f6SNicolas Le Bayon mmio_write_32(BSEC_BASE + BSEC_FVR(otp), val);
250ae6542f6SNicolas Le Bayon
251ae6542f6SNicolas Le Bayon return BSEC_OK;
252ae6542f6SNicolas Le Bayon }
253ae6542f6SNicolas Le Bayon
254ae6542f6SNicolas Le Bayon /*
255ae6542f6SNicolas Le Bayon * bsec_program_otp: program a bit in SAFMEM after the prog.
256ae6542f6SNicolas Le Bayon * The OTP data is not refreshed.
257ae6542f6SNicolas Le Bayon * val: value to program.
258ae6542f6SNicolas Le Bayon * otp: OTP number.
259ae6542f6SNicolas Le Bayon * return value: BSEC_OK if no error.
260ae6542f6SNicolas Le Bayon */
bsec_program_otp(uint32_t val,uint32_t otp)261ae6542f6SNicolas Le Bayon uint32_t bsec_program_otp(uint32_t val, uint32_t otp)
262ae6542f6SNicolas Le Bayon {
263ae6542f6SNicolas Le Bayon uint32_t result;
264ae6542f6SNicolas Le Bayon uint32_t i;
265ae6542f6SNicolas Le Bayon bool value;
266ae6542f6SNicolas Le Bayon
267ae6542f6SNicolas Le Bayon if (otp > STM32MP2_OTP_MAX_ID) {
268ae6542f6SNicolas Le Bayon panic();
269ae6542f6SNicolas Le Bayon }
270ae6542f6SNicolas Le Bayon
271ae6542f6SNicolas Le Bayon if (is_bsec_write_locked() == true) {
272ae6542f6SNicolas Le Bayon return BSEC_WRITE_LOCKED;
273ae6542f6SNicolas Le Bayon }
274ae6542f6SNicolas Le Bayon
275ae6542f6SNicolas Le Bayon result = bsec_read_sp_lock(otp, &value);
276ae6542f6SNicolas Le Bayon if (result != BSEC_OK) {
277ae6542f6SNicolas Le Bayon WARN("BSEC: %u Sticky-prog bit read Error %u\n", otp, result);
278ae6542f6SNicolas Le Bayon } else if (value) {
279ae6542f6SNicolas Le Bayon WARN("BSEC: OTP locked, prog will be ignored\n");
280ae6542f6SNicolas Le Bayon return BSEC_WRITE_LOCKED;
281ae6542f6SNicolas Le Bayon }
282ae6542f6SNicolas Le Bayon
283ae6542f6SNicolas Le Bayon mmio_write_32(BSEC_BASE + BSEC_WDR, val);
284ae6542f6SNicolas Le Bayon
285ae6542f6SNicolas Le Bayon for (i = 0U; i < MAX_NB_TRIES; i++) {
286ae6542f6SNicolas Le Bayon mmio_write_32(BSEC_BASE + BSEC_OTPCR, otp | BSEC_OTPCR_PROG);
287ae6542f6SNicolas Le Bayon
288ae6542f6SNicolas Le Bayon poll_otp_status_busy();
289ae6542f6SNicolas Le Bayon
290ae6542f6SNicolas Le Bayon result = check_program_error(otp);
291ae6542f6SNicolas Le Bayon if (result != BSEC_RETRY) {
292ae6542f6SNicolas Le Bayon break;
293ae6542f6SNicolas Le Bayon }
294ae6542f6SNicolas Le Bayon }
295ae6542f6SNicolas Le Bayon
296ae6542f6SNicolas Le Bayon return result;
297ae6542f6SNicolas Le Bayon }
298ae6542f6SNicolas Le Bayon
299ae6542f6SNicolas Le Bayon /*
300ae6542f6SNicolas Le Bayon * bsec_read_debug_conf: read debug configuration.
301ae6542f6SNicolas Le Bayon */
bsec_read_debug_conf(void)302ae6542f6SNicolas Le Bayon uint32_t bsec_read_debug_conf(void)
303ae6542f6SNicolas Le Bayon {
304ae6542f6SNicolas Le Bayon return mmio_read_32(BSEC_BASE + BSEC_DENR);
305ae6542f6SNicolas Le Bayon }
306ae6542f6SNicolas Le Bayon
bsec_lock_register_set(uint32_t offset,uint32_t mask)307ae6542f6SNicolas Le Bayon static uint32_t bsec_lock_register_set(uint32_t offset, uint32_t mask)
308ae6542f6SNicolas Le Bayon {
309ae6542f6SNicolas Le Bayon uint32_t value = mmio_read_32(BSEC_BASE + offset);
310ae6542f6SNicolas Le Bayon
311ae6542f6SNicolas Le Bayon /* The lock is already set */
312ae6542f6SNicolas Le Bayon if ((value & mask) != 0U) {
313ae6542f6SNicolas Le Bayon return BSEC_OK;
314ae6542f6SNicolas Le Bayon }
315ae6542f6SNicolas Le Bayon
316ae6542f6SNicolas Le Bayon if (is_bsec_write_locked()) {
317ae6542f6SNicolas Le Bayon return BSEC_WRITE_LOCKED;
318ae6542f6SNicolas Le Bayon }
319ae6542f6SNicolas Le Bayon
320ae6542f6SNicolas Le Bayon value |= mask;
321ae6542f6SNicolas Le Bayon
322ae6542f6SNicolas Le Bayon mmio_write_32(BSEC_BASE + offset, value);
323ae6542f6SNicolas Le Bayon
324ae6542f6SNicolas Le Bayon return BSEC_OK;
325ae6542f6SNicolas Le Bayon }
326ae6542f6SNicolas Le Bayon
bsec_lock_register_get(uint32_t offset,uint32_t mask)327ae6542f6SNicolas Le Bayon static bool bsec_lock_register_get(uint32_t offset, uint32_t mask)
328ae6542f6SNicolas Le Bayon {
329ae6542f6SNicolas Le Bayon uint32_t value = mmio_read_32(BSEC_BASE + offset);
330ae6542f6SNicolas Le Bayon
331ae6542f6SNicolas Le Bayon return (value & mask) != 0U;
332ae6542f6SNicolas Le Bayon }
333ae6542f6SNicolas Le Bayon
334ae6542f6SNicolas Le Bayon /*
335ae6542f6SNicolas Le Bayon * bsec_set_sr_lock: set shadow-read lock.
336ae6542f6SNicolas Le Bayon * otp: OTP number.
337ae6542f6SNicolas Le Bayon * return value: BSEC_OK if no error.
338ae6542f6SNicolas Le Bayon */
bsec_set_sr_lock(uint32_t otp)339ae6542f6SNicolas Le Bayon uint32_t bsec_set_sr_lock(uint32_t otp)
340ae6542f6SNicolas Le Bayon {
341ae6542f6SNicolas Le Bayon uint32_t bank = otp_bank(otp);
342ae6542f6SNicolas Le Bayon uint32_t otp_mask = otp_bit_mask(otp);
343ae6542f6SNicolas Le Bayon
344ae6542f6SNicolas Le Bayon if (otp > STM32MP2_OTP_MAX_ID) {
345ae6542f6SNicolas Le Bayon panic();
346ae6542f6SNicolas Le Bayon }
347ae6542f6SNicolas Le Bayon
348ae6542f6SNicolas Le Bayon return bsec_lock_register_set(BSEC_SRLOCK(bank), otp_mask);
349ae6542f6SNicolas Le Bayon }
350ae6542f6SNicolas Le Bayon
351ae6542f6SNicolas Le Bayon /*
352ae6542f6SNicolas Le Bayon * bsec_read_sr_lock: read shadow-read lock.
353ae6542f6SNicolas Le Bayon * otp: OTP number.
354ae6542f6SNicolas Le Bayon * value: read value (true or false).
355ae6542f6SNicolas Le Bayon * return value: BSEC_OK if no error.
356ae6542f6SNicolas Le Bayon */
bsec_read_sr_lock(uint32_t otp,bool * value)357ae6542f6SNicolas Le Bayon uint32_t bsec_read_sr_lock(uint32_t otp, bool *value)
358ae6542f6SNicolas Le Bayon {
359ae6542f6SNicolas Le Bayon uint32_t bank = otp_bank(otp);
360ae6542f6SNicolas Le Bayon uint32_t otp_mask = otp_bit_mask(otp);
361ae6542f6SNicolas Le Bayon
362ae6542f6SNicolas Le Bayon assert(value != NULL);
363ae6542f6SNicolas Le Bayon if (otp > STM32MP2_OTP_MAX_ID) {
364ae6542f6SNicolas Le Bayon panic();
365ae6542f6SNicolas Le Bayon }
366ae6542f6SNicolas Le Bayon
367ae6542f6SNicolas Le Bayon *value = bsec_lock_register_get(BSEC_SRLOCK(bank), otp_mask);
368ae6542f6SNicolas Le Bayon
369ae6542f6SNicolas Le Bayon return BSEC_OK;
370ae6542f6SNicolas Le Bayon }
371ae6542f6SNicolas Le Bayon
372ae6542f6SNicolas Le Bayon /*
373ae6542f6SNicolas Le Bayon * bsec_set_sw_lock: set shadow-write lock.
374ae6542f6SNicolas Le Bayon * otp: OTP number.
375ae6542f6SNicolas Le Bayon * return value: BSEC_OK if no error.
376ae6542f6SNicolas Le Bayon */
bsec_set_sw_lock(uint32_t otp)377ae6542f6SNicolas Le Bayon uint32_t bsec_set_sw_lock(uint32_t otp)
378ae6542f6SNicolas Le Bayon {
379ae6542f6SNicolas Le Bayon uint32_t bank = otp_bank(otp);
380ae6542f6SNicolas Le Bayon uint32_t otp_mask = otp_bit_mask(otp);
381ae6542f6SNicolas Le Bayon
382ae6542f6SNicolas Le Bayon if (otp > STM32MP2_OTP_MAX_ID) {
383ae6542f6SNicolas Le Bayon panic();
384ae6542f6SNicolas Le Bayon }
385ae6542f6SNicolas Le Bayon
386ae6542f6SNicolas Le Bayon return bsec_lock_register_set(BSEC_SWLOCK(bank), otp_mask);
387ae6542f6SNicolas Le Bayon }
388ae6542f6SNicolas Le Bayon
389ae6542f6SNicolas Le Bayon /*
390ae6542f6SNicolas Le Bayon * bsec_read_sw_lock: read shadow-write lock.
391ae6542f6SNicolas Le Bayon * otp: OTP number.
392ae6542f6SNicolas Le Bayon * value: read value (true or false).
393ae6542f6SNicolas Le Bayon * return value: BSEC_OK if no error.
394ae6542f6SNicolas Le Bayon */
bsec_read_sw_lock(uint32_t otp,bool * value)395ae6542f6SNicolas Le Bayon uint32_t bsec_read_sw_lock(uint32_t otp, bool *value)
396ae6542f6SNicolas Le Bayon {
397ae6542f6SNicolas Le Bayon uint32_t bank = otp_bank(otp);
398ae6542f6SNicolas Le Bayon uint32_t otp_mask = otp_bit_mask(otp);
399ae6542f6SNicolas Le Bayon
400ae6542f6SNicolas Le Bayon assert(value != NULL);
401ae6542f6SNicolas Le Bayon if (otp > STM32MP2_OTP_MAX_ID) {
402ae6542f6SNicolas Le Bayon panic();
403ae6542f6SNicolas Le Bayon }
404ae6542f6SNicolas Le Bayon
405ae6542f6SNicolas Le Bayon *value = bsec_lock_register_get(BSEC_SWLOCK(bank), otp_mask);
406ae6542f6SNicolas Le Bayon
407ae6542f6SNicolas Le Bayon return BSEC_OK;
408ae6542f6SNicolas Le Bayon }
409ae6542f6SNicolas Le Bayon
410ae6542f6SNicolas Le Bayon /*
411ae6542f6SNicolas Le Bayon * bsec_set_sp_lock: set shadow-program lock.
412ae6542f6SNicolas Le Bayon * otp: OTP number.
413ae6542f6SNicolas Le Bayon * return value: BSEC_OK if no error.
414ae6542f6SNicolas Le Bayon */
bsec_set_sp_lock(uint32_t otp)415ae6542f6SNicolas Le Bayon uint32_t bsec_set_sp_lock(uint32_t otp)
416ae6542f6SNicolas Le Bayon {
417ae6542f6SNicolas Le Bayon uint32_t bank = otp_bank(otp);
418ae6542f6SNicolas Le Bayon uint32_t otp_mask = otp_bit_mask(otp);
419ae6542f6SNicolas Le Bayon
420ae6542f6SNicolas Le Bayon if (otp > STM32MP2_OTP_MAX_ID) {
421ae6542f6SNicolas Le Bayon panic();
422ae6542f6SNicolas Le Bayon }
423ae6542f6SNicolas Le Bayon
424ae6542f6SNicolas Le Bayon return bsec_lock_register_set(BSEC_SPLOCK(bank), otp_mask);
425ae6542f6SNicolas Le Bayon }
426ae6542f6SNicolas Le Bayon
427ae6542f6SNicolas Le Bayon /*
428ae6542f6SNicolas Le Bayon * bsec_read_sp_lock: read shadow-program lock.
429ae6542f6SNicolas Le Bayon * otp: OTP number.
430ae6542f6SNicolas Le Bayon * value: read value (true or false).
431ae6542f6SNicolas Le Bayon * return value: BSEC_OK if no error.
432ae6542f6SNicolas Le Bayon */
bsec_read_sp_lock(uint32_t otp,bool * value)433ae6542f6SNicolas Le Bayon uint32_t bsec_read_sp_lock(uint32_t otp, bool *value)
434ae6542f6SNicolas Le Bayon {
435ae6542f6SNicolas Le Bayon uint32_t bank = otp_bank(otp);
436ae6542f6SNicolas Le Bayon uint32_t otp_mask = otp_bit_mask(otp);
437ae6542f6SNicolas Le Bayon
438ae6542f6SNicolas Le Bayon assert(value != NULL);
439ae6542f6SNicolas Le Bayon if (otp > STM32MP2_OTP_MAX_ID) {
440ae6542f6SNicolas Le Bayon panic();
441ae6542f6SNicolas Le Bayon }
442ae6542f6SNicolas Le Bayon
443ae6542f6SNicolas Le Bayon *value = bsec_lock_register_get(BSEC_SPLOCK(bank), otp_mask);
444ae6542f6SNicolas Le Bayon
445ae6542f6SNicolas Le Bayon return BSEC_OK;
446ae6542f6SNicolas Le Bayon }
447ae6542f6SNicolas Le Bayon
448ae6542f6SNicolas Le Bayon /*
449ae6542f6SNicolas Le Bayon * bsec_get_secure_state: read state in BSEC status register.
450ae6542f6SNicolas Le Bayon * return: secure state
451ae6542f6SNicolas Le Bayon */
bsec_get_secure_state(void)452ae6542f6SNicolas Le Bayon uint32_t bsec_get_secure_state(void)
453ae6542f6SNicolas Le Bayon {
454ae6542f6SNicolas Le Bayon uint32_t state = BSEC_STATE_INVALID;
455ae6542f6SNicolas Le Bayon uint32_t status = bsec_get_status();
456ae6542f6SNicolas Le Bayon uint32_t bsec_sr = mmio_read_32(BSEC_BASE + BSEC_SR);
457ae6542f6SNicolas Le Bayon
458*6fede181SPatrick Delaunay if ((status & BSEC_OTPSR_INIT_DONE) == BSEC_OTPSR_INIT_DONE) {
459*6fede181SPatrick Delaunay /* NVSTATE is only valid if INIT_DONE */
460ae6542f6SNicolas Le Bayon uint32_t nvstates = (bsec_sr & BSEC_SR_NVSTATE_MASK) >> BSEC_SR_NVSTATE_SHIFT;
461ae6542f6SNicolas Le Bayon
462ae6542f6SNicolas Le Bayon if (nvstates == BSEC_SR_NVSTATE_OPEN) {
463ae6542f6SNicolas Le Bayon state = BSEC_STATE_SEC_OPEN;
464ae6542f6SNicolas Le Bayon } else if (nvstates == BSEC_SR_NVSTATE_CLOSED) {
465ae6542f6SNicolas Le Bayon state = BSEC_STATE_SEC_CLOSED;
466ae6542f6SNicolas Le Bayon } else {
467ae6542f6SNicolas Le Bayon VERBOSE("%s nvstates = %u\n", __func__, nvstates);
468ae6542f6SNicolas Le Bayon }
469ae6542f6SNicolas Le Bayon }
470ae6542f6SNicolas Le Bayon
471ae6542f6SNicolas Le Bayon return state;
472ae6542f6SNicolas Le Bayon }
473ae6542f6SNicolas Le Bayon
474ae6542f6SNicolas Le Bayon /*
475ae6542f6SNicolas Le Bayon * bsec_shadow_read_otp: Load OTP from SAFMEM and provide its value
476ae6542f6SNicolas Le Bayon * val: read value.
477ae6542f6SNicolas Le Bayon * otp: OTP number.
478ae6542f6SNicolas Le Bayon * return value: BSEC_OK if no error.
479ae6542f6SNicolas Le Bayon */
bsec_shadow_read_otp(uint32_t * val,uint32_t otp)480ae6542f6SNicolas Le Bayon uint32_t bsec_shadow_read_otp(uint32_t *val, uint32_t otp)
481ae6542f6SNicolas Le Bayon {
482ae6542f6SNicolas Le Bayon assert(val != NULL);
483ae6542f6SNicolas Le Bayon if (otp > STM32MP2_OTP_MAX_ID) {
484ae6542f6SNicolas Le Bayon panic();
485ae6542f6SNicolas Le Bayon }
486ae6542f6SNicolas Le Bayon
487ae6542f6SNicolas Le Bayon *val = 0U;
488ae6542f6SNicolas Le Bayon
489ae6542f6SNicolas Le Bayon if (is_bsec_write_locked()) {
490ae6542f6SNicolas Le Bayon return BSEC_WRITE_LOCKED;
491ae6542f6SNicolas Le Bayon }
492ae6542f6SNicolas Le Bayon
493ae6542f6SNicolas Le Bayon if (!is_fuse_shadowed(otp)) {
494ae6542f6SNicolas Le Bayon uint32_t result = bsec_shadow_register(otp);
495ae6542f6SNicolas Le Bayon
496ae6542f6SNicolas Le Bayon if (result != BSEC_OK) {
497ae6542f6SNicolas Le Bayon ERROR("BSEC: %u Shadowing Error %u\n", otp, result);
498ae6542f6SNicolas Le Bayon return result;
499ae6542f6SNicolas Le Bayon }
500ae6542f6SNicolas Le Bayon }
501ae6542f6SNicolas Le Bayon
502ae6542f6SNicolas Le Bayon *val = mmio_read_32(BSEC_BASE + BSEC_FVR(otp));
503ae6542f6SNicolas Le Bayon
504ae6542f6SNicolas Le Bayon return BSEC_OK;
505ae6542f6SNicolas Le Bayon }
506ae6542f6SNicolas Le Bayon
507ae6542f6SNicolas Le Bayon /*
508ae6542f6SNicolas Le Bayon * bsec_read_otp: read an OTP data value.
509ae6542f6SNicolas Le Bayon * val: read value.
510ae6542f6SNicolas Le Bayon * otp: OTP number.
511ae6542f6SNicolas Le Bayon * return value: BSEC_OK if no error.
512ae6542f6SNicolas Le Bayon */
bsec_read_otp(uint32_t * val,uint32_t otp)513ae6542f6SNicolas Le Bayon uint32_t bsec_read_otp(uint32_t *val, uint32_t otp)
514ae6542f6SNicolas Le Bayon {
515ae6542f6SNicolas Le Bayon assert(val != NULL);
516ae6542f6SNicolas Le Bayon if (otp > STM32MP2_OTP_MAX_ID) {
517ae6542f6SNicolas Le Bayon panic();
518ae6542f6SNicolas Le Bayon }
519ae6542f6SNicolas Le Bayon
520ae6542f6SNicolas Le Bayon return bsec_shadow_read_otp(val, otp);
521ae6542f6SNicolas Le Bayon }
522