blob: 28a8280b2804ccb5f70b9fd0ec77b8131310f828 [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 */
Patrice Chotard1115c302023-10-27 16:43:00 +0200113static bool bsec_read_lock(void __iomem *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
Patrice Chotard1115c302023-10-27 16:43:00 +0200121 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 */
Patrice Chotard1115c302023-10-27 16:43:00 +0200130static u32 bsec_check_error(void __iomem *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 */
Patrice Chotard1115c302023-10-27 16:43:00 +0200152static bool bsec_read_SR_lock(void __iomem *base, u32 otp)
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200153{
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 */
Patrice Chotard1115c302023-10-27 16:43:00 +0200163static bool bsec_read_SP_lock(void __iomem *base, u32 otp)
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200164{
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 */
Patrice Chotard1115c302023-10-27 16:43:00 +0200174static bool bsec_read_SW_lock(void __iomem *base, u32 otp)
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200175{
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 */
Patrice Chotard1115c302023-10-27 16:43:00 +0200185static int bsec_power_safmem(void __iomem *base, bool power)
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200186{
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 */
Patrice Chotard1115c302023-10-27 16:43:00 +0200211static int bsec_shadow_register(struct udevice *dev, void __iomem *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 */
Patrice Chotard1115c302023-10-27 16:43:00 +0200256static int bsec_read_shadow(struct udevice *dev, void __iomem *base, u32 *val,
257 u32 otp)
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200258{
259 *val = readl(base + BSEC_OTP_DATA_OFF + otp * sizeof(u32));
260
261 return bsec_check_error(base, otp);
262}
263
264/**
265 * bsec_write_shadow() - write value in BSEC data register in shadow
Patrick Delaunay6292db12022-02-15 16:08:51 +0100266 * @dev: bsec IP device
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200267 * @base: base address of bsec IP
268 * @val: value to write
269 * @otp: otp number (0 - BSEC_OTP_MAX_VALUE)
270 * Return: 0 if no error
271 */
Patrice Chotard1115c302023-10-27 16:43:00 +0200272static int bsec_write_shadow(struct udevice *dev, void __iomem *base, u32 val, u32 otp)
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200273{
274 /* check if programming of otp is locked */
275 if (bsec_read_SW_lock(base, otp))
Patrick Delaunayfbefc102020-11-06 19:01:31 +0100276 dev_dbg(dev, "OTP %d is lock, write will be ignore\n", otp);
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200277
278 writel(val, base + BSEC_OTP_DATA_OFF + otp * sizeof(u32));
279
280 return bsec_check_error(base, otp);
281}
282
283/**
284 * bsec_program_otp() - program a bit in SAFMEM
Patrick Delaunay6292db12022-02-15 16:08:51 +0100285 * @dev: bsec IP device
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200286 * @base: base address of bsec IP
287 * @val: value to program
288 * @otp: otp number (0 - BSEC_OTP_MAX_VALUE)
289 * after the function the otp data is not refreshed in shadow
290 * Return: 0 if no error
291 */
Patrice Chotard1115c302023-10-27 16:43:00 +0200292static int bsec_program_otp(struct udevice *dev, void __iomem *base, u32 val, u32 otp)
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200293{
294 u32 ret;
295 bool power_up = false;
296
297 if (bsec_read_SP_lock(base, otp))
Patrick Delaunayfbefc102020-11-06 19:01:31 +0100298 dev_dbg(dev, "OTP %d locked, prog will be ignore\n", otp);
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200299
300 if (readl(base + BSEC_OTP_LOCK_OFF) & (1 << BSEC_LOCK_PROGRAM))
Patrick Delaunayfbefc102020-11-06 19:01:31 +0100301 dev_dbg(dev, "Global lock, prog will be ignore\n");
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200302
303 /* check if safemem is power up */
304 if (!(readl(base + BSEC_OTP_STATUS_OFF) & BSEC_MODE_PWR_MASK)) {
305 ret = bsec_power_safmem(base, true);
306 if (ret)
307 return ret;
308
309 power_up = true;
310 }
311 /* set value in write register*/
312 writel(val, base + BSEC_OTP_WRDATA_OFF);
313
314 /* set BSEC_OTP_CTRL_OFF with the otp value */
315 writel(otp | BSEC_WRITE, base + BSEC_OTP_CTRL_OFF);
316
317 /* check otp status*/
318 ret = readl_poll_timeout(base + BSEC_OTP_STATUS_OFF,
319 val, (val & BSEC_MODE_BUSY_MASK) == 0,
320 BSEC_TIMEOUT_US);
321 if (ret)
322 return ret;
323
324 if (val & BSEC_MODE_PROGFAIL_MASK)
325 ret = -EACCES;
326 else
327 ret = bsec_check_error(base, otp);
328
329 if (power_up)
330 bsec_power_safmem(base, false);
331
332 return ret;
333}
334
Patrick Delaunayb9201a72022-02-15 16:08:50 +0100335/**
336 * bsec_permanent_lock_otp() - permanent lock of OTP in SAFMEM
337 * @dev: bsec IP device
338 * @base: base address of bsec IP
339 * @otp: otp number (0 - BSEC_OTP_MAX_VALUE)
340 * Return: 0 if no error
341 */
Patrice Chotard1115c302023-10-27 16:43:00 +0200342static int bsec_permanent_lock_otp(struct udevice *dev, void __iomem *base, uint32_t otp)
Patrick Delaunayb9201a72022-02-15 16:08:50 +0100343{
344 int ret;
345 bool power_up = false;
346 u32 val, addr;
347
348 /* check if safemem is power up */
349 if (!(readl(base + BSEC_OTP_STATUS_OFF) & BSEC_MODE_PWR_MASK)) {
350 ret = bsec_power_safmem(base, true);
351 if (ret)
352 return ret;
353
354 power_up = true;
355 }
356
357 /*
358 * low OTPs = 2 bits word for low OTPs, 1 bits per word for upper OTP
359 * and only 16 bits used in WRDATA
360 */
361 if (otp < BSEC_OTP_UPPER_START) {
362 addr = otp / 8;
363 val = 0x03 << ((otp * 2) & 0xF);
364 } else {
365 addr = BSEC_OTP_UPPER_START / 8 +
366 ((otp - BSEC_OTP_UPPER_START) / 16);
367 val = 0x01 << (otp & 0xF);
368 }
369
370 /* set value in write register*/
371 writel(val, base + BSEC_OTP_WRDATA_OFF);
372
373 /* set BSEC_OTP_CTRL_OFF with the otp addr and lock request*/
374 writel(addr | BSEC_WRITE | BSEC_LOCK, base + BSEC_OTP_CTRL_OFF);
375
376 /* check otp status*/
377 ret = readl_poll_timeout(base + BSEC_OTP_STATUS_OFF,
378 val, (val & BSEC_MODE_BUSY_MASK) == 0,
379 BSEC_TIMEOUT_US);
380 if (ret)
381 return ret;
382
383 if (val & BSEC_MODE_PROGFAIL_MASK)
384 ret = -EACCES;
385 else
386 ret = bsec_check_error(base, otp);
387
388 if (power_up)
389 bsec_power_safmem(base, false);
390
391 return ret;
392}
393
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200394/* BSEC MISC driver *******************************************************/
Simon Glassb75b15b2020-12-03 16:55:23 -0700395struct stm32mp_bsec_plat {
Patrice Chotard1115c302023-10-27 16:43:00 +0200396 void __iomem *base;
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200397};
398
Patrick Delaunayd5388292023-01-06 13:20:15 +0100399struct stm32mp_bsec_priv {
400 struct udevice *tee;
401};
402
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200403static int stm32mp_bsec_read_otp(struct udevice *dev, u32 *val, u32 otp)
404{
Simon Glassb75b15b2020-12-03 16:55:23 -0700405 struct stm32mp_bsec_plat *plat;
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200406 u32 tmp_data = 0;
407 int ret;
408
Patrick Delaunay72a57622021-10-11 09:52:50 +0200409 if (IS_ENABLED(CONFIG_ARM_SMCCC) && !IS_ENABLED(CONFIG_SPL_BUILD))
Patrick Delaunay1dffeaf2020-07-31 16:31:51 +0200410 return stm32_smc(STM32_SMC_BSEC,
411 STM32_SMC_READ_OTP,
412 otp, 0, val);
413
Simon Glassfa20e932020-12-03 16:55:20 -0700414 plat = dev_get_plat(dev);
Patrick Delaunay1dffeaf2020-07-31 16:31:51 +0200415
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200416 /* read current shadow value */
Patrick Delaunayfbefc102020-11-06 19:01:31 +0100417 ret = bsec_read_shadow(dev, plat->base, &tmp_data, otp);
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200418 if (ret)
419 return ret;
420
421 /* copy otp in shadow */
Patrick Delaunayfbefc102020-11-06 19:01:31 +0100422 ret = bsec_shadow_register(dev, plat->base, otp);
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200423 if (ret)
424 return ret;
425
Patrick Delaunayfbefc102020-11-06 19:01:31 +0100426 ret = bsec_read_shadow(dev, plat->base, val, otp);
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200427 if (ret)
428 return ret;
429
430 /* restore shadow value */
Patrick Delaunayfbefc102020-11-06 19:01:31 +0100431 ret = bsec_write_shadow(dev, plat->base, tmp_data, otp);
Patrick Delaunay1dffeaf2020-07-31 16:31:51 +0200432
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200433 return ret;
434}
435
436static int stm32mp_bsec_read_shadow(struct udevice *dev, u32 *val, u32 otp)
437{
Simon Glassb75b15b2020-12-03 16:55:23 -0700438 struct stm32mp_bsec_plat *plat;
Patrick Delaunay1dffeaf2020-07-31 16:31:51 +0200439
Patrick Delaunay72a57622021-10-11 09:52:50 +0200440 if (IS_ENABLED(CONFIG_ARM_SMCCC) && !IS_ENABLED(CONFIG_SPL_BUILD))
Patrick Delaunay1dffeaf2020-07-31 16:31:51 +0200441 return stm32_smc(STM32_SMC_BSEC,
442 STM32_SMC_READ_SHADOW,
443 otp, 0, val);
444
Simon Glassfa20e932020-12-03 16:55:20 -0700445 plat = dev_get_plat(dev);
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200446
Patrick Delaunayfbefc102020-11-06 19:01:31 +0100447 return bsec_read_shadow(dev, plat->base, val, otp);
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200448}
449
Patrick Delaunayb10cddf2020-02-12 19:37:38 +0100450static int stm32mp_bsec_read_lock(struct udevice *dev, u32 *val, u32 otp)
451{
Simon Glassb75b15b2020-12-03 16:55:23 -0700452 struct stm32mp_bsec_plat *plat = dev_get_plat(dev);
Patrick Delaunayb9201a72022-02-15 16:08:50 +0100453 u32 wrlock;
Patrick Delaunayb10cddf2020-02-12 19:37:38 +0100454
455 /* return OTP permanent write lock status */
Patrick Delaunayb9201a72022-02-15 16:08:50 +0100456 wrlock = bsec_read_lock(plat->base + BSEC_WRLOCK_OFF, otp);
457
458 *val = 0;
459 if (wrlock)
460 *val = BSEC_LOCK_PERM;
Patrick Delaunayb10cddf2020-02-12 19:37:38 +0100461
462 return 0;
463}
464
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200465static int stm32mp_bsec_write_otp(struct udevice *dev, u32 val, u32 otp)
466{
Simon Glassb75b15b2020-12-03 16:55:23 -0700467 struct stm32mp_bsec_plat *plat;
Patrick Delaunay1dffeaf2020-07-31 16:31:51 +0200468
Patrick Delaunay72a57622021-10-11 09:52:50 +0200469 if (IS_ENABLED(CONFIG_ARM_SMCCC) && !IS_ENABLED(CONFIG_SPL_BUILD))
Patrick Delaunay1dffeaf2020-07-31 16:31:51 +0200470 return stm32_smc_exec(STM32_SMC_BSEC,
471 STM32_SMC_PROG_OTP,
472 otp, val);
473
Simon Glassfa20e932020-12-03 16:55:20 -0700474 plat = dev_get_plat(dev);
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200475
Patrick Delaunayfbefc102020-11-06 19:01:31 +0100476 return bsec_program_otp(dev, plat->base, val, otp);
Patrick Delaunay1dffeaf2020-07-31 16:31:51 +0200477
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200478}
479
480static int stm32mp_bsec_write_shadow(struct udevice *dev, u32 val, u32 otp)
481{
Simon Glassb75b15b2020-12-03 16:55:23 -0700482 struct stm32mp_bsec_plat *plat;
Patrick Delaunay1dffeaf2020-07-31 16:31:51 +0200483
Patrick Delaunay72a57622021-10-11 09:52:50 +0200484 if (IS_ENABLED(CONFIG_ARM_SMCCC) && !IS_ENABLED(CONFIG_SPL_BUILD))
Patrick Delaunay1dffeaf2020-07-31 16:31:51 +0200485 return stm32_smc_exec(STM32_SMC_BSEC,
486 STM32_SMC_WRITE_SHADOW,
487 otp, val);
488
Simon Glassfa20e932020-12-03 16:55:20 -0700489 plat = dev_get_plat(dev);
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200490
Patrick Delaunayfbefc102020-11-06 19:01:31 +0100491 return bsec_write_shadow(dev, plat->base, val, otp);
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200492}
493
Patrick Delaunayb10cddf2020-02-12 19:37:38 +0100494static int stm32mp_bsec_write_lock(struct udevice *dev, u32 val, u32 otp)
495{
Patrick Delaunayb9201a72022-02-15 16:08:50 +0100496 struct stm32mp_bsec_plat *plat;
497
498 /* only permanent write lock is supported in U-Boot */
499 if (!(val & BSEC_LOCK_PERM)) {
500 dev_dbg(dev, "lock option without BSEC_LOCK_PERM: %x\n", val);
501 return 0; /* nothing to do */
502 }
Patrick Delaunay1dffeaf2020-07-31 16:31:51 +0200503
Patrick Delaunayb9201a72022-02-15 16:08:50 +0100504 if (IS_ENABLED(CONFIG_ARM_SMCCC) && !IS_ENABLED(CONFIG_SPL_BUILD))
Patrick Delaunayb10cddf2020-02-12 19:37:38 +0100505 return stm32_smc_exec(STM32_SMC_BSEC,
506 STM32_SMC_WRLOCK_OTP,
507 otp, 0);
Patrick Delaunayb9201a72022-02-15 16:08:50 +0100508
509 plat = dev_get_plat(dev);
510
511 return bsec_permanent_lock_otp(dev, plat->base, otp);
Patrick Delaunayb10cddf2020-02-12 19:37:38 +0100512}
513
Patrick Delaunayd5388292023-01-06 13:20:15 +0100514static int bsec_pta_open_session(struct udevice *tee, u32 *tee_session)
515{
516 const struct tee_optee_ta_uuid uuid = PTA_BSEC_UUID;
517 struct tee_open_session_arg arg;
518 int rc;
519
520 memset(&arg, 0, sizeof(arg));
521 tee_optee_ta_uuid_to_octets(arg.uuid, &uuid);
522 arg.clnt_login = TEE_LOGIN_REE_KERNEL;
523 rc = tee_open_session(tee, &arg, 0, NULL);
524 if (rc < 0)
525 return -ENODEV;
526
527 *tee_session = arg.session;
528
529 return 0;
530}
531
532static int bsec_optee_open(struct udevice *dev)
533{
534 struct stm32mp_bsec_priv *priv = dev_get_priv(dev);
535 struct udevice *tee;
536 u32 tee_session;
537 int rc;
538
539 tee = tee_find_device(NULL, NULL, NULL, NULL);
540 if (!tee)
541 return -ENODEV;
542
543 /* try to open the STM32 BSEC TA */
544 rc = bsec_pta_open_session(tee, &tee_session);
545 if (rc)
546 return rc;
547
548 tee_close_session(tee, tee_session);
549
550 priv->tee = tee;
551
552 return 0;
553}
554
555static int bsec_optee_pta(struct udevice *dev, int cmd, int type, int offset,
556 void *buff, ulong size)
557{
558 struct stm32mp_bsec_priv *priv = dev_get_priv(dev);
559 u32 tee_session;
560 struct tee_invoke_arg arg;
561 struct tee_param param[2];
562 struct tee_shm *fw_shm;
563 int rc;
564
565 rc = bsec_pta_open_session(priv->tee, &tee_session);
566 if (rc)
567 return rc;
568
569 rc = tee_shm_register(priv->tee, buff, size, 0, &fw_shm);
570 if (rc)
571 goto close_session;
572
573 memset(&arg, 0, sizeof(arg));
574 arg.func = cmd;
575 arg.session = tee_session;
576
577 memset(param, 0, sizeof(param));
578
579 param[0].attr = TEE_PARAM_ATTR_TYPE_VALUE_INPUT;
580 param[0].u.value.a = offset;
581 param[0].u.value.b = type;
582
583 if (cmd == PTA_BSEC_WRITE_MEM)
584 param[1].attr = TEE_PARAM_ATTR_TYPE_MEMREF_INPUT;
585 else
586 param[1].attr = TEE_PARAM_ATTR_TYPE_MEMREF_OUTPUT;
587
588 param[1].u.memref.shm = fw_shm;
589 param[1].u.memref.size = size;
590
591 rc = tee_invoke_func(priv->tee, &arg, 2, param);
592 if (rc < 0 || arg.ret != 0) {
593 dev_err(priv->tee,
594 "PTA_BSEC invoke failed TEE err: %x, err:%x\n",
595 arg.ret, rc);
596 if (!rc)
597 rc = -EIO;
598 }
599
600 tee_shm_free(fw_shm);
601
602close_session:
603 tee_close_session(priv->tee, tee_session);
604
605 return rc;
606}
607
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200608static int stm32mp_bsec_read(struct udevice *dev, int offset,
609 void *buf, int size)
610{
Patrick Delaunayd5388292023-01-06 13:20:15 +0100611 struct stm32mp_bsec_priv *priv = dev_get_priv(dev);
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200612 int ret;
613 int i;
Patrick Delaunayb10cddf2020-02-12 19:37:38 +0100614 bool shadow = true, lock = false;
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200615 int nb_otp = size / sizeof(u32);
Patrick Delaunayd5388292023-01-06 13:20:15 +0100616 int otp, cmd;
Patrick Delaunay4c7c0742019-06-21 15:26:43 +0200617 unsigned int offs = offset;
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200618
Patrick Delaunayb10cddf2020-02-12 19:37:38 +0100619 if (offs >= STM32_BSEC_LOCK_OFFSET) {
620 offs -= STM32_BSEC_LOCK_OFFSET;
621 lock = true;
622 } else if (offs >= STM32_BSEC_OTP_OFFSET) {
Patrick Delaunay4c7c0742019-06-21 15:26:43 +0200623 offs -= STM32_BSEC_OTP_OFFSET;
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200624 shadow = false;
625 }
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200626
Patrick Delaunay8275ff32023-04-27 15:36:34 +0200627 if ((offs % 4) || (size % 4) || !size)
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200628 return -EINVAL;
Patrick Delaunay7e5f8e32019-08-02 13:08:02 +0200629
Patrick Delaunayd5388292023-01-06 13:20:15 +0100630 if (IS_ENABLED(CONFIG_OPTEE) && priv->tee) {
631 cmd = FUSE_ACCESS;
632 if (shadow)
633 cmd = SHADOW_ACCESS;
634 if (lock)
635 cmd = LOCK_ACCESS;
636 ret = bsec_optee_pta(dev, PTA_BSEC_READ_MEM, cmd, offs, buf, size);
637 if (ret)
638 return ret;
639
640 return size;
641 }
642
Patrick Delaunay7e5f8e32019-08-02 13:08:02 +0200643 otp = offs / sizeof(u32);
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200644
Patrick Delaunay7e5f8e32019-08-02 13:08:02 +0200645 for (i = otp; i < (otp + nb_otp) && i <= BSEC_OTP_MAX_VALUE; i++) {
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200646 u32 *addr = &((u32 *)buf)[i - otp];
647
Patrick Delaunayb10cddf2020-02-12 19:37:38 +0100648 if (lock)
649 ret = stm32mp_bsec_read_lock(dev, addr, i);
650 else if (shadow)
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200651 ret = stm32mp_bsec_read_shadow(dev, addr, i);
652 else
653 ret = stm32mp_bsec_read_otp(dev, addr, i);
654
655 if (ret)
656 break;
657 }
Patrick Delaunay7e5f8e32019-08-02 13:08:02 +0200658 if (ret)
659 return ret;
660 else
661 return (i - otp) * 4;
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200662}
663
664static int stm32mp_bsec_write(struct udevice *dev, int offset,
665 const void *buf, int size)
666{
Patrick Delaunayd5388292023-01-06 13:20:15 +0100667 struct stm32mp_bsec_priv *priv = dev_get_priv(dev);
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200668 int ret = 0;
669 int i;
Patrick Delaunayb10cddf2020-02-12 19:37:38 +0100670 bool shadow = true, lock = false;
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200671 int nb_otp = size / sizeof(u32);
Patrick Delaunayd5388292023-01-06 13:20:15 +0100672 int otp, cmd;
Patrick Delaunay4c7c0742019-06-21 15:26:43 +0200673 unsigned int offs = offset;
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200674
Patrick Delaunayb10cddf2020-02-12 19:37:38 +0100675 if (offs >= STM32_BSEC_LOCK_OFFSET) {
676 offs -= STM32_BSEC_LOCK_OFFSET;
677 lock = true;
678 } else if (offs >= STM32_BSEC_OTP_OFFSET) {
Patrick Delaunay4c7c0742019-06-21 15:26:43 +0200679 offs -= STM32_BSEC_OTP_OFFSET;
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200680 shadow = false;
681 }
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200682
Patrick Delaunay8275ff32023-04-27 15:36:34 +0200683 if ((offs % 4) || (size % 4) || !size)
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200684 return -EINVAL;
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200685
Patrick Delaunayd5388292023-01-06 13:20:15 +0100686 if (IS_ENABLED(CONFIG_OPTEE) && priv->tee) {
687 cmd = FUSE_ACCESS;
688 if (shadow)
689 cmd = SHADOW_ACCESS;
690 if (lock)
691 cmd = LOCK_ACCESS;
692 ret = bsec_optee_pta(dev, PTA_BSEC_WRITE_MEM, cmd, offs, (void *)buf, size);
693 if (ret)
694 return ret;
695
696 return size;
697 }
698
Patrick Delaunay7e5f8e32019-08-02 13:08:02 +0200699 otp = offs / sizeof(u32);
700
701 for (i = otp; i < otp + nb_otp && i <= BSEC_OTP_MAX_VALUE; i++) {
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200702 u32 *val = &((u32 *)buf)[i - otp];
703
Patrick Delaunayb10cddf2020-02-12 19:37:38 +0100704 if (lock)
705 ret = stm32mp_bsec_write_lock(dev, *val, i);
706 else if (shadow)
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200707 ret = stm32mp_bsec_write_shadow(dev, *val, i);
708 else
709 ret = stm32mp_bsec_write_otp(dev, *val, i);
710 if (ret)
711 break;
712 }
Patrick Delaunay7e5f8e32019-08-02 13:08:02 +0200713 if (ret)
714 return ret;
715 else
716 return (i - otp) * 4;
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200717}
718
719static const struct misc_ops stm32mp_bsec_ops = {
720 .read = stm32mp_bsec_read,
721 .write = stm32mp_bsec_write,
722};
723
Simon Glassaad29ae2020-12-03 16:55:21 -0700724static int stm32mp_bsec_of_to_plat(struct udevice *dev)
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200725{
Simon Glassb75b15b2020-12-03 16:55:23 -0700726 struct stm32mp_bsec_plat *plat = dev_get_plat(dev);
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200727
Patrice Chotard1115c302023-10-27 16:43:00 +0200728 plat->base = dev_read_addr_ptr(dev);
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200729
730 return 0;
731}
732
Patrick Delaunayf95686b2019-02-27 17:01:28 +0100733static int stm32mp_bsec_probe(struct udevice *dev)
734{
735 int otp;
Simon Glassb75b15b2020-12-03 16:55:23 -0700736 struct stm32mp_bsec_plat *plat;
Patrick Delaunayaaf1f962021-02-25 13:43:07 +0100737 struct clk_bulk clk_bulk;
738 int ret;
739
740 ret = clk_get_bulk(dev, &clk_bulk);
741 if (!ret) {
742 ret = clk_enable_bulk(&clk_bulk);
743 if (ret)
744 return ret;
745 }
Patrick Delaunayf95686b2019-02-27 17:01:28 +0100746
Patrick Delaunayd5388292023-01-06 13:20:15 +0100747 if (IS_ENABLED(CONFIG_OPTEE))
748 bsec_optee_open(dev);
749
Patrick Delaunayb6cc5052020-05-25 12:19:41 +0200750 /*
751 * update unlocked shadow for OTP cleared by the rom code
Patrick Delaunaydd2ca252021-10-11 09:52:48 +0200752 * only executed in SPL, it is done in TF-A for TFABOOT
Patrick Delaunayb6cc5052020-05-25 12:19:41 +0200753 */
Patrick Delaunaydd2ca252021-10-11 09:52:48 +0200754 if (IS_ENABLED(CONFIG_SPL_BUILD)) {
Simon Glassfa20e932020-12-03 16:55:20 -0700755 plat = dev_get_plat(dev);
Patrick Delaunay1dffeaf2020-07-31 16:31:51 +0200756
757 for (otp = 57; otp <= BSEC_OTP_MAX_VALUE; otp++)
758 if (!bsec_read_SR_lock(plat->base, otp))
Patrick Delaunayfbefc102020-11-06 19:01:31 +0100759 bsec_shadow_register(dev, plat->base, otp);
Patrick Delaunay1dffeaf2020-07-31 16:31:51 +0200760 }
Patrick Delaunayf95686b2019-02-27 17:01:28 +0100761
762 return 0;
763}
Patrick Delaunayf95686b2019-02-27 17:01:28 +0100764
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200765static const struct udevice_id stm32mp_bsec_ids[] = {
Patrick Delaunay986ec7b2023-01-06 13:20:16 +0100766 { .compatible = "st,stm32mp13-bsec" },
Patrick Delaunaybdd71362019-02-27 17:01:27 +0100767 { .compatible = "st,stm32mp15-bsec" },
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200768 {}
769};
770
771U_BOOT_DRIVER(stm32mp_bsec) = {
772 .name = "stm32mp_bsec",
773 .id = UCLASS_MISC,
774 .of_match = stm32mp_bsec_ids,
Simon Glassaad29ae2020-12-03 16:55:21 -0700775 .of_to_plat = stm32mp_bsec_of_to_plat,
Patrick Delaunay5fa74b82023-01-06 13:20:14 +0100776 .plat_auto = sizeof(struct stm32mp_bsec_plat),
Patrick Delaunayd5388292023-01-06 13:20:15 +0100777 .priv_auto = sizeof(struct stm32mp_bsec_priv),
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200778 .ops = &stm32mp_bsec_ops,
Patrick Delaunayf95686b2019-02-27 17:01:28 +0100779 .probe = stm32mp_bsec_probe,
Patrick Delaunay14d6a242018-05-17 15:24:05 +0200780};
Patrick Delaunay6332c042020-06-16 18:27:44 +0200781
782bool bsec_dbgswenable(void)
783{
784 struct udevice *dev;
Simon Glassb75b15b2020-12-03 16:55:23 -0700785 struct stm32mp_bsec_plat *plat;
Patrick Delaunay6332c042020-06-16 18:27:44 +0200786 int ret;
787
788 ret = uclass_get_device_by_driver(UCLASS_MISC,
Simon Glass65130cd2020-12-28 20:34:56 -0700789 DM_DRIVER_GET(stm32mp_bsec), &dev);
Patrick Delaunay6332c042020-06-16 18:27:44 +0200790 if (ret || !dev) {
Patrick Delaunayfbefc102020-11-06 19:01:31 +0100791 log_debug("bsec driver not available\n");
Patrick Delaunay6332c042020-06-16 18:27:44 +0200792 return false;
793 }
794
Simon Glassfa20e932020-12-03 16:55:20 -0700795 plat = dev_get_plat(dev);
Patrick Delaunay6332c042020-06-16 18:27:44 +0200796 if (readl(plat->base + BSEC_DENABLE_OFF) & BSEC_DENABLE_DBGSWENABLE)
797 return true;
798
799 return false;
800}
Patrick Delaunay9fa24a52022-05-20 18:24:41 +0200801
802u32 get_otp(int index, int shift, int mask)
803{
804 int ret;
805 struct udevice *dev;
806 u32 otp = 0;
807
808 ret = uclass_get_device_by_driver(UCLASS_MISC,
809 DM_DRIVER_GET(stm32mp_bsec),
810 &dev);
811
812 if (!ret)
813 ret = misc_read(dev, STM32_BSEC_SHADOW(index),
814 &otp, sizeof(otp));
815
816 return (otp >> shift) & mask;
817}