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