blob: 599e63a93dd90ec1f02c12c5cbfbb562cc15680f [file] [log] [blame]
Patrick Delaunay14d6a242018-05-17 15:24:05 +02001// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Copyright (C) 2018, STMicroelectronics - All Rights Reserved
4 */
5
Patrick Delaunayfbefc102020-11-06 19:01:31 +01006#define LOG_CATEGORY UCLASS_MISC
7
Patrick Delaunay14d6a242018-05-17 15:24:05 +02008#include <common.h>
Patrick Delaunayaaf1f962021-02-25 13:43:07 +01009#include <clk.h>
Patrick Delaunay14d6a242018-05-17 15:24:05 +020010#include <dm.h>
Simon Glass0f2af882020-05-10 11:40:05 -060011#include <log.h>
Patrick Delaunay14d6a242018-05-17 15:24:05 +020012#include <misc.h>
Patrick Delaunayd5388292023-01-06 13:20:15 +010013#include <tee.h>
Patrick Delaunay14d6a242018-05-17 15:24:05 +020014#include <asm/io.h>
Patrick Delaunay6332c042020-06-16 18:27:44 +020015#include <asm/arch/bsec.h>
Patrick Delaunay7858d7e2019-02-12 11:44:40 +010016#include <asm/arch/stm32mp1_smc.h>
Patrick Delaunayd5388292023-01-06 13:20:15 +010017#include <dm/device.h>
Patrick Delaunayfbefc102020-11-06 19:01:31 +010018#include <dm/device_compat.h>
Patrick Delaunay7858d7e2019-02-12 11:44:40 +010019#include <linux/arm-smccc.h>
Patrick Delaunay2fa55eb2019-04-18 17:32:39 +020020#include <linux/iopoll.h>
Simon Glassbdd5f812023-09-14 18:21:46 -060021#include <linux/printk.h>
Patrick Delaunay14d6a242018-05-17 15:24:05 +020022
23#define BSEC_OTP_MAX_VALUE 95
Patrick Delaunayb9201a72022-02-15 16:08:50 +010024#define BSEC_OTP_UPPER_START 32
Patrick Delaunay14d6a242018-05-17 15:24:05 +020025#define BSEC_TIMEOUT_US 10000
26
27/* BSEC REGISTER OFFSET (base relative) */
28#define BSEC_OTP_CONF_OFF 0x000
29#define BSEC_OTP_CTRL_OFF 0x004
30#define BSEC_OTP_WRDATA_OFF 0x008
31#define BSEC_OTP_STATUS_OFF 0x00C
32#define BSEC_OTP_LOCK_OFF 0x010
Patrick Delaunay6332c042020-06-16 18:27:44 +020033#define BSEC_DENABLE_OFF 0x014
Patrick Delaunay14d6a242018-05-17 15:24:05 +020034#define BSEC_DISTURBED_OFF 0x01C
35#define BSEC_ERROR_OFF 0x034
Patrick Delaunayb10cddf2020-02-12 19:37:38 +010036#define BSEC_WRLOCK_OFF 0x04C /* OTP write permananet lock */
37#define BSEC_SPLOCK_OFF 0x064 /* OTP write sticky lock */
38#define BSEC_SWLOCK_OFF 0x07C /* shadow write sticky lock */
39#define BSEC_SRLOCK_OFF 0x094 /* shadow read sticky lock */
Patrick Delaunay14d6a242018-05-17 15:24:05 +020040#define BSEC_OTP_DATA_OFF 0x200
41
42/* BSEC_CONFIGURATION Register MASK */
43#define BSEC_CONF_POWER_UP 0x001
44
45/* BSEC_CONTROL Register */
46#define BSEC_READ 0x000
47#define BSEC_WRITE 0x100
Patrick Delaunayb9201a72022-02-15 16:08:50 +010048#define BSEC_LOCK 0x200
Patrick Delaunay14d6a242018-05-17 15:24:05 +020049
50/* LOCK Register */
51#define OTP_LOCK_MASK 0x1F
52#define OTP_LOCK_BANK_SHIFT 0x05
53#define OTP_LOCK_BIT_MASK 0x01
54
55/* STATUS Register */
56#define BSEC_MODE_BUSY_MASK 0x08
57#define BSEC_MODE_PROGFAIL_MASK 0x10
58#define BSEC_MODE_PWR_MASK 0x20
59
Patrick Delaunay6332c042020-06-16 18:27:44 +020060/* DENABLE Register */
61#define BSEC_DENABLE_DBGSWENABLE BIT(10)
62
Patrick Delaunay14d6a242018-05-17 15:24:05 +020063/*
64 * OTP Lock services definition
65 * Value must corresponding to the bit number in the register
66 */
67#define BSEC_LOCK_PROGRAM 0x04
68
Patrick Delaunayd5388292023-01-06 13:20:15 +010069#define PTA_BSEC_UUID { 0x94cf71ad, 0x80e6, 0x40b5, \
70 { 0xa7, 0xc6, 0x3d, 0xc5, 0x01, 0xeb, 0x28, 0x03 } }
71
72/*
73 * Read OTP memory
74 *
75 * [in] value[0].a OTP start offset in byte
76 * [in] value[0].b Access type (0:shadow, 1:fuse, 2:lock)
77 * [out] memref[1].buffer Output buffer to store read values
78 * [out] memref[1].size Size of OTP to be read
79 *
80 * Return codes:
81 * TEE_SUCCESS - Invoke command success
82 * TEE_ERROR_BAD_PARAMETERS - Incorrect input param
83 * TEE_ERROR_ACCESS_DENIED - OTP not accessible by caller
84 */
85#define PTA_BSEC_READ_MEM 0x0
86
Patrick Delaunayb9201a72022-02-15 16:08:50 +010087/*
Patrick Delaunayd5388292023-01-06 13:20:15 +010088 * Write OTP memory
89 *
90 * [in] value[0].a OTP start offset in byte
91 * [in] value[0].b Access type (0:shadow, 1:fuse, 2:lock)
92 * [in] memref[1].buffer Input buffer to read values
93 * [in] memref[1].size Size of OTP to be written
94 *
95 * Return codes:
96 * TEE_SUCCESS - Invoke command success
97 * TEE_ERROR_BAD_PARAMETERS - Incorrect input param
98 * TEE_ERROR_ACCESS_DENIED - OTP not accessible by caller
Patrick Delaunayb9201a72022-02-15 16:08:50 +010099 */
Patrick Delaunayd5388292023-01-06 13:20:15 +0100100#define PTA_BSEC_WRITE_MEM 0x1
101
102/* value of PTA_BSEC access type = value[in] b */
103#define SHADOW_ACCESS 0
104#define FUSE_ACCESS 1
105#define LOCK_ACCESS 2
Patrick Delaunayb9201a72022-02-15 16:08:50 +0100106
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200107/**
Patrick Delaunayb10cddf2020-02-12 19:37:38 +0100108 * bsec_lock() - manage lock for each type SR/SP/SW
109 * @address: address of bsec IP register
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200110 * @otp: otp number (0 - BSEC_OTP_MAX_VALUE)
Patrick Delaunayb10cddf2020-02-12 19:37:38 +0100111 * Return: true if locked else false
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200112 */
Patrick Delaunayb10cddf2020-02-12 19:37:38 +0100113static bool bsec_read_lock(u32 address, u32 otp)
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200114{
115 u32 bit;
116 u32 bank;
117
118 bit = 1 << (otp & OTP_LOCK_MASK);
119 bank = ((otp >> OTP_LOCK_BANK_SHIFT) & OTP_LOCK_MASK) * sizeof(u32);
120
Patrick Delaunayb10cddf2020-02-12 19:37:38 +0100121 return !!(readl(address + bank) & bit);
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200122}
123
124/**
Patrick Delaunayb10cddf2020-02-12 19:37:38 +0100125 * bsec_check_error() - Check status of one otp
126 * @base: base address of bsec IP
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200127 * @otp: otp number (0 - BSEC_OTP_MAX_VALUE)
Patrick Delaunayb10cddf2020-02-12 19:37:38 +0100128 * Return: 0 if no error, -EAGAIN or -ENOTSUPP
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200129 */
Patrick Delaunayb10cddf2020-02-12 19:37:38 +0100130static u32 bsec_check_error(u32 base, u32 otp)
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200131{
132 u32 bit;
133 u32 bank;
134
135 bit = 1 << (otp & OTP_LOCK_MASK);
136 bank = ((otp >> OTP_LOCK_BANK_SHIFT) & OTP_LOCK_MASK) * sizeof(u32);
137
Patrick Delaunayb10cddf2020-02-12 19:37:38 +0100138 if (readl(base + BSEC_DISTURBED_OFF + bank) & bit)
139 return -EAGAIN;
140 else if (readl(base + BSEC_ERROR_OFF + bank) & bit)
141 return -ENOTSUPP;
142
143 return 0;
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200144}
145
146/**
147 * bsec_read_SR_lock() - read SR lock (Shadowing)
148 * @base: base address of bsec IP
149 * @otp: otp number (0 - BSEC_OTP_MAX_VALUE)
150 * Return: true if locked else false
151 */
152static bool bsec_read_SR_lock(u32 base, u32 otp)
153{
154 return bsec_read_lock(base + BSEC_SRLOCK_OFF, otp);
155}
156
157/**
158 * bsec_read_SP_lock() - read SP lock (program Lock)
159 * @base: base address of bsec IP
160 * @otp: otp number (0 - BSEC_OTP_MAX_VALUE)
161 * Return: true if locked else false
162 */
163static bool bsec_read_SP_lock(u32 base, u32 otp)
164{
165 return bsec_read_lock(base + BSEC_SPLOCK_OFF, otp);
166}
167
168/**
169 * bsec_SW_lock() - manage SW lock (Write in Shadow)
170 * @base: base address of bsec IP
171 * @otp: otp number (0 - BSEC_OTP_MAX_VALUE)
172 * Return: true if locked else false
173 */
174static bool bsec_read_SW_lock(u32 base, u32 otp)
175{
176 return bsec_read_lock(base + BSEC_SWLOCK_OFF, otp);
177}
178
179/**
180 * bsec_power_safmem() - Activate or deactivate safmem power
181 * @base: base address of bsec IP
182 * @power: true to power up , false to power down
183 * Return: 0 if succeed
184 */
185static int bsec_power_safmem(u32 base, bool power)
186{
187 u32 val;
188 u32 mask;
189
190 if (power) {
191 setbits_le32(base + BSEC_OTP_CONF_OFF, BSEC_CONF_POWER_UP);
192 mask = BSEC_MODE_PWR_MASK;
193 } else {
194 clrbits_le32(base + BSEC_OTP_CONF_OFF, BSEC_CONF_POWER_UP);
195 mask = 0;
196 }
197
198 /* waiting loop */
199 return readl_poll_timeout(base + BSEC_OTP_STATUS_OFF,
200 val, (val & BSEC_MODE_PWR_MASK) == mask,
201 BSEC_TIMEOUT_US);
202}
203
204/**
205 * bsec_shadow_register() - copy safmen otp to bsec data
Patrick Delaunay6292db12022-02-15 16:08:51 +0100206 * @dev: bsec IP device
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200207 * @base: base address of bsec IP
208 * @otp: otp number (0 - BSEC_OTP_MAX_VALUE)
209 * Return: 0 if no error
210 */
Patrick Delaunayfbefc102020-11-06 19:01:31 +0100211static int bsec_shadow_register(struct udevice *dev, u32 base, u32 otp)
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200212{
213 u32 val;
214 int ret;
215 bool power_up = false;
216
217 /* check if shadowing of otp is locked */
218 if (bsec_read_SR_lock(base, otp))
Patrick Delaunayfbefc102020-11-06 19:01:31 +0100219 dev_dbg(dev, "OTP %d is locked and refreshed with 0\n",
220 otp);
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200221
222 /* check if safemem is power up */
223 val = readl(base + BSEC_OTP_STATUS_OFF);
224 if (!(val & BSEC_MODE_PWR_MASK)) {
225 ret = bsec_power_safmem(base, true);
226 if (ret)
227 return ret;
Patrick Delaunayf95686b2019-02-27 17:01:28 +0100228 power_up = true;
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200229 }
230 /* set BSEC_OTP_CTRL_OFF with the otp value*/
231 writel(otp | BSEC_READ, base + BSEC_OTP_CTRL_OFF);
232
233 /* check otp status*/
234 ret = readl_poll_timeout(base + BSEC_OTP_STATUS_OFF,
235 val, (val & BSEC_MODE_BUSY_MASK) == 0,
236 BSEC_TIMEOUT_US);
237 if (ret)
238 return ret;
239
240 ret = bsec_check_error(base, otp);
241
242 if (power_up)
243 bsec_power_safmem(base, false);
244
245 return ret;
246}
247
248/**
249 * bsec_read_shadow() - read an otp data value from shadow
Patrick Delaunay6292db12022-02-15 16:08:51 +0100250 * @dev: bsec IP device
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200251 * @base: base address of bsec IP
252 * @val: read value
253 * @otp: otp number (0 - BSEC_OTP_MAX_VALUE)
254 * Return: 0 if no error
255 */
Patrick Delaunayfbefc102020-11-06 19:01:31 +0100256static int bsec_read_shadow(struct udevice *dev, u32 base, u32 *val, u32 otp)
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200257{
258 *val = readl(base + BSEC_OTP_DATA_OFF + otp * sizeof(u32));
259
260 return bsec_check_error(base, otp);
261}
262
263/**
264 * bsec_write_shadow() - write value in BSEC data register in shadow
Patrick Delaunay6292db12022-02-15 16:08:51 +0100265 * @dev: bsec IP device
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200266 * @base: base address of bsec IP
267 * @val: value to write
268 * @otp: otp number (0 - BSEC_OTP_MAX_VALUE)
269 * Return: 0 if no error
270 */
Patrick Delaunayfbefc102020-11-06 19:01:31 +0100271static int bsec_write_shadow(struct udevice *dev, u32 base, u32 val, u32 otp)
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200272{
273 /* check if programming of otp is locked */
274 if (bsec_read_SW_lock(base, otp))
Patrick Delaunayfbefc102020-11-06 19:01:31 +0100275 dev_dbg(dev, "OTP %d is lock, write will be ignore\n", otp);
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200276
277 writel(val, base + BSEC_OTP_DATA_OFF + otp * sizeof(u32));
278
279 return bsec_check_error(base, otp);
280}
281
282/**
283 * bsec_program_otp() - program a bit in SAFMEM
Patrick Delaunay6292db12022-02-15 16:08:51 +0100284 * @dev: bsec IP device
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200285 * @base: base address of bsec IP
286 * @val: value to program
287 * @otp: otp number (0 - BSEC_OTP_MAX_VALUE)
288 * after the function the otp data is not refreshed in shadow
289 * Return: 0 if no error
290 */
Patrick Delaunayfbefc102020-11-06 19:01:31 +0100291static int bsec_program_otp(struct udevice *dev, long base, u32 val, u32 otp)
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200292{
293 u32 ret;
294 bool power_up = false;
295
296 if (bsec_read_SP_lock(base, otp))
Patrick Delaunayfbefc102020-11-06 19:01:31 +0100297 dev_dbg(dev, "OTP %d locked, prog will be ignore\n", otp);
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200298
299 if (readl(base + BSEC_OTP_LOCK_OFF) & (1 << BSEC_LOCK_PROGRAM))
Patrick Delaunayfbefc102020-11-06 19:01:31 +0100300 dev_dbg(dev, "Global lock, prog will be ignore\n");
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200301
302 /* check if safemem is power up */
303 if (!(readl(base + BSEC_OTP_STATUS_OFF) & BSEC_MODE_PWR_MASK)) {
304 ret = bsec_power_safmem(base, true);
305 if (ret)
306 return ret;
307
308 power_up = true;
309 }
310 /* set value in write register*/
311 writel(val, base + BSEC_OTP_WRDATA_OFF);
312
313 /* set BSEC_OTP_CTRL_OFF with the otp value */
314 writel(otp | BSEC_WRITE, base + BSEC_OTP_CTRL_OFF);
315
316 /* check otp status*/
317 ret = readl_poll_timeout(base + BSEC_OTP_STATUS_OFF,
318 val, (val & BSEC_MODE_BUSY_MASK) == 0,
319 BSEC_TIMEOUT_US);
320 if (ret)
321 return ret;
322
323 if (val & BSEC_MODE_PROGFAIL_MASK)
324 ret = -EACCES;
325 else
326 ret = bsec_check_error(base, otp);
327
328 if (power_up)
329 bsec_power_safmem(base, false);
330
331 return ret;
332}
333
Patrick Delaunayb9201a72022-02-15 16:08:50 +0100334/**
335 * bsec_permanent_lock_otp() - permanent lock of OTP in SAFMEM
336 * @dev: bsec IP device
337 * @base: base address of bsec IP
338 * @otp: otp number (0 - BSEC_OTP_MAX_VALUE)
339 * Return: 0 if no error
340 */
341static int bsec_permanent_lock_otp(struct udevice *dev, long base, uint32_t otp)
342{
343 int ret;
344 bool power_up = false;
345 u32 val, addr;
346
347 /* check if safemem is power up */
348 if (!(readl(base + BSEC_OTP_STATUS_OFF) & BSEC_MODE_PWR_MASK)) {
349 ret = bsec_power_safmem(base, true);
350 if (ret)
351 return ret;
352
353 power_up = true;
354 }
355
356 /*
357 * low OTPs = 2 bits word for low OTPs, 1 bits per word for upper OTP
358 * and only 16 bits used in WRDATA
359 */
360 if (otp < BSEC_OTP_UPPER_START) {
361 addr = otp / 8;
362 val = 0x03 << ((otp * 2) & 0xF);
363 } else {
364 addr = BSEC_OTP_UPPER_START / 8 +
365 ((otp - BSEC_OTP_UPPER_START) / 16);
366 val = 0x01 << (otp & 0xF);
367 }
368
369 /* set value in write register*/
370 writel(val, base + BSEC_OTP_WRDATA_OFF);
371
372 /* set BSEC_OTP_CTRL_OFF with the otp addr and lock request*/
373 writel(addr | BSEC_WRITE | BSEC_LOCK, base + BSEC_OTP_CTRL_OFF);
374
375 /* check otp status*/
376 ret = readl_poll_timeout(base + BSEC_OTP_STATUS_OFF,
377 val, (val & BSEC_MODE_BUSY_MASK) == 0,
378 BSEC_TIMEOUT_US);
379 if (ret)
380 return ret;
381
382 if (val & BSEC_MODE_PROGFAIL_MASK)
383 ret = -EACCES;
384 else
385 ret = bsec_check_error(base, otp);
386
387 if (power_up)
388 bsec_power_safmem(base, false);
389
390 return ret;
391}
392
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200393/* BSEC MISC driver *******************************************************/
Simon Glassb75b15b2020-12-03 16:55:23 -0700394struct stm32mp_bsec_plat {
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200395 u32 base;
396};
397
Patrick Delaunayd5388292023-01-06 13:20:15 +0100398struct stm32mp_bsec_priv {
399 struct udevice *tee;
400};
401
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200402static int stm32mp_bsec_read_otp(struct udevice *dev, u32 *val, u32 otp)
403{
Simon Glassb75b15b2020-12-03 16:55:23 -0700404 struct stm32mp_bsec_plat *plat;
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200405 u32 tmp_data = 0;
406 int ret;
407
Patrick Delaunay72a57622021-10-11 09:52:50 +0200408 if (IS_ENABLED(CONFIG_ARM_SMCCC) && !IS_ENABLED(CONFIG_SPL_BUILD))
Patrick Delaunay1dffeaf2020-07-31 16:31:51 +0200409 return stm32_smc(STM32_SMC_BSEC,
410 STM32_SMC_READ_OTP,
411 otp, 0, val);
412
Simon Glassfa20e932020-12-03 16:55:20 -0700413 plat = dev_get_plat(dev);
Patrick Delaunay1dffeaf2020-07-31 16:31:51 +0200414
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200415 /* read current shadow value */
Patrick Delaunayfbefc102020-11-06 19:01:31 +0100416 ret = bsec_read_shadow(dev, plat->base, &tmp_data, otp);
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200417 if (ret)
418 return ret;
419
420 /* copy otp in shadow */
Patrick Delaunayfbefc102020-11-06 19:01:31 +0100421 ret = bsec_shadow_register(dev, plat->base, otp);
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200422 if (ret)
423 return ret;
424
Patrick Delaunayfbefc102020-11-06 19:01:31 +0100425 ret = bsec_read_shadow(dev, plat->base, val, otp);
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200426 if (ret)
427 return ret;
428
429 /* restore shadow value */
Patrick Delaunayfbefc102020-11-06 19:01:31 +0100430 ret = bsec_write_shadow(dev, plat->base, tmp_data, otp);
Patrick Delaunay1dffeaf2020-07-31 16:31:51 +0200431
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200432 return ret;
433}
434
435static int stm32mp_bsec_read_shadow(struct udevice *dev, u32 *val, u32 otp)
436{
Simon Glassb75b15b2020-12-03 16:55:23 -0700437 struct stm32mp_bsec_plat *plat;
Patrick Delaunay1dffeaf2020-07-31 16:31:51 +0200438
Patrick Delaunay72a57622021-10-11 09:52:50 +0200439 if (IS_ENABLED(CONFIG_ARM_SMCCC) && !IS_ENABLED(CONFIG_SPL_BUILD))
Patrick Delaunay1dffeaf2020-07-31 16:31:51 +0200440 return stm32_smc(STM32_SMC_BSEC,
441 STM32_SMC_READ_SHADOW,
442 otp, 0, val);
443
Simon Glassfa20e932020-12-03 16:55:20 -0700444 plat = dev_get_plat(dev);
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200445
Patrick Delaunayfbefc102020-11-06 19:01:31 +0100446 return bsec_read_shadow(dev, plat->base, val, otp);
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200447}
448
Patrick Delaunayb10cddf2020-02-12 19:37:38 +0100449static int stm32mp_bsec_read_lock(struct udevice *dev, u32 *val, u32 otp)
450{
Simon Glassb75b15b2020-12-03 16:55:23 -0700451 struct stm32mp_bsec_plat *plat = dev_get_plat(dev);
Patrick Delaunayb9201a72022-02-15 16:08:50 +0100452 u32 wrlock;
Patrick Delaunayb10cddf2020-02-12 19:37:38 +0100453
454 /* return OTP permanent write lock status */
Patrick Delaunayb9201a72022-02-15 16:08:50 +0100455 wrlock = bsec_read_lock(plat->base + BSEC_WRLOCK_OFF, otp);
456
457 *val = 0;
458 if (wrlock)
459 *val = BSEC_LOCK_PERM;
Patrick Delaunayb10cddf2020-02-12 19:37:38 +0100460
461 return 0;
462}
463
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200464static int stm32mp_bsec_write_otp(struct udevice *dev, u32 val, u32 otp)
465{
Simon Glassb75b15b2020-12-03 16:55:23 -0700466 struct stm32mp_bsec_plat *plat;
Patrick Delaunay1dffeaf2020-07-31 16:31:51 +0200467
Patrick Delaunay72a57622021-10-11 09:52:50 +0200468 if (IS_ENABLED(CONFIG_ARM_SMCCC) && !IS_ENABLED(CONFIG_SPL_BUILD))
Patrick Delaunay1dffeaf2020-07-31 16:31:51 +0200469 return stm32_smc_exec(STM32_SMC_BSEC,
470 STM32_SMC_PROG_OTP,
471 otp, val);
472
Simon Glassfa20e932020-12-03 16:55:20 -0700473 plat = dev_get_plat(dev);
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200474
Patrick Delaunayfbefc102020-11-06 19:01:31 +0100475 return bsec_program_otp(dev, plat->base, val, otp);
Patrick Delaunay1dffeaf2020-07-31 16:31:51 +0200476
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200477}
478
479static int stm32mp_bsec_write_shadow(struct udevice *dev, u32 val, u32 otp)
480{
Simon Glassb75b15b2020-12-03 16:55:23 -0700481 struct stm32mp_bsec_plat *plat;
Patrick Delaunay1dffeaf2020-07-31 16:31:51 +0200482
Patrick Delaunay72a57622021-10-11 09:52:50 +0200483 if (IS_ENABLED(CONFIG_ARM_SMCCC) && !IS_ENABLED(CONFIG_SPL_BUILD))
Patrick Delaunay1dffeaf2020-07-31 16:31:51 +0200484 return stm32_smc_exec(STM32_SMC_BSEC,
485 STM32_SMC_WRITE_SHADOW,
486 otp, val);
487
Simon Glassfa20e932020-12-03 16:55:20 -0700488 plat = dev_get_plat(dev);
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200489
Patrick Delaunayfbefc102020-11-06 19:01:31 +0100490 return bsec_write_shadow(dev, plat->base, val, otp);
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200491}
492
Patrick Delaunayb10cddf2020-02-12 19:37:38 +0100493static int stm32mp_bsec_write_lock(struct udevice *dev, u32 val, u32 otp)
494{
Patrick Delaunayb9201a72022-02-15 16:08:50 +0100495 struct stm32mp_bsec_plat *plat;
496
497 /* only permanent write lock is supported in U-Boot */
498 if (!(val & BSEC_LOCK_PERM)) {
499 dev_dbg(dev, "lock option without BSEC_LOCK_PERM: %x\n", val);
500 return 0; /* nothing to do */
501 }
Patrick Delaunay1dffeaf2020-07-31 16:31:51 +0200502
Patrick Delaunayb9201a72022-02-15 16:08:50 +0100503 if (IS_ENABLED(CONFIG_ARM_SMCCC) && !IS_ENABLED(CONFIG_SPL_BUILD))
Patrick Delaunayb10cddf2020-02-12 19:37:38 +0100504 return stm32_smc_exec(STM32_SMC_BSEC,
505 STM32_SMC_WRLOCK_OTP,
506 otp, 0);
Patrick Delaunayb9201a72022-02-15 16:08:50 +0100507
508 plat = dev_get_plat(dev);
509
510 return bsec_permanent_lock_otp(dev, plat->base, otp);
Patrick Delaunayb10cddf2020-02-12 19:37:38 +0100511}
512
Patrick Delaunayd5388292023-01-06 13:20:15 +0100513static int bsec_pta_open_session(struct udevice *tee, u32 *tee_session)
514{
515 const struct tee_optee_ta_uuid uuid = PTA_BSEC_UUID;
516 struct tee_open_session_arg arg;
517 int rc;
518
519 memset(&arg, 0, sizeof(arg));
520 tee_optee_ta_uuid_to_octets(arg.uuid, &uuid);
521 arg.clnt_login = TEE_LOGIN_REE_KERNEL;
522 rc = tee_open_session(tee, &arg, 0, NULL);
523 if (rc < 0)
524 return -ENODEV;
525
526 *tee_session = arg.session;
527
528 return 0;
529}
530
531static int bsec_optee_open(struct udevice *dev)
532{
533 struct stm32mp_bsec_priv *priv = dev_get_priv(dev);
534 struct udevice *tee;
535 u32 tee_session;
536 int rc;
537
538 tee = tee_find_device(NULL, NULL, NULL, NULL);
539 if (!tee)
540 return -ENODEV;
541
542 /* try to open the STM32 BSEC TA */
543 rc = bsec_pta_open_session(tee, &tee_session);
544 if (rc)
545 return rc;
546
547 tee_close_session(tee, tee_session);
548
549 priv->tee = tee;
550
551 return 0;
552}
553
554static int bsec_optee_pta(struct udevice *dev, int cmd, int type, int offset,
555 void *buff, ulong size)
556{
557 struct stm32mp_bsec_priv *priv = dev_get_priv(dev);
558 u32 tee_session;
559 struct tee_invoke_arg arg;
560 struct tee_param param[2];
561 struct tee_shm *fw_shm;
562 int rc;
563
564 rc = bsec_pta_open_session(priv->tee, &tee_session);
565 if (rc)
566 return rc;
567
568 rc = tee_shm_register(priv->tee, buff, size, 0, &fw_shm);
569 if (rc)
570 goto close_session;
571
572 memset(&arg, 0, sizeof(arg));
573 arg.func = cmd;
574 arg.session = tee_session;
575
576 memset(param, 0, sizeof(param));
577
578 param[0].attr = TEE_PARAM_ATTR_TYPE_VALUE_INPUT;
579 param[0].u.value.a = offset;
580 param[0].u.value.b = type;
581
582 if (cmd == PTA_BSEC_WRITE_MEM)
583 param[1].attr = TEE_PARAM_ATTR_TYPE_MEMREF_INPUT;
584 else
585 param[1].attr = TEE_PARAM_ATTR_TYPE_MEMREF_OUTPUT;
586
587 param[1].u.memref.shm = fw_shm;
588 param[1].u.memref.size = size;
589
590 rc = tee_invoke_func(priv->tee, &arg, 2, param);
591 if (rc < 0 || arg.ret != 0) {
592 dev_err(priv->tee,
593 "PTA_BSEC invoke failed TEE err: %x, err:%x\n",
594 arg.ret, rc);
595 if (!rc)
596 rc = -EIO;
597 }
598
599 tee_shm_free(fw_shm);
600
601close_session:
602 tee_close_session(priv->tee, tee_session);
603
604 return rc;
605}
606
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200607static int stm32mp_bsec_read(struct udevice *dev, int offset,
608 void *buf, int size)
609{
Patrick Delaunayd5388292023-01-06 13:20:15 +0100610 struct stm32mp_bsec_priv *priv = dev_get_priv(dev);
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200611 int ret;
612 int i;
Patrick Delaunayb10cddf2020-02-12 19:37:38 +0100613 bool shadow = true, lock = false;
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200614 int nb_otp = size / sizeof(u32);
Patrick Delaunayd5388292023-01-06 13:20:15 +0100615 int otp, cmd;
Patrick Delaunay4c7c0742019-06-21 15:26:43 +0200616 unsigned int offs = offset;
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200617
Patrick Delaunayb10cddf2020-02-12 19:37:38 +0100618 if (offs >= STM32_BSEC_LOCK_OFFSET) {
619 offs -= STM32_BSEC_LOCK_OFFSET;
620 lock = true;
621 } else if (offs >= STM32_BSEC_OTP_OFFSET) {
Patrick Delaunay4c7c0742019-06-21 15:26:43 +0200622 offs -= STM32_BSEC_OTP_OFFSET;
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200623 shadow = false;
624 }
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200625
Patrick Delaunay8275ff32023-04-27 15:36:34 +0200626 if ((offs % 4) || (size % 4) || !size)
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200627 return -EINVAL;
Patrick Delaunay7e5f8e32019-08-02 13:08:02 +0200628
Patrick Delaunayd5388292023-01-06 13:20:15 +0100629 if (IS_ENABLED(CONFIG_OPTEE) && priv->tee) {
630 cmd = FUSE_ACCESS;
631 if (shadow)
632 cmd = SHADOW_ACCESS;
633 if (lock)
634 cmd = LOCK_ACCESS;
635 ret = bsec_optee_pta(dev, PTA_BSEC_READ_MEM, cmd, offs, buf, size);
636 if (ret)
637 return ret;
638
639 return size;
640 }
641
Patrick Delaunay7e5f8e32019-08-02 13:08:02 +0200642 otp = offs / sizeof(u32);
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200643
Patrick Delaunay7e5f8e32019-08-02 13:08:02 +0200644 for (i = otp; i < (otp + nb_otp) && i <= BSEC_OTP_MAX_VALUE; i++) {
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200645 u32 *addr = &((u32 *)buf)[i - otp];
646
Patrick Delaunayb10cddf2020-02-12 19:37:38 +0100647 if (lock)
648 ret = stm32mp_bsec_read_lock(dev, addr, i);
649 else if (shadow)
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200650 ret = stm32mp_bsec_read_shadow(dev, addr, i);
651 else
652 ret = stm32mp_bsec_read_otp(dev, addr, i);
653
654 if (ret)
655 break;
656 }
Patrick Delaunay7e5f8e32019-08-02 13:08:02 +0200657 if (ret)
658 return ret;
659 else
660 return (i - otp) * 4;
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200661}
662
663static int stm32mp_bsec_write(struct udevice *dev, int offset,
664 const void *buf, int size)
665{
Patrick Delaunayd5388292023-01-06 13:20:15 +0100666 struct stm32mp_bsec_priv *priv = dev_get_priv(dev);
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200667 int ret = 0;
668 int i;
Patrick Delaunayb10cddf2020-02-12 19:37:38 +0100669 bool shadow = true, lock = false;
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200670 int nb_otp = size / sizeof(u32);
Patrick Delaunayd5388292023-01-06 13:20:15 +0100671 int otp, cmd;
Patrick Delaunay4c7c0742019-06-21 15:26:43 +0200672 unsigned int offs = offset;
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200673
Patrick Delaunayb10cddf2020-02-12 19:37:38 +0100674 if (offs >= STM32_BSEC_LOCK_OFFSET) {
675 offs -= STM32_BSEC_LOCK_OFFSET;
676 lock = true;
677 } else if (offs >= STM32_BSEC_OTP_OFFSET) {
Patrick Delaunay4c7c0742019-06-21 15:26:43 +0200678 offs -= STM32_BSEC_OTP_OFFSET;
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200679 shadow = false;
680 }
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200681
Patrick Delaunay8275ff32023-04-27 15:36:34 +0200682 if ((offs % 4) || (size % 4) || !size)
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200683 return -EINVAL;
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200684
Patrick Delaunayd5388292023-01-06 13:20:15 +0100685 if (IS_ENABLED(CONFIG_OPTEE) && priv->tee) {
686 cmd = FUSE_ACCESS;
687 if (shadow)
688 cmd = SHADOW_ACCESS;
689 if (lock)
690 cmd = LOCK_ACCESS;
691 ret = bsec_optee_pta(dev, PTA_BSEC_WRITE_MEM, cmd, offs, (void *)buf, size);
692 if (ret)
693 return ret;
694
695 return size;
696 }
697
Patrick Delaunay7e5f8e32019-08-02 13:08:02 +0200698 otp = offs / sizeof(u32);
699
700 for (i = otp; i < otp + nb_otp && i <= BSEC_OTP_MAX_VALUE; i++) {
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200701 u32 *val = &((u32 *)buf)[i - otp];
702
Patrick Delaunayb10cddf2020-02-12 19:37:38 +0100703 if (lock)
704 ret = stm32mp_bsec_write_lock(dev, *val, i);
705 else if (shadow)
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200706 ret = stm32mp_bsec_write_shadow(dev, *val, i);
707 else
708 ret = stm32mp_bsec_write_otp(dev, *val, i);
709 if (ret)
710 break;
711 }
Patrick Delaunay7e5f8e32019-08-02 13:08:02 +0200712 if (ret)
713 return ret;
714 else
715 return (i - otp) * 4;
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200716}
717
718static const struct misc_ops stm32mp_bsec_ops = {
719 .read = stm32mp_bsec_read,
720 .write = stm32mp_bsec_write,
721};
722
Simon Glassaad29ae2020-12-03 16:55:21 -0700723static int stm32mp_bsec_of_to_plat(struct udevice *dev)
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200724{
Simon Glassb75b15b2020-12-03 16:55:23 -0700725 struct stm32mp_bsec_plat *plat = dev_get_plat(dev);
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200726
727 plat->base = (u32)dev_read_addr_ptr(dev);
728
729 return 0;
730}
731
Patrick Delaunayf95686b2019-02-27 17:01:28 +0100732static int stm32mp_bsec_probe(struct udevice *dev)
733{
734 int otp;
Simon Glassb75b15b2020-12-03 16:55:23 -0700735 struct stm32mp_bsec_plat *plat;
Patrick Delaunayaaf1f962021-02-25 13:43:07 +0100736 struct clk_bulk clk_bulk;
737 int ret;
738
739 ret = clk_get_bulk(dev, &clk_bulk);
740 if (!ret) {
741 ret = clk_enable_bulk(&clk_bulk);
742 if (ret)
743 return ret;
744 }
Patrick Delaunayf95686b2019-02-27 17:01:28 +0100745
Patrick Delaunayd5388292023-01-06 13:20:15 +0100746 if (IS_ENABLED(CONFIG_OPTEE))
747 bsec_optee_open(dev);
748
Patrick Delaunayb6cc5052020-05-25 12:19:41 +0200749 /*
750 * update unlocked shadow for OTP cleared by the rom code
Patrick Delaunaydd2ca252021-10-11 09:52:48 +0200751 * only executed in SPL, it is done in TF-A for TFABOOT
Patrick Delaunayb6cc5052020-05-25 12:19:41 +0200752 */
Patrick Delaunaydd2ca252021-10-11 09:52:48 +0200753 if (IS_ENABLED(CONFIG_SPL_BUILD)) {
Simon Glassfa20e932020-12-03 16:55:20 -0700754 plat = dev_get_plat(dev);
Patrick Delaunay1dffeaf2020-07-31 16:31:51 +0200755
756 for (otp = 57; otp <= BSEC_OTP_MAX_VALUE; otp++)
757 if (!bsec_read_SR_lock(plat->base, otp))
Patrick Delaunayfbefc102020-11-06 19:01:31 +0100758 bsec_shadow_register(dev, plat->base, otp);
Patrick Delaunay1dffeaf2020-07-31 16:31:51 +0200759 }
Patrick Delaunayf95686b2019-02-27 17:01:28 +0100760
761 return 0;
762}
Patrick Delaunayf95686b2019-02-27 17:01:28 +0100763
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200764static const struct udevice_id stm32mp_bsec_ids[] = {
Patrick Delaunay986ec7b2023-01-06 13:20:16 +0100765 { .compatible = "st,stm32mp13-bsec" },
Patrick Delaunaybdd71362019-02-27 17:01:27 +0100766 { .compatible = "st,stm32mp15-bsec" },
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200767 {}
768};
769
770U_BOOT_DRIVER(stm32mp_bsec) = {
771 .name = "stm32mp_bsec",
772 .id = UCLASS_MISC,
773 .of_match = stm32mp_bsec_ids,
Simon Glassaad29ae2020-12-03 16:55:21 -0700774 .of_to_plat = stm32mp_bsec_of_to_plat,
Patrick Delaunay5fa74b82023-01-06 13:20:14 +0100775 .plat_auto = sizeof(struct stm32mp_bsec_plat),
Patrick Delaunayd5388292023-01-06 13:20:15 +0100776 .priv_auto = sizeof(struct stm32mp_bsec_priv),
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200777 .ops = &stm32mp_bsec_ops,
Patrick Delaunayf95686b2019-02-27 17:01:28 +0100778 .probe = stm32mp_bsec_probe,
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200779};
Patrick Delaunay6332c042020-06-16 18:27:44 +0200780
781bool bsec_dbgswenable(void)
782{
783 struct udevice *dev;
Simon Glassb75b15b2020-12-03 16:55:23 -0700784 struct stm32mp_bsec_plat *plat;
Patrick Delaunay6332c042020-06-16 18:27:44 +0200785 int ret;
786
787 ret = uclass_get_device_by_driver(UCLASS_MISC,
Simon Glass65130cd2020-12-28 20:34:56 -0700788 DM_DRIVER_GET(stm32mp_bsec), &dev);
Patrick Delaunay6332c042020-06-16 18:27:44 +0200789 if (ret || !dev) {
Patrick Delaunayfbefc102020-11-06 19:01:31 +0100790 log_debug("bsec driver not available\n");
Patrick Delaunay6332c042020-06-16 18:27:44 +0200791 return false;
792 }
793
Simon Glassfa20e932020-12-03 16:55:20 -0700794 plat = dev_get_plat(dev);
Patrick Delaunay6332c042020-06-16 18:27:44 +0200795 if (readl(plat->base + BSEC_DENABLE_OFF) & BSEC_DENABLE_DBGSWENABLE)
796 return true;
797
798 return false;
799}
Patrick Delaunay9fa24a52022-05-20 18:24:41 +0200800
801u32 get_otp(int index, int shift, int mask)
802{
803 int ret;
804 struct udevice *dev;
805 u32 otp = 0;
806
807 ret = uclass_get_device_by_driver(UCLASS_MISC,
808 DM_DRIVER_GET(stm32mp_bsec),
809 &dev);
810
811 if (!ret)
812 ret = misc_read(dev, STM32_BSEC_SHADOW(index),
813 &otp, sizeof(otp));
814
815 return (otp >> shift) & mask;
816}