1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
|
From 34236d8df51d00d1167481760fda5abb56850765 Mon Sep 17 00:00:00 2001
From: Arunachalam Ganapathy <arunachalam.ganapathy@arm.com>
Date: Fri, 14 Jan 2022 18:47:08 +0000
Subject: [PATCH 33/40] ANDROID: trusty: Add trusty-ffa driver
Initial changes related to FFA transport support
- Adds FFA transport descriptor
- Defines Trusty UUID
- Initializes FFA transport does probe, sets ffa_ops
- Defers Trusty probe if ARM FF-A driver is not initialized or
Trusty SP not found.
- Link FF-A device as the supplier for Trusty platform device.
Signed-off-by: Arunachalam Ganapathy <arunachalam.ganapathy@arm.com>
Change-Id: I78f72b85c20e4bad4c24cf0826e96f27dcf2ee1d
Upstream-Status: Pending [Not submitted to upstream yet]
Signed-off-by: Rupinderjit Singh <rupinderjit.singh@arm.com
---
drivers/trusty/Makefile | 1 +
drivers/trusty/trusty-ffa.c | 196 ++++++++++++++++++++++++++++++++
drivers/trusty/trusty-ffa.h | 28 +++++
drivers/trusty/trusty-private.h | 1 +
drivers/trusty/trusty.c | 6 +
5 files changed, 232 insertions(+)
create mode 100644 drivers/trusty/trusty-ffa.c
create mode 100644 drivers/trusty/trusty-ffa.h
diff --git a/drivers/trusty/Makefile b/drivers/trusty/Makefile
index fbb53ee93003..797d61bf68ef 100644
--- a/drivers/trusty/Makefile
+++ b/drivers/trusty/Makefile
@@ -6,6 +6,7 @@
obj-$(CONFIG_TRUSTY) += trusty-core.o
trusty-core-objs += trusty.o trusty-mem.o
trusty-core-objs += trusty-smc.o
+trusty-core-objs += trusty-ffa.o
trusty-core-$(CONFIG_ARM) += trusty-smc-arm.o
trusty-core-$(CONFIG_ARM64) += trusty-smc-arm64.o
obj-$(CONFIG_TRUSTY_IRQ) += trusty-irq.o
diff --git a/drivers/trusty/trusty-ffa.c b/drivers/trusty/trusty-ffa.c
new file mode 100644
index 000000000000..c8c16a1fc700
--- /dev/null
+++ b/drivers/trusty/trusty-ffa.c
@@ -0,0 +1,196 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (C) 2022 ARM Ltd.
+ */
+
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/trusty/smcall.h>
+#include <linux/arm_ffa.h>
+#include <linux/trusty/trusty.h>
+
+#include <linux/scatterlist.h>
+#include <linux/dma-mapping.h>
+
+#include "trusty-ffa.h"
+#include "trusty-private.h"
+
+static const struct trusty_mem_ops trusty_ffa_mem_ops = {
+ .desc = &trusty_ffa_transport,
+};
+
+static const struct ffa_device_id trusty_ffa_device_id[] = {
+ /*
+ * Trusty UID: RFC-4122 compliant UUID version 4
+ * 40ee25f0-a2bc-304c-8c4ca173c57d8af1
+ */
+ { UUID_INIT(0x40ee25f0, 0xa2bc, 0x304c,
+ 0x8c, 0x4c, 0xa1, 0x73, 0xc5, 0x7d, 0x8a, 0xf1) },
+ {}
+};
+
+static int trusty_ffa_dev_match(struct device *dev, const void *uuid)
+{
+ struct ffa_device *ffa_dev;
+
+ ffa_dev = to_ffa_dev(dev);
+ if (uuid_equal(&ffa_dev->uuid, uuid))
+ return 1;
+
+ return 0;
+}
+
+static struct ffa_device *trusty_ffa_dev_find(void)
+{
+ const void *data;
+ struct device *dev;
+
+ /* currently only one trusty instance is probed */
+ data = &trusty_ffa_device_id[0].uuid;
+
+ dev = bus_find_device(&ffa_bus_type, NULL, data, trusty_ffa_dev_match);
+ if (dev) {
+ /* drop reference count */
+ put_device(dev);
+ return to_ffa_dev(dev);
+ }
+
+ return NULL;
+}
+
+static int trusty_ffa_link_supplier(struct device *c_dev, struct device *s_dev)
+{
+ if (!c_dev || !s_dev)
+ return -EINVAL;
+
+ if (!device_link_add(c_dev, s_dev, DL_FLAG_AUTOREMOVE_CONSUMER)) {
+ return -ENODEV;
+ }
+
+ return 0;
+}
+
+/*
+ * called from trusty probe
+ */
+static int trusty_ffa_transport_setup(struct device *dev)
+{
+ int rc;
+ struct trusty_state *s = platform_get_drvdata(to_platform_device(dev));
+ struct trusty_ffa_state *ffa_state;
+ struct ffa_device *ffa_dev;
+
+ /* ffa transport not required for lower api versions */
+ if (s->api_version != 0 && s->api_version < TRUSTY_API_VERSION_MEM_OBJ) {
+ return -EINVAL;
+ }
+
+ ffa_dev = trusty_ffa_dev_find();
+ if (!ffa_dev) {
+ dev_dbg(dev, "FFA: Trusty device not found defer probe\n");
+ return -EPROBE_DEFER;
+ }
+
+ ffa_state = ffa_dev_get_drvdata(ffa_dev);
+ if (!ffa_state)
+ return -EINVAL;
+
+ rc = trusty_ffa_link_supplier(dev, &ffa_dev->dev);
+ if (rc != 0)
+ return rc;
+
+ /* FFA used only for memory sharing operations */
+ if (s->api_version == TRUSTY_API_VERSION_MEM_OBJ) {
+ s->ffa = ffa_state;
+ s->mem_ops = &trusty_ffa_mem_ops;
+ return 0;
+ }
+
+ return -EINVAL;
+}
+
+static void trusty_ffa_transport_cleanup(struct device *dev)
+{
+ struct trusty_state *s = platform_get_drvdata(to_platform_device(dev));
+
+ /* ffa transport not setup for lower api versions */
+ if (s->api_version < TRUSTY_API_VERSION_MEM_OBJ) {
+ return;
+ }
+
+ s->ffa = NULL;
+ s->mem_ops = NULL;
+}
+
+static int trusty_ffa_probe(struct ffa_device *ffa_dev)
+{
+ const struct ffa_dev_ops *ffa_ops;
+ struct trusty_ffa_state *s;
+ u32 ffa_drv_version;
+
+ ffa_ops = ffa_dev_ops_get(ffa_dev);
+ if (!ffa_ops) {
+ dev_dbg(&ffa_dev->dev, "ffa_dev_ops_get: failed\n");
+ return -ENOENT;
+ }
+
+ /* check ffa driver version compatibility */
+ ffa_drv_version = ffa_ops->api_version_get();
+ if (TO_TRUSTY_FFA_MAJOR(ffa_drv_version) != TRUSTY_FFA_VERSION_MAJOR ||
+ TO_TRUSTY_FFA_MINOR(ffa_drv_version) < TRUSTY_FFA_VERSION_MINOR)
+ return -EINVAL;
+
+ s = kzalloc(sizeof(*s), GFP_KERNEL);
+ if (!s)
+ return -ENOMEM;
+
+ s->dev = &ffa_dev->dev;
+ s->ops = ffa_ops;
+ mutex_init(&s->share_memory_msg_lock);
+ ffa_dev_set_drvdata(ffa_dev, s);
+
+ ffa_ops->mode_32bit_set(ffa_dev);
+
+ return 0;
+}
+
+static void trusty_ffa_remove(struct ffa_device *ffa_dev)
+{
+ struct trusty_ffa_state *s;
+
+ s = ffa_dev_get_drvdata(ffa_dev);
+
+ mutex_destroy(&s->share_memory_msg_lock);
+ memset(s, 0, sizeof(struct trusty_ffa_state));
+ kfree(s);
+}
+
+static struct ffa_driver trusty_ffa_driver = {
+ .name = "trusty-ffa",
+ .probe = trusty_ffa_probe,
+ .remove = trusty_ffa_remove,
+ .id_table = trusty_ffa_device_id,
+};
+
+static int __init trusty_ffa_transport_init(void)
+{
+ if (IS_REACHABLE(CONFIG_ARM_FFA_TRANSPORT)) {
+ return ffa_register(&trusty_ffa_driver);
+ } else
+ return -ENODEV;
+}
+
+static void __exit trusty_ffa_transport_exit(void)
+{
+ if (IS_REACHABLE(CONFIG_ARM_FFA_TRANSPORT))
+ ffa_unregister(&trusty_ffa_driver);
+}
+
+const struct trusty_transport_desc trusty_ffa_transport = {
+ .name = "ffa",
+ .setup = trusty_ffa_transport_setup,
+ .cleanup = trusty_ffa_transport_cleanup,
+};
+
+module_init(trusty_ffa_transport_init);
+module_exit(trusty_ffa_transport_exit);
diff --git a/drivers/trusty/trusty-ffa.h b/drivers/trusty/trusty-ffa.h
new file mode 100644
index 000000000000..267ca2c5db29
--- /dev/null
+++ b/drivers/trusty/trusty-ffa.h
@@ -0,0 +1,28 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (C) 2022 ARM Ltd.
+ */
+
+#ifndef __LINUX_TRUSTY_FFA_H
+#define __LINUX_TRUSTY_FFA_H
+
+#include <linux/types.h>
+#include <linux/uuid.h>
+#include <linux/arm_ffa.h>
+
+#define TRUSTY_FFA_VERSION_MAJOR (1U)
+#define TRUSTY_FFA_VERSION_MINOR (0U)
+#define TRUSTY_FFA_VERSION_MAJOR_SHIFT (16U)
+#define TRUSTY_FFA_VERSION_MAJOR_MASK (0x7fffU)
+#define TRUSTY_FFA_VERSION_MINOR_SHIFT (0U)
+#define TRUSTY_FFA_VERSION_MINOR_MASK (0U)
+
+#define TO_TRUSTY_FFA_MAJOR(v) \
+ ((u16)((v >> TRUSTY_FFA_VERSION_MAJOR_SHIFT) & \
+ TRUSTY_FFA_VERSION_MAJOR_MASK))
+
+#define TO_TRUSTY_FFA_MINOR(v) \
+ ((u16)((v >> TRUSTY_FFA_VERSION_MINOR_SHIFT) & \
+ TRUSTY_FFA_VERSION_MINOR_MASK))
+
+#endif /* __LINUX_TRUSTY_FFA_H */
diff --git a/drivers/trusty/trusty-private.h b/drivers/trusty/trusty-private.h
index 74b88bb8f83b..2496f397e5d2 100644
--- a/drivers/trusty/trusty-private.h
+++ b/drivers/trusty/trusty-private.h
@@ -73,5 +73,6 @@ int trusty_init_api_version(struct trusty_state *s, struct device *dev,
typedef const struct trusty_transport_desc *trusty_transports_t;
extern const struct trusty_transport_desc trusty_smc_transport;
+extern const struct trusty_transport_desc trusty_ffa_transport;
#endif /* _TRUSTY_PRIVATE_H */
diff --git a/drivers/trusty/trusty.c b/drivers/trusty/trusty.c
index ec0fccfaa24c..4686b0d34f61 100644
--- a/drivers/trusty/trusty.c
+++ b/drivers/trusty/trusty.c
@@ -509,6 +509,11 @@ trusty_transports_setup(const trusty_transports_t *transports,
return -EINVAL;
ret = transport->setup(dev);
+ if (ret == -EPROBE_DEFER) {
+ dev_notice(dev, "transport %s: defer probe\n",
+ transport->name);
+ return ret;
+ }
transports_ret &= ret;
}
@@ -672,6 +677,7 @@ static int trusty_remove(struct platform_device *pdev)
*/
static const trusty_transports_t trusty_transports[] = {
&trusty_smc_transport,
+ &trusty_ffa_transport,
NULL,
};
--
2.34.1
|