xref: /openbmc/u-boot/arch/arm/mach-stm32mp/bsec.c (revision 1d6edcbfed2af33c748f2beb399810a0441888da)
1*19f58992SPatrick Delaunay // SPDX-License-Identifier: GPL-2.0+
2*19f58992SPatrick Delaunay /*
3*19f58992SPatrick Delaunay  * Copyright (C) 2018, STMicroelectronics - All Rights Reserved
4*19f58992SPatrick Delaunay  */
5*19f58992SPatrick Delaunay 
6*19f58992SPatrick Delaunay #include <common.h>
7*19f58992SPatrick Delaunay #include <dm.h>
8*19f58992SPatrick Delaunay #include <misc.h>
9*19f58992SPatrick Delaunay #include <asm/io.h>
10*19f58992SPatrick Delaunay #include <linux/iopoll.h>
11*19f58992SPatrick Delaunay 
12*19f58992SPatrick Delaunay #define BSEC_OTP_MAX_VALUE		95
13*19f58992SPatrick Delaunay 
14*19f58992SPatrick Delaunay #define BSEC_TIMEOUT_US			10000
15*19f58992SPatrick Delaunay 
16*19f58992SPatrick Delaunay /* BSEC REGISTER OFFSET (base relative) */
17*19f58992SPatrick Delaunay #define BSEC_OTP_CONF_OFF		0x000
18*19f58992SPatrick Delaunay #define BSEC_OTP_CTRL_OFF		0x004
19*19f58992SPatrick Delaunay #define BSEC_OTP_WRDATA_OFF		0x008
20*19f58992SPatrick Delaunay #define BSEC_OTP_STATUS_OFF		0x00C
21*19f58992SPatrick Delaunay #define BSEC_OTP_LOCK_OFF		0x010
22*19f58992SPatrick Delaunay #define BSEC_DISTURBED_OFF		0x01C
23*19f58992SPatrick Delaunay #define BSEC_ERROR_OFF			0x034
24*19f58992SPatrick Delaunay #define BSEC_SPLOCK_OFF			0x064 /* Program safmem sticky lock */
25*19f58992SPatrick Delaunay #define BSEC_SWLOCK_OFF			0x07C /* write in OTP sticky lock */
26*19f58992SPatrick Delaunay #define BSEC_SRLOCK_OFF			0x094 /* shadowing sticky lock */
27*19f58992SPatrick Delaunay #define BSEC_OTP_DATA_OFF		0x200
28*19f58992SPatrick Delaunay 
29*19f58992SPatrick Delaunay /* BSEC_CONFIGURATION Register MASK */
30*19f58992SPatrick Delaunay #define BSEC_CONF_POWER_UP		0x001
31*19f58992SPatrick Delaunay 
32*19f58992SPatrick Delaunay /* BSEC_CONTROL Register */
33*19f58992SPatrick Delaunay #define BSEC_READ			0x000
34*19f58992SPatrick Delaunay #define BSEC_WRITE			0x100
35*19f58992SPatrick Delaunay 
36*19f58992SPatrick Delaunay /* LOCK Register */
37*19f58992SPatrick Delaunay #define OTP_LOCK_MASK			0x1F
38*19f58992SPatrick Delaunay #define OTP_LOCK_BANK_SHIFT		0x05
39*19f58992SPatrick Delaunay #define OTP_LOCK_BIT_MASK		0x01
40*19f58992SPatrick Delaunay 
41*19f58992SPatrick Delaunay /* STATUS Register */
42*19f58992SPatrick Delaunay #define BSEC_MODE_BUSY_MASK		0x08
43*19f58992SPatrick Delaunay #define BSEC_MODE_PROGFAIL_MASK		0x10
44*19f58992SPatrick Delaunay #define BSEC_MODE_PWR_MASK		0x20
45*19f58992SPatrick Delaunay 
46*19f58992SPatrick Delaunay /*
47*19f58992SPatrick Delaunay  * OTP Lock services definition
48*19f58992SPatrick Delaunay  * Value must corresponding to the bit number in the register
49*19f58992SPatrick Delaunay  */
50*19f58992SPatrick Delaunay #define BSEC_LOCK_PROGRAM		0x04
51*19f58992SPatrick Delaunay 
52*19f58992SPatrick Delaunay /**
53*19f58992SPatrick Delaunay  * bsec_check_error() - Check status of one otp
54*19f58992SPatrick Delaunay  * @base: base address of bsec IP
55*19f58992SPatrick Delaunay  * @otp: otp number (0 - BSEC_OTP_MAX_VALUE)
56*19f58992SPatrick Delaunay  * Return: 0 if no error, -EAGAIN or -ENOTSUPP
57*19f58992SPatrick Delaunay  */
bsec_check_error(u32 base,u32 otp)58*19f58992SPatrick Delaunay static u32 bsec_check_error(u32 base, u32 otp)
59*19f58992SPatrick Delaunay {
60*19f58992SPatrick Delaunay 	u32 bit;
61*19f58992SPatrick Delaunay 	u32 bank;
62*19f58992SPatrick Delaunay 
63*19f58992SPatrick Delaunay 	bit = 1 << (otp & OTP_LOCK_MASK);
64*19f58992SPatrick Delaunay 	bank = ((otp >> OTP_LOCK_BANK_SHIFT) & OTP_LOCK_MASK) * sizeof(u32);
65*19f58992SPatrick Delaunay 
66*19f58992SPatrick Delaunay 	if (readl(base + BSEC_DISTURBED_OFF + bank) & bit)
67*19f58992SPatrick Delaunay 		return -EAGAIN;
68*19f58992SPatrick Delaunay 	else if (readl(base + BSEC_ERROR_OFF + bank) & bit)
69*19f58992SPatrick Delaunay 		return -ENOTSUPP;
70*19f58992SPatrick Delaunay 
71*19f58992SPatrick Delaunay 	return 0;
72*19f58992SPatrick Delaunay }
73*19f58992SPatrick Delaunay 
74*19f58992SPatrick Delaunay /**
75*19f58992SPatrick Delaunay  * bsec_lock() - manage lock for each type SR/SP/SW
76*19f58992SPatrick Delaunay  * @address: address of bsec IP register
77*19f58992SPatrick Delaunay  * @otp: otp number (0 - BSEC_OTP_MAX_VALUE)
78*19f58992SPatrick Delaunay  * Return: true if locked else false
79*19f58992SPatrick Delaunay  */
bsec_read_lock(u32 address,u32 otp)80*19f58992SPatrick Delaunay static bool bsec_read_lock(u32 address, u32 otp)
81*19f58992SPatrick Delaunay {
82*19f58992SPatrick Delaunay 	u32 bit;
83*19f58992SPatrick Delaunay 	u32 bank;
84*19f58992SPatrick Delaunay 
85*19f58992SPatrick Delaunay 	bit = 1 << (otp & OTP_LOCK_MASK);
86*19f58992SPatrick Delaunay 	bank = ((otp >> OTP_LOCK_BANK_SHIFT) & OTP_LOCK_MASK) * sizeof(u32);
87*19f58992SPatrick Delaunay 
88*19f58992SPatrick Delaunay 	return !!(readl(address + bank) & bit);
89*19f58992SPatrick Delaunay }
90*19f58992SPatrick Delaunay 
91*19f58992SPatrick Delaunay /**
92*19f58992SPatrick Delaunay  * bsec_read_SR_lock() - read SR lock (Shadowing)
93*19f58992SPatrick Delaunay  * @base: base address of bsec IP
94*19f58992SPatrick Delaunay  * @otp: otp number (0 - BSEC_OTP_MAX_VALUE)
95*19f58992SPatrick Delaunay  * Return: true if locked else false
96*19f58992SPatrick Delaunay  */
bsec_read_SR_lock(u32 base,u32 otp)97*19f58992SPatrick Delaunay static bool bsec_read_SR_lock(u32 base, u32 otp)
98*19f58992SPatrick Delaunay {
99*19f58992SPatrick Delaunay 	return bsec_read_lock(base + BSEC_SRLOCK_OFF, otp);
100*19f58992SPatrick Delaunay }
101*19f58992SPatrick Delaunay 
102*19f58992SPatrick Delaunay /**
103*19f58992SPatrick Delaunay  * bsec_read_SP_lock() - read SP lock (program Lock)
104*19f58992SPatrick Delaunay  * @base: base address of bsec IP
105*19f58992SPatrick Delaunay  * @otp: otp number (0 - BSEC_OTP_MAX_VALUE)
106*19f58992SPatrick Delaunay  * Return: true if locked else false
107*19f58992SPatrick Delaunay  */
bsec_read_SP_lock(u32 base,u32 otp)108*19f58992SPatrick Delaunay static bool bsec_read_SP_lock(u32 base, u32 otp)
109*19f58992SPatrick Delaunay {
110*19f58992SPatrick Delaunay 	return bsec_read_lock(base + BSEC_SPLOCK_OFF, otp);
111*19f58992SPatrick Delaunay }
112*19f58992SPatrick Delaunay 
113*19f58992SPatrick Delaunay /**
114*19f58992SPatrick Delaunay  * bsec_SW_lock() - manage SW lock (Write in Shadow)
115*19f58992SPatrick Delaunay  * @base: base address of bsec IP
116*19f58992SPatrick Delaunay  * @otp: otp number (0 - BSEC_OTP_MAX_VALUE)
117*19f58992SPatrick Delaunay  * Return: true if locked else false
118*19f58992SPatrick Delaunay  */
bsec_read_SW_lock(u32 base,u32 otp)119*19f58992SPatrick Delaunay static bool bsec_read_SW_lock(u32 base, u32 otp)
120*19f58992SPatrick Delaunay {
121*19f58992SPatrick Delaunay 	return bsec_read_lock(base + BSEC_SWLOCK_OFF, otp);
122*19f58992SPatrick Delaunay }
123*19f58992SPatrick Delaunay 
124*19f58992SPatrick Delaunay /**
125*19f58992SPatrick Delaunay  * bsec_power_safmem() - Activate or deactivate safmem power
126*19f58992SPatrick Delaunay  * @base: base address of bsec IP
127*19f58992SPatrick Delaunay  * @power: true to power up , false to power down
128*19f58992SPatrick Delaunay  * Return: 0 if succeed
129*19f58992SPatrick Delaunay  */
bsec_power_safmem(u32 base,bool power)130*19f58992SPatrick Delaunay static int bsec_power_safmem(u32 base, bool power)
131*19f58992SPatrick Delaunay {
132*19f58992SPatrick Delaunay 	u32 val;
133*19f58992SPatrick Delaunay 	u32 mask;
134*19f58992SPatrick Delaunay 
135*19f58992SPatrick Delaunay 	if (power) {
136*19f58992SPatrick Delaunay 		setbits_le32(base + BSEC_OTP_CONF_OFF, BSEC_CONF_POWER_UP);
137*19f58992SPatrick Delaunay 		mask = BSEC_MODE_PWR_MASK;
138*19f58992SPatrick Delaunay 	} else {
139*19f58992SPatrick Delaunay 		clrbits_le32(base + BSEC_OTP_CONF_OFF, BSEC_CONF_POWER_UP);
140*19f58992SPatrick Delaunay 		mask = 0;
141*19f58992SPatrick Delaunay 	}
142*19f58992SPatrick Delaunay 
143*19f58992SPatrick Delaunay 	/* waiting loop */
144*19f58992SPatrick Delaunay 	return readl_poll_timeout(base + BSEC_OTP_STATUS_OFF,
145*19f58992SPatrick Delaunay 				  val, (val & BSEC_MODE_PWR_MASK) == mask,
146*19f58992SPatrick Delaunay 				  BSEC_TIMEOUT_US);
147*19f58992SPatrick Delaunay }
148*19f58992SPatrick Delaunay 
149*19f58992SPatrick Delaunay /**
150*19f58992SPatrick Delaunay  * bsec_shadow_register() - copy safmen otp to bsec data
151*19f58992SPatrick Delaunay  * @base: base address of bsec IP
152*19f58992SPatrick Delaunay  * @otp: otp number (0 - BSEC_OTP_MAX_VALUE)
153*19f58992SPatrick Delaunay  * Return: 0 if no error
154*19f58992SPatrick Delaunay  */
bsec_shadow_register(u32 base,u32 otp)155*19f58992SPatrick Delaunay static int bsec_shadow_register(u32 base, u32 otp)
156*19f58992SPatrick Delaunay {
157*19f58992SPatrick Delaunay 	u32 val;
158*19f58992SPatrick Delaunay 	int ret;
159*19f58992SPatrick Delaunay 	bool power_up = false;
160*19f58992SPatrick Delaunay 
161*19f58992SPatrick Delaunay 	/* check if shadowing of otp is locked */
162*19f58992SPatrick Delaunay 	if (bsec_read_SR_lock(base, otp))
163*19f58992SPatrick Delaunay 		pr_debug("bsec : OTP %d is locked and refreshed with 0\n", otp);
164*19f58992SPatrick Delaunay 
165*19f58992SPatrick Delaunay 	/* check if safemem is power up */
166*19f58992SPatrick Delaunay 	val = readl(base + BSEC_OTP_STATUS_OFF);
167*19f58992SPatrick Delaunay 	if (!(val & BSEC_MODE_PWR_MASK)) {
168*19f58992SPatrick Delaunay 		ret = bsec_power_safmem(base, true);
169*19f58992SPatrick Delaunay 		if (ret)
170*19f58992SPatrick Delaunay 			return ret;
171*19f58992SPatrick Delaunay 		power_up = 1;
172*19f58992SPatrick Delaunay 	}
173*19f58992SPatrick Delaunay 	/* set BSEC_OTP_CTRL_OFF with the otp value*/
174*19f58992SPatrick Delaunay 	writel(otp | BSEC_READ, base + BSEC_OTP_CTRL_OFF);
175*19f58992SPatrick Delaunay 
176*19f58992SPatrick Delaunay 	/* check otp status*/
177*19f58992SPatrick Delaunay 	ret = readl_poll_timeout(base + BSEC_OTP_STATUS_OFF,
178*19f58992SPatrick Delaunay 				 val, (val & BSEC_MODE_BUSY_MASK) == 0,
179*19f58992SPatrick Delaunay 				 BSEC_TIMEOUT_US);
180*19f58992SPatrick Delaunay 	if (ret)
181*19f58992SPatrick Delaunay 		return ret;
182*19f58992SPatrick Delaunay 
183*19f58992SPatrick Delaunay 	ret = bsec_check_error(base, otp);
184*19f58992SPatrick Delaunay 
185*19f58992SPatrick Delaunay 	if (power_up)
186*19f58992SPatrick Delaunay 		bsec_power_safmem(base, false);
187*19f58992SPatrick Delaunay 
188*19f58992SPatrick Delaunay 	return ret;
189*19f58992SPatrick Delaunay }
190*19f58992SPatrick Delaunay 
191*19f58992SPatrick Delaunay /**
192*19f58992SPatrick Delaunay  * bsec_read_shadow() - read an otp data value from shadow
193*19f58992SPatrick Delaunay  * @base: base address of bsec IP
194*19f58992SPatrick Delaunay  * @val: read value
195*19f58992SPatrick Delaunay  * @otp: otp number (0 - BSEC_OTP_MAX_VALUE)
196*19f58992SPatrick Delaunay  * Return: 0 if no error
197*19f58992SPatrick Delaunay  */
bsec_read_shadow(u32 base,u32 * val,u32 otp)198*19f58992SPatrick Delaunay static int bsec_read_shadow(u32 base, u32 *val, u32 otp)
199*19f58992SPatrick Delaunay {
200*19f58992SPatrick Delaunay 	*val = readl(base + BSEC_OTP_DATA_OFF + otp * sizeof(u32));
201*19f58992SPatrick Delaunay 
202*19f58992SPatrick Delaunay 	return bsec_check_error(base, otp);
203*19f58992SPatrick Delaunay }
204*19f58992SPatrick Delaunay 
205*19f58992SPatrick Delaunay /**
206*19f58992SPatrick Delaunay  * bsec_write_shadow() - write value in BSEC data register in shadow
207*19f58992SPatrick Delaunay  * @base: base address of bsec IP
208*19f58992SPatrick Delaunay  * @val: value to write
209*19f58992SPatrick Delaunay  * @otp: otp number (0 - BSEC_OTP_MAX_VALUE)
210*19f58992SPatrick Delaunay  * Return: 0 if no error
211*19f58992SPatrick Delaunay  */
bsec_write_shadow(u32 base,u32 val,u32 otp)212*19f58992SPatrick Delaunay static int bsec_write_shadow(u32 base, u32 val, u32 otp)
213*19f58992SPatrick Delaunay {
214*19f58992SPatrick Delaunay 	/* check if programming of otp is locked */
215*19f58992SPatrick Delaunay 	if (bsec_read_SW_lock(base, otp))
216*19f58992SPatrick Delaunay 		pr_debug("bsec : OTP %d is lock, write will be ignore\n", otp);
217*19f58992SPatrick Delaunay 
218*19f58992SPatrick Delaunay 	writel(val, base + BSEC_OTP_DATA_OFF + otp * sizeof(u32));
219*19f58992SPatrick Delaunay 
220*19f58992SPatrick Delaunay 	return bsec_check_error(base, otp);
221*19f58992SPatrick Delaunay }
222*19f58992SPatrick Delaunay 
223*19f58992SPatrick Delaunay /**
224*19f58992SPatrick Delaunay  * bsec_program_otp() - program a bit in SAFMEM
225*19f58992SPatrick Delaunay  * @base: base address of bsec IP
226*19f58992SPatrick Delaunay  * @val: value to program
227*19f58992SPatrick Delaunay  * @otp: otp number (0 - BSEC_OTP_MAX_VALUE)
228*19f58992SPatrick Delaunay  * after the function the otp data is not refreshed in shadow
229*19f58992SPatrick Delaunay  * Return: 0 if no error
230*19f58992SPatrick Delaunay  */
bsec_program_otp(long base,u32 val,u32 otp)231*19f58992SPatrick Delaunay static int bsec_program_otp(long base, u32 val, u32 otp)
232*19f58992SPatrick Delaunay {
233*19f58992SPatrick Delaunay 	u32 ret;
234*19f58992SPatrick Delaunay 	bool power_up = false;
235*19f58992SPatrick Delaunay 
236*19f58992SPatrick Delaunay 	if (bsec_read_SP_lock(base, otp))
237*19f58992SPatrick Delaunay 		pr_debug("bsec : OTP %d locked, prog will be ignore\n", otp);
238*19f58992SPatrick Delaunay 
239*19f58992SPatrick Delaunay 	if (readl(base + BSEC_OTP_LOCK_OFF) & (1 << BSEC_LOCK_PROGRAM))
240*19f58992SPatrick Delaunay 		pr_debug("bsec : Global lock, prog will be ignore\n");
241*19f58992SPatrick Delaunay 
242*19f58992SPatrick Delaunay 	/* check if safemem is power up */
243*19f58992SPatrick Delaunay 	if (!(readl(base + BSEC_OTP_STATUS_OFF) & BSEC_MODE_PWR_MASK)) {
244*19f58992SPatrick Delaunay 		ret = bsec_power_safmem(base, true);
245*19f58992SPatrick Delaunay 		if (ret)
246*19f58992SPatrick Delaunay 			return ret;
247*19f58992SPatrick Delaunay 
248*19f58992SPatrick Delaunay 		power_up = true;
249*19f58992SPatrick Delaunay 	}
250*19f58992SPatrick Delaunay 	/* set value in write register*/
251*19f58992SPatrick Delaunay 	writel(val, base + BSEC_OTP_WRDATA_OFF);
252*19f58992SPatrick Delaunay 
253*19f58992SPatrick Delaunay 	/* set BSEC_OTP_CTRL_OFF with the otp value */
254*19f58992SPatrick Delaunay 	writel(otp | BSEC_WRITE, base + BSEC_OTP_CTRL_OFF);
255*19f58992SPatrick Delaunay 
256*19f58992SPatrick Delaunay 	/* check otp status*/
257*19f58992SPatrick Delaunay 	ret = readl_poll_timeout(base + BSEC_OTP_STATUS_OFF,
258*19f58992SPatrick Delaunay 				 val, (val & BSEC_MODE_BUSY_MASK) == 0,
259*19f58992SPatrick Delaunay 				 BSEC_TIMEOUT_US);
260*19f58992SPatrick Delaunay 	if (ret)
261*19f58992SPatrick Delaunay 		return ret;
262*19f58992SPatrick Delaunay 
263*19f58992SPatrick Delaunay 	if (val & BSEC_MODE_PROGFAIL_MASK)
264*19f58992SPatrick Delaunay 		ret = -EACCES;
265*19f58992SPatrick Delaunay 	else
266*19f58992SPatrick Delaunay 		ret = bsec_check_error(base, otp);
267*19f58992SPatrick Delaunay 
268*19f58992SPatrick Delaunay 	if (power_up)
269*19f58992SPatrick Delaunay 		bsec_power_safmem(base, false);
270*19f58992SPatrick Delaunay 
271*19f58992SPatrick Delaunay 	return ret;
272*19f58992SPatrick Delaunay }
273*19f58992SPatrick Delaunay 
274*19f58992SPatrick Delaunay /* BSEC MISC driver *******************************************************/
275*19f58992SPatrick Delaunay struct stm32mp_bsec_platdata {
276*19f58992SPatrick Delaunay 	u32 base;
277*19f58992SPatrick Delaunay };
278*19f58992SPatrick Delaunay 
stm32mp_bsec_read_otp(struct udevice * dev,u32 * val,u32 otp)279*19f58992SPatrick Delaunay static int stm32mp_bsec_read_otp(struct udevice *dev, u32 *val, u32 otp)
280*19f58992SPatrick Delaunay {
281*19f58992SPatrick Delaunay 	struct stm32mp_bsec_platdata *plat = dev_get_platdata(dev);
282*19f58992SPatrick Delaunay 	u32 tmp_data = 0;
283*19f58992SPatrick Delaunay 	int ret;
284*19f58992SPatrick Delaunay 
285*19f58992SPatrick Delaunay 	/* read current shadow value */
286*19f58992SPatrick Delaunay 	ret = bsec_read_shadow(plat->base, &tmp_data, otp);
287*19f58992SPatrick Delaunay 	if (ret)
288*19f58992SPatrick Delaunay 		return ret;
289*19f58992SPatrick Delaunay 
290*19f58992SPatrick Delaunay 	/* copy otp in shadow */
291*19f58992SPatrick Delaunay 	ret = bsec_shadow_register(plat->base, otp);
292*19f58992SPatrick Delaunay 	if (ret)
293*19f58992SPatrick Delaunay 		return ret;
294*19f58992SPatrick Delaunay 
295*19f58992SPatrick Delaunay 	ret = bsec_read_shadow(plat->base, val, otp);
296*19f58992SPatrick Delaunay 	if (ret)
297*19f58992SPatrick Delaunay 		return ret;
298*19f58992SPatrick Delaunay 
299*19f58992SPatrick Delaunay 	/* restore shadow value */
300*19f58992SPatrick Delaunay 	ret = bsec_write_shadow(plat->base, tmp_data, otp);
301*19f58992SPatrick Delaunay 	return ret;
302*19f58992SPatrick Delaunay }
303*19f58992SPatrick Delaunay 
stm32mp_bsec_read_shadow(struct udevice * dev,u32 * val,u32 otp)304*19f58992SPatrick Delaunay static int stm32mp_bsec_read_shadow(struct udevice *dev, u32 *val, u32 otp)
305*19f58992SPatrick Delaunay {
306*19f58992SPatrick Delaunay 	struct stm32mp_bsec_platdata *plat = dev_get_platdata(dev);
307*19f58992SPatrick Delaunay 
308*19f58992SPatrick Delaunay 	return bsec_read_shadow(plat->base, val, otp);
309*19f58992SPatrick Delaunay }
310*19f58992SPatrick Delaunay 
stm32mp_bsec_write_otp(struct udevice * dev,u32 val,u32 otp)311*19f58992SPatrick Delaunay static int stm32mp_bsec_write_otp(struct udevice *dev, u32 val, u32 otp)
312*19f58992SPatrick Delaunay {
313*19f58992SPatrick Delaunay 	struct stm32mp_bsec_platdata *plat = dev_get_platdata(dev);
314*19f58992SPatrick Delaunay 
315*19f58992SPatrick Delaunay 	return bsec_program_otp(plat->base, val, otp);
316*19f58992SPatrick Delaunay }
317*19f58992SPatrick Delaunay 
stm32mp_bsec_write_shadow(struct udevice * dev,u32 val,u32 otp)318*19f58992SPatrick Delaunay static int stm32mp_bsec_write_shadow(struct udevice *dev, u32 val, u32 otp)
319*19f58992SPatrick Delaunay {
320*19f58992SPatrick Delaunay 	struct stm32mp_bsec_platdata *plat = dev_get_platdata(dev);
321*19f58992SPatrick Delaunay 
322*19f58992SPatrick Delaunay 	return bsec_write_shadow(plat->base, val, otp);
323*19f58992SPatrick Delaunay }
324*19f58992SPatrick Delaunay 
stm32mp_bsec_read(struct udevice * dev,int offset,void * buf,int size)325*19f58992SPatrick Delaunay static int stm32mp_bsec_read(struct udevice *dev, int offset,
326*19f58992SPatrick Delaunay 			     void *buf, int size)
327*19f58992SPatrick Delaunay {
328*19f58992SPatrick Delaunay 	int ret;
329*19f58992SPatrick Delaunay 	int i;
330*19f58992SPatrick Delaunay 	bool shadow = true;
331*19f58992SPatrick Delaunay 	int nb_otp = size / sizeof(u32);
332*19f58992SPatrick Delaunay 	int otp;
333*19f58992SPatrick Delaunay 
334*19f58992SPatrick Delaunay 	if (offset >= STM32_BSEC_OTP_OFFSET) {
335*19f58992SPatrick Delaunay 		offset -= STM32_BSEC_OTP_OFFSET;
336*19f58992SPatrick Delaunay 		shadow = false;
337*19f58992SPatrick Delaunay 	}
338*19f58992SPatrick Delaunay 	otp = offset / sizeof(u32);
339*19f58992SPatrick Delaunay 
340*19f58992SPatrick Delaunay 	if (otp < 0 || (otp + nb_otp - 1) > BSEC_OTP_MAX_VALUE) {
341*19f58992SPatrick Delaunay 		dev_err(dev, "wrong value for otp, max value : %i\n",
342*19f58992SPatrick Delaunay 			BSEC_OTP_MAX_VALUE);
343*19f58992SPatrick Delaunay 		return -EINVAL;
344*19f58992SPatrick Delaunay 	}
345*19f58992SPatrick Delaunay 
346*19f58992SPatrick Delaunay 	for (i = otp; i < (otp + nb_otp); i++) {
347*19f58992SPatrick Delaunay 		u32 *addr = &((u32 *)buf)[i - otp];
348*19f58992SPatrick Delaunay 
349*19f58992SPatrick Delaunay 		if (shadow)
350*19f58992SPatrick Delaunay 			ret = stm32mp_bsec_read_shadow(dev, addr, i);
351*19f58992SPatrick Delaunay 		else
352*19f58992SPatrick Delaunay 			ret = stm32mp_bsec_read_otp(dev, addr, i);
353*19f58992SPatrick Delaunay 
354*19f58992SPatrick Delaunay 		if (ret)
355*19f58992SPatrick Delaunay 			break;
356*19f58992SPatrick Delaunay 	}
357*19f58992SPatrick Delaunay 	return ret;
358*19f58992SPatrick Delaunay }
359*19f58992SPatrick Delaunay 
stm32mp_bsec_write(struct udevice * dev,int offset,const void * buf,int size)360*19f58992SPatrick Delaunay static int stm32mp_bsec_write(struct udevice *dev, int offset,
361*19f58992SPatrick Delaunay 			      const void *buf, int size)
362*19f58992SPatrick Delaunay {
363*19f58992SPatrick Delaunay 	int ret = 0;
364*19f58992SPatrick Delaunay 	int i;
365*19f58992SPatrick Delaunay 	bool shadow = true;
366*19f58992SPatrick Delaunay 	int nb_otp = size / sizeof(u32);
367*19f58992SPatrick Delaunay 	int otp;
368*19f58992SPatrick Delaunay 
369*19f58992SPatrick Delaunay 	if (offset >= STM32_BSEC_OTP_OFFSET) {
370*19f58992SPatrick Delaunay 		offset -= STM32_BSEC_OTP_OFFSET;
371*19f58992SPatrick Delaunay 		shadow = false;
372*19f58992SPatrick Delaunay 	}
373*19f58992SPatrick Delaunay 	otp = offset / sizeof(u32);
374*19f58992SPatrick Delaunay 
375*19f58992SPatrick Delaunay 	if (otp < 0 || (otp + nb_otp - 1) > BSEC_OTP_MAX_VALUE) {
376*19f58992SPatrick Delaunay 		dev_err(dev, "wrong value for otp, max value : %d\n",
377*19f58992SPatrick Delaunay 			BSEC_OTP_MAX_VALUE);
378*19f58992SPatrick Delaunay 		return -EINVAL;
379*19f58992SPatrick Delaunay 	}
380*19f58992SPatrick Delaunay 
381*19f58992SPatrick Delaunay 	for (i = otp; i < otp + nb_otp; i++) {
382*19f58992SPatrick Delaunay 		u32 *val = &((u32 *)buf)[i - otp];
383*19f58992SPatrick Delaunay 
384*19f58992SPatrick Delaunay 		if (shadow)
385*19f58992SPatrick Delaunay 			ret = stm32mp_bsec_write_shadow(dev, *val, i);
386*19f58992SPatrick Delaunay 		else
387*19f58992SPatrick Delaunay 			ret = stm32mp_bsec_write_otp(dev, *val, i);
388*19f58992SPatrick Delaunay 		if (ret)
389*19f58992SPatrick Delaunay 			break;
390*19f58992SPatrick Delaunay 	}
391*19f58992SPatrick Delaunay 	return ret;
392*19f58992SPatrick Delaunay }
393*19f58992SPatrick Delaunay 
394*19f58992SPatrick Delaunay static const struct misc_ops stm32mp_bsec_ops = {
395*19f58992SPatrick Delaunay 	.read = stm32mp_bsec_read,
396*19f58992SPatrick Delaunay 	.write = stm32mp_bsec_write,
397*19f58992SPatrick Delaunay };
398*19f58992SPatrick Delaunay 
stm32mp_bsec_ofdata_to_platdata(struct udevice * dev)399*19f58992SPatrick Delaunay static int stm32mp_bsec_ofdata_to_platdata(struct udevice *dev)
400*19f58992SPatrick Delaunay {
401*19f58992SPatrick Delaunay 	struct stm32mp_bsec_platdata *plat = dev_get_platdata(dev);
402*19f58992SPatrick Delaunay 
403*19f58992SPatrick Delaunay 	plat->base = (u32)dev_read_addr_ptr(dev);
404*19f58992SPatrick Delaunay 
405*19f58992SPatrick Delaunay 	return 0;
406*19f58992SPatrick Delaunay }
407*19f58992SPatrick Delaunay 
408*19f58992SPatrick Delaunay static const struct udevice_id stm32mp_bsec_ids[] = {
409*19f58992SPatrick Delaunay 	{ .compatible = "st,stm32mp-bsec" },
410*19f58992SPatrick Delaunay 	{}
411*19f58992SPatrick Delaunay };
412*19f58992SPatrick Delaunay 
413*19f58992SPatrick Delaunay U_BOOT_DRIVER(stm32mp_bsec) = {
414*19f58992SPatrick Delaunay 	.name = "stm32mp_bsec",
415*19f58992SPatrick Delaunay 	.id = UCLASS_MISC,
416*19f58992SPatrick Delaunay 	.of_match = stm32mp_bsec_ids,
417*19f58992SPatrick Delaunay 	.ofdata_to_platdata = stm32mp_bsec_ofdata_to_platdata,
418*19f58992SPatrick Delaunay 	.platdata_auto_alloc_size = sizeof(struct stm32mp_bsec_platdata),
419*19f58992SPatrick Delaunay 	.ops = &stm32mp_bsec_ops,
420*19f58992SPatrick Delaunay };
421*19f58992SPatrick Delaunay 
422*19f58992SPatrick Delaunay /* bsec IP is not present in device tee, manage IP address by platdata */
423*19f58992SPatrick Delaunay static struct stm32mp_bsec_platdata stm32_bsec_platdata = {
424*19f58992SPatrick Delaunay 	.base = STM32_BSEC_BASE,
425*19f58992SPatrick Delaunay };
426*19f58992SPatrick Delaunay 
427*19f58992SPatrick Delaunay U_BOOT_DEVICE(stm32mp_bsec) = {
428*19f58992SPatrick Delaunay 	.name = "stm32mp_bsec",
429*19f58992SPatrick Delaunay 	.platdata = &stm32_bsec_platdata,
430*19f58992SPatrick Delaunay };
431