1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3 * Rockchip Secure OTP Driver
4 *
5 * Copyright (c) 2023 Rockchip Electronics Co. Ltd.
6 * Author: Hisping <hisping.lin@rock-chips.com>
7 */
8
9 #include <linux/clk.h>
10 #include <linux/delay.h>
11 #include <linux/device.h>
12 #include <linux/io.h>
13 #include <linux/iopoll.h>
14 #include <linux/module.h>
15 #include <linux/nvmem-provider.h>
16 #include <linux/reset.h>
17 #include <linux/rockchip/cpu.h>
18 #include <linux/slab.h>
19 #include <linux/of.h>
20 #include <linux/of_platform.h>
21 #include <linux/platform_device.h>
22 #include <linux/tee_drv.h>
23 #include <linux/uuid.h>
24
25 static DEFINE_MUTEX(nvmem_mutex);
26
27 struct rockchip_data;
28
29 struct rockchip_otp {
30 struct device *dev;
31 struct nvmem_config *config;
32 const struct rockchip_data *data;
33 };
34
35 struct rockchip_data {
36 int size;
37 int (*reg_read)(unsigned int offset, void *val, size_t bytes);
38 int (*reg_write)(unsigned int offset, void *val, size_t bytes);
39 int (*init)(struct rockchip_otp *otp);
40 };
41
optee_ctx_match(struct tee_ioctl_version_data * ver,const void * data)42 static int optee_ctx_match(struct tee_ioctl_version_data *ver, const void *data)
43 {
44 if (ver->impl_id == TEE_IMPL_ID_OPTEE)
45 return 1;
46 else
47 return 0;
48 }
49
50 /*
51 * func: read data from non-protected oem zone in secure otp
52 */
53 #define STORAGE_CMD_READ_OEM_NS_OTP 13
rockchip_read_oem_non_protected_otp(unsigned int byte_off,void * byte_buf,size_t byte_len)54 int rockchip_read_oem_non_protected_otp(unsigned int byte_off,
55 void *byte_buf, size_t byte_len)
56 {
57 const uuid_t pta_uuid =
58 UUID_INIT(0x2d26d8a8, 0x5134, 0x4dd8,
59 0xb3, 0x2f, 0xb3, 0x4b, 0xce, 0xeb, 0xc4, 0x71);
60 struct tee_ioctl_open_session_arg sess_arg;
61 struct tee_shm *device_shm = NULL;
62 struct tee_context *ctx = NULL;
63 u32 shm_size = 0;
64 int rc;
65 struct tee_ioctl_invoke_arg inv_arg;
66 struct tee_param param[4];
67 u8 *read_data = NULL;
68
69 if (!byte_buf) {
70 pr_err("buf is null\n");
71 return -EINVAL;
72 }
73
74 memset(&sess_arg, 0, sizeof(sess_arg));
75
76 mutex_lock(&nvmem_mutex);
77
78 /* Open context with OP-TEE driver */
79 ctx = tee_client_open_context(NULL, optee_ctx_match, NULL, NULL);
80 if (IS_ERR(ctx)) {
81 pr_err("tee_client_open_context failed\n");
82 rc = -ENODEV;
83 goto out_exit;
84 }
85
86 /* Open session */
87 memcpy(sess_arg.uuid, pta_uuid.b, TEE_IOCTL_UUID_LEN);
88 sess_arg.clnt_login = TEE_IOCTL_LOGIN_PUBLIC;
89 sess_arg.num_params = 0;
90
91 rc = tee_client_open_session(ctx, &sess_arg, NULL);
92 if ((rc < 0) || (sess_arg.ret != 0)) {
93 pr_err("tee_client_open_session failed, err: %x\n",
94 sess_arg.ret);
95 rc = -EINVAL;
96 goto out_ctx;
97 }
98
99 /* Alloc share memory */
100 shm_size = byte_len;
101 device_shm = tee_shm_alloc(ctx, shm_size,
102 TEE_SHM_MAPPED | TEE_SHM_DMA_BUF);
103 if (IS_ERR(device_shm)) {
104 pr_err("tee_shm_alloc failed\n");
105 rc = PTR_ERR(device_shm);
106 goto out_sess;
107 }
108
109 /* Invoke func */
110 memset(&inv_arg, 0, sizeof(inv_arg));
111 memset(¶m, 0, sizeof(param));
112
113 inv_arg.func = STORAGE_CMD_READ_OEM_NS_OTP;
114 inv_arg.session = sess_arg.session;
115 inv_arg.num_params = 4;
116
117 /* Fill invoke cmd params */
118 param[0].attr = TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT;
119 param[0].u.value.a = byte_off;
120
121 param[1].attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT;
122 param[1].u.memref.shm = device_shm;
123 param[1].u.memref.size = shm_size;
124 param[1].u.memref.shm_offs = 0;
125
126 rc = tee_client_invoke_func(ctx, &inv_arg, param);
127 if ((rc < 0) || (inv_arg.ret != 0)) {
128 pr_err("invoke function err: %x\n", inv_arg.ret);
129 rc = -EINVAL;
130 goto out_shm;
131 }
132
133 read_data = tee_shm_get_va(device_shm, 0);
134 if (IS_ERR(read_data)) {
135 pr_err("tee_shm_get_va failed\n");
136 rc = -EINVAL;
137 goto out_shm;
138 }
139 memcpy(byte_buf, read_data, byte_len);
140
141 out_shm:
142 tee_shm_free(device_shm);
143 out_sess:
144 tee_client_close_session(ctx, sess_arg.session);
145 out_ctx:
146 tee_client_close_context(ctx);
147 out_exit:
148 mutex_unlock(&nvmem_mutex);
149 return rc;
150 }
151 EXPORT_SYMBOL_GPL(rockchip_read_oem_non_protected_otp);
152
153 /*
154 * func: write data to non-protected oem zone in secure otp
155 */
156 #define STORAGE_CMD_WRITE_OEM_NS_OTP 12
rockchip_write_oem_non_protected_otp(unsigned int byte_off,void * byte_buf,size_t byte_len)157 int rockchip_write_oem_non_protected_otp(unsigned int byte_off,
158 void *byte_buf, size_t byte_len)
159 {
160 const uuid_t pta_uuid =
161 UUID_INIT(0x2d26d8a8, 0x5134, 0x4dd8,
162 0xb3, 0x2f, 0xb3, 0x4b, 0xce, 0xeb, 0xc4, 0x71);
163 struct tee_ioctl_open_session_arg sess_arg;
164 struct tee_shm *device_shm = NULL;
165 struct tee_context *ctx = NULL;
166 u32 shm_size = 0;
167 int rc;
168 struct tee_ioctl_invoke_arg inv_arg;
169 struct tee_param param[4];
170 u8 *write_data = NULL;
171
172 if (!byte_buf) {
173 pr_err("buf is null\n");
174 return -EINVAL;
175 }
176
177 memset(&sess_arg, 0, sizeof(sess_arg));
178
179 mutex_lock(&nvmem_mutex);
180
181 /* Open context with OP-TEE driver */
182 ctx = tee_client_open_context(NULL, optee_ctx_match, NULL, NULL);
183 if (IS_ERR(ctx)) {
184 pr_err("tee_client_open_context failed\n");
185 rc = -ENODEV;
186 goto out_exit;
187 }
188
189 /* Open session */
190 memcpy(sess_arg.uuid, pta_uuid.b, TEE_IOCTL_UUID_LEN);
191 sess_arg.clnt_login = TEE_IOCTL_LOGIN_PUBLIC;
192 sess_arg.num_params = 0;
193
194 rc = tee_client_open_session(ctx, &sess_arg, NULL);
195 if ((rc < 0) || (sess_arg.ret != 0)) {
196 pr_err("tee_client_open_session failed, err: %x\n",
197 sess_arg.ret);
198 rc = -EINVAL;
199 goto out_ctx;
200 }
201
202 /* Alloc share memory */
203 shm_size = byte_len;
204 device_shm = tee_shm_alloc(ctx, shm_size,
205 TEE_SHM_MAPPED | TEE_SHM_DMA_BUF);
206 if (IS_ERR(device_shm)) {
207 pr_err("tee_shm_alloc failed\n");
208 rc = PTR_ERR(device_shm);
209 goto out_sess;
210 }
211
212 write_data = tee_shm_get_va(device_shm, 0);
213 if (IS_ERR(write_data)) {
214 pr_err("tee_shm_get_va failed\n");
215 rc = -EINVAL;
216 goto out_shm;
217 }
218 memcpy(write_data, byte_buf, byte_len);
219
220 /* Invoke func */
221 memset(&inv_arg, 0, sizeof(inv_arg));
222 memset(¶m, 0, sizeof(param));
223
224 inv_arg.func = STORAGE_CMD_WRITE_OEM_NS_OTP;
225 inv_arg.session = sess_arg.session;
226 inv_arg.num_params = 4;
227
228 /* Fill invoke cmd params */
229 param[0].attr = TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT;
230 param[0].u.value.a = byte_off;
231
232 param[1].attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT;
233 param[1].u.memref.shm = device_shm;
234 param[1].u.memref.size = shm_size;
235 param[1].u.memref.shm_offs = 0;
236
237 rc = tee_client_invoke_func(ctx, &inv_arg, param);
238 if ((rc < 0) || (inv_arg.ret != 0)) {
239 pr_err("invoke function err: %x\n", inv_arg.ret);
240 rc = -EINVAL;
241 goto out_shm;
242 }
243
244 out_shm:
245 tee_shm_free(device_shm);
246 out_sess:
247 tee_client_close_session(ctx, sess_arg.session);
248 out_ctx:
249 tee_client_close_context(ctx);
250 out_exit:
251 mutex_unlock(&nvmem_mutex);
252 return rc;
253 }
254 EXPORT_SYMBOL_GPL(rockchip_write_oem_non_protected_otp);
255
rockchip_secure_otp_read(void * context,unsigned int offset,void * val,size_t bytes)256 static int rockchip_secure_otp_read(void *context, unsigned int offset,
257 void *val, size_t bytes)
258 {
259 struct rockchip_otp *otp = context;
260 int ret = -EINVAL;
261
262 if (otp->data && otp->data->reg_read)
263 ret = otp->data->reg_read(offset, val, bytes);
264
265 return ret;
266 }
267
rockchip_secure_otp_write(void * context,unsigned int offset,void * val,size_t bytes)268 static int rockchip_secure_otp_write(void *context, unsigned int offset,
269 void *val, size_t bytes)
270 {
271 struct rockchip_otp *otp = context;
272 int ret = -EINVAL;
273
274 if (otp->data && otp->data->reg_write)
275 ret = otp->data->reg_write(offset, val, bytes);
276
277 return ret;
278 }
279
280 static struct nvmem_config otp_config = {
281 .name = "rockchip-secure-otp",
282 .owner = THIS_MODULE,
283 .read_only = false,
284 .reg_read = rockchip_secure_otp_read,
285 .reg_write = rockchip_secure_otp_write,
286 .stride = 4,
287 .word_size = 4,
288 };
289
290 static const struct rockchip_data secure_otp_data = {
291 .reg_read = rockchip_read_oem_non_protected_otp,
292 .reg_write = rockchip_write_oem_non_protected_otp,
293 };
294
295 static const struct of_device_id rockchip_secure_otp_match[] = {
296 {
297 .compatible = "rockchip,secure-otp",
298 .data = (void *)&secure_otp_data,
299 },
300 { /* sentinel */ },
301 };
302 MODULE_DEVICE_TABLE(of, rockchip_secure_otp_match);
303
rockchip_secure_otp_probe(struct platform_device * pdev)304 static int rockchip_secure_otp_probe(struct platform_device *pdev)
305 {
306 struct device *dev = &pdev->dev;
307 struct rockchip_otp *otp;
308 const struct rockchip_data *data;
309 struct nvmem_device *nvmem;
310 u32 otp_size;
311 int ret;
312
313 data = device_get_match_data(dev);
314 if (!data) {
315 dev_err(dev, "failed to get match data\n");
316 return -EINVAL;
317 }
318
319 ret = device_property_read_u32(dev, "rockchip,otp-size", &otp_size);
320 if (ret) {
321 dev_err(dev, "otp size parameter not specified\n");
322 return -EINVAL;
323 } else if (otp_size == 0) {
324 dev_err(dev, "otp size must be > 0\n");
325 return -EINVAL;
326 }
327
328 otp = devm_kzalloc(&pdev->dev, sizeof(struct rockchip_otp),
329 GFP_KERNEL);
330 if (!otp)
331 return -ENOMEM;
332
333 otp->data = data;
334 otp->dev = dev;
335
336 otp->config = &otp_config;
337 otp->config->size = otp_size;
338 otp->config->priv = otp;
339 otp->config->dev = dev;
340
341 if (data->init) {
342 ret = data->init(otp);
343 if (ret)
344 return ret;
345 }
346
347 nvmem = devm_nvmem_register(dev, otp->config);
348
349 return PTR_ERR_OR_ZERO(nvmem);
350 }
351
352 static struct platform_driver rockchip_secure_otp_driver = {
353 .probe = rockchip_secure_otp_probe,
354 .driver = {
355 .name = "rockchip-secure-otp",
356 .of_match_table = rockchip_secure_otp_match,
357 },
358 };
359
rockchip_secure_otp_init(void)360 static int __init rockchip_secure_otp_init(void)
361 {
362 int ret;
363
364 ret = platform_driver_register(&rockchip_secure_otp_driver);
365 if (ret) {
366 pr_err("failed to register secure otp driver\n");
367 return ret;
368 }
369
370 return 0;
371 }
372
rockchip_secure_otp_exit(void)373 static void __exit rockchip_secure_otp_exit(void)
374 {
375 return platform_driver_unregister(&rockchip_secure_otp_driver);
376 }
377
378 subsys_initcall(rockchip_secure_otp_init);
379 module_exit(rockchip_secure_otp_exit);
380
381 MODULE_DESCRIPTION("Rockchip Secure OTP Driver");
382 MODULE_LICENSE("GPL");
383