blob: 9ba7a6c9a892958280c23c0bd0fa2d853b54ebd9 [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 Delaunayaaf1f962021-02-25 13:43:07 +01008#include <clk.h>
Patrick Delaunay14d6a242018-05-17 15:24:05 +02009#include <dm.h>
Simon Glass0f2af882020-05-10 11:40:05 -060010#include <log.h>
Patrick Delaunay14d6a242018-05-17 15:24:05 +020011#include <misc.h>
Patrick Delaunayd5388292023-01-06 13:20:15 +010012#include <tee.h>
Patrick Delaunay14d6a242018-05-17 15:24:05 +020013#include <asm/io.h>
Patrick Delaunay6332c042020-06-16 18:27:44 +020014#include <asm/arch/bsec.h>
Patrick Delaunay7858d7e2019-02-12 11:44:40 +010015#include <asm/arch/stm32mp1_smc.h>
Patrick Delaunayd5388292023-01-06 13:20:15 +010016#include <dm/device.h>
Patrick Delaunayfbefc102020-11-06 19:01:31 +010017#include <dm/device_compat.h>
Patrick Delaunay7858d7e2019-02-12 11:44:40 +010018#include <linux/arm-smccc.h>
Patrick Delaunay2fa55eb2019-04-18 17:32:39 +020019#include <linux/iopoll.h>
Simon Glassbdd5f812023-09-14 18:21:46 -060020#include <linux/printk.h>
Patrick Delaunay14d6a242018-05-17 15:24:05 +020021
Patrick Delaunayb9201a72022-02-15 16:08:50 +010022#define BSEC_OTP_UPPER_START 32
Patrick Delaunay14d6a242018-05-17 15:24:05 +020023#define BSEC_TIMEOUT_US 10000
24
25/* BSEC REGISTER OFFSET (base relative) */
26#define BSEC_OTP_CONF_OFF 0x000
27#define BSEC_OTP_CTRL_OFF 0x004
28#define BSEC_OTP_WRDATA_OFF 0x008
29#define BSEC_OTP_STATUS_OFF 0x00C
30#define BSEC_OTP_LOCK_OFF 0x010
Patrick Delaunay6332c042020-06-16 18:27:44 +020031#define BSEC_DENABLE_OFF 0x014
Patrick Delaunay14d6a242018-05-17 15:24:05 +020032#define BSEC_DISTURBED_OFF 0x01C
33#define BSEC_ERROR_OFF 0x034
Patrick Delaunayb10cddf2020-02-12 19:37:38 +010034#define BSEC_WRLOCK_OFF 0x04C /* OTP write permananet lock */
35#define BSEC_SPLOCK_OFF 0x064 /* OTP write sticky lock */
36#define BSEC_SWLOCK_OFF 0x07C /* shadow write sticky lock */
37#define BSEC_SRLOCK_OFF 0x094 /* shadow read sticky lock */
Patrick Delaunay14d6a242018-05-17 15:24:05 +020038#define BSEC_OTP_DATA_OFF 0x200
39
40/* BSEC_CONFIGURATION Register MASK */
41#define BSEC_CONF_POWER_UP 0x001
42
43/* BSEC_CONTROL Register */
44#define BSEC_READ 0x000
45#define BSEC_WRITE 0x100
Patrick Delaunayb9201a72022-02-15 16:08:50 +010046#define BSEC_LOCK 0x200
Patrick Delaunay14d6a242018-05-17 15:24:05 +020047
48/* LOCK Register */
49#define OTP_LOCK_MASK 0x1F
50#define OTP_LOCK_BANK_SHIFT 0x05
51#define OTP_LOCK_BIT_MASK 0x01
52
53/* STATUS Register */
54#define BSEC_MODE_BUSY_MASK 0x08
55#define BSEC_MODE_PROGFAIL_MASK 0x10
56#define BSEC_MODE_PWR_MASK 0x20
57
Patrick Delaunay6332c042020-06-16 18:27:44 +020058/* DENABLE Register */
59#define BSEC_DENABLE_DBGSWENABLE BIT(10)
60
Patrick Delaunay14d6a242018-05-17 15:24:05 +020061/*
62 * OTP Lock services definition
63 * Value must corresponding to the bit number in the register
64 */
65#define BSEC_LOCK_PROGRAM 0x04
66
Patrick Delaunayd5388292023-01-06 13:20:15 +010067#define PTA_BSEC_UUID { 0x94cf71ad, 0x80e6, 0x40b5, \
68 { 0xa7, 0xc6, 0x3d, 0xc5, 0x01, 0xeb, 0x28, 0x03 } }
69
70/*
71 * Read OTP memory
72 *
73 * [in] value[0].a OTP start offset in byte
74 * [in] value[0].b Access type (0:shadow, 1:fuse, 2:lock)
75 * [out] memref[1].buffer Output buffer to store read values
76 * [out] memref[1].size Size of OTP to be read
77 *
78 * Return codes:
79 * TEE_SUCCESS - Invoke command success
80 * TEE_ERROR_BAD_PARAMETERS - Incorrect input param
81 * TEE_ERROR_ACCESS_DENIED - OTP not accessible by caller
82 */
83#define PTA_BSEC_READ_MEM 0x0
84
Patrick Delaunayb9201a72022-02-15 16:08:50 +010085/*
Patrick Delaunayd5388292023-01-06 13:20:15 +010086 * Write OTP memory
87 *
88 * [in] value[0].a OTP start offset in byte
89 * [in] value[0].b Access type (0:shadow, 1:fuse, 2:lock)
90 * [in] memref[1].buffer Input buffer to read values
91 * [in] memref[1].size Size of OTP to be written
92 *
93 * Return codes:
94 * TEE_SUCCESS - Invoke command success
95 * TEE_ERROR_BAD_PARAMETERS - Incorrect input param
96 * TEE_ERROR_ACCESS_DENIED - OTP not accessible by caller
Patrick Delaunayb9201a72022-02-15 16:08:50 +010097 */
Patrick Delaunayd5388292023-01-06 13:20:15 +010098#define PTA_BSEC_WRITE_MEM 0x1
99
100/* value of PTA_BSEC access type = value[in] b */
101#define SHADOW_ACCESS 0
102#define FUSE_ACCESS 1
103#define LOCK_ACCESS 2
Patrick Delaunayb9201a72022-02-15 16:08:50 +0100104
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200105/**
Patrick Delaunayb10cddf2020-02-12 19:37:38 +0100106 * bsec_lock() - manage lock for each type SR/SP/SW
107 * @address: address of bsec IP register
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200108 * @otp: otp number (0 - BSEC_OTP_MAX_VALUE)
Patrick Delaunayb10cddf2020-02-12 19:37:38 +0100109 * Return: true if locked else false
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200110 */
Patrice Chotard1115c302023-10-27 16:43:00 +0200111static bool bsec_read_lock(void __iomem *address, u32 otp)
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200112{
113 u32 bit;
114 u32 bank;
115
116 bit = 1 << (otp & OTP_LOCK_MASK);
117 bank = ((otp >> OTP_LOCK_BANK_SHIFT) & OTP_LOCK_MASK) * sizeof(u32);
118
Patrice Chotard1115c302023-10-27 16:43:00 +0200119 return !!(readl((address + bank)) & bit);
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200120}
121
122/**
Patrick Delaunayb10cddf2020-02-12 19:37:38 +0100123 * bsec_check_error() - Check status of one otp
124 * @base: base address of bsec IP
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200125 * @otp: otp number (0 - BSEC_OTP_MAX_VALUE)
Patrick Delaunayb10cddf2020-02-12 19:37:38 +0100126 * Return: 0 if no error, -EAGAIN or -ENOTSUPP
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200127 */
Patrice Chotard1115c302023-10-27 16:43:00 +0200128static u32 bsec_check_error(void __iomem *base, u32 otp)
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200129{
130 u32 bit;
131 u32 bank;
132
133 bit = 1 << (otp & OTP_LOCK_MASK);
134 bank = ((otp >> OTP_LOCK_BANK_SHIFT) & OTP_LOCK_MASK) * sizeof(u32);
135
Patrick Delaunayb10cddf2020-02-12 19:37:38 +0100136 if (readl(base + BSEC_DISTURBED_OFF + bank) & bit)
137 return -EAGAIN;
138 else if (readl(base + BSEC_ERROR_OFF + bank) & bit)
139 return -ENOTSUPP;
140
141 return 0;
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200142}
143
144/**
145 * bsec_read_SR_lock() - read SR lock (Shadowing)
146 * @base: base address of bsec IP
147 * @otp: otp number (0 - BSEC_OTP_MAX_VALUE)
148 * Return: true if locked else false
149 */
Patrice Chotard1115c302023-10-27 16:43:00 +0200150static bool bsec_read_SR_lock(void __iomem *base, u32 otp)
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200151{
152 return bsec_read_lock(base + BSEC_SRLOCK_OFF, otp);
153}
154
155/**
156 * bsec_read_SP_lock() - read SP lock (program Lock)
157 * @base: base address of bsec IP
158 * @otp: otp number (0 - BSEC_OTP_MAX_VALUE)
159 * Return: true if locked else false
160 */
Patrice Chotard1115c302023-10-27 16:43:00 +0200161static bool bsec_read_SP_lock(void __iomem *base, u32 otp)
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200162{
163 return bsec_read_lock(base + BSEC_SPLOCK_OFF, otp);
164}
165
166/**
167 * bsec_SW_lock() - manage SW lock (Write in Shadow)
168 * @base: base address of bsec IP
169 * @otp: otp number (0 - BSEC_OTP_MAX_VALUE)
170 * Return: true if locked else false
171 */
Patrice Chotard1115c302023-10-27 16:43:00 +0200172static bool bsec_read_SW_lock(void __iomem *base, u32 otp)
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200173{
174 return bsec_read_lock(base + BSEC_SWLOCK_OFF, otp);
175}
176
177/**
178 * bsec_power_safmem() - Activate or deactivate safmem power
179 * @base: base address of bsec IP
180 * @power: true to power up , false to power down
181 * Return: 0 if succeed
182 */
Patrice Chotard1115c302023-10-27 16:43:00 +0200183static int bsec_power_safmem(void __iomem *base, bool power)
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200184{
185 u32 val;
186 u32 mask;
187
188 if (power) {
189 setbits_le32(base + BSEC_OTP_CONF_OFF, BSEC_CONF_POWER_UP);
190 mask = BSEC_MODE_PWR_MASK;
191 } else {
192 clrbits_le32(base + BSEC_OTP_CONF_OFF, BSEC_CONF_POWER_UP);
193 mask = 0;
194 }
195
196 /* waiting loop */
197 return readl_poll_timeout(base + BSEC_OTP_STATUS_OFF,
198 val, (val & BSEC_MODE_PWR_MASK) == mask,
199 BSEC_TIMEOUT_US);
200}
201
202/**
203 * bsec_shadow_register() - copy safmen otp to bsec data
Patrick Delaunay6292db12022-02-15 16:08:51 +0100204 * @dev: bsec IP device
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200205 * @base: base address of bsec IP
206 * @otp: otp number (0 - BSEC_OTP_MAX_VALUE)
207 * Return: 0 if no error
208 */
Patrice Chotard1115c302023-10-27 16:43:00 +0200209static int bsec_shadow_register(struct udevice *dev, void __iomem *base, u32 otp)
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200210{
211 u32 val;
212 int ret;
213 bool power_up = false;
214
215 /* check if shadowing of otp is locked */
216 if (bsec_read_SR_lock(base, otp))
Patrick Delaunayfbefc102020-11-06 19:01:31 +0100217 dev_dbg(dev, "OTP %d is locked and refreshed with 0\n",
218 otp);
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200219
220 /* check if safemem is power up */
221 val = readl(base + BSEC_OTP_STATUS_OFF);
222 if (!(val & BSEC_MODE_PWR_MASK)) {
223 ret = bsec_power_safmem(base, true);
224 if (ret)
225 return ret;
Patrick Delaunayf95686b2019-02-27 17:01:28 +0100226 power_up = true;
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200227 }
228 /* set BSEC_OTP_CTRL_OFF with the otp value*/
229 writel(otp | BSEC_READ, base + BSEC_OTP_CTRL_OFF);
230
231 /* check otp status*/
232 ret = readl_poll_timeout(base + BSEC_OTP_STATUS_OFF,
233 val, (val & BSEC_MODE_BUSY_MASK) == 0,
234 BSEC_TIMEOUT_US);
235 if (ret)
236 return ret;
237
238 ret = bsec_check_error(base, otp);
239
240 if (power_up)
241 bsec_power_safmem(base, false);
242
243 return ret;
244}
245
246/**
247 * bsec_read_shadow() - read an otp data value from shadow
Patrick Delaunay6292db12022-02-15 16:08:51 +0100248 * @dev: bsec IP device
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200249 * @base: base address of bsec IP
250 * @val: read value
251 * @otp: otp number (0 - BSEC_OTP_MAX_VALUE)
252 * Return: 0 if no error
253 */
Patrice Chotard1115c302023-10-27 16:43:00 +0200254static int bsec_read_shadow(struct udevice *dev, void __iomem *base, u32 *val,
255 u32 otp)
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200256{
257 *val = readl(base + BSEC_OTP_DATA_OFF + otp * sizeof(u32));
258
259 return bsec_check_error(base, otp);
260}
261
262/**
263 * bsec_write_shadow() - write value in BSEC data register in shadow
Patrick Delaunay6292db12022-02-15 16:08:51 +0100264 * @dev: bsec IP device
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200265 * @base: base address of bsec IP
266 * @val: value to write
267 * @otp: otp number (0 - BSEC_OTP_MAX_VALUE)
268 * Return: 0 if no error
269 */
Patrice Chotard1115c302023-10-27 16:43:00 +0200270static int bsec_write_shadow(struct udevice *dev, void __iomem *base, u32 val, u32 otp)
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200271{
272 /* check if programming of otp is locked */
273 if (bsec_read_SW_lock(base, otp))
Patrick Delaunayfbefc102020-11-06 19:01:31 +0100274 dev_dbg(dev, "OTP %d is lock, write will be ignore\n", otp);
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200275
276 writel(val, base + BSEC_OTP_DATA_OFF + otp * sizeof(u32));
277
278 return bsec_check_error(base, otp);
279}
280
281/**
282 * bsec_program_otp() - program a bit in SAFMEM
Patrick Delaunay6292db12022-02-15 16:08:51 +0100283 * @dev: bsec IP device
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200284 * @base: base address of bsec IP
285 * @val: value to program
286 * @otp: otp number (0 - BSEC_OTP_MAX_VALUE)
287 * after the function the otp data is not refreshed in shadow
288 * Return: 0 if no error
289 */
Patrice Chotard1115c302023-10-27 16:43:00 +0200290static int bsec_program_otp(struct udevice *dev, void __iomem *base, u32 val, u32 otp)
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200291{
292 u32 ret;
293 bool power_up = false;
294
295 if (bsec_read_SP_lock(base, otp))
Patrick Delaunayfbefc102020-11-06 19:01:31 +0100296 dev_dbg(dev, "OTP %d locked, prog will be ignore\n", otp);
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200297
298 if (readl(base + BSEC_OTP_LOCK_OFF) & (1 << BSEC_LOCK_PROGRAM))
Patrick Delaunayfbefc102020-11-06 19:01:31 +0100299 dev_dbg(dev, "Global lock, prog will be ignore\n");
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200300
301 /* check if safemem is power up */
302 if (!(readl(base + BSEC_OTP_STATUS_OFF) & BSEC_MODE_PWR_MASK)) {
303 ret = bsec_power_safmem(base, true);
304 if (ret)
305 return ret;
306
307 power_up = true;
308 }
309 /* set value in write register*/
310 writel(val, base + BSEC_OTP_WRDATA_OFF);
311
312 /* set BSEC_OTP_CTRL_OFF with the otp value */
313 writel(otp | BSEC_WRITE, base + BSEC_OTP_CTRL_OFF);
314
315 /* check otp status*/
316 ret = readl_poll_timeout(base + BSEC_OTP_STATUS_OFF,
317 val, (val & BSEC_MODE_BUSY_MASK) == 0,
318 BSEC_TIMEOUT_US);
319 if (ret)
320 return ret;
321
322 if (val & BSEC_MODE_PROGFAIL_MASK)
323 ret = -EACCES;
324 else
325 ret = bsec_check_error(base, otp);
326
327 if (power_up)
328 bsec_power_safmem(base, false);
329
330 return ret;
331}
332
Patrick Delaunayb9201a72022-02-15 16:08:50 +0100333/**
334 * bsec_permanent_lock_otp() - permanent lock of OTP in SAFMEM
335 * @dev: bsec IP device
336 * @base: base address of bsec IP
337 * @otp: otp number (0 - BSEC_OTP_MAX_VALUE)
338 * Return: 0 if no error
339 */
Patrice Chotard1115c302023-10-27 16:43:00 +0200340static int bsec_permanent_lock_otp(struct udevice *dev, void __iomem *base, uint32_t otp)
Patrick Delaunayb9201a72022-02-15 16:08:50 +0100341{
342 int ret;
343 bool power_up = false;
344 u32 val, addr;
345
346 /* check if safemem is power up */
347 if (!(readl(base + BSEC_OTP_STATUS_OFF) & BSEC_MODE_PWR_MASK)) {
348 ret = bsec_power_safmem(base, true);
349 if (ret)
350 return ret;
351
352 power_up = true;
353 }
354
355 /*
356 * low OTPs = 2 bits word for low OTPs, 1 bits per word for upper OTP
357 * and only 16 bits used in WRDATA
358 */
359 if (otp < BSEC_OTP_UPPER_START) {
360 addr = otp / 8;
361 val = 0x03 << ((otp * 2) & 0xF);
362 } else {
363 addr = BSEC_OTP_UPPER_START / 8 +
364 ((otp - BSEC_OTP_UPPER_START) / 16);
365 val = 0x01 << (otp & 0xF);
366 }
367
368 /* set value in write register*/
369 writel(val, base + BSEC_OTP_WRDATA_OFF);
370
371 /* set BSEC_OTP_CTRL_OFF with the otp addr and lock request*/
372 writel(addr | BSEC_WRITE | BSEC_LOCK, base + BSEC_OTP_CTRL_OFF);
373
374 /* check otp status*/
375 ret = readl_poll_timeout(base + BSEC_OTP_STATUS_OFF,
376 val, (val & BSEC_MODE_BUSY_MASK) == 0,
377 BSEC_TIMEOUT_US);
378 if (ret)
379 return ret;
380
381 if (val & BSEC_MODE_PROGFAIL_MASK)
382 ret = -EACCES;
383 else
384 ret = bsec_check_error(base, otp);
385
386 if (power_up)
387 bsec_power_safmem(base, false);
388
389 return ret;
390}
391
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200392/* BSEC MISC driver *******************************************************/
Simon Glassb75b15b2020-12-03 16:55:23 -0700393struct stm32mp_bsec_plat {
Patrice Chotard1115c302023-10-27 16:43:00 +0200394 void __iomem *base;
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200395};
396
Patrick Delaunayd5388292023-01-06 13:20:15 +0100397struct stm32mp_bsec_priv {
398 struct udevice *tee;
399};
400
Patrick Delaunay9356dbc2024-01-15 15:05:46 +0100401struct stm32mp_bsec_drvdata {
402 int size;
403 bool ta;
404};
405
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200406static int stm32mp_bsec_read_otp(struct udevice *dev, u32 *val, u32 otp)
407{
Simon Glassb75b15b2020-12-03 16:55:23 -0700408 struct stm32mp_bsec_plat *plat;
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200409 u32 tmp_data = 0;
410 int ret;
411
Patrick Delaunay72a57622021-10-11 09:52:50 +0200412 if (IS_ENABLED(CONFIG_ARM_SMCCC) && !IS_ENABLED(CONFIG_SPL_BUILD))
Patrick Delaunay1dffeaf2020-07-31 16:31:51 +0200413 return stm32_smc(STM32_SMC_BSEC,
414 STM32_SMC_READ_OTP,
415 otp, 0, val);
416
Simon Glassfa20e932020-12-03 16:55:20 -0700417 plat = dev_get_plat(dev);
Patrick Delaunay1dffeaf2020-07-31 16:31:51 +0200418
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200419 /* read current shadow value */
Patrick Delaunayfbefc102020-11-06 19:01:31 +0100420 ret = bsec_read_shadow(dev, plat->base, &tmp_data, otp);
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200421 if (ret)
422 return ret;
423
424 /* copy otp in shadow */
Patrick Delaunayfbefc102020-11-06 19:01:31 +0100425 ret = bsec_shadow_register(dev, plat->base, otp);
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200426 if (ret)
427 return ret;
428
Patrick Delaunayfbefc102020-11-06 19:01:31 +0100429 ret = bsec_read_shadow(dev, plat->base, val, otp);
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200430 if (ret)
431 return ret;
432
433 /* restore shadow value */
Patrick Delaunayfbefc102020-11-06 19:01:31 +0100434 ret = bsec_write_shadow(dev, plat->base, tmp_data, otp);
Patrick Delaunay1dffeaf2020-07-31 16:31:51 +0200435
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200436 return ret;
437}
438
439static int stm32mp_bsec_read_shadow(struct udevice *dev, u32 *val, u32 otp)
440{
Simon Glassb75b15b2020-12-03 16:55:23 -0700441 struct stm32mp_bsec_plat *plat;
Patrick Delaunay1dffeaf2020-07-31 16:31:51 +0200442
Patrick Delaunay72a57622021-10-11 09:52:50 +0200443 if (IS_ENABLED(CONFIG_ARM_SMCCC) && !IS_ENABLED(CONFIG_SPL_BUILD))
Patrick Delaunay1dffeaf2020-07-31 16:31:51 +0200444 return stm32_smc(STM32_SMC_BSEC,
445 STM32_SMC_READ_SHADOW,
446 otp, 0, val);
447
Simon Glassfa20e932020-12-03 16:55:20 -0700448 plat = dev_get_plat(dev);
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200449
Patrick Delaunayfbefc102020-11-06 19:01:31 +0100450 return bsec_read_shadow(dev, plat->base, val, otp);
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200451}
452
Patrick Delaunayb10cddf2020-02-12 19:37:38 +0100453static int stm32mp_bsec_read_lock(struct udevice *dev, u32 *val, u32 otp)
454{
Simon Glassb75b15b2020-12-03 16:55:23 -0700455 struct stm32mp_bsec_plat *plat = dev_get_plat(dev);
Patrick Delaunayb9201a72022-02-15 16:08:50 +0100456 u32 wrlock;
Patrick Delaunayb10cddf2020-02-12 19:37:38 +0100457
458 /* return OTP permanent write lock status */
Patrick Delaunayb9201a72022-02-15 16:08:50 +0100459 wrlock = bsec_read_lock(plat->base + BSEC_WRLOCK_OFF, otp);
460
461 *val = 0;
462 if (wrlock)
463 *val = BSEC_LOCK_PERM;
Patrick Delaunayb10cddf2020-02-12 19:37:38 +0100464
465 return 0;
466}
467
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200468static int stm32mp_bsec_write_otp(struct udevice *dev, u32 val, u32 otp)
469{
Simon Glassb75b15b2020-12-03 16:55:23 -0700470 struct stm32mp_bsec_plat *plat;
Patrick Delaunay1dffeaf2020-07-31 16:31:51 +0200471
Patrick Delaunay72a57622021-10-11 09:52:50 +0200472 if (IS_ENABLED(CONFIG_ARM_SMCCC) && !IS_ENABLED(CONFIG_SPL_BUILD))
Patrick Delaunay1dffeaf2020-07-31 16:31:51 +0200473 return stm32_smc_exec(STM32_SMC_BSEC,
474 STM32_SMC_PROG_OTP,
475 otp, val);
476
Simon Glassfa20e932020-12-03 16:55:20 -0700477 plat = dev_get_plat(dev);
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200478
Patrick Delaunayfbefc102020-11-06 19:01:31 +0100479 return bsec_program_otp(dev, plat->base, val, otp);
Patrick Delaunay1dffeaf2020-07-31 16:31:51 +0200480
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200481}
482
483static int stm32mp_bsec_write_shadow(struct udevice *dev, u32 val, u32 otp)
484{
Simon Glassb75b15b2020-12-03 16:55:23 -0700485 struct stm32mp_bsec_plat *plat;
Patrick Delaunay1dffeaf2020-07-31 16:31:51 +0200486
Patrick Delaunay72a57622021-10-11 09:52:50 +0200487 if (IS_ENABLED(CONFIG_ARM_SMCCC) && !IS_ENABLED(CONFIG_SPL_BUILD))
Patrick Delaunay1dffeaf2020-07-31 16:31:51 +0200488 return stm32_smc_exec(STM32_SMC_BSEC,
489 STM32_SMC_WRITE_SHADOW,
490 otp, val);
491
Simon Glassfa20e932020-12-03 16:55:20 -0700492 plat = dev_get_plat(dev);
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200493
Patrick Delaunayfbefc102020-11-06 19:01:31 +0100494 return bsec_write_shadow(dev, plat->base, val, otp);
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200495}
496
Patrick Delaunayb10cddf2020-02-12 19:37:38 +0100497static int stm32mp_bsec_write_lock(struct udevice *dev, u32 val, u32 otp)
498{
Patrick Delaunayb9201a72022-02-15 16:08:50 +0100499 struct stm32mp_bsec_plat *plat;
500
501 /* only permanent write lock is supported in U-Boot */
502 if (!(val & BSEC_LOCK_PERM)) {
503 dev_dbg(dev, "lock option without BSEC_LOCK_PERM: %x\n", val);
504 return 0; /* nothing to do */
505 }
Patrick Delaunay1dffeaf2020-07-31 16:31:51 +0200506
Patrick Delaunayb9201a72022-02-15 16:08:50 +0100507 if (IS_ENABLED(CONFIG_ARM_SMCCC) && !IS_ENABLED(CONFIG_SPL_BUILD))
Patrick Delaunayb10cddf2020-02-12 19:37:38 +0100508 return stm32_smc_exec(STM32_SMC_BSEC,
509 STM32_SMC_WRLOCK_OTP,
510 otp, 0);
Patrick Delaunayb9201a72022-02-15 16:08:50 +0100511
512 plat = dev_get_plat(dev);
513
514 return bsec_permanent_lock_otp(dev, plat->base, otp);
Patrick Delaunayb10cddf2020-02-12 19:37:38 +0100515}
516
Patrick Delaunayd5388292023-01-06 13:20:15 +0100517static int bsec_pta_open_session(struct udevice *tee, u32 *tee_session)
518{
519 const struct tee_optee_ta_uuid uuid = PTA_BSEC_UUID;
520 struct tee_open_session_arg arg;
521 int rc;
522
523 memset(&arg, 0, sizeof(arg));
524 tee_optee_ta_uuid_to_octets(arg.uuid, &uuid);
525 arg.clnt_login = TEE_LOGIN_REE_KERNEL;
526 rc = tee_open_session(tee, &arg, 0, NULL);
527 if (rc < 0)
528 return -ENODEV;
529
530 *tee_session = arg.session;
531
532 return 0;
533}
534
535static int bsec_optee_open(struct udevice *dev)
536{
537 struct stm32mp_bsec_priv *priv = dev_get_priv(dev);
538 struct udevice *tee;
539 u32 tee_session;
540 int rc;
541
542 tee = tee_find_device(NULL, NULL, NULL, NULL);
543 if (!tee)
544 return -ENODEV;
545
546 /* try to open the STM32 BSEC TA */
547 rc = bsec_pta_open_session(tee, &tee_session);
548 if (rc)
549 return rc;
550
551 tee_close_session(tee, tee_session);
552
553 priv->tee = tee;
554
555 return 0;
556}
557
558static int bsec_optee_pta(struct udevice *dev, int cmd, int type, int offset,
559 void *buff, ulong size)
560{
561 struct stm32mp_bsec_priv *priv = dev_get_priv(dev);
562 u32 tee_session;
563 struct tee_invoke_arg arg;
564 struct tee_param param[2];
565 struct tee_shm *fw_shm;
566 int rc;
567
568 rc = bsec_pta_open_session(priv->tee, &tee_session);
569 if (rc)
570 return rc;
571
572 rc = tee_shm_register(priv->tee, buff, size, 0, &fw_shm);
573 if (rc)
574 goto close_session;
575
576 memset(&arg, 0, sizeof(arg));
577 arg.func = cmd;
578 arg.session = tee_session;
579
580 memset(param, 0, sizeof(param));
581
582 param[0].attr = TEE_PARAM_ATTR_TYPE_VALUE_INPUT;
583 param[0].u.value.a = offset;
584 param[0].u.value.b = type;
585
586 if (cmd == PTA_BSEC_WRITE_MEM)
587 param[1].attr = TEE_PARAM_ATTR_TYPE_MEMREF_INPUT;
588 else
589 param[1].attr = TEE_PARAM_ATTR_TYPE_MEMREF_OUTPUT;
590
591 param[1].u.memref.shm = fw_shm;
592 param[1].u.memref.size = size;
593
594 rc = tee_invoke_func(priv->tee, &arg, 2, param);
595 if (rc < 0 || arg.ret != 0) {
596 dev_err(priv->tee,
597 "PTA_BSEC invoke failed TEE err: %x, err:%x\n",
598 arg.ret, rc);
599 if (!rc)
600 rc = -EIO;
601 }
602
603 tee_shm_free(fw_shm);
604
605close_session:
606 tee_close_session(priv->tee, tee_session);
607
608 return rc;
609}
610
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200611static int stm32mp_bsec_read(struct udevice *dev, int offset,
612 void *buf, int size)
613{
Patrick Delaunayd5388292023-01-06 13:20:15 +0100614 struct stm32mp_bsec_priv *priv = dev_get_priv(dev);
Patrick Delaunay9356dbc2024-01-15 15:05:46 +0100615 struct stm32mp_bsec_drvdata *data = (struct stm32mp_bsec_drvdata *)dev_get_driver_data(dev);
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200616 int ret;
617 int i;
Patrick Delaunayb10cddf2020-02-12 19:37:38 +0100618 bool shadow = true, lock = false;
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200619 int nb_otp = size / sizeof(u32);
Patrick Delaunayd5388292023-01-06 13:20:15 +0100620 int otp, cmd;
Patrick Delaunay4c7c0742019-06-21 15:26:43 +0200621 unsigned int offs = offset;
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200622
Patrick Delaunayb10cddf2020-02-12 19:37:38 +0100623 if (offs >= STM32_BSEC_LOCK_OFFSET) {
624 offs -= STM32_BSEC_LOCK_OFFSET;
625 lock = true;
626 } else if (offs >= STM32_BSEC_OTP_OFFSET) {
Patrick Delaunay4c7c0742019-06-21 15:26:43 +0200627 offs -= STM32_BSEC_OTP_OFFSET;
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200628 shadow = false;
629 }
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200630
Patrick Delaunay8275ff32023-04-27 15:36:34 +0200631 if ((offs % 4) || (size % 4) || !size)
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200632 return -EINVAL;
Patrick Delaunay7e5f8e32019-08-02 13:08:02 +0200633
Patrick Delaunayd5388292023-01-06 13:20:15 +0100634 if (IS_ENABLED(CONFIG_OPTEE) && priv->tee) {
635 cmd = FUSE_ACCESS;
636 if (shadow)
637 cmd = SHADOW_ACCESS;
638 if (lock)
639 cmd = LOCK_ACCESS;
640 ret = bsec_optee_pta(dev, PTA_BSEC_READ_MEM, cmd, offs, buf, size);
641 if (ret)
642 return ret;
643
644 return size;
645 }
646
Patrick Delaunay7e5f8e32019-08-02 13:08:02 +0200647 otp = offs / sizeof(u32);
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200648
Patrick Delaunay9356dbc2024-01-15 15:05:46 +0100649 for (i = otp; i < (otp + nb_otp) && i < data->size; i++) {
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200650 u32 *addr = &((u32 *)buf)[i - otp];
651
Patrick Delaunayb10cddf2020-02-12 19:37:38 +0100652 if (lock)
653 ret = stm32mp_bsec_read_lock(dev, addr, i);
654 else if (shadow)
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200655 ret = stm32mp_bsec_read_shadow(dev, addr, i);
656 else
657 ret = stm32mp_bsec_read_otp(dev, addr, i);
658
659 if (ret)
660 break;
661 }
Patrick Delaunay7e5f8e32019-08-02 13:08:02 +0200662 if (ret)
663 return ret;
664 else
665 return (i - otp) * 4;
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200666}
667
668static int stm32mp_bsec_write(struct udevice *dev, int offset,
669 const void *buf, int size)
670{
Patrick Delaunayd5388292023-01-06 13:20:15 +0100671 struct stm32mp_bsec_priv *priv = dev_get_priv(dev);
Patrick Delaunay9356dbc2024-01-15 15:05:46 +0100672 struct stm32mp_bsec_drvdata *data = (struct stm32mp_bsec_drvdata *)dev_get_driver_data(dev);
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200673 int ret = 0;
674 int i;
Patrick Delaunayb10cddf2020-02-12 19:37:38 +0100675 bool shadow = true, lock = false;
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200676 int nb_otp = size / sizeof(u32);
Patrick Delaunayd5388292023-01-06 13:20:15 +0100677 int otp, cmd;
Patrick Delaunay4c7c0742019-06-21 15:26:43 +0200678 unsigned int offs = offset;
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200679
Patrick Delaunayb10cddf2020-02-12 19:37:38 +0100680 if (offs >= STM32_BSEC_LOCK_OFFSET) {
681 offs -= STM32_BSEC_LOCK_OFFSET;
682 lock = true;
683 } else if (offs >= STM32_BSEC_OTP_OFFSET) {
Patrick Delaunay4c7c0742019-06-21 15:26:43 +0200684 offs -= STM32_BSEC_OTP_OFFSET;
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200685 shadow = false;
686 }
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200687
Patrick Delaunay8275ff32023-04-27 15:36:34 +0200688 if ((offs % 4) || (size % 4) || !size)
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200689 return -EINVAL;
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200690
Patrick Delaunayd5388292023-01-06 13:20:15 +0100691 if (IS_ENABLED(CONFIG_OPTEE) && priv->tee) {
692 cmd = FUSE_ACCESS;
693 if (shadow)
694 cmd = SHADOW_ACCESS;
695 if (lock)
696 cmd = LOCK_ACCESS;
697 ret = bsec_optee_pta(dev, PTA_BSEC_WRITE_MEM, cmd, offs, (void *)buf, size);
698 if (ret)
699 return ret;
700
701 return size;
702 }
703
Patrick Delaunay7e5f8e32019-08-02 13:08:02 +0200704 otp = offs / sizeof(u32);
705
Patrick Delaunay9356dbc2024-01-15 15:05:46 +0100706 for (i = otp; i < otp + nb_otp && i < data->size; i++) {
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200707 u32 *val = &((u32 *)buf)[i - otp];
708
Patrick Delaunayb10cddf2020-02-12 19:37:38 +0100709 if (lock)
710 ret = stm32mp_bsec_write_lock(dev, *val, i);
711 else if (shadow)
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200712 ret = stm32mp_bsec_write_shadow(dev, *val, i);
713 else
714 ret = stm32mp_bsec_write_otp(dev, *val, i);
715 if (ret)
716 break;
717 }
Patrick Delaunay7e5f8e32019-08-02 13:08:02 +0200718 if (ret)
719 return ret;
720 else
721 return (i - otp) * 4;
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200722}
723
724static const struct misc_ops stm32mp_bsec_ops = {
725 .read = stm32mp_bsec_read,
726 .write = stm32mp_bsec_write,
727};
728
Simon Glassaad29ae2020-12-03 16:55:21 -0700729static int stm32mp_bsec_of_to_plat(struct udevice *dev)
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200730{
Simon Glassb75b15b2020-12-03 16:55:23 -0700731 struct stm32mp_bsec_plat *plat = dev_get_plat(dev);
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200732
Patrice Chotard1115c302023-10-27 16:43:00 +0200733 plat->base = dev_read_addr_ptr(dev);
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200734
735 return 0;
736}
737
Patrick Delaunayf95686b2019-02-27 17:01:28 +0100738static int stm32mp_bsec_probe(struct udevice *dev)
739{
Patrick Delaunay9356dbc2024-01-15 15:05:46 +0100740 struct stm32mp_bsec_drvdata *data = (struct stm32mp_bsec_drvdata *)dev_get_driver_data(dev);
Patrick Delaunayf95686b2019-02-27 17:01:28 +0100741 int otp;
Simon Glassb75b15b2020-12-03 16:55:23 -0700742 struct stm32mp_bsec_plat *plat;
Patrick Delaunayaaf1f962021-02-25 13:43:07 +0100743 struct clk_bulk clk_bulk;
744 int ret;
745
746 ret = clk_get_bulk(dev, &clk_bulk);
747 if (!ret) {
748 ret = clk_enable_bulk(&clk_bulk);
749 if (ret)
750 return ret;
751 }
Patrick Delaunayf95686b2019-02-27 17:01:28 +0100752
Patrick Delaunayd5388292023-01-06 13:20:15 +0100753 if (IS_ENABLED(CONFIG_OPTEE))
Patrick Delaunay9356dbc2024-01-15 15:05:46 +0100754 ret = bsec_optee_open(dev);
755 else
756 ret = -ENOTSUPP;
757 /* failed if OP-TEE TA is required */
758 if (data->ta && !ret)
759 return ret;
Patrick Delaunayd5388292023-01-06 13:20:15 +0100760
Patrick Delaunayb6cc5052020-05-25 12:19:41 +0200761 /*
762 * update unlocked shadow for OTP cleared by the rom code
Patrick Delaunaydd2ca252021-10-11 09:52:48 +0200763 * only executed in SPL, it is done in TF-A for TFABOOT
Patrick Delaunayb6cc5052020-05-25 12:19:41 +0200764 */
Patrick Delaunay9356dbc2024-01-15 15:05:46 +0100765 if (IS_ENABLED(CONFIG_SPL_BUILD) && !data->ta) {
Simon Glassfa20e932020-12-03 16:55:20 -0700766 plat = dev_get_plat(dev);
Patrick Delaunay1dffeaf2020-07-31 16:31:51 +0200767
Patrick Delaunay9356dbc2024-01-15 15:05:46 +0100768 /* here 57 is the value for STM32MP15x ROM code, only MPU with SPL support*/
769 for (otp = 57; otp < data->size; otp++)
Patrick Delaunay1dffeaf2020-07-31 16:31:51 +0200770 if (!bsec_read_SR_lock(plat->base, otp))
Patrick Delaunayfbefc102020-11-06 19:01:31 +0100771 bsec_shadow_register(dev, plat->base, otp);
Patrick Delaunay1dffeaf2020-07-31 16:31:51 +0200772 }
Patrick Delaunayf95686b2019-02-27 17:01:28 +0100773
774 return 0;
775}
Patrick Delaunayf95686b2019-02-27 17:01:28 +0100776
Patrick Delaunay9356dbc2024-01-15 15:05:46 +0100777static const struct stm32mp_bsec_drvdata stm32mp13_data = {
778 .size = 96,
779 .ta = true,
780};
781
782static const struct stm32mp_bsec_drvdata stm32mp15_data = {
783 .size = 96,
784 .ta = false,
785};
Patrick Delaunaydb9d93c2024-01-15 15:05:47 +0100786
787static const struct stm32mp_bsec_drvdata stm32mp25_data = {
788 .size = 368, /* 384 but no access to HWKEY and STM32PRVKEY */
789 .ta = true,
790};
791
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200792static const struct udevice_id stm32mp_bsec_ids[] = {
Patrick Delaunay9356dbc2024-01-15 15:05:46 +0100793 { .compatible = "st,stm32mp13-bsec", .data = (ulong)&stm32mp13_data},
794 { .compatible = "st,stm32mp15-bsec", .data = (ulong)&stm32mp15_data},
Patrick Delaunaydb9d93c2024-01-15 15:05:47 +0100795 { .compatible = "st,stm32mp25-bsec", .data = (ulong)&stm32mp25_data},
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200796 {}
797};
798
799U_BOOT_DRIVER(stm32mp_bsec) = {
800 .name = "stm32mp_bsec",
801 .id = UCLASS_MISC,
802 .of_match = stm32mp_bsec_ids,
Simon Glassaad29ae2020-12-03 16:55:21 -0700803 .of_to_plat = stm32mp_bsec_of_to_plat,
Patrick Delaunay5fa74b82023-01-06 13:20:14 +0100804 .plat_auto = sizeof(struct stm32mp_bsec_plat),
Patrick Delaunayd5388292023-01-06 13:20:15 +0100805 .priv_auto = sizeof(struct stm32mp_bsec_priv),
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200806 .ops = &stm32mp_bsec_ops,
Patrick Delaunayf95686b2019-02-27 17:01:28 +0100807 .probe = stm32mp_bsec_probe,
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200808};
Patrick Delaunay6332c042020-06-16 18:27:44 +0200809
810bool bsec_dbgswenable(void)
811{
812 struct udevice *dev;
Simon Glassb75b15b2020-12-03 16:55:23 -0700813 struct stm32mp_bsec_plat *plat;
Patrick Delaunay6332c042020-06-16 18:27:44 +0200814 int ret;
815
816 ret = uclass_get_device_by_driver(UCLASS_MISC,
Simon Glass65130cd2020-12-28 20:34:56 -0700817 DM_DRIVER_GET(stm32mp_bsec), &dev);
Patrick Delaunay6332c042020-06-16 18:27:44 +0200818 if (ret || !dev) {
Patrick Delaunayfbefc102020-11-06 19:01:31 +0100819 log_debug("bsec driver not available\n");
Patrick Delaunay6332c042020-06-16 18:27:44 +0200820 return false;
821 }
822
Simon Glassfa20e932020-12-03 16:55:20 -0700823 plat = dev_get_plat(dev);
Patrick Delaunay6332c042020-06-16 18:27:44 +0200824 if (readl(plat->base + BSEC_DENABLE_OFF) & BSEC_DENABLE_DBGSWENABLE)
825 return true;
826
827 return false;
828}
Patrick Delaunay9fa24a52022-05-20 18:24:41 +0200829
830u32 get_otp(int index, int shift, int mask)
831{
832 int ret;
833 struct udevice *dev;
834 u32 otp = 0;
835
836 ret = uclass_get_device_by_driver(UCLASS_MISC,
837 DM_DRIVER_GET(stm32mp_bsec),
838 &dev);
839
840 if (!ret)
841 ret = misc_read(dev, STM32_BSEC_SHADOW(index),
842 &otp, sizeof(otp));
843
844 return (otp >> shift) & mask;
845}