xref: /rk3399_ARM-atf/drivers/st/bsec/bsec3.c (revision 9526ad6058720fa6ad0369839c1aa72e60f5ce82)
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