1 /*
2  * Copyright (C) 2022 Huawei Technologies Co., Ltd.
3  * Decription: functions for ffa settings
4  *
5  * This software is licensed under the terms of the GNU General Public
6  * License version 2, as published by the Free Software Foundation, and
7  * may be copied, distributed, and modified under those terms.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  */
14 #include <linux/arm_ffa.h>
15 #include "ffa_abi.h"
16 #include "teek_ns_client.h"
17 #include "tz_pm.h"
18 #include "smc_call.h"
19 
20 const struct ffa_ops *g_ffa_ops = NULL;
21 struct ffa_device *g_ffa_dev = NULL;
22 
ffa_remove(struct ffa_device *ffa_dev)23 static void ffa_remove(struct ffa_device *ffa_dev)
24 {
25 	tlogd("stub remove ffa driver!\n");
26 }
27 
ffa_probe(struct ffa_device *ffa_dev)28 static int ffa_probe(struct ffa_device *ffa_dev)
29 {
30 	g_ffa_ops = ffa_dev->ops;
31 	g_ffa_dev = ffa_dev;
32 	if (!g_ffa_ops) {
33 		tloge("failed to get ffa_ops!\n");
34 		return -ENOENT;
35 	}
36 
37 	g_ffa_ops->mode_32bit_set(ffa_dev);
38 	return 0;
39 }
40 
41 /* two sp uuid can be the same */
42 const struct ffa_device_id tz_ffa_device_id[] = {
43 	/* uuid = <0xe0786148 0xe311f8e7 0x02005ebc 0x1bc5d5a5> */
44 	{0x48, 0x61, 0x78, 0xe0, 0xe7, 0xf8, 0x11, 0xe3, 0xbc, 0x5e, 0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b},
45 	{}
46 };
47 
48 static struct ffa_driver tz_ffa_driver = {
49 	.name = "iTrustee",
50 	.probe = ffa_probe,
51 	.remove = ffa_remove,
52 	.id_table = tz_ffa_device_id,
53 };
54 
ffa_abi_register(void)55 int ffa_abi_register(void)
56 {
57 	return ffa_register(&tz_ffa_driver);
58 }
59 
ffa_abi_unregister(void)60 void ffa_abi_unregister(void)
61 {
62 	ffa_unregister(&tz_ffa_driver);
63 }
64 
smc_req(struct smc_in_params *in, struct smc_out_params *out, uint8_t wait)65 void smc_req(struct smc_in_params *in, struct smc_out_params *out, uint8_t wait)
66 {
67 	ffa_forward_call(in, out, wait);
68 }
69 
convert_smc_param_to_ffa_param(struct smc_in_params *in_param, struct ffa_send_direct_data *ffa_param)70 static void convert_smc_param_to_ffa_param(struct smc_in_params *in_param, struct ffa_send_direct_data *ffa_param)
71 {
72 	ffa_param->data0 = in_param->x1;
73 	ffa_param->data1 = in_param->x2;
74 	ffa_param->data2 = in_param->x3;
75 	ffa_param->data3 = in_param->x4;
76 	/* x0(smc id) need to be transported for tee dealing it directly */
77 	ffa_param->data4 = in_param->x0;
78 }
79 
convert_ffa_param_to_smc_param(struct ffa_send_direct_data *ffa_param, struct smc_out_params *out_param)80 static void convert_ffa_param_to_smc_param(struct ffa_send_direct_data *ffa_param, struct smc_out_params *out_param)
81 {
82 	out_param->ret = ffa_param->data4;
83 	out_param->exit_reason = ffa_param->data0;
84 	out_param->ta = ffa_param->data1;
85 	out_param->target = ffa_param->data2;
86 }
87 
ffa_forward_call(struct smc_in_params *in_param, struct smc_out_params *out_param, uint8_t wait)88 int ffa_forward_call(struct smc_in_params *in_param, struct smc_out_params *out_param, uint8_t wait)
89 {
90 	if (in_param == NULL || out_param == NULL) {
91 		tloge("invalid parameter ffa forward!\n");
92 		return -1;
93 	}
94 
95 	int ret;
96 	struct ffa_send_direct_data ffa_param = {};
97 	convert_smc_param_to_ffa_param(in_param, &ffa_param);
98 
99 	do {
100 		ret = g_ffa_ops->sync_send_receive(g_ffa_dev, &ffa_param);
101 		convert_ffa_param_to_smc_param(&ffa_param, out_param);
102 	} while (out_param->ret == TSP_REQUEST && wait != 0);
103 
104 	if (ret != 0)
105 		tloge("failed to call! ret is %d\n", ret);
106 	return ret;
107 }