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