blob: 64653b30fac94a91338c8cd7fdac353966410453 [file] [log] [blame]
Patrick Williams8dd68482022-10-04 07:57:18 -05001From 4729efd57e260b8c02d8cd1c30a443d29885dbd1 Mon Sep 17 00:00:00 2001
2From: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
3Date: Mon, 15 Aug 2022 15:00:44 +0100
4Subject: [PATCH 09/26] arm_ffa: introduce Arm FF-A low-level driver
5
6Add the driver implementing Arm Firmware Framework for Armv8-A v1.0
7
8The Firmware Framework for Arm A-profile processors (FF-A)
9describes interfaces (ABIs) that standardize communication
10between the Secure World and Normal World leveraging TrustZone
11technology.
12
13This driver uses 64-bit registers as per SMCCCv1.2 spec and comes
14on top of the SMCCC layer. The driver provides the FF-A ABIs needed for
15querying the FF-A framework from the secure world.
16
1732-bit version of the ABIs is supported and 64-bit version of FFA_RXTX_MAP
18and FFA_MSG_SEND_DIRECT_{REQ, RESP}.
19
20In u-boot FF-A design, FF-A is considered as a discoverable bus.
21The Secure World is considered as one entity to communicate with
22using the FF-A bus. FF-A communication is handled by one device and
23one instance (the bus). This FF-A driver takes care of all the
24interactions between Normal world and Secure World.
25
26The driver exports its operations to be used by upper layers.
27
28Exported operations:
29
30- partition_info_get
31- sync_send_receive
32- rxtx_unmap
33
34This implementation provides an optional feature to copy the driver data
35to EFI runtime area.
36
37Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
38Upstream-Status: Submitted [cover letter: https://lore.kernel.org/all/20220926101723.9965-1-abdellatif.elkhlifi@arm.com/]
39---
40
41Changelog:
42===============
43
44v4:
45
46* add doc/README.ffa.drv
47* moving the FF-A driver work to drivers/firmware/arm-ffa
48* use less #ifdefs in lib/efi_loader/efi_boottime.c and replace
49 #if defined by #if CONFIG_IS_ENABLED
50* improving error handling by mapping the FF-A errors to standard errors
51 and logs
52* replacing panics with an error log and returning an error code
53* improving features discovery in FFA_FEATURES by introducing
54 rxtx_min_pages private data field
55* add ffa_remove and ffa_bind functions
56* improve how the driver behaves when bus discovery is done more than
57 once
58
59v3:
60
61* align the interfaces of the u-boot FF-A driver with those in the linux
62 FF-A driver
63* remove the FF-A helper layer
64* make the u-boot FF-A driver independent from EFI
65* provide an optional config that enables copying the driver data to EFI
66 runtime section at ExitBootServices service
67* use 64-bit version of FFA_RXTX_MAP, FFA_MSG_SEND_DIRECT_{REQ, RESP}
68
69v2:
70
71* make FF-A bus discoverable using device_{bind, probe} APIs
72* remove device tree support
73
74v1:
75
76* introduce FF-A bus driver with device tree support
77
78 MAINTAINERS | 7 +
79 common/board_r.c | 7 +
80 doc/README.ffa.drv | 160 ++
81 drivers/Kconfig | 2 +
82 drivers/Makefile | 1 +
83 drivers/firmware/arm-ffa/Kconfig | 39 +
84 drivers/firmware/arm-ffa/Makefile | 7 +
85 drivers/firmware/arm-ffa/arm-ffa-uclass.c | 16 +
86 drivers/firmware/arm-ffa/arm_ffa_prv.h | 196 +++
87 drivers/firmware/arm-ffa/core.c | 1344 +++++++++++++++++
88 .../arm-ffa/efi_ffa_runtime_data_mgr.c | 94 ++
89 include/arm_ffa.h | 127 ++
90 include/dm/uclass-id.h | 1 +
91 lib/efi_loader/efi_boottime.c | 12 +
92 14 files changed, 2013 insertions(+)
93 create mode 100644 doc/README.ffa.drv
94 create mode 100644 drivers/firmware/arm-ffa/Kconfig
95 create mode 100644 drivers/firmware/arm-ffa/Makefile
96 create mode 100644 drivers/firmware/arm-ffa/arm-ffa-uclass.c
97 create mode 100644 drivers/firmware/arm-ffa/arm_ffa_prv.h
98 create mode 100644 drivers/firmware/arm-ffa/core.c
99 create mode 100644 drivers/firmware/arm-ffa/efi_ffa_runtime_data_mgr.c
100 create mode 100644 include/arm_ffa.h
101
102diff --git a/MAINTAINERS b/MAINTAINERS
103index 7f27ff4c20..e760b4ca3a 100644
104--- a/MAINTAINERS
105+++ b/MAINTAINERS
106@@ -244,6 +244,13 @@ F: board/CZ.NIC/
107 F: configs/turris_*_defconfig
108 F: include/configs/turris_*.h
109
110+ARM FF-A
111+M: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
112+S: Maintained
113+F: doc/README.ffa.drv
114+F: drivers/firmware/arm-ffa/
115+F: include/arm_ffa.h
116+
117 ARM FREESCALE IMX
118 M: Stefano Babic <sbabic@denx.de>
119 M: Fabio Estevam <festevam@gmail.com>
120diff --git a/common/board_r.c b/common/board_r.c
121index 6f4aca2077..c75634286b 100644
122--- a/common/board_r.c
123+++ b/common/board_r.c
124@@ -63,6 +63,10 @@
125 #include <efi_loader.h>
126 #include <relocate.h>
127
128+#ifdef CONFIG_ARM_FFA_TRANSPORT
129+#include <arm_ffa.h>
130+#endif
131+
132 DECLARE_GLOBAL_DATA_PTR;
133
134 ulong monitor_flash_len;
135@@ -779,6 +783,9 @@ static init_fnc_t init_sequence_r[] = {
136 INIT_FUNC_WATCHDOG_RESET
137 initr_net,
138 #endif
139+#ifdef CONFIG_ARM_FFA_TRANSPORT
140+ ffa_bus_discover,
141+#endif
142 #ifdef CONFIG_POST
143 initr_post,
144 #endif
145diff --git a/doc/README.ffa.drv b/doc/README.ffa.drv
146new file mode 100644
147index 0000000000..1c0a33deb8
148--- /dev/null
149+++ b/doc/README.ffa.drv
150@@ -0,0 +1,160 @@
151+Arm FF-A Driver
152+====================
153+
154+Introduction
155+--------------------
156+
157+FF-A stands for Firmware Framework for Arm A-profile processors.
158+
159+FF-A specifies interfaces that enable a pair of software sandboxes to communicate with each other. A sandbox aka partition could
160+be a VM in the Normal or Secure world, an application in S-EL0, or a Trusted OS in S-EL1.
161+
162+This FF-A driver implements the interfaces to communicate with partitions in the Secure world aka Secure partitions (SPs).
163+
164+The driver specifically focuses on communicating with SPs that isolate portions of EFI runtime services that must run in a
165+protected environment which is inaccessible by the Host OS or Hypervisor. Examples of such services are set/get variables.
166+
167+FF-A driver uses the SMC ABIs defined by the FF-A specification to:
168+
169+- Discover the presence of SPs of interest.
170+- Access an SP's service through communication protocols e.g. EFI MM communication protocol.
171+
172+FF-A and SMC specifications
173+-------------------------------------------
174+
175+The current implementation of the driver relies on FF-A specification v1.0 and uses SMC32 calling convention.
176+
177+The driver has been tested with Optee OS which supports SMC32 for most of the SMC ABIs.
178+
179+For more details please refer to: https://developer.arm.com/documentation/den0077/a/?lang=en
180+
181+The FF-A driver uses 64-bit registers as per SMCCCv1.2 specification.
182+
183+For more details please refer to: https://documentation-service.arm.com/static/5f8edaeff86e16515cdbe4c6?token=
184+
185+Supported hardware
186+--------------------------------
187+
188+Aarch64 plaforms
189+
190+Configuration
191+----------------------
192+
193+CONFIG_ARM_FFA_TRANSPORT
194+ Enables the FF-A bus driver. Turn this on if you want to use FF-A communication.
195+
196+CONFIG_ARM_FFA_EFI_RUNTIME_MODE
197+ Optional config that enables EFI runtime support for FF-A data and code.
198+ ffa_copy_runtime_data allows to copy the FF-A driver data structures to EFI runtime data section.
199+ Turning the config on makes ffa_copy_runtime_data available for use and the driver code placed at EFI runtime code section.
200+ Call ffa_copy_runtime_data at the event on which you want the FF-A data to be copied (example: at ExitBootServices).
201+
202+CONFIG_SANDBOX_FFA
203+ Enables FF-A Sandbox driver. This emulates the FF-A ABIs handling under Sandbox and provides
204+ functional tests for FF-A.
205+
206+FF-A ABIs under the hood
207+---------------------------------------
208+
209+Invoking an FF-A ABI involves providing to the secure world/hypervisor the expected arguments from the ABI.
210+
211+The ABI arguments are stored in x0 to x7 registers. Then, an SMC instruction is executed.
212+
213+At the secure side level or hypervisor the ABI is handled at a higher exception level and the arguments are read and processed.
214+
215+The response is put back through x0 to x7 registers and control is giving back to the u-boot FF-A driver (non secure world).
216+
217+The driver reads the response and processes it accordingly.
218+
219+This methodology applies to all the FF-A ABIs in the driver.
220+
221+FF-A bus discovery in u-boot
222+-------------------------------------------
223+
224+When CONFIG_ARM_FFA_TRANSPORT is enabled, the FF-A bus is automatically discovered at initcall level (after u-boot relocation).
225+
226+The function that triggers the discovery process is ffa_bus_discover.
227+
228+ffa_bus_discover creates, binds and probes the arm_ffa device using device_{bind, probe} APIs.
229+
230+When the device is probed, ffa_probe is called which tries to communicate with the secure world or hypervisor.
231+
232+The FF-A bus is usable when these checks succeed:
233+
234+- querying the FF-A framework version
235+- querying from secure world the u-boot endpoint ID
236+- querying from secure world the supported features of the specified FF-A calls
237+- mapping the RX/TX buffers
238+- querying from secure world all the partitions information
239+
240+Probing fails when any of these operations fail. The FF-A bus discovery succeeds when probing is successful.
241+
242+When discovery fails the arm_ffa device is destroyed.
243+
244+The bus driver layer
245+------------------------------
246+
247+The driver comes on top of the SMCCC layer and is implemented in drivers/firmware/arm-ffa/core.c
248+
249+The driver provides the following features:
250+
251+- Support for the 32-bit version of the following ABIs:
252+
253+FFA_VERSION
254+FFA_ID_GET
255+FFA_FEATURES
256+FFA_PARTITION_INFO_GET
257+FFA_RXTX_UNMAP
258+FFA_RX_RELEASE
259+FFA_RUN
260+FFA_ERROR
261+FFA_SUCCESS
262+FFA_INTERRUPT
263+
264+- Support for the 64-bit version of the following ABIs:
265+
266+FFA_RXTX_MAP
267+FFA_MSG_SEND_DIRECT_REQ
268+FFA_MSG_SEND_DIRECT_RESP
269+
270+- Processing the received data from the secure world/hypervisor and caching it
271+
272+- Hiding from upper layers the FF-A protocol and registers details. Upper layers focus on exchanged data,
273+the driver takes care of how to transport that to the secure world/hypervisor using FF-A.
274+
275+- The driver provides callbacks to be used by clients to access the FF-A bus:
276+
277+partition_info_get
278+sync_send_receive
279+rxtx_unmap
280+
281+- FF-A bus discovery at initcalls level (after u-boot relocation). The bus is up and running if the FF-A framework is responsive and compatible with the driver.
282+
283+- When EFI is enabled, unmap the RX/TX buffers at ExitBootServices() level.
284+
285+- When CONFIG_ARM_FFA_EFI_RUNTIME_MODE enabled, ffa_copy_runtime_data function is available for use.
286+
287+Using armffa command
288+-----------------------------------
289+
290+armffa is a command showcasing how to use the FF-A driver and how to invoke its operations.
291+
292+This provides a guidance to the client developers on how to call the FF-A bus interfaces.
293+
294+Usage:
295+
296+armffa <sub-command> <arguments>
297+
298+sub-commands:
299+
300+ getpart <partition UUID>
301+
302+ lists the partition(s) info
303+
304+ ping <partition ID>
305+
306+ sends a data pattern to the specified partition
307+
308+ devlist
309+
310+ displays the arm_ffa device info
311diff --git a/drivers/Kconfig b/drivers/Kconfig
312index b26ca8cf70..4a602517bf 100644
313--- a/drivers/Kconfig
314+++ b/drivers/Kconfig
315@@ -6,6 +6,8 @@ source "drivers/core/Kconfig"
316
317 source "drivers/adc/Kconfig"
318
319+source "drivers/firmware/arm-ffa/Kconfig"
320+
321 source "drivers/ata/Kconfig"
322
323 source "drivers/axi/Kconfig"
324diff --git a/drivers/Makefile b/drivers/Makefile
325index 67c8af7442..77db8736e6 100644
326--- a/drivers/Makefile
327+++ b/drivers/Makefile
328@@ -109,6 +109,7 @@ obj-y += iommu/
329 obj-y += smem/
330 obj-y += thermal/
331 obj-$(CONFIG_TEE) += tee/
332+obj-$(CONFIG_ARM_FFA_TRANSPORT) += firmware/arm-ffa/
333 obj-y += axi/
334 obj-y += ufs/
335 obj-$(CONFIG_W1) += w1/
336diff --git a/drivers/firmware/arm-ffa/Kconfig b/drivers/firmware/arm-ffa/Kconfig
337new file mode 100644
338index 0000000000..aceb61cf49
339--- /dev/null
340+++ b/drivers/firmware/arm-ffa/Kconfig
341@@ -0,0 +1,39 @@
342+# SPDX-License-Identifier: GPL-2.0
343+
344+config ARM_FFA_TRANSPORT
345+ bool "Enable Arm Firmware Framework for Armv8-A driver"
346+ depends on DM && ARM64
347+ select ARM_SMCCC
348+ select LIB_UUID
349+ select DEVRES
350+ help
351+ The Firmware Framework for Arm A-profile processors (FF-A)
352+ describes interfaces (ABIs) that standardize communication
353+ between the Secure World and Normal World leveraging TrustZone
354+ technology.
355+
356+ This driver is based on FF-A specification v1.0 and uses SMC32
357+ calling convention.
358+
359+ FF-A specification:
360+
361+ https://developer.arm.com/documentation/den0077/a/?lang=en
362+
363+ In u-boot FF-A design, FF-A is considered as a discoverable bus.
364+ The Secure World is considered as one entity to communicate with
365+ using the FF-A bus.
366+ FF-A communication is handled by one device and one instance (the bus).
367+ This FF-A driver takes care of all the interactions between Normal world
368+ and Secure World.
369+
370+ For more details about the FF-A driver, please refer to doc/README.ffa.drv
371+
372+config ARM_FFA_EFI_RUNTIME_MODE
373+ bool "Enable EFI runtime support for FF-A data and code"
374+ depends on ARM_FFA_TRANSPORT && EFI_LOADER
375+ help
376+ Allows FF-A driver data structures and code to be accessible at EFI runtime.
377+ FF-A data is copied by ffa_copy_runtime_data function.
378+ The driver Code needed at runtime is placed at EFI runtime code section.
379+ Turning this on makes ffa_copy_runtime_data available for use and the driver
380+ code placed at EFI runtime code section.
381diff --git a/drivers/firmware/arm-ffa/Makefile b/drivers/firmware/arm-ffa/Makefile
382new file mode 100644
383index 0000000000..0b9b0a61b4
384--- /dev/null
385+++ b/drivers/firmware/arm-ffa/Makefile
386@@ -0,0 +1,7 @@
387+# SPDX-License-Identifier: GPL-2.0+
388+#
389+# (C) Copyright 2022 Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
390+#
391+
392+obj-y += arm-ffa-uclass.o core.o
393+obj-$(CONFIG_ARM_FFA_EFI_RUNTIME_MODE) += efi_ffa_runtime_data_mgr.o
394diff --git a/drivers/firmware/arm-ffa/arm-ffa-uclass.c b/drivers/firmware/arm-ffa/arm-ffa-uclass.c
395new file mode 100644
396index 0000000000..7d9695d289
397--- /dev/null
398+++ b/drivers/firmware/arm-ffa/arm-ffa-uclass.c
399@@ -0,0 +1,16 @@
400+// SPDX-License-Identifier: GPL-2.0+
401+/*
402+ * (C) Copyright 2022 ARM Limited
403+ * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
404+ */
405+
406+#include <common.h>
407+#include <dm.h>
408+#include <asm/global_data.h>
409+
410+DECLARE_GLOBAL_DATA_PTR;
411+
412+UCLASS_DRIVER(ffa) = {
413+ .name = "ffa",
414+ .id = UCLASS_FFA,
415+};
416diff --git a/drivers/firmware/arm-ffa/arm_ffa_prv.h b/drivers/firmware/arm-ffa/arm_ffa_prv.h
417new file mode 100644
418index 0000000000..7bc90f7f66
419--- /dev/null
420+++ b/drivers/firmware/arm-ffa/arm_ffa_prv.h
421@@ -0,0 +1,196 @@
422+/* SPDX-License-Identifier: GPL-2.0+ */
423+/*
424+ * (C) Copyright 2022 ARM Limited
425+ * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
426+ */
427+
428+#ifndef __ARM_FFA_PRV_H
429+#define __ARM_FFA_PRV_H
430+
431+#include <arm_ffa.h>
432+#include <linux/bitfield.h>
433+#include <linux/bitops.h>
434+#include <linux/arm-smccc.h>
435+
436+/*
437+ * This header is private. It is exclusively used by the FF-A driver
438+ */
439+
440+/* FF-A core driver name */
441+#define FFA_DRV_NAME "arm_ffa"
442+
443+/* FF-A driver version definitions */
444+
445+#define MAJOR_VERSION_MASK GENMASK(30, 16)
446+#define MINOR_VERSION_MASK GENMASK(15, 0)
447+#define GET_FFA_MAJOR_VERSION(x) \
448+ ((u16)(FIELD_GET(MAJOR_VERSION_MASK, (x))))
449+#define GET_FFA_MINOR_VERSION(x) \
450+ ((u16)(FIELD_GET(MINOR_VERSION_MASK, (x))))
451+#define PACK_VERSION_INFO(major, minor) \
452+ (FIELD_PREP(MAJOR_VERSION_MASK, (major)) | \
453+ FIELD_PREP(MINOR_VERSION_MASK, (minor)))
454+
455+#define FFA_MAJOR_VERSION (1)
456+#define FFA_MINOR_VERSION (0)
457+#define FFA_VERSION_1_0 \
458+ PACK_VERSION_INFO(FFA_MAJOR_VERSION, FFA_MINOR_VERSION)
459+
460+/* Endpoint ID mask (u-boot endpoint ID) */
461+
462+#define GET_SELF_ENDPOINT_ID_MASK GENMASK(15, 0)
463+#define GET_SELF_ENDPOINT_ID(x) \
464+ ((u16)(FIELD_GET(GET_SELF_ENDPOINT_ID_MASK, (x))))
465+
466+#define PREP_SELF_ENDPOINT_ID_MASK GENMASK(31, 16)
467+#define PREP_SELF_ENDPOINT_ID(x) \
468+ (FIELD_PREP(PREP_SELF_ENDPOINT_ID_MASK, (x)))
469+
470+/* Partition endpoint ID mask (partition with which u-boot communicates with) */
471+
472+#define PREP_PART_ENDPOINT_ID_MASK GENMASK(15, 0)
473+#define PREP_PART_ENDPOINT_ID(x) \
474+ (FIELD_PREP(PREP_PART_ENDPOINT_ID_MASK, (x)))
475+
476+/*
477+ * Definitions of the Arm FF-A interfaces supported by the Arm FF-A driver
478+ */
479+
480+#define FFA_SMC(calling_convention, func_num) \
481+ ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, (calling_convention), \
482+ ARM_SMCCC_OWNER_STANDARD, (func_num))
483+
484+#define FFA_SMC_32(func_num) FFA_SMC(ARM_SMCCC_SMC_32, (func_num))
485+#define FFA_SMC_64(func_num) FFA_SMC(ARM_SMCCC_SMC_64, (func_num))
486+
487+enum ffa_abis {
488+ FFA_ERROR = 0x60,
489+ FFA_SUCCESS = 0x61,
490+ FFA_INTERRUPT = 0x62,
491+ FFA_VERSION = 0x63,
492+ FFA_FEATURES = 0x64,
493+ FFA_RX_RELEASE = 0x65,
494+ FFA_RXTX_MAP = 0x66,
495+ FFA_RXTX_UNMAP = 0x67,
496+ FFA_PARTITION_INFO_GET = 0x68,
497+ FFA_ID_GET = 0x69,
498+ FFA_RUN = 0x6D,
499+ FFA_MSG_SEND_DIRECT_REQ = 0x6F,
500+ FFA_MSG_SEND_DIRECT_RESP = 0x70,
501+
502+ /* to be updated when adding new FFA IDs */
503+ FFA_FIRST_ID = FFA_ERROR, /* lowest number ID*/
504+ FFA_LAST_ID = FFA_MSG_SEND_DIRECT_RESP, /* highest number ID*/
505+};
506+
507+/* number of the errors supported by the FF-A specification */
508+#define MAX_NUMBER_FFA_ERR 9
509+
510+/* container structure and helper macros to map between an FF-A error and relevant error log */
511+struct ffa_abi_errmap {
512+ char *err_str[MAX_NUMBER_FFA_ERR];
513+};
514+
515+#define FFA_ERRMAP_COUNT (FFA_LAST_ID - FFA_FIRST_ID + 1)
516+#define FFA_ID_TO_ERRMAP_ID(ffa_id) ((ffa_id) - FFA_FIRST_ID)
517+
518+/* The FF-A SMC function definitions */
519+
520+typedef struct arm_smccc_1_2_regs ffa_value_t;
521+typedef void (*invoke_ffa_fn_t)(ffa_value_t args, ffa_value_t *res);
522+
523+/*
524+ * struct ffa_partition_uuid - 16 bytes UUID transmitted by FFA_PARTITION_INFO_GET
525+ * @a1-4: 32-bit words access to the UUID data
526+ *
527+ */
528+struct ffa_partition_uuid {
529+ u32 a1; /* w1 */
530+ u32 a2; /* w2 */
531+ u32 a3; /* w3 */
532+ u32 a4; /* w4 */
533+};
534+
535+/**
536+ * enum ffa_rxtx_buf_sizes - minimum sizes supported
537+ * for the RX/TX buffers
538+ */
539+enum ffa_rxtx_buf_sizes {
540+ RXTX_4K,
541+ RXTX_64K,
542+ RXTX_16K
543+};
544+
545+/**
546+ * struct ffa_rxtxpair - structure hosting the RX/TX buffers virtual addresses
547+ * @rxbuf: virtual address of the RX buffer
548+ * @txbuf: virtual address of the TX buffer
549+ * @rxtx_min_pages: RX/TX buffers minimum size in pages
550+ *
551+ * Data structure hosting the virtual addresses of the mapped RX/TX buffers
552+ * These addresses are used by the FF-A functions that use the RX/TX buffers
553+ */
554+struct ffa_rxtxpair {
555+ u64 rxbuf; /* virtual address */
556+ u64 txbuf; /* virtual address */
557+ size_t rxtx_min_pages; /* minimum number of pages in each of the RX/TX buffers */
558+};
559+
560+/**
561+ * struct ffa_partition_desc - the secure partition descriptor
562+ * @info: partition information
563+ * @sp_uuid: the secure partition UUID
564+ *
565+ * Each partition has its descriptor containing the partitions information and the UUID
566+ */
567+struct ffa_partition_desc {
568+ struct ffa_partition_info info;
569+ struct ffa_partition_uuid sp_uuid;
570+};
571+
572+/**
573+ * struct ffa_partitions - descriptors for all secure partitions
574+ * @count: The number of partitions descriptors
575+ * @descs The partitions descriptors table
576+ *
577+ * This data structure contains the partitions descriptors table
578+ */
579+struct ffa_partitions {
580+ u32 count;
581+ struct ffa_partition_desc *descs; /* virtual address */
582+};
583+
584+/**
585+ * struct ffa_prvdata - the driver private data structure
586+ *
587+ * @dev: The arm_ffa device under u-boot driver model
588+ * @ffa_ops: The driver operations structure
589+ * @fwk_version: FF-A framework version
590+ * @id: u-boot endpoint ID
591+ * @partitions: The partitions descriptors structure
592+ * @pair: The RX/TX buffers pair
593+ * @invoke_ffa_fn: The function executing the FF-A function
594+ *
595+ * The driver data structure hosting all resident data.
596+ */
597+struct ffa_prvdata {
598+ struct udevice *dev;
599+ struct ffa_bus_ops ffa_ops;
600+ u32 fwk_version;
601+ u16 id;
602+ struct ffa_partitions partitions;
603+ struct ffa_rxtxpair pair;
604+ invoke_ffa_fn_t invoke_ffa_fn;
605+};
606+
607+/**
608+ * ffa_device_get - create, bind and probe the arm_ffa device
609+ */
610+int ffa_device_get(void);
611+
612+/**
613+ * ffa_bus_prvdata_get - bus driver private data getter
614+ */
615+struct ffa_prvdata **ffa_bus_prvdata_get(void);
616+
617+#endif
618diff --git a/drivers/firmware/arm-ffa/core.c b/drivers/firmware/arm-ffa/core.c
619new file mode 100644
620index 0000000000..41c7b96e68
621--- /dev/null
622+++ b/drivers/firmware/arm-ffa/core.c
623@@ -0,0 +1,1344 @@
624+// SPDX-License-Identifier: GPL-2.0+
625+/*
626+ * (C) Copyright 2022 ARM Limited
627+ * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
628+ */
629+
630+#include "arm_ffa_prv.h"
631+#include <asm/global_data.h>
632+#include <common.h>
633+#include <dm.h>
634+#include <dm/device-internal.h>
635+#include <dm/devres.h>
636+#include <dm/root.h>
637+#include <linux/errno.h>
638+#include <linux/sizes.h>
639+#include <log.h>
640+#include <malloc.h>
641+#include <string.h>
642+#include <uuid.h>
643+
644+DECLARE_GLOBAL_DATA_PTR;
645+
646+/**
647+ * The device private data structure containing all the resident
648+ * data read from secure world
649+ */
650+__ffa_runtime_data struct ffa_prvdata *ffa_priv_data;
651+
652+/* Error mapping declarations */
653+
654+__ffa_runtime_data int ffa_to_std_errmap[MAX_NUMBER_FFA_ERR] = {
655+ 0,
656+ -EOPNOTSUPP, /* NOT_SUPPORTED */
657+ -EINVAL, /* INVALID_PARAMETERS */
658+ -ENOMEM, /* NO_MEMORY */
659+ -EBUSY, /* BUSY */
660+ -EINTR, /* INTERRUPTED */
661+ -EACCES, /* DENIED */
662+ -EAGAIN, /* RETRY */
663+ -ECANCELED, /* ABORTED */
664+};
665+
666+struct ffa_abi_errmap err_msg_map[FFA_ERRMAP_COUNT] = {
667+ [FFA_ID_TO_ERRMAP_ID(FFA_VERSION)] = {
668+ {
669+ "",
670+ "NOT_SUPPORTED: A Firmware Framework implementation does not exist",
671+ "", /* INVALID_PARAMETERS */
672+ "", /* NO_MEMORY */
673+ "", /* BUSY */
674+ "", /* INTERRUPTED */
675+ "", /* DENIED */
676+ "", /* RETRY */
677+ "", /* ABORTED */
678+ },
679+ },
680+ [FFA_ID_TO_ERRMAP_ID(FFA_ID_GET)] = {
681+ {
682+ "",
683+ "NOT_SUPPORTED: This function is not implemented at this FF-A instance",
684+ "", /* INVALID_PARAMETERS */
685+ "", /* NO_MEMORY */
686+ "", /* BUSY */
687+ "", /* INTERRUPTED */
688+ "", /* DENIED */
689+ "", /* RETRY */
690+ "", /* ABORTED */
691+ },
692+ },
693+ [FFA_ID_TO_ERRMAP_ID(FFA_FEATURES)] = {
694+ {
695+ "",
696+ "NOT_SUPPORTED: FFA_RXTX_MAP is not implemented at this FF-A instance",
697+ "", /* INVALID_PARAMETERS */
698+ "", /* NO_MEMORY */
699+ "", /* BUSY */
700+ "", /* INTERRUPTED */
701+ "", /* DENIED */
702+ "", /* RETRY */
703+ "", /* ABORTED */
704+ },
705+ },
706+ [FFA_ID_TO_ERRMAP_ID(FFA_PARTITION_INFO_GET)] = {
707+ {
708+ "",
709+ "NOT_SUPPORTED: This function is not implemented at this FF-A instance",
710+ "INVALID_PARAMETERS: Unrecognized UUID",
711+ "NO_MEMORY: Results cannot fit in RX buffer of the caller",
712+ "BUSY: RX buffer of the caller is not free",
713+ "", /* INTERRUPTED */
714+ "DENIED: Callee is not in a state to handle this request",
715+ "", /* RETRY */
716+ "", /* ABORTED */
717+ },
718+ },
719+ [FFA_ID_TO_ERRMAP_ID(FFA_RXTX_UNMAP)] = {
720+ {
721+ "",
722+ "NOT_SUPPORTED: FFA_RXTX_UNMAP is not implemented at this FF-A instance",
723+ "INVALID_PARAMETERS: No buffer pair registered on behalf of the caller",
724+ "", /* NO_MEMORY */
725+ "", /* BUSY */
726+ "", /* INTERRUPTED */
727+ "", /* DENIED */
728+ "", /* RETRY */
729+ "", /* ABORTED */
730+ },
731+ },
732+ [FFA_ID_TO_ERRMAP_ID(FFA_RX_RELEASE)] = {
733+ {
734+ "",
735+ "NOT_SUPPORTED: FFA_RX_RELEASE is not implemented at this FF-A instance",
736+ "", /* INVALID_PARAMETERS */
737+ "", /* NO_MEMORY */
738+ "", /* BUSY */
739+ "", /* INTERRUPTED */
740+ "DENIED: Caller did not have ownership of the RX buffer",
741+ "", /* RETRY */
742+ "", /* ABORTED */
743+ },
744+ },
745+ [FFA_ID_TO_ERRMAP_ID(FFA_RXTX_MAP)] = {
746+ {
747+ "",
748+ "NOT_SUPPORTED: This function is not implemented at this FF-A instance",
749+ "INVALID_PARAMETERS: Field(s) in input parameters incorrectly encoded",
750+ "NO_MEMORY: Not enough memory",
751+ "", /* BUSY */
752+ "", /* INTERRUPTED */
753+ "DENIED: Buffer pair already registered",
754+ "", /* RETRY */
755+ "", /* ABORTED */
756+ },
757+ },
758+};
759+
760+/**
761+ * ffa_to_std_errno - convert FF-A error code to standard error code
762+ * @ffa_errno: Error code returned by the FF-A ABI
763+ *
764+ * This runtime function maps the given FF-A error code as specified
765+ * by the spec to a u-boot standard error code.
766+ *
767+ * Return:
768+ *
769+ * The standard error code on success. . Otherwise, failure
770+ */
771+__ffa_runtime int ffa_to_std_errno(int ffa_errno)
772+{
773+ int err_idx = -ffa_errno;
774+
775+ /* map the FF-A error code to the standard u-boot error code */
776+ if (err_idx > 0 && err_idx < MAX_NUMBER_FFA_ERR)
777+ return ffa_to_std_errmap[err_idx];
778+ return -EINVAL;
779+}
780+
781+/**
782+ * ffa_print_error_log - print the error log corresponding to the selected FF-A ABI
783+ * @ffa_id: FF-A ABI ID
784+ * @ffa_errno: Error code returned by the FF-A ABI
785+ *
786+ * This boot time function maps the FF-A error code to the error log relevant to the
787+ * selected FF-A ABI. Then the error log is printed.
788+ *
789+ * Return:
790+ *
791+ * 0 on success. . Otherwise, failure
792+ */
793+int ffa_print_error_log(u32 ffa_id, int ffa_errno)
794+{
795+ int err_idx = -ffa_errno, abi_idx = 0;
796+
797+ /* map the FF-A error code to the corresponding error log */
798+
799+ if (err_idx <= 0 || err_idx >= MAX_NUMBER_FFA_ERR)
800+ return -EINVAL;
801+
802+ if (ffa_id < FFA_FIRST_ID || ffa_id > FFA_LAST_ID)
803+ return -EINVAL;
804+
805+ abi_idx = FFA_ID_TO_ERRMAP_ID(ffa_id);
806+ if (abi_idx < 0 || abi_idx >= FFA_ERRMAP_COUNT)
807+ return -EINVAL;
808+
809+ if (!err_msg_map[abi_idx].err_str || !err_msg_map[abi_idx].err_str[err_idx])
810+ return -EINVAL;
811+
812+ ffa_err("%s", err_msg_map[abi_idx].err_str[err_idx]);
813+
814+ return 0;
815+}
816+
817+/*
818+ * Driver core functions
819+ */
820+
821+/**
822+ * ffa_remove_device - removes the arm_ffa device
823+ * @dev: the device to be removed
824+ *
825+ * This boot time function makes sure the arm_ffa device is removed
826+ * No need to free the kmalloced data when the device is destroyed.
827+ * It's automatically done by devm management by
828+ * device_remove() -> device_free() -> devres_release_probe().
829+ *
830+ * Return:
831+ *
832+ * 0 on success. Otherwise, failure
833+ */
834+int ffa_remove_device(struct udevice *dev)
835+{
836+ int ret;
837+
838+ if (!dev) {
839+ ffa_err("no udevice found");
840+ return -ENODEV;
841+ }
842+
843+ ret = device_remove(dev, DM_REMOVE_NORMAL);
844+ if (ret) {
845+ ffa_err("unable to remove. err:%d\n", ret);
846+ return ret;
847+ }
848+
849+ ffa_info("device removed and freed");
850+
851+ ret = device_unbind(dev);
852+ if (ret) {
853+ ffa_err("unable to unbind. err:%d\n", ret);
854+ return ret;
855+ }
856+
857+ ffa_info("device unbound");
858+
859+ return 0;
860+}
861+
862+/**
863+ * ffa_device_get - create, bind and probe the arm_ffa device
864+ *
865+ * This boot time function makes sure the arm_ffa device is
866+ * created, bound to this driver, probed and ready to use.
867+ * Arm FF-A transport is implemented through a single u-boot
868+ * device managing the FF-A bus (arm_ffa).
869+ *
870+ * Return:
871+ *
872+ * 0 on success. Otherwise, failure
873+ */
874+int ffa_device_get(void)
875+{
876+ int ret;
877+ struct udevice *dev = NULL;
878+
879+ ret = device_bind(dm_root(),
880+ DM_DRIVER_GET(arm_ffa),
881+ FFA_DRV_NAME,
882+ NULL,
883+ ofnode_null(),
884+ &dev);
885+ if (ret)
886+ return ret;
887+
888+ /* The FF-A bus discovery succeeds when probing is successful */
889+ ret = device_probe(dev);
890+ if (ret) {
891+ ffa_err("arm_ffa device probing failed");
892+ ffa_remove_device(dev);
893+ return ret;
894+ }
895+
896+ return 0;
897+}
898+
899+/**
900+ * ffa_get_version - FFA_VERSION handler function
901+ *
902+ * This is the boot time function that implements FFA_VERSION FF-A function
903+ * to get from the secure world the FF-A framework version
904+ *
905+ * Return:
906+ *
907+ * 0 on success. Otherwise, failure
908+ */
909+static int ffa_get_version(void)
910+{
911+ u16 major, minor;
912+ ffa_value_t res = {0};
913+ int ffa_errno;
914+
915+ ffa_priv_data->invoke_ffa_fn((ffa_value_t){
916+ .a0 = FFA_SMC_32(FFA_VERSION),
917+ .a1 = FFA_VERSION_1_0, .a2 = 0, .a3 = 0, .a4 = 0, .a5 = 0, .a6 = 0, .a7 = 0,
918+ }, &res);
919+
920+ ffa_errno = (int)res.a0;
921+ if (ffa_errno < 0) {
922+ ffa_print_error_log(FFA_VERSION, ffa_errno);
923+ return ffa_to_std_errno(ffa_errno);
924+ }
925+
926+ major = GET_FFA_MAJOR_VERSION((u32)res.a0);
927+ minor = GET_FFA_MINOR_VERSION((u32)res.a0);
928+
929+ ffa_info("FF-A driver %d.%d\nFF-A framework %d.%d",
930+ FFA_MAJOR_VERSION, FFA_MINOR_VERSION, major, minor);
931+
932+ if ((major == FFA_MAJOR_VERSION && minor >= FFA_MINOR_VERSION)) {
933+ ffa_info("Versions are compatible ");
934+
935+ ffa_priv_data->fwk_version = (u32)res.a0;
936+
937+ return 0;
938+ }
939+
940+ ffa_err("versions are incompatible\nExpected: %d.%d , Found: %d.%d\n",
941+ FFA_MAJOR_VERSION, FFA_MINOR_VERSION, major, minor);
942+
943+ return -EPROTONOSUPPORT;
944+}
945+
946+/**
947+ * ffa_get_endpoint_id - FFA_ID_GET handler function
948+ *
949+ * This is the boot time function that implements FFA_ID_GET FF-A function
950+ * to get from the secure world u-boot endpoint ID
951+ *
952+ * Return:
953+ *
954+ * 0 on success. Otherwise, failure
955+ */
956+static int ffa_get_endpoint_id(void)
957+{
958+ ffa_value_t res = {0};
959+ int ffa_errno;
960+
961+ ffa_priv_data->invoke_ffa_fn((ffa_value_t){
962+ .a0 = FFA_SMC_32(FFA_ID_GET),
963+ .a1 = 0, .a2 = 0, .a3 = 0, .a4 = 0, .a5 = 0, .a6 = 0, .a7 = 0,
964+ }, &res);
965+
966+ if (res.a0 == FFA_SMC_32(FFA_SUCCESS)) {
967+ ffa_priv_data->id = GET_SELF_ENDPOINT_ID((u32)res.a2);
968+ ffa_info("endpoint ID is %u", ffa_priv_data->id);
969+
970+ return 0;
971+ }
972+
973+ ffa_errno = (int)res.a2;
974+
975+ ffa_print_error_log(FFA_ID_GET, ffa_errno);
976+
977+ return ffa_to_std_errno(ffa_errno);
978+}
979+
980+/**
981+ * ffa_set_rxtx_buffers_pages_cnt - sets the minimum number of pages in each of the RX/TX buffers
982+ * @prop_field: properties field obtained from FFA_FEATURES ABI
983+ *
984+ * This boot time function sets the minimum number of pages
985+ * in each of the RX/TX buffers in the private data structure
986+ *
987+ * Return:
988+ *
989+ * buf_4k_pages points to the returned number of pages
990+ * 0 on success. Otherwise, failure
991+ */
992+static int ffa_set_rxtx_buffers_pages_cnt(u32 prop_field)
993+{
994+ if (!ffa_priv_data)
995+ return -EINVAL;
996+
997+ switch (prop_field) {
998+ case RXTX_4K:
999+ ffa_priv_data->pair.rxtx_min_pages = 1;
1000+ break;
1001+ case RXTX_16K:
1002+ ffa_priv_data->pair.rxtx_min_pages = 4;
1003+ break;
1004+ case RXTX_64K:
1005+ ffa_priv_data->pair.rxtx_min_pages = 16;
1006+ break;
1007+ default:
1008+ ffa_err("RX/TX buffer size not supported");
1009+ return -EINVAL;
1010+ }
1011+
1012+ return 0;
1013+}
1014+
1015+/**
1016+ * ffa_get_rxtx_map_features - FFA_FEATURES handler function with FFA_RXTX_MAP argument
1017+ *
1018+ * This is the boot time function that implements FFA_FEATURES FF-A function
1019+ * to retrieve the FFA_RXTX_MAP features
1020+ *
1021+ * Return:
1022+ *
1023+ * 0 on success. Otherwise, failure
1024+ */
1025+static int ffa_get_rxtx_map_features(void)
1026+{
1027+ ffa_value_t res = {0};
1028+ int ffa_errno;
1029+
1030+ ffa_priv_data->invoke_ffa_fn((ffa_value_t){
1031+ .a0 = FFA_SMC_32(FFA_FEATURES),
1032+ .a1 = FFA_SMC_64(FFA_RXTX_MAP),
1033+ .a2 = 0, .a3 = 0, .a4 = 0, .a5 = 0, .a6 = 0, .a7 = 0,
1034+ }, &res);
1035+
1036+ if (res.a0 == FFA_SMC_32(FFA_SUCCESS))
1037+ return ffa_set_rxtx_buffers_pages_cnt((u32)res.a2);
1038+
1039+ ffa_errno = (int)res.a2;
1040+ ffa_print_error_log(FFA_FEATURES, ffa_errno);
1041+
1042+ return ffa_to_std_errno(ffa_errno);
1043+}
1044+
1045+/**
1046+ * ffa_free_rxtx_buffers - frees the RX/TX buffers
1047+ *
1048+ * This is the boot time function used to free the RX/TX buffers
1049+ *
1050+ */
1051+static void ffa_free_rxtx_buffers(void)
1052+{
1053+ ffa_info("Freeing RX/TX buffers");
1054+
1055+ if (ffa_priv_data->pair.rxbuf) {
1056+ free((void *)ffa_priv_data->pair.rxbuf);
1057+ ffa_priv_data->pair.rxbuf = 0;
1058+ }
1059+
1060+ if (ffa_priv_data->pair.txbuf) {
1061+ free((void *)ffa_priv_data->pair.txbuf);
1062+ ffa_priv_data->pair.txbuf = 0;
1063+ }
1064+}
1065+
1066+/**
1067+ * ffa_alloc_rxtx_buffers - allocates the RX/TX buffers
1068+ *
1069+ * This is the boot time function used by ffa_map_rxtx_buffers to allocate
1070+ * the RX/TX buffers before mapping them. The allocated memory is physically
1071+ * contiguous since memalign ends up calling malloc which allocates
1072+ * contiguous memory in u-boot.
1073+ *
1074+ * Return:
1075+ *
1076+ * 0 on success. Otherwise, failure
1077+ */
1078+static int ffa_alloc_rxtx_buffers(void)
1079+{
1080+ u64 bytes;
1081+
1082+ ffa_info("Using %lu 4KB page(s) for RX/TX buffers size",
1083+ ffa_priv_data->pair.rxtx_min_pages);
1084+
1085+ bytes = ffa_priv_data->pair.rxtx_min_pages * SZ_4K;
1086+
1087+ /* RX/TX buffers addresses should be PAGE_SIZE aligned */
1088+
1089+ ffa_priv_data->pair.rxbuf = (u64)memalign(PAGE_SIZE, bytes);
1090+ if (!ffa_priv_data->pair.rxbuf) {
1091+ ffa_err("failure to allocate RX buffer");
1092+ return -ENOBUFS;
1093+ }
1094+
1095+ ffa_info("RX buffer at virtual address 0x%llx", ffa_priv_data->pair.rxbuf);
1096+
1097+ ffa_priv_data->pair.txbuf = (u64)memalign(PAGE_SIZE, bytes);
1098+ if (!ffa_priv_data->pair.txbuf) {
1099+ free((void *)ffa_priv_data->pair.rxbuf);
1100+ ffa_priv_data->pair.rxbuf = 0;
1101+ ffa_err("failure to allocate the TX buffer");
1102+ return -ENOBUFS;
1103+ }
1104+
1105+ ffa_info("TX buffer at virtual address 0x%llx", ffa_priv_data->pair.txbuf);
1106+
1107+ /*
1108+ * make sure the buffers are cleared before use
1109+ */
1110+ memset((void *)ffa_priv_data->pair.rxbuf, 0, bytes);
1111+ memset((void *)ffa_priv_data->pair.txbuf, 0, bytes);
1112+
1113+ return 0;
1114+}
1115+
1116+/**
1117+ * ffa_map_rxtx_buffers - FFA_RXTX_MAP handler function
1118+ *
1119+ * This is the boot time function that implements FFA_RXTX_MAP FF-A function
1120+ * to map the RX/TX buffers
1121+ *
1122+ * Return:
1123+ *
1124+ * 0 on success. Otherwise, failure
1125+ */
1126+static int ffa_map_rxtx_buffers(void)
1127+{
1128+ int ret;
1129+ ffa_value_t res = {0};
1130+ int ffa_errno;
1131+
1132+ ret = ffa_alloc_rxtx_buffers();
1133+ if (ret)
1134+ return ret;
1135+
1136+ /*
1137+ * we need to pass the physical addresses of the RX/TX buffers
1138+ * in u-boot physical/virtual mapping is 1:1
1139+ *no need to convert from virtual to physical
1140+ */
1141+
1142+ ffa_priv_data->invoke_ffa_fn((ffa_value_t){
1143+ .a0 = FFA_SMC_64(FFA_RXTX_MAP),
1144+ .a1 = ffa_priv_data->pair.txbuf,
1145+ .a2 = ffa_priv_data->pair.rxbuf,
1146+ .a3 = ffa_priv_data->pair.rxtx_min_pages,
1147+ .a4 = 0, .a5 = 0, .a6 = 0, .a7 = 0,
1148+ }, &res);
1149+
1150+ if (res.a0 == FFA_SMC_32(FFA_SUCCESS)) {
1151+ ffa_info("RX/TX buffers mapped");
1152+ return 0;
1153+ }
1154+
1155+ ffa_errno = (int)res.a2;
1156+ ffa_print_error_log(FFA_RXTX_MAP, ffa_errno);
1157+
1158+ ffa_free_rxtx_buffers();
1159+
1160+ return ffa_to_std_errno(ffa_errno);
1161+}
1162+
1163+/**
1164+ * ffa_unmap_rxtx_buffers - FFA_RXTX_UNMAP handler function
1165+ *
1166+ * This is the boot time function that implements FFA_RXTX_UNMAP FF-A function
1167+ * to unmap the RX/TX buffers
1168+ *
1169+ * Return:
1170+ *
1171+ * 0 on success. Otherwise, failure
1172+ */
1173+static int ffa_unmap_rxtx_buffers(void)
1174+{
1175+ ffa_value_t res = {0};
1176+ int ffa_errno;
1177+
1178+ ffa_priv_data->invoke_ffa_fn((ffa_value_t){
1179+ .a0 = FFA_SMC_32(FFA_RXTX_UNMAP),
1180+ .a1 = PREP_SELF_ENDPOINT_ID(ffa_priv_data->id),
1181+ .a2 = 0, .a3 = 0, .a4 = 0, .a5 = 0, .a6 = 0, .a7 = 0,
1182+ }, &res);
1183+
1184+ if (res.a0 == FFA_SMC_32(FFA_SUCCESS)) {
1185+ ffa_free_rxtx_buffers();
1186+ return 0;
1187+ }
1188+
1189+ ffa_errno = (int)res.a2;
1190+ ffa_print_error_log(FFA_RXTX_UNMAP, ffa_errno);
1191+
1192+ return ffa_to_std_errno(ffa_errno);
1193+}
1194+
1195+/**
1196+ * ffa_release_rx_buffer - FFA_RX_RELEASE handler function
1197+ *
1198+ * This is the boot time function that invokes FFA_RX_RELEASE FF-A function
1199+ * to release the ownership of the RX buffer
1200+ *
1201+ * Return:
1202+ *
1203+ * 0 on success. Otherwise, failure
1204+ */
1205+static int ffa_release_rx_buffer(void)
1206+{
1207+ ffa_value_t res = {0};
1208+ int ffa_errno;
1209+
1210+ ffa_priv_data->invoke_ffa_fn((ffa_value_t){
1211+ .a0 = FFA_SMC_32(FFA_RX_RELEASE),
1212+ .a1 = 0, .a2 = 0, .a3 = 0, .a4 = 0, .a5 = 0, .a6 = 0, .a7 = 0,
1213+ }, &res);
1214+
1215+ if (res.a0 == FFA_SMC_32(FFA_SUCCESS))
1216+ return 0;
1217+
1218+ ffa_errno = (int)res.a2;
1219+ ffa_print_error_log(FFA_RX_RELEASE, ffa_errno);
1220+
1221+ return ffa_to_std_errno(ffa_errno);
1222+}
1223+
1224+/**
1225+ * ffa_uuid_are_identical - checks whether two given UUIDs are identical
1226+ * @uuid1: first UUID
1227+ * @uuid2: second UUID
1228+ *
1229+ * This is a boot time function used by ffa_read_partitions_info to search
1230+ * for a UUID in the partitions descriptors table
1231+ *
1232+ * Return:
1233+ *
1234+ * 1 when UUIDs match. Otherwise, 0
1235+ */
1236+int ffa_uuid_are_identical(const struct ffa_partition_uuid *uuid1,
1237+ const struct ffa_partition_uuid *uuid2)
1238+{
1239+ if (!uuid1 || !uuid2)
1240+ return 0;
1241+
1242+ return (!memcmp(uuid1, uuid2, sizeof(struct ffa_partition_uuid)));
1243+}
1244+
1245+/**
1246+ * ffa_read_partitions_info - reads the data queried by FFA_PARTITION_INFO_GET
1247+ * and saves it in the private structure
1248+ * @count: The number of partitions queried
1249+ * @part_uuid: Pointer to the partition(s) UUID
1250+ *
1251+ * This is the boot time function that reads the partitions information
1252+ * returned by the FFA_PARTITION_INFO_GET and saves it in the private
1253+ * data structure.
1254+ *
1255+ * Return:
1256+ *
1257+ * The private data structure is updated with the partition(s) information
1258+ * 0 is returned on success. Otherwise, failure
1259+ */
1260+static int ffa_read_partitions_info(u32 count, struct ffa_partition_uuid *part_uuid)
1261+{
1262+ if (!count) {
1263+ ffa_err("no partition detected");
1264+ return -ENODATA;
1265+ }
1266+
1267+ ffa_info("Reading partitions data from the RX buffer");
1268+
1269+ if (!part_uuid) {
1270+ /*
1271+ * querying information of all partitions
1272+ */
1273+ u64 buf_bytes;
1274+ u64 data_bytes;
1275+ u32 desc_idx;
1276+ struct ffa_partition_info *parts_info;
1277+
1278+ data_bytes = count * sizeof(struct ffa_partition_desc);
1279+
1280+ buf_bytes = ffa_priv_data->pair.rxtx_min_pages * SZ_4K;
1281+
1282+ if (data_bytes > buf_bytes) {
1283+ ffa_err("partitions data size exceeds the RX buffer size:");
1284+ ffa_err(" sizes in bytes: data %llu , RX buffer %llu ",
1285+ data_bytes,
1286+ buf_bytes);
1287+
1288+ return -ENOMEM;
1289+ }
1290+
1291+ ffa_priv_data->partitions.descs = (struct ffa_partition_desc *)
1292+ devm_kmalloc(ffa_priv_data->dev, data_bytes, __GFP_ZERO);
1293+ if (!ffa_priv_data->partitions.descs) {
1294+ ffa_err("cannot allocate partitions data buffer");
1295+ return -ENOMEM;
1296+ }
1297+
1298+ parts_info = (struct ffa_partition_info *)ffa_priv_data->pair.rxbuf;
1299+
1300+ for (desc_idx = 0 ; desc_idx < count ; desc_idx++) {
1301+ ffa_priv_data->partitions.descs[desc_idx].info =
1302+ parts_info[desc_idx];
1303+
1304+ ffa_info("Partition ID %x : info cached",
1305+ ffa_priv_data->partitions.descs[desc_idx].info.id);
1306+ }
1307+
1308+ ffa_priv_data->partitions.count = count;
1309+
1310+ ffa_info("%d partition(s) found and cached", count);
1311+
1312+ } else {
1313+ u32 rx_desc_idx, cached_desc_idx;
1314+ struct ffa_partition_info *parts_info;
1315+ u8 desc_found;
1316+
1317+ parts_info = (struct ffa_partition_info *)ffa_priv_data->pair.rxbuf;
1318+
1319+ /*
1320+ * search for the SP IDs read from the RX buffer
1321+ * in the already cached SPs.
1322+ * Update the UUID when ID found.
1323+ */
1324+ for (rx_desc_idx = 0; rx_desc_idx < count ; rx_desc_idx++) {
1325+ desc_found = 0;
1326+
1327+ /*
1328+ * search the current ID in the cached partitions
1329+ */
1330+ for (cached_desc_idx = 0;
1331+ cached_desc_idx < ffa_priv_data->partitions.count;
1332+ cached_desc_idx++) {
1333+ /*
1334+ * save the UUID
1335+ */
1336+ if (ffa_priv_data->partitions.descs[cached_desc_idx].info.id ==
1337+ parts_info[rx_desc_idx].id) {
1338+ ffa_priv_data->partitions.descs[cached_desc_idx].sp_uuid =
1339+ *part_uuid;
1340+
1341+ desc_found = 1;
1342+ break;
1343+ }
1344+ }
1345+
1346+ if (!desc_found)
1347+ return -ENODATA;
1348+ }
1349+ }
1350+
1351+ return 0;
1352+}
1353+
1354+/**
1355+ * ffa_query_partitions_info - invokes FFA_PARTITION_INFO_GET and saves partitions data
1356+ *
1357+ * @part_uuid: Pointer to the partition(s) UUID
1358+ * @pcount: Pointer to the number of partitions variable filled when querying
1359+ *
1360+ * This is the boot time function that executes the FFA_PARTITION_INFO_GET
1361+ * to query the partitions data. Then, it calls ffa_read_partitions_info
1362+ * to save the data in the private data structure.
1363+ *
1364+ * After reading the data the RX buffer is released using ffa_release_rx_buffer
1365+ *
1366+ * Return:
1367+ *
1368+ * When part_uuid is NULL, all partitions data are retrieved from secure world
1369+ * When part_uuid is non NULL, data for partitions matching the given UUID are
1370+ * retrieved and the number of partitions is returned
1371+ * 0 is returned on success. Otherwise, failure
1372+ */
1373+static int ffa_query_partitions_info(struct ffa_partition_uuid *part_uuid,
1374+ u32 *pcount)
1375+{
1376+ struct ffa_partition_uuid query_uuid = {0};
1377+ ffa_value_t res = {0};
1378+ int ffa_errno;
1379+
1380+ /*
1381+ * If a UUID is specified. Information for one or more
1382+ * partitions in the system is queried. Otherwise, information
1383+ * for all installed partitions is queried
1384+ */
1385+
1386+ if (part_uuid) {
1387+ if (!pcount)
1388+ return -EINVAL;
1389+
1390+ query_uuid = *part_uuid;
1391+ } else if (pcount) {
1392+ return -EINVAL;
1393+ }
1394+
1395+ ffa_priv_data->invoke_ffa_fn((ffa_value_t){
1396+ .a0 = FFA_SMC_32(FFA_PARTITION_INFO_GET),
1397+ .a1 = query_uuid.a1,
1398+ .a2 = query_uuid.a2,
1399+ .a3 = query_uuid.a3,
1400+ .a4 = query_uuid.a4,
1401+ .a5 = 0,
1402+ .a6 = 0,
1403+ .a7 = 0,
1404+ }, &res);
1405+
1406+ if (res.a0 == FFA_SMC_32(FFA_SUCCESS)) {
1407+ int ret;
1408+
1409+ /*
1410+ * res.a2 contains the count of partition information descriptors
1411+ * populated in the RX buffer
1412+ */
1413+ if (res.a2) {
1414+ ret = ffa_read_partitions_info((u32)res.a2, part_uuid);
1415+ if (ret) {
1416+ ffa_err("failed to read partition(s) data , error (%d)", ret);
1417+ ffa_release_rx_buffer();
1418+ return -EINVAL;
1419+ }
1420+ }
1421+
1422+ /*
1423+ * return the SP count (when querying using a UUID)
1424+ */
1425+ if (pcount)
1426+ *pcount = (u32)res.a2;
1427+
1428+ /*
1429+ * After calling FFA_PARTITION_INFO_GET the buffer ownership
1430+ * is assigned to the consumer (u-boot). So, we need to give
1431+ * the ownership back to the SPM or hypervisor
1432+ */
1433+ ret = ffa_release_rx_buffer();
1434+
1435+ return ret;
1436+ }
1437+
1438+ ffa_errno = (int)res.a2;
1439+ ffa_print_error_log(FFA_PARTITION_INFO_GET, ffa_errno);
1440+
1441+ return ffa_to_std_errno(ffa_errno);
1442+}
1443+
1444+/**
1445+ * ffa_get_partitions_info - FFA_PARTITION_INFO_GET handler function
1446+ *
1447+ * The passed arguments:
1448+ * Mode 1: When getting from the driver the number of
1449+ * secure partitions:
1450+ * @uuid_str: pointer to the UUID string
1451+ * @parts_size: pointer to the variable that contains the number of partitions
1452+ * The variable will be set by the driver
1453+ * @buffer: NULL
1454+ *
1455+ * Mode 2: When requesting the driver to return the
1456+ * partitions information:
1457+ * @uuid_str: pointer to the UUID string
1458+ * @parts_size: pointer to the size of the SPs information buffer in bytes
1459+ * @buffer: pointer to SPs information buffer
1460+ * (allocated by the client).
1461+ * The buffer will be filled by the driver
1462+ *
1463+ * This is the boot time function that queries the secure partition data from
1464+ * the private data structure. If not found, it invokes FFA_PARTITION_INFO_GET
1465+ * FF-A function to query the partition information from secure world.
1466+ *
1467+ * A client of the FF-A driver should know the UUID of the service it wants to
1468+ * access. It should use the UUID to request the FF-A driver to provide the
1469+ * partition(s) information of the service. The FF-A driver uses
1470+ * PARTITION_INFO_GET to obtain this information. This is implemented through
1471+ * ffa_get_partitions_info function.
1472+ * A new FFA_PARTITION_INFO_GET call is issued (first one performed through
1473+ * ffa_cache_partitions_info) allowing to retrieve the partition(s) information.
1474+ * They are not saved (already done). We only update the UUID in the cached area.
1475+ * This assumes that partitions data does not change in the secure world.
1476+ * Otherwise u-boot will have an outdated partition data. The benefit of caching
1477+ * the information in the FF-A driver is to accommodate discovery after
1478+ * ExitBootServices().
1479+ *
1480+ * When invoked through a client request, ffa_get_partitions_info should be
1481+ * called twice. First call is to get from the driver the number of secure
1482+ * partitions (SPs) associated to a particular UUID.
1483+ * Then, the caller (client) allocates the buffer to host the SPs data and
1484+ * issues a 2nd call. Then, the driver fills the SPs data in the pre-allocated
1485+ * buffer.
1486+ *
1487+ * To achieve the mechanism described above, ffa_get_partitions_info uses the
1488+ * following functions:
1489+ * ffa_read_partitions_info
1490+ * ffa_query_partitions_info
1491+ *
1492+ * Return:
1493+ *
1494+ * @parts_size: When pointing to the number of partitions variable, the number is
1495+ * set by the driver.
1496+ * When pointing to the partitions information buffer size, the buffer will be
1497+ * filled by the driver.
1498+ *
1499+ * On success 0 is returned. Otherwise, failure
1500+ */
1501+static int ffa_get_partitions_info(const char *uuid_str,
1502+ u32 *parts_size, struct ffa_partition_info *buffer)
1503+{
1504+ /*
1505+ * fill_data:
1506+ * 0: return the SP count
1507+ * 1: fill SP data and return it to the caller
1508+ * -1: undefined mode
1509+ */
1510+ int fill_data = -1;
1511+ u32 desc_idx, client_desc_idx;
1512+ struct ffa_partition_uuid part_uuid = {0};
1513+ u32 client_desc_max_cnt;
1514+ u32 parts_found = 0;
1515+
1516+ if (!ffa_priv_data->partitions.count || !ffa_priv_data->partitions.descs) {
1517+ ffa_err("no partition installed");
1518+ return -EINVAL;
1519+ }
1520+
1521+ if (!uuid_str) {
1522+ ffa_err("no UUID provided");
1523+ return -EINVAL;
1524+ }
1525+
1526+ if (!parts_size) {
1527+ ffa_err("no size/count provided");
1528+ return -EINVAL;
1529+ }
1530+
1531+ if (be_uuid_str_to_le_bin(uuid_str, (unsigned char *)&part_uuid)) {
1532+ ffa_err("invalid UUID");
1533+ return -EINVAL;
1534+ }
1535+
1536+ if (!buffer) {
1537+ /* Mode 1: getting the number of secure partitions */
1538+
1539+ fill_data = 0;
1540+
1541+ ffa_info("Preparing for checking partitions count");
1542+
1543+ } else if ((*parts_size >= sizeof(struct ffa_partition_info)) &&
1544+ !(*parts_size % sizeof(struct ffa_partition_info))) {
1545+ /* Mode 2: retrieving the partitions information */
1546+
1547+ fill_data = 1;
1548+
1549+ client_desc_idx = 0;
1550+
1551+ /*
1552+ * number of empty descriptors preallocated by the caller
1553+ */
1554+ client_desc_max_cnt = *parts_size / sizeof(struct ffa_partition_info);
1555+
1556+ ffa_info("Preparing for filling partitions info");
1557+
1558+ } else {
1559+ ffa_err("invalid function arguments provided");
1560+ return -EINVAL;
1561+ }
1562+
1563+ ffa_info("Searching partitions using the provided UUID");
1564+
1565+ /*
1566+ * search in the cached partitions
1567+ */
1568+ for (desc_idx = 0;
1569+ desc_idx < ffa_priv_data->partitions.count;
1570+ desc_idx++) {
1571+ if (ffa_uuid_are_identical(&ffa_priv_data->partitions.descs[desc_idx].sp_uuid,
1572+ &part_uuid)) {
1573+ ffa_info("Partition ID %x matches the provided UUID",
1574+ ffa_priv_data->partitions.descs[desc_idx].info.id);
1575+
1576+ parts_found++;
1577+
1578+ if (fill_data) {
1579+ /*
1580+ * trying to fill the partition info in the input buffer
1581+ */
1582+
1583+ if (client_desc_idx < client_desc_max_cnt) {
1584+ buffer[client_desc_idx++] =
1585+ ffa_priv_data->partitions.descs[desc_idx].info;
1586+ continue;
1587+ }
1588+
1589+ ffa_err("failed to fill the current descriptor client buffer full");
1590+ return -ENOBUFS;
1591+ }
1592+ }
1593+ }
1594+
1595+ if (!parts_found) {
1596+ int ret;
1597+
1598+ ffa_info("No partition found. Querying framework ...");
1599+
1600+ ret = ffa_query_partitions_info(&part_uuid, &parts_found);
1601+
1602+ if (ret == 0) {
1603+ if (!fill_data) {
1604+ *parts_size = parts_found;
1605+
1606+ ffa_info("Number of partition(s) found matching the UUID: %d",
1607+ parts_found);
1608+ } else {
1609+ /*
1610+ * If SPs data detected, they are already in the private data
1611+ * structure, retry searching SP data again to return them
1612+ * to the caller
1613+ */
1614+ if (parts_found)
1615+ ret = ffa_get_partitions_info(uuid_str, parts_size, buffer);
1616+ else
1617+ ret = -ENODATA;
1618+ }
1619+ }
1620+
1621+ return ret;
1622+ }
1623+
1624+ /* partition(s) found */
1625+ if (!fill_data)
1626+ *parts_size = parts_found;
1627+
1628+ return 0;
1629+}
1630+
1631+/**
1632+ * ffa_cache_partitions_info - Queries and saves all secure partitions data
1633+ *
1634+ * This is a boot time function that invokes FFA_PARTITION_INFO_GET FF-A
1635+ * function to query from secure world all partitions information.
1636+ *
1637+ * The FFA_PARTITION_INFO_GET call is issued with nil UUID as an argument.
1638+ * All installed partitions information are returned. We cache them in the
1639+ * resident private data structure and we keep the UUID field empty
1640+ * (in FF-A 1.0 UUID is not provided by the partition descriptor)
1641+ *
1642+ * This function is called at the device probing level.
1643+ * ffa_cache_partitions_info uses ffa_query_partitions_info to get the data
1644+ *
1645+ * Return:
1646+ *
1647+ * 0 on success. Otherwise, failure
1648+ */
1649+static int ffa_cache_partitions_info(void)
1650+{
1651+ return ffa_query_partitions_info(NULL, NULL);
1652+}
1653+
1654+/**
1655+ * ffa_msg_send_direct_req - FFA_MSG_SEND_DIRECT_{REQ,RESP} handler function
1656+ * @dst_part_id: destination partition ID
1657+ * @msg: pointer to the message data preallocated by the client (in/out)
1658+ *
1659+ * This is the runtime function that implements FFA_MSG_SEND_DIRECT_{REQ,RESP}
1660+ * FF-A functions.
1661+ *
1662+ * FFA_MSG_SEND_DIRECT_REQ is used to send the data to the secure partition.
1663+ * The response from the secure partition is handled by reading the
1664+ * FFA_MSG_SEND_DIRECT_RESP arguments.
1665+ *
1666+ * The maximum size of the data that can be exchanged is 40 bytes which is
1667+ * sizeof(struct ffa_send_direct_data) as defined by the FF-A specification 1.0
1668+ * in the section relevant to FFA_MSG_SEND_DIRECT_{REQ,RESP}
1669+ *
1670+ * Return:
1671+ *
1672+ * 0 on success. Otherwise, failure
1673+ */
1674+static int __ffa_runtime ffa_msg_send_direct_req(u16 dst_part_id, struct ffa_send_direct_data *msg)
1675+{
1676+ ffa_value_t res = {0};
1677+ int ffa_errno;
1678+
1679+ if (!ffa_priv_data || !ffa_priv_data->invoke_ffa_fn)
1680+ return -EINVAL;
1681+
1682+ /* No partition installed */
1683+ if (!ffa_priv_data->partitions.count || !ffa_priv_data->partitions.descs)
1684+ return -ENODEV;
1685+
1686+ ffa_priv_data->invoke_ffa_fn((ffa_value_t){
1687+ .a0 = FFA_SMC_64(FFA_MSG_SEND_DIRECT_REQ),
1688+ .a1 = PREP_SELF_ENDPOINT_ID(ffa_priv_data->id) |
1689+ PREP_PART_ENDPOINT_ID(dst_part_id),
1690+ .a2 = 0,
1691+ .a3 = msg->data0,
1692+ .a4 = msg->data1,
1693+ .a5 = msg->data2,
1694+ .a6 = msg->data3,
1695+ .a7 = msg->data4,
1696+ }, &res);
1697+
1698+ while (res.a0 == FFA_SMC_32(FFA_INTERRUPT))
1699+ ffa_priv_data->invoke_ffa_fn((ffa_value_t){
1700+ .a0 = FFA_SMC_32(FFA_RUN),
1701+ .a1 = res.a1, .a2 = 0, .a3 = 0, .a4 = 0, .a5 = 0, .a6 = 0, .a7 = 0,
1702+ }, &res);
1703+
1704+ if (res.a0 == FFA_SMC_32(FFA_SUCCESS)) {
1705+ /* Message sent with no response */
1706+ return 0;
1707+ }
1708+
1709+ if (res.a0 == FFA_SMC_64(FFA_MSG_SEND_DIRECT_RESP)) {
1710+ /*
1711+ * Message sent with response
1712+ * extract the return data
1713+ */
1714+ msg->data0 = res.a3;
1715+ msg->data1 = res.a4;
1716+ msg->data2 = res.a5;
1717+ msg->data3 = res.a6;
1718+ msg->data4 = res.a7;
1719+
1720+ return 0;
1721+ }
1722+
1723+ ffa_errno = (int)res.a2;
1724+ return ffa_to_std_errno(ffa_errno);
1725+}
1726+
1727+/**
1728+ * __arm_ffa_fn_smc - SMC wrapper
1729+ * @args: FF-A ABI arguments to be copied to Xn registers
1730+ * @res: FF-A ABI return data to be copied from Xn registers
1731+ *
1732+ * Calls low level SMC assembly function
1733+ *
1734+ * Return: void
1735+ */
1736+void __ffa_runtime __arm_ffa_fn_smc(ffa_value_t args, ffa_value_t *res)
1737+{
1738+ arm_smccc_1_2_smc(&args, res);
1739+}
1740+
1741+/**
1742+ * ffa_set_smc_conduit - Set the SMC conduit
1743+ *
1744+ * This boot time function selects the SMC conduit by setting the driver invoke function
1745+ * to SMC assembly function
1746+ *
1747+ * Return:
1748+ *
1749+ * 0 on success. Otherwise, failure
1750+ */
1751+static int ffa_set_smc_conduit(void)
1752+{
1753+ ffa_priv_data->invoke_ffa_fn = __arm_ffa_fn_smc;
1754+
1755+ if (!ffa_priv_data->invoke_ffa_fn) {
1756+ ffa_err("failure to set the invoke function");
1757+ return -EINVAL;
1758+ }
1759+
1760+ ffa_info("Conduit is SMC");
1761+
1762+ return 0;
1763+}
1764+
1765+/**
1766+ * ffa_set_bus_ops - Set the bus driver operations
1767+ *
1768+ * Setting the driver callbacks.
1769+ *
1770+ */
1771+static void ffa_set_bus_ops(void)
1772+{
1773+ ffa_priv_data->ffa_ops.partition_info_get = ffa_get_partitions_info;
1774+ ffa_priv_data->ffa_ops.sync_send_receive = ffa_msg_send_direct_req;
1775+ ffa_priv_data->ffa_ops.rxtx_unmap = ffa_unmap_rxtx_buffers;
1776+}
1777+
1778+/**
1779+ * ffa_alloc_prvdata - allocate the driver main data structure and sets the device
1780+ * @dev: the arm_ffa device
1781+ *
1782+ * This boot time function creates the main data structure embedding all the driver data.
1783+ *
1784+ * Return:
1785+ *
1786+ * 0 on success. Otherwise, failure
1787+ */
1788+static int ffa_alloc_prvdata(struct udevice *dev)
1789+{
1790+ if (!dev) {
1791+ ffa_err("no udevice found");
1792+ return -ENODEV;
1793+ }
1794+
1795+ /* The device is registered with the DM. Let's create the driver main data structure*/
1796+
1797+ ffa_priv_data = devm_kmalloc(dev, sizeof(struct ffa_prvdata), __GFP_ZERO);
1798+ if (!ffa_priv_data) {
1799+ ffa_err("can not allocate the driver main data structure");
1800+ return -ENOMEM;
1801+ }
1802+
1803+ ffa_priv_data->dev = dev;
1804+
1805+ return 0;
1806+}
1807+
1808+/**
1809+ * ffa_probe - The driver probe function
1810+ * @dev: the arm_ffa device
1811+ *
1812+ * Probing is done at boot time and triggered by the uclass device discovery.
1813+ * At probe level the following actions are done:
1814+ * - setting the conduit
1815+ * - querying the FF-A framework version
1816+ * - querying from secure world the u-boot endpoint ID
1817+ * - querying from secure world the supported features of FFA_RXTX_MAP
1818+ * - mapping the RX/TX buffers
1819+ * - querying from secure world all the partitions information
1820+ *
1821+ * All data queried from secure world is saved in the resident private data structure.
1822+ *
1823+ * The probe will fail if either FF-A framework is not detected or the
1824+ * FF-A requests are not behaving correctly. This ensures that the
1825+ * driver is not installed and its operations are not exported to the clients.
1826+ *
1827+ * Return:
1828+ *
1829+ * 0 on success. Otherwise, failure
1830+ */
1831+static int ffa_probe(struct udevice *dev)
1832+{
1833+ int ret;
1834+
1835+ ret = ffa_alloc_prvdata(dev);
1836+ if (ret != 0)
1837+ return ret;
1838+
1839+ ffa_set_bus_ops();
1840+
1841+ ret = ffa_set_smc_conduit();
1842+ if (ret != 0)
1843+ return ret;
1844+
1845+ ret = ffa_get_version();
1846+ if (ret != 0)
1847+ return ret;
1848+
1849+ ret = ffa_get_endpoint_id();
1850+ if (ret != 0)
1851+ return ret;
1852+
1853+ ret = ffa_get_rxtx_map_features();
1854+ if (ret != 0)
1855+ return ret;
1856+
1857+ ret = ffa_map_rxtx_buffers();
1858+ if (ret != 0)
1859+ return ret;
1860+
1861+ ret = ffa_cache_partitions_info();
1862+ if (ret != 0) {
1863+ ffa_free_rxtx_buffers();
1864+ return ret;
1865+ }
1866+
1867+ return 0;
1868+}
1869+
1870+/**
1871+ * ffa_remove - The driver remove function
1872+ * @dev: the arm_ffa device
1873+ * When the device is about to be removed , unmap the RX/TX buffers and free the memory
1874+ * Return:
1875+ *
1876+ * 0 on success.
1877+ */
1878+static int ffa_remove(struct udevice *dev)
1879+{
1880+ ffa_info("removing the device");
1881+
1882+ ffa_unmap_rxtx_buffers();
1883+
1884+ if (ffa_priv_data->pair.rxbuf || ffa_priv_data->pair.txbuf)
1885+ ffa_free_rxtx_buffers();
1886+
1887+ return 0;
1888+}
1889+
1890+/**
1891+ * ffa_unbind - The driver unbind function
1892+ * @dev: the arm_ffa device
1893+ * After the device is removed and memory freed the device is unbound
1894+ * Return:
1895+ *
1896+ * 0 on success.
1897+ */
1898+static int ffa_unbind(struct udevice *dev)
1899+{
1900+ ffa_info("unbinding the device , private data already released");
1901+
1902+ ffa_priv_data = NULL;
1903+
1904+ return 0;
1905+}
1906+
1907+/**
1908+ * ffa_bus_ops_get - bus driver operations getter
1909+ *
1910+ * Return:
1911+ * This runtime function returns a pointer to the driver operations structure
1912+ */
1913+const struct ffa_bus_ops * __ffa_runtime ffa_bus_ops_get(void)
1914+{
1915+ return &ffa_priv_data->ffa_ops;
1916+}
1917+
1918+/**
1919+ * ffa_bus_prvdata_get - bus driver private data getter
1920+ *
1921+ * Return:
1922+ * This boot time function returns a pointer to the main private data structure
1923+ */
1924+struct ffa_prvdata **ffa_bus_prvdata_get(void)
1925+{
1926+ return &ffa_priv_data;
1927+}
1928+
1929+/**
1930+ * ffa_bus_discover - discover FF-A bus and probe the arm_ffa device
1931+ *
1932+ * This boot time function makes sure the FF-A bus is discoverable.
1933+ * Then, the arm_ffa device is probed and ready to use.
1934+ * This function is called automatically at initcalls
1935+ * level (after u-boot relocation).
1936+ *
1937+ * When the bus was already discovered successfully the discovery will not run again.
1938+ *
1939+ * Arm FF-A transport is implemented through arm_ffa u-boot device managing the FF-A
1940+ * communication.
1941+ * All FF-A clients should use the arm_ffa device to use the FF-A transport.
1942+ *
1943+ * Return:
1944+ *
1945+ * 0 on success. Otherwise, failure
1946+ */
1947+int ffa_bus_discover(void)
1948+{
1949+ int ret = 0;
1950+
1951+ if (!ffa_priv_data)
1952+ ret = ffa_device_get();
1953+
1954+ return ret;
1955+}
1956+
1957+/**
1958+ * Declaring the arm_ffa driver under UCLASS_FFA
1959+ */
1960+
1961+U_BOOT_DRIVER(arm_ffa) = {
1962+ .name = FFA_DRV_NAME,
1963+ .id = UCLASS_FFA,
1964+ .probe = ffa_probe,
1965+ .remove = ffa_remove,
1966+ .unbind = ffa_unbind,
1967+};
1968diff --git a/drivers/firmware/arm-ffa/efi_ffa_runtime_data_mgr.c b/drivers/firmware/arm-ffa/efi_ffa_runtime_data_mgr.c
1969new file mode 100644
1970index 0000000000..c76cf2147b
1971--- /dev/null
1972+++ b/drivers/firmware/arm-ffa/efi_ffa_runtime_data_mgr.c
1973@@ -0,0 +1,94 @@
1974+// SPDX-License-Identifier: GPL-2.0+
1975+/*
1976+ * (C) Copyright 2022 ARM Limited
1977+ * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
1978+ */
1979+
1980+#include "arm_ffa_prv.h"
1981+
1982+/**
1983+ * ffa_copy_runtime_data - copy the private data structure to the runtime area
1984+ *
1985+ * This boot time function copies the arm_ffa driver data structures including
1986+ * partitions data to the EFI runtime data section.
1987+ *
1988+ * Return:
1989+ *
1990+ * 0 on success. Otherwise, failure
1991+ */
1992+efi_status_t ffa_copy_runtime_data(void)
1993+{
1994+ efi_status_t efi_ret;
1995+ efi_uintn_t prvdata_pages;
1996+ efi_uintn_t descs_pages;
1997+ struct ffa_prvdata **prvdata = NULL; /* Pointer to the current structure */
1998+ struct ffa_prvdata *runtime_prvdata = NULL; /* Pointer to the structure runtime copy */
1999+ u64 runtime_descs = 0;
2000+
2001+ prvdata = ffa_bus_prvdata_get();
2002+
2003+ printf("INFO: EFI: FFA: prv data area at 0x%llx\n", (u64)prvdata);
2004+
2005+ /* allocate private data runtime area */
2006+
2007+ prvdata_pages = efi_size_in_pages(sizeof(struct ffa_prvdata));
2008+ efi_ret = efi_allocate_pages(EFI_ALLOCATE_ANY_PAGES,
2009+ EFI_RUNTIME_SERVICES_DATA,
2010+ prvdata_pages,
2011+ (u64 *)&runtime_prvdata);
2012+
2013+ if (efi_ret != EFI_SUCCESS) {
2014+ printf("ERROR: EFI: FFA: allocating runtime data (err: 0x%lx, addr 0x%llx)\n",
2015+ efi_ret, (u64)runtime_prvdata);
2016+
2017+ return efi_ret;
2018+ }
2019+
2020+ printf("INFO: EFI: FFA: runtime data area at 0x%llx\n", (u64)runtime_prvdata);
2021+
2022+ if (!runtime_prvdata)
2023+ return EFI_INVALID_PARAMETER;
2024+
2025+ /* allocate the partition data runtime area */
2026+
2027+ descs_pages = efi_size_in_pages((*prvdata)->partitions.count *
2028+ sizeof(struct ffa_partition_desc));
2029+ efi_ret = efi_allocate_pages(EFI_ALLOCATE_ANY_PAGES,
2030+ EFI_RUNTIME_SERVICES_DATA,
2031+ descs_pages,
2032+ &runtime_descs);
2033+
2034+ if (efi_ret != EFI_SUCCESS) {
2035+ printf("ERROR: EFI: FFA: allocating runtime SPs data (err: 0x%lx, addr 0x%llx)\n",
2036+ efi_ret, runtime_descs);
2037+
2038+ efi_free_pages((u64)runtime_prvdata, prvdata_pages);
2039+
2040+ return efi_ret;
2041+ }
2042+
2043+ printf("INFO: EFI: FFA: SPs runtime area at 0x%llx\n", (u64)runtime_descs);
2044+
2045+ if (!runtime_descs)
2046+ return EFI_INVALID_PARAMETER;
2047+
2048+ *runtime_prvdata = **prvdata;
2049+
2050+ runtime_prvdata->dev = NULL;
2051+ runtime_prvdata->ffa_ops.partition_info_get = NULL;
2052+ runtime_prvdata->ffa_ops.rxtx_unmap = NULL;
2053+ runtime_prvdata->partitions.descs = (struct ffa_partition_desc *)runtime_descs;
2054+ runtime_prvdata->pair.rxbuf = 0;
2055+ runtime_prvdata->pair.txbuf = 0;
2056+
2057+ /*
2058+ * Update the private data structure pointer in the driver
2059+ * no need to free the old structure. devm takes care of that
2060+ */
2061+ *prvdata = runtime_prvdata;
2062+
2063+ printf("INFO: EFI: FFA: runtime prv data now at 0x%llx , SPs count %d\n",
2064+ (u64)*prvdata, (*prvdata)->partitions.count);
2065+
2066+ return 0;
2067+}
2068diff --git a/include/arm_ffa.h b/include/arm_ffa.h
2069new file mode 100644
2070index 0000000000..f17b100497
2071--- /dev/null
2072+++ b/include/arm_ffa.h
2073@@ -0,0 +1,127 @@
2074+/* SPDX-License-Identifier: GPL-2.0+ */
2075+/*
2076+ * (C) Copyright 2022 ARM Limited
2077+ * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
2078+ */
2079+
2080+#ifndef __ARM_FFA_H
2081+#define __ARM_FFA_H
2082+
2083+#include <linux/printk.h>
2084+
2085+/*
2086+ * This header is public. It can be used by clients to access
2087+ * data structures and definitions they need
2088+ */
2089+
2090+/*
2091+ * Macros for displaying logs
2092+ */
2093+
2094+#define ffa_info(fmt, ...) pr_info("[FFA] " fmt "\n", ##__VA_ARGS__)
2095+#define ffa_err(fmt, ...) pr_err("[FFA] " fmt "\n", ##__VA_ARGS__)
2096+
2097+/*
2098+ * struct ffa_partition_info - Partition information descriptor
2099+ * @id: Partition ID
2100+ * @exec_ctxt: Execution context count
2101+ * @properties: Partition properties
2102+ *
2103+ * Data structure containing information about partitions instantiated in the system
2104+ * This structure is filled with the data queried by FFA_PARTITION_INFO_GET
2105+ */
2106+struct __packed ffa_partition_info {
2107+ u16 id;
2108+ u16 exec_ctxt;
2109+/* partition supports receipt of direct requests */
2110+#define FFA_PARTITION_DIRECT_RECV BIT(0)
2111+/* partition can send direct requests. */
2112+#define FFA_PARTITION_DIRECT_SEND BIT(1)
2113+/* partition can send and receive indirect messages. */
2114+#define FFA_PARTITION_INDIRECT_MSG BIT(2)
2115+ u32 properties;
2116+};
2117+
2118+/*
2119+ * struct ffa_send_direct_data - Data structure hosting the data
2120+ * used by FFA_MSG_SEND_DIRECT_{REQ,RESP}
2121+ * @data0-4: Data read/written from/to x3-x7 registers
2122+ *
2123+ * Data structure containing the data to be sent by FFA_MSG_SEND_DIRECT_REQ
2124+ * or read from FFA_MSG_SEND_DIRECT_RESP
2125+ */
2126+
2127+/* For use with FFA_MSG_SEND_DIRECT_{REQ,RESP} which pass data via registers */
2128+struct __packed ffa_send_direct_data {
2129+ unsigned long data0; /* w3/x3 */
2130+ unsigned long data1; /* w4/x4 */
2131+ unsigned long data2; /* w5/x5 */
2132+ unsigned long data3; /* w6/x6 */
2133+ unsigned long data4; /* w7/x7 */
2134+};
2135+
2136+#if CONFIG_IS_ENABLED(ARM_FFA_EFI_RUNTIME_MODE)
2137+
2138+#include <efi_loader.h>
2139+
2140+/*
2141+ * __ffa_runtime - controls whether functions are
2142+ * available after calling the EFI ExitBootServices service.
2143+ * Functions tagged with these keywords are resident (available at boot time and
2144+ * at runtime)
2145+ */
2146+
2147+#define __ffa_runtime_data __efi_runtime_data
2148+#define __ffa_runtime __efi_runtime
2149+
2150+#else
2151+
2152+/*
2153+ * The FF-A driver is independent from EFI
2154+ */
2155+
2156+#define __ffa_runtime_data
2157+#define __ffa_runtime
2158+
2159+#endif
2160+
2161+/**
2162+ * struct ffa_bus_ops - The driver operations structure
2163+ * @partition_info_get: callback for the FFA_PARTITION_INFO_GET
2164+ * @sync_send_receive: callback for the FFA_MSG_SEND_DIRECT_REQ
2165+ * @rxtx_unmap: callback for the FFA_RXTX_UNMAP
2166+ *
2167+ * The data structure providing all the operations supported by the driver.
2168+ * This structure is EFI runtime resident.
2169+ */
2170+struct ffa_bus_ops {
2171+ int (*partition_info_get)(const char *uuid_str,
2172+ u32 *parts_size, struct ffa_partition_info *buffer);
2173+ int (*sync_send_receive)(u16 dst_part_id, struct ffa_send_direct_data *msg);
2174+ int (*rxtx_unmap)(void);
2175+};
2176+
2177+/**
2178+ * The device driver and the Uclass driver public functions
2179+ */
2180+
2181+/**
2182+ * ffa_bus_ops_get - driver operations getter
2183+ */
2184+const struct ffa_bus_ops * __ffa_runtime ffa_bus_ops_get(void);
2185+
2186+/**
2187+ * ffa_bus_discover - discover FF-A bus and probes the arm_ffa device
2188+ */
2189+int ffa_bus_discover(void);
2190+
2191+#if CONFIG_IS_ENABLED(ARM_FFA_EFI_RUNTIME_MODE)
2192+
2193+/**
2194+ * ffa_copy_runtime_data - copy the private data structure and the SPs data to the runtime area
2195+ */
2196+efi_status_t ffa_copy_runtime_data(void);
2197+
2198+#endif
2199+
2200+#endif
2201diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h
2202index 3ba69ad9a0..7324418245 100644
2203--- a/include/dm/uclass-id.h
2204+++ b/include/dm/uclass-id.h
2205@@ -55,6 +55,7 @@ enum uclass_id {
2206 UCLASS_EFI_MEDIA, /* Devices provided by UEFI firmware */
2207 UCLASS_ETH, /* Ethernet device */
2208 UCLASS_ETH_PHY, /* Ethernet PHY device */
2209+ UCLASS_FFA, /* Arm Firmware Framework for Armv8-A */
2210 UCLASS_FIRMWARE, /* Firmware */
2211 UCLASS_FS_FIRMWARE_LOADER, /* Generic loader */
2212 UCLASS_GPIO, /* Bank of general-purpose I/O pins */
2213diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c
2214index 4da64b5d29..0ec002ac8b 100644
2215--- a/lib/efi_loader/efi_boottime.c
2216+++ b/lib/efi_loader/efi_boottime.c
2217@@ -23,6 +23,10 @@
2218 #include <asm/setjmp.h>
2219 #include <linux/libfdt_env.h>
2220
2221+#if CONFIG_IS_ENABLED(ARM_FFA_TRANSPORT)
2222+#include <arm_ffa.h>
2223+#endif
2224+
2225 DECLARE_GLOBAL_DATA_PTR;
2226
2227 /* Task priority level */
2228@@ -2173,6 +2177,14 @@ static efi_status_t EFIAPI efi_exit_boot_services(efi_handle_t image_handle,
2229 dm_remove_devices_flags(DM_REMOVE_ACTIVE_ALL);
2230 }
2231
2232+#if CONFIG_IS_ENABLED(ARM_FFA_TRANSPORT)
2233+ /* unmap FF-A RX/TX buffers */
2234+ if (ffa_bus_ops_get()->rxtx_unmap())
2235+ debug("[efi_boottime][ERROR]: can not unmap FF-A RX/TX buffers\n");
2236+ else
2237+ debug("[efi_boottime][INFO]: FF-A RX/TX buffers unmapped\n");
2238+#endif
2239+
2240 /* Patch out unsupported runtime function */
2241 efi_runtime_detach();
2242
2243--
22442.17.1
2245