1// SPDX-License-Identifier: GPL-2.0
2/*
3 * Copyright 2020, 2023 NXP
4 *
5 */
6
7#include <common.h>
8#include <hang.h>
9#include <malloc.h>
10#include <asm/io.h>
11#include <dm.h>
12#include <asm/mach-imx/ele_api.h>
13#include <misc.h>
14
15DECLARE_GLOBAL_DATA_PTR;
16
17static u32 compute_crc(const struct ele_msg *msg)
18{
19	u32 crc = 0;
20	size_t i = 0;
21	u32 *data = (u32 *)msg;
22
23	for (i = 0; i < (msg->size - 1); i++)
24		crc ^= data[i];
25
26	return crc;
27}
28
29int ele_release_rdc(u8 core_id, u8 xrdc, u32 *response)
30{
31	struct udevice *dev = gd->arch.ele_dev;
32	int size = sizeof(struct ele_msg);
33	struct ele_msg msg;
34	int ret;
35
36	if (!dev) {
37		printf("ele dev is not initialized\n");
38		return -ENODEV;
39	}
40
41	msg.version = ELE_VERSION;
42	msg.tag = ELE_CMD_TAG;
43	msg.size = 2;
44	msg.command = ELE_RELEASE_RDC_REQ;
45	switch (xrdc) {
46	case 0:
47		msg.data[0] = (0x74 << 8) | core_id;
48		break;
49	case 1:
50		msg.data[0] = (0x78 << 8) | core_id;
51		break;
52	case 2:
53		msg.data[0] = (0x82 << 8) | core_id;
54		break;
55	case 3:
56		msg.data[0] = (0x86 << 8) | core_id;
57		break;
58	default:
59		printf("Error: wrong xrdc index %u\n", xrdc);
60		return -EINVAL;
61	}
62
63	ret = misc_call(dev, false, &msg, size, &msg, size);
64	if (ret)
65		printf("Error: %s: ret %d, core id %u, response 0x%x\n",
66		       __func__, ret, core_id, msg.data[0]);
67
68	if (response)
69		*response = msg.data[0];
70
71	return ret;
72}
73
74int ele_auth_oem_ctnr(ulong ctnr_addr, u32 *response)
75{
76	struct udevice *dev = gd->arch.ele_dev;
77	int size = sizeof(struct ele_msg);
78	struct ele_msg msg;
79	int ret;
80
81	if (!dev) {
82		printf("ele dev is not initialized\n");
83		return -ENODEV;
84	}
85
86	msg.version = ELE_VERSION;
87	msg.tag = ELE_CMD_TAG;
88	msg.size = 3;
89	msg.command = ELE_OEM_CNTN_AUTH_REQ;
90	msg.data[0] = upper_32_bits(ctnr_addr);
91	msg.data[1] = lower_32_bits(ctnr_addr);
92
93	ret = misc_call(dev, false, &msg, size, &msg, size);
94	if (ret)
95		printf("Error: %s: ret %d, cntr_addr 0x%lx, response 0x%x\n",
96		       __func__, ret, ctnr_addr, msg.data[0]);
97
98	if (response)
99		*response = msg.data[0];
100
101	return ret;
102}
103
104int ele_release_container(u32 *response)
105{
106	struct udevice *dev = gd->arch.ele_dev;
107	int size = sizeof(struct ele_msg);
108	struct ele_msg msg;
109	int ret;
110
111	if (!dev) {
112		printf("ele dev is not initialized\n");
113		return -ENODEV;
114	}
115
116	msg.version = ELE_VERSION;
117	msg.tag = ELE_CMD_TAG;
118	msg.size = 1;
119	msg.command = ELE_RELEASE_CONTAINER_REQ;
120
121	ret = misc_call(dev, false, &msg, size, &msg, size);
122	if (ret)
123		printf("Error: %s: ret %d, response 0x%x\n",
124		       __func__, ret, msg.data[0]);
125
126	if (response)
127		*response = msg.data[0];
128
129	return ret;
130}
131
132int ele_verify_image(u32 img_id, u32 *response)
133{
134	struct udevice *dev = gd->arch.ele_dev;
135	int size = sizeof(struct ele_msg);
136	struct ele_msg msg;
137	int ret;
138
139	if (!dev) {
140		printf("ele dev is not initialized\n");
141		return -ENODEV;
142	}
143
144	msg.version = ELE_VERSION;
145	msg.tag = ELE_CMD_TAG;
146	msg.size = 2;
147	msg.command = ELE_VERIFY_IMAGE_REQ;
148	msg.data[0] = 1 << img_id;
149
150	ret = misc_call(dev, false, &msg, size, &msg, size);
151	if (ret)
152		printf("Error: %s: ret %d, img_id %u, response 0x%x\n",
153		       __func__, ret, img_id, msg.data[0]);
154
155	if (response)
156		*response = msg.data[0];
157
158	return ret;
159}
160
161int ele_forward_lifecycle(u16 life_cycle, u32 *response)
162{
163	struct udevice *dev = gd->arch.ele_dev;
164	int size = sizeof(struct ele_msg);
165	struct ele_msg msg;
166	int ret;
167
168	if (!dev) {
169		printf("ele dev is not initialized\n");
170		return -ENODEV;
171	}
172
173	msg.version = ELE_VERSION;
174	msg.tag = ELE_CMD_TAG;
175	msg.size = 2;
176	msg.command = ELE_FWD_LIFECYCLE_UP_REQ;
177	msg.data[0] = life_cycle;
178
179	ret = misc_call(dev, false, &msg, size, &msg, size);
180	if (ret)
181		printf("Error: %s: ret %d, life_cycle 0x%x, response 0x%x\n",
182		       __func__, ret, life_cycle, msg.data[0]);
183
184	if (response)
185		*response = msg.data[0];
186
187	return ret;
188}
189
190int ele_read_common_fuse(u16 fuse_id, u32 *fuse_words, u32 fuse_num, u32 *response)
191{
192	struct udevice *dev = gd->arch.ele_dev;
193	int size = sizeof(struct ele_msg);
194	struct ele_msg msg;
195	int ret;
196
197	if (!dev) {
198		printf("ele dev is not initialized\n");
199		return -ENODEV;
200	}
201
202	if (!fuse_words) {
203		printf("Invalid parameters for fuse read\n");
204		return -EINVAL;
205	}
206
207	if ((fuse_id != 1 && fuse_num != 1) ||
208	    (fuse_id == 1 && fuse_num != 4)) {
209		printf("Invalid fuse number parameter\n");
210		return -EINVAL;
211	}
212
213	msg.version = ELE_VERSION;
214	msg.tag = ELE_CMD_TAG;
215	msg.size = 2;
216	msg.command = ELE_READ_FUSE_REQ;
217	msg.data[0] = fuse_id;
218
219	ret = misc_call(dev, false, &msg, size, &msg, size);
220	if (ret)
221		printf("Error: %s: ret %d, fuse_id 0x%x, response 0x%x\n",
222		       __func__, ret, fuse_id, msg.data[0]);
223
224	if (response)
225		*response = msg.data[0];
226
227	fuse_words[0] = msg.data[1];
228	if (fuse_id == 1) {
229		/* OTP_UNIQ_ID */
230		fuse_words[1] = msg.data[2];
231		fuse_words[2] = msg.data[3];
232		fuse_words[3] = msg.data[4];
233	}
234
235	return ret;
236}
237
238int ele_write_fuse(u16 fuse_id, u32 fuse_val, bool lock, u32 *response)
239{
240	struct udevice *dev = gd->arch.ele_dev;
241	int size = sizeof(struct ele_msg);
242	struct ele_msg msg;
243	int ret;
244
245	if (!dev) {
246		printf("ele dev is not initialized\n");
247		return -ENODEV;
248	}
249
250	msg.version = ELE_VERSION;
251	msg.tag = ELE_CMD_TAG;
252	msg.size = 3;
253	msg.command = ELE_WRITE_FUSE_REQ;
254	msg.data[0] = (32 << 16) | (fuse_id << 5);
255	if (lock)
256		msg.data[0] |= (1 << 31);
257
258	msg.data[1] = fuse_val;
259
260	ret = misc_call(dev, false, &msg, size, &msg, size);
261	if (ret)
262		printf("Error: %s: ret %d, fuse_id 0x%x, response 0x%x\n",
263		       __func__, ret, fuse_id, msg.data[0]);
264
265	if (response)
266		*response = msg.data[0];
267
268	return ret;
269}
270
271int ele_release_caam(u32 core_did, u32 *response)
272{
273	struct udevice *dev = gd->arch.ele_dev;
274	int size = sizeof(struct ele_msg);
275	struct ele_msg msg;
276	int ret;
277
278	if (!dev) {
279		printf("ele dev is not initialized\n");
280		return -ENODEV;
281	}
282
283	msg.version = ELE_VERSION;
284	msg.tag = ELE_CMD_TAG;
285	msg.size = 2;
286	msg.command = ELE_RELEASE_CAAM_REQ;
287	msg.data[0] = core_did;
288
289	ret = misc_call(dev, false, &msg, size, &msg, size);
290	if (ret)
291		printf("Error: %s: ret %d, response 0x%x\n",
292		       __func__, ret, msg.data[0]);
293
294	if (response)
295		*response = msg.data[0];
296
297	return ret;
298}
299
300int ele_get_fw_version(u32 *fw_version, u32 *sha1, u32 *response)
301{
302	struct udevice *dev = gd->arch.ele_dev;
303	int size = sizeof(struct ele_msg);
304	struct ele_msg msg;
305	int ret;
306
307	if (!dev) {
308		printf("ele dev is not initialized\n");
309		return -ENODEV;
310	}
311
312	if (!fw_version) {
313		printf("Invalid parameters for f/w version read\n");
314		return -EINVAL;
315	}
316
317	if (!sha1) {
318		printf("Invalid parameters for commit sha1\n");
319		return -EINVAL;
320	}
321
322	msg.version = ELE_VERSION;
323	msg.tag = ELE_CMD_TAG;
324	msg.size = 1;
325	msg.command = ELE_GET_FW_VERSION_REQ;
326
327	ret = misc_call(dev, false, &msg, size, &msg, size);
328	if (ret)
329		printf("Error: %s: ret %d, response 0x%x\n",
330		       __func__, ret, msg.data[0]);
331
332	if (response)
333		*response = msg.data[0];
334
335	*fw_version = msg.data[1];
336	*sha1 = msg.data[2];
337
338	return ret;
339}
340
341int ele_dump_buffer(u32 *buffer, u32 buffer_length)
342{
343	struct udevice *dev = gd->arch.ele_dev;
344	int size = sizeof(struct ele_msg);
345	struct ele_msg msg;
346	int ret, i = 0;
347
348	if (!dev) {
349		printf("ele dev is not initialized\n");
350		return -ENODEV;
351	}
352
353	msg.version = ELE_VERSION;
354	msg.tag = ELE_CMD_TAG;
355	msg.size = 1;
356	msg.command = ELE_DUMP_DEBUG_BUFFER_REQ;
357
358	ret = misc_call(dev, false, &msg, size, &msg, size);
359	if (ret) {
360		printf("Error: %s: ret %d, response 0x%x\n",
361		       __func__, ret, msg.data[0]);
362
363		return ret;
364	}
365
366	if (buffer) {
367		buffer[i++] = *(u32 *)&msg; /* Need dump the response header */
368		for (; i < buffer_length && i < msg.size; i++)
369			buffer[i] = msg.data[i - 1];
370	}
371
372	return i;
373}
374
375int ele_get_info(struct ele_get_info_data *info, u32 *response)
376{
377	struct udevice *dev = gd->arch.ele_dev;
378	int size = sizeof(struct ele_msg);
379	struct ele_msg msg;
380	int ret;
381
382	if (!dev) {
383		printf("ele dev is not initialized\n");
384		return -ENODEV;
385	}
386
387	msg.version = ELE_VERSION;
388	msg.tag = ELE_CMD_TAG;
389	msg.size = 4;
390	msg.command = ELE_GET_INFO_REQ;
391	msg.data[0] = upper_32_bits((ulong)info);
392	msg.data[1] = lower_32_bits((ulong)info);
393	msg.data[2] = sizeof(struct ele_get_info_data);
394
395	ret = misc_call(dev, false, &msg, size, &msg, size);
396	if (ret)
397		printf("Error: %s: ret %d, response 0x%x\n",
398		       __func__, ret, msg.data[0]);
399
400	if (response)
401		*response = msg.data[0];
402
403	return ret;
404}
405
406int ele_get_fw_status(u32 *status, u32 *response)
407{
408	struct udevice *dev = gd->arch.ele_dev;
409	int size = sizeof(struct ele_msg);
410	struct ele_msg msg;
411	int ret;
412
413	if (!dev) {
414		printf("ele dev is not initialized\n");
415		return -ENODEV;
416	}
417
418	msg.version = ELE_VERSION;
419	msg.tag = ELE_CMD_TAG;
420	msg.size = 1;
421	msg.command = ELE_GET_FW_STATUS_REQ;
422
423	ret = misc_call(dev, false, &msg, size, &msg, size);
424	if (ret)
425		printf("Error: %s: ret %d, response 0x%x\n",
426		       __func__, ret, msg.data[0]);
427
428	if (response)
429		*response = msg.data[0];
430
431	*status = msg.data[1] & 0xF;
432
433	return ret;
434}
435
436int ele_release_m33_trout(void)
437{
438	struct udevice *dev = gd->arch.ele_dev;
439	int size = sizeof(struct ele_msg);
440	struct ele_msg msg;
441	int ret;
442
443	if (!dev) {
444		printf("ele dev is not initialized\n");
445		return -ENODEV;
446	}
447
448	msg.version = ELE_VERSION;
449	msg.tag = ELE_CMD_TAG;
450	msg.size = 1;
451	msg.command = ELE_ENABLE_RTC_REQ;
452
453	ret = misc_call(dev, false, &msg, size, &msg, size);
454	if (ret)
455		printf("Error: %s: ret %d, response 0x%x\n",
456		       __func__, ret, msg.data[0]);
457
458	return ret;
459}
460
461int ele_get_events(u32 *events, u32 *events_cnt, u32 *response)
462{
463	struct udevice *dev = gd->arch.ele_dev;
464	int size = sizeof(struct ele_msg);
465	struct ele_msg msg;
466	int ret, i = 0;
467	u32 actual_events;
468
469	if (!dev) {
470		printf("ele dev is not initialized\n");
471		return -ENODEV;
472	}
473
474	if (!events || !events_cnt || *events_cnt == 0) {
475		printf("Invalid parameters for %s\n", __func__);
476		return -EINVAL;
477	}
478
479	msg.version = ELE_VERSION;
480	msg.tag = ELE_CMD_TAG;
481	msg.size = 1;
482	msg.command = ELE_GET_EVENTS_REQ;
483
484	ret = misc_call(dev, false, &msg, size, &msg, size);
485	if (ret)
486		printf("Error: %s: ret %d, response 0x%x\n",
487		       __func__, ret, msg.data[0]);
488
489	if (response)
490		*response = msg.data[0];
491
492	if (!ret) {
493		actual_events = msg.data[1] & 0xffff;
494		if (*events_cnt < actual_events)
495			actual_events = *events_cnt;
496
497		for (; i < actual_events; i++)
498			events[i] = msg.data[i + 2];
499
500		*events_cnt = actual_events;
501	}
502
503	return ret;
504}
505
506int ele_start_rng(void)
507{
508	struct udevice *dev = gd->arch.ele_dev;
509	int size = sizeof(struct ele_msg);
510	struct ele_msg msg;
511	int ret;
512
513	if (!dev) {
514		printf("ele dev is not initialized\n");
515		return -ENODEV;
516	}
517
518	msg.version = ELE_VERSION;
519	msg.tag = ELE_CMD_TAG;
520	msg.size = 1;
521	msg.command = ELE_START_RNG;
522
523	ret = misc_call(dev, false, &msg, size, &msg, size);
524	if (ret)
525		printf("Error: %s: ret %d, response 0x%x\n",
526		       __func__, ret, msg.data[0]);
527
528	return ret;
529}
530
531int ele_commit(u16 fuse_id, u32 *response, u32 *info_type)
532{
533	struct udevice *dev = gd->arch.ele_dev;
534	int size = sizeof(struct ele_msg);
535	struct ele_msg msg;
536	int ret = 0;
537
538	if (!dev) {
539		printf("ele dev is not initialized\n");
540		return -ENODEV;
541	}
542
543	msg.version = ELE_VERSION;
544	msg.tag = ELE_CMD_TAG;
545	msg.size = 2;
546	msg.command = ELE_COMMIT_REQ;
547	msg.data[0] = fuse_id;
548
549	ret = misc_call(dev, false, &msg, size, &msg, size);
550	if (ret)
551		printf("Error: %s: ret %d, fuse_id 0x%x, response 0x%x\n",
552		       __func__, ret, fuse_id, msg.data[0]);
553
554	if (response)
555		*response = msg.data[0];
556
557	if (info_type)
558		*info_type = msg.data[1];
559
560	return ret;
561}
562
563int ele_write_secure_fuse(ulong signed_msg_blk, u32 *response)
564{
565	struct udevice *dev = gd->arch.ele_dev;
566	int size = sizeof(struct ele_msg);
567	struct ele_msg msg;
568	int ret;
569
570	if (!dev) {
571		printf("ele dev is not initialized\n");
572		return -ENODEV;
573	}
574
575	msg.version = ELE_VERSION;
576	msg.tag = ELE_CMD_TAG;
577	msg.size = 3;
578	msg.command = ELE_WRITE_SECURE_FUSE_REQ;
579
580	msg.data[0] = upper_32_bits(signed_msg_blk);
581	msg.data[1] = lower_32_bits(signed_msg_blk);
582
583	ret = misc_call(dev, false, &msg, size, &msg, size);
584	if (ret)
585		printf("Error: %s: ret %d, response 0x%x, failed fuse row index %u\n",
586		       __func__, ret, msg.data[0], msg.data[1]);
587
588	if (response)
589		*response = msg.data[0];
590
591	return ret;
592}
593
594int ele_return_lifecycle_update(ulong signed_msg_blk, u32 *response)
595{
596	struct udevice *dev = gd->arch.ele_dev;
597	int size = sizeof(struct ele_msg);
598	struct ele_msg msg;
599	int ret;
600
601	if (!dev) {
602		printf("ele dev is not initialized\n");
603		return -ENODEV;
604	}
605
606	msg.version = ELE_VERSION;
607	msg.tag = ELE_CMD_TAG;
608	msg.size = 3;
609	msg.command = ELE_RET_LIFECYCLE_UP_REQ;
610
611	msg.data[0] = upper_32_bits(signed_msg_blk);
612	msg.data[1] = lower_32_bits(signed_msg_blk);
613
614	ret = misc_call(dev, false, &msg, size, &msg, size);
615	if (ret)
616		printf("Error: %s: ret %d, response 0x%x, failed fuse row index %u\n",
617		       __func__, ret, msg.data[0], msg.data[1]);
618
619	if (response)
620		*response = msg.data[0];
621
622	return ret;
623}
624
625int ele_generate_dek_blob(u32 key_id, u32 src_paddr, u32 dst_paddr, u32 max_output_size)
626{
627	struct udevice *dev = gd->arch.ele_dev;
628	int size = sizeof(struct ele_msg);
629	struct ele_msg msg;
630	int ret;
631
632	if (!dev) {
633		printf("ele dev is not initialized\n");
634		return -ENODEV;
635	}
636
637	msg.version = ELE_VERSION;
638	msg.tag = ELE_CMD_TAG;
639	msg.size = 8;
640	msg.command = ELE_GENERATE_DEK_BLOB;
641	msg.data[0] = key_id;
642	msg.data[1] = 0x0;
643	msg.data[2] = src_paddr;
644	msg.data[3] = 0x0;
645	msg.data[4] = dst_paddr;
646	msg.data[5] = max_output_size;
647	msg.data[6] = compute_crc(&msg);
648
649	ret = misc_call(dev, false, &msg, size, &msg, size);
650	if (ret)
651		printf("Error: %s: ret 0x%x, response 0x%x\n",
652		       __func__, ret, msg.data[0]);
653
654	return ret;
655}
656