xref: /aosp_15_r20/external/arm-trusted-firmware/drivers/st/bsec/bsec.c (revision 54fd6939e177f8ff529b10183254802c76df6d08)
1*54fd6939SJiyong Park /*
2*54fd6939SJiyong Park  * Copyright (c) 2017-2019, STMicroelectronics - All Rights Reserved
3*54fd6939SJiyong Park  *
4*54fd6939SJiyong Park  * SPDX-License-Identifier: BSD-3-Clause
5*54fd6939SJiyong Park  */
6*54fd6939SJiyong Park 
7*54fd6939SJiyong Park #include <assert.h>
8*54fd6939SJiyong Park #include <limits.h>
9*54fd6939SJiyong Park 
10*54fd6939SJiyong Park #include <libfdt.h>
11*54fd6939SJiyong Park 
12*54fd6939SJiyong Park #include <platform_def.h>
13*54fd6939SJiyong Park 
14*54fd6939SJiyong Park #include <arch_helpers.h>
15*54fd6939SJiyong Park #include <common/debug.h>
16*54fd6939SJiyong Park #include <drivers/st/bsec.h>
17*54fd6939SJiyong Park #include <lib/mmio.h>
18*54fd6939SJiyong Park #include <lib/spinlock.h>
19*54fd6939SJiyong Park 
20*54fd6939SJiyong Park #define BSEC_IP_VERSION_1_0	0x10
21*54fd6939SJiyong Park #define BSEC_COMPAT		"st,stm32mp15-bsec"
22*54fd6939SJiyong Park 
23*54fd6939SJiyong Park #define OTP_ACCESS_SIZE (round_up(OTP_MAX_SIZE, __WORD_BIT) / __WORD_BIT)
24*54fd6939SJiyong Park 
25*54fd6939SJiyong Park static uint32_t otp_nsec_access[OTP_ACCESS_SIZE] __unused;
26*54fd6939SJiyong Park 
27*54fd6939SJiyong Park static uint32_t bsec_power_safmem(bool power);
28*54fd6939SJiyong Park 
29*54fd6939SJiyong Park /* BSEC access protection */
30*54fd6939SJiyong Park static spinlock_t bsec_spinlock;
31*54fd6939SJiyong Park static uintptr_t bsec_base;
32*54fd6939SJiyong Park 
bsec_lock(void)33*54fd6939SJiyong Park static void bsec_lock(void)
34*54fd6939SJiyong Park {
35*54fd6939SJiyong Park 	if (stm32mp_lock_available()) {
36*54fd6939SJiyong Park 		spin_lock(&bsec_spinlock);
37*54fd6939SJiyong Park 	}
38*54fd6939SJiyong Park }
39*54fd6939SJiyong Park 
bsec_unlock(void)40*54fd6939SJiyong Park static void bsec_unlock(void)
41*54fd6939SJiyong Park {
42*54fd6939SJiyong Park 	if (stm32mp_lock_available()) {
43*54fd6939SJiyong Park 		spin_unlock(&bsec_spinlock);
44*54fd6939SJiyong Park 	}
45*54fd6939SJiyong Park }
46*54fd6939SJiyong Park 
bsec_get_dt_node(struct dt_node_info * info)47*54fd6939SJiyong Park static int bsec_get_dt_node(struct dt_node_info *info)
48*54fd6939SJiyong Park {
49*54fd6939SJiyong Park 	int node;
50*54fd6939SJiyong Park 
51*54fd6939SJiyong Park 	node = dt_get_node(info, -1, BSEC_COMPAT);
52*54fd6939SJiyong Park 	if (node < 0) {
53*54fd6939SJiyong Park 		return -FDT_ERR_NOTFOUND;
54*54fd6939SJiyong Park 	}
55*54fd6939SJiyong Park 
56*54fd6939SJiyong Park 	return node;
57*54fd6939SJiyong Park }
58*54fd6939SJiyong Park 
59*54fd6939SJiyong Park #if defined(IMAGE_BL32)
enable_non_secure_access(uint32_t otp)60*54fd6939SJiyong Park static void enable_non_secure_access(uint32_t otp)
61*54fd6939SJiyong Park {
62*54fd6939SJiyong Park 	otp_nsec_access[otp / __WORD_BIT] |= BIT(otp % __WORD_BIT);
63*54fd6939SJiyong Park 
64*54fd6939SJiyong Park 	if (bsec_shadow_register(otp) != BSEC_OK) {
65*54fd6939SJiyong Park 		panic();
66*54fd6939SJiyong Park 	}
67*54fd6939SJiyong Park }
68*54fd6939SJiyong Park 
non_secure_can_access(uint32_t otp)69*54fd6939SJiyong Park static bool non_secure_can_access(uint32_t otp)
70*54fd6939SJiyong Park {
71*54fd6939SJiyong Park 	return (otp_nsec_access[otp / __WORD_BIT] &
72*54fd6939SJiyong Park 		BIT(otp % __WORD_BIT)) != 0;
73*54fd6939SJiyong Park }
74*54fd6939SJiyong Park 
bsec_dt_otp_nsec_access(void * fdt,int bsec_node)75*54fd6939SJiyong Park static int bsec_dt_otp_nsec_access(void *fdt, int bsec_node)
76*54fd6939SJiyong Park {
77*54fd6939SJiyong Park 	int bsec_subnode;
78*54fd6939SJiyong Park 
79*54fd6939SJiyong Park 	fdt_for_each_subnode(bsec_subnode, fdt, bsec_node) {
80*54fd6939SJiyong Park 		const fdt32_t *cuint;
81*54fd6939SJiyong Park 		uint32_t reg;
82*54fd6939SJiyong Park 		uint32_t i;
83*54fd6939SJiyong Park 		uint32_t size;
84*54fd6939SJiyong Park 		uint8_t status;
85*54fd6939SJiyong Park 
86*54fd6939SJiyong Park 		cuint = fdt_getprop(fdt, bsec_subnode, "reg", NULL);
87*54fd6939SJiyong Park 		if (cuint == NULL) {
88*54fd6939SJiyong Park 			panic();
89*54fd6939SJiyong Park 		}
90*54fd6939SJiyong Park 
91*54fd6939SJiyong Park 		reg = fdt32_to_cpu(*cuint) / sizeof(uint32_t);
92*54fd6939SJiyong Park 		if (reg < STM32MP1_UPPER_OTP_START) {
93*54fd6939SJiyong Park 			continue;
94*54fd6939SJiyong Park 		}
95*54fd6939SJiyong Park 
96*54fd6939SJiyong Park 		status = fdt_get_status(bsec_subnode);
97*54fd6939SJiyong Park 		if ((status & DT_NON_SECURE) == 0U)  {
98*54fd6939SJiyong Park 			continue;
99*54fd6939SJiyong Park 		}
100*54fd6939SJiyong Park 
101*54fd6939SJiyong Park 		size = fdt32_to_cpu(*(cuint + 1)) / sizeof(uint32_t);
102*54fd6939SJiyong Park 
103*54fd6939SJiyong Park 		if ((fdt32_to_cpu(*(cuint + 1)) % sizeof(uint32_t)) != 0) {
104*54fd6939SJiyong Park 			size++;
105*54fd6939SJiyong Park 		}
106*54fd6939SJiyong Park 
107*54fd6939SJiyong Park 		for (i = reg; i < (reg + size); i++) {
108*54fd6939SJiyong Park 			enable_non_secure_access(i);
109*54fd6939SJiyong Park 		}
110*54fd6939SJiyong Park 	}
111*54fd6939SJiyong Park 
112*54fd6939SJiyong Park 	return 0;
113*54fd6939SJiyong Park }
114*54fd6939SJiyong Park #endif
115*54fd6939SJiyong Park 
otp_bank_offset(uint32_t otp)116*54fd6939SJiyong Park static uint32_t otp_bank_offset(uint32_t otp)
117*54fd6939SJiyong Park {
118*54fd6939SJiyong Park 	assert(otp <= STM32MP1_OTP_MAX_ID);
119*54fd6939SJiyong Park 
120*54fd6939SJiyong Park 	return ((otp & ~BSEC_OTP_MASK) >> BSEC_OTP_BANK_SHIFT) *
121*54fd6939SJiyong Park 	       sizeof(uint32_t);
122*54fd6939SJiyong Park }
123*54fd6939SJiyong Park 
bsec_check_error(uint32_t otp)124*54fd6939SJiyong Park static uint32_t bsec_check_error(uint32_t otp)
125*54fd6939SJiyong Park {
126*54fd6939SJiyong Park 	uint32_t bit = BIT(otp & BSEC_OTP_MASK);
127*54fd6939SJiyong Park 	uint32_t bank = otp_bank_offset(otp);
128*54fd6939SJiyong Park 
129*54fd6939SJiyong Park 	if ((mmio_read_32(bsec_base + BSEC_DISTURBED_OFF + bank) & bit) != 0U) {
130*54fd6939SJiyong Park 		return BSEC_DISTURBED;
131*54fd6939SJiyong Park 	}
132*54fd6939SJiyong Park 
133*54fd6939SJiyong Park 	if ((mmio_read_32(bsec_base + BSEC_ERROR_OFF + bank) & bit) != 0U) {
134*54fd6939SJiyong Park 		return BSEC_ERROR;
135*54fd6939SJiyong Park 	}
136*54fd6939SJiyong Park 
137*54fd6939SJiyong Park 	return BSEC_OK;
138*54fd6939SJiyong Park }
139*54fd6939SJiyong Park 
140*54fd6939SJiyong Park /*
141*54fd6939SJiyong Park  * bsec_probe: initialize BSEC driver.
142*54fd6939SJiyong Park  * return value: BSEC_OK if no error.
143*54fd6939SJiyong Park  */
bsec_probe(void)144*54fd6939SJiyong Park uint32_t bsec_probe(void)
145*54fd6939SJiyong Park {
146*54fd6939SJiyong Park 	void *fdt;
147*54fd6939SJiyong Park 	int node;
148*54fd6939SJiyong Park 	struct dt_node_info bsec_info;
149*54fd6939SJiyong Park 
150*54fd6939SJiyong Park 	if (fdt_get_address(&fdt) == 0) {
151*54fd6939SJiyong Park 		panic();
152*54fd6939SJiyong Park 	}
153*54fd6939SJiyong Park 
154*54fd6939SJiyong Park 	node = bsec_get_dt_node(&bsec_info);
155*54fd6939SJiyong Park 	if (node < 0) {
156*54fd6939SJiyong Park 		panic();
157*54fd6939SJiyong Park 	}
158*54fd6939SJiyong Park 
159*54fd6939SJiyong Park 	bsec_base = bsec_info.base;
160*54fd6939SJiyong Park 
161*54fd6939SJiyong Park #if defined(IMAGE_BL32)
162*54fd6939SJiyong Park 	bsec_dt_otp_nsec_access(fdt, node);
163*54fd6939SJiyong Park #endif
164*54fd6939SJiyong Park 	return BSEC_OK;
165*54fd6939SJiyong Park }
166*54fd6939SJiyong Park 
167*54fd6939SJiyong Park /*
168*54fd6939SJiyong Park  * bsec_get_base: return BSEC base address.
169*54fd6939SJiyong Park  */
bsec_get_base(void)170*54fd6939SJiyong Park uint32_t bsec_get_base(void)
171*54fd6939SJiyong Park {
172*54fd6939SJiyong Park 	return bsec_base;
173*54fd6939SJiyong Park }
174*54fd6939SJiyong Park 
175*54fd6939SJiyong Park /*
176*54fd6939SJiyong Park  * bsec_set_config: enable and configure BSEC.
177*54fd6939SJiyong Park  * cfg: pointer to param structure used to set register.
178*54fd6939SJiyong Park  * return value: BSEC_OK if no error.
179*54fd6939SJiyong Park  */
bsec_set_config(struct bsec_config * cfg)180*54fd6939SJiyong Park uint32_t bsec_set_config(struct bsec_config *cfg)
181*54fd6939SJiyong Park {
182*54fd6939SJiyong Park 	uint32_t value;
183*54fd6939SJiyong Park 	int32_t result;
184*54fd6939SJiyong Park 
185*54fd6939SJiyong Park 	value = ((((uint32_t)cfg->freq << BSEC_CONF_FRQ_SHIFT) &
186*54fd6939SJiyong Park 						BSEC_CONF_FRQ_MASK) |
187*54fd6939SJiyong Park 		 (((uint32_t)cfg->pulse_width << BSEC_CONF_PRG_WIDTH_SHIFT) &
188*54fd6939SJiyong Park 						BSEC_CONF_PRG_WIDTH_MASK) |
189*54fd6939SJiyong Park 		 (((uint32_t)cfg->tread << BSEC_CONF_TREAD_SHIFT) &
190*54fd6939SJiyong Park 						BSEC_CONF_TREAD_MASK));
191*54fd6939SJiyong Park 
192*54fd6939SJiyong Park 	bsec_lock();
193*54fd6939SJiyong Park 
194*54fd6939SJiyong Park 	mmio_write_32(bsec_base + BSEC_OTP_CONF_OFF, value);
195*54fd6939SJiyong Park 
196*54fd6939SJiyong Park 	bsec_unlock();
197*54fd6939SJiyong Park 
198*54fd6939SJiyong Park 	result = bsec_power_safmem((bool)cfg->power &
199*54fd6939SJiyong Park 				   BSEC_CONF_POWER_UP_MASK);
200*54fd6939SJiyong Park 	if (result != BSEC_OK) {
201*54fd6939SJiyong Park 		return result;
202*54fd6939SJiyong Park 	}
203*54fd6939SJiyong Park 
204*54fd6939SJiyong Park 	value = ((((uint32_t)cfg->upper_otp_lock << UPPER_OTP_LOCK_SHIFT) &
205*54fd6939SJiyong Park 						UPPER_OTP_LOCK_MASK) |
206*54fd6939SJiyong Park 		 (((uint32_t)cfg->den_lock << DENREG_LOCK_SHIFT) &
207*54fd6939SJiyong Park 						DENREG_LOCK_MASK) |
208*54fd6939SJiyong Park 		 (((uint32_t)cfg->prog_lock << GPLOCK_LOCK_SHIFT) &
209*54fd6939SJiyong Park 						GPLOCK_LOCK_MASK));
210*54fd6939SJiyong Park 
211*54fd6939SJiyong Park 	bsec_lock();
212*54fd6939SJiyong Park 
213*54fd6939SJiyong Park 	mmio_write_32(bsec_base + BSEC_OTP_LOCK_OFF, value);
214*54fd6939SJiyong Park 
215*54fd6939SJiyong Park 	bsec_unlock();
216*54fd6939SJiyong Park 
217*54fd6939SJiyong Park 	return BSEC_OK;
218*54fd6939SJiyong Park }
219*54fd6939SJiyong Park 
220*54fd6939SJiyong Park /*
221*54fd6939SJiyong Park  * bsec_get_config: return config parameters set in BSEC registers.
222*54fd6939SJiyong Park  * cfg: config param return.
223*54fd6939SJiyong Park  * return value: BSEC_OK if no error.
224*54fd6939SJiyong Park  */
bsec_get_config(struct bsec_config * cfg)225*54fd6939SJiyong Park uint32_t bsec_get_config(struct bsec_config *cfg)
226*54fd6939SJiyong Park {
227*54fd6939SJiyong Park 	uint32_t value;
228*54fd6939SJiyong Park 
229*54fd6939SJiyong Park 	if (cfg == NULL) {
230*54fd6939SJiyong Park 		return BSEC_INVALID_PARAM;
231*54fd6939SJiyong Park 	}
232*54fd6939SJiyong Park 
233*54fd6939SJiyong Park 	value = mmio_read_32(bsec_base + BSEC_OTP_CONF_OFF);
234*54fd6939SJiyong Park 	cfg->power = (uint8_t)((value & BSEC_CONF_POWER_UP_MASK) >>
235*54fd6939SJiyong Park 						BSEC_CONF_POWER_UP_SHIFT);
236*54fd6939SJiyong Park 	cfg->freq = (uint8_t)((value & BSEC_CONF_FRQ_MASK) >>
237*54fd6939SJiyong Park 						BSEC_CONF_FRQ_SHIFT);
238*54fd6939SJiyong Park 	cfg->pulse_width = (uint8_t)((value & BSEC_CONF_PRG_WIDTH_MASK) >>
239*54fd6939SJiyong Park 						BSEC_CONF_PRG_WIDTH_SHIFT);
240*54fd6939SJiyong Park 	cfg->tread = (uint8_t)((value & BSEC_CONF_TREAD_MASK) >>
241*54fd6939SJiyong Park 						BSEC_CONF_TREAD_SHIFT);
242*54fd6939SJiyong Park 
243*54fd6939SJiyong Park 	value = mmio_read_32(bsec_base + BSEC_OTP_LOCK_OFF);
244*54fd6939SJiyong Park 	cfg->upper_otp_lock = (uint8_t)((value & UPPER_OTP_LOCK_MASK) >>
245*54fd6939SJiyong Park 						UPPER_OTP_LOCK_SHIFT);
246*54fd6939SJiyong Park 	cfg->den_lock = (uint8_t)((value & DENREG_LOCK_MASK) >>
247*54fd6939SJiyong Park 						DENREG_LOCK_SHIFT);
248*54fd6939SJiyong Park 	cfg->prog_lock = (uint8_t)((value & GPLOCK_LOCK_MASK) >>
249*54fd6939SJiyong Park 						GPLOCK_LOCK_SHIFT);
250*54fd6939SJiyong Park 
251*54fd6939SJiyong Park 	return BSEC_OK;
252*54fd6939SJiyong Park }
253*54fd6939SJiyong Park 
254*54fd6939SJiyong Park /*
255*54fd6939SJiyong Park  * bsec_shadow_register: copy SAFMEM OTP to BSEC data.
256*54fd6939SJiyong Park  * otp: OTP number.
257*54fd6939SJiyong Park  * return value: BSEC_OK if no error.
258*54fd6939SJiyong Park  */
bsec_shadow_register(uint32_t otp)259*54fd6939SJiyong Park uint32_t bsec_shadow_register(uint32_t otp)
260*54fd6939SJiyong Park {
261*54fd6939SJiyong Park 	uint32_t result;
262*54fd6939SJiyong Park 	bool power_up = false;
263*54fd6939SJiyong Park 
264*54fd6939SJiyong Park 	if (otp > STM32MP1_OTP_MAX_ID) {
265*54fd6939SJiyong Park 		return BSEC_INVALID_PARAM;
266*54fd6939SJiyong Park 	}
267*54fd6939SJiyong Park 
268*54fd6939SJiyong Park 	/* Check if shadowing of OTP is locked */
269*54fd6939SJiyong Park 	if (bsec_read_sr_lock(otp)) {
270*54fd6939SJiyong Park 		VERBOSE("BSEC: OTP %i is locked and will not be refreshed\n",
271*54fd6939SJiyong Park 			otp);
272*54fd6939SJiyong Park 	}
273*54fd6939SJiyong Park 
274*54fd6939SJiyong Park 	if ((bsec_get_status() & BSEC_MODE_PWR_MASK) == 0U) {
275*54fd6939SJiyong Park 		result = bsec_power_safmem(true);
276*54fd6939SJiyong Park 
277*54fd6939SJiyong Park 		if (result != BSEC_OK) {
278*54fd6939SJiyong Park 			return result;
279*54fd6939SJiyong Park 		}
280*54fd6939SJiyong Park 
281*54fd6939SJiyong Park 		power_up = true;
282*54fd6939SJiyong Park 	}
283*54fd6939SJiyong Park 
284*54fd6939SJiyong Park 	bsec_lock();
285*54fd6939SJiyong Park 
286*54fd6939SJiyong Park 	/* Set BSEC_OTP_CTRL_OFF and set ADDR with the OTP value */
287*54fd6939SJiyong Park 	mmio_write_32(bsec_base + BSEC_OTP_CTRL_OFF, otp | BSEC_READ);
288*54fd6939SJiyong Park 
289*54fd6939SJiyong Park 	while ((bsec_get_status() & BSEC_MODE_BUSY_MASK) != 0U) {
290*54fd6939SJiyong Park 		;
291*54fd6939SJiyong Park 	}
292*54fd6939SJiyong Park 
293*54fd6939SJiyong Park 	result = bsec_check_error(otp);
294*54fd6939SJiyong Park 
295*54fd6939SJiyong Park 	bsec_unlock();
296*54fd6939SJiyong Park 
297*54fd6939SJiyong Park 	if (power_up) {
298*54fd6939SJiyong Park 		if (bsec_power_safmem(false) != BSEC_OK) {
299*54fd6939SJiyong Park 			panic();
300*54fd6939SJiyong Park 		}
301*54fd6939SJiyong Park 	}
302*54fd6939SJiyong Park 
303*54fd6939SJiyong Park 	return result;
304*54fd6939SJiyong Park }
305*54fd6939SJiyong Park 
306*54fd6939SJiyong Park /*
307*54fd6939SJiyong Park  * bsec_read_otp: read an OTP data value.
308*54fd6939SJiyong Park  * val: read value.
309*54fd6939SJiyong Park  * otp: OTP number.
310*54fd6939SJiyong Park  * return value: BSEC_OK if no error.
311*54fd6939SJiyong Park  */
bsec_read_otp(uint32_t * val,uint32_t otp)312*54fd6939SJiyong Park uint32_t bsec_read_otp(uint32_t *val, uint32_t otp)
313*54fd6939SJiyong Park {
314*54fd6939SJiyong Park 	uint32_t result;
315*54fd6939SJiyong Park 
316*54fd6939SJiyong Park 	if (otp > STM32MP1_OTP_MAX_ID) {
317*54fd6939SJiyong Park 		return BSEC_INVALID_PARAM;
318*54fd6939SJiyong Park 	}
319*54fd6939SJiyong Park 
320*54fd6939SJiyong Park 	bsec_lock();
321*54fd6939SJiyong Park 
322*54fd6939SJiyong Park 	*val = mmio_read_32(bsec_base + BSEC_OTP_DATA_OFF +
323*54fd6939SJiyong Park 			    (otp * sizeof(uint32_t)));
324*54fd6939SJiyong Park 
325*54fd6939SJiyong Park 	result = bsec_check_error(otp);
326*54fd6939SJiyong Park 
327*54fd6939SJiyong Park 	bsec_unlock();
328*54fd6939SJiyong Park 
329*54fd6939SJiyong Park 	return result;
330*54fd6939SJiyong Park }
331*54fd6939SJiyong Park 
332*54fd6939SJiyong Park /*
333*54fd6939SJiyong Park  * bsec_write_otp: write value in BSEC data register.
334*54fd6939SJiyong Park  * val: value to write.
335*54fd6939SJiyong Park  * otp: OTP number.
336*54fd6939SJiyong Park  * return value: BSEC_OK if no error.
337*54fd6939SJiyong Park  */
bsec_write_otp(uint32_t val,uint32_t otp)338*54fd6939SJiyong Park uint32_t bsec_write_otp(uint32_t val, uint32_t otp)
339*54fd6939SJiyong Park {
340*54fd6939SJiyong Park 	uint32_t result;
341*54fd6939SJiyong Park 
342*54fd6939SJiyong Park 	if (otp > STM32MP1_OTP_MAX_ID) {
343*54fd6939SJiyong Park 		return BSEC_INVALID_PARAM;
344*54fd6939SJiyong Park 	}
345*54fd6939SJiyong Park 
346*54fd6939SJiyong Park 	/* Check if programming of OTP is locked */
347*54fd6939SJiyong Park 	if (bsec_read_sw_lock(otp)) {
348*54fd6939SJiyong Park 		VERBOSE("BSEC: OTP %i is locked and write will be ignored\n",
349*54fd6939SJiyong Park 			otp);
350*54fd6939SJiyong Park 	}
351*54fd6939SJiyong Park 
352*54fd6939SJiyong Park 	bsec_lock();
353*54fd6939SJiyong Park 
354*54fd6939SJiyong Park 	mmio_write_32(bsec_base + BSEC_OTP_DATA_OFF +
355*54fd6939SJiyong Park 		      (otp * sizeof(uint32_t)), val);
356*54fd6939SJiyong Park 
357*54fd6939SJiyong Park 	result = bsec_check_error(otp);
358*54fd6939SJiyong Park 
359*54fd6939SJiyong Park 	bsec_unlock();
360*54fd6939SJiyong Park 
361*54fd6939SJiyong Park 	return result;
362*54fd6939SJiyong Park }
363*54fd6939SJiyong Park 
364*54fd6939SJiyong Park /*
365*54fd6939SJiyong Park  * bsec_program_otp: program a bit in SAFMEM after the prog.
366*54fd6939SJiyong Park  *	The OTP data is not refreshed.
367*54fd6939SJiyong Park  * val: value to program.
368*54fd6939SJiyong Park  * otp: OTP number.
369*54fd6939SJiyong Park  * return value: BSEC_OK if no error.
370*54fd6939SJiyong Park  */
bsec_program_otp(uint32_t val,uint32_t otp)371*54fd6939SJiyong Park uint32_t bsec_program_otp(uint32_t val, uint32_t otp)
372*54fd6939SJiyong Park {
373*54fd6939SJiyong Park 	uint32_t result;
374*54fd6939SJiyong Park 	bool power_up = false;
375*54fd6939SJiyong Park 
376*54fd6939SJiyong Park 	if (otp > STM32MP1_OTP_MAX_ID) {
377*54fd6939SJiyong Park 		return BSEC_INVALID_PARAM;
378*54fd6939SJiyong Park 	}
379*54fd6939SJiyong Park 
380*54fd6939SJiyong Park 	/* Check if programming of OTP is locked */
381*54fd6939SJiyong Park 	if (bsec_read_sp_lock(otp)) {
382*54fd6939SJiyong Park 		WARN("BSEC: OTP locked, prog will be ignored\n");
383*54fd6939SJiyong Park 	}
384*54fd6939SJiyong Park 
385*54fd6939SJiyong Park 	if ((mmio_read_32(bsec_base + BSEC_OTP_LOCK_OFF) &
386*54fd6939SJiyong Park 	     BIT(BSEC_LOCK_PROGRAM)) != 0U) {
387*54fd6939SJiyong Park 		WARN("BSEC: GPLOCK activated, prog will be ignored\n");
388*54fd6939SJiyong Park 	}
389*54fd6939SJiyong Park 
390*54fd6939SJiyong Park 	if ((bsec_get_status() & BSEC_MODE_PWR_MASK) == 0U) {
391*54fd6939SJiyong Park 		result = bsec_power_safmem(true);
392*54fd6939SJiyong Park 
393*54fd6939SJiyong Park 		if (result != BSEC_OK) {
394*54fd6939SJiyong Park 			return result;
395*54fd6939SJiyong Park 		}
396*54fd6939SJiyong Park 
397*54fd6939SJiyong Park 		power_up = true;
398*54fd6939SJiyong Park 	}
399*54fd6939SJiyong Park 
400*54fd6939SJiyong Park 	bsec_lock();
401*54fd6939SJiyong Park 
402*54fd6939SJiyong Park 	/* Set value in write register */
403*54fd6939SJiyong Park 	mmio_write_32(bsec_base + BSEC_OTP_WRDATA_OFF, val);
404*54fd6939SJiyong Park 
405*54fd6939SJiyong Park 	/* Set BSEC_OTP_CTRL_OFF and set ADDR with the OTP value */
406*54fd6939SJiyong Park 	mmio_write_32(bsec_base + BSEC_OTP_CTRL_OFF, otp | BSEC_WRITE);
407*54fd6939SJiyong Park 
408*54fd6939SJiyong Park 	while ((bsec_get_status() & BSEC_MODE_BUSY_MASK) != 0U) {
409*54fd6939SJiyong Park 		;
410*54fd6939SJiyong Park 	}
411*54fd6939SJiyong Park 
412*54fd6939SJiyong Park 	if ((bsec_get_status() & BSEC_MODE_PROGFAIL_MASK) != 0U) {
413*54fd6939SJiyong Park 		result = BSEC_PROG_FAIL;
414*54fd6939SJiyong Park 	} else {
415*54fd6939SJiyong Park 		result = bsec_check_error(otp);
416*54fd6939SJiyong Park 	}
417*54fd6939SJiyong Park 
418*54fd6939SJiyong Park 	bsec_unlock();
419*54fd6939SJiyong Park 
420*54fd6939SJiyong Park 	if (power_up) {
421*54fd6939SJiyong Park 		if (bsec_power_safmem(false) != BSEC_OK) {
422*54fd6939SJiyong Park 			panic();
423*54fd6939SJiyong Park 		}
424*54fd6939SJiyong Park 	}
425*54fd6939SJiyong Park 
426*54fd6939SJiyong Park 	return result;
427*54fd6939SJiyong Park }
428*54fd6939SJiyong Park 
429*54fd6939SJiyong Park /*
430*54fd6939SJiyong Park  * bsec_permanent_lock_otp: permanent lock of OTP in SAFMEM.
431*54fd6939SJiyong Park  * otp: OTP number.
432*54fd6939SJiyong Park  * return value: BSEC_OK if no error.
433*54fd6939SJiyong Park  */
bsec_permanent_lock_otp(uint32_t otp)434*54fd6939SJiyong Park uint32_t bsec_permanent_lock_otp(uint32_t otp)
435*54fd6939SJiyong Park {
436*54fd6939SJiyong Park 	uint32_t result;
437*54fd6939SJiyong Park 	bool power_up = false;
438*54fd6939SJiyong Park 	uint32_t data;
439*54fd6939SJiyong Park 	uint32_t addr;
440*54fd6939SJiyong Park 
441*54fd6939SJiyong Park 	if (otp > STM32MP1_OTP_MAX_ID) {
442*54fd6939SJiyong Park 		return BSEC_INVALID_PARAM;
443*54fd6939SJiyong Park 	}
444*54fd6939SJiyong Park 
445*54fd6939SJiyong Park 	if ((bsec_get_status() & BSEC_MODE_PWR_MASK) == 0U) {
446*54fd6939SJiyong Park 		result = bsec_power_safmem(true);
447*54fd6939SJiyong Park 
448*54fd6939SJiyong Park 		if (result != BSEC_OK) {
449*54fd6939SJiyong Park 			return result;
450*54fd6939SJiyong Park 		}
451*54fd6939SJiyong Park 
452*54fd6939SJiyong Park 		power_up = true;
453*54fd6939SJiyong Park 	}
454*54fd6939SJiyong Park 
455*54fd6939SJiyong Park 	if (otp < STM32MP1_UPPER_OTP_START) {
456*54fd6939SJiyong Park 		addr = otp >> ADDR_LOWER_OTP_PERLOCK_SHIFT;
457*54fd6939SJiyong Park 		data = DATA_LOWER_OTP_PERLOCK_BIT <<
458*54fd6939SJiyong Park 		       ((otp & DATA_LOWER_OTP_PERLOCK_MASK) << 1U);
459*54fd6939SJiyong Park 	} else {
460*54fd6939SJiyong Park 		addr = (otp >> ADDR_UPPER_OTP_PERLOCK_SHIFT) + 2U;
461*54fd6939SJiyong Park 		data = DATA_UPPER_OTP_PERLOCK_BIT <<
462*54fd6939SJiyong Park 		       (otp & DATA_UPPER_OTP_PERLOCK_MASK);
463*54fd6939SJiyong Park 	}
464*54fd6939SJiyong Park 
465*54fd6939SJiyong Park 	bsec_lock();
466*54fd6939SJiyong Park 
467*54fd6939SJiyong Park 	/* Set value in write register */
468*54fd6939SJiyong Park 	mmio_write_32(bsec_base + BSEC_OTP_WRDATA_OFF, data);
469*54fd6939SJiyong Park 
470*54fd6939SJiyong Park 	/* Set BSEC_OTP_CTRL_OFF and set ADDR with the OTP value */
471*54fd6939SJiyong Park 	mmio_write_32(bsec_base + BSEC_OTP_CTRL_OFF,
472*54fd6939SJiyong Park 		      addr | BSEC_WRITE | BSEC_LOCK);
473*54fd6939SJiyong Park 
474*54fd6939SJiyong Park 	while ((bsec_get_status() & BSEC_MODE_BUSY_MASK) != 0U) {
475*54fd6939SJiyong Park 		;
476*54fd6939SJiyong Park 	}
477*54fd6939SJiyong Park 
478*54fd6939SJiyong Park 	if ((bsec_get_status() & BSEC_MODE_PROGFAIL_MASK) != 0U) {
479*54fd6939SJiyong Park 		result = BSEC_PROG_FAIL;
480*54fd6939SJiyong Park 	} else {
481*54fd6939SJiyong Park 		result = bsec_check_error(otp);
482*54fd6939SJiyong Park 	}
483*54fd6939SJiyong Park 
484*54fd6939SJiyong Park 	bsec_unlock();
485*54fd6939SJiyong Park 
486*54fd6939SJiyong Park 	if (power_up) {
487*54fd6939SJiyong Park 		if (bsec_power_safmem(false) != BSEC_OK) {
488*54fd6939SJiyong Park 			panic();
489*54fd6939SJiyong Park 		}
490*54fd6939SJiyong Park 	}
491*54fd6939SJiyong Park 
492*54fd6939SJiyong Park 	return result;
493*54fd6939SJiyong Park }
494*54fd6939SJiyong Park 
495*54fd6939SJiyong Park /*
496*54fd6939SJiyong Park  * bsec_write_debug_conf: write value in debug feature
497*54fd6939SJiyong Park  *	to enable/disable debug service.
498*54fd6939SJiyong Park  * val: value to write.
499*54fd6939SJiyong Park  * return value: BSEC_OK if no error.
500*54fd6939SJiyong Park  */
bsec_write_debug_conf(uint32_t val)501*54fd6939SJiyong Park uint32_t bsec_write_debug_conf(uint32_t val)
502*54fd6939SJiyong Park {
503*54fd6939SJiyong Park 	uint32_t result = BSEC_ERROR;
504*54fd6939SJiyong Park 	uint32_t masked_val = val & BSEC_DEN_ALL_MSK;
505*54fd6939SJiyong Park 
506*54fd6939SJiyong Park 	bsec_lock();
507*54fd6939SJiyong Park 
508*54fd6939SJiyong Park 	mmio_write_32(bsec_base + BSEC_DEN_OFF, masked_val);
509*54fd6939SJiyong Park 
510*54fd6939SJiyong Park 	if ((mmio_read_32(bsec_base + BSEC_DEN_OFF) ^ masked_val) == 0U) {
511*54fd6939SJiyong Park 		result = BSEC_OK;
512*54fd6939SJiyong Park 	}
513*54fd6939SJiyong Park 
514*54fd6939SJiyong Park 	bsec_unlock();
515*54fd6939SJiyong Park 
516*54fd6939SJiyong Park 	return result;
517*54fd6939SJiyong Park }
518*54fd6939SJiyong Park 
519*54fd6939SJiyong Park /*
520*54fd6939SJiyong Park  * bsec_read_debug_conf: read debug configuration.
521*54fd6939SJiyong Park  */
bsec_read_debug_conf(void)522*54fd6939SJiyong Park uint32_t bsec_read_debug_conf(void)
523*54fd6939SJiyong Park {
524*54fd6939SJiyong Park 	return mmio_read_32(bsec_base + BSEC_DEN_OFF);
525*54fd6939SJiyong Park }
526*54fd6939SJiyong Park 
527*54fd6939SJiyong Park /*
528*54fd6939SJiyong Park  * bsec_get_status: return status register value.
529*54fd6939SJiyong Park  */
bsec_get_status(void)530*54fd6939SJiyong Park uint32_t bsec_get_status(void)
531*54fd6939SJiyong Park {
532*54fd6939SJiyong Park 	return mmio_read_32(bsec_base + BSEC_OTP_STATUS_OFF);
533*54fd6939SJiyong Park }
534*54fd6939SJiyong Park 
535*54fd6939SJiyong Park /*
536*54fd6939SJiyong Park  * bsec_get_hw_conf: return hardware configuration.
537*54fd6939SJiyong Park  */
bsec_get_hw_conf(void)538*54fd6939SJiyong Park uint32_t bsec_get_hw_conf(void)
539*54fd6939SJiyong Park {
540*54fd6939SJiyong Park 	return mmio_read_32(bsec_base + BSEC_IPHW_CFG_OFF);
541*54fd6939SJiyong Park }
542*54fd6939SJiyong Park 
543*54fd6939SJiyong Park /*
544*54fd6939SJiyong Park  * bsec_get_version: return BSEC version.
545*54fd6939SJiyong Park  */
bsec_get_version(void)546*54fd6939SJiyong Park uint32_t bsec_get_version(void)
547*54fd6939SJiyong Park {
548*54fd6939SJiyong Park 	return mmio_read_32(bsec_base + BSEC_IPVR_OFF);
549*54fd6939SJiyong Park }
550*54fd6939SJiyong Park 
551*54fd6939SJiyong Park /*
552*54fd6939SJiyong Park  * bsec_get_id: return BSEC ID.
553*54fd6939SJiyong Park  */
bsec_get_id(void)554*54fd6939SJiyong Park uint32_t bsec_get_id(void)
555*54fd6939SJiyong Park {
556*54fd6939SJiyong Park 	return mmio_read_32(bsec_base + BSEC_IP_ID_OFF);
557*54fd6939SJiyong Park }
558*54fd6939SJiyong Park 
559*54fd6939SJiyong Park /*
560*54fd6939SJiyong Park  * bsec_get_magic_id: return BSEC magic number.
561*54fd6939SJiyong Park  */
bsec_get_magic_id(void)562*54fd6939SJiyong Park uint32_t bsec_get_magic_id(void)
563*54fd6939SJiyong Park {
564*54fd6939SJiyong Park 	return mmio_read_32(bsec_base + BSEC_IP_MAGIC_ID_OFF);
565*54fd6939SJiyong Park }
566*54fd6939SJiyong Park 
567*54fd6939SJiyong Park /*
568*54fd6939SJiyong Park  * bsec_write_sr_lock: write shadow-read lock.
569*54fd6939SJiyong Park  * otp: OTP number.
570*54fd6939SJiyong Park  * value: value to write in the register.
571*54fd6939SJiyong Park  *	Must be always 1.
572*54fd6939SJiyong Park  * return: true if OTP is locked, else false.
573*54fd6939SJiyong Park  */
bsec_write_sr_lock(uint32_t otp,uint32_t value)574*54fd6939SJiyong Park bool bsec_write_sr_lock(uint32_t otp, uint32_t value)
575*54fd6939SJiyong Park {
576*54fd6939SJiyong Park 	bool result = false;
577*54fd6939SJiyong Park 	uint32_t bank = otp_bank_offset(otp);
578*54fd6939SJiyong Park 	uint32_t bank_value;
579*54fd6939SJiyong Park 	uint32_t otp_mask = BIT(otp & BSEC_OTP_MASK);
580*54fd6939SJiyong Park 
581*54fd6939SJiyong Park 	bsec_lock();
582*54fd6939SJiyong Park 
583*54fd6939SJiyong Park 	bank_value = mmio_read_32(bsec_base + BSEC_SRLOCK_OFF + bank);
584*54fd6939SJiyong Park 
585*54fd6939SJiyong Park 	if ((bank_value & otp_mask) == value) {
586*54fd6939SJiyong Park 		/*
587*54fd6939SJiyong Park 		 * In case of write don't need to write,
588*54fd6939SJiyong Park 		 * the lock is already set.
589*54fd6939SJiyong Park 		 */
590*54fd6939SJiyong Park 		if (value != 0U) {
591*54fd6939SJiyong Park 			result = true;
592*54fd6939SJiyong Park 		}
593*54fd6939SJiyong Park 	} else {
594*54fd6939SJiyong Park 		if (value != 0U) {
595*54fd6939SJiyong Park 			bank_value = bank_value | otp_mask;
596*54fd6939SJiyong Park 		} else {
597*54fd6939SJiyong Park 			bank_value = bank_value & ~otp_mask;
598*54fd6939SJiyong Park 		}
599*54fd6939SJiyong Park 
600*54fd6939SJiyong Park 		/*
601*54fd6939SJiyong Park 		 * We can write 0 in all other OTP
602*54fd6939SJiyong Park 		 * if the lock is activated in one of other OTP.
603*54fd6939SJiyong Park 		 * Write 0 has no effect.
604*54fd6939SJiyong Park 		 */
605*54fd6939SJiyong Park 		mmio_write_32(bsec_base + BSEC_SRLOCK_OFF + bank, bank_value);
606*54fd6939SJiyong Park 		result = true;
607*54fd6939SJiyong Park 	}
608*54fd6939SJiyong Park 
609*54fd6939SJiyong Park 	bsec_unlock();
610*54fd6939SJiyong Park 
611*54fd6939SJiyong Park 	return result;
612*54fd6939SJiyong Park }
613*54fd6939SJiyong Park 
614*54fd6939SJiyong Park /*
615*54fd6939SJiyong Park  * bsec_read_sr_lock: read shadow-read lock.
616*54fd6939SJiyong Park  * otp: OTP number.
617*54fd6939SJiyong Park  * return: true if otp is locked, else false.
618*54fd6939SJiyong Park  */
bsec_read_sr_lock(uint32_t otp)619*54fd6939SJiyong Park bool bsec_read_sr_lock(uint32_t otp)
620*54fd6939SJiyong Park {
621*54fd6939SJiyong Park 	uint32_t bank = otp_bank_offset(otp);
622*54fd6939SJiyong Park 	uint32_t otp_mask = BIT(otp & BSEC_OTP_MASK);
623*54fd6939SJiyong Park 	uint32_t bank_value = mmio_read_32(bsec_base + BSEC_SRLOCK_OFF + bank);
624*54fd6939SJiyong Park 
625*54fd6939SJiyong Park 	return (bank_value & otp_mask) != 0U;
626*54fd6939SJiyong Park }
627*54fd6939SJiyong Park 
628*54fd6939SJiyong Park /*
629*54fd6939SJiyong Park  * bsec_write_sw_lock: write shadow-write lock.
630*54fd6939SJiyong Park  * otp: OTP number.
631*54fd6939SJiyong Park  * value: Value to write in the register.
632*54fd6939SJiyong Park  *	Must be always 1.
633*54fd6939SJiyong Park  * return: true if OTP is locked, else false.
634*54fd6939SJiyong Park  */
bsec_write_sw_lock(uint32_t otp,uint32_t value)635*54fd6939SJiyong Park bool bsec_write_sw_lock(uint32_t otp, uint32_t value)
636*54fd6939SJiyong Park {
637*54fd6939SJiyong Park 	bool result = false;
638*54fd6939SJiyong Park 	uint32_t bank = otp_bank_offset(otp);
639*54fd6939SJiyong Park 	uint32_t otp_mask = BIT(otp & BSEC_OTP_MASK);
640*54fd6939SJiyong Park 	uint32_t bank_value;
641*54fd6939SJiyong Park 
642*54fd6939SJiyong Park 	bsec_lock();
643*54fd6939SJiyong Park 
644*54fd6939SJiyong Park 	bank_value = mmio_read_32(bsec_base + BSEC_SWLOCK_OFF + bank);
645*54fd6939SJiyong Park 
646*54fd6939SJiyong Park 	if ((bank_value & otp_mask) == value) {
647*54fd6939SJiyong Park 		/*
648*54fd6939SJiyong Park 		 * In case of write don't need to write,
649*54fd6939SJiyong Park 		 * the lock is already set.
650*54fd6939SJiyong Park 		 */
651*54fd6939SJiyong Park 		if (value != 0U) {
652*54fd6939SJiyong Park 			result = true;
653*54fd6939SJiyong Park 		}
654*54fd6939SJiyong Park 	} else {
655*54fd6939SJiyong Park 		if (value != 0U) {
656*54fd6939SJiyong Park 			bank_value = bank_value | otp_mask;
657*54fd6939SJiyong Park 		} else {
658*54fd6939SJiyong Park 			bank_value = bank_value & ~otp_mask;
659*54fd6939SJiyong Park 		}
660*54fd6939SJiyong Park 
661*54fd6939SJiyong Park 		/*
662*54fd6939SJiyong Park 		 * We can write 0 in all other OTP
663*54fd6939SJiyong Park 		 * if the lock is activated in one of other OTP.
664*54fd6939SJiyong Park 		 * Write 0 has no effect.
665*54fd6939SJiyong Park 		 */
666*54fd6939SJiyong Park 		mmio_write_32(bsec_base + BSEC_SWLOCK_OFF + bank, bank_value);
667*54fd6939SJiyong Park 		result = true;
668*54fd6939SJiyong Park 	}
669*54fd6939SJiyong Park 
670*54fd6939SJiyong Park 	bsec_unlock();
671*54fd6939SJiyong Park 
672*54fd6939SJiyong Park 	return result;
673*54fd6939SJiyong Park }
674*54fd6939SJiyong Park 
675*54fd6939SJiyong Park /*
676*54fd6939SJiyong Park  * bsec_read_sw_lock: read shadow-write lock.
677*54fd6939SJiyong Park  * otp: OTP number.
678*54fd6939SJiyong Park  * return: true if OTP is locked, else false.
679*54fd6939SJiyong Park  */
bsec_read_sw_lock(uint32_t otp)680*54fd6939SJiyong Park bool bsec_read_sw_lock(uint32_t otp)
681*54fd6939SJiyong Park {
682*54fd6939SJiyong Park 	uint32_t bank = otp_bank_offset(otp);
683*54fd6939SJiyong Park 	uint32_t otp_mask = BIT(otp & BSEC_OTP_MASK);
684*54fd6939SJiyong Park 	uint32_t bank_value = mmio_read_32(bsec_base + BSEC_SWLOCK_OFF + bank);
685*54fd6939SJiyong Park 
686*54fd6939SJiyong Park 	return (bank_value & otp_mask) != 0U;
687*54fd6939SJiyong Park }
688*54fd6939SJiyong Park 
689*54fd6939SJiyong Park /*
690*54fd6939SJiyong Park  * bsec_write_sp_lock: write shadow-program lock.
691*54fd6939SJiyong Park  * otp: OTP number.
692*54fd6939SJiyong Park  * value: Value to write in the register.
693*54fd6939SJiyong Park  *	Must be always 1.
694*54fd6939SJiyong Park  * return: true if OTP is locked, else false.
695*54fd6939SJiyong Park  */
bsec_write_sp_lock(uint32_t otp,uint32_t value)696*54fd6939SJiyong Park bool bsec_write_sp_lock(uint32_t otp, uint32_t value)
697*54fd6939SJiyong Park {
698*54fd6939SJiyong Park 	bool result = false;
699*54fd6939SJiyong Park 	uint32_t bank = otp_bank_offset(otp);
700*54fd6939SJiyong Park 	uint32_t bank_value;
701*54fd6939SJiyong Park 	uint32_t otp_mask = BIT(otp & BSEC_OTP_MASK);
702*54fd6939SJiyong Park 
703*54fd6939SJiyong Park 	bsec_lock();
704*54fd6939SJiyong Park 
705*54fd6939SJiyong Park 	bank_value = mmio_read_32(bsec_base + BSEC_SPLOCK_OFF + bank);
706*54fd6939SJiyong Park 
707*54fd6939SJiyong Park 	if ((bank_value & otp_mask) == value) {
708*54fd6939SJiyong Park 		/*
709*54fd6939SJiyong Park 		 * In case of write don't need to write,
710*54fd6939SJiyong Park 		 * the lock is already set.
711*54fd6939SJiyong Park 		 */
712*54fd6939SJiyong Park 		if (value != 0U) {
713*54fd6939SJiyong Park 			result = true;
714*54fd6939SJiyong Park 		}
715*54fd6939SJiyong Park 	} else {
716*54fd6939SJiyong Park 		if (value != 0U) {
717*54fd6939SJiyong Park 			bank_value = bank_value | otp_mask;
718*54fd6939SJiyong Park 		} else {
719*54fd6939SJiyong Park 			bank_value = bank_value & ~otp_mask;
720*54fd6939SJiyong Park 		}
721*54fd6939SJiyong Park 
722*54fd6939SJiyong Park 		/*
723*54fd6939SJiyong Park 		 * We can write 0 in all other OTP
724*54fd6939SJiyong Park 		 * if the lock is activated in one of other OTP.
725*54fd6939SJiyong Park 		 * Write 0 has no effect.
726*54fd6939SJiyong Park 		 */
727*54fd6939SJiyong Park 		mmio_write_32(bsec_base + BSEC_SPLOCK_OFF + bank, bank_value);
728*54fd6939SJiyong Park 		result = true;
729*54fd6939SJiyong Park 	}
730*54fd6939SJiyong Park 
731*54fd6939SJiyong Park 	bsec_unlock();
732*54fd6939SJiyong Park 
733*54fd6939SJiyong Park 	return result;
734*54fd6939SJiyong Park }
735*54fd6939SJiyong Park 
736*54fd6939SJiyong Park /*
737*54fd6939SJiyong Park  * bsec_read_sp_lock: read shadow-program lock.
738*54fd6939SJiyong Park  * otp: OTP number.
739*54fd6939SJiyong Park  * return: true if OTP is locked, else false.
740*54fd6939SJiyong Park  */
bsec_read_sp_lock(uint32_t otp)741*54fd6939SJiyong Park bool bsec_read_sp_lock(uint32_t otp)
742*54fd6939SJiyong Park {
743*54fd6939SJiyong Park 	uint32_t bank = otp_bank_offset(otp);
744*54fd6939SJiyong Park 	uint32_t otp_mask = BIT(otp & BSEC_OTP_MASK);
745*54fd6939SJiyong Park 	uint32_t bank_value = mmio_read_32(bsec_base + BSEC_SPLOCK_OFF + bank);
746*54fd6939SJiyong Park 
747*54fd6939SJiyong Park 	return (bank_value & otp_mask) != 0U;
748*54fd6939SJiyong Park }
749*54fd6939SJiyong Park 
750*54fd6939SJiyong Park /*
751*54fd6939SJiyong Park  * bsec_wr_lock: Read permanent lock status.
752*54fd6939SJiyong Park  * otp: OTP number.
753*54fd6939SJiyong Park  * return: true if OTP is locked, else false.
754*54fd6939SJiyong Park  */
bsec_wr_lock(uint32_t otp)755*54fd6939SJiyong Park bool bsec_wr_lock(uint32_t otp)
756*54fd6939SJiyong Park {
757*54fd6939SJiyong Park 	uint32_t bank = otp_bank_offset(otp);
758*54fd6939SJiyong Park 	uint32_t lock_bit = BIT(otp & BSEC_OTP_MASK);
759*54fd6939SJiyong Park 
760*54fd6939SJiyong Park 	if ((mmio_read_32(bsec_base + BSEC_WRLOCK_OFF + bank) &
761*54fd6939SJiyong Park 	     lock_bit) != 0U) {
762*54fd6939SJiyong Park 		/*
763*54fd6939SJiyong Park 		 * In case of write don't need to write,
764*54fd6939SJiyong Park 		 * the lock is already set.
765*54fd6939SJiyong Park 		 */
766*54fd6939SJiyong Park 		return true;
767*54fd6939SJiyong Park 	}
768*54fd6939SJiyong Park 
769*54fd6939SJiyong Park 	return false;
770*54fd6939SJiyong Park }
771*54fd6939SJiyong Park 
772*54fd6939SJiyong Park /*
773*54fd6939SJiyong Park  * bsec_otp_lock: Lock Upper OTP or Global programming or debug enable
774*54fd6939SJiyong Park  * service: Service to lock see header file.
775*54fd6939SJiyong Park  * value: Value to write must always set to 1 (only use for debug purpose).
776*54fd6939SJiyong Park  * return: BSEC_OK if succeed.
777*54fd6939SJiyong Park  */
bsec_otp_lock(uint32_t service,uint32_t value)778*54fd6939SJiyong Park uint32_t bsec_otp_lock(uint32_t service, uint32_t value)
779*54fd6939SJiyong Park {
780*54fd6939SJiyong Park 	uintptr_t reg = bsec_base + BSEC_OTP_LOCK_OFF;
781*54fd6939SJiyong Park 
782*54fd6939SJiyong Park 	switch (service) {
783*54fd6939SJiyong Park 	case BSEC_LOCK_UPPER_OTP:
784*54fd6939SJiyong Park 		mmio_write_32(reg, value << BSEC_LOCK_UPPER_OTP);
785*54fd6939SJiyong Park 		break;
786*54fd6939SJiyong Park 	case BSEC_LOCK_DEBUG:
787*54fd6939SJiyong Park 		mmio_write_32(reg, value << BSEC_LOCK_DEBUG);
788*54fd6939SJiyong Park 		break;
789*54fd6939SJiyong Park 	case BSEC_LOCK_PROGRAM:
790*54fd6939SJiyong Park 		mmio_write_32(reg, value << BSEC_LOCK_PROGRAM);
791*54fd6939SJiyong Park 		break;
792*54fd6939SJiyong Park 	default:
793*54fd6939SJiyong Park 		return BSEC_INVALID_PARAM;
794*54fd6939SJiyong Park 	}
795*54fd6939SJiyong Park 
796*54fd6939SJiyong Park 	return BSEC_OK;
797*54fd6939SJiyong Park }
798*54fd6939SJiyong Park 
799*54fd6939SJiyong Park /*
800*54fd6939SJiyong Park  * bsec_power_safmem: Activate or deactivate SAFMEM power.
801*54fd6939SJiyong Park  * power: true to power up, false to power down.
802*54fd6939SJiyong Park  * return: BSEC_OK if succeed.
803*54fd6939SJiyong Park  */
bsec_power_safmem(bool power)804*54fd6939SJiyong Park static uint32_t bsec_power_safmem(bool power)
805*54fd6939SJiyong Park {
806*54fd6939SJiyong Park 	uint32_t register_val;
807*54fd6939SJiyong Park 	uint32_t timeout = BSEC_TIMEOUT_VALUE;
808*54fd6939SJiyong Park 
809*54fd6939SJiyong Park 	bsec_lock();
810*54fd6939SJiyong Park 
811*54fd6939SJiyong Park 	register_val = mmio_read_32(bsec_base + BSEC_OTP_CONF_OFF);
812*54fd6939SJiyong Park 
813*54fd6939SJiyong Park 	if (power) {
814*54fd6939SJiyong Park 		register_val |= BSEC_CONF_POWER_UP_MASK;
815*54fd6939SJiyong Park 	} else {
816*54fd6939SJiyong Park 		register_val &= ~BSEC_CONF_POWER_UP_MASK;
817*54fd6939SJiyong Park 	}
818*54fd6939SJiyong Park 
819*54fd6939SJiyong Park 	mmio_write_32(bsec_base + BSEC_OTP_CONF_OFF, register_val);
820*54fd6939SJiyong Park 
821*54fd6939SJiyong Park 	/* Waiting loop */
822*54fd6939SJiyong Park 	if (power) {
823*54fd6939SJiyong Park 		while (((bsec_get_status() & BSEC_MODE_PWR_MASK) == 0U) &&
824*54fd6939SJiyong Park 		       (timeout != 0U)) {
825*54fd6939SJiyong Park 			timeout--;
826*54fd6939SJiyong Park 		}
827*54fd6939SJiyong Park 	} else {
828*54fd6939SJiyong Park 		while (((bsec_get_status() & BSEC_MODE_PWR_MASK) != 0U) &&
829*54fd6939SJiyong Park 		       (timeout != 0U)) {
830*54fd6939SJiyong Park 			timeout--;
831*54fd6939SJiyong Park 		}
832*54fd6939SJiyong Park 	}
833*54fd6939SJiyong Park 
834*54fd6939SJiyong Park 	bsec_unlock();
835*54fd6939SJiyong Park 
836*54fd6939SJiyong Park 	if (timeout == 0U) {
837*54fd6939SJiyong Park 		return BSEC_TIMEOUT;
838*54fd6939SJiyong Park 	}
839*54fd6939SJiyong Park 
840*54fd6939SJiyong Park 	return BSEC_OK;
841*54fd6939SJiyong Park }
842*54fd6939SJiyong Park 
843*54fd6939SJiyong Park /*
844*54fd6939SJiyong Park  * bsec_shadow_read_otp: Load OTP from SAFMEM and provide its value
845*54fd6939SJiyong Park  * otp_value: read value.
846*54fd6939SJiyong Park  * word: OTP number.
847*54fd6939SJiyong Park  * return value: BSEC_OK if no error.
848*54fd6939SJiyong Park  */
bsec_shadow_read_otp(uint32_t * otp_value,uint32_t word)849*54fd6939SJiyong Park uint32_t bsec_shadow_read_otp(uint32_t *otp_value, uint32_t word)
850*54fd6939SJiyong Park {
851*54fd6939SJiyong Park 	uint32_t result;
852*54fd6939SJiyong Park 
853*54fd6939SJiyong Park 	result = bsec_shadow_register(word);
854*54fd6939SJiyong Park 	if (result != BSEC_OK) {
855*54fd6939SJiyong Park 		ERROR("BSEC: %u Shadowing Error %i\n", word, result);
856*54fd6939SJiyong Park 		return result;
857*54fd6939SJiyong Park 	}
858*54fd6939SJiyong Park 
859*54fd6939SJiyong Park 	result = bsec_read_otp(otp_value, word);
860*54fd6939SJiyong Park 	if (result != BSEC_OK) {
861*54fd6939SJiyong Park 		ERROR("BSEC: %u Read Error %i\n", word, result);
862*54fd6939SJiyong Park 	}
863*54fd6939SJiyong Park 
864*54fd6939SJiyong Park 	return result;
865*54fd6939SJiyong Park }
866*54fd6939SJiyong Park 
867*54fd6939SJiyong Park /*
868*54fd6939SJiyong Park  * bsec_check_nsec_access_rights: check non-secure access rights to target OTP.
869*54fd6939SJiyong Park  * otp: OTP number.
870*54fd6939SJiyong Park  * return: BSEC_OK if authorized access.
871*54fd6939SJiyong Park  */
bsec_check_nsec_access_rights(uint32_t otp)872*54fd6939SJiyong Park uint32_t bsec_check_nsec_access_rights(uint32_t otp)
873*54fd6939SJiyong Park {
874*54fd6939SJiyong Park #if defined(IMAGE_BL32)
875*54fd6939SJiyong Park 	if (otp > STM32MP1_OTP_MAX_ID) {
876*54fd6939SJiyong Park 		return BSEC_INVALID_PARAM;
877*54fd6939SJiyong Park 	}
878*54fd6939SJiyong Park 
879*54fd6939SJiyong Park 	if (otp >= STM32MP1_UPPER_OTP_START) {
880*54fd6939SJiyong Park 		/* Check if BSEC is in OTP-SECURED closed_device state. */
881*54fd6939SJiyong Park 		if (stm32mp_is_closed_device()) {
882*54fd6939SJiyong Park 			if (!non_secure_can_access(otp)) {
883*54fd6939SJiyong Park 				return BSEC_ERROR;
884*54fd6939SJiyong Park 			}
885*54fd6939SJiyong Park 		}
886*54fd6939SJiyong Park 	}
887*54fd6939SJiyong Park #endif
888*54fd6939SJiyong Park 
889*54fd6939SJiyong Park 	return BSEC_OK;
890*54fd6939SJiyong Park }
891*54fd6939SJiyong Park 
892