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 }