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