blob: 774af445631e978064baa34269baf566ada3813b [file] [log] [blame]
Andrew Geisslerea144b032023-01-27 16:03:57 -06001From 93e3267b19c5c5d27664ef133121db4b678ad72d Mon Sep 17 00:00:00 2001
Patrick Williams8dd68482022-10-04 07:57:18 -05002From: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
Andrew Geisslerea144b032023-01-27 16:03:57 -06003Date: Tue, 29 Nov 2022 14:40:05 +0000
4Subject: [PATCH 03/25] arm_ffa: introduce Arm FF-A low-level driver
Patrick Williams8dd68482022-10-04 07:57:18 -05005
Andrew Geisslerea144b032023-01-27 16:03:57 -06006Add the core driver implementing Arm Firmware Framework for Armv8-A v1.0
Patrick Williams8dd68482022-10-04 07:57:18 -05007
Andrew Geisslerea144b032023-01-27 16:03:57 -06008The Firmware Framework for Arm A-profile processors (FF-A v1.0) [1]
Patrick Williams8dd68482022-10-04 07:57:18 -05009describes 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
Andrew Geisslerea144b032023-01-27 16:03:57 -060017The driver uses SMC32 calling convention which means using the first
1832-bit data of the Xn registers.
Patrick Williams8dd68482022-10-04 07:57:18 -050019
Andrew Geisslerea144b032023-01-27 16:03:57 -060020All supported ABIs come with their 32-bit version except FFA_RXTX_MAP
21which has 64-bit version supported.
22
23Both 32-bit and 64-bit direct messaging are supported which allows both
2432-bit and 64-bit clients to use the FF-A bus.
25
26In U-Boot FF-A design, FF-A is considered as a discoverable bus.
Patrick Williams8dd68482022-10-04 07:57:18 -050027The Secure World is considered as one entity to communicate with
28using the FF-A bus. FF-A communication is handled by one device and
29one instance (the bus). This FF-A driver takes care of all the
30interactions between Normal world and Secure World.
31
32The driver exports its operations to be used by upper layers.
33
34Exported operations:
35
36- partition_info_get
37- sync_send_receive
38- rxtx_unmap
39
Andrew Geisslerea144b032023-01-27 16:03:57 -060040For more details please refer to the driver documentation [2].
41
42[1]: https://developer.arm.com/documentation/den0077/latest/
43[2]: doc/arch/arm64.ffa.rst
Patrick Williams8dd68482022-10-04 07:57:18 -050044
45Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
Andrew Geisslerea144b032023-01-27 16:03:57 -060046Cc: Tom Rini <trini@konsulko.com>
47Cc: Simon Glass <sjg@chromium.org>
48Cc: Ilias Apalodimas <ilias.apalodimas@linaro.org>
49Cc: Jens Wiklander <jens.wiklander@linaro.org>
50Upstream-Status: Submitted [cover letter: https://lore.kernel.org/all/20221122131751.22747-1-abdellatif.elkhlifi@arm.com/]
Patrick Williams8dd68482022-10-04 07:57:18 -050051
52Changelog:
53===============
54
Andrew Geisslerea144b032023-01-27 16:03:57 -060055v8:
56
57* make ffa_get_partitions_info() second argument to be an SP count in both
58 modes
59* update ffa_bus_prvdata_get() to return a pointer rather than a pointer
60 address
61* remove packing from ffa_partition_info and ffa_send_direct_data structures
62* pass the FF-A bus device to the bus operations
63
64v7:
65
66* add support for 32-bit direct messaging
67* rename be_uuid_str_to_le_bin() to uuid_str_to_le_bin()
68* improve the declaration of error handling mapping
69* stating in doc/arch/arm64.ffa.rst that EFI runtime is not supported
70
71v6:
72
73* drop use of EFI runtime support (We decided with Linaro to add this later)
74* drop discovery from initcalls (discovery will be on demand by FF-A users)
75* set the alignment of the RX/TX buffers to the larger translation granule size
76* move FF-A RX/TX buffers unmapping at ExitBootServices() to a separate commit
77* update the documentation and move it to doc/arch/arm64.ffa.rst
78
Patrick Williams8dd68482022-10-04 07:57:18 -050079v4:
80
81* add doc/README.ffa.drv
82* moving the FF-A driver work to drivers/firmware/arm-ffa
83* use less #ifdefs in lib/efi_loader/efi_boottime.c and replace
84 #if defined by #if CONFIG_IS_ENABLED
85* improving error handling by mapping the FF-A errors to standard errors
86 and logs
87* replacing panics with an error log and returning an error code
88* improving features discovery in FFA_FEATURES by introducing
89 rxtx_min_pages private data field
Andrew Geisslerea144b032023-01-27 16:03:57 -060090* add ffa_remove and ffa_unbind functions
Patrick Williams8dd68482022-10-04 07:57:18 -050091* improve how the driver behaves when bus discovery is done more than
92 once
93
94v3:
95
Andrew Geisslerea144b032023-01-27 16:03:57 -060096* align the interfaces of the U-Boot FF-A driver with those in the linux
Patrick Williams8dd68482022-10-04 07:57:18 -050097 FF-A driver
98* remove the FF-A helper layer
Andrew Geisslerea144b032023-01-27 16:03:57 -060099* make the U-Boot FF-A driver independent from EFI
Patrick Williams8dd68482022-10-04 07:57:18 -0500100* provide an optional config that enables copying the driver data to EFI
101 runtime section at ExitBootServices service
102* use 64-bit version of FFA_RXTX_MAP, FFA_MSG_SEND_DIRECT_{REQ, RESP}
103
104v2:
105
106* make FF-A bus discoverable using device_{bind, probe} APIs
107* remove device tree support
108
109v1:
110
111* introduce FF-A bus driver with device tree support
Andrew Geisslerea144b032023-01-27 16:03:57 -0600112---
113 MAINTAINERS | 7 +
114 doc/arch/arm64.ffa.rst | 218 ++++
115 doc/arch/index.rst | 1 +
116 drivers/Kconfig | 2 +
117 drivers/Makefile | 1 +
118 drivers/firmware/arm-ffa/Kconfig | 30 +
119 drivers/firmware/arm-ffa/Makefile | 6 +
120 drivers/firmware/arm-ffa/arm-ffa-uclass.c | 16 +
121 drivers/firmware/arm-ffa/arm_ffa_prv.h | 200 ++++
122 drivers/firmware/arm-ffa/core.c | 1315 +++++++++++++++++++++
123 include/arm_ffa.h | 97 ++
124 include/dm/uclass-id.h | 4 +
125 12 files changed, 1897 insertions(+)
126 create mode 100644 doc/arch/arm64.ffa.rst
Patrick Williams8dd68482022-10-04 07:57:18 -0500127 create mode 100644 drivers/firmware/arm-ffa/Kconfig
128 create mode 100644 drivers/firmware/arm-ffa/Makefile
129 create mode 100644 drivers/firmware/arm-ffa/arm-ffa-uclass.c
130 create mode 100644 drivers/firmware/arm-ffa/arm_ffa_prv.h
131 create mode 100644 drivers/firmware/arm-ffa/core.c
Patrick Williams8dd68482022-10-04 07:57:18 -0500132 create mode 100644 include/arm_ffa.h
133
134diff --git a/MAINTAINERS b/MAINTAINERS
Andrew Geisslerea144b032023-01-27 16:03:57 -0600135index 83346183ee..734fcb10c4 100644
Patrick Williams8dd68482022-10-04 07:57:18 -0500136--- a/MAINTAINERS
137+++ b/MAINTAINERS
Andrew Geisslerea144b032023-01-27 16:03:57 -0600138@@ -248,6 +248,13 @@ F: drivers/net/cortina_ni.h
139 F: drivers/net/phy/ca_phy.c
140 F: configs/cortina_presidio-asic-pnand_defconfig
Patrick Williams8dd68482022-10-04 07:57:18 -0500141
142+ARM FF-A
143+M: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
144+S: Maintained
Andrew Geisslerea144b032023-01-27 16:03:57 -0600145+F: doc/arch/arm64.ffa.rst
Patrick Williams8dd68482022-10-04 07:57:18 -0500146+F: drivers/firmware/arm-ffa/
147+F: include/arm_ffa.h
148+
149 ARM FREESCALE IMX
150 M: Stefano Babic <sbabic@denx.de>
151 M: Fabio Estevam <festevam@gmail.com>
Andrew Geisslerea144b032023-01-27 16:03:57 -0600152diff --git a/doc/arch/arm64.ffa.rst b/doc/arch/arm64.ffa.rst
Patrick Williams8dd68482022-10-04 07:57:18 -0500153new file mode 100644
Andrew Geisslerea144b032023-01-27 16:03:57 -0600154index 0000000000..dfcec82e45
Patrick Williams8dd68482022-10-04 07:57:18 -0500155--- /dev/null
Andrew Geisslerea144b032023-01-27 16:03:57 -0600156+++ b/doc/arch/arm64.ffa.rst
157@@ -0,0 +1,218 @@
158+.. SPDX-License-Identifier: GPL-2.0+
Patrick Williams8dd68482022-10-04 07:57:18 -0500159+
Andrew Geisslerea144b032023-01-27 16:03:57 -0600160+Arm FF-A Driver
161+===============
162+
163+Summary
164+-------
Patrick Williams8dd68482022-10-04 07:57:18 -0500165+
166+FF-A stands for Firmware Framework for Arm A-profile processors.
167+
Andrew Geisslerea144b032023-01-27 16:03:57 -0600168+FF-A specifies interfaces that enable a pair of software sandboxes to
169+communicate with each other. A sandbox aka partition could
170+be a VM in the Normal or Secure world, an application in S-EL0, or a
171+Trusted OS in S-EL1.
Patrick Williams8dd68482022-10-04 07:57:18 -0500172+
Andrew Geisslerea144b032023-01-27 16:03:57 -0600173+This FF-A driver implements the interfaces to communicate with partitions in
174+the Secure world aka Secure partitions (SPs).
Patrick Williams8dd68482022-10-04 07:57:18 -0500175+
Andrew Geisslerea144b032023-01-27 16:03:57 -0600176+The driver specifically focuses on communicating with SPs that isolate portions
177+of EFI runtime services that must run in a protected environment which is
178+inaccessible by the Host OS or Hypervisor. Examples of such services are
179+set/get variables.
Patrick Williams8dd68482022-10-04 07:57:18 -0500180+
181+FF-A driver uses the SMC ABIs defined by the FF-A specification to:
182+
Andrew Geisslerea144b032023-01-27 16:03:57 -0600183+- Discover the presence of SPs of interest
184+- Access an SP's service through communication protocols
185+ e.g. EFI MM communication protocol
186+
187+At this stage of development the FF-A driver supports EFI boot time only.
188+
189+Runtime support will be added in future developments.
Patrick Williams8dd68482022-10-04 07:57:18 -0500190+
191+FF-A and SMC specifications
192+-------------------------------------------
193+
Andrew Geisslerea144b032023-01-27 16:03:57 -0600194+The current implementation of the driver relies on FF-A specification v1.0
195+and uses SMC32 calling convention which means using the first 32-bit data of the
196+Xn registers.
Patrick Williams8dd68482022-10-04 07:57:18 -0500197+
Andrew Geisslerea144b032023-01-27 16:03:57 -0600198+At this stage we only need the FF-A v1.0 features.
Patrick Williams8dd68482022-10-04 07:57:18 -0500199+
Andrew Geisslerea144b032023-01-27 16:03:57 -0600200+The driver has been tested with OP-TEE which supports SMC32 calling convention.
201+
202+For more details please refer to the FF-A v1.0 spec:
203+https://documentation-service.arm.com/static/5fb7e8a6ca04df4095c1d65e?token=
204+
205+Hypervisors are supported if they are configured to trap SMC calls.
Patrick Williams8dd68482022-10-04 07:57:18 -0500206+
207+The FF-A driver uses 64-bit registers as per SMCCCv1.2 specification.
208+
Andrew Geisslerea144b032023-01-27 16:03:57 -0600209+For more details please refer to the SMC Calling Convention v1.2 spec:
210+https://documentation-service.arm.com/static/5f8edaeff86e16515cdbe4c6?token=
Patrick Williams8dd68482022-10-04 07:57:18 -0500211+
212+Supported hardware
213+--------------------------------
214+
215+Aarch64 plaforms
216+
217+Configuration
218+----------------------
219+
220+CONFIG_ARM_FFA_TRANSPORT
Andrew Geisslerea144b032023-01-27 16:03:57 -0600221+ Enables the FF-A bus driver. Turn this on if you want to use FF-A
222+ communication.
Patrick Williams8dd68482022-10-04 07:57:18 -0500223+
224+CONFIG_SANDBOX_FFA
Andrew Geisslerea144b032023-01-27 16:03:57 -0600225+ Enables FF-A Sandbox driver. This emulates the FF-A ABIs handling under
226+ Sandbox and provides functional tests for FF-A.
Patrick Williams8dd68482022-10-04 07:57:18 -0500227+
228+FF-A ABIs under the hood
229+---------------------------------------
230+
Andrew Geisslerea144b032023-01-27 16:03:57 -0600231+Invoking an FF-A ABI involves providing to the secure world/hypervisor the
232+expected arguments from the ABI.
Patrick Williams8dd68482022-10-04 07:57:18 -0500233+
Andrew Geisslerea144b032023-01-27 16:03:57 -0600234+The ABI arguments are stored in x0 to x7 registers. Then, an SMC instruction
235+is executed.
Patrick Williams8dd68482022-10-04 07:57:18 -0500236+
Andrew Geisslerea144b032023-01-27 16:03:57 -0600237+At the secure side level or hypervisor the ABI is handled at a higher exception
238+level and the arguments are read and processed.
Patrick Williams8dd68482022-10-04 07:57:18 -0500239+
Andrew Geisslerea144b032023-01-27 16:03:57 -0600240+The response is put back through x0 to x7 registers and control is given back
241+to the U-Boot FF-A driver (non-secure world).
Patrick Williams8dd68482022-10-04 07:57:18 -0500242+
243+The driver reads the response and processes it accordingly.
244+
245+This methodology applies to all the FF-A ABIs in the driver.
246+
Andrew Geisslerea144b032023-01-27 16:03:57 -0600247+FF-A bus discovery in U-Boot
Patrick Williams8dd68482022-10-04 07:57:18 -0500248+-------------------------------------------
249+
Andrew Geisslerea144b032023-01-27 16:03:57 -0600250+When CONFIG_ARM_FFA_TRANSPORT is enabled, the FF-A bus is discovered on
251+demand by the clients (users).
Patrick Williams8dd68482022-10-04 07:57:18 -0500252+
Andrew Geisslerea144b032023-01-27 16:03:57 -0600253+Clients can discover the FF-A bus using ffa_bus_discover() API which triggers the
254+discovery process.
Patrick Williams8dd68482022-10-04 07:57:18 -0500255+
Andrew Geisslerea144b032023-01-27 16:03:57 -0600256+ffa_bus_discover() creates, binds and probes the arm_ffa device using
257+device_{bind, probe} APIs.
Patrick Williams8dd68482022-10-04 07:57:18 -0500258+
Andrew Geisslerea144b032023-01-27 16:03:57 -0600259+The discovery process consists in communicating with secure world (or hypervisor)
260+and querying specific data.
Patrick Williams8dd68482022-10-04 07:57:18 -0500261+
Andrew Geisslerea144b032023-01-27 16:03:57 -0600262+The discovery process takes place during the arm_ffa device probing which is
263+handled by ffa_probe().
264+
265+The FF-A bus discovery is successful and the bus is ready for use when these
266+operations succeed:
Patrick Williams8dd68482022-10-04 07:57:18 -0500267+
268+- querying the FF-A framework version
Andrew Geisslerea144b032023-01-27 16:03:57 -0600269+- querying from secure world the U-Boot endpoint ID
270+- querying from secure world the RX/TX mapping features
Patrick Williams8dd68482022-10-04 07:57:18 -0500271+- mapping the RX/TX buffers
272+- querying from secure world all the partitions information
273+
Andrew Geisslerea144b032023-01-27 16:03:57 -0600274+Discovery failure results in a probing failure and the arm_ffa device is
275+destroyed.
Patrick Williams8dd68482022-10-04 07:57:18 -0500276+
Andrew Geisslerea144b032023-01-27 16:03:57 -0600277+Requirements for clients
278+-------------------------------------
279+
280+When using the FF-A bus with EFI, clients must:
281+
282+- Query SPs in EFI boot time mode using the service UUID.
283+- Unmap RX/TX buffers before EFI runtime mode starts.
284+
285+The RX/TX buffers are only available at EFI boot time. Querying partitions is
286+done at boot time and data is cached for future use.
287+
288+RX/TX buffers should be unmapped by the user before EFI runtime mode
289+starts. The driver provides a bus operation for that: rxtx_unmap()
290+
291+If RX/TX buffers created by U-Boot are not unmapped and by
292+consequence becoming available at EFI runtime, secure world will get confused
293+about RX/TX buffers ownership (U-Boot vs kernel).
294+
295+When invoking FF-A direct messaging, clients should specify which ABI protocol
296+they want to use (32-bit vs 64-bit). Selecting the protocol means using
297+the 32-bit or 64-bit version of FFA_MSG_SEND_DIRECT_{REQ, RESP}.
298+The calling convention stays the same: SMC32.
Patrick Williams8dd68482022-10-04 07:57:18 -0500299+
300+The bus driver layer
301+------------------------------
302+
Andrew Geisslerea144b032023-01-27 16:03:57 -0600303+The driver comes on top of the SMCCC layer and is implemented in
304+drivers/firmware/arm-ffa/core.c
Patrick Williams8dd68482022-10-04 07:57:18 -0500305+
306+The driver provides the following features:
307+
308+- Support for the 32-bit version of the following ABIs:
309+
310+FFA_VERSION
311+FFA_ID_GET
312+FFA_FEATURES
313+FFA_PARTITION_INFO_GET
314+FFA_RXTX_UNMAP
315+FFA_RX_RELEASE
316+FFA_RUN
317+FFA_ERROR
318+FFA_SUCCESS
319+FFA_INTERRUPT
Andrew Geisslerea144b032023-01-27 16:03:57 -0600320+FFA_MSG_SEND_DIRECT_REQ
321+FFA_MSG_SEND_DIRECT_RESP
Patrick Williams8dd68482022-10-04 07:57:18 -0500322+
323+- Support for the 64-bit version of the following ABIs:
324+
325+FFA_RXTX_MAP
326+FFA_MSG_SEND_DIRECT_REQ
327+FFA_MSG_SEND_DIRECT_RESP
328+
329+- Processing the received data from the secure world/hypervisor and caching it
330+
Andrew Geisslerea144b032023-01-27 16:03:57 -0600331+- Hiding from upper layers the FF-A protocol and registers details. Upper
332+ layers focus on exchanged data, the driver takes care of how to transport
333+ that to the secure world/hypervisor using FF-A
Patrick Williams8dd68482022-10-04 07:57:18 -0500334+
335+- The driver provides callbacks to be used by clients to access the FF-A bus:
336+
337+partition_info_get
338+sync_send_receive
339+rxtx_unmap
340+
Andrew Geisslerea144b032023-01-27 16:03:57 -0600341+- FF-A bus discovery makes sure FF-A framework is responsive and compatible
342+ with the driver
Patrick Williams8dd68482022-10-04 07:57:18 -0500343+
Andrew Geisslerea144b032023-01-27 16:03:57 -0600344+- FF-A bus can be compiled and used without EFI
Patrick Williams8dd68482022-10-04 07:57:18 -0500345+
346+Using armffa command
347+-----------------------------------
348+
Andrew Geisslerea144b032023-01-27 16:03:57 -0600349+armffa is an implementation defined command showcasing how to use the FF-A driver and how to invoke
350+its operations.
Patrick Williams8dd68482022-10-04 07:57:18 -0500351+
Andrew Geisslerea144b032023-01-27 16:03:57 -0600352+This provides a guidance to the client developers on how to call the FF-A bus
353+interfaces.
Patrick Williams8dd68482022-10-04 07:57:18 -0500354+
355+Usage:
356+
357+armffa <sub-command> <arguments>
358+
359+sub-commands:
360+
361+ getpart <partition UUID>
362+
363+ lists the partition(s) info
364+
365+ ping <partition ID>
366+
367+ sends a data pattern to the specified partition
368+
369+ devlist
370+
371+ displays the arm_ffa device info
Andrew Geisslerea144b032023-01-27 16:03:57 -0600372+
373+Contributors
374+------------
375+ * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
376diff --git a/doc/arch/index.rst b/doc/arch/index.rst
377index 792d9182c3..8d1ab0ad4e 100644
378--- a/doc/arch/index.rst
379+++ b/doc/arch/index.rst
380@@ -8,6 +8,7 @@ Architecture-specific doc
381
382 arc
383 arm64
384+ arm64.ffa
385 m68k
386 mips
387 nios2
Patrick Williams8dd68482022-10-04 07:57:18 -0500388diff --git a/drivers/Kconfig b/drivers/Kconfig
Andrew Geisslerea144b032023-01-27 16:03:57 -0600389index 8b6fead351..b06b1ae481 100644
Patrick Williams8dd68482022-10-04 07:57:18 -0500390--- a/drivers/Kconfig
391+++ b/drivers/Kconfig
392@@ -6,6 +6,8 @@ source "drivers/core/Kconfig"
393
394 source "drivers/adc/Kconfig"
395
396+source "drivers/firmware/arm-ffa/Kconfig"
397+
398 source "drivers/ata/Kconfig"
399
400 source "drivers/axi/Kconfig"
401diff --git a/drivers/Makefile b/drivers/Makefile
Andrew Geisslerea144b032023-01-27 16:03:57 -0600402index eba9940231..c3bfad94ac 100644
Patrick Williams8dd68482022-10-04 07:57:18 -0500403--- a/drivers/Makefile
404+++ b/drivers/Makefile
Andrew Geisslerea144b032023-01-27 16:03:57 -0600405@@ -110,6 +110,7 @@ obj-y += iommu/
Patrick Williams8dd68482022-10-04 07:57:18 -0500406 obj-y += smem/
407 obj-y += thermal/
408 obj-$(CONFIG_TEE) += tee/
409+obj-$(CONFIG_ARM_FFA_TRANSPORT) += firmware/arm-ffa/
410 obj-y += axi/
411 obj-y += ufs/
412 obj-$(CONFIG_W1) += w1/
413diff --git a/drivers/firmware/arm-ffa/Kconfig b/drivers/firmware/arm-ffa/Kconfig
414new file mode 100644
Andrew Geisslerea144b032023-01-27 16:03:57 -0600415index 0000000000..e4914b9bc7
Patrick Williams8dd68482022-10-04 07:57:18 -0500416--- /dev/null
417+++ b/drivers/firmware/arm-ffa/Kconfig
Andrew Geisslerea144b032023-01-27 16:03:57 -0600418@@ -0,0 +1,30 @@
Patrick Williams8dd68482022-10-04 07:57:18 -0500419+# SPDX-License-Identifier: GPL-2.0
420+
421+config ARM_FFA_TRANSPORT
422+ bool "Enable Arm Firmware Framework for Armv8-A driver"
423+ depends on DM && ARM64
424+ select ARM_SMCCC
425+ select LIB_UUID
426+ select DEVRES
427+ help
428+ The Firmware Framework for Arm A-profile processors (FF-A)
429+ describes interfaces (ABIs) that standardize communication
430+ between the Secure World and Normal World leveraging TrustZone
431+ technology.
432+
433+ This driver is based on FF-A specification v1.0 and uses SMC32
434+ calling convention.
435+
436+ FF-A specification:
437+
438+ https://developer.arm.com/documentation/den0077/a/?lang=en
439+
Andrew Geisslerea144b032023-01-27 16:03:57 -0600440+ In U-Boot FF-A design, FF-A is considered as a discoverable bus.
Patrick Williams8dd68482022-10-04 07:57:18 -0500441+ The Secure World is considered as one entity to communicate with
442+ using the FF-A bus.
443+ FF-A communication is handled by one device and one instance (the bus).
444+ This FF-A driver takes care of all the interactions between Normal world
445+ and Secure World.
446+
Andrew Geisslerea144b032023-01-27 16:03:57 -0600447+ For more details about the FF-A driver, please refer to doc/arch/arm64.ffa.rst
Patrick Williams8dd68482022-10-04 07:57:18 -0500448+
Patrick Williams8dd68482022-10-04 07:57:18 -0500449diff --git a/drivers/firmware/arm-ffa/Makefile b/drivers/firmware/arm-ffa/Makefile
450new file mode 100644
Andrew Geisslerea144b032023-01-27 16:03:57 -0600451index 0000000000..043a8915be
Patrick Williams8dd68482022-10-04 07:57:18 -0500452--- /dev/null
453+++ b/drivers/firmware/arm-ffa/Makefile
Andrew Geisslerea144b032023-01-27 16:03:57 -0600454@@ -0,0 +1,6 @@
Patrick Williams8dd68482022-10-04 07:57:18 -0500455+# SPDX-License-Identifier: GPL-2.0+
456+#
Andrew Geisslerea144b032023-01-27 16:03:57 -0600457+# (C) Copyright 2022
458+# Abdellatif El Khlifi, Arm Limited, abdellatif.elkhlifi@arm.com.
Patrick Williams8dd68482022-10-04 07:57:18 -0500459+
460+obj-y += arm-ffa-uclass.o core.o
Patrick Williams8dd68482022-10-04 07:57:18 -0500461diff --git a/drivers/firmware/arm-ffa/arm-ffa-uclass.c b/drivers/firmware/arm-ffa/arm-ffa-uclass.c
462new file mode 100644
463index 0000000000..7d9695d289
464--- /dev/null
465+++ b/drivers/firmware/arm-ffa/arm-ffa-uclass.c
466@@ -0,0 +1,16 @@
467+// SPDX-License-Identifier: GPL-2.0+
468+/*
469+ * (C) Copyright 2022 ARM Limited
470+ * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
471+ */
472+
473+#include <common.h>
474+#include <dm.h>
475+#include <asm/global_data.h>
476+
477+DECLARE_GLOBAL_DATA_PTR;
478+
479+UCLASS_DRIVER(ffa) = {
480+ .name = "ffa",
481+ .id = UCLASS_FFA,
482+};
483diff --git a/drivers/firmware/arm-ffa/arm_ffa_prv.h b/drivers/firmware/arm-ffa/arm_ffa_prv.h
484new file mode 100644
Andrew Geisslerea144b032023-01-27 16:03:57 -0600485index 0000000000..4eea7dc036
Patrick Williams8dd68482022-10-04 07:57:18 -0500486--- /dev/null
487+++ b/drivers/firmware/arm-ffa/arm_ffa_prv.h
Andrew Geisslerea144b032023-01-27 16:03:57 -0600488@@ -0,0 +1,200 @@
Patrick Williams8dd68482022-10-04 07:57:18 -0500489+/* SPDX-License-Identifier: GPL-2.0+ */
490+/*
491+ * (C) Copyright 2022 ARM Limited
492+ * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
493+ */
494+
495+#ifndef __ARM_FFA_PRV_H
496+#define __ARM_FFA_PRV_H
497+
498+#include <arm_ffa.h>
499+#include <linux/bitfield.h>
500+#include <linux/bitops.h>
501+#include <linux/arm-smccc.h>
502+
503+/*
504+ * This header is private. It is exclusively used by the FF-A driver
505+ */
506+
507+/* FF-A core driver name */
508+#define FFA_DRV_NAME "arm_ffa"
509+
510+/* FF-A driver version definitions */
511+
512+#define MAJOR_VERSION_MASK GENMASK(30, 16)
513+#define MINOR_VERSION_MASK GENMASK(15, 0)
514+#define GET_FFA_MAJOR_VERSION(x) \
515+ ((u16)(FIELD_GET(MAJOR_VERSION_MASK, (x))))
516+#define GET_FFA_MINOR_VERSION(x) \
517+ ((u16)(FIELD_GET(MINOR_VERSION_MASK, (x))))
518+#define PACK_VERSION_INFO(major, minor) \
519+ (FIELD_PREP(MAJOR_VERSION_MASK, (major)) | \
520+ FIELD_PREP(MINOR_VERSION_MASK, (minor)))
521+
522+#define FFA_MAJOR_VERSION (1)
523+#define FFA_MINOR_VERSION (0)
524+#define FFA_VERSION_1_0 \
525+ PACK_VERSION_INFO(FFA_MAJOR_VERSION, FFA_MINOR_VERSION)
526+
527+/* Endpoint ID mask (u-boot endpoint ID) */
528+
529+#define GET_SELF_ENDPOINT_ID_MASK GENMASK(15, 0)
530+#define GET_SELF_ENDPOINT_ID(x) \
531+ ((u16)(FIELD_GET(GET_SELF_ENDPOINT_ID_MASK, (x))))
532+
533+#define PREP_SELF_ENDPOINT_ID_MASK GENMASK(31, 16)
534+#define PREP_SELF_ENDPOINT_ID(x) \
535+ (FIELD_PREP(PREP_SELF_ENDPOINT_ID_MASK, (x)))
536+
537+/* Partition endpoint ID mask (partition with which u-boot communicates with) */
538+
539+#define PREP_PART_ENDPOINT_ID_MASK GENMASK(15, 0)
540+#define PREP_PART_ENDPOINT_ID(x) \
541+ (FIELD_PREP(PREP_PART_ENDPOINT_ID_MASK, (x)))
542+
543+/*
544+ * Definitions of the Arm FF-A interfaces supported by the Arm FF-A driver
545+ */
546+
547+#define FFA_SMC(calling_convention, func_num) \
548+ ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, (calling_convention), \
549+ ARM_SMCCC_OWNER_STANDARD, (func_num))
550+
551+#define FFA_SMC_32(func_num) FFA_SMC(ARM_SMCCC_SMC_32, (func_num))
552+#define FFA_SMC_64(func_num) FFA_SMC(ARM_SMCCC_SMC_64, (func_num))
553+
554+enum ffa_abis {
Andrew Geisslerea144b032023-01-27 16:03:57 -0600555+ FFA_ERROR = 0x60,
556+ FFA_SUCCESS = 0x61,
557+ FFA_INTERRUPT = 0x62,
558+ FFA_VERSION = 0x63,
559+ FFA_FEATURES = 0x64,
560+ FFA_RX_RELEASE = 0x65,
561+ FFA_RXTX_MAP = 0x66,
562+ FFA_RXTX_UNMAP = 0x67,
563+ FFA_PARTITION_INFO_GET = 0x68,
564+ FFA_ID_GET = 0x69,
565+ FFA_RUN = 0x6D,
566+ FFA_MSG_SEND_DIRECT_REQ = 0x6F,
567+ FFA_MSG_SEND_DIRECT_RESP = 0x70,
Patrick Williams8dd68482022-10-04 07:57:18 -0500568+
569+ /* to be updated when adding new FFA IDs */
Andrew Geisslerea144b032023-01-27 16:03:57 -0600570+ FFA_FIRST_ID = FFA_ERROR, /* lowest number ID*/
571+ FFA_LAST_ID = FFA_MSG_SEND_DIRECT_RESP, /* highest number ID*/
Patrick Williams8dd68482022-10-04 07:57:18 -0500572+};
573+
Andrew Geisslerea144b032023-01-27 16:03:57 -0600574+enum ffa_abi_errcode {
575+ NOT_SUPPORTED = 1,
576+ INVALID_PARAMETERS,
577+ NO_MEMORY,
578+ BUSY,
579+ INTERRUPTED,
580+ DENIED,
581+ RETRY,
582+ ABORTED,
583+ MAX_NUMBER_FFA_ERR
584+};
Patrick Williams8dd68482022-10-04 07:57:18 -0500585+
586+/* container structure and helper macros to map between an FF-A error and relevant error log */
587+struct ffa_abi_errmap {
588+ char *err_str[MAX_NUMBER_FFA_ERR];
589+};
590+
591+#define FFA_ERRMAP_COUNT (FFA_LAST_ID - FFA_FIRST_ID + 1)
592+#define FFA_ID_TO_ERRMAP_ID(ffa_id) ((ffa_id) - FFA_FIRST_ID)
593+
594+/* The FF-A SMC function definitions */
595+
596+typedef struct arm_smccc_1_2_regs ffa_value_t;
597+typedef void (*invoke_ffa_fn_t)(ffa_value_t args, ffa_value_t *res);
598+
599+/*
600+ * struct ffa_partition_uuid - 16 bytes UUID transmitted by FFA_PARTITION_INFO_GET
601+ * @a1-4: 32-bit words access to the UUID data
602+ *
603+ */
604+struct ffa_partition_uuid {
605+ u32 a1; /* w1 */
606+ u32 a2; /* w2 */
607+ u32 a3; /* w3 */
608+ u32 a4; /* w4 */
609+};
610+
611+/**
612+ * enum ffa_rxtx_buf_sizes - minimum sizes supported
613+ * for the RX/TX buffers
614+ */
615+enum ffa_rxtx_buf_sizes {
616+ RXTX_4K,
617+ RXTX_64K,
618+ RXTX_16K
619+};
620+
621+/**
622+ * struct ffa_rxtxpair - structure hosting the RX/TX buffers virtual addresses
623+ * @rxbuf: virtual address of the RX buffer
624+ * @txbuf: virtual address of the TX buffer
625+ * @rxtx_min_pages: RX/TX buffers minimum size in pages
626+ *
627+ * Data structure hosting the virtual addresses of the mapped RX/TX buffers
628+ * These addresses are used by the FF-A functions that use the RX/TX buffers
629+ */
630+struct ffa_rxtxpair {
631+ u64 rxbuf; /* virtual address */
632+ u64 txbuf; /* virtual address */
633+ size_t rxtx_min_pages; /* minimum number of pages in each of the RX/TX buffers */
634+};
635+
636+/**
637+ * struct ffa_partition_desc - the secure partition descriptor
638+ * @info: partition information
639+ * @sp_uuid: the secure partition UUID
640+ *
641+ * Each partition has its descriptor containing the partitions information and the UUID
642+ */
643+struct ffa_partition_desc {
644+ struct ffa_partition_info info;
645+ struct ffa_partition_uuid sp_uuid;
646+};
647+
648+/**
649+ * struct ffa_partitions - descriptors for all secure partitions
650+ * @count: The number of partitions descriptors
651+ * @descs The partitions descriptors table
652+ *
653+ * This data structure contains the partitions descriptors table
654+ */
655+struct ffa_partitions {
656+ u32 count;
657+ struct ffa_partition_desc *descs; /* virtual address */
658+};
659+
660+/**
661+ * struct ffa_prvdata - the driver private data structure
662+ *
663+ * @dev: The arm_ffa device under u-boot driver model
664+ * @ffa_ops: The driver operations structure
665+ * @fwk_version: FF-A framework version
666+ * @id: u-boot endpoint ID
667+ * @partitions: The partitions descriptors structure
668+ * @pair: The RX/TX buffers pair
669+ * @invoke_ffa_fn: The function executing the FF-A function
670+ *
671+ * The driver data structure hosting all resident data.
672+ */
673+struct ffa_prvdata {
674+ struct udevice *dev;
675+ struct ffa_bus_ops ffa_ops;
676+ u32 fwk_version;
677+ u16 id;
678+ struct ffa_partitions partitions;
679+ struct ffa_rxtxpair pair;
680+ invoke_ffa_fn_t invoke_ffa_fn;
681+};
682+
683+/**
Patrick Williams8dd68482022-10-04 07:57:18 -0500684+ * ffa_bus_prvdata_get - bus driver private data getter
685+ */
Andrew Geisslerea144b032023-01-27 16:03:57 -0600686+struct ffa_prvdata *ffa_bus_prvdata_get(void);
Patrick Williams8dd68482022-10-04 07:57:18 -0500687+
688+#endif
689diff --git a/drivers/firmware/arm-ffa/core.c b/drivers/firmware/arm-ffa/core.c
690new file mode 100644
Andrew Geisslerea144b032023-01-27 16:03:57 -0600691index 0000000000..0b1f8e6a07
Patrick Williams8dd68482022-10-04 07:57:18 -0500692--- /dev/null
693+++ b/drivers/firmware/arm-ffa/core.c
Andrew Geisslerea144b032023-01-27 16:03:57 -0600694@@ -0,0 +1,1315 @@
Patrick Williams8dd68482022-10-04 07:57:18 -0500695+// SPDX-License-Identifier: GPL-2.0+
696+/*
697+ * (C) Copyright 2022 ARM Limited
698+ * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
699+ */
700+
701+#include "arm_ffa_prv.h"
702+#include <asm/global_data.h>
703+#include <common.h>
704+#include <dm.h>
705+#include <dm/device-internal.h>
706+#include <dm/devres.h>
707+#include <dm/root.h>
708+#include <linux/errno.h>
709+#include <linux/sizes.h>
710+#include <log.h>
711+#include <malloc.h>
712+#include <string.h>
713+#include <uuid.h>
714+
715+DECLARE_GLOBAL_DATA_PTR;
716+
717+/**
Andrew Geisslerea144b032023-01-27 16:03:57 -0600718+ * The device private data structure containing all the
Patrick Williams8dd68482022-10-04 07:57:18 -0500719+ * data read from secure world
720+ */
Andrew Geisslerea144b032023-01-27 16:03:57 -0600721+struct ffa_prvdata *ffa_priv_data;
Patrick Williams8dd68482022-10-04 07:57:18 -0500722+
723+/* Error mapping declarations */
724+
Andrew Geisslerea144b032023-01-27 16:03:57 -0600725+int ffa_to_std_errmap[MAX_NUMBER_FFA_ERR] = {
726+ [NOT_SUPPORTED] = -EOPNOTSUPP,
727+ [INVALID_PARAMETERS] = -EINVAL,
728+ [NO_MEMORY] = -ENOMEM,
729+ [BUSY] = -EBUSY,
730+ [INTERRUPTED] = -EINTR,
731+ [DENIED] = -EACCES,
732+ [RETRY] = -EAGAIN,
733+ [ABORTED] = -ECANCELED,
Patrick Williams8dd68482022-10-04 07:57:18 -0500734+};
735+
736+struct ffa_abi_errmap err_msg_map[FFA_ERRMAP_COUNT] = {
737+ [FFA_ID_TO_ERRMAP_ID(FFA_VERSION)] = {
738+ {
Andrew Geisslerea144b032023-01-27 16:03:57 -0600739+ [NOT_SUPPORTED] =
Patrick Williams8dd68482022-10-04 07:57:18 -0500740+ "NOT_SUPPORTED: A Firmware Framework implementation does not exist",
Patrick Williams8dd68482022-10-04 07:57:18 -0500741+ },
742+ },
743+ [FFA_ID_TO_ERRMAP_ID(FFA_ID_GET)] = {
744+ {
Andrew Geisslerea144b032023-01-27 16:03:57 -0600745+ [NOT_SUPPORTED] =
Patrick Williams8dd68482022-10-04 07:57:18 -0500746+ "NOT_SUPPORTED: This function is not implemented at this FF-A instance",
Patrick Williams8dd68482022-10-04 07:57:18 -0500747+ },
748+ },
749+ [FFA_ID_TO_ERRMAP_ID(FFA_FEATURES)] = {
750+ {
Andrew Geisslerea144b032023-01-27 16:03:57 -0600751+ [NOT_SUPPORTED] =
Patrick Williams8dd68482022-10-04 07:57:18 -0500752+ "NOT_SUPPORTED: FFA_RXTX_MAP is not implemented at this FF-A instance",
Patrick Williams8dd68482022-10-04 07:57:18 -0500753+ },
754+ },
755+ [FFA_ID_TO_ERRMAP_ID(FFA_PARTITION_INFO_GET)] = {
756+ {
Andrew Geisslerea144b032023-01-27 16:03:57 -0600757+ [NOT_SUPPORTED] =
Patrick Williams8dd68482022-10-04 07:57:18 -0500758+ "NOT_SUPPORTED: This function is not implemented at this FF-A instance",
Andrew Geisslerea144b032023-01-27 16:03:57 -0600759+ [INVALID_PARAMETERS] =
Patrick Williams8dd68482022-10-04 07:57:18 -0500760+ "INVALID_PARAMETERS: Unrecognized UUID",
Andrew Geisslerea144b032023-01-27 16:03:57 -0600761+ [NO_MEMORY] =
Patrick Williams8dd68482022-10-04 07:57:18 -0500762+ "NO_MEMORY: Results cannot fit in RX buffer of the caller",
Andrew Geisslerea144b032023-01-27 16:03:57 -0600763+ [BUSY] =
Patrick Williams8dd68482022-10-04 07:57:18 -0500764+ "BUSY: RX buffer of the caller is not free",
Andrew Geisslerea144b032023-01-27 16:03:57 -0600765+ [DENIED] =
Patrick Williams8dd68482022-10-04 07:57:18 -0500766+ "DENIED: Callee is not in a state to handle this request",
Patrick Williams8dd68482022-10-04 07:57:18 -0500767+ },
768+ },
769+ [FFA_ID_TO_ERRMAP_ID(FFA_RXTX_UNMAP)] = {
Andrew Geisslerea144b032023-01-27 16:03:57 -0600770+ {
771+ [NOT_SUPPORTED] =
Patrick Williams8dd68482022-10-04 07:57:18 -0500772+ "NOT_SUPPORTED: FFA_RXTX_UNMAP is not implemented at this FF-A instance",
Andrew Geisslerea144b032023-01-27 16:03:57 -0600773+ [INVALID_PARAMETERS] =
Patrick Williams8dd68482022-10-04 07:57:18 -0500774+ "INVALID_PARAMETERS: No buffer pair registered on behalf of the caller",
Patrick Williams8dd68482022-10-04 07:57:18 -0500775+ },
776+ },
777+ [FFA_ID_TO_ERRMAP_ID(FFA_RX_RELEASE)] = {
Andrew Geisslerea144b032023-01-27 16:03:57 -0600778+ {
779+ [NOT_SUPPORTED] =
Patrick Williams8dd68482022-10-04 07:57:18 -0500780+ "NOT_SUPPORTED: FFA_RX_RELEASE is not implemented at this FF-A instance",
Andrew Geisslerea144b032023-01-27 16:03:57 -0600781+ [DENIED] =
Patrick Williams8dd68482022-10-04 07:57:18 -0500782+ "DENIED: Caller did not have ownership of the RX buffer",
Patrick Williams8dd68482022-10-04 07:57:18 -0500783+ },
784+ },
785+ [FFA_ID_TO_ERRMAP_ID(FFA_RXTX_MAP)] = {
Andrew Geisslerea144b032023-01-27 16:03:57 -0600786+ {
787+ [NOT_SUPPORTED] =
Patrick Williams8dd68482022-10-04 07:57:18 -0500788+ "NOT_SUPPORTED: This function is not implemented at this FF-A instance",
Andrew Geisslerea144b032023-01-27 16:03:57 -0600789+ [INVALID_PARAMETERS] =
Patrick Williams8dd68482022-10-04 07:57:18 -0500790+ "INVALID_PARAMETERS: Field(s) in input parameters incorrectly encoded",
Andrew Geisslerea144b032023-01-27 16:03:57 -0600791+ [NO_MEMORY] =
Patrick Williams8dd68482022-10-04 07:57:18 -0500792+ "NO_MEMORY: Not enough memory",
Andrew Geisslerea144b032023-01-27 16:03:57 -0600793+ [DENIED] =
Patrick Williams8dd68482022-10-04 07:57:18 -0500794+ "DENIED: Buffer pair already registered",
Patrick Williams8dd68482022-10-04 07:57:18 -0500795+ },
796+ },
797+};
798+
799+/**
800+ * ffa_to_std_errno - convert FF-A error code to standard error code
801+ * @ffa_errno: Error code returned by the FF-A ABI
802+ *
Andrew Geisslerea144b032023-01-27 16:03:57 -0600803+ * This function maps the given FF-A error code as specified
Patrick Williams8dd68482022-10-04 07:57:18 -0500804+ * by the spec to a u-boot standard error code.
805+ *
806+ * Return:
807+ *
808+ * The standard error code on success. . Otherwise, failure
809+ */
Andrew Geisslerea144b032023-01-27 16:03:57 -0600810+int ffa_to_std_errno(int ffa_errno)
Patrick Williams8dd68482022-10-04 07:57:18 -0500811+{
812+ int err_idx = -ffa_errno;
813+
814+ /* map the FF-A error code to the standard u-boot error code */
815+ if (err_idx > 0 && err_idx < MAX_NUMBER_FFA_ERR)
816+ return ffa_to_std_errmap[err_idx];
817+ return -EINVAL;
818+}
819+
820+/**
821+ * ffa_print_error_log - print the error log corresponding to the selected FF-A ABI
822+ * @ffa_id: FF-A ABI ID
823+ * @ffa_errno: Error code returned by the FF-A ABI
824+ *
Andrew Geisslerea144b032023-01-27 16:03:57 -0600825+ * This function maps the FF-A error code to the error log relevant to the
Patrick Williams8dd68482022-10-04 07:57:18 -0500826+ * selected FF-A ABI. Then the error log is printed.
827+ *
828+ * Return:
829+ *
830+ * 0 on success. . Otherwise, failure
831+ */
832+int ffa_print_error_log(u32 ffa_id, int ffa_errno)
833+{
834+ int err_idx = -ffa_errno, abi_idx = 0;
835+
836+ /* map the FF-A error code to the corresponding error log */
837+
838+ if (err_idx <= 0 || err_idx >= MAX_NUMBER_FFA_ERR)
839+ return -EINVAL;
840+
841+ if (ffa_id < FFA_FIRST_ID || ffa_id > FFA_LAST_ID)
842+ return -EINVAL;
843+
844+ abi_idx = FFA_ID_TO_ERRMAP_ID(ffa_id);
845+ if (abi_idx < 0 || abi_idx >= FFA_ERRMAP_COUNT)
846+ return -EINVAL;
847+
Andrew Geisslerea144b032023-01-27 16:03:57 -0600848+ if (!err_msg_map[abi_idx].err_str[err_idx])
Patrick Williams8dd68482022-10-04 07:57:18 -0500849+ return -EINVAL;
850+
851+ ffa_err("%s", err_msg_map[abi_idx].err_str[err_idx]);
852+
853+ return 0;
854+}
855+
856+/*
857+ * Driver core functions
858+ */
859+
860+/**
861+ * ffa_remove_device - removes the arm_ffa device
862+ * @dev: the device to be removed
863+ *
Andrew Geisslerea144b032023-01-27 16:03:57 -0600864+ * This function makes sure the arm_ffa device is removed
Patrick Williams8dd68482022-10-04 07:57:18 -0500865+ * No need to free the kmalloced data when the device is destroyed.
866+ * It's automatically done by devm management by
867+ * device_remove() -> device_free() -> devres_release_probe().
868+ *
869+ * Return:
870+ *
871+ * 0 on success. Otherwise, failure
872+ */
873+int ffa_remove_device(struct udevice *dev)
874+{
875+ int ret;
876+
877+ if (!dev) {
878+ ffa_err("no udevice found");
879+ return -ENODEV;
880+ }
881+
882+ ret = device_remove(dev, DM_REMOVE_NORMAL);
883+ if (ret) {
884+ ffa_err("unable to remove. err:%d\n", ret);
885+ return ret;
886+ }
887+
888+ ffa_info("device removed and freed");
889+
890+ ret = device_unbind(dev);
891+ if (ret) {
892+ ffa_err("unable to unbind. err:%d\n", ret);
893+ return ret;
894+ }
895+
896+ ffa_info("device unbound");
897+
898+ return 0;
899+}
900+
901+/**
902+ * ffa_device_get - create, bind and probe the arm_ffa device
Andrew Geisslerea144b032023-01-27 16:03:57 -0600903+ * @pdev: the address of a device pointer (to be filled when the arm_ffa bus device is created
904+ * successfully)
Patrick Williams8dd68482022-10-04 07:57:18 -0500905+ *
Andrew Geisslerea144b032023-01-27 16:03:57 -0600906+ * This function makes sure the arm_ffa device is
Patrick Williams8dd68482022-10-04 07:57:18 -0500907+ * created, bound to this driver, probed and ready to use.
Andrew Geisslerea144b032023-01-27 16:03:57 -0600908+ * Arm FF-A transport is implemented through a single U-Boot
Patrick Williams8dd68482022-10-04 07:57:18 -0500909+ * device managing the FF-A bus (arm_ffa).
910+ *
911+ * Return:
912+ *
913+ * 0 on success. Otherwise, failure
914+ */
Andrew Geisslerea144b032023-01-27 16:03:57 -0600915+int ffa_device_get(struct udevice **pdev)
Patrick Williams8dd68482022-10-04 07:57:18 -0500916+{
917+ int ret;
918+ struct udevice *dev = NULL;
919+
Andrew Geisslerea144b032023-01-27 16:03:57 -0600920+ ret = device_bind(dm_root(), DM_DRIVER_GET(arm_ffa), FFA_DRV_NAME, NULL, ofnode_null(),
Patrick Williams8dd68482022-10-04 07:57:18 -0500921+ &dev);
922+ if (ret)
923+ return ret;
924+
925+ /* The FF-A bus discovery succeeds when probing is successful */
926+ ret = device_probe(dev);
927+ if (ret) {
928+ ffa_err("arm_ffa device probing failed");
929+ ffa_remove_device(dev);
930+ return ret;
931+ }
932+
Andrew Geisslerea144b032023-01-27 16:03:57 -0600933+ if (pdev)
934+ *pdev = dev;
935+
Patrick Williams8dd68482022-10-04 07:57:18 -0500936+ return 0;
937+}
938+
939+/**
940+ * ffa_get_version - FFA_VERSION handler function
941+ *
Andrew Geisslerea144b032023-01-27 16:03:57 -0600942+ * This function implements FFA_VERSION FF-A function
Patrick Williams8dd68482022-10-04 07:57:18 -0500943+ * to get from the secure world the FF-A framework version
944+ *
945+ * Return:
946+ *
947+ * 0 on success. Otherwise, failure
948+ */
949+static int ffa_get_version(void)
950+{
951+ u16 major, minor;
952+ ffa_value_t res = {0};
953+ int ffa_errno;
954+
955+ ffa_priv_data->invoke_ffa_fn((ffa_value_t){
Andrew Geisslerea144b032023-01-27 16:03:57 -0600956+ .a0 = FFA_SMC_32(FFA_VERSION), .a1 = FFA_VERSION_1_0,
Patrick Williams8dd68482022-10-04 07:57:18 -0500957+ }, &res);
958+
Andrew Geisslerea144b032023-01-27 16:03:57 -0600959+ ffa_errno = res.a0;
Patrick Williams8dd68482022-10-04 07:57:18 -0500960+ if (ffa_errno < 0) {
961+ ffa_print_error_log(FFA_VERSION, ffa_errno);
962+ return ffa_to_std_errno(ffa_errno);
963+ }
964+
Andrew Geisslerea144b032023-01-27 16:03:57 -0600965+ major = GET_FFA_MAJOR_VERSION(res.a0);
966+ minor = GET_FFA_MINOR_VERSION(res.a0);
Patrick Williams8dd68482022-10-04 07:57:18 -0500967+
968+ ffa_info("FF-A driver %d.%d\nFF-A framework %d.%d",
969+ FFA_MAJOR_VERSION, FFA_MINOR_VERSION, major, minor);
970+
971+ if ((major == FFA_MAJOR_VERSION && minor >= FFA_MINOR_VERSION)) {
972+ ffa_info("Versions are compatible ");
973+
Andrew Geisslerea144b032023-01-27 16:03:57 -0600974+ ffa_priv_data->fwk_version = res.a0;
Patrick Williams8dd68482022-10-04 07:57:18 -0500975+
976+ return 0;
977+ }
978+
979+ ffa_err("versions are incompatible\nExpected: %d.%d , Found: %d.%d\n",
980+ FFA_MAJOR_VERSION, FFA_MINOR_VERSION, major, minor);
981+
982+ return -EPROTONOSUPPORT;
983+}
984+
985+/**
986+ * ffa_get_endpoint_id - FFA_ID_GET handler function
987+ *
Andrew Geisslerea144b032023-01-27 16:03:57 -0600988+ * This function implements FFA_ID_GET FF-A function
Patrick Williams8dd68482022-10-04 07:57:18 -0500989+ * to get from the secure world u-boot endpoint ID
990+ *
991+ * Return:
992+ *
993+ * 0 on success. Otherwise, failure
994+ */
995+static int ffa_get_endpoint_id(void)
996+{
997+ ffa_value_t res = {0};
998+ int ffa_errno;
999+
1000+ ffa_priv_data->invoke_ffa_fn((ffa_value_t){
1001+ .a0 = FFA_SMC_32(FFA_ID_GET),
Patrick Williams8dd68482022-10-04 07:57:18 -05001002+ }, &res);
1003+
1004+ if (res.a0 == FFA_SMC_32(FFA_SUCCESS)) {
1005+ ffa_priv_data->id = GET_SELF_ENDPOINT_ID((u32)res.a2);
1006+ ffa_info("endpoint ID is %u", ffa_priv_data->id);
1007+
1008+ return 0;
1009+ }
1010+
Andrew Geisslerea144b032023-01-27 16:03:57 -06001011+ ffa_errno = res.a2;
Patrick Williams8dd68482022-10-04 07:57:18 -05001012+
1013+ ffa_print_error_log(FFA_ID_GET, ffa_errno);
1014+
1015+ return ffa_to_std_errno(ffa_errno);
1016+}
1017+
1018+/**
1019+ * ffa_set_rxtx_buffers_pages_cnt - sets the minimum number of pages in each of the RX/TX buffers
1020+ * @prop_field: properties field obtained from FFA_FEATURES ABI
1021+ *
Andrew Geisslerea144b032023-01-27 16:03:57 -06001022+ * This function sets the minimum number of pages
Patrick Williams8dd68482022-10-04 07:57:18 -05001023+ * in each of the RX/TX buffers in the private data structure
1024+ *
1025+ * Return:
1026+ *
1027+ * buf_4k_pages points to the returned number of pages
1028+ * 0 on success. Otherwise, failure
1029+ */
1030+static int ffa_set_rxtx_buffers_pages_cnt(u32 prop_field)
1031+{
1032+ if (!ffa_priv_data)
1033+ return -EINVAL;
1034+
1035+ switch (prop_field) {
1036+ case RXTX_4K:
1037+ ffa_priv_data->pair.rxtx_min_pages = 1;
1038+ break;
1039+ case RXTX_16K:
1040+ ffa_priv_data->pair.rxtx_min_pages = 4;
1041+ break;
1042+ case RXTX_64K:
1043+ ffa_priv_data->pair.rxtx_min_pages = 16;
1044+ break;
1045+ default:
1046+ ffa_err("RX/TX buffer size not supported");
1047+ return -EINVAL;
1048+ }
1049+
1050+ return 0;
1051+}
1052+
1053+/**
1054+ * ffa_get_rxtx_map_features - FFA_FEATURES handler function with FFA_RXTX_MAP argument
1055+ *
Andrew Geisslerea144b032023-01-27 16:03:57 -06001056+ * This function implements FFA_FEATURES FF-A function
Patrick Williams8dd68482022-10-04 07:57:18 -05001057+ * to retrieve the FFA_RXTX_MAP features
1058+ *
1059+ * Return:
1060+ *
1061+ * 0 on success. Otherwise, failure
1062+ */
1063+static int ffa_get_rxtx_map_features(void)
1064+{
1065+ ffa_value_t res = {0};
1066+ int ffa_errno;
1067+
1068+ ffa_priv_data->invoke_ffa_fn((ffa_value_t){
1069+ .a0 = FFA_SMC_32(FFA_FEATURES),
1070+ .a1 = FFA_SMC_64(FFA_RXTX_MAP),
Patrick Williams8dd68482022-10-04 07:57:18 -05001071+ }, &res);
1072+
1073+ if (res.a0 == FFA_SMC_32(FFA_SUCCESS))
Andrew Geisslerea144b032023-01-27 16:03:57 -06001074+ return ffa_set_rxtx_buffers_pages_cnt(res.a2);
Patrick Williams8dd68482022-10-04 07:57:18 -05001075+
Andrew Geisslerea144b032023-01-27 16:03:57 -06001076+ ffa_errno = res.a2;
Patrick Williams8dd68482022-10-04 07:57:18 -05001077+ ffa_print_error_log(FFA_FEATURES, ffa_errno);
1078+
1079+ return ffa_to_std_errno(ffa_errno);
1080+}
1081+
1082+/**
1083+ * ffa_free_rxtx_buffers - frees the RX/TX buffers
1084+ *
Andrew Geisslerea144b032023-01-27 16:03:57 -06001085+ * This function frees the RX/TX buffers
Patrick Williams8dd68482022-10-04 07:57:18 -05001086+ *
1087+ */
1088+static void ffa_free_rxtx_buffers(void)
1089+{
1090+ ffa_info("Freeing RX/TX buffers");
1091+
1092+ if (ffa_priv_data->pair.rxbuf) {
1093+ free((void *)ffa_priv_data->pair.rxbuf);
1094+ ffa_priv_data->pair.rxbuf = 0;
1095+ }
1096+
1097+ if (ffa_priv_data->pair.txbuf) {
1098+ free((void *)ffa_priv_data->pair.txbuf);
1099+ ffa_priv_data->pair.txbuf = 0;
1100+ }
1101+}
1102+
1103+/**
1104+ * ffa_alloc_rxtx_buffers - allocates the RX/TX buffers
1105+ *
Andrew Geisslerea144b032023-01-27 16:03:57 -06001106+ * This function is used by ffa_map_rxtx_buffers to allocate
Patrick Williams8dd68482022-10-04 07:57:18 -05001107+ * the RX/TX buffers before mapping them. The allocated memory is physically
1108+ * contiguous since memalign ends up calling malloc which allocates
1109+ * contiguous memory in u-boot.
1110+ *
1111+ * Return:
1112+ *
1113+ * 0 on success. Otherwise, failure
1114+ */
1115+static int ffa_alloc_rxtx_buffers(void)
1116+{
1117+ u64 bytes;
1118+
1119+ ffa_info("Using %lu 4KB page(s) for RX/TX buffers size",
1120+ ffa_priv_data->pair.rxtx_min_pages);
1121+
1122+ bytes = ffa_priv_data->pair.rxtx_min_pages * SZ_4K;
1123+
Andrew Geisslerea144b032023-01-27 16:03:57 -06001124+ /*
1125+ * The alignment of the RX and TX buffers must be equal
1126+ * to the larger translation granule size
1127+ */
Patrick Williams8dd68482022-10-04 07:57:18 -05001128+
Andrew Geisslerea144b032023-01-27 16:03:57 -06001129+ ffa_priv_data->pair.rxbuf = (u64)memalign(bytes, bytes);
Patrick Williams8dd68482022-10-04 07:57:18 -05001130+ if (!ffa_priv_data->pair.rxbuf) {
1131+ ffa_err("failure to allocate RX buffer");
1132+ return -ENOBUFS;
1133+ }
1134+
1135+ ffa_info("RX buffer at virtual address 0x%llx", ffa_priv_data->pair.rxbuf);
1136+
Andrew Geisslerea144b032023-01-27 16:03:57 -06001137+ ffa_priv_data->pair.txbuf = (u64)memalign(bytes, bytes);
Patrick Williams8dd68482022-10-04 07:57:18 -05001138+ if (!ffa_priv_data->pair.txbuf) {
1139+ free((void *)ffa_priv_data->pair.rxbuf);
1140+ ffa_priv_data->pair.rxbuf = 0;
1141+ ffa_err("failure to allocate the TX buffer");
1142+ return -ENOBUFS;
1143+ }
1144+
1145+ ffa_info("TX buffer at virtual address 0x%llx", ffa_priv_data->pair.txbuf);
1146+
1147+ /*
1148+ * make sure the buffers are cleared before use
1149+ */
1150+ memset((void *)ffa_priv_data->pair.rxbuf, 0, bytes);
1151+ memset((void *)ffa_priv_data->pair.txbuf, 0, bytes);
1152+
1153+ return 0;
1154+}
1155+
1156+/**
1157+ * ffa_map_rxtx_buffers - FFA_RXTX_MAP handler function
1158+ *
Andrew Geisslerea144b032023-01-27 16:03:57 -06001159+ * This function implements FFA_RXTX_MAP FF-A function
Patrick Williams8dd68482022-10-04 07:57:18 -05001160+ * to map the RX/TX buffers
1161+ *
1162+ * Return:
1163+ *
1164+ * 0 on success. Otherwise, failure
1165+ */
1166+static int ffa_map_rxtx_buffers(void)
1167+{
1168+ int ret;
1169+ ffa_value_t res = {0};
1170+ int ffa_errno;
1171+
1172+ ret = ffa_alloc_rxtx_buffers();
1173+ if (ret)
1174+ return ret;
1175+
1176+ /*
1177+ * we need to pass the physical addresses of the RX/TX buffers
1178+ * in u-boot physical/virtual mapping is 1:1
Andrew Geisslerea144b032023-01-27 16:03:57 -06001179+ * no need to convert from virtual to physical
Patrick Williams8dd68482022-10-04 07:57:18 -05001180+ */
1181+
1182+ ffa_priv_data->invoke_ffa_fn((ffa_value_t){
1183+ .a0 = FFA_SMC_64(FFA_RXTX_MAP),
1184+ .a1 = ffa_priv_data->pair.txbuf,
1185+ .a2 = ffa_priv_data->pair.rxbuf,
1186+ .a3 = ffa_priv_data->pair.rxtx_min_pages,
Patrick Williams8dd68482022-10-04 07:57:18 -05001187+ }, &res);
1188+
1189+ if (res.a0 == FFA_SMC_32(FFA_SUCCESS)) {
1190+ ffa_info("RX/TX buffers mapped");
1191+ return 0;
1192+ }
1193+
Andrew Geisslerea144b032023-01-27 16:03:57 -06001194+ ffa_errno = res.a2;
Patrick Williams8dd68482022-10-04 07:57:18 -05001195+ ffa_print_error_log(FFA_RXTX_MAP, ffa_errno);
1196+
1197+ ffa_free_rxtx_buffers();
1198+
1199+ return ffa_to_std_errno(ffa_errno);
1200+}
1201+
1202+/**
1203+ * ffa_unmap_rxtx_buffers - FFA_RXTX_UNMAP handler function
Andrew Geisslerea144b032023-01-27 16:03:57 -06001204+ * @dev: The arm_ffa bus device
Patrick Williams8dd68482022-10-04 07:57:18 -05001205+ *
Andrew Geisslerea144b032023-01-27 16:03:57 -06001206+ * This function implements FFA_RXTX_UNMAP FF-A function
Patrick Williams8dd68482022-10-04 07:57:18 -05001207+ * to unmap the RX/TX buffers
1208+ *
1209+ * Return:
1210+ *
1211+ * 0 on success. Otherwise, failure
1212+ */
Andrew Geisslerea144b032023-01-27 16:03:57 -06001213+static int ffa_unmap_rxtx_buffers(struct udevice *dev)
Patrick Williams8dd68482022-10-04 07:57:18 -05001214+{
1215+ ffa_value_t res = {0};
1216+ int ffa_errno;
1217+
1218+ ffa_priv_data->invoke_ffa_fn((ffa_value_t){
1219+ .a0 = FFA_SMC_32(FFA_RXTX_UNMAP),
1220+ .a1 = PREP_SELF_ENDPOINT_ID(ffa_priv_data->id),
Patrick Williams8dd68482022-10-04 07:57:18 -05001221+ }, &res);
1222+
1223+ if (res.a0 == FFA_SMC_32(FFA_SUCCESS)) {
1224+ ffa_free_rxtx_buffers();
1225+ return 0;
1226+ }
1227+
Andrew Geisslerea144b032023-01-27 16:03:57 -06001228+ ffa_errno = res.a2;
Patrick Williams8dd68482022-10-04 07:57:18 -05001229+ ffa_print_error_log(FFA_RXTX_UNMAP, ffa_errno);
1230+
1231+ return ffa_to_std_errno(ffa_errno);
1232+}
1233+
1234+/**
1235+ * ffa_release_rx_buffer - FFA_RX_RELEASE handler function
1236+ *
Andrew Geisslerea144b032023-01-27 16:03:57 -06001237+ * This function invokes FFA_RX_RELEASE FF-A function
Patrick Williams8dd68482022-10-04 07:57:18 -05001238+ * to release the ownership of the RX buffer
1239+ *
1240+ * Return:
1241+ *
1242+ * 0 on success. Otherwise, failure
1243+ */
1244+static int ffa_release_rx_buffer(void)
1245+{
1246+ ffa_value_t res = {0};
1247+ int ffa_errno;
1248+
1249+ ffa_priv_data->invoke_ffa_fn((ffa_value_t){
1250+ .a0 = FFA_SMC_32(FFA_RX_RELEASE),
Patrick Williams8dd68482022-10-04 07:57:18 -05001251+ }, &res);
1252+
1253+ if (res.a0 == FFA_SMC_32(FFA_SUCCESS))
1254+ return 0;
1255+
Andrew Geisslerea144b032023-01-27 16:03:57 -06001256+ ffa_errno = res.a2;
Patrick Williams8dd68482022-10-04 07:57:18 -05001257+ ffa_print_error_log(FFA_RX_RELEASE, ffa_errno);
1258+
1259+ return ffa_to_std_errno(ffa_errno);
1260+}
1261+
1262+/**
1263+ * ffa_uuid_are_identical - checks whether two given UUIDs are identical
1264+ * @uuid1: first UUID
1265+ * @uuid2: second UUID
1266+ *
Andrew Geisslerea144b032023-01-27 16:03:57 -06001267+ * This function is used by ffa_read_partitions_info to search
Patrick Williams8dd68482022-10-04 07:57:18 -05001268+ * for a UUID in the partitions descriptors table
1269+ *
1270+ * Return:
1271+ *
1272+ * 1 when UUIDs match. Otherwise, 0
1273+ */
Andrew Geisslerea144b032023-01-27 16:03:57 -06001274+bool ffa_uuid_are_identical(const struct ffa_partition_uuid *uuid1,
1275+ const struct ffa_partition_uuid *uuid2)
Patrick Williams8dd68482022-10-04 07:57:18 -05001276+{
1277+ if (!uuid1 || !uuid2)
1278+ return 0;
1279+
Andrew Geisslerea144b032023-01-27 16:03:57 -06001280+ return !memcmp(uuid1, uuid2, sizeof(struct ffa_partition_uuid));
Patrick Williams8dd68482022-10-04 07:57:18 -05001281+}
1282+
1283+/**
1284+ * ffa_read_partitions_info - reads the data queried by FFA_PARTITION_INFO_GET
1285+ * and saves it in the private structure
1286+ * @count: The number of partitions queried
1287+ * @part_uuid: Pointer to the partition(s) UUID
1288+ *
Andrew Geisslerea144b032023-01-27 16:03:57 -06001289+ * This function reads the partitions information
Patrick Williams8dd68482022-10-04 07:57:18 -05001290+ * returned by the FFA_PARTITION_INFO_GET and saves it in the private
1291+ * data structure.
1292+ *
1293+ * Return:
1294+ *
1295+ * The private data structure is updated with the partition(s) information
1296+ * 0 is returned on success. Otherwise, failure
1297+ */
1298+static int ffa_read_partitions_info(u32 count, struct ffa_partition_uuid *part_uuid)
1299+{
1300+ if (!count) {
1301+ ffa_err("no partition detected");
1302+ return -ENODATA;
1303+ }
1304+
1305+ ffa_info("Reading partitions data from the RX buffer");
1306+
1307+ if (!part_uuid) {
1308+ /*
1309+ * querying information of all partitions
1310+ */
1311+ u64 buf_bytes;
1312+ u64 data_bytes;
1313+ u32 desc_idx;
1314+ struct ffa_partition_info *parts_info;
1315+
1316+ data_bytes = count * sizeof(struct ffa_partition_desc);
1317+
1318+ buf_bytes = ffa_priv_data->pair.rxtx_min_pages * SZ_4K;
1319+
1320+ if (data_bytes > buf_bytes) {
1321+ ffa_err("partitions data size exceeds the RX buffer size:");
1322+ ffa_err(" sizes in bytes: data %llu , RX buffer %llu ",
1323+ data_bytes,
1324+ buf_bytes);
1325+
1326+ return -ENOMEM;
1327+ }
1328+
Andrew Geisslerea144b032023-01-27 16:03:57 -06001329+ ffa_priv_data->partitions.descs = devm_kmalloc(ffa_priv_data->dev, data_bytes,
1330+ __GFP_ZERO);
Patrick Williams8dd68482022-10-04 07:57:18 -05001331+ if (!ffa_priv_data->partitions.descs) {
1332+ ffa_err("cannot allocate partitions data buffer");
1333+ return -ENOMEM;
1334+ }
1335+
1336+ parts_info = (struct ffa_partition_info *)ffa_priv_data->pair.rxbuf;
1337+
1338+ for (desc_idx = 0 ; desc_idx < count ; desc_idx++) {
1339+ ffa_priv_data->partitions.descs[desc_idx].info =
1340+ parts_info[desc_idx];
1341+
1342+ ffa_info("Partition ID %x : info cached",
1343+ ffa_priv_data->partitions.descs[desc_idx].info.id);
1344+ }
1345+
1346+ ffa_priv_data->partitions.count = count;
1347+
1348+ ffa_info("%d partition(s) found and cached", count);
1349+
1350+ } else {
1351+ u32 rx_desc_idx, cached_desc_idx;
1352+ struct ffa_partition_info *parts_info;
1353+ u8 desc_found;
1354+
1355+ parts_info = (struct ffa_partition_info *)ffa_priv_data->pair.rxbuf;
1356+
1357+ /*
1358+ * search for the SP IDs read from the RX buffer
1359+ * in the already cached SPs.
1360+ * Update the UUID when ID found.
1361+ */
1362+ for (rx_desc_idx = 0; rx_desc_idx < count ; rx_desc_idx++) {
1363+ desc_found = 0;
1364+
1365+ /*
1366+ * search the current ID in the cached partitions
1367+ */
1368+ for (cached_desc_idx = 0;
1369+ cached_desc_idx < ffa_priv_data->partitions.count;
1370+ cached_desc_idx++) {
1371+ /*
1372+ * save the UUID
1373+ */
1374+ if (ffa_priv_data->partitions.descs[cached_desc_idx].info.id ==
1375+ parts_info[rx_desc_idx].id) {
1376+ ffa_priv_data->partitions.descs[cached_desc_idx].sp_uuid =
1377+ *part_uuid;
1378+
1379+ desc_found = 1;
1380+ break;
1381+ }
1382+ }
1383+
1384+ if (!desc_found)
1385+ return -ENODATA;
1386+ }
1387+ }
1388+
1389+ return 0;
1390+}
1391+
1392+/**
1393+ * ffa_query_partitions_info - invokes FFA_PARTITION_INFO_GET and saves partitions data
1394+ *
1395+ * @part_uuid: Pointer to the partition(s) UUID
1396+ * @pcount: Pointer to the number of partitions variable filled when querying
1397+ *
Andrew Geisslerea144b032023-01-27 16:03:57 -06001398+ * This function executes the FFA_PARTITION_INFO_GET
Patrick Williams8dd68482022-10-04 07:57:18 -05001399+ * to query the partitions data. Then, it calls ffa_read_partitions_info
1400+ * to save the data in the private data structure.
1401+ *
1402+ * After reading the data the RX buffer is released using ffa_release_rx_buffer
1403+ *
1404+ * Return:
1405+ *
1406+ * When part_uuid is NULL, all partitions data are retrieved from secure world
1407+ * When part_uuid is non NULL, data for partitions matching the given UUID are
1408+ * retrieved and the number of partitions is returned
1409+ * 0 is returned on success. Otherwise, failure
1410+ */
1411+static int ffa_query_partitions_info(struct ffa_partition_uuid *part_uuid,
1412+ u32 *pcount)
1413+{
1414+ struct ffa_partition_uuid query_uuid = {0};
1415+ ffa_value_t res = {0};
1416+ int ffa_errno;
1417+
1418+ /*
1419+ * If a UUID is specified. Information for one or more
1420+ * partitions in the system is queried. Otherwise, information
1421+ * for all installed partitions is queried
1422+ */
1423+
1424+ if (part_uuid) {
1425+ if (!pcount)
1426+ return -EINVAL;
1427+
1428+ query_uuid = *part_uuid;
1429+ } else if (pcount) {
1430+ return -EINVAL;
1431+ }
1432+
1433+ ffa_priv_data->invoke_ffa_fn((ffa_value_t){
1434+ .a0 = FFA_SMC_32(FFA_PARTITION_INFO_GET),
1435+ .a1 = query_uuid.a1,
1436+ .a2 = query_uuid.a2,
1437+ .a3 = query_uuid.a3,
1438+ .a4 = query_uuid.a4,
Patrick Williams8dd68482022-10-04 07:57:18 -05001439+ }, &res);
1440+
1441+ if (res.a0 == FFA_SMC_32(FFA_SUCCESS)) {
1442+ int ret;
1443+
1444+ /*
1445+ * res.a2 contains the count of partition information descriptors
1446+ * populated in the RX buffer
1447+ */
1448+ if (res.a2) {
1449+ ret = ffa_read_partitions_info((u32)res.a2, part_uuid);
1450+ if (ret) {
1451+ ffa_err("failed to read partition(s) data , error (%d)", ret);
1452+ ffa_release_rx_buffer();
1453+ return -EINVAL;
1454+ }
1455+ }
1456+
1457+ /*
1458+ * return the SP count (when querying using a UUID)
1459+ */
1460+ if (pcount)
1461+ *pcount = (u32)res.a2;
1462+
1463+ /*
1464+ * After calling FFA_PARTITION_INFO_GET the buffer ownership
1465+ * is assigned to the consumer (u-boot). So, we need to give
1466+ * the ownership back to the SPM or hypervisor
1467+ */
1468+ ret = ffa_release_rx_buffer();
1469+
1470+ return ret;
1471+ }
1472+
Andrew Geisslerea144b032023-01-27 16:03:57 -06001473+ ffa_errno = res.a2;
Patrick Williams8dd68482022-10-04 07:57:18 -05001474+ ffa_print_error_log(FFA_PARTITION_INFO_GET, ffa_errno);
1475+
1476+ return ffa_to_std_errno(ffa_errno);
1477+}
1478+
1479+/**
1480+ * ffa_get_partitions_info - FFA_PARTITION_INFO_GET handler function
1481+ *
1482+ * The passed arguments:
1483+ * Mode 1: When getting from the driver the number of
1484+ * secure partitions:
1485+ * @uuid_str: pointer to the UUID string
Andrew Geisslerea144b032023-01-27 16:03:57 -06001486+ * @sp_count: pointer to the variable that contains the number of partitions
Patrick Williams8dd68482022-10-04 07:57:18 -05001487+ * The variable will be set by the driver
1488+ * @buffer: NULL
1489+ *
1490+ * Mode 2: When requesting the driver to return the
1491+ * partitions information:
Andrew Geisslerea144b032023-01-27 16:03:57 -06001492+ * @dev: The arm_ffa bus device
Patrick Williams8dd68482022-10-04 07:57:18 -05001493+ * @uuid_str: pointer to the UUID string
Andrew Geisslerea144b032023-01-27 16:03:57 -06001494+ * @sp_count: pointer to the variable that contains the number of empty partition descriptors
1495+ * The variable will be read by the driver
Patrick Williams8dd68482022-10-04 07:57:18 -05001496+ * @buffer: pointer to SPs information buffer
Andrew Geisslerea144b032023-01-27 16:03:57 -06001497+ * (allocated by the client and contains empty @sp_count descriptors).
Patrick Williams8dd68482022-10-04 07:57:18 -05001498+ * The buffer will be filled by the driver
1499+ *
Andrew Geisslerea144b032023-01-27 16:03:57 -06001500+ * This function queries the secure partition data from
Patrick Williams8dd68482022-10-04 07:57:18 -05001501+ * the private data structure. If not found, it invokes FFA_PARTITION_INFO_GET
1502+ * FF-A function to query the partition information from secure world.
1503+ *
1504+ * A client of the FF-A driver should know the UUID of the service it wants to
1505+ * access. It should use the UUID to request the FF-A driver to provide the
1506+ * partition(s) information of the service. The FF-A driver uses
1507+ * PARTITION_INFO_GET to obtain this information. This is implemented through
1508+ * ffa_get_partitions_info function.
1509+ * A new FFA_PARTITION_INFO_GET call is issued (first one performed through
1510+ * ffa_cache_partitions_info) allowing to retrieve the partition(s) information.
1511+ * They are not saved (already done). We only update the UUID in the cached area.
1512+ * This assumes that partitions data does not change in the secure world.
1513+ * Otherwise u-boot will have an outdated partition data. The benefit of caching
1514+ * the information in the FF-A driver is to accommodate discovery after
1515+ * ExitBootServices().
1516+ *
1517+ * When invoked through a client request, ffa_get_partitions_info should be
1518+ * called twice. First call is to get from the driver the number of secure
1519+ * partitions (SPs) associated to a particular UUID.
1520+ * Then, the caller (client) allocates the buffer to host the SPs data and
1521+ * issues a 2nd call. Then, the driver fills the SPs data in the pre-allocated
1522+ * buffer.
1523+ *
1524+ * To achieve the mechanism described above, ffa_get_partitions_info uses the
1525+ * following functions:
1526+ * ffa_read_partitions_info
1527+ * ffa_query_partitions_info
1528+ *
1529+ * Return:
1530+ *
Andrew Geisslerea144b032023-01-27 16:03:57 -06001531+ * @sp_count: When pointing to the number of partitions variable, the number is
Patrick Williams8dd68482022-10-04 07:57:18 -05001532+ * set by the driver.
1533+ * When pointing to the partitions information buffer size, the buffer will be
1534+ * filled by the driver.
1535+ *
1536+ * On success 0 is returned. Otherwise, failure
1537+ */
Andrew Geisslerea144b032023-01-27 16:03:57 -06001538+static int ffa_get_partitions_info(struct udevice *dev, const char *uuid_str,
1539+ u32 *sp_count, struct ffa_partition_info *buffer)
Patrick Williams8dd68482022-10-04 07:57:18 -05001540+{
1541+ /*
1542+ * fill_data:
1543+ * 0: return the SP count
1544+ * 1: fill SP data and return it to the caller
Patrick Williams8dd68482022-10-04 07:57:18 -05001545+ */
Andrew Geisslerea144b032023-01-27 16:03:57 -06001546+ bool fill_data = 0;
Patrick Williams8dd68482022-10-04 07:57:18 -05001547+ u32 desc_idx, client_desc_idx;
1548+ struct ffa_partition_uuid part_uuid = {0};
Andrew Geisslerea144b032023-01-27 16:03:57 -06001549+ u32 sp_found = 0;
Patrick Williams8dd68482022-10-04 07:57:18 -05001550+
1551+ if (!ffa_priv_data->partitions.count || !ffa_priv_data->partitions.descs) {
1552+ ffa_err("no partition installed");
1553+ return -EINVAL;
1554+ }
1555+
1556+ if (!uuid_str) {
1557+ ffa_err("no UUID provided");
1558+ return -EINVAL;
1559+ }
1560+
Andrew Geisslerea144b032023-01-27 16:03:57 -06001561+ if (!sp_count) {
Patrick Williams8dd68482022-10-04 07:57:18 -05001562+ ffa_err("no size/count provided");
1563+ return -EINVAL;
1564+ }
1565+
Andrew Geisslerea144b032023-01-27 16:03:57 -06001566+ if (uuid_str_to_le_bin(uuid_str, (unsigned char *)&part_uuid)) {
Patrick Williams8dd68482022-10-04 07:57:18 -05001567+ ffa_err("invalid UUID");
1568+ return -EINVAL;
1569+ }
1570+
1571+ if (!buffer) {
1572+ /* Mode 1: getting the number of secure partitions */
1573+
1574+ fill_data = 0;
1575+
1576+ ffa_info("Preparing for checking partitions count");
1577+
Andrew Geisslerea144b032023-01-27 16:03:57 -06001578+ } else if (*sp_count) {
Patrick Williams8dd68482022-10-04 07:57:18 -05001579+ /* Mode 2: retrieving the partitions information */
1580+
1581+ fill_data = 1;
1582+
1583+ client_desc_idx = 0;
1584+
Patrick Williams8dd68482022-10-04 07:57:18 -05001585+ ffa_info("Preparing for filling partitions info");
1586+
1587+ } else {
1588+ ffa_err("invalid function arguments provided");
1589+ return -EINVAL;
1590+ }
1591+
1592+ ffa_info("Searching partitions using the provided UUID");
1593+
1594+ /*
1595+ * search in the cached partitions
1596+ */
1597+ for (desc_idx = 0;
1598+ desc_idx < ffa_priv_data->partitions.count;
1599+ desc_idx++) {
1600+ if (ffa_uuid_are_identical(&ffa_priv_data->partitions.descs[desc_idx].sp_uuid,
1601+ &part_uuid)) {
1602+ ffa_info("Partition ID %x matches the provided UUID",
1603+ ffa_priv_data->partitions.descs[desc_idx].info.id);
1604+
Andrew Geisslerea144b032023-01-27 16:03:57 -06001605+ sp_found++;
Patrick Williams8dd68482022-10-04 07:57:18 -05001606+
1607+ if (fill_data) {
1608+ /*
1609+ * trying to fill the partition info in the input buffer
1610+ */
1611+
Andrew Geisslerea144b032023-01-27 16:03:57 -06001612+ if (client_desc_idx < *sp_count) {
Patrick Williams8dd68482022-10-04 07:57:18 -05001613+ buffer[client_desc_idx++] =
1614+ ffa_priv_data->partitions.descs[desc_idx].info;
1615+ continue;
1616+ }
1617+
1618+ ffa_err("failed to fill the current descriptor client buffer full");
1619+ return -ENOBUFS;
1620+ }
1621+ }
1622+ }
1623+
Andrew Geisslerea144b032023-01-27 16:03:57 -06001624+ if (!sp_found) {
Patrick Williams8dd68482022-10-04 07:57:18 -05001625+ int ret;
1626+
1627+ ffa_info("No partition found. Querying framework ...");
1628+
Andrew Geisslerea144b032023-01-27 16:03:57 -06001629+ ret = ffa_query_partitions_info(&part_uuid, &sp_found);
Patrick Williams8dd68482022-10-04 07:57:18 -05001630+
1631+ if (ret == 0) {
1632+ if (!fill_data) {
Andrew Geisslerea144b032023-01-27 16:03:57 -06001633+ *sp_count = sp_found;
Patrick Williams8dd68482022-10-04 07:57:18 -05001634+
1635+ ffa_info("Number of partition(s) found matching the UUID: %d",
Andrew Geisslerea144b032023-01-27 16:03:57 -06001636+ sp_found);
Patrick Williams8dd68482022-10-04 07:57:18 -05001637+ } else {
1638+ /*
1639+ * If SPs data detected, they are already in the private data
1640+ * structure, retry searching SP data again to return them
1641+ * to the caller
1642+ */
Andrew Geisslerea144b032023-01-27 16:03:57 -06001643+ if (sp_found)
1644+ ret = ffa_get_partitions_info(dev, uuid_str, sp_count,
1645+ buffer);
Patrick Williams8dd68482022-10-04 07:57:18 -05001646+ else
1647+ ret = -ENODATA;
1648+ }
1649+ }
1650+
1651+ return ret;
1652+ }
1653+
1654+ /* partition(s) found */
1655+ if (!fill_data)
Andrew Geisslerea144b032023-01-27 16:03:57 -06001656+ *sp_count = sp_found;
Patrick Williams8dd68482022-10-04 07:57:18 -05001657+
1658+ return 0;
1659+}
1660+
1661+/**
1662+ * ffa_cache_partitions_info - Queries and saves all secure partitions data
1663+ *
Andrew Geisslerea144b032023-01-27 16:03:57 -06001664+ * This function invokes FFA_PARTITION_INFO_GET FF-A
Patrick Williams8dd68482022-10-04 07:57:18 -05001665+ * function to query from secure world all partitions information.
1666+ *
1667+ * The FFA_PARTITION_INFO_GET call is issued with nil UUID as an argument.
1668+ * All installed partitions information are returned. We cache them in the
1669+ * resident private data structure and we keep the UUID field empty
1670+ * (in FF-A 1.0 UUID is not provided by the partition descriptor)
1671+ *
1672+ * This function is called at the device probing level.
1673+ * ffa_cache_partitions_info uses ffa_query_partitions_info to get the data
1674+ *
1675+ * Return:
1676+ *
1677+ * 0 on success. Otherwise, failure
1678+ */
1679+static int ffa_cache_partitions_info(void)
1680+{
1681+ return ffa_query_partitions_info(NULL, NULL);
1682+}
1683+
1684+/**
1685+ * ffa_msg_send_direct_req - FFA_MSG_SEND_DIRECT_{REQ,RESP} handler function
Andrew Geisslerea144b032023-01-27 16:03:57 -06001686+ * @dev: The arm_ffa bus device
Patrick Williams8dd68482022-10-04 07:57:18 -05001687+ * @dst_part_id: destination partition ID
1688+ * @msg: pointer to the message data preallocated by the client (in/out)
Andrew Geisslerea144b032023-01-27 16:03:57 -06001689+ * @is_smc64: select 64-bit or 32-bit FF-A ABI
Patrick Williams8dd68482022-10-04 07:57:18 -05001690+ *
Andrew Geisslerea144b032023-01-27 16:03:57 -06001691+ * This function implements FFA_MSG_SEND_DIRECT_{REQ,RESP}
Patrick Williams8dd68482022-10-04 07:57:18 -05001692+ * FF-A functions.
1693+ *
1694+ * FFA_MSG_SEND_DIRECT_REQ is used to send the data to the secure partition.
1695+ * The response from the secure partition is handled by reading the
1696+ * FFA_MSG_SEND_DIRECT_RESP arguments.
1697+ *
1698+ * The maximum size of the data that can be exchanged is 40 bytes which is
1699+ * sizeof(struct ffa_send_direct_data) as defined by the FF-A specification 1.0
1700+ * in the section relevant to FFA_MSG_SEND_DIRECT_{REQ,RESP}
1701+ *
1702+ * Return:
1703+ *
1704+ * 0 on success. Otherwise, failure
1705+ */
Andrew Geisslerea144b032023-01-27 16:03:57 -06001706+static int ffa_msg_send_direct_req(struct udevice *dev, u16 dst_part_id,
1707+ struct ffa_send_direct_data *msg, bool is_smc64)
Patrick Williams8dd68482022-10-04 07:57:18 -05001708+{
1709+ ffa_value_t res = {0};
1710+ int ffa_errno;
Andrew Geisslerea144b032023-01-27 16:03:57 -06001711+ u64 req_mode, resp_mode;
Patrick Williams8dd68482022-10-04 07:57:18 -05001712+
1713+ if (!ffa_priv_data || !ffa_priv_data->invoke_ffa_fn)
1714+ return -EINVAL;
1715+
1716+ /* No partition installed */
1717+ if (!ffa_priv_data->partitions.count || !ffa_priv_data->partitions.descs)
1718+ return -ENODEV;
1719+
Andrew Geisslerea144b032023-01-27 16:03:57 -06001720+ if (is_smc64) {
1721+ req_mode = FFA_SMC_64(FFA_MSG_SEND_DIRECT_REQ);
1722+ resp_mode = FFA_SMC_64(FFA_MSG_SEND_DIRECT_RESP);
1723+ } else {
1724+ req_mode = FFA_SMC_32(FFA_MSG_SEND_DIRECT_REQ);
1725+ resp_mode = FFA_SMC_32(FFA_MSG_SEND_DIRECT_RESP);
1726+ }
1727+
Patrick Williams8dd68482022-10-04 07:57:18 -05001728+ ffa_priv_data->invoke_ffa_fn((ffa_value_t){
Andrew Geisslerea144b032023-01-27 16:03:57 -06001729+ .a0 = req_mode,
Patrick Williams8dd68482022-10-04 07:57:18 -05001730+ .a1 = PREP_SELF_ENDPOINT_ID(ffa_priv_data->id) |
1731+ PREP_PART_ENDPOINT_ID(dst_part_id),
1732+ .a2 = 0,
1733+ .a3 = msg->data0,
1734+ .a4 = msg->data1,
1735+ .a5 = msg->data2,
1736+ .a6 = msg->data3,
1737+ .a7 = msg->data4,
1738+ }, &res);
1739+
1740+ while (res.a0 == FFA_SMC_32(FFA_INTERRUPT))
1741+ ffa_priv_data->invoke_ffa_fn((ffa_value_t){
1742+ .a0 = FFA_SMC_32(FFA_RUN),
Andrew Geisslerea144b032023-01-27 16:03:57 -06001743+ .a1 = res.a1,
Patrick Williams8dd68482022-10-04 07:57:18 -05001744+ }, &res);
1745+
1746+ if (res.a0 == FFA_SMC_32(FFA_SUCCESS)) {
1747+ /* Message sent with no response */
1748+ return 0;
1749+ }
1750+
Andrew Geisslerea144b032023-01-27 16:03:57 -06001751+ if (res.a0 == resp_mode) {
Patrick Williams8dd68482022-10-04 07:57:18 -05001752+ /*
1753+ * Message sent with response
1754+ * extract the return data
1755+ */
1756+ msg->data0 = res.a3;
1757+ msg->data1 = res.a4;
1758+ msg->data2 = res.a5;
1759+ msg->data3 = res.a6;
1760+ msg->data4 = res.a7;
1761+
1762+ return 0;
1763+ }
1764+
Andrew Geisslerea144b032023-01-27 16:03:57 -06001765+ ffa_errno = res.a2;
Patrick Williams8dd68482022-10-04 07:57:18 -05001766+ return ffa_to_std_errno(ffa_errno);
1767+}
1768+
1769+/**
1770+ * __arm_ffa_fn_smc - SMC wrapper
1771+ * @args: FF-A ABI arguments to be copied to Xn registers
1772+ * @res: FF-A ABI return data to be copied from Xn registers
1773+ *
1774+ * Calls low level SMC assembly function
1775+ *
1776+ * Return: void
1777+ */
Andrew Geisslerea144b032023-01-27 16:03:57 -06001778+void __arm_ffa_fn_smc(ffa_value_t args, ffa_value_t *res)
Patrick Williams8dd68482022-10-04 07:57:18 -05001779+{
1780+ arm_smccc_1_2_smc(&args, res);
1781+}
1782+
1783+/**
1784+ * ffa_set_smc_conduit - Set the SMC conduit
1785+ *
Andrew Geisslerea144b032023-01-27 16:03:57 -06001786+ * This function selects the SMC conduit by setting the driver invoke function
Patrick Williams8dd68482022-10-04 07:57:18 -05001787+ * to SMC assembly function
1788+ *
1789+ * Return:
1790+ *
1791+ * 0 on success. Otherwise, failure
1792+ */
1793+static int ffa_set_smc_conduit(void)
1794+{
1795+ ffa_priv_data->invoke_ffa_fn = __arm_ffa_fn_smc;
1796+
1797+ if (!ffa_priv_data->invoke_ffa_fn) {
1798+ ffa_err("failure to set the invoke function");
1799+ return -EINVAL;
1800+ }
1801+
1802+ ffa_info("Conduit is SMC");
1803+
1804+ return 0;
1805+}
1806+
1807+/**
1808+ * ffa_set_bus_ops - Set the bus driver operations
1809+ *
1810+ * Setting the driver callbacks.
1811+ *
1812+ */
1813+static void ffa_set_bus_ops(void)
1814+{
1815+ ffa_priv_data->ffa_ops.partition_info_get = ffa_get_partitions_info;
1816+ ffa_priv_data->ffa_ops.sync_send_receive = ffa_msg_send_direct_req;
1817+ ffa_priv_data->ffa_ops.rxtx_unmap = ffa_unmap_rxtx_buffers;
1818+}
1819+
1820+/**
1821+ * ffa_alloc_prvdata - allocate the driver main data structure and sets the device
1822+ * @dev: the arm_ffa device
1823+ *
Andrew Geisslerea144b032023-01-27 16:03:57 -06001824+ * This function creates the main data structure embedding all the driver data.
Patrick Williams8dd68482022-10-04 07:57:18 -05001825+ *
1826+ * Return:
1827+ *
1828+ * 0 on success. Otherwise, failure
1829+ */
1830+static int ffa_alloc_prvdata(struct udevice *dev)
1831+{
1832+ if (!dev) {
1833+ ffa_err("no udevice found");
1834+ return -ENODEV;
1835+ }
1836+
1837+ /* The device is registered with the DM. Let's create the driver main data structure*/
1838+
1839+ ffa_priv_data = devm_kmalloc(dev, sizeof(struct ffa_prvdata), __GFP_ZERO);
1840+ if (!ffa_priv_data) {
1841+ ffa_err("can not allocate the driver main data structure");
1842+ return -ENOMEM;
1843+ }
1844+
1845+ ffa_priv_data->dev = dev;
1846+
1847+ return 0;
1848+}
1849+
1850+/**
1851+ * ffa_probe - The driver probe function
1852+ * @dev: the arm_ffa device
1853+ *
1854+ * Probing is done at boot time and triggered by the uclass device discovery.
1855+ * At probe level the following actions are done:
1856+ * - setting the conduit
1857+ * - querying the FF-A framework version
1858+ * - querying from secure world the u-boot endpoint ID
1859+ * - querying from secure world the supported features of FFA_RXTX_MAP
1860+ * - mapping the RX/TX buffers
1861+ * - querying from secure world all the partitions information
1862+ *
1863+ * All data queried from secure world is saved in the resident private data structure.
1864+ *
1865+ * The probe will fail if either FF-A framework is not detected or the
1866+ * FF-A requests are not behaving correctly. This ensures that the
1867+ * driver is not installed and its operations are not exported to the clients.
1868+ *
1869+ * Return:
1870+ *
1871+ * 0 on success. Otherwise, failure
1872+ */
1873+static int ffa_probe(struct udevice *dev)
1874+{
1875+ int ret;
1876+
1877+ ret = ffa_alloc_prvdata(dev);
1878+ if (ret != 0)
1879+ return ret;
1880+
1881+ ffa_set_bus_ops();
1882+
1883+ ret = ffa_set_smc_conduit();
1884+ if (ret != 0)
1885+ return ret;
1886+
1887+ ret = ffa_get_version();
1888+ if (ret != 0)
1889+ return ret;
1890+
1891+ ret = ffa_get_endpoint_id();
1892+ if (ret != 0)
1893+ return ret;
1894+
1895+ ret = ffa_get_rxtx_map_features();
1896+ if (ret != 0)
1897+ return ret;
1898+
1899+ ret = ffa_map_rxtx_buffers();
1900+ if (ret != 0)
1901+ return ret;
1902+
1903+ ret = ffa_cache_partitions_info();
1904+ if (ret != 0) {
1905+ ffa_free_rxtx_buffers();
1906+ return ret;
1907+ }
1908+
1909+ return 0;
1910+}
1911+
1912+/**
1913+ * ffa_remove - The driver remove function
1914+ * @dev: the arm_ffa device
1915+ * When the device is about to be removed , unmap the RX/TX buffers and free the memory
1916+ * Return:
1917+ *
1918+ * 0 on success.
1919+ */
1920+static int ffa_remove(struct udevice *dev)
1921+{
1922+ ffa_info("removing the device");
1923+
Andrew Geisslerea144b032023-01-27 16:03:57 -06001924+ ffa_unmap_rxtx_buffers(dev);
Patrick Williams8dd68482022-10-04 07:57:18 -05001925+
1926+ if (ffa_priv_data->pair.rxbuf || ffa_priv_data->pair.txbuf)
1927+ ffa_free_rxtx_buffers();
1928+
1929+ return 0;
1930+}
1931+
1932+/**
1933+ * ffa_unbind - The driver unbind function
1934+ * @dev: the arm_ffa device
1935+ * After the device is removed and memory freed the device is unbound
1936+ * Return:
1937+ *
1938+ * 0 on success.
1939+ */
1940+static int ffa_unbind(struct udevice *dev)
1941+{
1942+ ffa_info("unbinding the device , private data already released");
1943+
1944+ ffa_priv_data = NULL;
1945+
1946+ return 0;
1947+}
1948+
1949+/**
1950+ * ffa_bus_ops_get - bus driver operations getter
1951+ *
1952+ * Return:
Andrew Geisslerea144b032023-01-27 16:03:57 -06001953+ * This function returns a pointer to the driver operations structure
Patrick Williams8dd68482022-10-04 07:57:18 -05001954+ */
Andrew Geisslerea144b032023-01-27 16:03:57 -06001955+const struct ffa_bus_ops *ffa_bus_ops_get(void)
Patrick Williams8dd68482022-10-04 07:57:18 -05001956+{
1957+ return &ffa_priv_data->ffa_ops;
1958+}
1959+
1960+/**
1961+ * ffa_bus_prvdata_get - bus driver private data getter
1962+ *
1963+ * Return:
Andrew Geisslerea144b032023-01-27 16:03:57 -06001964+ * This function returns a pointer to the main private data structure
Patrick Williams8dd68482022-10-04 07:57:18 -05001965+ */
Andrew Geisslerea144b032023-01-27 16:03:57 -06001966+struct ffa_prvdata *ffa_bus_prvdata_get(void)
Patrick Williams8dd68482022-10-04 07:57:18 -05001967+{
Andrew Geisslerea144b032023-01-27 16:03:57 -06001968+ return ffa_priv_data;
Patrick Williams8dd68482022-10-04 07:57:18 -05001969+}
1970+
1971+/**
Andrew Geisslerea144b032023-01-27 16:03:57 -06001972+ * ffa_bus_discover - discover FF-A bus and probe arm_ffa device
1973+ * @pdev: the address of a device pointer (to be filled when the arm_ffa bus device is created
1974+ * successfully)
Patrick Williams8dd68482022-10-04 07:57:18 -05001975+ *
Andrew Geisslerea144b032023-01-27 16:03:57 -06001976+ * This function makes sure the FF-A bus is discoverable.
1977+ * When probing succeeds FF-A discovery is done. The arm_ffa device is ready to use.
Patrick Williams8dd68482022-10-04 07:57:18 -05001978+ *
1979+ * When the bus was already discovered successfully the discovery will not run again.
1980+ *
1981+ * Arm FF-A transport is implemented through arm_ffa u-boot device managing the FF-A
1982+ * communication.
1983+ * All FF-A clients should use the arm_ffa device to use the FF-A transport.
1984+ *
1985+ * Return:
1986+ *
1987+ * 0 on success. Otherwise, failure
1988+ */
Andrew Geisslerea144b032023-01-27 16:03:57 -06001989+int ffa_bus_discover(struct udevice **pdev)
Patrick Williams8dd68482022-10-04 07:57:18 -05001990+{
1991+ int ret = 0;
1992+
Andrew Geisslerea144b032023-01-27 16:03:57 -06001993+ if (!ffa_priv_data) {
1994+ ret = ffa_device_get(pdev);
Patrick Williams8dd68482022-10-04 07:57:18 -05001995+
1996+ return ret;
1997+}
1998+
1999+/**
2000+ * Declaring the arm_ffa driver under UCLASS_FFA
2001+ */
2002+
2003+U_BOOT_DRIVER(arm_ffa) = {
2004+ .name = FFA_DRV_NAME,
2005+ .id = UCLASS_FFA,
2006+ .probe = ffa_probe,
2007+ .remove = ffa_remove,
2008+ .unbind = ffa_unbind,
2009+};
Patrick Williams8dd68482022-10-04 07:57:18 -05002010diff --git a/include/arm_ffa.h b/include/arm_ffa.h
2011new file mode 100644
Andrew Geisslerea144b032023-01-27 16:03:57 -06002012index 0000000000..74b16174c2
Patrick Williams8dd68482022-10-04 07:57:18 -05002013--- /dev/null
2014+++ b/include/arm_ffa.h
Andrew Geisslerea144b032023-01-27 16:03:57 -06002015@@ -0,0 +1,97 @@
Patrick Williams8dd68482022-10-04 07:57:18 -05002016+/* SPDX-License-Identifier: GPL-2.0+ */
2017+/*
2018+ * (C) Copyright 2022 ARM Limited
2019+ * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
2020+ */
2021+
2022+#ifndef __ARM_FFA_H
2023+#define __ARM_FFA_H
2024+
2025+#include <linux/printk.h>
2026+
2027+/*
2028+ * This header is public. It can be used by clients to access
2029+ * data structures and definitions they need
2030+ */
2031+
2032+/*
2033+ * Macros for displaying logs
2034+ */
2035+
2036+#define ffa_info(fmt, ...) pr_info("[FFA] " fmt "\n", ##__VA_ARGS__)
2037+#define ffa_err(fmt, ...) pr_err("[FFA] " fmt "\n", ##__VA_ARGS__)
2038+
2039+/*
2040+ * struct ffa_partition_info - Partition information descriptor
2041+ * @id: Partition ID
2042+ * @exec_ctxt: Execution context count
2043+ * @properties: Partition properties
2044+ *
2045+ * Data structure containing information about partitions instantiated in the system
2046+ * This structure is filled with the data queried by FFA_PARTITION_INFO_GET
2047+ */
Andrew Geisslerea144b032023-01-27 16:03:57 -06002048+struct ffa_partition_info {
Patrick Williams8dd68482022-10-04 07:57:18 -05002049+ u16 id;
2050+ u16 exec_ctxt;
2051+/* partition supports receipt of direct requests */
2052+#define FFA_PARTITION_DIRECT_RECV BIT(0)
2053+/* partition can send direct requests. */
2054+#define FFA_PARTITION_DIRECT_SEND BIT(1)
2055+/* partition can send and receive indirect messages. */
2056+#define FFA_PARTITION_INDIRECT_MSG BIT(2)
2057+ u32 properties;
2058+};
2059+
2060+/*
2061+ * struct ffa_send_direct_data - Data structure hosting the data
2062+ * used by FFA_MSG_SEND_DIRECT_{REQ,RESP}
2063+ * @data0-4: Data read/written from/to x3-x7 registers
2064+ *
2065+ * Data structure containing the data to be sent by FFA_MSG_SEND_DIRECT_REQ
2066+ * or read from FFA_MSG_SEND_DIRECT_RESP
2067+ */
2068+
2069+/* For use with FFA_MSG_SEND_DIRECT_{REQ,RESP} which pass data via registers */
Andrew Geisslerea144b032023-01-27 16:03:57 -06002070+struct ffa_send_direct_data {
Patrick Williams8dd68482022-10-04 07:57:18 -05002071+ unsigned long data0; /* w3/x3 */
2072+ unsigned long data1; /* w4/x4 */
2073+ unsigned long data2; /* w5/x5 */
2074+ unsigned long data3; /* w6/x6 */
2075+ unsigned long data4; /* w7/x7 */
2076+};
2077+
Andrew Geisslerea144b032023-01-27 16:03:57 -06002078+struct udevice;
Patrick Williams8dd68482022-10-04 07:57:18 -05002079+
2080+/**
2081+ * struct ffa_bus_ops - The driver operations structure
2082+ * @partition_info_get: callback for the FFA_PARTITION_INFO_GET
2083+ * @sync_send_receive: callback for the FFA_MSG_SEND_DIRECT_REQ
2084+ * @rxtx_unmap: callback for the FFA_RXTX_UNMAP
2085+ *
2086+ * The data structure providing all the operations supported by the driver.
2087+ * This structure is EFI runtime resident.
2088+ */
2089+struct ffa_bus_ops {
Andrew Geisslerea144b032023-01-27 16:03:57 -06002090+ int (*partition_info_get)(struct udevice *dev, const char *uuid_str,
2091+ u32 *sp_count, struct ffa_partition_info *buffer);
2092+ int (*sync_send_receive)(struct udevice *dev, u16 dst_part_id,
2093+ struct ffa_send_direct_data *msg,
2094+ bool is_smc64);
2095+ int (*rxtx_unmap)(struct udevice *dev);
Patrick Williams8dd68482022-10-04 07:57:18 -05002096+};
2097+
2098+/**
2099+ * The device driver and the Uclass driver public functions
2100+ */
2101+
2102+/**
2103+ * ffa_bus_ops_get - driver operations getter
2104+ */
Andrew Geisslerea144b032023-01-27 16:03:57 -06002105+const struct ffa_bus_ops *ffa_bus_ops_get(void);
Patrick Williams8dd68482022-10-04 07:57:18 -05002106+
2107+/**
2108+ * ffa_bus_discover - discover FF-A bus and probes the arm_ffa device
2109+ */
Andrew Geisslerea144b032023-01-27 16:03:57 -06002110+int ffa_bus_discover(struct udevice **pdev);
Patrick Williams8dd68482022-10-04 07:57:18 -05002111+
2112+#endif
2113diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h
Andrew Geisslerea144b032023-01-27 16:03:57 -06002114index a432e43871..5dd698b7a9 100644
Patrick Williams8dd68482022-10-04 07:57:18 -05002115--- a/include/dm/uclass-id.h
2116+++ b/include/dm/uclass-id.h
Andrew Geisslerea144b032023-01-27 16:03:57 -06002117@@ -4,6 +4,9 @@
2118 *
2119 * (C) Copyright 2012
2120 * Pavel Herrmann <morpheus.ibis@gmail.com>
2121+ *
2122+ * (C) Copyright 2022 ARM Limited
2123+ * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
2124 */
2125
2126 #ifndef _DM_UCLASS_ID_H
2127@@ -55,6 +58,7 @@ enum uclass_id {
Patrick Williams8dd68482022-10-04 07:57:18 -05002128 UCLASS_EFI_MEDIA, /* Devices provided by UEFI firmware */
2129 UCLASS_ETH, /* Ethernet device */
2130 UCLASS_ETH_PHY, /* Ethernet PHY device */
2131+ UCLASS_FFA, /* Arm Firmware Framework for Armv8-A */
2132 UCLASS_FIRMWARE, /* Firmware */
Andrew Geisslerea144b032023-01-27 16:03:57 -06002133 UCLASS_FUZZING_ENGINE, /* Fuzzing engine */
Patrick Williams8dd68482022-10-04 07:57:18 -05002134 UCLASS_FS_FIRMWARE_LOADER, /* Generic loader */
Patrick Williams8dd68482022-10-04 07:57:18 -05002135--
21362.17.1
2137