blob: 88c7aec8b4300e1a76ab02092b279538b789fac8 [file] [log] [blame]
Patrick Delaunay19f58992018-05-17 15:24:05 +02001// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Copyright (C) 2018, STMicroelectronics - All Rights Reserved
4 */
5
Patrick Delaunayb66bfdf2020-11-06 19:01:31 +01006#define LOG_CATEGORY UCLASS_MISC
7
Patrick Delaunay19f58992018-05-17 15:24:05 +02008#include <common.h>
9#include <dm.h>
Simon Glassf7ae49f2020-05-10 11:40:05 -060010#include <log.h>
Patrick Delaunay19f58992018-05-17 15:24:05 +020011#include <misc.h>
12#include <asm/io.h>
Patrick Delaunaybd3f60d2020-06-16 18:27:44 +020013#include <asm/arch/bsec.h>
Patrick Delaunayd859c612019-02-12 11:44:40 +010014#include <asm/arch/stm32mp1_smc.h>
Patrick Delaunayb66bfdf2020-11-06 19:01:31 +010015#include <dm/device_compat.h>
Patrick Delaunayd859c612019-02-12 11:44:40 +010016#include <linux/arm-smccc.h>
Patrick Delaunayee7d7722019-04-18 17:32:39 +020017#include <linux/iopoll.h>
Patrick Delaunay19f58992018-05-17 15:24:05 +020018
19#define BSEC_OTP_MAX_VALUE 95
Patrick Delaunay19f58992018-05-17 15:24:05 +020020#define BSEC_TIMEOUT_US 10000
21
22/* BSEC REGISTER OFFSET (base relative) */
23#define BSEC_OTP_CONF_OFF 0x000
24#define BSEC_OTP_CTRL_OFF 0x004
25#define BSEC_OTP_WRDATA_OFF 0x008
26#define BSEC_OTP_STATUS_OFF 0x00C
27#define BSEC_OTP_LOCK_OFF 0x010
Patrick Delaunaybd3f60d2020-06-16 18:27:44 +020028#define BSEC_DENABLE_OFF 0x014
Patrick Delaunay19f58992018-05-17 15:24:05 +020029#define BSEC_DISTURBED_OFF 0x01C
30#define BSEC_ERROR_OFF 0x034
Patrick Delaunay7ae22d72020-02-12 19:37:38 +010031#define BSEC_WRLOCK_OFF 0x04C /* OTP write permananet lock */
32#define BSEC_SPLOCK_OFF 0x064 /* OTP write sticky lock */
33#define BSEC_SWLOCK_OFF 0x07C /* shadow write sticky lock */
34#define BSEC_SRLOCK_OFF 0x094 /* shadow read sticky lock */
Patrick Delaunay19f58992018-05-17 15:24:05 +020035#define BSEC_OTP_DATA_OFF 0x200
36
37/* BSEC_CONFIGURATION Register MASK */
38#define BSEC_CONF_POWER_UP 0x001
39
40/* BSEC_CONTROL Register */
41#define BSEC_READ 0x000
42#define BSEC_WRITE 0x100
43
44/* LOCK Register */
45#define OTP_LOCK_MASK 0x1F
46#define OTP_LOCK_BANK_SHIFT 0x05
47#define OTP_LOCK_BIT_MASK 0x01
48
49/* STATUS Register */
50#define BSEC_MODE_BUSY_MASK 0x08
51#define BSEC_MODE_PROGFAIL_MASK 0x10
52#define BSEC_MODE_PWR_MASK 0x20
53
Patrick Delaunaybd3f60d2020-06-16 18:27:44 +020054/* DENABLE Register */
55#define BSEC_DENABLE_DBGSWENABLE BIT(10)
56
Patrick Delaunay19f58992018-05-17 15:24:05 +020057/*
58 * OTP Lock services definition
59 * Value must corresponding to the bit number in the register
60 */
61#define BSEC_LOCK_PROGRAM 0x04
62
63/**
Patrick Delaunay7ae22d72020-02-12 19:37:38 +010064 * bsec_lock() - manage lock for each type SR/SP/SW
65 * @address: address of bsec IP register
66 * @otp: otp number (0 - BSEC_OTP_MAX_VALUE)
67 * Return: true if locked else false
68 */
69static bool bsec_read_lock(u32 address, u32 otp)
70{
71 u32 bit;
72 u32 bank;
73
74 bit = 1 << (otp & OTP_LOCK_MASK);
75 bank = ((otp >> OTP_LOCK_BANK_SHIFT) & OTP_LOCK_MASK) * sizeof(u32);
76
77 return !!(readl(address + bank) & bit);
78}
79
Patrick Delaunay7ae22d72020-02-12 19:37:38 +010080/**
Patrick Delaunay19f58992018-05-17 15:24:05 +020081 * bsec_check_error() - Check status of one otp
82 * @base: base address of bsec IP
83 * @otp: otp number (0 - BSEC_OTP_MAX_VALUE)
84 * Return: 0 if no error, -EAGAIN or -ENOTSUPP
85 */
86static u32 bsec_check_error(u32 base, u32 otp)
87{
88 u32 bit;
89 u32 bank;
90
91 bit = 1 << (otp & OTP_LOCK_MASK);
92 bank = ((otp >> OTP_LOCK_BANK_SHIFT) & OTP_LOCK_MASK) * sizeof(u32);
93
94 if (readl(base + BSEC_DISTURBED_OFF + bank) & bit)
95 return -EAGAIN;
96 else if (readl(base + BSEC_ERROR_OFF + bank) & bit)
97 return -ENOTSUPP;
98
99 return 0;
100}
101
102/**
Patrick Delaunay19f58992018-05-17 15:24:05 +0200103 * bsec_read_SR_lock() - read SR lock (Shadowing)
104 * @base: base address of bsec IP
105 * @otp: otp number (0 - BSEC_OTP_MAX_VALUE)
106 * Return: true if locked else false
107 */
108static bool bsec_read_SR_lock(u32 base, u32 otp)
109{
110 return bsec_read_lock(base + BSEC_SRLOCK_OFF, otp);
111}
112
113/**
114 * bsec_read_SP_lock() - read SP lock (program Lock)
115 * @base: base address of bsec IP
116 * @otp: otp number (0 - BSEC_OTP_MAX_VALUE)
117 * Return: true if locked else false
118 */
119static bool bsec_read_SP_lock(u32 base, u32 otp)
120{
121 return bsec_read_lock(base + BSEC_SPLOCK_OFF, otp);
122}
123
124/**
125 * bsec_SW_lock() - manage SW lock (Write in Shadow)
126 * @base: base address of bsec IP
127 * @otp: otp number (0 - BSEC_OTP_MAX_VALUE)
128 * Return: true if locked else false
129 */
130static bool bsec_read_SW_lock(u32 base, u32 otp)
131{
132 return bsec_read_lock(base + BSEC_SWLOCK_OFF, otp);
133}
134
135/**
136 * bsec_power_safmem() - Activate or deactivate safmem power
137 * @base: base address of bsec IP
138 * @power: true to power up , false to power down
139 * Return: 0 if succeed
140 */
141static int bsec_power_safmem(u32 base, bool power)
142{
143 u32 val;
144 u32 mask;
145
146 if (power) {
147 setbits_le32(base + BSEC_OTP_CONF_OFF, BSEC_CONF_POWER_UP);
148 mask = BSEC_MODE_PWR_MASK;
149 } else {
150 clrbits_le32(base + BSEC_OTP_CONF_OFF, BSEC_CONF_POWER_UP);
151 mask = 0;
152 }
153
154 /* waiting loop */
155 return readl_poll_timeout(base + BSEC_OTP_STATUS_OFF,
156 val, (val & BSEC_MODE_PWR_MASK) == mask,
157 BSEC_TIMEOUT_US);
158}
159
160/**
161 * bsec_shadow_register() - copy safmen otp to bsec data
162 * @base: base address of bsec IP
163 * @otp: otp number (0 - BSEC_OTP_MAX_VALUE)
164 * Return: 0 if no error
165 */
Patrick Delaunayb66bfdf2020-11-06 19:01:31 +0100166static int bsec_shadow_register(struct udevice *dev, u32 base, u32 otp)
Patrick Delaunay19f58992018-05-17 15:24:05 +0200167{
168 u32 val;
169 int ret;
170 bool power_up = false;
171
172 /* check if shadowing of otp is locked */
173 if (bsec_read_SR_lock(base, otp))
Patrick Delaunayb66bfdf2020-11-06 19:01:31 +0100174 dev_dbg(dev, "OTP %d is locked and refreshed with 0\n",
175 otp);
Patrick Delaunay19f58992018-05-17 15:24:05 +0200176
177 /* check if safemem is power up */
178 val = readl(base + BSEC_OTP_STATUS_OFF);
179 if (!(val & BSEC_MODE_PWR_MASK)) {
180 ret = bsec_power_safmem(base, true);
181 if (ret)
182 return ret;
Patrick Delaunay815bc8b2019-02-27 17:01:28 +0100183 power_up = true;
Patrick Delaunay19f58992018-05-17 15:24:05 +0200184 }
185 /* set BSEC_OTP_CTRL_OFF with the otp value*/
186 writel(otp | BSEC_READ, base + BSEC_OTP_CTRL_OFF);
187
188 /* check otp status*/
189 ret = readl_poll_timeout(base + BSEC_OTP_STATUS_OFF,
190 val, (val & BSEC_MODE_BUSY_MASK) == 0,
191 BSEC_TIMEOUT_US);
192 if (ret)
193 return ret;
194
195 ret = bsec_check_error(base, otp);
196
197 if (power_up)
198 bsec_power_safmem(base, false);
199
200 return ret;
201}
202
203/**
204 * bsec_read_shadow() - read an otp data value from shadow
205 * @base: base address of bsec IP
206 * @val: read value
207 * @otp: otp number (0 - BSEC_OTP_MAX_VALUE)
208 * Return: 0 if no error
209 */
Patrick Delaunayb66bfdf2020-11-06 19:01:31 +0100210static int bsec_read_shadow(struct udevice *dev, u32 base, u32 *val, u32 otp)
Patrick Delaunay19f58992018-05-17 15:24:05 +0200211{
212 *val = readl(base + BSEC_OTP_DATA_OFF + otp * sizeof(u32));
213
214 return bsec_check_error(base, otp);
215}
216
217/**
218 * bsec_write_shadow() - write value in BSEC data register in shadow
219 * @base: base address of bsec IP
220 * @val: value to write
221 * @otp: otp number (0 - BSEC_OTP_MAX_VALUE)
222 * Return: 0 if no error
223 */
Patrick Delaunayb66bfdf2020-11-06 19:01:31 +0100224static int bsec_write_shadow(struct udevice *dev, u32 base, u32 val, u32 otp)
Patrick Delaunay19f58992018-05-17 15:24:05 +0200225{
226 /* check if programming of otp is locked */
227 if (bsec_read_SW_lock(base, otp))
Patrick Delaunayb66bfdf2020-11-06 19:01:31 +0100228 dev_dbg(dev, "OTP %d is lock, write will be ignore\n", otp);
Patrick Delaunay19f58992018-05-17 15:24:05 +0200229
230 writel(val, base + BSEC_OTP_DATA_OFF + otp * sizeof(u32));
231
232 return bsec_check_error(base, otp);
233}
234
235/**
236 * bsec_program_otp() - program a bit in SAFMEM
237 * @base: base address of bsec IP
238 * @val: value to program
239 * @otp: otp number (0 - BSEC_OTP_MAX_VALUE)
240 * after the function the otp data is not refreshed in shadow
241 * Return: 0 if no error
242 */
Patrick Delaunayb66bfdf2020-11-06 19:01:31 +0100243static int bsec_program_otp(struct udevice *dev, long base, u32 val, u32 otp)
Patrick Delaunay19f58992018-05-17 15:24:05 +0200244{
245 u32 ret;
246 bool power_up = false;
247
248 if (bsec_read_SP_lock(base, otp))
Patrick Delaunayb66bfdf2020-11-06 19:01:31 +0100249 dev_dbg(dev, "OTP %d locked, prog will be ignore\n", otp);
Patrick Delaunay19f58992018-05-17 15:24:05 +0200250
251 if (readl(base + BSEC_OTP_LOCK_OFF) & (1 << BSEC_LOCK_PROGRAM))
Patrick Delaunayb66bfdf2020-11-06 19:01:31 +0100252 dev_dbg(dev, "Global lock, prog will be ignore\n");
Patrick Delaunay19f58992018-05-17 15:24:05 +0200253
254 /* check if safemem is power up */
255 if (!(readl(base + BSEC_OTP_STATUS_OFF) & BSEC_MODE_PWR_MASK)) {
256 ret = bsec_power_safmem(base, true);
257 if (ret)
258 return ret;
259
260 power_up = true;
261 }
262 /* set value in write register*/
263 writel(val, base + BSEC_OTP_WRDATA_OFF);
264
265 /* set BSEC_OTP_CTRL_OFF with the otp value */
266 writel(otp | BSEC_WRITE, base + BSEC_OTP_CTRL_OFF);
267
268 /* check otp status*/
269 ret = readl_poll_timeout(base + BSEC_OTP_STATUS_OFF,
270 val, (val & BSEC_MODE_BUSY_MASK) == 0,
271 BSEC_TIMEOUT_US);
272 if (ret)
273 return ret;
274
275 if (val & BSEC_MODE_PROGFAIL_MASK)
276 ret = -EACCES;
277 else
278 ret = bsec_check_error(base, otp);
279
280 if (power_up)
281 bsec_power_safmem(base, false);
282
283 return ret;
284}
285
286/* BSEC MISC driver *******************************************************/
Simon Glass8a8d24b2020-12-03 16:55:23 -0700287struct stm32mp_bsec_plat {
Patrick Delaunay19f58992018-05-17 15:24:05 +0200288 u32 base;
289};
290
291static int stm32mp_bsec_read_otp(struct udevice *dev, u32 *val, u32 otp)
292{
Simon Glass8a8d24b2020-12-03 16:55:23 -0700293 struct stm32mp_bsec_plat *plat;
Patrick Delaunay19f58992018-05-17 15:24:05 +0200294 u32 tmp_data = 0;
295 int ret;
296
Patrick Delaunay4e9e3582020-07-31 16:31:51 +0200297 if (IS_ENABLED(CONFIG_TFABOOT))
298 return stm32_smc(STM32_SMC_BSEC,
299 STM32_SMC_READ_OTP,
300 otp, 0, val);
301
Simon Glassc69cda22020-12-03 16:55:20 -0700302 plat = dev_get_plat(dev);
Patrick Delaunay4e9e3582020-07-31 16:31:51 +0200303
Patrick Delaunay19f58992018-05-17 15:24:05 +0200304 /* read current shadow value */
Patrick Delaunayb66bfdf2020-11-06 19:01:31 +0100305 ret = bsec_read_shadow(dev, plat->base, &tmp_data, otp);
Patrick Delaunay19f58992018-05-17 15:24:05 +0200306 if (ret)
307 return ret;
308
309 /* copy otp in shadow */
Patrick Delaunayb66bfdf2020-11-06 19:01:31 +0100310 ret = bsec_shadow_register(dev, plat->base, otp);
Patrick Delaunay19f58992018-05-17 15:24:05 +0200311 if (ret)
312 return ret;
313
Patrick Delaunayb66bfdf2020-11-06 19:01:31 +0100314 ret = bsec_read_shadow(dev, plat->base, val, otp);
Patrick Delaunay19f58992018-05-17 15:24:05 +0200315 if (ret)
316 return ret;
317
318 /* restore shadow value */
Patrick Delaunayb66bfdf2020-11-06 19:01:31 +0100319 ret = bsec_write_shadow(dev, plat->base, tmp_data, otp);
Patrick Delaunay4e9e3582020-07-31 16:31:51 +0200320
Patrick Delaunay19f58992018-05-17 15:24:05 +0200321 return ret;
322}
323
324static int stm32mp_bsec_read_shadow(struct udevice *dev, u32 *val, u32 otp)
325{
Simon Glass8a8d24b2020-12-03 16:55:23 -0700326 struct stm32mp_bsec_plat *plat;
Patrick Delaunay4e9e3582020-07-31 16:31:51 +0200327
328 if (IS_ENABLED(CONFIG_TFABOOT))
329 return stm32_smc(STM32_SMC_BSEC,
330 STM32_SMC_READ_SHADOW,
331 otp, 0, val);
332
Simon Glassc69cda22020-12-03 16:55:20 -0700333 plat = dev_get_plat(dev);
Patrick Delaunay19f58992018-05-17 15:24:05 +0200334
Patrick Delaunayb66bfdf2020-11-06 19:01:31 +0100335 return bsec_read_shadow(dev, plat->base, val, otp);
Patrick Delaunay19f58992018-05-17 15:24:05 +0200336}
337
Patrick Delaunay7ae22d72020-02-12 19:37:38 +0100338static int stm32mp_bsec_read_lock(struct udevice *dev, u32 *val, u32 otp)
339{
Simon Glass8a8d24b2020-12-03 16:55:23 -0700340 struct stm32mp_bsec_plat *plat = dev_get_plat(dev);
Patrick Delaunay7ae22d72020-02-12 19:37:38 +0100341
342 /* return OTP permanent write lock status */
343 *val = bsec_read_lock(plat->base + BSEC_WRLOCK_OFF, otp);
344
345 return 0;
346}
347
Patrick Delaunay19f58992018-05-17 15:24:05 +0200348static int stm32mp_bsec_write_otp(struct udevice *dev, u32 val, u32 otp)
349{
Simon Glass8a8d24b2020-12-03 16:55:23 -0700350 struct stm32mp_bsec_plat *plat;
Patrick Delaunay4e9e3582020-07-31 16:31:51 +0200351
352 if (IS_ENABLED(CONFIG_TFABOOT))
353 return stm32_smc_exec(STM32_SMC_BSEC,
354 STM32_SMC_PROG_OTP,
355 otp, val);
356
Simon Glassc69cda22020-12-03 16:55:20 -0700357 plat = dev_get_plat(dev);
Patrick Delaunay19f58992018-05-17 15:24:05 +0200358
Patrick Delaunayb66bfdf2020-11-06 19:01:31 +0100359 return bsec_program_otp(dev, plat->base, val, otp);
Patrick Delaunay4e9e3582020-07-31 16:31:51 +0200360
Patrick Delaunay19f58992018-05-17 15:24:05 +0200361}
362
363static int stm32mp_bsec_write_shadow(struct udevice *dev, u32 val, u32 otp)
364{
Simon Glass8a8d24b2020-12-03 16:55:23 -0700365 struct stm32mp_bsec_plat *plat;
Patrick Delaunay4e9e3582020-07-31 16:31:51 +0200366
367 if (IS_ENABLED(CONFIG_TFABOOT))
368 return stm32_smc_exec(STM32_SMC_BSEC,
369 STM32_SMC_WRITE_SHADOW,
370 otp, val);
371
Simon Glassc69cda22020-12-03 16:55:20 -0700372 plat = dev_get_plat(dev);
Patrick Delaunay19f58992018-05-17 15:24:05 +0200373
Patrick Delaunayb66bfdf2020-11-06 19:01:31 +0100374 return bsec_write_shadow(dev, plat->base, val, otp);
Patrick Delaunay19f58992018-05-17 15:24:05 +0200375}
376
Patrick Delaunay7ae22d72020-02-12 19:37:38 +0100377static int stm32mp_bsec_write_lock(struct udevice *dev, u32 val, u32 otp)
378{
Patrick Delaunay4e9e3582020-07-31 16:31:51 +0200379 if (!IS_ENABLED(CONFIG_TFABOOT))
380 return -ENOTSUPP;
381
Patrick Delaunay7ae22d72020-02-12 19:37:38 +0100382 if (val == 1)
383 return stm32_smc_exec(STM32_SMC_BSEC,
384 STM32_SMC_WRLOCK_OTP,
385 otp, 0);
386 if (val == 0)
387 return 0; /* nothing to do */
388
389 return -EINVAL;
Patrick Delaunay7ae22d72020-02-12 19:37:38 +0100390}
391
Patrick Delaunay19f58992018-05-17 15:24:05 +0200392static int stm32mp_bsec_read(struct udevice *dev, int offset,
393 void *buf, int size)
394{
395 int ret;
396 int i;
Patrick Delaunay7ae22d72020-02-12 19:37:38 +0100397 bool shadow = true, lock = false;
Patrick Delaunay19f58992018-05-17 15:24:05 +0200398 int nb_otp = size / sizeof(u32);
399 int otp;
Patrick Delaunay745b6762019-06-21 15:26:43 +0200400 unsigned int offs = offset;
Patrick Delaunay19f58992018-05-17 15:24:05 +0200401
Patrick Delaunay7ae22d72020-02-12 19:37:38 +0100402 if (offs >= STM32_BSEC_LOCK_OFFSET) {
403 offs -= STM32_BSEC_LOCK_OFFSET;
404 lock = true;
405 } else if (offs >= STM32_BSEC_OTP_OFFSET) {
Patrick Delaunay745b6762019-06-21 15:26:43 +0200406 offs -= STM32_BSEC_OTP_OFFSET;
Patrick Delaunay19f58992018-05-17 15:24:05 +0200407 shadow = false;
408 }
Patrick Delaunay0c8620d2019-08-02 13:08:02 +0200409
Patrick Delaunaydf2d1b82020-02-12 19:37:37 +0100410 if ((offs % 4) || (size % 4))
Patrick Delaunay0c8620d2019-08-02 13:08:02 +0200411 return -EINVAL;
412
Patrick Delaunay745b6762019-06-21 15:26:43 +0200413 otp = offs / sizeof(u32);
Patrick Delaunay19f58992018-05-17 15:24:05 +0200414
Patrick Delaunay0c8620d2019-08-02 13:08:02 +0200415 for (i = otp; i < (otp + nb_otp) && i <= BSEC_OTP_MAX_VALUE; i++) {
Patrick Delaunay19f58992018-05-17 15:24:05 +0200416 u32 *addr = &((u32 *)buf)[i - otp];
417
Patrick Delaunay7ae22d72020-02-12 19:37:38 +0100418 if (lock)
419 ret = stm32mp_bsec_read_lock(dev, addr, i);
420 else if (shadow)
Patrick Delaunay19f58992018-05-17 15:24:05 +0200421 ret = stm32mp_bsec_read_shadow(dev, addr, i);
422 else
423 ret = stm32mp_bsec_read_otp(dev, addr, i);
424
425 if (ret)
426 break;
427 }
Patrick Delaunay0c8620d2019-08-02 13:08:02 +0200428 if (ret)
429 return ret;
430 else
431 return (i - otp) * 4;
Patrick Delaunay19f58992018-05-17 15:24:05 +0200432}
433
434static int stm32mp_bsec_write(struct udevice *dev, int offset,
435 const void *buf, int size)
436{
437 int ret = 0;
438 int i;
Patrick Delaunay7ae22d72020-02-12 19:37:38 +0100439 bool shadow = true, lock = false;
Patrick Delaunay19f58992018-05-17 15:24:05 +0200440 int nb_otp = size / sizeof(u32);
441 int otp;
Patrick Delaunay745b6762019-06-21 15:26:43 +0200442 unsigned int offs = offset;
Patrick Delaunay19f58992018-05-17 15:24:05 +0200443
Patrick Delaunay7ae22d72020-02-12 19:37:38 +0100444 if (offs >= STM32_BSEC_LOCK_OFFSET) {
445 offs -= STM32_BSEC_LOCK_OFFSET;
446 lock = true;
447 } else if (offs >= STM32_BSEC_OTP_OFFSET) {
Patrick Delaunay745b6762019-06-21 15:26:43 +0200448 offs -= STM32_BSEC_OTP_OFFSET;
Patrick Delaunay19f58992018-05-17 15:24:05 +0200449 shadow = false;
450 }
Patrick Delaunay0c8620d2019-08-02 13:08:02 +0200451
Patrick Delaunaydf2d1b82020-02-12 19:37:37 +0100452 if ((offs % 4) || (size % 4))
Patrick Delaunay0c8620d2019-08-02 13:08:02 +0200453 return -EINVAL;
454
Patrick Delaunay745b6762019-06-21 15:26:43 +0200455 otp = offs / sizeof(u32);
Patrick Delaunay19f58992018-05-17 15:24:05 +0200456
Patrick Delaunay0c8620d2019-08-02 13:08:02 +0200457 for (i = otp; i < otp + nb_otp && i <= BSEC_OTP_MAX_VALUE; i++) {
Patrick Delaunay19f58992018-05-17 15:24:05 +0200458 u32 *val = &((u32 *)buf)[i - otp];
459
Patrick Delaunay7ae22d72020-02-12 19:37:38 +0100460 if (lock)
461 ret = stm32mp_bsec_write_lock(dev, *val, i);
462 else if (shadow)
Patrick Delaunay19f58992018-05-17 15:24:05 +0200463 ret = stm32mp_bsec_write_shadow(dev, *val, i);
464 else
465 ret = stm32mp_bsec_write_otp(dev, *val, i);
466 if (ret)
467 break;
468 }
Patrick Delaunay0c8620d2019-08-02 13:08:02 +0200469 if (ret)
470 return ret;
471 else
472 return (i - otp) * 4;
Patrick Delaunay19f58992018-05-17 15:24:05 +0200473}
474
475static const struct misc_ops stm32mp_bsec_ops = {
476 .read = stm32mp_bsec_read,
477 .write = stm32mp_bsec_write,
478};
479
Simon Glassd1998a92020-12-03 16:55:21 -0700480static int stm32mp_bsec_of_to_plat(struct udevice *dev)
Patrick Delaunay19f58992018-05-17 15:24:05 +0200481{
Simon Glass8a8d24b2020-12-03 16:55:23 -0700482 struct stm32mp_bsec_plat *plat = dev_get_plat(dev);
Patrick Delaunay19f58992018-05-17 15:24:05 +0200483
484 plat->base = (u32)dev_read_addr_ptr(dev);
485
486 return 0;
487}
488
Patrick Delaunay815bc8b2019-02-27 17:01:28 +0100489static int stm32mp_bsec_probe(struct udevice *dev)
490{
491 int otp;
Simon Glass8a8d24b2020-12-03 16:55:23 -0700492 struct stm32mp_bsec_plat *plat;
Patrick Delaunay815bc8b2019-02-27 17:01:28 +0100493
Patrick Delaunay95bd49a2020-05-25 12:19:41 +0200494 /*
495 * update unlocked shadow for OTP cleared by the rom code
496 * only executed in U-Boot proper when TF-A is not used
497 */
Patrick Delaunay4e9e3582020-07-31 16:31:51 +0200498
499 if (!IS_ENABLED(CONFIG_TFABOOT) && !IS_ENABLED(CONFIG_SPL_BUILD)) {
Simon Glassc69cda22020-12-03 16:55:20 -0700500 plat = dev_get_plat(dev);
Patrick Delaunay4e9e3582020-07-31 16:31:51 +0200501
502 for (otp = 57; otp <= BSEC_OTP_MAX_VALUE; otp++)
503 if (!bsec_read_SR_lock(plat->base, otp))
Patrick Delaunayb66bfdf2020-11-06 19:01:31 +0100504 bsec_shadow_register(dev, plat->base, otp);
Patrick Delaunay4e9e3582020-07-31 16:31:51 +0200505 }
Patrick Delaunay815bc8b2019-02-27 17:01:28 +0100506
507 return 0;
508}
Patrick Delaunay815bc8b2019-02-27 17:01:28 +0100509
Patrick Delaunay19f58992018-05-17 15:24:05 +0200510static const struct udevice_id stm32mp_bsec_ids[] = {
Patrick Delaunaybfe1f082019-02-27 17:01:27 +0100511 { .compatible = "st,stm32mp15-bsec" },
Patrick Delaunay19f58992018-05-17 15:24:05 +0200512 {}
513};
514
515U_BOOT_DRIVER(stm32mp_bsec) = {
516 .name = "stm32mp_bsec",
517 .id = UCLASS_MISC,
518 .of_match = stm32mp_bsec_ids,
Simon Glassd1998a92020-12-03 16:55:21 -0700519 .of_to_plat = stm32mp_bsec_of_to_plat,
Simon Glass8a8d24b2020-12-03 16:55:23 -0700520 .plat_auto = sizeof(struct stm32mp_bsec_plat),
Patrick Delaunay19f58992018-05-17 15:24:05 +0200521 .ops = &stm32mp_bsec_ops,
Patrick Delaunay815bc8b2019-02-27 17:01:28 +0100522 .probe = stm32mp_bsec_probe,
Patrick Delaunay19f58992018-05-17 15:24:05 +0200523};
Patrick Delaunaybd3f60d2020-06-16 18:27:44 +0200524
525bool bsec_dbgswenable(void)
526{
527 struct udevice *dev;
Simon Glass8a8d24b2020-12-03 16:55:23 -0700528 struct stm32mp_bsec_plat *plat;
Patrick Delaunaybd3f60d2020-06-16 18:27:44 +0200529 int ret;
530
531 ret = uclass_get_device_by_driver(UCLASS_MISC,
Simon Glass65e25be2020-12-28 20:34:56 -0700532 DM_DRIVER_GET(stm32mp_bsec), &dev);
Patrick Delaunaybd3f60d2020-06-16 18:27:44 +0200533 if (ret || !dev) {
Patrick Delaunayb66bfdf2020-11-06 19:01:31 +0100534 log_debug("bsec driver not available\n");
Patrick Delaunaybd3f60d2020-06-16 18:27:44 +0200535 return false;
536 }
537
Simon Glassc69cda22020-12-03 16:55:20 -0700538 plat = dev_get_plat(dev);
Patrick Delaunaybd3f60d2020-06-16 18:27:44 +0200539 if (readl(plat->base + BSEC_DENABLE_OFF) & BSEC_DENABLE_DBGSWENABLE)
540 return true;
541
542 return false;
543}