* [PATCH 1/6] arm: update Android common kernel
@ 2021-07-22 11:32 Arunachalam Ganapathy
2021-07-22 11:32 ` [PATCH 2/6] arm-bsp/linux: add ffa driver to TC0 Arunachalam Ganapathy
` (4 more replies)
0 siblings, 5 replies; 6+ messages in thread
From: Arunachalam Ganapathy @ 2021-07-22 11:32 UTC (permalink / raw)
To: meta-arm; +Cc: nd, Anders Dellien, Arunachalam Ganapathy
From: Anders Dellien <anders.dellien@arm.com>
Update ACK to 5.10 and remove the 5.4 recipe
Change-Id: I7a0cc0bc95d02bed965530d36aedaf544045fee4
Signed-off-by: Anders Dellien <anders.dellien@arm.com>
Signed-off-by: Arunachalam Ganapathy <arunachalam.ganapathy@arm.com>
---
meta-arm-bsp/conf/machine/tc0.conf | 2 +-
.../linux/linux-arm-platforms.inc | 19 +-
...m-Add-component-aware-simple-encoder.patch | 21 +-
...dd-RENDER-capability-to-the-device-n.patch | 13 +-
...Adapt-ION-interface-to-match-Android.patch | 33 +
...dings-mailbox-arm-mhuv2-Add-bindings.patch | 241 ++
.../0005-mailbox-arm_mhuv2-Add-driver.patch | 1256 +++++++
...ailbox-arm_mhuv2-Fix-sparse-warnings.patch | 114 +
...uv2-make-remove-callback-return-void.patch | 47 +
...2-Skip-calling-kfree-with-invalid-po.patch | 41 +
.../tc0/defconfig | 85 +-
...2-add-device-tree-binding-documentat.patch | 134 -
...ilbox-arm_mhuv2-add-arm-mhuv2-driver.patch | 822 -----
...2-add-doorbell-transport-protocol-op.patch | 156 -
...2-add-multi-word-transport-protocol-.patch | 271 --
...rm_scmi-Add-fast_switch_possible-api.patch | 67 -
...-Set-fast_switch_possible-conditiona.patch | 42 -
...Initial-version-of-ffa-driver-based-.patch | 1461 --------
...for-session-s-client-UUID-generation.patch | 252 --
...pport-for-session-login-client-UUID-.patch | 43 -
...iver-optee-Support-for-ffa-transport.patch | 3150 -----------------
...m-handle-removal-in-ffa_shm_unregist.patch | 51 -
...t-for-asymmetric-AArch32-EL0-configu.patch | 462 ---
...t-hotplugging-the-last-AArch32-able-.patch | 89 -
...bbappend => linux-arm64-ack_5.10.bbappend} | 0
.../recipes-kernel/linux/linux-arm64-ack.inc | 4 +-
...-definition-of-traceid_list-global-v.patch | 69 -
..._account-Make-global-variable-static.patch | 43 -
...-some-global-variables-to-fix-build-.patch | 240 --
...ceevent-Fix-build-with-binutils-2.35.patch | 39 -
.../linux/linux-arm64-ack_5.10.bb | 12 +
.../linux/linux-arm64-ack_5.4.bb | 16 -
32 files changed, 1801 insertions(+), 7494 deletions(-)
rename meta-arm-bsp/recipes-kernel/linux/{linux-arm64-ack-5.4 => linux-arm64-ack-5.10}/tc0/0001-drm-Add-component-aware-simple-encoder.patch (94%)
rename meta-arm-bsp/recipes-kernel/linux/{linux-arm64-ack-5.4 => linux-arm64-ack-5.10}/tc0/0002-drm-arm-komeda-add-RENDER-capability-to-the-device-n.patch (68%)
create mode 100644 meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc0/0003-Adapt-ION-interface-to-match-Android.patch
create mode 100644 meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc0/0004-dt-bindings-mailbox-arm-mhuv2-Add-bindings.patch
create mode 100644 meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc0/0005-mailbox-arm_mhuv2-Add-driver.patch
create mode 100644 meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc0/0006-mailbox-arm_mhuv2-Fix-sparse-warnings.patch
create mode 100644 meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc0/0007-mailbox-arm_mhuv2-make-remove-callback-return-void.patch
create mode 100644 meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc0/0008-mailbox-arm_mhuv2-Skip-calling-kfree-with-invalid-po.patch
rename meta-arm-bsp/recipes-kernel/linux/{linux-arm64-ack-5.4 => linux-arm64-ack-5.10}/tc0/defconfig (95%)
delete mode 100644 meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.4/tc0/0003-mailbox-arm_mhuv2-add-device-tree-binding-documentat.patch
delete mode 100644 meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.4/tc0/0004-mailbox-arm_mhuv2-add-arm-mhuv2-driver.patch
delete mode 100644 meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.4/tc0/0005-mailbox-arm_mhuv2-add-doorbell-transport-protocol-op.patch
delete mode 100644 meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.4/tc0/0006-mailbox-arm_mhuv2-add-multi-word-transport-protocol-.patch
delete mode 100644 meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.4/tc0/0007-firmware-arm_scmi-Add-fast_switch_possible-api.patch
delete mode 100644 meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.4/tc0/0008-cpufreq-arm_scmi-Set-fast_switch_possible-conditiona.patch
delete mode 100644 meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.4/tc0/0009-driver-firmware-Initial-version-of-ffa-driver-based-.patch
delete mode 100644 meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.4/tc0/0010-tee-add-support-for-session-s-client-UUID-generation.patch
delete mode 100644 meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.4/tc0/0011-tee-optee-Add-support-for-session-login-client-UUID-.patch
delete mode 100644 meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.4/tc0/0012-driver-optee-Support-for-ffa-transport.patch
delete mode 100644 meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.4/tc0/0013-tee-optee-fix-mem-handle-removal-in-ffa_shm_unregist.patch
delete mode 100644 meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.4/tc0/0014-arm64-Add-support-for-asymmetric-AArch32-EL0-configu.patch
delete mode 100644 meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.4/tc0/0015-arm64-smp-Prevent-hotplugging-the-last-AArch32-able-.patch
rename meta-arm-bsp/recipes-kernel/linux/{linux-arm64-ack_5.4.bbappend => linux-arm64-ack_5.10.bbappend} (100%)
delete mode 100644 meta-arm/recipes-kernel/linux/linux-arm64-ack/0001-perf-cs-etm-Move-definition-of-traceid_list-global-v.patch
delete mode 100644 meta-arm/recipes-kernel/linux/linux-arm64-ack/0002-perf-tests-bp_account-Make-global-variable-static.patch
delete mode 100644 meta-arm/recipes-kernel/linux/linux-arm64-ack/0003-perf-bench-Share-some-global-variables-to-fix-build-.patch
delete mode 100644 meta-arm/recipes-kernel/linux/linux-arm64-ack/0004-libtraceevent-Fix-build-with-binutils-2.35.patch
create mode 100644 meta-arm/recipes-kernel/linux/linux-arm64-ack_5.10.bb
delete mode 100644 meta-arm/recipes-kernel/linux/linux-arm64-ack_5.4.bb
diff --git a/meta-arm-bsp/conf/machine/tc0.conf b/meta-arm-bsp/conf/machine/tc0.conf
index a83fd28..565afda 100644
--- a/meta-arm-bsp/conf/machine/tc0.conf
+++ b/meta-arm-bsp/conf/machine/tc0.conf
@@ -30,7 +30,7 @@ PREFERRED_PROVIDER_virtual/trusted-firmware-a ?= "trusted-firmware-a"
PREFERRED_VERSION_trusted-firmware-a ?= "2.5%"
PREFERRED_PROVIDER_virtual/kernel ?= "linux-arm64-ack"
-PREFERRED_VERSION_linux-arm64-ack ?= "5.4"
+PREFERRED_VERSION_linux-arm64-ack ?= "5.10"
# Cannot use the default zImage on arm64
KERNEL_IMAGETYPE = "Image"
diff --git a/meta-arm-bsp/recipes-kernel/linux/linux-arm-platforms.inc b/meta-arm-bsp/recipes-kernel/linux/linux-arm-platforms.inc
index 5c361f7..0a679da 100644
--- a/meta-arm-bsp/recipes-kernel/linux/linux-arm-platforms.inc
+++ b/meta-arm-bsp/recipes-kernel/linux/linux-arm-platforms.inc
@@ -79,19 +79,12 @@ SRC_URI_append_tc0 = " \
file://defconfig \
file://0001-drm-Add-component-aware-simple-encoder.patch \
file://0002-drm-arm-komeda-add-RENDER-capability-to-the-device-n.patch \
- file://0003-mailbox-arm_mhuv2-add-device-tree-binding-documentat.patch \
- file://0004-mailbox-arm_mhuv2-add-arm-mhuv2-driver.patch \
- file://0005-mailbox-arm_mhuv2-add-doorbell-transport-protocol-op.patch \
- file://0006-mailbox-arm_mhuv2-add-multi-word-transport-protocol-.patch \
- file://0007-firmware-arm_scmi-Add-fast_switch_possible-api.patch \
- file://0008-cpufreq-arm_scmi-Set-fast_switch_possible-conditiona.patch \
- file://0009-driver-firmware-Initial-version-of-ffa-driver-based-.patch \
- file://0010-tee-add-support-for-session-s-client-UUID-generation.patch \
- file://0011-tee-optee-Add-support-for-session-login-client-UUID-.patch \
- file://0012-driver-optee-Support-for-ffa-transport.patch \
- file://0013-tee-optee-fix-mem-handle-removal-in-ffa_shm_unregist.patch \
- file://0014-arm64-Add-support-for-asymmetric-AArch32-EL0-configu.patch \
- file://0015-arm64-smp-Prevent-hotplugging-the-last-AArch32-able-.patch \
+ file://0003-Adapt-ION-interface-to-match-Android.patch \
+ file://0004-dt-bindings-mailbox-arm-mhuv2-Add-bindings.patch \
+ file://0005-mailbox-arm_mhuv2-Add-driver.patch \
+ file://0006-mailbox-arm_mhuv2-Fix-sparse-warnings.patch \
+ file://0007-mailbox-arm_mhuv2-make-remove-callback-return-void.patch \
+ file://0008-mailbox-arm_mhuv2-Skip-calling-kfree-with-invalid-po.patch \
"
#
diff --git a/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.4/tc0/0001-drm-Add-component-aware-simple-encoder.patch b/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc0/0001-drm-Add-component-aware-simple-encoder.patch
similarity index 94%
rename from meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.4/tc0/0001-drm-Add-component-aware-simple-encoder.patch
rename to meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc0/0001-drm-Add-component-aware-simple-encoder.patch
index 7855bee..b698ec7 100644
--- a/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.4/tc0/0001-drm-Add-component-aware-simple-encoder.patch
+++ b/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc0/0001-drm-Add-component-aware-simple-encoder.patch
@@ -1,7 +1,7 @@
-From 7863ac1515009547bae3a66e0808e72b3bdcf8c8 Mon Sep 17 00:00:00 2001
+From 9080fb7fc011445d4d6ee164d02d86ff6df0822a Mon Sep 17 00:00:00 2001
From: Tushar Khandelwal <tushar.khandelwal@arm.com>
Date: Tue, 16 Jun 2020 12:39:06 +0000
-Subject: [PATCH 1/9] drm: Add component-aware simple encoder
+Subject: [PATCH 01/10] drm: Add component-aware simple encoder
This is a simple DRM encoder that gets its connector timings information
from a OF subnode in the device tree and exposes that as a "discovered"
@@ -12,6 +12,7 @@ and the display output is configured outside the kernel.
Signed-off-by: Tushar Khandelwal <tushar.khandelwal@arm.com>
Upstream-Status: Backport [https://git.linaro.org/landing-teams/working/arm/kernel-release.git/commit/?h=latest-armlt&id=15283f7be4b1e586702551e85b4caf06531ac2fc]
+Signed-off-by: Arunachalam Ganapathy <arunachalam.ganapathy@arm.com>
---
drivers/gpu/drm/Kconfig | 11 +
drivers/gpu/drm/Makefile | 2 +
@@ -20,10 +21,10 @@ Upstream-Status: Backport [https://git.linaro.org/landing-teams/working/arm/kern
create mode 100644 drivers/gpu/drm/drm_virtual_encoder.c
diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
-index e67c194c2aca..c95279cd9341 100644
+index ca868271f4c4..6ae8ba3ca7b3 100644
--- a/drivers/gpu/drm/Kconfig
+++ b/drivers/gpu/drm/Kconfig
-@@ -265,6 +265,17 @@ config DRM_VKMS
+@@ -300,6 +300,17 @@ config DRM_VKMS
If M is selected the module will be called vkms.
@@ -38,14 +39,14 @@ index e67c194c2aca..c95279cd9341 100644
+ drm_vencoder.
+
+
- config DRM_ATI_PCIGART
- bool
+ source "drivers/gpu/drm/exynos/Kconfig"
+ source "drivers/gpu/drm/rockchip/Kconfig"
diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile
-index 82ff826b33cc..d2ab6fc64932 100644
+index 81569009f884..a3429152c613 100644
--- a/drivers/gpu/drm/Makefile
+++ b/drivers/gpu/drm/Makefile
-@@ -53,6 +53,8 @@ drm_kms_helper-$(CONFIG_DRM_DP_CEC) += drm_dp_cec.o
+@@ -56,6 +56,8 @@ drm_kms_helper-$(CONFIG_DRM_DP_CEC) += drm_dp_cec.o
obj-$(CONFIG_DRM_KMS_HELPER) += drm_kms_helper.o
obj-$(CONFIG_DRM_DEBUG_SELFTEST) += selftests/
@@ -56,7 +57,7 @@ index 82ff826b33cc..d2ab6fc64932 100644
obj-$(CONFIG_DRM_MIPI_DBI) += drm_mipi_dbi.o
diff --git a/drivers/gpu/drm/drm_virtual_encoder.c b/drivers/gpu/drm/drm_virtual_encoder.c
new file mode 100644
-index 000000000000..4fd2098df286
+index 000000000000..2f65c6b47d00
--- /dev/null
+++ b/drivers/gpu/drm/drm_virtual_encoder.c
@@ -0,0 +1,299 @@
@@ -250,7 +251,7 @@ index 000000000000..4fd2098df286
+ crtcs = drm_of_find_possible_crtcs(drm, dev->of_node);
+ bridge = of_drm_find_bridge(dev->of_node);
+ if (bridge) {
-+ ret = drm_bridge_attach(encoder, bridge, NULL);
++ ret = drm_bridge_attach(encoder, bridge, NULL, 0);
+ if (ret) {
+ DRM_ERROR("Failed to initialize bridge\n");
+ return ret;
diff --git a/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.4/tc0/0002-drm-arm-komeda-add-RENDER-capability-to-the-device-n.patch b/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc0/0002-drm-arm-komeda-add-RENDER-capability-to-the-device-n.patch
similarity index 68%
rename from meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.4/tc0/0002-drm-arm-komeda-add-RENDER-capability-to-the-device-n.patch
rename to meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc0/0002-drm-arm-komeda-add-RENDER-capability-to-the-device-n.patch
index 412e982..c3febff 100644
--- a/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.4/tc0/0002-drm-arm-komeda-add-RENDER-capability-to-the-device-n.patch
+++ b/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc0/0002-drm-arm-komeda-add-RENDER-capability-to-the-device-n.patch
@@ -1,7 +1,7 @@
-From 190c6354a0d80c31214550553cfbee25571e1942 Mon Sep 17 00:00:00 2001
+From 7a0e6189c7b104a679bc7b91465425e2de909456 Mon Sep 17 00:00:00 2001
From: Tushar Khandelwal <tushar.khandelwal@arm.com>
Date: Wed, 17 Jun 2020 10:49:26 +0000
-Subject: [PATCH 2/9] drm: arm: komeda: add RENDER capability to the device
+Subject: [PATCH 02/10] drm: arm: komeda: add RENDER capability to the device
node
this is required to make this driver work with android framework
@@ -9,23 +9,24 @@ this is required to make this driver work with android framework
Signed-off-by: Tushar Khandelwal <tushar.khandelwal@arm.com>
Upstream-Status: Inappropriate [Product specific configuration]
+Signed-off-by: Arunachalam Ganapathy <arunachalam.ganapathy@arm.com>
---
drivers/gpu/drm/arm/display/komeda/komeda_kms.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_kms.c b/drivers/gpu/drm/arm/display/komeda/komeda_kms.c
-index ae274902ff92..238bd8466206 100644
+index 1f6682032ca4..9d1a1942e673 100644
--- a/drivers/gpu/drm/arm/display/komeda/komeda_kms.c
+++ b/drivers/gpu/drm/arm/display/komeda/komeda_kms.c
-@@ -56,7 +56,7 @@ static irqreturn_t komeda_kms_irq_handler(int irq, void *data)
+@@ -59,7 +59,7 @@ static irqreturn_t komeda_kms_irq_handler(int irq, void *data)
}
static struct drm_driver komeda_kms_driver = {
- .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC,
+ .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC | DRIVER_RENDER,
.lastclose = drm_fb_helper_lastclose,
- .gem_free_object_unlocked = drm_gem_cma_free_object,
- .gem_vm_ops = &drm_gem_cma_vm_ops,
+ DRM_GEM_CMA_DRIVER_OPS_WITH_DUMB_CREATE(komeda_gem_cma_dumb_create),
+ .fops = &komeda_cma_fops,
--
2.17.1
diff --git a/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc0/0003-Adapt-ION-interface-to-match-Android.patch b/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc0/0003-Adapt-ION-interface-to-match-Android.patch
new file mode 100644
index 0000000..1d6a403
--- /dev/null
+++ b/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc0/0003-Adapt-ION-interface-to-match-Android.patch
@@ -0,0 +1,33 @@
+From b98c6070320ad31318a028482f026d6a5eddce5b Mon Sep 17 00:00:00 2001
+From: Anders Dellien <anders.dellien@arm.com>
+Date: Fri, 29 Jan 2021 09:44:38 +0000
+Subject: [PATCH 03/10] Adapt ION interface to match Android
+
+Change-Id: I62b69cc357868f725170899c862530b8f3069666
+Signed-off-by: Anders Dellien <anders.dellien@arm.com>
+
+Upstream-Status: Inappropriate [Product specific configuration]
+Signed-off-by: Arunachalam Ganapathy <arunachalam.ganapathy@arm.com>
+---
+ include/uapi/linux/ion.h | 5 ++++-
+ 1 file changed, 4 insertions(+), 1 deletion(-)
+
+diff --git a/include/uapi/linux/ion.h b/include/uapi/linux/ion.h
+index 371e44662755..7022ea223736 100644
+--- a/include/uapi/linux/ion.h
++++ b/include/uapi/linux/ion.h
+@@ -24,7 +24,10 @@
+ */
+ enum ion_heap_type {
+ ION_HEAP_TYPE_SYSTEM = 0,
+- ION_HEAP_TYPE_DMA = 2,
++ ION_HEAP_TYPE_SYSTEM_CONTIG = 1,
++ ION_HEAP_TYPE_CARVEOUT = 2,
++ ION_HEAP_TYPE_CHUNK = 3,
++ ION_HEAP_TYPE_DMA = 4,
+ /* reserved range for future standard heap types */
+ ION_HEAP_TYPE_CUSTOM = 16,
+ ION_HEAP_TYPE_MAX = 31,
+--
+2.17.1
+
diff --git a/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc0/0004-dt-bindings-mailbox-arm-mhuv2-Add-bindings.patch b/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc0/0004-dt-bindings-mailbox-arm-mhuv2-Add-bindings.patch
new file mode 100644
index 0000000..be5801a
--- /dev/null
+++ b/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc0/0004-dt-bindings-mailbox-arm-mhuv2-Add-bindings.patch
@@ -0,0 +1,241 @@
+From 4cafac5cd54c7f5069a4d6e17bdbd8f94cd5fa0b Mon Sep 17 00:00:00 2001
+From: Viresh Kumar <viresh.kumar@linaro.org>
+Date: Tue, 17 Nov 2020 15:32:05 +0530
+Subject: [PATCH 04/10] dt-bindings: mailbox : arm,mhuv2: Add bindings
+
+This patch adds device tree binding for ARM Message Handling Unit (MHU)
+controller version 2.
+
+Based on earlier work by Morten Borup Petersen.
+
+Reviewed-by: Rob Herring <robh@kernel.org>
+Co-developed-by: Tushar Khandelwal <tushar.khandelwal@arm.com>
+Signed-off-by: Tushar Khandelwal <tushar.khandelwal@arm.com>
+Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
+Signed-off-by: Jassi Brar <jaswinder.singh@linaro.org>
+
+Upstream-Status: Backport [https://lkml.org/lkml/2020/11/17/234]
+Signed-off-by: Arunachalam Ganapathy <arunachalam.ganapathy@arm.com>
+---
+ .../bindings/mailbox/arm,mhuv2.yaml | 209 ++++++++++++++++++
+ 1 file changed, 209 insertions(+)
+ create mode 100644 Documentation/devicetree/bindings/mailbox/arm,mhuv2.yaml
+
+diff --git a/Documentation/devicetree/bindings/mailbox/arm,mhuv2.yaml b/Documentation/devicetree/bindings/mailbox/arm,mhuv2.yaml
+new file mode 100644
+index 000000000000..6608545ea66f
+--- /dev/null
++++ b/Documentation/devicetree/bindings/mailbox/arm,mhuv2.yaml
+@@ -0,0 +1,209 @@
++# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
++%YAML 1.2
++---
++$id: http://devicetree.org/schemas/mailbox/arm,mhuv2.yaml#
++$schema: http://devicetree.org/meta-schemas/core.yaml#
++
++title: ARM MHUv2 Mailbox Controller
++
++maintainers:
++ - Tushar Khandelwal <tushar.khandelwal@arm.com>
++ - Viresh Kumar <viresh.kumar@linaro.org>
++
++description: |
++ The Arm Message Handling Unit (MHU) Version 2 is a mailbox controller that has
++ between 1 and 124 channel windows (each 32-bit wide) to provide unidirectional
++ communication with remote processor(s), where the number of channel windows
++ are implementation dependent.
++
++ Given the unidirectional nature of the controller, an MHUv2 mailbox may only
++ be written to or read from. If a pair of MHU controllers is implemented
++ between two processing elements to provide bidirectional communication, these
++ must be specified as two separate mailboxes.
++
++ If the interrupts property is present in device tree node, then its treated as
++ a "receiver" mailbox, otherwise a "sender".
++
++ An MHU controller must be specified along with the supported transport
++ protocols. The transport protocols determine the method of data transmission
++ as well as the number of provided mailbox channels.
++
++ Following are the possible transport protocols.
++
++ - Data-transfer: Each transfer is made of one or more words, using one or more
++ channel windows.
++
++ - Doorbell: Each transfer is made up of single bit flag, using any one of the
++ bits in a channel window. A channel window can support up to 32 doorbells
++ and the entire window shall be used in doorbell protocol. Optionally, data
++ may be transmitted through a shared memory region, wherein the MHU is used
++ strictly as an interrupt generation mechanism but that is out of the scope
++ of these bindings.
++
++# We need a select here so we don't match all nodes with 'arm,primecell'
++select:
++ properties:
++ compatible:
++ contains:
++ enum:
++ - arm,mhuv2-tx
++ - arm,mhuv2-rx
++ required:
++ - compatible
++
++properties:
++ compatible:
++ oneOf:
++ - description: Sender mode
++ items:
++ - const: arm,mhuv2-tx
++ - const: arm,primecell
++
++ - description: Receiver-mode
++ items:
++ - const: arm,mhuv2-rx
++ - const: arm,primecell
++
++ reg:
++ maxItems: 1
++
++ interrupts:
++ description: |
++ The MHUv2 controller always implements an interrupt in the "receiver"
++ mode, while the interrupt in the "sender" mode was not available in the
++ version MHUv2.0, but the later versions do have it.
++ maxItems: 1
++
++ clocks:
++ maxItems: 1
++
++ clock-names:
++ maxItems: 1
++
++ arm,mhuv2-protocols:
++ $ref: /schemas/types.yaml#/definitions/uint32-matrix
++ description: |
++ The MHUv2 controller may contain up to 124 channel windows (each 32-bit
++ wide). The hardware and the DT bindings allows any combination of those to
++ be used for various transport protocols.
++
++ This property allows a platform to describe how these channel windows are
++ used in various transport protocols. The entries in this property shall be
++ present as an array of tuples, where each tuple describes details about
++ one of the transport protocol being implemented over some channel
++ window(s).
++
++ The first field of a tuple signifies the transfer protocol, 0 is reserved
++ for doorbell protocol, and 1 is reserved for data-transfer protocol.
++ Using any other value in the first field of a tuple makes it invalid.
++
++ The second field of a tuple signifies the number of channel windows where
++ the protocol would be used and should be set to a non zero value. For
++ doorbell protocol this field signifies the number of 32-bit channel
++ windows that implement the doorbell protocol. For data-transfer protocol,
++ this field signifies the number of 32-bit channel windows that implement
++ the data-transfer protocol.
++
++ The total number of channel windows specified here shouldn't be more than
++ the ones implemented by the platform, though one can specify lesser number
++ of windows here than what the platform implements.
++
++ mhu: mailbox@2b1f0000 {
++ ...
++
++ arm,mhuv2-protocols = <0 2>, <1 1>, <1 5>, <1 7>;
++ }
++
++ The above example defines the protocols of an ARM MHUv2 mailbox
++ controller, where a total of 15 channel windows are used. The first two
++ windows are used in doorbell protocol (64 doorbells), followed by 1, 5 and
++ 7 windows (separately) used in data-transfer protocol.
++
++ minItems: 1
++ maxItems: 124
++ items:
++ items:
++ - enum: [ 0, 1 ]
++ - minimum: 0
++ maximum: 124
++
++
++ '#mbox-cells':
++ description: |
++ It is always set to 2. The first argument in the consumers 'mboxes'
++ property represents the channel window group, which may be used in
++ doorbell, or data-transfer protocol, and the second argument (only
++ relevant in doorbell protocol, should be 0 otherwise) represents the
++ doorbell number within the 32 bit wide channel window.
++
++ From the example given above for arm,mhuv2-protocols, here is how a client
++ node can reference them.
++
++ mboxes = <&mhu 0 5>; // Channel Window Group 0, doorbell 5.
++ mboxes = <&mhu 1 7>; // Channel Window Group 1, doorbell 7.
++ mboxes = <&mhu 2 0>; // Channel Window Group 2, data transfer protocol with 1 window.
++ mboxes = <&mhu 3 0>; // Channel Window Group 3, data transfer protocol with 5 windows.
++ mboxes = <&mhu 4 0>; // Channel Window Group 4, data transfer protocol with 7 windows.
++
++ const: 2
++
++if:
++ # Interrupt is compulsory for receiver
++ properties:
++ compatible:
++ contains:
++ const: arm,mhuv2-rx
++then:
++ required:
++ - interrupts
++
++required:
++ - compatible
++ - reg
++ - '#mbox-cells'
++ - arm,mhuv2-protocols
++
++additionalProperties: false
++
++examples:
++ # Multiple transport protocols implemented by the mailbox controllers
++ - |
++ soc {
++ #address-cells = <2>;
++ #size-cells = <2>;
++
++ mhu_tx: mailbox@2b1f0000 {
++ #mbox-cells = <2>;
++ compatible = "arm,mhuv2-tx", "arm,primecell";
++ reg = <0 0x2b1f0000 0 0x1000>;
++ clocks = <&clock 0>;
++ clock-names = "apb_pclk";
++ interrupts = <0 45 4>;
++ arm,mhuv2-protocols = <1 5>, <1 2>, <1 5>, <1 7>, <0 2>;
++ };
++
++ mhu_rx: mailbox@2b1f1000 {
++ #mbox-cells = <2>;
++ compatible = "arm,mhuv2-rx", "arm,primecell";
++ reg = <0 0x2b1f1000 0 0x1000>;
++ clocks = <&clock 0>;
++ clock-names = "apb_pclk";
++ interrupts = <0 46 4>;
++ arm,mhuv2-protocols = <1 1>, <1 7>, <0 2>;
++ };
++
++ mhu_client: scb@2e000000 {
++ compatible = "fujitsu,mb86s70-scb-1.0";
++ reg = <0 0x2e000000 0 0x4000>;
++
++ mboxes =
++ //data-transfer protocol with 5 windows, mhu-tx
++ <&mhu_tx 2 0>,
++ //data-transfer protocol with 7 windows, mhu-tx
++ <&mhu_tx 3 0>,
++ //doorbell protocol channel 4, doorbell 27, mhu-tx
++ <&mhu_tx 4 27>,
++ //data-transfer protocol with 1 window, mhu-rx
++ <&mhu_rx 0 0>;
++ };
++ };
+--
+2.17.1
+
diff --git a/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc0/0005-mailbox-arm_mhuv2-Add-driver.patch b/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc0/0005-mailbox-arm_mhuv2-Add-driver.patch
new file mode 100644
index 0000000..f3f90ed
--- /dev/null
+++ b/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc0/0005-mailbox-arm_mhuv2-Add-driver.patch
@@ -0,0 +1,1256 @@
+From 51f0bb9cf8e8fca22b040d89e7be802c5ea0cf16 Mon Sep 17 00:00:00 2001
+From: Viresh Kumar <viresh.kumar@linaro.org>
+Date: Tue, 17 Nov 2020 15:32:06 +0530
+Subject: [PATCH 05/10] mailbox: arm_mhuv2: Add driver
+
+This adds driver for the ARM MHUv2 (Message Handling Unit) mailbox
+controller.
+
+This is based on the accepted DT bindings of the controller and supports
+combination of both transport protocols, i.e. doorbell and data-transfer.
+
+Transmitting and receiving data through the mailbox framework is done
+through struct arm_mhuv2_mbox_msg.
+
+Based on the initial work done by Morten Borup Petersen from ARM.
+
+Co-developed-by: Tushar Khandelwal <tushar.khandelwal@arm.com>
+Signed-off-by: Tushar Khandelwal <tushar.khandelwal@arm.com>
+Tested-by: Usama Arif <usama.arif@arm.com>
+Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
+Signed-off-by: Jassi Brar <jaswinder.singh@linaro.org>
+
+Upstream-Status: Backport [https://www.lkml.org/lkml/2020/11/17/235]
+Signed-off-by: Arunachalam Ganapathy <arunachalam.ganapathy@arm.com>
+---
+ MAINTAINERS | 9 +
+ drivers/mailbox/Kconfig | 7 +
+ drivers/mailbox/Makefile | 2 +
+ drivers/mailbox/arm_mhuv2.c | 1136 +++++++++++++++++++++
+ include/linux/mailbox/arm_mhuv2_message.h | 20 +
+ 5 files changed, 1174 insertions(+)
+ create mode 100644 drivers/mailbox/arm_mhuv2.c
+ create mode 100644 include/linux/mailbox/arm_mhuv2_message.h
+
+diff --git a/MAINTAINERS b/MAINTAINERS
+index db2a3dfb063d..389f356aed5d 100644
+--- a/MAINTAINERS
++++ b/MAINTAINERS
+@@ -10458,6 +10458,15 @@ F: drivers/mailbox/
+ F: include/linux/mailbox_client.h
+ F: include/linux/mailbox_controller.h
+
++MAILBOX ARM MHUv2
++M: Viresh Kumar <viresh.kumar@linaro.org>
++M: Tushar Khandelwal <Tushar.Khandelwal@arm.com>
++L: linux-kernel@vger.kernel.org
++S: Maintained
++F: drivers/mailbox/arm_mhuv2.c
++F: include/linux/mailbox/arm_mhuv2_message.h
++F: Documentation/devicetree/bindings/mailbox/arm,mhuv2.yaml
++
+ MAN-PAGES: MANUAL PAGES FOR LINUX -- Sections 2, 3, 4, 5, and 7
+ M: Michael Kerrisk <mtk.manpages@gmail.com>
+ L: linux-man@vger.kernel.org
+diff --git a/drivers/mailbox/Kconfig b/drivers/mailbox/Kconfig
+index 05b1009e2820..3c0ea96a0a8b 100644
+--- a/drivers/mailbox/Kconfig
++++ b/drivers/mailbox/Kconfig
+@@ -16,6 +16,13 @@ config ARM_MHU
+ The controller has 3 mailbox channels, the last of which can be
+ used in Secure mode only.
+
++config ARM_MHU_V2
++ tristate "ARM MHUv2 Mailbox"
++ depends on ARM_AMBA
++ help
++ Say Y here if you want to build the ARM MHUv2 controller driver,
++ which provides unidirectional mailboxes between processing elements.
++
+ config IMX_MBOX
+ tristate "i.MX Mailbox"
+ depends on ARCH_MXC || COMPILE_TEST
+diff --git a/drivers/mailbox/Makefile b/drivers/mailbox/Makefile
+index 2e06e02b2e03..7194fa92c787 100644
+--- a/drivers/mailbox/Makefile
++++ b/drivers/mailbox/Makefile
+@@ -7,6 +7,8 @@ obj-$(CONFIG_MAILBOX_TEST) += mailbox-test.o
+
+ obj-$(CONFIG_ARM_MHU) += arm_mhu.o arm_mhu_db.o
+
++obj-$(CONFIG_ARM_MHU_V2) += arm_mhuv2.o
++
+ obj-$(CONFIG_IMX_MBOX) += imx-mailbox.o
+
+ obj-$(CONFIG_ARMADA_37XX_RWTM_MBOX) += armada-37xx-rwtm-mailbox.o
+diff --git a/drivers/mailbox/arm_mhuv2.c b/drivers/mailbox/arm_mhuv2.c
+new file mode 100644
+index 000000000000..67fb10885bb4
+--- /dev/null
++++ b/drivers/mailbox/arm_mhuv2.c
+@@ -0,0 +1,1136 @@
++// SPDX-License-Identifier: GPL-2.0
++/*
++ * ARM Message Handling Unit Version 2 (MHUv2) driver.
++ *
++ * Copyright (C) 2020 ARM Ltd.
++ * Copyright (C) 2020 Linaro Ltd.
++ *
++ * An MHUv2 mailbox controller can provide up to 124 channel windows (each 32
++ * bit long) and the driver allows any combination of both the transport
++ * protocol modes: data-transfer and doorbell, to be used on those channel
++ * windows.
++ *
++ * The transport protocols should be specified in the device tree entry for the
++ * device. The transport protocols determine how the underlying hardware
++ * resources of the device are utilized when transmitting data. Refer to the
++ * device tree bindings of the ARM MHUv2 controller for more details.
++ *
++ * The number of registered mailbox channels is dependent on both the underlying
++ * hardware - mainly the number of channel windows implemented by the platform,
++ * as well as the selected transport protocols.
++ *
++ * The MHUv2 controller can work both as a sender and receiver, but the driver
++ * and the DT bindings support unidirectional transfers for better allocation of
++ * the channels. That is, this driver will be probed for two separate devices
++ * for each mailbox controller, a sender device and a receiver device.
++ */
++
++#include <linux/amba/bus.h>
++#include <linux/interrupt.h>
++#include <linux/mailbox_controller.h>
++#include <linux/mailbox/arm_mhuv2_message.h>
++#include <linux/module.h>
++#include <linux/of_address.h>
++#include <linux/spinlock.h>
++
++/* ====== MHUv2 Registers ====== */
++
++/* Maximum number of channel windows */
++#define MHUV2_CH_WN_MAX 124
++/* Number of combined interrupt status registers */
++#define MHUV2_CMB_INT_ST_REG_CNT 4
++#define MHUV2_STAT_BYTES (sizeof(u32))
++#define MHUV2_STAT_BITS (MHUV2_STAT_BYTES * __CHAR_BIT__)
++
++#define LSB_MASK(n) ((1 << (n * __CHAR_BIT__)) - 1)
++#define MHUV2_PROTOCOL_PROP "arm,mhuv2-protocols"
++
++/* Register Message Handling Unit Configuration fields */
++struct mhu_cfg_t {
++ u32 num_ch : 7;
++ u32 pad : 25;
++} __packed;
++
++/* register Interrupt Status fields */
++struct int_st_t {
++ u32 nr2r : 1;
++ u32 r2nr : 1;
++ u32 pad : 30;
++} __packed;
++
++/* Register Interrupt Clear fields */
++struct int_clr_t {
++ u32 nr2r : 1;
++ u32 r2nr : 1;
++ u32 pad : 30;
++} __packed;
++
++/* Register Interrupt Enable fields */
++struct int_en_t {
++ u32 r2nr : 1;
++ u32 nr2r : 1;
++ u32 chcomb : 1;
++ u32 pad : 29;
++} __packed;
++
++/* Register Implementer Identification fields */
++struct iidr_t {
++ u32 implementer : 12;
++ u32 revision : 4;
++ u32 variant : 4;
++ u32 product_id : 12;
++} __packed;
++
++/* Register Architecture Identification Register fields */
++struct aidr_t {
++ u32 arch_minor_rev : 4;
++ u32 arch_major_rev : 4;
++ u32 pad : 24;
++} __packed;
++
++/* Sender Channel Window fields */
++struct mhu2_send_ch_wn_reg {
++ u32 stat;
++ u8 pad1[0x0C - 0x04];
++ u32 stat_set;
++ u32 int_st;
++ u32 int_clr;
++ u32 int_en;
++ u8 pad2[0x20 - 0x1C];
++} __packed;
++
++/* Sender frame register fields */
++struct mhu2_send_frame_reg {
++ struct mhu2_send_ch_wn_reg ch_wn[MHUV2_CH_WN_MAX];
++ struct mhu_cfg_t mhu_cfg;
++ u32 resp_cfg;
++ u32 access_request;
++ u32 access_ready;
++ struct int_st_t int_st;
++ struct int_clr_t int_clr;
++ struct int_en_t int_en;
++ u32 reserved0;
++ u32 chcomb_int_st[MHUV2_CMB_INT_ST_REG_CNT];
++ u8 pad[0xFC8 - 0xFB0];
++ struct iidr_t iidr;
++ struct aidr_t aidr;
++} __packed;
++
++/* Receiver Channel Window fields */
++struct mhu2_recv_ch_wn_reg {
++ u32 stat;
++ u32 stat_masked;
++ u32 stat_clear;
++ u8 reserved0[0x10 - 0x0C];
++ u32 mask;
++ u32 mask_set;
++ u32 mask_clear;
++ u8 pad[0x20 - 0x1C];
++} __packed;
++
++/* Receiver frame register fields */
++struct mhu2_recv_frame_reg {
++ struct mhu2_recv_ch_wn_reg ch_wn[MHUV2_CH_WN_MAX];
++ struct mhu_cfg_t mhu_cfg;
++ u8 reserved0[0xF90 - 0xF84];
++ struct int_st_t int_st;
++ struct int_clr_t int_clr;
++ struct int_en_t int_en;
++ u32 pad;
++ u32 chcomb_int_st[MHUV2_CMB_INT_ST_REG_CNT];
++ u8 reserved2[0xFC8 - 0xFB0];
++ struct iidr_t iidr;
++ struct aidr_t aidr;
++} __packed;
++
++
++/* ====== MHUv2 data structures ====== */
++
++enum mhuv2_transport_protocol {
++ DOORBELL = 0,
++ DATA_TRANSFER = 1
++};
++
++enum mhuv2_frame {
++ RECEIVER_FRAME,
++ SENDER_FRAME
++};
++
++/**
++ * struct mhuv2 - MHUv2 mailbox controller data
++ *
++ * @mbox: Mailbox controller belonging to the MHU frame.
++ * @send/recv: Base address of the register mapping region.
++ * @frame: Frame type: RECEIVER_FRAME or SENDER_FRAME.
++ * @irq: Interrupt.
++ * @windows: Channel windows implemented by the platform.
++ * @minor: Minor version of the controller.
++ * @length: Length of the protocols array in bytes.
++ * @protocols: Raw protocol information, derived from device tree.
++ * @doorbell_pending_lock: spinlock required for correct operation of Tx
++ * interrupt for doorbells.
++ */
++struct mhuv2 {
++ struct mbox_controller mbox;
++ union {
++ struct mhu2_send_frame_reg __iomem *send;
++ struct mhu2_recv_frame_reg __iomem *recv;
++ };
++ enum mhuv2_frame frame;
++ unsigned int irq;
++ unsigned int windows;
++ unsigned int minor;
++ unsigned int length;
++ u32 *protocols;
++
++ spinlock_t doorbell_pending_lock;
++};
++
++#define mhu_from_mbox(_mbox) container_of(_mbox, struct mhuv2, mbox)
++
++/**
++ * struct mhuv2_protocol_ops - MHUv2 operations
++ *
++ * Each transport protocol must provide an implementation of the operations
++ * provided here.
++ *
++ * @rx_startup: Startup callback for receiver.
++ * @rx_shutdown: Shutdown callback for receiver.
++ * @read_data: Reads and clears newly available data.
++ * @tx_startup: Startup callback for receiver.
++ * @tx_shutdown: Shutdown callback for receiver.
++ * @last_tx_done: Report back if the last tx is completed or not.
++ * @send_data: Send data to the receiver.
++ */
++struct mhuv2_protocol_ops {
++ int (*rx_startup)(struct mhuv2 *mhu, struct mbox_chan *chan);
++ void (*rx_shutdown)(struct mhuv2 *mhu, struct mbox_chan *chan);
++ void *(*read_data)(struct mhuv2 *mhu, struct mbox_chan *chan);
++
++ void (*tx_startup)(struct mhuv2 *mhu, struct mbox_chan *chan);
++ void (*tx_shutdown)(struct mhuv2 *mhu, struct mbox_chan *chan);
++ int (*last_tx_done)(struct mhuv2 *mhu, struct mbox_chan *chan);
++ int (*send_data)(struct mhuv2 *mhu, struct mbox_chan *chan, void *arg);
++};
++
++/*
++ * MHUv2 mailbox channel's private information
++ *
++ * @ops: protocol specific ops for the channel.
++ * @ch_wn_idx: Channel window index allocated to the channel.
++ * @windows: Total number of windows consumed by the channel, only relevant
++ * in DATA_TRANSFER protocol.
++ * @doorbell: Doorbell bit number within the ch_wn_idx window, only relevant
++ * in DOORBELL protocol.
++ * @pending: Flag indicating pending doorbell interrupt, only relevant in
++ * DOORBELL protocol.
++ */
++struct mhuv2_mbox_chan_priv {
++ const struct mhuv2_protocol_ops *ops;
++ u32 ch_wn_idx;
++ union {
++ u32 windows;
++ struct {
++ u32 doorbell;
++ u32 pending;
++ };
++ };
++};
++
++/* Macro for reading a bitfield within a physically mapped packed struct */
++#define readl_relaxed_bitfield(_regptr, _field) \
++ ({ \
++ u32 _regval; \
++ _regval = readl_relaxed((_regptr)); \
++ (*(typeof((_regptr)))(&_regval))._field; \
++ })
++
++/* Macro for writing a bitfield within a physically mapped packed struct */
++#define writel_relaxed_bitfield(_value, _regptr, _field) \
++ ({ \
++ u32 _regval; \
++ _regval = readl_relaxed(_regptr); \
++ (*(typeof(_regptr))(&_regval))._field = _value; \
++ writel_relaxed(_regval, _regptr); \
++ })
++
++
++/* =================== Doorbell transport protocol operations =============== */
++
++static int mhuv2_doorbell_rx_startup(struct mhuv2 *mhu, struct mbox_chan *chan)
++{
++ struct mhuv2_mbox_chan_priv *priv = chan->con_priv;
++
++ writel_relaxed(BIT(priv->doorbell),
++ &mhu->recv->ch_wn[priv->ch_wn_idx].mask_clear);
++ return 0;
++}
++
++static void mhuv2_doorbell_rx_shutdown(struct mhuv2 *mhu,
++ struct mbox_chan *chan)
++{
++ struct mhuv2_mbox_chan_priv *priv = chan->con_priv;
++
++ writel_relaxed(BIT(priv->doorbell),
++ &mhu->recv->ch_wn[priv->ch_wn_idx].mask_set);
++}
++
++static void *mhuv2_doorbell_read_data(struct mhuv2 *mhu, struct mbox_chan *chan)
++{
++ struct mhuv2_mbox_chan_priv *priv = chan->con_priv;
++
++ writel_relaxed(BIT(priv->doorbell),
++ &mhu->recv->ch_wn[priv->ch_wn_idx].stat_clear);
++ return NULL;
++}
++
++static int mhuv2_doorbell_last_tx_done(struct mhuv2 *mhu,
++ struct mbox_chan *chan)
++{
++ struct mhuv2_mbox_chan_priv *priv = chan->con_priv;
++
++ return !(readl_relaxed(&mhu->send->ch_wn[priv->ch_wn_idx].stat) &
++ BIT(priv->doorbell));
++}
++
++static int mhuv2_doorbell_send_data(struct mhuv2 *mhu, struct mbox_chan *chan,
++ void *arg)
++{
++ struct mhuv2_mbox_chan_priv *priv = chan->con_priv;
++ unsigned long flags;
++
++ spin_lock_irqsave(&mhu->doorbell_pending_lock, flags);
++
++ priv->pending = 1;
++ writel_relaxed(BIT(priv->doorbell),
++ &mhu->send->ch_wn[priv->ch_wn_idx].stat_set);
++
++ spin_unlock_irqrestore(&mhu->doorbell_pending_lock, flags);
++
++ return 0;
++}
++
++static const struct mhuv2_protocol_ops mhuv2_doorbell_ops = {
++ .rx_startup = mhuv2_doorbell_rx_startup,
++ .rx_shutdown = mhuv2_doorbell_rx_shutdown,
++ .read_data = mhuv2_doorbell_read_data,
++ .last_tx_done = mhuv2_doorbell_last_tx_done,
++ .send_data = mhuv2_doorbell_send_data,
++};
++#define IS_PROTOCOL_DOORBELL(_priv) (_priv->ops == &mhuv2_doorbell_ops)
++
++/* ============= Data transfer transport protocol operations ================ */
++
++static int mhuv2_data_transfer_rx_startup(struct mhuv2 *mhu,
++ struct mbox_chan *chan)
++{
++ struct mhuv2_mbox_chan_priv *priv = chan->con_priv;
++ int i = priv->ch_wn_idx + priv->windows - 1;
++
++ /*
++ * The protocol mandates that all but the last status register must be
++ * masked.
++ */
++ writel_relaxed(0xFFFFFFFF, &mhu->recv->ch_wn[i].mask_clear);
++ return 0;
++}
++
++static void mhuv2_data_transfer_rx_shutdown(struct mhuv2 *mhu,
++ struct mbox_chan *chan)
++{
++ struct mhuv2_mbox_chan_priv *priv = chan->con_priv;
++ int i = priv->ch_wn_idx + priv->windows - 1;
++
++ writel_relaxed(0xFFFFFFFF, &mhu->recv->ch_wn[i].mask_set);
++}
++
++static void *mhuv2_data_transfer_read_data(struct mhuv2 *mhu,
++ struct mbox_chan *chan)
++{
++ struct mhuv2_mbox_chan_priv *priv = chan->con_priv;
++ const int windows = priv->windows;
++ struct arm_mhuv2_mbox_msg *msg;
++ u32 *data;
++ int i, idx;
++
++ msg = kzalloc(sizeof(*msg) + windows * MHUV2_STAT_BYTES, GFP_KERNEL);
++ if (!msg)
++ return ERR_PTR(-ENOMEM);
++
++ data = msg->data = msg + 1;
++ msg->len = windows * MHUV2_STAT_BYTES;
++
++ /*
++ * Messages are expected in order of most significant word to least
++ * significant word. Refer mhuv2_data_transfer_send_data() for more
++ * details.
++ *
++ * We also need to read the stat register instead of stat_masked, as we
++ * masked all but the last window.
++ *
++ * Last channel window must be cleared as the final operation. Upon
++ * clearing the last channel window register, which is unmasked in
++ * data-transfer protocol, the interrupt is de-asserted.
++ */
++ for (i = 0; i < windows; i++) {
++ idx = priv->ch_wn_idx + i;
++ data[windows - 1 - i] = readl_relaxed(&mhu->recv->ch_wn[idx].stat);
++ writel_relaxed(0xFFFFFFFF, &mhu->recv->ch_wn[idx].stat_clear);
++ }
++
++ return msg;
++}
++
++static void mhuv2_data_transfer_tx_startup(struct mhuv2 *mhu,
++ struct mbox_chan *chan)
++{
++ struct mhuv2_mbox_chan_priv *priv = chan->con_priv;
++ int i = priv->ch_wn_idx + priv->windows - 1;
++
++ /* Enable interrupts only for the last window */
++ if (mhu->minor) {
++ writel_relaxed(0x1, &mhu->send->ch_wn[i].int_clr);
++ writel_relaxed(0x1, &mhu->send->ch_wn[i].int_en);
++ }
++}
++
++static void mhuv2_data_transfer_tx_shutdown(struct mhuv2 *mhu,
++ struct mbox_chan *chan)
++{
++ struct mhuv2_mbox_chan_priv *priv = chan->con_priv;
++ int i = priv->ch_wn_idx + priv->windows - 1;
++
++ if (mhu->minor)
++ writel_relaxed(0x0, &mhu->send->ch_wn[i].int_en);
++}
++
++static int mhuv2_data_transfer_last_tx_done(struct mhuv2 *mhu,
++ struct mbox_chan *chan)
++{
++ struct mhuv2_mbox_chan_priv *priv = chan->con_priv;
++ int i = priv->ch_wn_idx + priv->windows - 1;
++
++ /* Just checking the last channel window should be enough */
++ return !readl_relaxed(&mhu->send->ch_wn[i].stat);
++}
++
++/*
++ * Message will be transmitted from most significant to least significant word.
++ * This is to allow for messages shorter than channel windows to still trigger
++ * the receiver interrupt which gets activated when the last stat register is
++ * written. As an example, a 6-word message is to be written on a 4-channel MHU
++ * connection: Registers marked with '*' are masked, and will not generate an
++ * interrupt on the receiver side once written.
++ *
++ * u32 *data = [0x00000001], [0x00000002], [0x00000003], [0x00000004],
++ * [0x00000005], [0x00000006]
++ *
++ * ROUND 1:
++ * stat reg To write Write sequence
++ * [ stat 3 ] <- [0x00000001] 4 <- triggers interrupt on receiver
++ * [ stat 2 ] <- [0x00000002] 3
++ * [ stat 1 ] <- [0x00000003] 2
++ * [ stat 0 ] <- [0x00000004] 1
++ *
++ * data += 4 // Increment data pointer by number of stat regs
++ *
++ * ROUND 2:
++ * stat reg To write Write sequence
++ * [ stat 3 ] <- [0x00000005] 2 <- triggers interrupt on receiver
++ * [ stat 2 ] <- [0x00000006] 1
++ * [ stat 1 ] <- [0x00000000]
++ * [ stat 0 ] <- [0x00000000]
++ */
++static int mhuv2_data_transfer_send_data(struct mhuv2 *mhu,
++ struct mbox_chan *chan, void *arg)
++{
++ const struct arm_mhuv2_mbox_msg *msg = arg;
++ int bytes_left = msg->len, bytes_to_send, bytes_in_round, i;
++ struct mhuv2_mbox_chan_priv *priv = chan->con_priv;
++ int windows = priv->windows;
++ u32 *data = msg->data, word;
++
++ while (bytes_left) {
++ if (!data[0]) {
++ dev_err(mhu->mbox.dev, "Data aligned at first window can't be zero to guarantee interrupt generation at receiver");
++ return -EINVAL;
++ }
++
++ while(!mhuv2_data_transfer_last_tx_done(mhu, chan))
++ continue;
++
++ bytes_in_round = min(bytes_left, (int)(windows * MHUV2_STAT_BYTES));
++
++ for (i = windows - 1; i >= 0; i--) {
++ /* Data less than windows can transfer ? */
++ if (unlikely(bytes_in_round <= i * MHUV2_STAT_BYTES))
++ continue;
++
++ word = data[i];
++ bytes_to_send = bytes_in_round & (MHUV2_STAT_BYTES - 1);
++ if (unlikely(bytes_to_send))
++ word &= LSB_MASK(bytes_to_send);
++ else
++ bytes_to_send = MHUV2_STAT_BYTES;
++
++ writel_relaxed(word, &mhu->send->ch_wn[priv->ch_wn_idx + windows - 1 - i].stat_set);
++ bytes_left -= bytes_to_send;
++ bytes_in_round -= bytes_to_send;
++ }
++
++ data += windows;
++ }
++
++ return 0;
++}
++
++static const struct mhuv2_protocol_ops mhuv2_data_transfer_ops = {
++ .rx_startup = mhuv2_data_transfer_rx_startup,
++ .rx_shutdown = mhuv2_data_transfer_rx_shutdown,
++ .read_data = mhuv2_data_transfer_read_data,
++ .tx_startup = mhuv2_data_transfer_tx_startup,
++ .tx_shutdown = mhuv2_data_transfer_tx_shutdown,
++ .last_tx_done = mhuv2_data_transfer_last_tx_done,
++ .send_data = mhuv2_data_transfer_send_data,
++};
++
++/* Interrupt handlers */
++
++static struct mbox_chan *get_irq_chan_comb(struct mhuv2 *mhu, u32 *reg)
++{
++ struct mbox_chan *chans = mhu->mbox.chans;
++ int channel = 0, i, offset = 0, windows, protocol, ch_wn;
++ u32 stat;
++
++ for (i = 0; i < MHUV2_CMB_INT_ST_REG_CNT; i++) {
++ stat = readl_relaxed(reg + i);
++ if (!stat)
++ continue;
++
++ ch_wn = i * MHUV2_STAT_BITS + __builtin_ctz(stat);
++
++ for (i = 0; i < mhu->length; i += 2) {
++ protocol = mhu->protocols[i];
++ windows = mhu->protocols[i + 1];
++
++ if (ch_wn >= offset + windows) {
++ if (protocol == DOORBELL)
++ channel += MHUV2_STAT_BITS * windows;
++ else
++ channel++;
++
++ offset += windows;
++ continue;
++ }
++
++ /* Return first chan of the window in doorbell mode */
++ if (protocol == DOORBELL)
++ channel += MHUV2_STAT_BITS * (ch_wn - offset);
++
++ return &chans[channel];
++ }
++ }
++
++ return ERR_PTR(-EIO);
++}
++
++static irqreturn_t mhuv2_sender_interrupt(int irq, void *data)
++{
++ struct mhuv2 *mhu = data;
++ struct device *dev = mhu->mbox.dev;
++ struct mhuv2_mbox_chan_priv *priv;
++ struct mbox_chan *chan;
++ unsigned long flags;
++ int i, found = 0;
++ u32 stat;
++
++ chan = get_irq_chan_comb(mhu, mhu->send->chcomb_int_st);
++ if (IS_ERR(chan)) {
++ dev_warn(dev, "Failed to find channel for the Tx interrupt\n");
++ return IRQ_NONE;
++ }
++ priv = chan->con_priv;
++
++ if (!IS_PROTOCOL_DOORBELL(priv)) {
++ writel_relaxed(1, &mhu->send->ch_wn[priv->ch_wn_idx + priv->windows - 1].int_clr);
++
++ if (chan->cl) {
++ mbox_chan_txdone(chan, 0);
++ return IRQ_HANDLED;
++ }
++
++ dev_warn(dev, "Tx interrupt Received on channel (%u) not currently attached to a mailbox client\n",
++ priv->ch_wn_idx);
++ return IRQ_NONE;
++ }
++
++ /* Clear the interrupt first, so we don't miss any doorbell later */
++ writel_relaxed(1, &mhu->send->ch_wn[priv->ch_wn_idx].int_clr);
++
++ /*
++ * In Doorbell mode, make sure no new transitions happen while the
++ * interrupt handler is trying to find the finished doorbell tx
++ * operations, else we may think few of the transfers were complete
++ * before they actually were.
++ */
++ spin_lock_irqsave(&mhu->doorbell_pending_lock, flags);
++
++ /*
++ * In case of doorbell mode, the first channel of the window is returned
++ * by get_irq_chan_comb(). Find all the pending channels here.
++ */
++ stat = readl_relaxed(&mhu->send->ch_wn[priv->ch_wn_idx].stat);
++
++ for (i = 0; i < MHUV2_STAT_BITS; i++) {
++ priv = chan[i].con_priv;
++
++ /* Find cases where pending was 1, but stat's bit is cleared */
++ if (priv->pending ^ ((stat >> i) & 0x1)) {
++ BUG_ON(!priv->pending);
++
++ if (!chan->cl) {
++ dev_warn(dev, "Tx interrupt received on doorbell (%u : %u) channel not currently attached to a mailbox client\n",
++ priv->ch_wn_idx, i);
++ continue;
++ }
++
++ mbox_chan_txdone(&chan[i], 0);
++ priv->pending = 0;
++ found++;
++ }
++ }
++
++ spin_unlock_irqrestore(&mhu->doorbell_pending_lock, flags);
++
++ if (!found) {
++ /*
++ * We may have already processed the doorbell in the previous
++ * iteration if the interrupt came right after we cleared it but
++ * before we read the stat register.
++ */
++ dev_dbg(dev, "Couldn't find the doorbell (%u) for the Tx interrupt interrupt\n",
++ priv->ch_wn_idx);
++ return IRQ_NONE;
++ }
++
++ return IRQ_HANDLED;
++}
++
++static struct mbox_chan *get_irq_chan_comb_rx(struct mhuv2 *mhu)
++{
++ struct mhuv2_mbox_chan_priv *priv;
++ struct mbox_chan *chan;
++ u32 stat;
++
++ chan = get_irq_chan_comb(mhu, mhu->recv->chcomb_int_st);
++ if (IS_ERR(chan))
++ return chan;
++
++ priv = chan->con_priv;
++ if (!IS_PROTOCOL_DOORBELL(priv))
++ return chan;
++
++ /*
++ * In case of doorbell mode, the first channel of the window is returned
++ * by the routine. Find the exact channel here.
++ */
++ stat = readl_relaxed(&mhu->recv->ch_wn[priv->ch_wn_idx].stat_masked);
++ BUG_ON(!stat);
++
++ return chan + __builtin_ctz(stat);
++}
++
++static struct mbox_chan *get_irq_chan_stat_rx(struct mhuv2 *mhu)
++{
++ struct mbox_chan *chans = mhu->mbox.chans;
++ struct mhuv2_mbox_chan_priv *priv;
++ u32 stat;
++ int i = 0;
++
++ while (i < mhu->mbox.num_chans) {
++ priv = chans[i].con_priv;
++ stat = readl_relaxed(&mhu->recv->ch_wn[priv->ch_wn_idx].stat_masked);
++
++ if (stat) {
++ if (IS_PROTOCOL_DOORBELL(priv))
++ i += __builtin_ctz(stat);
++ return &chans[i];
++ }
++
++ i += IS_PROTOCOL_DOORBELL(priv) ? MHUV2_STAT_BITS : 1;
++ }
++
++ return ERR_PTR(-EIO);
++}
++
++static struct mbox_chan *get_irq_chan_rx(struct mhuv2 *mhu)
++{
++ if (!mhu->minor)
++ return get_irq_chan_stat_rx(mhu);
++
++ return get_irq_chan_comb_rx(mhu);
++}
++
++static irqreturn_t mhuv2_receiver_interrupt(int irq, void *arg)
++{
++ struct mhuv2 *mhu = arg;
++ struct mbox_chan *chan = get_irq_chan_rx(mhu);
++ struct device *dev = mhu->mbox.dev;
++ struct mhuv2_mbox_chan_priv *priv;
++ int ret = IRQ_NONE;
++ void *data;
++
++ if (IS_ERR(chan)) {
++ dev_warn(dev, "Failed to find channel for the rx interrupt\n");
++ return IRQ_NONE;
++ }
++ priv = chan->con_priv;
++
++ /* Read and clear the data first */
++ data = priv->ops->read_data(mhu, chan);
++
++ if (!chan->cl) {
++ dev_warn(dev, "Received data on channel (%u) not currently attached to a mailbox client\n",
++ priv->ch_wn_idx);
++ } else if (IS_ERR(data)) {
++ dev_err(dev, "Failed to read data: %lu\n", PTR_ERR(data));
++ } else {
++ mbox_chan_received_data(chan, data);
++ ret = IRQ_HANDLED;
++ }
++
++ kfree(data);
++ return ret;
++}
++
++/* Sender and receiver ops */
++static bool mhuv2_sender_last_tx_done(struct mbox_chan *chan)
++{
++ struct mhuv2 *mhu = mhu_from_mbox(chan->mbox);
++ struct mhuv2_mbox_chan_priv *priv = chan->con_priv;
++
++ return priv->ops->last_tx_done(mhu, chan);
++}
++
++static int mhuv2_sender_send_data(struct mbox_chan *chan, void *data)
++{
++ struct mhuv2 *mhu = mhu_from_mbox(chan->mbox);
++ struct mhuv2_mbox_chan_priv *priv = chan->con_priv;
++
++ if (!priv->ops->last_tx_done(mhu, chan))
++ return -EBUSY;
++
++ return priv->ops->send_data(mhu, chan, data);
++}
++
++static int mhuv2_sender_startup(struct mbox_chan *chan)
++{
++ struct mhuv2 *mhu = mhu_from_mbox(chan->mbox);
++ struct mhuv2_mbox_chan_priv *priv = chan->con_priv;
++
++ if (priv->ops->tx_startup)
++ priv->ops->tx_startup(mhu, chan);
++ return 0;
++}
++
++static void mhuv2_sender_shutdown(struct mbox_chan *chan)
++{
++ struct mhuv2 *mhu = mhu_from_mbox(chan->mbox);
++ struct mhuv2_mbox_chan_priv *priv = chan->con_priv;
++
++ if (priv->ops->tx_shutdown)
++ priv->ops->tx_shutdown(mhu, chan);
++}
++
++static const struct mbox_chan_ops mhuv2_sender_ops = {
++ .send_data = mhuv2_sender_send_data,
++ .startup = mhuv2_sender_startup,
++ .shutdown = mhuv2_sender_shutdown,
++ .last_tx_done = mhuv2_sender_last_tx_done,
++};
++
++static int mhuv2_receiver_startup(struct mbox_chan *chan)
++{
++ struct mhuv2 *mhu = mhu_from_mbox(chan->mbox);
++ struct mhuv2_mbox_chan_priv *priv = chan->con_priv;
++
++ return priv->ops->rx_startup(mhu, chan);
++}
++
++static void mhuv2_receiver_shutdown(struct mbox_chan *chan)
++{
++ struct mhuv2 *mhu = mhu_from_mbox(chan->mbox);
++ struct mhuv2_mbox_chan_priv *priv = chan->con_priv;
++
++ priv->ops->rx_shutdown(mhu, chan);
++}
++
++static int mhuv2_receiver_send_data(struct mbox_chan *chan, void *data)
++{
++ dev_err(chan->mbox->dev,
++ "Trying to transmit on a receiver MHU frame\n");
++ return -EIO;
++}
++
++static bool mhuv2_receiver_last_tx_done(struct mbox_chan *chan)
++{
++ dev_err(chan->mbox->dev, "Trying to Tx poll on a receiver MHU frame\n");
++ return true;
++}
++
++static const struct mbox_chan_ops mhuv2_receiver_ops = {
++ .send_data = mhuv2_receiver_send_data,
++ .startup = mhuv2_receiver_startup,
++ .shutdown = mhuv2_receiver_shutdown,
++ .last_tx_done = mhuv2_receiver_last_tx_done,
++};
++
++static struct mbox_chan *mhuv2_mbox_of_xlate(struct mbox_controller *mbox,
++ const struct of_phandle_args *pa)
++{
++ struct mhuv2 *mhu = mhu_from_mbox(mbox);
++ struct mbox_chan *chans = mbox->chans;
++ int channel = 0, i, offset, doorbell, protocol, windows;
++
++ if (pa->args_count != 2)
++ return ERR_PTR(-EINVAL);
++
++ offset = pa->args[0];
++ doorbell = pa->args[1];
++ if (doorbell >= MHUV2_STAT_BITS)
++ goto out;
++
++ for (i = 0; i < mhu->length; i += 2) {
++ protocol = mhu->protocols[i];
++ windows = mhu->protocols[i + 1];
++
++ if (protocol == DOORBELL) {
++ if (offset < windows)
++ return &chans[channel + MHUV2_STAT_BITS * offset + doorbell];
++
++ channel += MHUV2_STAT_BITS * windows;
++ offset -= windows;
++ } else {
++ if (offset == 0) {
++ if (doorbell)
++ goto out;
++
++ return &chans[channel];
++ }
++
++ channel++;
++ offset--;
++ }
++ }
++
++out:
++ dev_err(mbox->dev, "Couldn't xlate to a valid channel (%d: %d)\n",
++ pa->args[0], doorbell);
++ return ERR_PTR(-ENODEV);
++}
++
++static int mhuv2_verify_protocol(struct mhuv2 *mhu)
++{
++ struct device *dev = mhu->mbox.dev;
++ int protocol, windows, channels = 0, total_windows = 0, i;
++
++ for (i = 0; i < mhu->length; i += 2) {
++ protocol = mhu->protocols[i];
++ windows = mhu->protocols[i + 1];
++
++ if (!windows) {
++ dev_err(dev, "Window size can't be zero (%d)\n", i);
++ return -EINVAL;
++ }
++ total_windows += windows;
++
++ if (protocol == DOORBELL) {
++ channels += MHUV2_STAT_BITS * windows;
++ } else if (protocol == DATA_TRANSFER) {
++ channels++;
++ } else {
++ dev_err(dev, "Invalid protocol (%d) present in %s property at index %d\n",
++ protocol, MHUV2_PROTOCOL_PROP, i);
++ return -EINVAL;
++ }
++ }
++
++ if (total_windows > mhu->windows) {
++ dev_err(dev, "Channel windows can't be more than what's implemented by the hardware ( %d: %d)\n",
++ total_windows, mhu->windows);
++ return -EINVAL;
++ }
++
++ mhu->mbox.num_chans = channels;
++ return 0;
++}
++
++static int mhuv2_allocate_channels(struct mhuv2 *mhu)
++{
++ struct mbox_controller *mbox = &mhu->mbox;
++ struct mhuv2_mbox_chan_priv *priv;
++ struct device *dev = mbox->dev;
++ struct mbox_chan *chans;
++ int protocol, windows = 0, next_window = 0, i, j, k;
++
++ chans = devm_kcalloc(dev, mbox->num_chans, sizeof(*chans), GFP_KERNEL);
++ if (!chans)
++ return -ENOMEM;
++
++ mbox->chans = chans;
++
++ for (i = 0; i < mhu->length; i += 2) {
++ next_window += windows;
++
++ protocol = mhu->protocols[i];
++ windows = mhu->protocols[i + 1];
++
++ if (protocol == DATA_TRANSFER) {
++ priv = devm_kmalloc(dev, sizeof(*priv), GFP_KERNEL);
++ if (!priv)
++ return -ENOMEM;
++
++ priv->ch_wn_idx = next_window;
++ priv->ops = &mhuv2_data_transfer_ops;
++ priv->windows = windows;
++ chans++->con_priv = priv;
++ continue;
++ }
++
++ for (j = 0; j < windows; j++) {
++ for (k = 0; k < MHUV2_STAT_BITS; k++) {
++ priv = devm_kmalloc(dev, sizeof(*priv), GFP_KERNEL);
++ if (!priv)
++ return -ENOMEM;
++
++ priv->ch_wn_idx = next_window + j;
++ priv->ops = &mhuv2_doorbell_ops;
++ priv->doorbell = k;
++ chans++->con_priv = priv;
++ }
++
++ /*
++ * Permanently enable interrupt as we can't
++ * control it per doorbell.
++ */
++ if (mhu->frame == SENDER_FRAME && mhu->minor)
++ writel_relaxed(0x1, &mhu->send->ch_wn[priv->ch_wn_idx].int_en);
++ }
++ }
++
++ /* Make sure we have initialized all channels */
++ BUG_ON(chans - mbox->chans != mbox->num_chans);
++
++ return 0;
++}
++
++static int mhuv2_parse_channels(struct mhuv2 *mhu)
++{
++ struct device *dev = mhu->mbox.dev;
++ const struct device_node *np = dev->of_node;
++ int ret, count;
++ u32 *protocols;
++
++ count = of_property_count_u32_elems(np, MHUV2_PROTOCOL_PROP);
++ if (count <= 0 || count % 2) {
++ dev_err(dev, "Invalid %s property (%d)\n", MHUV2_PROTOCOL_PROP,
++ count);
++ return -EINVAL;
++ }
++
++ protocols = devm_kmalloc_array(dev, count, sizeof(*protocols), GFP_KERNEL);
++ if (!protocols)
++ return -ENOMEM;
++
++ ret = of_property_read_u32_array(np, MHUV2_PROTOCOL_PROP, protocols, count);
++ if (ret) {
++ dev_err(dev, "Failed to read %s property: %d\n",
++ MHUV2_PROTOCOL_PROP, ret);
++ return ret;
++ }
++
++ mhu->protocols = protocols;
++ mhu->length = count;
++
++ ret = mhuv2_verify_protocol(mhu);
++ if (ret)
++ return ret;
++
++ return mhuv2_allocate_channels(mhu);
++}
++
++static int mhuv2_tx_init(struct amba_device *adev, struct mhuv2 *mhu,
++ void __iomem *reg)
++{
++ struct device *dev = mhu->mbox.dev;
++ int ret, i;
++
++ mhu->frame = SENDER_FRAME;
++ mhu->mbox.ops = &mhuv2_sender_ops;
++ mhu->send = reg;
++
++ mhu->windows = readl_relaxed_bitfield(&mhu->send->mhu_cfg, num_ch);
++ mhu->minor = readl_relaxed_bitfield(&mhu->send->aidr, arch_minor_rev);
++
++ spin_lock_init(&mhu->doorbell_pending_lock);
++
++ /*
++ * For minor version 1 and forward, tx interrupt is provided by
++ * the controller.
++ */
++ if (mhu->minor && adev->irq[0]) {
++ ret = devm_request_threaded_irq(dev, adev->irq[0], NULL,
++ mhuv2_sender_interrupt,
++ IRQF_ONESHOT, "mhuv2-tx", mhu);
++ if (ret) {
++ dev_err(dev, "Failed to request tx IRQ, fallback to polling mode: %d\n",
++ ret);
++ } else {
++ mhu->mbox.txdone_irq = true;
++ mhu->mbox.txdone_poll = false;
++ mhu->irq = adev->irq[0];
++
++ writel_relaxed_bitfield(1, &mhu->send->int_en, chcomb);
++
++ /* Disable all channel interrupts */
++ for (i = 0; i < mhu->windows; i++)
++ writel_relaxed(0x0, &mhu->send->ch_wn[i].int_en);
++
++ goto out;
++ }
++ }
++
++ mhu->mbox.txdone_irq = false;
++ mhu->mbox.txdone_poll = true;
++ mhu->mbox.txpoll_period = 1;
++
++out:
++ /* Wait for receiver to be ready */
++ writel_relaxed(0x1, &mhu->send->access_request);
++ while (!readl_relaxed(&mhu->send->access_ready))
++ continue;
++
++ return 0;
++}
++
++static int mhuv2_rx_init(struct amba_device *adev, struct mhuv2 *mhu,
++ void __iomem *reg)
++{
++ struct device *dev = mhu->mbox.dev;
++ int ret, i;
++
++ mhu->frame = RECEIVER_FRAME;
++ mhu->mbox.ops = &mhuv2_receiver_ops;
++ mhu->recv = reg;
++
++ mhu->windows = readl_relaxed_bitfield(&mhu->recv->mhu_cfg, num_ch);
++ mhu->minor = readl_relaxed_bitfield(&mhu->recv->aidr, arch_minor_rev);
++
++ mhu->irq = adev->irq[0];
++ if (!mhu->irq) {
++ dev_err(dev, "Missing receiver IRQ\n");
++ return -EINVAL;
++ }
++
++ ret = devm_request_threaded_irq(dev, mhu->irq, NULL,
++ mhuv2_receiver_interrupt, IRQF_ONESHOT,
++ "mhuv2-rx", mhu);
++ if (ret) {
++ dev_err(dev, "Failed to request rx IRQ\n");
++ return ret;
++ }
++
++ /* Mask all the channel windows */
++ for (i = 0; i < mhu->windows; i++)
++ writel_relaxed(0xFFFFFFFF, &mhu->recv->ch_wn[i].mask_set);
++
++ if (mhu->minor)
++ writel_relaxed_bitfield(1, &mhu->recv->int_en, chcomb);
++
++ return 0;
++}
++
++static int mhuv2_probe(struct amba_device *adev, const struct amba_id *id)
++{
++ struct device *dev = &adev->dev;
++ const struct device_node *np = dev->of_node;
++ struct mhuv2 *mhu;
++ void __iomem *reg;
++ int ret = -EINVAL;
++
++ reg = devm_of_iomap(dev, dev->of_node, 0, NULL);
++ if (!reg)
++ return -ENOMEM;
++
++ mhu = devm_kzalloc(dev, sizeof(*mhu), GFP_KERNEL);
++ if (!mhu)
++ return -ENOMEM;
++
++ mhu->mbox.dev = dev;
++ mhu->mbox.of_xlate = mhuv2_mbox_of_xlate;
++
++ if (of_device_is_compatible(np, "arm,mhuv2-tx"))
++ ret = mhuv2_tx_init(adev, mhu, reg);
++ else if (of_device_is_compatible(np, "arm,mhuv2-rx"))
++ ret = mhuv2_rx_init(adev, mhu, reg);
++ else
++ dev_err(dev, "Invalid compatible property\n");
++
++ if (ret)
++ return ret;
++
++ /* Channel windows can't be 0 */
++ BUG_ON(!mhu->windows);
++
++ ret = mhuv2_parse_channels(mhu);
++ if (ret)
++ return ret;
++
++ amba_set_drvdata(adev, mhu);
++
++ ret = devm_mbox_controller_register(dev, &mhu->mbox);
++ if (ret)
++ dev_err(dev, "failed to register ARM MHUv2 driver %d\n", ret);
++
++ return ret;
++}
++
++static int mhuv2_remove(struct amba_device *adev)
++{
++ struct mhuv2 *mhu = amba_get_drvdata(adev);
++
++ if (mhu->frame == SENDER_FRAME)
++ writel_relaxed(0x0, &mhu->send->access_request);
++
++ return 0;
++}
++
++static struct amba_id mhuv2_ids[] = {
++ {
++ /* 2.0 */
++ .id = 0xbb0d1,
++ .mask = 0xfffff,
++ },
++ {
++ /* 2.1 */
++ .id = 0xbb076,
++ .mask = 0xfffff,
++ },
++ { 0, 0 },
++};
++MODULE_DEVICE_TABLE(amba, mhuv2_ids);
++
++static struct amba_driver mhuv2_driver = {
++ .drv = {
++ .name = "arm-mhuv2",
++ },
++ .id_table = mhuv2_ids,
++ .probe = mhuv2_probe,
++ .remove = mhuv2_remove,
++};
++module_amba_driver(mhuv2_driver);
++
++MODULE_LICENSE("GPL v2");
++MODULE_DESCRIPTION("ARM MHUv2 Driver");
++MODULE_AUTHOR("Viresh Kumar <viresh.kumar@linaro.org>");
++MODULE_AUTHOR("Tushar Khandelwal <tushar.khandelwal@arm.com>");
+diff --git a/include/linux/mailbox/arm_mhuv2_message.h b/include/linux/mailbox/arm_mhuv2_message.h
+new file mode 100644
+index 000000000000..821b9d96daa4
+--- /dev/null
++++ b/include/linux/mailbox/arm_mhuv2_message.h
+@@ -0,0 +1,20 @@
++// SPDX-License-Identifier: GPL-2.0
++/*
++ * ARM MHUv2 Mailbox Message
++ *
++ * Copyright (C) 2020 Arm Ltd.
++ * Copyright (C) 2020 Linaro Ltd.
++ */
++
++#ifndef _LINUX_ARM_MHUV2_MESSAGE_H_
++#define _LINUX_ARM_MHUV2_MESSAGE_H_
++
++#include <linux/types.h>
++
++/* Data structure for data-transfer protocol */
++struct arm_mhuv2_mbox_msg {
++ void *data;
++ size_t len;
++};
++
++#endif /* _LINUX_ARM_MHUV2_MESSAGE_H_ */
+--
+2.17.1
+
diff --git a/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc0/0006-mailbox-arm_mhuv2-Fix-sparse-warnings.patch b/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc0/0006-mailbox-arm_mhuv2-Fix-sparse-warnings.patch
new file mode 100644
index 0000000..46fe1aa
--- /dev/null
+++ b/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc0/0006-mailbox-arm_mhuv2-Fix-sparse-warnings.patch
@@ -0,0 +1,114 @@
+From f082677cb35ea843e749e1c9e5a9b9fba44c5d48 Mon Sep 17 00:00:00 2001
+From: Viresh Kumar <viresh.kumar@linaro.org>
+Date: Wed, 30 Dec 2020 10:12:04 +0530
+Subject: [PATCH 06/10] mailbox: arm_mhuv2: Fix sparse warnings
+
+This patch fixes a bunch of sparse warnings in the newly added arm_mhuv2
+driver.
+
+drivers/mailbox/arm_mhuv2.c:506:24: warning: incorrect type in argument 1 (different address spaces)
+drivers/mailbox/arm_mhuv2.c:506:24: expected void const volatile [noderef] __iomem *addr
+drivers/mailbox/arm_mhuv2.c:506:24: got unsigned int [usertype] *
+drivers/mailbox/arm_mhuv2.c:547:42: warning: incorrect type in argument 2 (different address spaces)
+drivers/mailbox/arm_mhuv2.c:547:42: expected unsigned int [usertype] *reg
+drivers/mailbox/arm_mhuv2.c:547:42: got unsigned int [noderef] __iomem *
+drivers/mailbox/arm_mhuv2.c:625:42: warning: incorrect type in argument 2 (different address spaces)
+drivers/mailbox/arm_mhuv2.c:625:42: expected unsigned int [usertype] *reg
+drivers/mailbox/arm_mhuv2.c:625:42: got unsigned int [noderef] __iomem *
+drivers/mailbox/arm_mhuv2.c:972:24: warning: dereference of noderef expression
+drivers/mailbox/arm_mhuv2.c:973:22: warning: dereference of noderef expression
+drivers/mailbox/arm_mhuv2.c:993:25: warning: dereference of noderef expression
+drivers/mailbox/arm_mhuv2.c:1026:24: warning: dereference of noderef expression
+drivers/mailbox/arm_mhuv2.c:1027:22: warning: dereference of noderef expression
+drivers/mailbox/arm_mhuv2.c:1048:17: warning: dereference of noderef expression
+
+Reported-by: kernel test robot <lkp@intel.com>
+Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
+Signed-off-by: Jassi Brar <jaswinder.singh@linaro.org>
+
+Upstream-Status: Backport [https://lkml.org/lkml/2021/2/9/428]
+Signed-off-by: Arunachalam Ganapathy <arunachalam.ganapathy@arm.com>
+---
+ drivers/mailbox/arm_mhuv2.c | 22 +++++++++++-----------
+ 1 file changed, 11 insertions(+), 11 deletions(-)
+
+diff --git a/drivers/mailbox/arm_mhuv2.c b/drivers/mailbox/arm_mhuv2.c
+index 67fb10885bb4..8223c1005254 100644
+--- a/drivers/mailbox/arm_mhuv2.c
++++ b/drivers/mailbox/arm_mhuv2.c
+@@ -238,19 +238,19 @@ struct mhuv2_mbox_chan_priv {
+ };
+
+ /* Macro for reading a bitfield within a physically mapped packed struct */
+-#define readl_relaxed_bitfield(_regptr, _field) \
++#define readl_relaxed_bitfield(_regptr, _type, _field) \
+ ({ \
+ u32 _regval; \
+ _regval = readl_relaxed((_regptr)); \
+- (*(typeof((_regptr)))(&_regval))._field; \
++ (*(_type *)(&_regval))._field; \
+ })
+
+ /* Macro for writing a bitfield within a physically mapped packed struct */
+-#define writel_relaxed_bitfield(_value, _regptr, _field) \
++#define writel_relaxed_bitfield(_value, _regptr, _type, _field) \
+ ({ \
+ u32 _regval; \
+ _regval = readl_relaxed(_regptr); \
+- (*(typeof(_regptr))(&_regval))._field = _value; \
++ (*(_type *)(&_regval))._field = _value; \
+ writel_relaxed(_regval, _regptr); \
+ })
+
+@@ -496,7 +496,7 @@ static const struct mhuv2_protocol_ops mhuv2_data_transfer_ops = {
+
+ /* Interrupt handlers */
+
+-static struct mbox_chan *get_irq_chan_comb(struct mhuv2 *mhu, u32 *reg)
++static struct mbox_chan *get_irq_chan_comb(struct mhuv2 *mhu, u32 __iomem *reg)
+ {
+ struct mbox_chan *chans = mhu->mbox.chans;
+ int channel = 0, i, offset = 0, windows, protocol, ch_wn;
+@@ -969,8 +969,8 @@ static int mhuv2_tx_init(struct amba_device *adev, struct mhuv2 *mhu,
+ mhu->mbox.ops = &mhuv2_sender_ops;
+ mhu->send = reg;
+
+- mhu->windows = readl_relaxed_bitfield(&mhu->send->mhu_cfg, num_ch);
+- mhu->minor = readl_relaxed_bitfield(&mhu->send->aidr, arch_minor_rev);
++ mhu->windows = readl_relaxed_bitfield(&mhu->send->mhu_cfg, struct mhu_cfg_t, num_ch);
++ mhu->minor = readl_relaxed_bitfield(&mhu->send->aidr, struct aidr_t, arch_minor_rev);
+
+ spin_lock_init(&mhu->doorbell_pending_lock);
+
+@@ -990,7 +990,7 @@ static int mhuv2_tx_init(struct amba_device *adev, struct mhuv2 *mhu,
+ mhu->mbox.txdone_poll = false;
+ mhu->irq = adev->irq[0];
+
+- writel_relaxed_bitfield(1, &mhu->send->int_en, chcomb);
++ writel_relaxed_bitfield(1, &mhu->send->int_en, struct int_en_t, chcomb);
+
+ /* Disable all channel interrupts */
+ for (i = 0; i < mhu->windows; i++)
+@@ -1023,8 +1023,8 @@ static int mhuv2_rx_init(struct amba_device *adev, struct mhuv2 *mhu,
+ mhu->mbox.ops = &mhuv2_receiver_ops;
+ mhu->recv = reg;
+
+- mhu->windows = readl_relaxed_bitfield(&mhu->recv->mhu_cfg, num_ch);
+- mhu->minor = readl_relaxed_bitfield(&mhu->recv->aidr, arch_minor_rev);
++ mhu->windows = readl_relaxed_bitfield(&mhu->recv->mhu_cfg, struct mhu_cfg_t, num_ch);
++ mhu->minor = readl_relaxed_bitfield(&mhu->recv->aidr, struct aidr_t, arch_minor_rev);
+
+ mhu->irq = adev->irq[0];
+ if (!mhu->irq) {
+@@ -1045,7 +1045,7 @@ static int mhuv2_rx_init(struct amba_device *adev, struct mhuv2 *mhu,
+ writel_relaxed(0xFFFFFFFF, &mhu->recv->ch_wn[i].mask_set);
+
+ if (mhu->minor)
+- writel_relaxed_bitfield(1, &mhu->recv->int_en, chcomb);
++ writel_relaxed_bitfield(1, &mhu->recv->int_en, struct int_en_t, chcomb);
+
+ return 0;
+ }
+--
+2.17.1
+
diff --git a/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc0/0007-mailbox-arm_mhuv2-make-remove-callback-return-void.patch b/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc0/0007-mailbox-arm_mhuv2-make-remove-callback-return-void.patch
new file mode 100644
index 0000000..cd1bb0b
--- /dev/null
+++ b/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc0/0007-mailbox-arm_mhuv2-make-remove-callback-return-void.patch
@@ -0,0 +1,47 @@
+From a0e07a4d72dfe8892ebcfb29c0a1007c35eebd66 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= <u.kleine-koenig@pengutronix.de>
+Date: Tue, 2 Feb 2021 20:43:08 +0100
+Subject: [PATCH 07/10] mailbox: arm_mhuv2: make remove callback return void
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+My build tests failed to catch that amba driver that would have needed
+adaption in commit 3fd269e74f2f ("amba: Make the remove callback return
+void"). Change the remove function to make the driver build again.
+
+Reported-by: kernel test robot <lkp@intel.com>
+Fixes: 3fd269e74f2f ("amba: Make the remove callback return void")
+Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
+Acked-by: Viresh Kumar <viresh.kumar@linaro.org>
+Signed-off-by: Jassi Brar <jaswinder.singh@linaro.org>
+
+Upstream-Status: Backport [https://lkml.org/lkml/2021/2/2/1525]
+Signed-off-by: Arunachalam Ganapathy <arunachalam.ganapathy@arm.com>
+---
+ drivers/mailbox/arm_mhuv2.c | 4 +---
+ 1 file changed, 1 insertion(+), 3 deletions(-)
+
+diff --git a/drivers/mailbox/arm_mhuv2.c b/drivers/mailbox/arm_mhuv2.c
+index 8223c1005254..cdfb1939fabf 100644
+--- a/drivers/mailbox/arm_mhuv2.c
++++ b/drivers/mailbox/arm_mhuv2.c
+@@ -1095,14 +1095,12 @@ static int mhuv2_probe(struct amba_device *adev, const struct amba_id *id)
+ return ret;
+ }
+
+-static int mhuv2_remove(struct amba_device *adev)
++static void mhuv2_remove(struct amba_device *adev)
+ {
+ struct mhuv2 *mhu = amba_get_drvdata(adev);
+
+ if (mhu->frame == SENDER_FRAME)
+ writel_relaxed(0x0, &mhu->send->access_request);
+-
+- return 0;
+ }
+
+ static struct amba_id mhuv2_ids[] = {
+--
+2.17.1
+
diff --git a/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc0/0008-mailbox-arm_mhuv2-Skip-calling-kfree-with-invalid-po.patch b/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc0/0008-mailbox-arm_mhuv2-Skip-calling-kfree-with-invalid-po.patch
new file mode 100644
index 0000000..6553594
--- /dev/null
+++ b/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc0/0008-mailbox-arm_mhuv2-Skip-calling-kfree-with-invalid-po.patch
@@ -0,0 +1,41 @@
+From c55091b7738802c503b1ce4276ee85d601604506 Mon Sep 17 00:00:00 2001
+From: Viresh Kumar <viresh.kumar@linaro.org>
+Date: Mon, 22 Feb 2021 12:48:06 +0530
+Subject: [PATCH 08/10] mailbox: arm_mhuv2: Skip calling kfree() with invalid
+ pointer
+
+It is possible that 'data' passed to kfree() is set to a error value
+instead of allocated space. Make sure it doesn't get called with invalid
+pointer.
+
+Fixes: 5a6338cce9f4 ("mailbox: arm_mhuv2: Add driver")
+Cc: v5.11 <stable@vger.kernel.org> # v5.11
+Reported-by: kernel test robot <lkp@intel.com>
+Reported-by: Dan Carpenter <dan.carpenter@oracle.com>
+Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
+Signed-off-by: Jassi Brar <jaswinder.singh@linaro.org>
+
+Upstream-Status: Backport [https://lkml.org/lkml/2021/2/22/57]
+Signed-off-by: Arunachalam Ganapathy <arunachalam.ganapathy@arm.com>
+---
+ drivers/mailbox/arm_mhuv2.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/mailbox/arm_mhuv2.c b/drivers/mailbox/arm_mhuv2.c
+index cdfb1939fabf..d997f8ebfa98 100644
+--- a/drivers/mailbox/arm_mhuv2.c
++++ b/drivers/mailbox/arm_mhuv2.c
+@@ -699,7 +699,9 @@ static irqreturn_t mhuv2_receiver_interrupt(int irq, void *arg)
+ ret = IRQ_HANDLED;
+ }
+
+- kfree(data);
++ if (!IS_ERR(data))
++ kfree(data);
++
+ return ret;
+ }
+
+--
+2.17.1
+
diff --git a/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.4/tc0/defconfig b/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc0/defconfig
similarity index 95%
rename from meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.4/tc0/defconfig
rename to meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc0/defconfig
index c8caa05..f16b899 100644
--- a/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.4/tc0/defconfig
+++ b/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc0/defconfig
@@ -2,7 +2,6 @@ CONFIG_POSIX_MQUEUE=y
CONFIG_AUDIT=y
CONFIG_NO_HZ=y
CONFIG_HIGH_RES_TIMERS=y
-CONFIG_ASYMMETRIC_AARCH32=y
CONFIG_PREEMPT=y
CONFIG_IRQ_TIME_ACCOUNTING=y
CONFIG_BSD_PROCESS_ACCT=y
@@ -67,7 +66,6 @@ CONFIG_ARCH_ZYNQMP=y
CONFIG_ARM64_VA_BITS_48=y
CONFIG_SCHED_MC=y
CONFIG_NUMA=y
-CONFIG_SECCOMP=y
CONFIG_KEXEC=y
CONFIG_CRASH_DUMP=y
CONFIG_XEN=y
@@ -86,7 +84,6 @@ CONFIG_ARM_CPUIDLE=y
CONFIG_ARM_PSCI_CPUIDLE=y
CONFIG_CPU_FREQ=y
CONFIG_CPU_FREQ_STAT=y
-CONFIG_CPU_FREQ_DEFAULT_GOV_SCHEDUTIL=y
CONFIG_CPU_FREQ_GOV_POWERSAVE=m
CONFIG_CPU_FREQ_GOV_USERSPACE=y
CONFIG_CPU_FREQ_GOV_ONDEMAND=y
@@ -113,10 +110,10 @@ CONFIG_IMX_SCU_PD=y
CONFIG_ACPI=y
CONFIG_ACPI_APEI=y
CONFIG_ACPI_APEI_GHES=y
-CONFIG_ACPI_APEI_PCIEAER=y
CONFIG_ACPI_APEI_MEMORY_FAILURE=y
CONFIG_ACPI_APEI_EINJ=y
CONFIG_VIRTUALIZATION=y
+CONFIG_KVM=y
CONFIG_ARM64_CRYPTO=y
CONFIG_CRYPTO_SHA1_ARM64_CE=y
CONFIG_CRYPTO_SHA2_ARM64_CE=y
@@ -242,7 +239,6 @@ CONFIG_QRTR_TUN=m
CONFIG_BPF_JIT=y
CONFIG_BT=m
CONFIG_BT_HIDP=m
-# CONFIG_BT_HS is not set
# CONFIG_BT_LE is not set
CONFIG_BT_LEDS=y
# CONFIG_BT_DEBUGFS is not set
@@ -278,7 +274,6 @@ CONFIG_PCIE_QCOM=y
CONFIG_PCIE_ARMADA_8K=y
CONFIG_PCIE_KIRIN=y
CONFIG_PCIE_HISI_STB=y
-CONFIG_PCIE_TEGRA194=m
CONFIG_DEVTMPFS=y
CONFIG_DEVTMPFS_MOUNT=y
CONFIG_FW_LOADER_USER_HELPER=y
@@ -287,12 +282,12 @@ CONFIG_HISILICON_LPC=y
CONFIG_SIMPLE_PM_BUS=y
CONFIG_MTD=y
CONFIG_MTD_BLOCK=y
+CONFIG_MTD_PHRAM=y
CONFIG_MTD_RAW_NAND=y
CONFIG_MTD_NAND_DENALI_DT=y
CONFIG_MTD_NAND_MARVELL=y
CONFIG_MTD_NAND_QCOM=y
CONFIG_MTD_SPI_NOR=y
-CONFIG_SPI_CADENCE_QUADSPI=y
CONFIG_BLK_DEV_LOOP=y
CONFIG_BLK_DEV_NBD=m
CONFIG_BLK_DEV_RAM=y
@@ -367,14 +362,14 @@ CONFIG_SMSC911X=y
CONFIG_SNI_AVE=y
CONFIG_SNI_NETSEC=y
CONFIG_STMMAC_ETH=m
-CONFIG_MDIO_BUS_MUX_MMIOREG=y
-CONFIG_AT803X_PHY=y
+CONFIG_MESON_GXL_PHY=m
CONFIG_MARVELL_PHY=m
CONFIG_MARVELL_10G_PHY=m
-CONFIG_MESON_GXL_PHY=m
CONFIG_MICREL_PHY=y
+CONFIG_AT803X_PHY=y
CONFIG_REALTEK_PHY=m
CONFIG_ROCKCHIP_PHY=y
+CONFIG_MDIO_BUS_MUX_MMIOREG=y
CONFIG_PPP=y
CONFIG_PPP_BSDCOMP=y
CONFIG_PPP_DEFLATE=y
@@ -403,7 +398,6 @@ CONFIG_INPUT_EVDEV=y
CONFIG_KEYBOARD_ADC=m
CONFIG_KEYBOARD_GPIO=y
CONFIG_KEYBOARD_SNVS_PWRKEY=m
-CONFIG_KEYBOARD_CROS_EC=y
CONFIG_INPUT_TOUCHSCREEN=y
CONFIG_TOUCHSCREEN_ATMEL_MXT=m
CONFIG_INPUT_MISC=y
@@ -470,11 +464,11 @@ CONFIG_I2C_SH_MOBILE=y
CONFIG_I2C_TEGRA=y
CONFIG_I2C_UNIPHIER_F=y
CONFIG_I2C_RCAR=y
-CONFIG_I2C_CROS_EC_TUNNEL=y
CONFIG_SPI=y
CONFIG_SPI_ARMADA_3700=y
CONFIG_SPI_BCM2835=m
CONFIG_SPI_BCM2835AUX=m
+CONFIG_SPI_CADENCE_QUADSPI=y
CONFIG_SPI_NXP_FLEXSPI=y
CONFIG_SPI_IMX=m
CONFIG_SPI_MESON_SPICC=m
@@ -498,16 +492,16 @@ CONFIG_PINCTRL_IMX8MM=y
CONFIG_PINCTRL_IMX8MN=y
CONFIG_PINCTRL_IMX8MQ=y
CONFIG_PINCTRL_IMX8QXP=y
-CONFIG_PINCTRL_IPQ8074=y
-CONFIG_PINCTRL_MSM8916=y
-CONFIG_PINCTRL_MSM8994=y
-CONFIG_PINCTRL_MSM8996=y
-CONFIG_PINCTRL_MSM8998=y
-CONFIG_PINCTRL_QCS404=y
-CONFIG_PINCTRL_QDF2XXX=y
+CONFIG_PINCTRL_IPQ8074=m
+CONFIG_PINCTRL_MSM8916=m
+CONFIG_PINCTRL_MSM8994=m
+CONFIG_PINCTRL_MSM8996=m
+CONFIG_PINCTRL_MSM8998=m
+CONFIG_PINCTRL_QCS404=m
+CONFIG_PINCTRL_QDF2XXX=m
CONFIG_PINCTRL_QCOM_SPMI_PMIC=y
-CONFIG_PINCTRL_SDM845=y
-CONFIG_PINCTRL_SM8150=y
+CONFIG_PINCTRL_SDM845=m
+CONFIG_PINCTRL_SM8150=m
CONFIG_GPIO_ALTERA=m
CONFIG_GPIO_DWAPB=y
CONFIG_GPIO_MB86S7X=y
@@ -520,14 +514,13 @@ CONFIG_GPIO_MAX732X=y
CONFIG_GPIO_PCA953X=y
CONFIG_GPIO_PCA953X_IRQ=y
CONFIG_GPIO_MAX77620=y
-CONFIG_POWER_AVS=y
-CONFIG_ROCKCHIP_IODOMAIN=y
CONFIG_POWER_RESET_MSM=y
CONFIG_POWER_RESET_XGENE=y
CONFIG_POWER_RESET_SYSCON=y
CONFIG_SYSCON_REBOOT_MODE=y
CONFIG_BATTERY_SBS=m
CONFIG_BATTERY_BQ27XXX=y
+CONFIG_SENSORS_ARM_SCMI=y
CONFIG_SENSORS_ARM_SCPI=y
CONFIG_SENSORS_LM90=m
CONFIG_SENSORS_PWM_FAN=m
@@ -586,7 +579,7 @@ CONFIG_REGULATOR_MAX77620=y
CONFIG_REGULATOR_MAX8973=y
CONFIG_REGULATOR_PFUZE100=y
CONFIG_REGULATOR_PWM=y
-CONFIG_REGULATOR_QCOM_RPMH=y
+CONFIG_REGULATOR_QCOM_RPMH=m
CONFIG_REGULATOR_QCOM_SMD_RPM=y
CONFIG_REGULATOR_QCOM_SPMI=y
CONFIG_REGULATOR_RK808=y
@@ -598,11 +591,7 @@ CONFIG_RC_DEVICES=y
CONFIG_IR_MESON=m
CONFIG_IR_SUNXI=m
CONFIG_MEDIA_SUPPORT=y
-CONFIG_MEDIA_CAMERA_SUPPORT=y
-CONFIG_MEDIA_ANALOG_TV_SUPPORT=y
-CONFIG_MEDIA_DIGITAL_TV_SUPPORT=y
-CONFIG_MEDIA_CONTROLLER=y
-CONFIG_VIDEO_V4L2_SUBDEV_API=y
+CONFIG_MEDIA_SUBDRV_AUTOSELECT=y
# CONFIG_DVB_NET is not set
CONFIG_MEDIA_USB_SUPPORT=y
CONFIG_USB_VIDEO_CLASS=m
@@ -614,7 +603,6 @@ CONFIG_VIDEO_SAMSUNG_S5P_MFC=m
CONFIG_VIDEO_SAMSUNG_EXYNOS_GSC=m
CONFIG_VIDEO_RENESAS_FCP=m
CONFIG_VIDEO_RENESAS_VSP1=m
-CONFIG_MEDIA_SUBDRV_AUTOSELECT=y
CONFIG_DRM=y
CONFIG_DRM_LOAD_EDID_FIRMWARE=y
CONFIG_DRM_I2C_CH7006=m
@@ -657,7 +645,6 @@ CONFIG_DRM_PANFROST=m
CONFIG_DRM_LEGACY=y
CONFIG_FB_MODE_HELPERS=y
CONFIG_FB_EFI=y
-CONFIG_BACKLIGHT_GENERIC=m
CONFIG_BACKLIGHT_PWM=m
CONFIG_BACKLIGHT_LP855X=m
CONFIG_FRAMEBUFFER_CONSOLE=y
@@ -699,7 +686,6 @@ CONFIG_HID_REDRAGON=y
CONFIG_HID_MICROSOFT=y
CONFIG_HID_MONTEREY=y
CONFIG_I2C_HID=m
-CONFIG_USB_CONN_GPIO=m
CONFIG_USB=y
CONFIG_USB_OTG=y
CONFIG_USB_XHCI_HCD=y
@@ -775,7 +761,6 @@ CONFIG_RTC_DRV_RX8581=m
CONFIG_RTC_DRV_S5M=y
CONFIG_RTC_DRV_DS3232=y
CONFIG_RTC_DRV_EFI=y
-CONFIG_RTC_DRV_CROS_EC=y
CONFIG_RTC_DRV_S3C=y
CONFIG_RTC_DRV_PL031=y
CONFIG_RTC_DRV_SUN6I=y
@@ -811,9 +796,7 @@ CONFIG_STAGING=y
CONFIG_ASHMEM=y
CONFIG_ION=y
CONFIG_ION_SYSTEM_HEAP=y
-CONFIG_MFD_CROS_EC=y
-CONFIG_CROS_EC_I2C=y
-CONFIG_CROS_EC_SPI=y
+CONFIG_ION_CMA_HEAP=y
CONFIG_COMMON_CLK_RK808=y
CONFIG_COMMON_CLK_SCMI=y
CONFIG_COMMON_CLK_SCPI=y
@@ -831,7 +814,7 @@ CONFIG_COMMON_CLK_QCOM=y
CONFIG_QCOM_A53PLL=y
CONFIG_QCOM_CLK_APCS_MSM8916=y
CONFIG_QCOM_CLK_SMD_RPM=y
-CONFIG_QCOM_CLK_RPMH=y
+CONFIG_QCOM_CLK_RPMH=m
CONFIG_IPQ_GCC_8074=y
CONFIG_MSM_GCC_8916=y
CONFIG_MSM_GCC_8994=y
@@ -862,26 +845,24 @@ CONFIG_RPMSG_QCOM_GLINK_SMEM=m
CONFIG_RPMSG_QCOM_SMD=y
CONFIG_OWL_PM_DOMAINS=y
CONFIG_RASPBERRYPI_POWER=y
-CONFIG_IMX_SCU_SOC=y
CONFIG_QCOM_AOSS_QMP=y
CONFIG_QCOM_GENI_SE=y
-CONFIG_QCOM_GLINK_SSR=m
CONFIG_QCOM_RMTFS_MEM=m
-CONFIG_QCOM_RPMH=y
-CONFIG_QCOM_RPMHPD=y
+CONFIG_QCOM_RPMH=m
+CONFIG_QCOM_RPMHPD=m
CONFIG_QCOM_SMEM=y
CONFIG_QCOM_SMD_RPM=y
CONFIG_QCOM_SMP2P=y
CONFIG_QCOM_SMSM=y
CONFIG_QCOM_SOCINFO=m
-CONFIG_ARCH_R8A774A1=y
-CONFIG_ARCH_R8A774C0=y
-CONFIG_ARCH_R8A7795=y
+CONFIG_ARCH_R8A77995=y
+CONFIG_ARCH_R8A77990=y
CONFIG_ARCH_R8A77965=y
-CONFIG_ARCH_R8A77970=y
CONFIG_ARCH_R8A77980=y
-CONFIG_ARCH_R8A77990=y
-CONFIG_ARCH_R8A77995=y
+CONFIG_ARCH_R8A77970=y
+CONFIG_ARCH_R8A774C0=y
+CONFIG_ARCH_R8A774A1=y
+CONFIG_ROCKCHIP_IODOMAIN=y
CONFIG_ROCKCHIP_PM_DOMAINS=y
CONFIG_ARCH_TEGRA_132_SOC=y
CONFIG_ARCH_TEGRA_210_SOC=y
@@ -891,21 +872,15 @@ CONFIG_ARCH_K3_AM6_SOC=y
CONFIG_ARCH_K3_J721E_SOC=y
CONFIG_TI_SCI_PM_DOMAINS=y
CONFIG_EXTCON_USB_GPIO=y
-CONFIG_EXTCON_USBC_CROS_EC=y
CONFIG_MEMORY=y
CONFIG_IIO=y
CONFIG_EXYNOS_ADC=y
CONFIG_QCOM_SPMI_ADC5=m
CONFIG_ROCKCHIP_SARADC=m
-CONFIG_IIO_CROS_EC_SENSORS_CORE=m
-CONFIG_IIO_CROS_EC_SENSORS=m
-CONFIG_IIO_CROS_EC_LIGHT_PROX=m
CONFIG_SENSORS_ISL29018=m
-CONFIG_IIO_CROS_EC_BARO=m
CONFIG_MPL3115=m
CONFIG_PWM=y
CONFIG_PWM_BCM2835=m
-CONFIG_PWM_CROS_EC=m
CONFIG_PWM_MESON=m
CONFIG_PWM_RCAR=m
CONFIG_PWM_ROCKCHIP=y
@@ -937,9 +912,9 @@ CONFIG_PHY_UNIPHIER_USB3=y
CONFIG_PHY_TEGRA_XUSB=y
CONFIG_ARM_SMMU_V3_PMU=m
CONFIG_FSL_IMX8_DDR_PMU=m
-CONFIG_HISI_PMU=y
CONFIG_QCOM_L2_PMU=y
CONFIG_QCOM_L3_PMU=y
+CONFIG_HISI_PMU=y
CONFIG_ANDROID=y
CONFIG_ANDROID_BINDER_IPC=y
CONFIG_NVMEM_IMX_OCOTP=y
@@ -995,8 +970,8 @@ CONFIG_CRYPTO_DEV_HISI_ZIP=m
CONFIG_CMA_SIZE_MBYTES=256
CONFIG_PRINTK_TIME=y
CONFIG_DEBUG_INFO=y
-CONFIG_DEBUG_FS=y
CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_FS=y
# CONFIG_SCHED_DEBUG is not set
# CONFIG_DEBUG_PREEMPT is not set
# CONFIG_FTRACE is not set
diff --git a/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.4/tc0/0003-mailbox-arm_mhuv2-add-device-tree-binding-documentat.patch b/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.4/tc0/0003-mailbox-arm_mhuv2-add-device-tree-binding-documentat.patch
deleted file mode 100644
index 060be39..0000000
--- a/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.4/tc0/0003-mailbox-arm_mhuv2-add-device-tree-binding-documentat.patch
+++ /dev/null
@@ -1,134 +0,0 @@
-From bca81c4c54765565651634b6de5edb6a191577a3 Mon Sep 17 00:00:00 2001
-From: Usama Arif <usama.arif@arm.com>
-Date: Thu, 27 Jun 2019 11:16:22 +0100
-Subject: [PATCH 3/9] mailbox: arm_mhuv2: add device tree binding documentation
-
-This patch adds device tree binding for Message Handling Unit
-controller version 2 from Arm.
-
-Change-Id: I8c46dd7cd1a48450020c33721ea7cce9f8b8e64f
-Signed-off-by: Usama Arif <usama.arif@arm.com>
-Signed-off-by: Morten Borup Petersen <morten.petersen@arm.com>
-Signed-off-by: Tushar Khandelwal <tushar.khandelwal@arm.com>
-Cc: robh+dt@kernel.org
-Cc: mark.rutland@arm.com
-Cc: devicetree@vger.kernel.org
-Cc: jassisinghbrar@gmail.com
-
-Upstream-Status: Denied [https://lkml.org/lkml/2019/7/17/615]
----
- .../devicetree/bindings/mailbox/arm,mhuv2.txt | 101 ++++++++++++++++++
- 1 file changed, 101 insertions(+)
- create mode 100644 Documentation/devicetree/bindings/mailbox/arm,mhuv2.txt
-
-diff --git a/Documentation/devicetree/bindings/mailbox/arm,mhuv2.txt b/Documentation/devicetree/bindings/mailbox/arm,mhuv2.txt
-new file mode 100644
-index 000000000000..5b8a2ab21ae0
---- /dev/null
-+++ b/Documentation/devicetree/bindings/mailbox/arm,mhuv2.txt
-@@ -0,0 +1,101 @@
-+Arm MHUv2 Mailbox Driver
-+========================
-+
-+The Arm Message-Handling-Unit (MHU) Version 2 is a mailbox controller that has
-+between 1 and 124 channel windows to provide unidirectional communication with
-+remote processor(s).
-+
-+Given the unidirectional nature of the device, an MHUv2 mailbox may only be
-+written to or read from. If a pair of MHU devices is implemented between two
-+processing elements to provide bidirectional communication, these must be
-+specified as two separate mailboxes.
-+
-+If the interrupts property is present in device tree node, then its treated
-+as a receiver frame, otherwise a sender frame.
-+
-+An MHU device must be specified with a transport protocol. The transport
-+protocol of an MHU device determines the method of data transmission as well as
-+the number of provided mailboxes.
-+Following are the possible transport protocol types:
-+- Single-word: An MHU device implements as many mailboxes as it
-+ provides channel windows. Data is transmitted through
-+ the MHU registers.
-+- Multi-word: An MHU device implements a single mailbox. All channel windows
-+ will be used during transmission. Data is transmitted through
-+ the MHU registers.
-+- Doorbell: An MHU device implements as many mailboxes as there are flag
-+ bits available in its channel windows. Optionally, data may
-+ be transmitted through a shared memory region, wherein the MHU
-+ is used strictly as an interrupt generation mechanism.
-+
-+Mailbox Device Node:
-+====================
-+
-+Required properties:
-+--------------------
-+- compatible: Shall be "arm,mhuv2" & "arm,primecell"
-+- reg: Contains the mailbox register address range (base
-+ address and length)
-+- #mbox-cells Shall be 1 - the index of the channel needed.
-+- mhu-protocol Transport protocol of the device. Shall be one of the
-+ following: "single-word", "multi-word", "doorbell"
-+
-+Required properties (receiver frame):
-+-------------------------------------
-+- interrupts: Contains the interrupt information for the receiver frame
-+
-+Example:
-+--------
-+
-+ mbox_mw_tx: mhu@10000000 {
-+ compatible = "arm,mhuv2","arm,primecell";
-+ reg = <0x10000000 0x1000>;
-+ clocks = <&refclk100mhz>;
-+ clock-names = "apb_pclk";
-+ #mbox-cells = <1>;
-+ mhu-protocol = "multi-word";
-+ };
-+
-+ mbox_sw_tx: mhu@10000000 {
-+ compatible = "arm,mhuv2","arm,primecell";
-+ reg = <0x11000000 0x1000>;
-+ clocks = <&refclk100mhz>;
-+ clock-names = "apb_pclk";
-+ #mbox-cells = <1>;
-+ mhu-protocol = "single-word";
-+ };
-+
-+ mbox_db_rx: mhu@10000000 {
-+ compatible = "arm,mhuv2","arm,primecell";
-+ reg = <0x12000000 0x1000>;
-+ clocks = <&refclk100mhz>;
-+ clock-names = "apb_pclk";
-+ #mbox-cells = <1>;
-+ interrupts = <0 45 4>;
-+ interrupt-names = "mhu_rx";
-+ mhu-protocol = "doorbell";
-+ };
-+
-+ mhu_client: scb@2e000000 {
-+ compatible = "fujitsu,mb86s70-scb-1.0";
-+ reg = <0 0x2e000000 0x4000>;
-+ mboxes =
-+ // For multi-word frames, client may only instantiate a single
-+ // mailbox for a mailbox controller
-+ <&mbox_mw_tx 0>,
-+
-+ // For single-word frames, client may instantiate as many
-+ // mailboxes as there are channel windows in the MHU
-+ <&mbox_sw_tx 0>,
-+ <&mbox_sw_tx 1>,
-+ <&mbox_sw_tx 2>,
-+ <&mbox_sw_tx 3>,
-+
-+ // For doorbell frames, client may instantiate as many mailboxes
-+ // as there are bits available in the combined number of channel
-+ // windows ((channel windows * 32) mailboxes)
-+ <mbox_db_rx 0>,
-+ <mbox_db_rx 1>,
-+ ...
-+ <mbox_db_rx 17>;
-+ };
-\ No newline at end of file
---
-2.17.1
-
diff --git a/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.4/tc0/0004-mailbox-arm_mhuv2-add-arm-mhuv2-driver.patch b/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.4/tc0/0004-mailbox-arm_mhuv2-add-arm-mhuv2-driver.patch
deleted file mode 100644
index f357935..0000000
--- a/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.4/tc0/0004-mailbox-arm_mhuv2-add-arm-mhuv2-driver.patch
+++ /dev/null
@@ -1,822 +0,0 @@
-From 364539028799290814a35aa10d32d850486f0b4a Mon Sep 17 00:00:00 2001
-From: Usama Arif <usama.arif@arm.com>
-Date: Thu, 27 Jun 2019 11:17:14 +0100
-Subject: [PATCH 4/9] mailbox: arm_mhuv2: add arm mhuv2 driver
-
-This commit adds a driver for the ARM MHUv2 (Message Handling Unit).
-The driver registers itself as a mailbox controller within the common
-mailbox framework.
-
-This commit implements the single-word transport protocol;
-In single-word mode, the mailbox controller will provide a mailbox for each
-channel window available in the MHU device.
-Transmitting and receiving data through the mailbox framework in
-single-word mode is done through a struct arm_mbox_msg.
-
-Change-Id: I718253ceb902a2d53f7199a746063a36129b0fa6
-Signed-off-by: Usama Arif <usama.arif@arm.com>
-Signed-off-by: Morten Borup Petersen <morten.petersen@arm.com>
-Signed-off-by: Tushar Khandelwal <tushar.khandelwal@arm.com>
-Cc: jassisinghbrar@gmail.com
-Cc: devicetree@vger.kernel.org
-
-Upstream-Status: Denied [https://lkml.org/lkml/2019/7/17/615]
----
- drivers/mailbox/Kconfig | 7 +
- drivers/mailbox/Makefile | 2 +
- drivers/mailbox/arm_mhu_v2.c | 707 +++++++++++++++++++++++
- include/linux/mailbox/arm-mbox-message.h | 37 ++
- 4 files changed, 753 insertions(+)
- create mode 100644 drivers/mailbox/arm_mhu_v2.c
- create mode 100644 include/linux/mailbox/arm-mbox-message.h
-
-diff --git a/drivers/mailbox/Kconfig b/drivers/mailbox/Kconfig
-index ab4eb750bbdd..0a0dce01098c 100644
---- a/drivers/mailbox/Kconfig
-+++ b/drivers/mailbox/Kconfig
-@@ -22,6 +22,13 @@ config IMX_MBOX
- help
- Mailbox implementation for i.MX Messaging Unit (MU).
-
-+config ARM_MHU_V2
-+ tristate "ARM MHUv2 Mailbox"
-+ depends on ARM_AMBA
-+ help
-+ Say Y here if you want to build the ARM MHUv2 controller driver,
-+ which provides unidirectional mailboxes between processing elements.
-+
- config PLATFORM_MHU
- tristate "Platform MHU Mailbox"
- depends on OF
-diff --git a/drivers/mailbox/Makefile b/drivers/mailbox/Makefile
-index c22fad6f696b..78377f459421 100644
---- a/drivers/mailbox/Makefile
-+++ b/drivers/mailbox/Makefile
-@@ -11,6 +11,8 @@ obj-$(CONFIG_IMX_MBOX) += imx-mailbox.o
-
- obj-$(CONFIG_ARMADA_37XX_RWTM_MBOX) += armada-37xx-rwtm-mailbox.o
-
-+obj-$(CONFIG_ARM_MHU_V2) += arm_mhu_v2.o
-+
- obj-$(CONFIG_PLATFORM_MHU) += platform_mhu.o
-
- obj-$(CONFIG_PL320_MBOX) += pl320-ipc.o
-diff --git a/drivers/mailbox/arm_mhu_v2.c b/drivers/mailbox/arm_mhu_v2.c
-new file mode 100644
-index 000000000000..d809076eb47b
---- /dev/null
-+++ b/drivers/mailbox/arm_mhu_v2.c
-@@ -0,0 +1,707 @@
-+// SPDX-License-Identifier: GPL-2.0
-+/*
-+ * Arm Message Handling Unit Version 2 (MHUv2) driver
-+ *
-+ * An MHU device may function in one of three transport protocol modes
-+ * (single-word, multi-word and doorbell).
-+ * This transport protocol should be specified in the device tree entry for the
-+ * device. The transport protocol determines how the underlying hardware
-+ * resources of the device are utilized when transmitting data.
-+ *
-+ * The arm MHUv2 driver registers as a mailbox controller with the common
-+ * mailbox framework. Each mailbox channel represents a separate virtual
-+ * communication channel through the MHU device.
-+ * The number of registered mailbox channels is dependent on both the
-+ * underlying hardware - mainly the number of channel windows within each MHU
-+ * frame, as well as the selected transport protocol.
-+ *
-+ * Copyright (C) 2019 Arm Ltd.
-+ */
-+
-+#include <linux/slab.h>
-+#include <linux/module.h>
-+#include <linux/amba/bus.h>
-+#include <linux/mailbox_controller.h>
-+#include <linux/mailbox/arm-mbox-message.h>
-+#include <linux/of_address.h>
-+#include <linux/interrupt.h>
-+
-+/* Maximum number of channel windows */
-+#define MHUV2_CHANNEL_MAX 124
-+/* Number of combined interrupt status registers */
-+#define MHUV2_CMB_INT_ST_REG_CNT 4
-+#define MHUV2_CH_UNKNOWN -1
-+
-+/* Channel window status register type */
-+typedef u32 mhuv2_stat_reg_t;
-+#define MHUV2_STAT_BYTES sizeof(mhuv2_stat_reg_t)
-+#define MHUV2_STAT_BITS (MHUV2_STAT_BYTES * __CHAR_BIT__)
-+
-+#define LSB_MASK(n) ((1 << (n)) - 1)
-+
-+#ifndef PAD
-+#define _PADLINE(line) pad##line
-+#define _XSTR(line) _PADLINE(line)
-+#define PAD _XSTR(__LINE__)
-+#endif
-+
-+/* ====== Arm MHUv2 register defines ====== */
-+
-+/* Register Message Handling Unit Configuration fields */
-+struct MHU_CFG_t {
-+ u32 NUM_CH : 7;
-+ u32 PAD : 25;
-+} __packed;
-+
-+/* Register Implementer Identification fields */
-+struct IIDR_t {
-+ u32 IMPLEMENTER : 12;
-+ u32 REVISION : 4;
-+ u32 VARIANT : 4;
-+ u32 PRODUCT_ID : 12;
-+} __packed;
-+
-+/* Register Architecture Identification Register fields */
-+struct AIDR_t {
-+ u32 ARCH_MINOR_REV : 4;
-+ u32 ARCH_MAJOR_REV : 4;
-+ u32 PAD : 24;
-+} __packed;
-+
-+/* register Interrupt Status fields */
-+struct INT_ST_t {
-+ u32 NR2R : 1;
-+ u32 R2NR : 1;
-+ u32 PAD : 30;
-+} __packed;
-+
-+/* Register Interrupt Clear fields */
-+struct INT_CLR_t {
-+ u32 NR2R : 1;
-+ u32 R2NR : 1;
-+ u32 PAD : 30;
-+} __packed;
-+
-+/* Register Interrupt Enable fields */
-+struct INT_EN_t {
-+ u32 R2NR : 1;
-+ u32 NR2R : 1;
-+ u32 CHCOMB : 1;
-+ u32 PAD : 29;
-+} __packed;
-+
-+/* Sender Channel Window fields */
-+struct mhu2_send_channel_reg {
-+ mhuv2_stat_reg_t STAT;
-+ u8 PAD[0xC - 0x4];
-+ mhuv2_stat_reg_t STAT_SET;
-+ u8 PAD[0x20 - 0x10];
-+} __packed;
-+
-+/* Sender frame register fields */
-+struct mhu2_send_frame_reg {
-+ struct mhu2_send_channel_reg channel[MHUV2_CHANNEL_MAX];
-+ struct MHU_CFG_t MHU_CFG;
-+ u32 RESP_CFG;
-+ u32 ACCESS_REQUEST;
-+ u32 ACCESS_READY;
-+ struct INT_ST_t INT_ST;
-+ struct INT_CLR_t INT_CLR;
-+ struct INT_EN_t INT_EN;
-+ u32 RESERVED0;
-+ u32 CHCOMB_INT_ST[MHUV2_CMB_INT_ST_REG_CNT];
-+ u8 PAD[0xFC8 - 0xFB0];
-+ struct IIDR_t IIDR;
-+ struct AIDR_t AIDR;
-+} __packed;
-+
-+/* Receiver Channel Window fields */
-+struct mhu2_recv_channel_reg {
-+ mhuv2_stat_reg_t STAT;
-+ mhuv2_stat_reg_t STAT_PEND;
-+ mhuv2_stat_reg_t STAT_CLEAR;
-+ u8 RESERVED0[0x10 - 0x0C];
-+ mhuv2_stat_reg_t MASK;
-+ mhuv2_stat_reg_t MASK_SET;
-+ mhuv2_stat_reg_t MASK_CLEAR;
-+ u8 PAD[0x20 - 0x1C];
-+} __packed;
-+
-+/* Receiver frame register fields */
-+struct mhu2_recv_frame_reg {
-+ struct mhu2_recv_channel_reg channel[MHUV2_CHANNEL_MAX];
-+ struct MHU_CFG_t MHU_CFG;
-+ u8 RESERVED0[0xF90 - 0xF84];
-+ struct INT_ST_t INT_ST;
-+ struct INT_CLR_t INT_CLR;
-+ struct INT_EN_t INT_EN;
-+ u32 PAD;
-+ mhuv2_stat_reg_t CHCOMB_INT_ST[MHUV2_CMB_INT_ST_REG_CNT];
-+ u8 RESERVED2[0xFC8 - 0xFB0];
-+ struct IIDR_t IIDR;
-+ struct AIDR_t AIDR;
-+} __packed;
-+
-+/* ====== Arm MHUv2 device tree property identifiers ====== */
-+
-+static const char *const mhuv2_protocol_dt_identifiers[] = { "single-word",
-+ "multi-word",
-+ "doorbell" };
-+
-+static const char *const mhuv2_frame_dt_identifiers[] = { "receiver",
-+ "sender" };
-+
-+/* ====== Arm MHUv2 data structures ====== */
-+
-+enum mhuv2_transport_protocol { SINGLE_WORD, MULTI_WORD, DOORBELL };
-+
-+enum mhuv2_frame { RECEIVER_FRAME, SENDER_FRAME };
-+
-+/**
-+ * Arm MHUv2 operations
-+ *
-+ * Each transport protocol must provide an implementation of the operations
-+ * presented in this structure.
-+ * Most operations present a struct mbox_chan* as argument. This channel will
-+ * correspond to one of the virtual channels within the MHU device. What
-+ * constitutes a channel within the MHU device is dependent on the transport
-+ * protocol.
-+ */
-+struct arm_mhuv2;
-+struct mhuv2_ops {
-+ int (*read_data)(struct arm_mhuv2 *mhuv2, struct mbox_chan *chan,
-+ struct arm_mbox_msg *msg);
-+ int (*clear_data)(struct arm_mhuv2 *mhuv2, struct mbox_chan *chan,
-+ struct arm_mbox_msg *msg);
-+ int (*send_data)(struct arm_mhuv2 *mhuv2, struct mbox_chan *chan,
-+ const struct arm_mbox_msg *msg);
-+ int (*setup)(struct arm_mhuv2 *mhuv2);
-+ int (*last_tx_done)(struct arm_mhuv2 *mhuv2, struct mbox_chan *chan);
-+ struct mbox_chan *(*get_active_mbox_chan)(struct arm_mhuv2 *mhuv2);
-+};
-+
-+/**
-+ * Arm MHUv2 mailbox channel information
-+ *
-+ * A channel contains a notion of its index within the array of mailbox channels
-+ * which a mailbox controller allocates.
-+ */
-+struct arm_mhuv2_mbox_chan_priv {
-+ u32 ch_idx;
-+};
-+
-+#define mhuv2_chan_idx(_chanptr) \
-+ (((struct arm_mhuv2_mbox_chan_priv *)(_chanptr)->con_priv)->ch_idx)
-+
-+/**
-+ * Arm MHUv2 mailbox controller data
-+ *
-+ * @reg: Base address of the register mapping region
-+ * @protocol: Transport protocol, derived from device tree
-+ * @frame: Frame type, derived from device tree
-+ * @irq: Interrupt, only valid for receiver frames
-+ * @mbox: Mailbox controller belonging to the MHU frame
-+ * @ops: Pointer to transport-protocol specific operations
-+ * @dev: Device to which it is attached
-+ */
-+struct arm_mhuv2 {
-+ union {
-+ struct mhu2_send_frame_reg __iomem *send;
-+ struct mhu2_recv_frame_reg __iomem *recv;
-+ } reg;
-+ enum mhuv2_frame frame;
-+ unsigned int irq;
-+ struct mbox_controller mbox;
-+ struct mhuv2_ops *ops;
-+ struct device *dev;
-+};
-+
-+#define mhu2_from_mbox_ctrl(_mbox) container_of(_mbox, struct arm_mhuv2, mbox)
-+#define mhu2_from_mbox_chan(_chan) mhu2_from_mbox_ctrl(_chan->mbox)
-+
-+/* Macro for reading a bitfield within a physically mapped packed struct */
-+#define readl_relaxed_bitfield(_regptr, _field) \
-+ ({ \
-+ mhuv2_stat_reg_t _regval; \
-+ BUILD_BUG_ON(sizeof(*(_regptr)) > sizeof(typeof(_regval))); \
-+ _regval = readl_relaxed((_regptr)); \
-+ (*(typeof((_regptr)))(&_regval))._field; \
-+ })
-+
-+/* Macro for writing a bitfield within a physically mapped packed struct */
-+#define writel_relaxed_bitfield(_value, _regptr, _field) \
-+ ({ \
-+ mhuv2_stat_reg_t _regval; \
-+ BUILD_BUG_ON(sizeof(*_regptr) > sizeof(typeof(_regval))); \
-+ _regval = readl_relaxed(_regptr); \
-+ (*(typeof(_regptr))(&_regval))._field = _value; \
-+ writel_relaxed(_regval, _regptr); \
-+ })
-+
-+static inline int __find_set_bit(uint32_t val)
-+{
-+ const uint32_t trailing_zeros = __builtin_ctz(val);
-+ return trailing_zeros == 32 ? -1 : trailing_zeros;
-+}
-+
-+/**
-+ * Get index of a set bit within the combined interrupt status registers
-+ *
-+ * The function will calculate the index being the offset from the LSB of the
-+ * first combined interrupt status register.
-+ *
-+ */
-+static inline int mhuv2_combint_idx(struct arm_mhuv2 *mhuv2)
-+{
-+ int ch_idx = 0;
-+ int set_bit_index, reg_idx;
-+
-+ for (reg_idx = 0; reg_idx < MHUV2_CMB_INT_ST_REG_CNT; reg_idx++) {
-+ mhuv2_stat_reg_t stat_reg;
-+
-+ stat_reg =
-+ readl_relaxed(&mhuv2->reg.recv->CHCOMB_INT_ST[reg_idx]);
-+ set_bit_index = __find_set_bit(stat_reg);
-+ if (set_bit_index == -1) {
-+ ch_idx += MHUV2_STAT_BITS;
-+ } else {
-+ ch_idx += set_bit_index;
-+ break;
-+ }
-+ }
-+ return (ch_idx >= (MHUV2_CMB_INT_ST_REG_CNT * MHUV2_STAT_BITS) ?
-+ MHUV2_CH_UNKNOWN :
-+ ch_idx);
-+}
-+
-+/* ================ Single word transport protocol operations =============== */
-+static inline int mhuv20_get_non_zero_ch_idx(struct arm_mhuv2 *mhuv2)
-+{
-+ /* Locate a channel window with a non-zero STAT register */
-+ int ch_idx;
-+ int ch = MHUV2_CH_UNKNOWN;
-+
-+ for (ch_idx = 0;
-+ ch_idx < readl_relaxed_bitfield(&mhuv2->reg.recv->MHU_CFG, NUM_CH);
-+ ch_idx++) {
-+ if (readl_relaxed(&mhuv2->reg.recv->channel[ch_idx].STAT)) {
-+ ch = ch_idx;
-+ break;
-+ }
-+ }
-+ return ch;
-+}
-+
-+static inline int mhuv2_get_non_zero_ch_idx(struct arm_mhuv2 *mhuv2)
-+{
-+ /* Identify index of channel window containing non-zero data */
-+ switch (readl_relaxed_bitfield(&mhuv2->reg.recv->AIDR,
-+ ARCH_MINOR_REV)) {
-+ case 1:
-+ return mhuv2_combint_idx(mhuv2);
-+ default:
-+ return mhuv20_get_non_zero_ch_idx(mhuv2);
-+ }
-+}
-+
-+static inline int mhuv2_read_data_single_word(struct arm_mhuv2 *mhuv2,
-+ struct mbox_chan *chan,
-+ struct arm_mbox_msg *msg)
-+{
-+ const u32 ch_idx = mhuv2_chan_idx(chan);
-+
-+ msg->data = kzalloc(MHUV2_STAT_BYTES, GFP_KERNEL);
-+ if (!msg->data)
-+ return -ENOMEM;
-+
-+ *(mhuv2_stat_reg_t *)msg->data =
-+ readl_relaxed(&mhuv2->reg.recv->channel[ch_idx].STAT);
-+ msg->len = MHUV2_STAT_BYTES;
-+ return 0;
-+}
-+
-+static inline int mhuv2_clear_data_single_word(struct arm_mhuv2 *mhuv2,
-+ struct mbox_chan *chan,
-+ struct arm_mbox_msg *msg)
-+{
-+ const u32 ch_idx = mhuv2_chan_idx(chan);
-+
-+ writel_relaxed(readl_relaxed(&mhuv2->reg.recv->channel[ch_idx].STAT),
-+ &mhuv2->reg.recv->channel[ch_idx].STAT_CLEAR);
-+ return 0;
-+}
-+
-+static inline int mhuv2_send_data_single_word(struct arm_mhuv2 *mhuv2,
-+ struct mbox_chan *chan,
-+ const struct arm_mbox_msg *msg)
-+{
-+ const u32 ch_idx = mhuv2_chan_idx(chan);
-+ int bytes_left = msg->len;
-+ char *data = msg->data;
-+
-+ if (ch_idx >= readl_relaxed_bitfield(&mhuv2->reg.recv->MHU_CFG, NUM_CH))
-+ return -ENODEV;
-+
-+ while (bytes_left > 0) {
-+ mhuv2_stat_reg_t word = *(mhuv2_stat_reg_t *)(data);
-+
-+ if (bytes_left < MHUV2_STAT_BYTES)
-+ word &= LSB_MASK(bytes_left * __CHAR_BIT__);
-+
-+ if (!word) {
-+ dev_err(mhuv2->dev,
-+ "Data transmitted in single-word mode must be non-zero\n");
-+ return -EINVAL;
-+ }
-+ writel_relaxed(word,
-+ &mhuv2->reg.send->channel[ch_idx].STAT_SET);
-+ while (readl_relaxed(&mhuv2->reg.send->channel[ch_idx].STAT))
-+ continue;
-+ bytes_left -= MHUV2_STAT_BYTES;
-+ data += MHUV2_STAT_BYTES;
-+ }
-+
-+ return 0;
-+}
-+
-+static inline int mhuv2_last_tx_done_single_word(struct arm_mhuv2 *mhuv2,
-+ struct mbox_chan *chan)
-+{
-+ const u32 ch_idx = mhuv2_chan_idx(chan);
-+
-+ return readl_relaxed(&mhuv2->reg.send->channel[ch_idx].STAT) == 0;
-+}
-+
-+static inline int mhuv2_setup_single_word(struct arm_mhuv2 *mhuv2)
-+{
-+ int i;
-+ const u32 channel_windows =
-+ readl_relaxed_bitfield(mhuv2->frame == RECEIVER_FRAME ?
-+ &mhuv2->reg.recv->MHU_CFG :
-+ &mhuv2->reg.send->MHU_CFG,
-+ NUM_CH);
-+
-+ mhuv2->mbox.num_chans = channel_windows;
-+ mhuv2->mbox.chans =
-+ devm_kzalloc(mhuv2->dev,
-+ mhuv2->mbox.num_chans * sizeof(struct mbox_chan),
-+ GFP_KERNEL);
-+
-+ for (i = 0; i < mhuv2->mbox.num_chans; i++) {
-+ mhuv2->mbox.chans[i].con_priv =
-+ devm_kzalloc(mhuv2->dev,
-+ sizeof(struct arm_mhuv2_mbox_chan_priv),
-+ GFP_KERNEL);
-+ mhuv2_chan_idx(&mhuv2->mbox.chans[i]) = i;
-+ }
-+
-+ if (mhuv2->frame == RECEIVER_FRAME) {
-+ /* Ensure all status registers are unmasked */
-+ for (i = 0; i < channel_windows; i++) {
-+ writel_relaxed(0x0,
-+ &mhuv2->reg.recv->channel[i].MASK_SET);
-+ }
-+ }
-+
-+ return 0;
-+}
-+
-+static inline struct mbox_chan *
-+ mhuv2_get_active_mbox_chan_single_word(struct arm_mhuv2 *mhuv2)
-+{
-+ const u32 ch_idx = mhuv2_get_non_zero_ch_idx(mhuv2);
-+
-+ if (ch_idx >= mhuv2->mbox.num_chans) {
-+ dev_err(mhuv2->dev,
-+ "Invalid active channel in single word mode\n");
-+ return ERR_PTR(-EINVAL);
-+ }
-+ return &mhuv2->mbox.chans[ch_idx];
-+}
-+
-+static const struct mhuv2_ops mhuv2_single_word_ops = {
-+ .read_data = mhuv2_read_data_single_word,
-+ .clear_data = mhuv2_clear_data_single_word,
-+ .send_data = mhuv2_send_data_single_word,
-+ .setup = mhuv2_setup_single_word,
-+ .last_tx_done = mhuv2_last_tx_done_single_word,
-+ .get_active_mbox_chan = mhuv2_get_active_mbox_chan_single_word,
-+};
-+/* ========================================================================== */
-+
-+/*
-+ * MHUv2 receiver interrupt service routine
-+ *
-+ * This routine will be called whenever a reception interrupt is raised on the
-+ * MHU device. Given that an MHU device may manage multiple mailboxes, it is
-+ * up to the protocol-specific operations to determine:
-+ * - What is the active mailbox channel
-+ * - Read the data within the MHU corresponding to the channel
-+ * - Clear the data within the MHU corresponding to the channel
-+ *
-+ * These operations must also ensure to not overwrite any data which may belong
-+ * to a different mailbox channel. For instance, if data is received in two
-+ * channel windows in single-word mode, the ISR will read and clear the data
-+ * from one of these channel windows within a pass. This will result in a status
-+ * register being non-zero upon returning from this routine, which in turn
-+ * will keep the interrupt asserted for a second round.
-+ */
-+static irqreturn_t mhuv2_rx_interrupt(int irq, void *data)
-+{
-+ struct arm_mbox_msg msg;
-+ int status;
-+ struct arm_mhuv2 *mhuv2 = data;
-+ struct mbox_chan *chan = mhuv2->ops->get_active_mbox_chan(mhuv2);
-+
-+ msg.data = NULL;
-+ msg.len = 0;
-+
-+ status = mhuv2->ops->read_data(mhuv2, chan, &msg);
-+ if (status != 0)
-+ goto rx_exit;
-+
-+ if (!chan->cl) {
-+ dev_warn(
-+ mhuv2->dev,
-+ "Warning: Received data on channel not currently attached to "
-+ "a mailbox client\n");
-+ } else {
-+ mbox_chan_received_data(chan, (void *)&msg);
-+ }
-+
-+ status = mhuv2->ops->clear_data(mhuv2, chan, &msg);
-+
-+rx_exit:
-+ kfree(msg.data);
-+
-+ return status == 0 ? IRQ_HANDLED : IRQ_NONE;
-+}
-+
-+static bool mhuv2_last_tx_done(struct mbox_chan *chan)
-+{
-+ struct arm_mhuv2 *mhuv2 = mhu2_from_mbox_chan(chan);
-+
-+ return mhuv2->ops->last_tx_done(mhuv2, chan);
-+}
-+
-+static int mhuv2_send_data(struct mbox_chan *chan, void *data)
-+{
-+ struct arm_mhuv2 *mhuv2 = mhu2_from_mbox_chan(chan);
-+ struct arm_mbox_msg *msg = data;
-+ int ret;
-+
-+ if (!mhuv2->ops->last_tx_done(mhuv2, chan))
-+ return -EBUSY;
-+
-+ ret = mhuv2->ops->send_data(mhuv2, chan, msg);
-+ return ret;
-+}
-+
-+static int mhuv2_startup(struct mbox_chan *chan)
-+{
-+ struct arm_mhuv2 *mhuv2 = mhu2_from_mbox_ctrl(chan->mbox);
-+
-+ writel_relaxed(0x1, &mhuv2->reg.send->ACCESS_REQUEST);
-+ while (!readl_relaxed(&mhuv2->reg.send->ACCESS_READY))
-+ continue;
-+
-+ return 0;
-+}
-+
-+static void mhuv2_shutdown(struct mbox_chan *chan)
-+{
-+ struct arm_mhuv2 *mhuv2 = mhu2_from_mbox_ctrl(chan->mbox);
-+
-+ writel_relaxed(0x0, &mhuv2->reg.send->ACCESS_REQUEST);
-+}
-+
-+static int mhuv2_recv_startup(struct mbox_chan *chan)
-+{
-+ return 0;
-+}
-+
-+static void mhuv2_recv_shutdown(struct mbox_chan *chan)
-+{
-+}
-+
-+static int mhuv2_recv_send_data(struct mbox_chan *chan, void *data)
-+{
-+ dev_err(chan->mbox->dev,
-+ "Trying to transmit on a receiver MHU frame\n");
-+ return -EIO;
-+}
-+
-+static bool mhuv2_recv_last_tx_done(struct mbox_chan *chan)
-+{
-+ dev_err(chan->mbox->dev, "Trying to Tx poll on a receiver MHU frame\n");
-+ return true;
-+}
-+
-+static const struct mbox_chan_ops mhuv2_receiver_ops = {
-+ .send_data = mhuv2_recv_send_data,
-+ .startup = mhuv2_recv_startup,
-+ .shutdown = mhuv2_recv_shutdown,
-+ .last_tx_done = mhuv2_recv_last_tx_done,
-+};
-+
-+static const struct mbox_chan_ops mhuv2_sender_ops = {
-+ .send_data = mhuv2_send_data,
-+ .startup = mhuv2_startup,
-+ .shutdown = mhuv2_shutdown,
-+ .last_tx_done = mhuv2_last_tx_done,
-+};
-+
-+static struct mbox_chan *mhuv2_mbox_of_xlate(struct mbox_controller *ctrl,
-+ const struct of_phandle_args *pa)
-+{
-+ struct mbox_chan *chan;
-+
-+ if (pa->args_count != 1)
-+ return ERR_PTR(-EINVAL);
-+
-+ if (pa->args[0] >= ctrl->num_chans)
-+ return ERR_PTR(-ENOENT);
-+
-+ chan = &ctrl->chans[pa->args[0]];
-+ return chan;
-+}
-+
-+static int mhuv2_probe(struct amba_device *adev, const struct amba_id *id)
-+{
-+ int err;
-+ struct device *dev = &adev->dev;
-+ const struct device_node *np = dev->of_node;
-+ struct arm_mhuv2 *mhuv2;
-+ const char *mhuv2_protocol_str;
-+
-+ /* Allocate memory for device */
-+ mhuv2 = devm_kzalloc(dev, sizeof(*mhuv2), GFP_KERNEL);
-+ if (!mhuv2)
-+ return -ENOMEM;
-+
-+ mhuv2->dev = dev;
-+
-+ /* Assign transport protocol-specific operations */
-+ err = of_property_read_string(np, "mhu-protocol", &mhuv2_protocol_str);
-+
-+ if (err) {
-+ dev_err(dev,
-+ "Probe failed: no transport protocol specified\n");
-+ return -ENODEV;
-+ } else if (strcmp(mhuv2_protocol_str,
-+ mhuv2_protocol_dt_identifiers[SINGLE_WORD]) == 0) {
-+ mhuv2->ops = &mhuv2_single_word_ops;
-+ } else {
-+ dev_err(dev,
-+ "Probe failed: '%s' is not a valid transport protocol specifier\n",
-+ mhuv2_protocol_str);
-+ return -ENODEV;
-+ }
-+
-+ /* Get MHU type specific properties from device tree */
-+ if (adev->irq[0]) {
-+ mhuv2->frame = RECEIVER_FRAME;
-+ mhuv2->reg.recv = (struct mhu2_recv_frame_reg *)of_iomap(
-+ (struct device_node *)np, 0);
-+ if (!mhuv2->reg.recv)
-+ goto io_fail;
-+ mhuv2->irq = adev->irq[0];
-+ } else {
-+ mhuv2->frame = SENDER_FRAME;
-+ mhuv2->reg.send = (struct mhu2_send_frame_reg *)of_iomap(
-+ (struct device_node *)np, 0);
-+ if (!mhuv2->reg.send)
-+ goto io_fail;
-+ }
-+
-+ /* Mailbox controller setup */
-+ mhuv2->mbox.dev = dev;
-+ mhuv2->mbox.txdone_irq = false;
-+ mhuv2->mbox.txdone_poll = true;
-+ mhuv2->mbox.txpoll_period = 1;
-+ mhuv2->mbox.of_xlate = mhuv2_mbox_of_xlate;
-+ mhuv2->mbox.ops = mhuv2->frame == SENDER_FRAME ? &mhuv2_sender_ops :
-+ &mhuv2_receiver_ops;
-+ /*
-+ * Transport protocol specific setup
-+ * Setup function _must_ allocate mailbox channels according to the
-+ * number of channels provided in the given transport protocol mode.
-+ */
-+ err = mhuv2->ops->setup(mhuv2);
-+ if (err)
-+ return err;
-+
-+ /* Request an interrupt if this is a receiver frame */
-+ if (mhuv2->frame == RECEIVER_FRAME) {
-+ err = devm_request_threaded_irq(dev, adev->irq[0], NULL,
-+ mhuv2_rx_interrupt, IRQF_ONESHOT, "mhuv2_link", mhuv2);
-+ if (err) {
-+ dev_err(dev, "unable to acquire IRQ %d\n", mhuv2->irq);
-+ return err;
-+ }
-+ /*
-+ * For minor version 1 and forward, the combined interrupt of
-+ * the receiver frame must be explicitly enabled during startup.
-+ */
-+ if (readl_relaxed_bitfield(&mhuv2->reg.recv->AIDR,
-+ ARCH_MINOR_REV) > 0) {
-+ writel_relaxed_bitfield(1, &mhuv2->reg.recv->INT_EN,
-+ CHCOMB);
-+ }
-+ }
-+
-+ amba_set_drvdata(adev, mhuv2);
-+
-+ err = devm_mbox_controller_register(dev, &mhuv2->mbox);
-+ if (err) {
-+ dev_err(dev, "failed to register ARM MHUv2 driver %d\n", err);
-+ iounmap(mhuv2->frame == RECEIVER_FRAME ? mhuv2->reg.recv :
-+ mhuv2->reg.send);
-+ return err;
-+ }
-+
-+ dev_info(dev, "ARM MHUv2 %s frame (%s) Mailbox driver registered\n",
-+ mhuv2_frame_dt_identifiers[mhuv2->frame],
-+ mhuv2_protocol_str);
-+
-+ return 0;
-+
-+io_fail:
-+ dev_err(dev, "Probe failed: failed to map '%s' frame\n",
-+ mhuv2_frame_dt_identifiers[mhuv2->frame]);
-+ iounmap(mhuv2->frame == RECEIVER_FRAME ? mhuv2->reg.recv :
-+ mhuv2->reg.send);
-+ return -ENOMEM;
-+}
-+
-+static int mhuv2_remove(struct amba_device *adev)
-+{
-+ return 0;
-+}
-+
-+static struct amba_id mhuv2_ids[] = {
-+ {
-+ .id = 0x4b0d1,
-+ .mask = 0xfffff,
-+ },
-+ {
-+ .id = 0xbb0d1,
-+ .mask = 0xfffff,
-+ },
-+ { 0, 0 },
-+};
-+MODULE_DEVICE_TABLE(amba, mhuv2_ids);
-+
-+static struct amba_driver arm_mhuv2_driver = {
-+ .drv = {
-+ .name = "mhuv2",
-+ },
-+ .id_table = mhuv2_ids,
-+ .probe = mhuv2_probe,
-+ .remove = mhuv2_remove,
-+};
-+module_amba_driver(arm_mhuv2_driver);
-+
-+MODULE_LICENSE("GPL v2");
-+MODULE_DESCRIPTION("ARM MHUv2 Driver");
-+MODULE_AUTHOR("Morten Borup Petersen <morten.petersen@arm.com>");
-diff --git a/include/linux/mailbox/arm-mbox-message.h b/include/linux/mailbox/arm-mbox-message.h
-new file mode 100644
-index 000000000000..112b4f927c1a
---- /dev/null
-+++ b/include/linux/mailbox/arm-mbox-message.h
-@@ -0,0 +1,37 @@
-+// SPDX-License-Identifier: GPL-2.0
-+/*
-+ * Arm Mailbox Message
-+ *
-+ * The Arm mailbox message structure is used to pass data- and length
-+ * information between a mailbox client and mailbox controller, through the
-+ * provided void* of the common mailbox frameworks send- and receive APIs.
-+ *
-+ * This will be utilized when a mailbox controller is able to transmit
-+ * more than a single word within a transmission, allowing the controller
-+ * to fully utilize its available resources.
-+ * No message protocol is enforced through this structure - a utilizing mailbox
-+ * client driver shall implement its own message protocol, which may then be
-+ * transmitted through an arm_mbox_msg.
-+ *
-+ * Given a message protocol of size A and an arm_mbox_msg containing data of
-+ * length B, a mailbox channel may callback with B < A. In this case, the
-+ * message protocol driver must implement a state machine which allows for
-+ * multiple callbacks that provides parts of a full message of size A. This
-+ * state machine must account for, that the length of the arm_mbox_msg received
-+ * may vary between callbacks based on the underlying hardware as well as the
-+ * transmitted data.
-+ *
-+ * Copyright (C) 2019 Arm Ltd.
-+ */
-+
-+#ifndef _LINUX_ARM_MBOX_MESSAGE_H_
-+#define _LINUX_ARM_MBOX_MESSAGE_H_
-+
-+#include <linux/types.h>
-+
-+struct arm_mbox_msg {
-+ void *data;
-+ size_t len;
-+};
-+
-+#endif /* _LINUX_ARM_MBOX_MESSAGE_H_ */
---
-2.17.1
-
diff --git a/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.4/tc0/0005-mailbox-arm_mhuv2-add-doorbell-transport-protocol-op.patch b/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.4/tc0/0005-mailbox-arm_mhuv2-add-doorbell-transport-protocol-op.patch
deleted file mode 100644
index a548d49..0000000
--- a/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.4/tc0/0005-mailbox-arm_mhuv2-add-doorbell-transport-protocol-op.patch
+++ /dev/null
@@ -1,156 +0,0 @@
-From 515a936531a25a0c48a97efe3828962ed8d781dd Mon Sep 17 00:00:00 2001
-From: Usama Arif <usama.arif@arm.com>
-Date: Wed, 19 Jun 2019 16:55:20 +0100
-Subject: [PATCH 5/9] mailbox: arm_mhuv2: add doorbell transport protocol
- operations
-
-In doorbell mode, the mailbox controller will provide a mailbox for each
-flag bit available in the combined number of channel windows available
-within the MHU device.
-
-When in doorbell mode, the MHU should be used solely as an interrupt
-generating mechanism. If data is to be transmitted, this must be done
-out-band, ie. through shared memory, by a driving utilizing the mailbox
-for interrupt generation.
-
-Change-Id: I8410b21471743c0b624c873388f9629ea0863789
-Signed-off-by: Usama Arif <usama.arif@arm.com>
-Signed-off-by: Morten Borup Petersen <morten.petersen@arm.com>
-Signed-off-by: Tushar Khandelwal <tushar.khandelwal@arm.com>
-Cc:Jassi Brar <jassisinghbrar@gmail.com
-Cc: devicetree@vger.kernel.org
-
-Upstream-Status: Denied [https://lkml.org/lkml/2019/7/17/615]
----
- drivers/mailbox/arm_mhu_v2.c | 108 +++++++++++++++++++++++++++++++++++
- 1 file changed, 108 insertions(+)
-
-diff --git a/drivers/mailbox/arm_mhu_v2.c b/drivers/mailbox/arm_mhu_v2.c
-index d809076eb47b..efde7a71a3f7 100644
---- a/drivers/mailbox/arm_mhu_v2.c
-+++ b/drivers/mailbox/arm_mhu_v2.c
-@@ -429,6 +429,111 @@ static const struct mhuv2_ops mhuv2_single_word_ops = {
- };
- /* ========================================================================== */
-
-+/* =================== Doorbell transport protocol operations =============== */
-+
-+static inline int mhuv2_read_data_doorbell(struct arm_mhuv2 *mhuv2,
-+ struct mbox_chan *chan,
-+ struct arm_mbox_msg *msg)
-+{
-+ return 0;
-+}
-+
-+static inline int mhuv2_clear_data_doorbell(struct arm_mhuv2 *mhuv2,
-+ struct mbox_chan *chan,
-+ struct arm_mbox_msg *msg)
-+{
-+ const u32 ch_mbox_idx = mhuv2_chan_idx(chan);
-+ const u32 ch_window_idx = ch_mbox_idx / MHUV2_STAT_BITS;
-+ const u32 ch_window_reg_idx = ch_mbox_idx % MHUV2_STAT_BITS;
-+
-+ writel_relaxed(BIT(ch_window_reg_idx),
-+ &mhuv2->reg.recv->channel[ch_window_idx].STAT_CLEAR);
-+ return 0;
-+}
-+
-+static inline int mhuv2_send_data_doorbell(struct arm_mhuv2 *mhuv2,
-+ struct mbox_chan *chan,
-+ const struct arm_mbox_msg *msg)
-+{
-+ const u32 ch_mbox_idx = mhuv2_chan_idx(chan);
-+ const u32 ch_window_idx = ch_mbox_idx / MHUV2_STAT_BITS;
-+ const u32 ch_window_reg_idx = ch_mbox_idx % MHUV2_STAT_BITS;
-+
-+ writel_relaxed(
-+ readl_relaxed(&mhuv2->reg.send->channel[ch_window_idx].STAT) |
-+ BIT(ch_window_reg_idx),
-+ &mhuv2->reg.send->channel[ch_window_idx].STAT_SET);
-+ return 0;
-+}
-+
-+static inline int mhuv2_last_tx_done_doorbell(struct arm_mhuv2 *mhuv2,
-+ struct mbox_chan *chan)
-+{
-+ const u32 ch_mbox_idx = mhuv2_chan_idx(chan);
-+ const u32 ch_window_idx = ch_mbox_idx / MHUV2_STAT_BITS;
-+ const u32 ch_window_reg_idx = ch_mbox_idx % MHUV2_STAT_BITS;
-+
-+ return (readl_relaxed(&mhuv2->reg.send->channel[ch_window_idx].STAT) &
-+ BIT(ch_window_reg_idx)) == 0;
-+}
-+
-+static inline int mhuv2_setup_doorbell(struct arm_mhuv2 *mhuv2)
-+{
-+ int i;
-+ const u32 channel_windows =
-+ readl_relaxed_bitfield(mhuv2->frame == RECEIVER_FRAME ?
-+ &mhuv2->reg.recv->MHU_CFG :
-+ &mhuv2->reg.send->MHU_CFG,
-+ NUM_CH);
-+
-+ mhuv2->mbox.num_chans = MHUV2_STAT_BITS * channel_windows;
-+ mhuv2->mbox.chans =
-+ devm_kzalloc(mhuv2->dev,
-+ mhuv2->mbox.num_chans * sizeof(struct mbox_chan),
-+ GFP_KERNEL);
-+
-+ for (i = 0; i < mhuv2->mbox.num_chans; i++) {
-+ mhuv2->mbox.chans[i].con_priv =
-+ devm_kzalloc(mhuv2->dev,
-+ sizeof(struct arm_mhuv2_mbox_chan_priv),
-+ GFP_KERNEL);
-+ mhuv2_chan_idx(&mhuv2->mbox.chans[i]) = i;
-+ }
-+
-+ if (mhuv2->frame == RECEIVER_FRAME) {
-+ /* Ensure all status registers are unmasked */
-+ for (i = 0; i < channel_windows; i++) {
-+ writel_relaxed(0x0,
-+ &mhuv2->reg.recv->channel[i].MASK_SET);
-+ }
-+ }
-+
-+ return 0;
-+}
-+
-+static inline struct mbox_chan *
-+ mhuv2_get_active_mbox_chan_doorbell(struct arm_mhuv2 *mhuv2)
-+{
-+ const u32 ch_window_idx = mhuv2_get_non_zero_ch_idx(mhuv2);
-+ const u32 ch_window_reg_idx = __find_set_bit(
-+ readl_relaxed(&mhuv2->reg.recv->channel[ch_window_idx].STAT));
-+ if (ch_window_reg_idx == -1)
-+ return ERR_PTR(-EIO);
-+
-+ return &mhuv2->mbox.chans[ch_window_reg_idx +
-+ ch_window_idx * MHUV2_STAT_BITS];
-+}
-+
-+static const struct mhuv2_ops mhuv2_doorbell_ops = {
-+ .read_data = mhuv2_read_data_doorbell,
-+ .clear_data = mhuv2_clear_data_doorbell,
-+ .send_data = mhuv2_send_data_doorbell,
-+ .setup = mhuv2_setup_doorbell,
-+ .last_tx_done = mhuv2_last_tx_done_doorbell,
-+ .get_active_mbox_chan = mhuv2_get_active_mbox_chan_doorbell,
-+};
-+/* ========================================================================== */
-+
- /*
- * MHUv2 receiver interrupt service routine
- *
-@@ -591,6 +696,9 @@ static int mhuv2_probe(struct amba_device *adev, const struct amba_id *id)
- } else if (strcmp(mhuv2_protocol_str,
- mhuv2_protocol_dt_identifiers[SINGLE_WORD]) == 0) {
- mhuv2->ops = &mhuv2_single_word_ops;
-+ } else if (strcmp(mhuv2_protocol_str,
-+ mhuv2_protocol_dt_identifiers[DOORBELL]) == 0) {
-+ mhuv2->ops = &mhuv2_doorbell_ops;
- } else {
- dev_err(dev,
- "Probe failed: '%s' is not a valid transport protocol specifier\n",
---
-2.17.1
-
diff --git a/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.4/tc0/0006-mailbox-arm_mhuv2-add-multi-word-transport-protocol-.patch b/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.4/tc0/0006-mailbox-arm_mhuv2-add-multi-word-transport-protocol-.patch
deleted file mode 100644
index 9fd327f..0000000
--- a/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.4/tc0/0006-mailbox-arm_mhuv2-add-multi-word-transport-protocol-.patch
+++ /dev/null
@@ -1,271 +0,0 @@
-From 31140984e2ead5d56b072d0fed0b5f18a1e7e825 Mon Sep 17 00:00:00 2001
-From: Usama Arif <usama.arif@arm.com>
-Date: Wed, 19 Jun 2019 17:00:31 +0100
-Subject: [PATCH 6/9] mailbox: arm_mhuv2: add multi word transport protocol
- operations
-
-When in multi-word mode, the mailbox controller will provide a single
-mailbox. It is required that the MHU device has at least 2 channel windows
-available for the MHU to function in multi-word mode.
-
-Transmitting and receiving data through the mailbox framework in
-multi-word mode is done through a struct arm_mbox_msg.
-
-Change-Id: Ibcf352d19ae3908093b20350853b16cf6a7933a2
-Signed-off-by: Usama Arif <usama.arif@arm.com>
-Signed-off-by: Morten Borup Petersen <morten.petersen@arm.com>
-Signed-off-by: Tushar Khandelwal <tushar.khandelwal@arm.com>
-Cc: jassisinghbrar@gmail.com
-Cc: devicetree@vger.kernel.org
-
-Upstream-Status: Denied [https://lkml.org/lkml/2019/7/17/615]
----
- drivers/mailbox/arm_mhu_v2.c | 225 +++++++++++++++++++++++++++++++++++
- 1 file changed, 225 insertions(+)
-
-diff --git a/drivers/mailbox/arm_mhu_v2.c b/drivers/mailbox/arm_mhu_v2.c
-index efde7a71a3f7..e73e829d4f1e 100644
---- a/drivers/mailbox/arm_mhu_v2.c
-+++ b/drivers/mailbox/arm_mhu_v2.c
-@@ -429,6 +429,228 @@ static const struct mhuv2_ops mhuv2_single_word_ops = {
- };
- /* ========================================================================== */
-
-+/* ================ Multi word transport protocol operations ================ */
-+static inline int mhuv2_read_data_multi_word(struct arm_mhuv2 *mhuv2,
-+ struct mbox_chan *chan,
-+ struct arm_mbox_msg *msg)
-+{
-+ int ch;
-+ const int channels =
-+ readl_relaxed_bitfield(&mhuv2->reg.recv->MHU_CFG, NUM_CH);
-+
-+ msg->data = kzalloc(MHUV2_STAT_BYTES * channels, GFP_KERNEL);
-+
-+ for (ch = 0; ch < channels; ch++) {
-+ /*
-+ * Messages are expected to be received in order of most
-+ * significant word to least significant word.
-+ * (see mhuv2_send_data_multi_word)
-+ */
-+ const mhuv2_stat_reg_t word =
-+ readl_relaxed(&mhuv2->reg.recv->channel[ch].STAT);
-+ ((mhuv2_stat_reg_t *)msg->data)[channels - 1 - ch] = word;
-+ }
-+
-+ msg->len = channels * MHUV2_STAT_BYTES;
-+ return 0;
-+}
-+
-+static inline int mhuv2_clear_data_multi_word(struct arm_mhuv2 *mhuv2,
-+ struct mbox_chan *chan,
-+ struct arm_mbox_msg *msg)
-+{
-+ int ch;
-+ const int channels =
-+ readl_relaxed_bitfield(&mhuv2->reg.recv->MHU_CFG, NUM_CH);
-+
-+ for (ch = 0; ch < channels; ch++) {
-+ /*
-+ * Last channel window must be cleared as the final operation.
-+ * Upon clearing the last channel window register, which is
-+ * unmasked in multi-word mode, the interrupt is deasserted.
-+ */
-+ writel_relaxed(
-+ readl_relaxed(&mhuv2->reg.recv->channel[ch].STAT),
-+ &mhuv2->reg.recv->channel[ch].STAT_CLEAR);
-+ }
-+ return 0;
-+}
-+
-+static inline int __mhuv2_mw_bytes_to_send(const int bytes_in_round,
-+ const int bytes_left)
-+{
-+ /*
-+ * Bytes to send on the current channel will always be MHUV2_STAT_BYTES
-+ * unless in the last round and
-+ * msg->len % MHUV2_STAT_BYTES != 0
-+ */
-+ if (bytes_in_round % MHUV2_STAT_BYTES != 0) {
-+ const int bts = bytes_left % MHUV2_STAT_BYTES;
-+ return bts == 0 ? MHUV2_STAT_BYTES : bts;
-+ } else {
-+ return MHUV2_STAT_BYTES;
-+ }
-+}
-+
-+static inline int mhuv2_send_data_multi_word(struct arm_mhuv2 *mhuv2,
-+ struct mbox_chan *chan,
-+ const struct arm_mbox_msg *msg)
-+{
-+ /*
-+ * Message will be transmitted from most significant to least
-+ * significant word. This is to allow for messages shorter than
-+ * $channels to still trigger the receiver interrupt which gets
-+ * activated when the last STAT register is written. As an example, a
-+ * 6-word message is to be written on a 4-channel MHU connection:
-+ * Registers marked with '*' are masked, and will not generate an
-+ * interrupt on the receiver side once written.
-+ *
-+ * uint32_t *data = [0x00000001],[0x00000002],[0x00000003],[0x00000004],
-+ * [0x00000005], [0x00000006]
-+ *
-+ * ROUND 1:
-+ * STAT reg To write Write sequence
-+ * [ STAT 3 ] <- [0x00000001] 4 <- triggers interrupt on receiver
-+ * *[ STAT 2 ] <- [0x00000002] 3
-+ * *[ STAT 1 ] <- [0x00000003] 2
-+ * *[ STAT 0 ] <- [0x00000004] 1
-+ *
-+ * data += 4 // Increment data pointer by number of STAT regs
-+ *
-+ * ROUND 2:
-+ * STAT reg To write Write sequence
-+ * [ STAT 3 ] <- [0x00000005] 2 <- triggers interrupt on receiver
-+ * *[ STAT 2 ] <- [0x00000006] 1
-+ * *[ STAT 1 ] <- [0x00000000]
-+ * *[ STAT 0 ] <- [0x00000000]
-+ */
-+ int bytes_left, bytes_to_send, i, ch_idx;
-+ const int ch_windows =
-+ readl_relaxed_bitfield(&mhuv2->reg.recv->MHU_CFG, NUM_CH);
-+ const size_t round_capacity = ch_windows * MHUV2_STAT_BYTES;
-+
-+ bytes_left = msg->len;
-+ mhuv2_stat_reg_t *data = msg->data;
-+
-+ while (bytes_left > 0) {
-+ /* Note: Each entry of this loop indicates a new ROUND */
-+ if (*(u32 *)data == 0) {
-+ dev_err(mhuv2->dev,
-+ "values in *data aligned on NUM_STAT boundaries must not be zero to ensure that receiver interrupt is triggered\n",
-+ ch_windows);
-+ return -EINVAL;
-+ }
-+
-+ const int bytes_in_round = bytes_left > round_capacity ?
-+ round_capacity :
-+ bytes_left;
-+
-+ for (i = (ch_windows - 1); i >= 0; i--) {
-+ ch_idx = ch_windows - 1 - i;
-+ /*
-+ * Check whether data should be transmitted in register
-+ * of index 'ch'.
-+ */
-+ if (bytes_in_round > (i * MHUV2_STAT_BYTES)) {
-+ mhuv2_stat_reg_t word = data[i];
-+
-+ bytes_to_send = __mhuv2_mw_bytes_to_send(
-+ bytes_in_round, bytes_left);
-+
-+ if (bytes_to_send != MHUV2_STAT_BYTES) {
-+ word &= LSB_MASK(bytes_to_send *
-+ __CHAR_BIT__);
-+ }
-+ while (readl_relaxed(
-+ &mhuv2->reg.send->channel[ch_idx]
-+ .STAT) != 0)
-+ continue;
-+
-+ writel_relaxed(
-+ word,
-+ &mhuv2->reg.send->channel[ch_idx].STAT_SET);
-+ bytes_left -= bytes_to_send;
-+ }
-+ }
-+
-+ data += ch_windows;
-+
-+ for (ch_idx = 0; ch_idx < ch_windows; ch_idx++) {
-+ while (readl_relaxed(
-+ &mhuv2->reg.send->channel[ch_idx].STAT) != 0)
-+ continue;
-+ }
-+ }
-+ return 0;
-+}
-+
-+
-+static inline int mhuv2_last_tx_done_multi_word(struct arm_mhuv2 *mhuv2,
-+ struct mbox_chan *chan)
-+{
-+ int ch_idx;
-+ bool tx_done = true;
-+
-+ for (ch_idx = 0;
-+ ch_idx < readl_relaxed_bitfield(&mhuv2->reg.send->MHU_CFG, NUM_CH);
-+ ch_idx++) {
-+ tx_done &= readl_relaxed(
-+ &mhuv2->reg.send->channel[ch_idx].STAT) == 0;
-+ }
-+ return tx_done;
-+}
-+
-+static inline int mhuv2_setup_multi_word(struct arm_mhuv2 *mhuv2)
-+{
-+ int ret, i;
-+
-+ const u32 channel_windows =
-+ readl_relaxed_bitfield(mhuv2->frame == RECEIVER_FRAME ?
-+ &mhuv2->reg.recv->MHU_CFG :
-+ &mhuv2->reg.send->MHU_CFG,
-+ NUM_CH);
-+ if (channel_windows < 2) {
-+ dev_err(mhuv2->dev,
-+ "Error: at least 2 MHU channel windows are required for using the multi-word transfer protocol");
-+ return -ENODEV;
-+ }
-+
-+ if (mhuv2->frame == RECEIVER_FRAME) {
-+ /*
-+ * The multi-word transport protocol mandates that all but
-+ * the last status register must be masked.
-+ */
-+ for (i = 0; i < (channel_windows - 1); i++) {
-+ writel_relaxed(-1,
-+ &mhuv2->reg.recv->channel[i].MASK_SET);
-+ }
-+ }
-+
-+ mhuv2->mbox.num_chans = 1;
-+ mhuv2->mbox.chans =
-+ devm_kzalloc(mhuv2->dev,
-+ mhuv2->mbox.num_chans * sizeof(struct mbox_chan),
-+ GFP_KERNEL);
-+
-+ return 0;
-+}
-+
-+static inline struct mbox_chan *
-+ mhuv2_get_active_mbox_chan_multi_word(struct arm_mhuv2 *mhuv2)
-+{
-+ return &mhuv2->mbox.chans[0];
-+}
-+
-+static const struct mhuv2_ops mhuv2_multi_word_ops = {
-+ .read_data = mhuv2_read_data_multi_word,
-+ .clear_data = mhuv2_clear_data_multi_word,
-+ .send_data = mhuv2_send_data_multi_word,
-+ .setup = mhuv2_setup_multi_word,
-+ .last_tx_done = mhuv2_last_tx_done_multi_word,
-+ .get_active_mbox_chan = mhuv2_get_active_mbox_chan_multi_word,
-+};
-+/* ========================================================================== */
-+
- /* =================== Doorbell transport protocol operations =============== */
-
- static inline int mhuv2_read_data_doorbell(struct arm_mhuv2 *mhuv2,
-@@ -696,6 +918,9 @@ static int mhuv2_probe(struct amba_device *adev, const struct amba_id *id)
- } else if (strcmp(mhuv2_protocol_str,
- mhuv2_protocol_dt_identifiers[SINGLE_WORD]) == 0) {
- mhuv2->ops = &mhuv2_single_word_ops;
-+ } else if (strcmp(mhuv2_protocol_str,
-+ mhuv2_protocol_dt_identifiers[MULTI_WORD]) == 0) {
-+ mhuv2->ops = &mhuv2_multi_word_ops;
- } else if (strcmp(mhuv2_protocol_str,
- mhuv2_protocol_dt_identifiers[DOORBELL]) == 0) {
- mhuv2->ops = &mhuv2_doorbell_ops;
---
-2.17.1
-
diff --git a/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.4/tc0/0007-firmware-arm_scmi-Add-fast_switch_possible-api.patch b/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.4/tc0/0007-firmware-arm_scmi-Add-fast_switch_possible-api.patch
deleted file mode 100644
index 9369d78..0000000
--- a/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.4/tc0/0007-firmware-arm_scmi-Add-fast_switch_possible-api.patch
+++ /dev/null
@@ -1,67 +0,0 @@
-From 68ce2dfe4c6f3806001fb8d682d6e99a9580dc2a Mon Sep 17 00:00:00 2001
-From: Usama Arif <usama.arif@arm.com>
-Date: Wed, 24 Jun 2020 11:16:01 +0100
-Subject: [PATCH 7/9] firmware: arm_scmi: Add fast_switch_possible() api
-
-Add a new fast_switch_possible interface to the existing
-perf_ops api to export the information of whether or not
-fast_switch is possible in this driver.
-
-This can be used by the CPUFreq driver and framework to
-choose proper mechanism for frequency change.
-
-Suggested-by: Lukasz Luba <lukasz.luba@arm.com>
-Signed-off-by: Nicola Mazzucato <nicola.mazzucato@arm.com>
-
-Upstream-Status: Backport [https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/drivers/firmware/arm_scmi?id=1909872ff20fc378ec6a44ea1a2b2966d834e504]
----
- drivers/firmware/arm_scmi/perf.c | 12 ++++++++++++
- include/linux/scmi_protocol.h | 2 ++
- 2 files changed, 14 insertions(+)
-
-diff --git a/drivers/firmware/arm_scmi/perf.c b/drivers/firmware/arm_scmi/perf.c
-index 601af4edad5e..c9350bb2ba1f 100644
---- a/drivers/firmware/arm_scmi/perf.c
-+++ b/drivers/firmware/arm_scmi/perf.c
-@@ -691,6 +691,17 @@ static int scmi_dvfs_est_power_get(const struct scmi_handle *handle, u32 domain,
- return ret;
- }
-
-+static bool scmi_fast_switch_possible(const struct scmi_handle *handle,
-+ struct device *dev)
-+{
-+ struct perf_dom_info *dom;
-+ struct scmi_perf_info *pi = handle->perf_priv;
-+
-+ dom = pi->dom_info + scmi_dev_domain_id(dev);
-+
-+ return (dom->fc_info && dom->fc_info->level_set_addr);
-+}
-+
- static struct scmi_perf_ops perf_ops = {
- .limits_set = scmi_perf_limits_set,
- .limits_get = scmi_perf_limits_get,
-@@ -702,6 +713,7 @@ static struct scmi_perf_ops perf_ops = {
- .freq_set = scmi_dvfs_freq_set,
- .freq_get = scmi_dvfs_freq_get,
- .est_power_get = scmi_dvfs_est_power_get,
-+ .fast_switch_possible = scmi_fast_switch_possible,
- };
-
- static int scmi_perf_protocol_init(struct scmi_handle *handle)
-diff --git a/include/linux/scmi_protocol.h b/include/linux/scmi_protocol.h
-index 881fea47c83d..b1f4a88219c5 100644
---- a/include/linux/scmi_protocol.h
-+++ b/include/linux/scmi_protocol.h
-@@ -114,6 +114,8 @@ struct scmi_perf_ops {
- unsigned long *rate, bool poll);
- int (*est_power_get)(const struct scmi_handle *handle, u32 domain,
- unsigned long *rate, unsigned long *power);
-+ bool (*fast_switch_possible)(const struct scmi_handle *handle,
-+ struct device *dev);
- };
-
- /**
---
-2.17.1
-
diff --git a/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.4/tc0/0008-cpufreq-arm_scmi-Set-fast_switch_possible-conditiona.patch b/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.4/tc0/0008-cpufreq-arm_scmi-Set-fast_switch_possible-conditiona.patch
deleted file mode 100644
index e392242..0000000
--- a/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.4/tc0/0008-cpufreq-arm_scmi-Set-fast_switch_possible-conditiona.patch
+++ /dev/null
@@ -1,42 +0,0 @@
-From 47300d8385801913709eda5fd237d54f51477546 Mon Sep 17 00:00:00 2001
-From: Usama Arif <usama.arif@arm.com>
-Date: Wed, 24 Jun 2020 11:25:02 +0100
-Subject: [PATCH 8/9] cpufreq: arm_scmi: Set fast_switch_possible conditionally
-
-Currently the fast_switch_possible flag is set unconditionally
-to true. Based on this, schedutil does not create a
-thread for frequency switching and would always use the
-fast switch path.
-However, if the platform does not support frequency
-fast switch, this may cause the governor to attempt an
-operation that is not supported by the platform.
-
-Fix this by correctly retrieve the fast_switch capability
-from the driver which knows if the platform can support
-this feature.
-
-Suggested-by: Lukasz Luba <lukasz.luba@arm.com>
-Signed-off-by: Nicola Mazzucato <nicola.mazzucato@arm.com>
-
-Upstream-Status: Backport [https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/drivers/cpufreq?id=fb3571276b970cbe7b45ecdc762e92f3f305ad6d]
----
- drivers/cpufreq/scmi-cpufreq.c | 3 ++-
- 1 file changed, 2 insertions(+), 1 deletion(-)
-
-diff --git a/drivers/cpufreq/scmi-cpufreq.c b/drivers/cpufreq/scmi-cpufreq.c
-index e6182c89df79..931fcf0ef221 100644
---- a/drivers/cpufreq/scmi-cpufreq.c
-+++ b/drivers/cpufreq/scmi-cpufreq.c
-@@ -198,7 +198,8 @@ static int scmi_cpufreq_init(struct cpufreq_policy *policy)
-
- policy->cpuinfo.transition_latency = latency;
-
-- policy->fast_switch_possible = true;
-+ policy->fast_switch_possible =
-+ handle->perf_ops->fast_switch_possible(handle, cpu_dev);
-
- em_register_perf_domain(policy->cpus, nr_opp, &em_cb);
-
---
-2.17.1
-
diff --git a/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.4/tc0/0009-driver-firmware-Initial-version-of-ffa-driver-based-.patch b/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.4/tc0/0009-driver-firmware-Initial-version-of-ffa-driver-based-.patch
deleted file mode 100644
index e5e1ff6..0000000
--- a/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.4/tc0/0009-driver-firmware-Initial-version-of-ffa-driver-based-.patch
+++ /dev/null
@@ -1,1461 +0,0 @@
-Upstream-Status: Pending [https://git.kernel.org/pub/scm/linux/kernel/git/sudeep.holla/linux.git/commit/?h=ffa_rel_proto&id=74aeede25bd737f4930e1322f5780ec1c61b9fd5]
-Signed-off-by: Arunachalam Ganapathy <arunachalam.ganapathy@arm.com>
-
-From 411f4ed69a06f213fb2abb7dbef0be5ce31ff55e Mon Sep 17 00:00:00 2001
-From: Jose Marinho <jose.marinho@arm.com>
-Date: Tue, 29 Oct 2019 09:28:55 +0000
-Subject: [PATCH] driver: firmware: Initial version of ffa driver based on
- ffa_rel_proto
-
-Initial version of ffa driver based on ffa_rel_proto [1].
-
-[1]: https://git.kernel.org/pub/scm/linux/kernel/git/sudeep.holla/linux.git/log/?h=ffa_rel_proto
-
-Squashed in:
- firmware: arm64/spci: Add initial SPCI driver
-
- Add initial SPCI driver
-
- firmware: spci: add conduit selection from DT
-
- The driver can use smc or hvc conduits depending on what is
- specified in the spci node in the DT.
-
- arm64: spci/smccc: Create smc call returning on x0 to x7
-
- The new smc call is SMCCCv1.2 compliant.
-
- arm_spci: Register Rx/Tx buffers.
-
- Registers the Rx/Tx buffers with the SPCI implementation at a higher EL.
- The buffers are restricted to 4KB in this implementation.
-
- arm_spci: Add SPCI memory sharing mechanisms.
-
- Add mem_share and mem_reclaim to the SPCI driver interface.
- These two methods allow for the basic memory sharing use-case where
- normal world shares a set of pages with secure world.
- The memory region description is in this implementation restricted to
- 4KB (i.e. it must fit in the Tx buffer of the normal world VM).
-
- spci_driver/mem_share: Add lock around TX Buffer
-
- Ensure we aquire a lock around the TX buffer when sending information to
- prevent race conditions.
-
- arm_spci: Expose SPCI_PARTITION_INFO_GET
-
- Expose the SPCI_PARTITION_INFO_GET ABI to allow querying the system for
- information about a set of partitions identified by a specified UUID.
-
- The function expects the 128bit UUID to be discovered passed via 4 32bit
- words in the format: UUID_0-UUID_1-UUID_2-UUID3 and a pointer to an
- array of `spci_partition_info` structs that will allocated and populated
- with the discovered partitions information by the SPCI driver. The
- caller is responsible for freeing this memory allocated by the SPCI
- driver.
-
- The function returns the number of the partitions found (and therefore
- the number of elements in the array) or a negative value indicating the
- error code if unsuccessful.
-
- This implementation currently disallows use of the NULL UUID.
-
- arm_spci: Implement rx_release
-
- SPCI: Move driver to directory
-
- The SPCI driver has a specific directory at drivers/firmware/spci.
-
- SPCI: multi-fragment memory share support
-
- arm_spci: use scatterlist in mem_share interface
-
- Previously an array of page* was passed in the mem_share interface.
- This commit introduces a scatterlist as partameter to mem_share function.
-
- arm_spci: Add RX_RELEASE return to spci_rx_release
-
- A Hypervisor can return SPCI_RX_RELEASE when the PVM calls
- SPCI_RX_RELEASE to signal that other VMs need to be scheduled.
-
- arm_spci: Change spci_memory_reclaim declaration
-
- Function takes an enum mem_clear_t flag to denote if memory should be
- cleared upon reclaim.
-
- arm_spci: Allow nil UUID in spci_parition_info_get
-
- Previously the nil UUID was disallowed.
-
- arm_spci: Add support for non-Tx buffer mem_share
-
- This commit introduces the buffer*, buffer_size parameters to the
- mem_share function. The buffer can be used alternatively to the Tx
- buffer. The mem_share function will populate the IPA-contiguous memory
- pointed to by buffer using the information in sg.
-
- The buffer* must be NULL is mem_share should use the Tx buffer.
- The buffer*, if non-NULL, must point to a IPA-contiguous memory region
- of size multiple of 4kiB.
-
- arm_spci: Support pause/resume in mem_share handle
-
- The Hypervisor is allowed to return SPCI_MEM_OPS_PAUSE if a mem_share
- operation is taking too long. The PVM must reply with
- SPCI_MEM_OPS_RESUME.
-
- arm_spci: Ammend debug print.
-
- arm_spci: add missing fields in mem descriptor
-
- The sender_id, vm_id fields were not properly filled in the mem_share
- function.
-
- arm_spci: mem_share selection of Tx or alloc buf
-
- This commit allows the mem_share invokation to select the tx buffer or a
- dynamically allocated buffer to be used for the transfer of the memory
- region description.
-
- if use_tx == true: the tx_lock is held until the memory region is fully
- transmitted.
-
- if use_tx == false: the tx_lock is very briefly held in the preamble
- and postamble of the mem_share procedure.
-
- arm_spci: Allow compilation for arm arch [smcccv1_2 bits]
-
- arm_spci: Allow compilation for arm arch [arm_spci bits]
-
- Implement SPCI features
-
- Currently only SPCI_Direct_Req is checked during SPCI driver
- initialisation.
-
- arm_spci: add err print when features does not report direct_req support
-
- arm_spci: refactor mem_share implementation for EAC [arm_spci bits]
-
- arm_spci: introduce support for SPCI_INTERRUPT
-
- A SP while executing in the context of a SPCI_MSG_SEND_DIRECT_REQ
- may be interrupted. In which case the scheduler must be instructed and
- be provided with the necessary information to resume the interrupted SP.
-
- arm_ffa: optee: Swap spci/SPCI for ffa/FFA. [arm_ffa bits]
-
- arm_ffa: Implement ffa_version discovery.
-
- arm_ffa: corrections to EAC support.
-
- arm_ffa: cast status return to signed for compare
-
- arm_ffa: rename 1st member of arm_smcccv1_2_return [arm-smcccv1_2.h bits]
-
- The smcccv1_2_return.func is renamed to arg0.
-
- arm_ffa: rename 1st member of arm_smcccv1_2_return [arm_ffa bits]
-
- The smcccv1_2_return.func is renamed to arg0.
-
- arm_ffa: set the default shareability to inner.
-
- Pages are shared with inner shareability attribute set in S2.
-
- arm_ffa: remove some panic calls
-
- Some panics were swaped by pr_warns and an error code return when the
- error condition being signaled is predicted by the FFA spec. The panics
- issued when an unexpected status is returned from EL2 or
- EL3 (behaviour deviating from the FFA spec) are left in the driver.
-
- arm_ffa: fix warnings and remove debug print
-
- Fixed few warnings related to unused variable and in pr_warn prints
-
- arm_ffa: correct checkpatch warnings
-
- arm_ffa.h: Split memory access permissions
-
- Split the FF-A instruction and data access permissions.
- This allows for specifying one attribute but not the other. This is
- required for lenders of memory for which must not specify the
- instruction access permission.
-
-Signed-off-by: Jose Marinho <jose.marinho@arm.com>
-Signed-off-by: Marc Bonnici <marc.bonnici@arm.com>
-Signed-off-by: Arunachalam Ganapathy <arunachalam.ganapathy@arm.com>
-Change-Id: I7bd8cf453e99498ab4df1f01092137a67116d15d
----
- arch/arm/kernel/Makefile | 1 +
- arch/arm/kernel/smcccv1_2-call.S | 58 +++
- arch/arm64/kernel/Makefile | 2 +-
- arch/arm64/kernel/smccc_v1_2-call.S | 24 +
- drivers/firmware/Kconfig | 11 +
- drivers/firmware/Makefile | 1 +
- drivers/firmware/ffa/Makefile | 6 +
- drivers/firmware/ffa/arm_ffa.c | 782 ++++++++++++++++++++++++++++
- include/linux/arm-smcccv1_2.h | 51 ++
- include/linux/arm_ffa.h | 235 +++++++++
- 10 files changed, 1170 insertions(+), 1 deletion(-)
- create mode 100644 arch/arm/kernel/smcccv1_2-call.S
- create mode 100644 arch/arm64/kernel/smccc_v1_2-call.S
- create mode 100644 drivers/firmware/ffa/Makefile
- create mode 100644 drivers/firmware/ffa/arm_ffa.c
- create mode 100644 include/linux/arm-smcccv1_2.h
- create mode 100644 include/linux/arm_ffa.h
-
-diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile
-index 8cad59465af3..5be97585d130 100644
---- a/arch/arm/kernel/Makefile
-+++ b/arch/arm/kernel/Makefile
-@@ -101,5 +101,6 @@ obj-$(CONFIG_SMP) += psci_smp.o
- endif
-
- obj-$(CONFIG_HAVE_ARM_SMCCC) += smccc-call.o
-+obj-$(CONFIG_HAVE_ARM_SMCCC) += smcccv1_2-call.o
-
- extra-y := $(head-y) vmlinux.lds
-diff --git a/arch/arm/kernel/smcccv1_2-call.S b/arch/arm/kernel/smcccv1_2-call.S
-new file mode 100644
-index 000000000000..9a577c4045a7
---- /dev/null
-+++ b/arch/arm/kernel/smcccv1_2-call.S
-@@ -0,0 +1,58 @@
-+/* SPDX-License-Identifier: GPL-2.0-only */
-+/*
-+ * Copyright (c) 2020, Linaro Limited
-+ */
-+#include <linux/linkage.h>
-+
-+#include <asm-generic/export.h>
-+#include <asm/opcodes-sec.h>
-+#include <asm/opcodes-virt.h>
-+#include <asm/unwind.h>
-+
-+ /*
-+ * Wrap c macros in asm macros to delay expansion until after the
-+ * SMCCC asm macro is expanded.
-+ */
-+ .macro SMCCC_SMC
-+ __SMC(0)
-+ .endm
-+
-+ .macro SMCCC_HVC
-+ __HVC(0)
-+ .endm
-+
-+ .macro SMCCC instr
-+UNWIND( .fnstart)
-+ mov r12, sp
-+ push {r4-r7}
-+UNWIND( .save {r4-r7})
-+ ldm r12, {r4-r7}
-+ \instr
-+ ldr r12, [sp, #(4 * 8)]
-+ stm r12, {r0-r7}
-+ pop {r4-r7}
-+ bx lr
-+UNWIND( .fnend)
-+ .endm
-+
-+/*
-+ * void smccc_smc(unsigned long a0, unsigned long a1, unsigned long a2,
-+ * unsigned long a3, unsigned long a4, unsigned long a5,
-+ * unsigned long a6, unsigned long a7, struct arm_smccc_res *res,
-+ * struct arm_smccc_quirk *quirk)
-+ */
-+ENTRY(__arm_smcccv1_2_smc)
-+ SMCCC SMCCC_SMC
-+ENDPROC(__arm_smcccv1_2_smc)
-+EXPORT_SYMBOL(__arm_smcccv1_2_smc)
-+
-+/*
-+ * void smccc_hvc(unsigned long a0, unsigned long a1, unsigned long a2,
-+ * unsigned long a3, unsigned long a4, unsigned long a5,
-+ * unsigned long a6, unsigned long a7, struct arm_smccc_res *res,
-+ * struct arm_smccc_quirk *quirk)
-+ */
-+ENTRY(__arm_smcccv1_2_hvc)
-+ SMCCC SMCCC_HVC
-+ENDPROC(__arm_smcccv1_2_hvc)
-+EXPORT_SYMBOL(__arm_smcccv1_2_hvc)
-diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile
-index b3995329d9e5..4327ef6f4f8d 100644
---- a/arch/arm64/kernel/Makefile
-+++ b/arch/arm64/kernel/Makefile
-@@ -19,7 +19,7 @@ obj-y := debug-monitors.o entry.o irq.o fpsimd.o \
- return_address.o cpuinfo.o cpu_errata.o \
- cpufeature.o alternative.o cacheinfo.o \
- smp.o smp_spin_table.o topology.o smccc-call.o \
-- syscall.o
-+ syscall.o smccc_v1_2-call.o
-
- extra-$(CONFIG_EFI) := efi-entry.o
-
-diff --git a/arch/arm64/kernel/smccc_v1_2-call.S b/arch/arm64/kernel/smccc_v1_2-call.S
-new file mode 100644
-index 000000000000..518e849409ed
---- /dev/null
-+++ b/arch/arm64/kernel/smccc_v1_2-call.S
-@@ -0,0 +1,24 @@
-+/* SPDX-License-Identifier: GPL-2.0-only */
-+/*
-+ * Copyright (C) 2019 Arm Ltd.
-+ */
-+
-+#include <linux/linkage.h>
-+
-+.macro SMC_CALL conduit
-+ \conduit #0
-+ ldr x8, [sp]
-+ stp x0, x1, [x8]
-+ stp x2, x3, [x8, #16]
-+ stp x4, x5, [x8, #32]
-+ stp x6, x7, [x8, #48]
-+ ret
-+.endm
-+
-+ENTRY(__arm_smcccv1_2_hvc)
-+ SMC_CALL hvc
-+ENDPROC(__arm_smcccv1_2_hvc)
-+
-+ENTRY(__arm_smcccv1_2_smc)
-+ SMC_CALL smc
-+ENDPROC(__arm_smcccv1_2_smc)
-diff --git a/drivers/firmware/Kconfig b/drivers/firmware/Kconfig
-index 1bc0e965f2e9..3bcf3d4514e4 100644
---- a/drivers/firmware/Kconfig
-+++ b/drivers/firmware/Kconfig
-@@ -77,6 +77,17 @@ config ARM_SDE_INTERFACE
- standard for registering callbacks from the platform firmware
- into the OS. This is typically used to implement RAS notifications.
-
-+config ARM_FFA_TRANSPORT
-+ bool "ARM Secure Partition Client Interface (FFA)"
-+ depends on ARM64 || ARM
-+ help
-+ The Secure Partition Client Interface (FFA) is an Arm standard for
-+ communication and memory sharing between entities managed by SMCCC
-+ compliant firmware.
-+
-+ This driver provides interface for all the client drivers making
-+ use of the features offered by FFA.
-+
- config EDD
- tristate "BIOS Enhanced Disk Drive calls determine boot disk"
- depends on X86
-diff --git a/drivers/firmware/Makefile b/drivers/firmware/Makefile
-index 64f5391e5749..10041c5f4d07 100644
---- a/drivers/firmware/Makefile
-+++ b/drivers/firmware/Makefile
-@@ -29,6 +29,7 @@ obj-$(CONFIG_TURRIS_MOX_RWTM) += turris-mox-rwtm.o
-
- obj-$(CONFIG_ARM_SCMI_PROTOCOL) += arm_scmi/
- obj-y += psci/
-+obj-y += ffa/
- obj-y += broadcom/
- obj-y += meson/
- obj-$(CONFIG_GOOGLE_FIRMWARE) += google/
-diff --git a/drivers/firmware/ffa/Makefile b/drivers/firmware/ffa/Makefile
-new file mode 100644
-index 000000000000..37f4ccae197b
---- /dev/null
-+++ b/drivers/firmware/ffa/Makefile
-@@ -0,0 +1,6 @@
-+# SPDX-License-Identifier: GPL-2.0
-+#
-+# Makefile for the linux kernel.
-+#
-+obj-$(CONFIG_ARM_FFA_TRANSPORT) += arm_ffa.o
-+ccflags-y += -Og
-diff --git a/drivers/firmware/ffa/arm_ffa.c b/drivers/firmware/ffa/arm_ffa.c
-new file mode 100644
-index 000000000000..21838f8c4632
---- /dev/null
-+++ b/drivers/firmware/ffa/arm_ffa.c
-@@ -0,0 +1,782 @@
-+// SPDX-License-Identifier: GPL-2.0-only
-+/*
-+ * Secure Partitions Communication Interface (FFA) Protocol driver
-+ *
-+ * FFA is a system message passing and memory sharing protocol allowing for
-+ * execution contexts to exchange information with other execution contexts
-+ * residing on other Secure Partitions or Virtual Machines managed by any FFA
-+ * compliant firmware framework.
-+ *
-+ * Copyright (C) 2019, 2020 Arm Ltd.
-+ */
-+#define DEBUG
-+
-+#include <linux/platform_device.h>
-+#include <linux/arm_ffa.h>
-+#include <linux/arm-smcccv1_2.h>
-+#include <linux/of_address.h>
-+#include <linux/of_platform.h>
-+#include <linux/module.h>
-+#include <linux/mm.h>
-+#include <linux/mutex.h>
-+#include <linux/slab.h>
-+#include <linux/scatterlist.h>
-+
-+
-+static DEFINE_MUTEX(rx_lock);
-+static DEFINE_MUTEX(tx_lock);
-+
-+static ffa_sp_id_t vm_id;
-+
-+static struct page *rx_buffer;
-+static struct page *tx_buffer;
-+
-+static struct arm_smcccv1_2_return
-+(*arm_ffa_smccc)(u32 func, u64 arg1, u64 arg2, u64 arg3, u64 arg4,
-+ u64 arg5, u64 arg6, u64 arg7);
-+
-+#define FFA_DEFINE_CALL(conduit) \
-+static struct arm_smcccv1_2_return \
-+arm_ffa_##conduit(u32 func, u64 arg1, u64 arg2, u64 arg3, u64 arg4, \
-+ u64 arg5, u64 arg6, u64 arg7) \
-+{ \
-+ struct arm_smcccv1_2_return smccc_ret; \
-+ \
-+ __arm_smcccv1_2_##conduit(func, arg1, arg2, arg3, arg4, arg5, \
-+ arg6, arg7, &smccc_ret); \
-+ \
-+ return smccc_ret; \
-+}
-+
-+FFA_DEFINE_CALL(smc)
-+FFA_DEFINE_CALL(hvc)
-+
-+static u32 sender_receiver_pack(u32 src_id, u32 dst_id)
-+{
-+ return (((src_id << 16) & 0xffff0000) | (dst_id & 0xffff));
-+}
-+
-+int ffa_msg_send(ffa_sp_id_t dst_id, u32 len, u32 attributes)
-+{
-+ struct arm_smcccv1_2_return msg_send_return;
-+
-+ /* w1[32:16] Sender endpoint ID, w1[15:0] destination endpoint id. */
-+ u32 sender_receiver = sender_receiver_pack(vm_id, dst_id);
-+
-+ msg_send_return = arm_ffa_smccc(FFA_MSG_SEND_32, sender_receiver,
-+ 0, len, attributes, 0, 0, 0);
-+
-+ if (msg_send_return.arg0 == FFA_ERROR_32) {
-+ switch ((int)msg_send_return.arg2) {
-+ case FFA_INVALID_PARAMETERS:
-+ return -ENXIO;
-+ case FFA_DENIED:
-+ case FFA_BUSY:
-+ return -EAGAIN;
-+ default:
-+ panic("%s: Unhandled return code (%lld)\n", __func__,
-+ msg_send_return.arg2);
-+ }
-+ }
-+ return 0;
-+}
-+
-+struct arm_smcccv1_2_return
-+ffa_msg_send_direct_req(ffa_sp_id_t dst_id, u64 w3, u64 w4, u64 w5,
-+ u64 w6, u64 w7)
-+{
-+ struct arm_smcccv1_2_return ret;
-+
-+ /* w1[32:16] Sender endpoint ID, w1[15:0] destination endpoint id. */
-+ u32 sender_receiver = sender_receiver_pack(vm_id, dst_id);
-+
-+ ret = arm_ffa_smccc(FFA_MSG_SEND_DIRECT_REQ_32, sender_receiver, 0,
-+ w3, w4, w5, w6, w7);
-+
-+ while (ret.arg0 != FFA_MSG_SEND_DIRECT_RESP_32 &&
-+ ret.arg0 != FFA_SUCCESS_32) {
-+ if (ret.arg0 == FFA_ERROR_32) {
-+ pr_err("%s: Error sending message %llu\n", __func__,
-+ ret.arg0);
-+ switch ((int)ret.arg1) {
-+ case FFA_INVALID_PARAMETERS:
-+ ret.arg0 = -ENXIO;
-+ goto out;
-+
-+ case FFA_DENIED:
-+ case FFA_NOT_SUPPORTED:
-+ ret.arg0 = -EIO;
-+ goto out;
-+
-+ case FFA_BUSY:
-+ ret.arg0 = -EAGAIN;
-+ goto out;
-+ }
-+ } else if (ret.arg0 == FFA_INTERRUPT_32) {
-+ ret = arm_ffa_smccc(FFA_RUN_32, ret.arg1,
-+ 0, 0, 0, 0, 0, 0);
-+ }
-+
-+ }
-+
-+ ret.arg0 = 0;
-+
-+out:
-+ return ret;
-+}
-+
-+static int ffa_share_next_frag(u64 handle, u32 frag_len, u32 *tx_offset)
-+{
-+
-+ struct arm_smcccv1_2_return smccc_return;
-+ u32 handle_high = (handle >> 32) & 0xffffffff;
-+ u32 handle_low = handle & 0xffffffff;
-+
-+ smccc_return =
-+ arm_ffa_smccc(FFA_MEM_FRAG_TX_32, handle_low,
-+ handle_high, frag_len, 0, 0, 0, 0);
-+
-+ while (smccc_return.arg0 != FFA_MEM_FRAG_RX_32) {
-+
-+ if (smccc_return.arg0 == FFA_ERROR_32) {
-+ switch ((int)smccc_return.arg2) {
-+ case FFA_INVALID_PARAMETERS:
-+ return -ENXIO;
-+ case FFA_NOT_SUPPORTED:
-+ return -ENODEV;
-+ default:
-+ pr_warn("%s: Unknown Error code %llx\n",
-+ __func__, smccc_return.arg2);
-+ return -EIO;
-+ }
-+ }
-+
-+ if (smccc_return.arg0 == FFA_MEM_OP_PAUSE_32) {
-+
-+ smccc_return = arm_ffa_smccc(FFA_MEM_OP_RESUME_32,
-+ smccc_return.arg1, smccc_return.arg2, 0, 0, 0,
-+ 0, 0);
-+ }
-+ }
-+
-+ *tx_offset = smccc_return.arg3;
-+
-+ return 0;
-+}
-+
-+static int ffa_share_init_frag(phys_addr_t buffer, u32 buffer_size,
-+ u32 fragment_len, u32 total_len, u64 *handle)
-+{
-+
-+ struct arm_smcccv1_2_return smccc_return;
-+
-+ smccc_return =
-+ arm_ffa_smccc(FFA_MEM_SHARE_64, total_len, fragment_len, buffer,
-+ buffer_size, 0, 0, 0);
-+
-+ while (smccc_return.arg0 != FFA_SUCCESS_32) {
-+
-+ if (smccc_return.arg0 == FFA_ERROR_32) {
-+ switch ((int)smccc_return.arg2) {
-+ case FFA_INVALID_PARAMETERS:
-+ return -ENXIO;
-+ case FFA_DENIED:
-+ return -EIO;
-+ case FFA_NO_MEMORY:
-+ return -ENOMEM;
-+ case FFA_ABORTED:
-+ return -EAGAIN;
-+ default:
-+ pr_warn("%s: Unknown Error code %llx\n",
-+ __func__, smccc_return.arg2);
-+ return -EIO;
-+ }
-+ }
-+
-+ if (smccc_return.arg0 == FFA_MEM_OP_PAUSE_32) {
-+
-+ smccc_return = arm_ffa_smccc(FFA_MEM_OP_RESUME_32,
-+ smccc_return.arg1, smccc_return.arg2, 0, 0, 0,
-+ 0, 0);
-+ }
-+ }
-+
-+ *handle = (smccc_return.arg3 << 32) | smccc_return.arg2;
-+
-+ return 0;
-+}
-+
-+static inline u32 compute_composite_offset(u32 num_attributes)
-+{
-+ u32 composite_offset = offsetof(struct ffa_mem_region,
-+ endpoints[num_attributes]);
-+
-+ /* ensure composite are 8 byte aligned. */
-+ if (composite_offset & 0x7)
-+ return (composite_offset & (~(u32)0x7)) + 0x8;
-+
-+ return composite_offset;
-+}
-+
-+static inline u32 compute_constituent_offset(u32 num_attributes)
-+{
-+ u32 constituent_offset = offsetof(struct ffa_mem_region,
-+ endpoints[num_attributes]) +
-+ offsetof(struct ffa_composite_memory_region, constituents[0]);
-+
-+ /* ensure constituents are 8 byte aligned. */
-+ if (constituent_offset & 0x7)
-+ return (constituent_offset & (~(u32)0x7)) + 0x8;
-+
-+ return constituent_offset;
-+}
-+
-+static inline u32 compute_region_length(u32 num_constituents,
-+ u32 num_attributes)
-+{
-+ /* This assumes that there is a single ffa_composite_memory_region. */
-+ return compute_constituent_offset(num_attributes) +
-+ sizeof(struct ffa_mem_region_constituent)*num_constituents;
-+}
-+
-+static int ffa_rx_release(void)
-+{
-+ struct arm_smcccv1_2_return rx_release_return;
-+
-+ rx_release_return = arm_ffa_smccc(FFA_RX_RELEASE_32,
-+ 0, 0, 0, 0, 0, 0, 0);
-+
-+ if (rx_release_return.arg0 == FFA_ERROR_32) {
-+ switch ((int)rx_release_return.arg2) {
-+ case FFA_DENIED:
-+ return -EAGAIN;
-+ default:
-+ panic("%s: Unhandled return code (%lld)\n", __func__,
-+ rx_release_return.arg2);
-+ }
-+ }
-+
-+ if (rx_release_return.arg0 == FFA_RX_RELEASE_32) {
-+ /*
-+ * FFA implementation returned FFA_RX_RELEASE which signals
-+ * the PVM that other VMs need to be scheduled.
-+ */
-+ return 1;
-+ }
-+
-+ return 0;
-+}
-+
-+static uint32_t ffa_get_num_pages_sg(struct scatterlist *sg)
-+{
-+ uint32_t num_pages = 0;
-+
-+ do {
-+ num_pages += sg->length/PAGE_SIZE;
-+ } while ((sg = sg_next(sg)));
-+
-+ return num_pages;
-+}
-+
-+static inline struct ffa_memory_region_attribute ffa_set_region_normal(
-+ enum ffa_mem_cacheability cacheability,
-+ enum ffa_mem_shareability shareability)
-+{
-+ struct ffa_memory_region_attribute attr = {0};
-+
-+ attr.attribute = (FFA_MEM_NORMAL << FFA_MEMTYPE_OFFSET) |
-+ (cacheability << FFA_CACHEABILITY_OFFSET) | shareability;
-+
-+ return attr;
-+}
-+
-+static inline struct ffa_memory_region_attribute ffa_set_region_device(
-+ enum ffa_mem_device_type device_type)
-+{
-+ struct ffa_memory_region_attribute attr = {0};
-+
-+ attr.attribute = (FFA_MEM_DEVICE << FFA_MEMTYPE_OFFSET) |
-+ (device_type << FFA_DEVICE_OFFSET);
-+
-+ return attr;
-+}
-+
-+static inline int ffa_transmit_fragment(u32 *tx_offset, phys_addr_t buffer,
-+ u32 buffer_size, u32 frag_len, u32 total_len, u64 *handle)
-+{
-+ int rc;
-+
-+ if (*tx_offset == 0) {
-+ rc = ffa_share_init_frag(buffer, buffer_size,
-+ frag_len, total_len, handle);
-+
-+ *tx_offset = frag_len;
-+ } else
-+ rc = ffa_share_next_frag(*handle, frag_len, tx_offset);
-+
-+
-+ return rc;
-+}
-+
-+/*
-+ * Share a set of pages with a list of destination endpoints.
-+ * Returns a system-wide unique handle
-+ */
-+static int _ffa_share_memory(u32 tag, enum mem_clear_t flags,
-+ struct ffa_mem_region_attributes *attrs,
-+ u32 num_attrs, struct scatterlist *sg, u32 nents,
-+ ffa_mem_handle_t *handle, phys_addr_t buffer, uint32_t buffer_size)
-+{
-+ struct ffa_mem_region *mem_region;
-+ u32 index;
-+ u32 num_constituents;
-+ struct ffa_mem_region_constituent *constituents;
-+ u32 total_len;
-+ u32 fragment_len = sizeof(struct ffa_mem_region);
-+ u32 max_fragment_size;
-+ int rc = 0;
-+ u32 tx_offset = 0;
-+ struct ffa_composite_memory_region *composite = NULL;
-+
-+ if (buffer) {
-+
-+ BUG_ON(!buffer_size);
-+ max_fragment_size = buffer_size * FFA_BASE_GRANULE_SIZE;
-+ mem_region = phys_to_virt(buffer);
-+
-+ } else {
-+
-+ BUG_ON(buffer_size);
-+ mem_region = (struct ffa_mem_region *)page_address(tx_buffer);
-+ max_fragment_size = FFA_BASE_GRANULE_SIZE;
-+
-+ }
-+
-+ mem_region->flags = flags;
-+ mem_region->tag = tag;
-+ mem_region->sender_id = vm_id;
-+ mem_region->region_attr = ffa_set_region_normal(FFA_WRITE_BACK,
-+ FFA_INNER_SHAREABLE);
-+ composite = ffa_get_composite(mem_region, num_attrs);
-+ composite->total_page_count = ffa_get_num_pages_sg(sg);
-+
-+ fragment_len = compute_constituent_offset(num_attrs);
-+
-+ /* Ensure attribute description fits within the Tx buffer. */
-+ if (fragment_len > max_fragment_size)
-+ return -ENXIO;
-+
-+ constituents = (struct ffa_mem_region_constituent *)
-+ (((void *)mem_region) + fragment_len);
-+
-+ composite->constituent_count = nents;
-+ total_len = compute_region_length(nents, num_attrs);
-+
-+ for (index = 0; index < num_attrs; index++) {
-+ mem_region->endpoints[index].receiver = attrs[index].receiver;
-+ mem_region->endpoints[index].attrs =
-+ attrs[index].attrs;
-+
-+ mem_region->endpoints[index].composite_off =
-+ compute_composite_offset(num_attrs);
-+ }
-+ mem_region->endpoint_count = num_attrs;
-+
-+ num_constituents = 0;
-+
-+ do {
-+ phys_addr_t address;
-+
-+ /*
-+ * If current fragment size equal Tx size trigger fragment
-+ * transfer.
-+ */
-+ if (fragment_len == max_fragment_size) {
-+
-+ /* Transmit fragment. */
-+ rc = ffa_transmit_fragment(&tx_offset, buffer,
-+ buffer_size, fragment_len, total_len, handle);
-+
-+ if (rc < 0)
-+ return -ENXIO;
-+
-+
-+ constituents =
-+ (struct ffa_mem_region_constituent *)mem_region;
-+
-+ num_constituents = 0;
-+ fragment_len = 0;
-+ }
-+
-+ address = sg_phys(sg);
-+
-+ /*
-+ * Detect if any part of the constituent region surpasses the Tx
-+ * region.
-+ */
-+ if (((void *) &constituents[num_constituents])
-+ - (void *)mem_region > max_fragment_size) {
-+ pr_err("%s: memory region fragment greater that the Tx buffer",
-+ __func__);
-+ return -EFAULT;
-+ }
-+#if 0
-+ pr_devel("arm_ffa mem_share pa=%#lX\n", address);
-+#endif
-+ constituents[num_constituents].address = address;
-+ constituents[num_constituents].page_count =
-+ sg->length/PAGE_SIZE;
-+ num_constituents++;
-+ fragment_len += sizeof(struct ffa_mem_region_constituent);
-+
-+
-+ } while ((sg = sg_next(sg)));
-+
-+ rc = ffa_transmit_fragment(&tx_offset, buffer, buffer_size,
-+ fragment_len, total_len, handle);
-+
-+ return rc;
-+}
-+
-+/*
-+ * Share a set of pages with a list of destination endpoints.
-+ *
-+ * Returns a system-wide unique handle
-+ */
-+static int ffa_share_memory(u32 tag, enum mem_clear_t flags,
-+ struct ffa_mem_region_attributes *attrs,
-+ u32 num_attrs, struct scatterlist *sg, u32 nents,
-+ ffa_mem_handle_t *global_handle, bool use_tx)
-+{
-+ u32 buffer_size = 0;
-+ phys_addr_t buffer_pa = 0;
-+ int ret;
-+ struct page *buffer_page = NULL;
-+
-+ if (!use_tx) {
-+ /* Allocate buffer for this mem_share operation. */
-+ buffer_page = alloc_page(GFP_KERNEL);
-+ if (IS_ERR_OR_NULL(buffer_page)) {
-+ /* print error. Return as tx lock is not held. */
-+ pr_err("%s: unable to allocate buffer", __func__);
-+ return -ENOMEM;
-+ }
-+
-+ buffer_pa = page_to_phys(buffer_page);
-+
-+ buffer_size = 1;
-+ }
-+
-+ if (use_tx)
-+ mutex_lock(&tx_lock);
-+
-+ ret = _ffa_share_memory(tag, flags, attrs, num_attrs, sg, nents,
-+ global_handle, buffer_pa, buffer_size);
-+
-+ if (use_tx)
-+ mutex_unlock(&tx_lock);
-+
-+ return ret;
-+}
-+
-+static int ffa_memory_reclaim(ffa_mem_handle_t global_handle,
-+ enum mem_clear_t flags)
-+{
-+
-+ struct arm_smcccv1_2_return smccc_return;
-+ u32 handle_high = (global_handle >> 32) & 0xffffffff;
-+ u32 handle_low = global_handle & 0xffffffff;
-+
-+ smccc_return = arm_ffa_smccc(FFA_MEM_RECLAIM_32, handle_low,
-+ handle_high, flags, 0, 0, 0, 0);
-+
-+ if (smccc_return.arg0 == FFA_ERROR_32) {
-+ pr_err("%s: Error sending message %llu\n", __func__,
-+ smccc_return.arg0);
-+ switch ((int)smccc_return.arg2) {
-+ case FFA_INVALID_PARAMETERS:
-+ return -ENXIO;
-+ case FFA_DENIED:
-+ case FFA_NOT_SUPPORTED:
-+ return -EIO;
-+ case FFA_BUSY:
-+ return -EAGAIN;
-+ default:
-+ pr_warn("%s: Unknown Error code %llx\n", __func__,
-+ smccc_return.arg2);
-+ return -EIO;
-+ }
-+ }
-+
-+ return 0;
-+}
-+
-+/*
-+ * Returns a negative value if function not supported. Otherwise returns w2,
-+ * supplying optional feature parameter else 0.
-+ */
-+
-+static int ffa_features(uint32_t function_id)
-+{
-+ struct arm_smcccv1_2_return features_return =
-+ arm_ffa_smccc(FFA_FEATURES_32, function_id, 0, 0, 0, 0, 0, 0);
-+
-+ if (features_return.arg0 == FFA_ERROR_32) {
-+ switch ((int)features_return.arg2) {
-+ case FFA_NOT_SUPPORTED:
-+ return -ENODEV;
-+ default:
-+ panic("%s: Unhandled return code (%lld)\n", __func__,
-+ features_return.arg2);
-+ }
-+ } else {
-+ return features_return.arg2;
-+ }
-+}
-+
-+static ffa_sp_id_t ffa_id_get(ffa_sp_id_t *vm_id_p)
-+{
-+ struct arm_smcccv1_2_return id_get_return =
-+ arm_ffa_smccc(FFA_ID_GET_32, 0, 0, 0, 0, 0, 0, 0);
-+
-+ if (id_get_return.arg0 == FFA_ERROR_32) {
-+ pr_warn("%s: failed to obtain vm id\n", __func__);
-+ return -EIO;
-+ }
-+
-+ *vm_id_p = id_get_return.arg2 & 0xffff;
-+
-+ return 0;
-+}
-+
-+static int ffa_partition_info_get(uint32_t uuid0, uint32_t uuid1,
-+ uint32_t uuid2, uint32_t uuid3,
-+ struct ffa_partition_info **buffer)
-+{
-+ int rc = 0;
-+ uint32_t count;
-+ struct ffa_partition_info *info =
-+ (struct ffa_partition_info *) page_address(rx_buffer);
-+ struct arm_smcccv1_2_return partition_info_get_return;
-+
-+ mutex_lock(&rx_lock);
-+ partition_info_get_return = arm_ffa_smccc(FFA_PARTITION_INFO_GET_32,
-+ uuid0, uuid1, uuid2, uuid3,
-+ 0, 0, 0);
-+
-+ if (partition_info_get_return.arg0 == FFA_ERROR_32) {
-+ switch ((int)partition_info_get_return.arg2) {
-+ case FFA_INVALID_PARAMETERS:
-+ rc = -ENXIO;
-+ goto err;
-+ case FFA_NO_MEMORY:
-+ rc = -ENOMEM;
-+ goto err;
-+ case FFA_NOT_SUPPORTED:
-+ rc = -ENODEV;
-+ goto err;
-+ default:
-+ panic("%s: Unhandled return code (%lld)\n", __func__,
-+ partition_info_get_return.arg2);
-+ }
-+ }
-+
-+ count = partition_info_get_return.arg2;
-+
-+ /* Allocate and copy the info structs.
-+ * Client is responsible for freeing.
-+ */
-+ *buffer = kzalloc(sizeof(struct ffa_partition_info) * count,
-+ GFP_KERNEL);
-+ if (*buffer == NULL) {
-+ rc = -ENOMEM;
-+ goto err;
-+ }
-+ memcpy(*buffer, info, sizeof(struct ffa_partition_info) * count);
-+
-+ ffa_rx_release();
-+
-+ rc = count;
-+err:
-+ mutex_unlock(&rx_lock);
-+
-+ return rc;
-+}
-+
-+static struct ffa_ops ffa_ops = {
-+ .async_msg_send = ffa_msg_send,
-+ .sync_msg_send = ffa_msg_send_direct_req,
-+ .mem_share = ffa_share_memory,
-+ .mem_reclaim = ffa_memory_reclaim,
-+ .partition_info_get = ffa_partition_info_get,
-+};
-+
-+struct ffa_ops *get_ffa_ops(void)
-+{
-+ return &ffa_ops;
-+}
-+EXPORT_SYMBOL_GPL(get_ffa_ops);
-+
-+static int ffa_dt_init(struct device_node *np)
-+{
-+ const char *conduit;
-+
-+ pr_info("FFA: obtaining conduit from DT.\n");
-+
-+ if (of_property_read_string(np, "conduit", &conduit)) {
-+ pr_warn("FFA: cannot find conduit in DT\n");
-+ return -ENXIO;
-+ }
-+
-+ if (!strcmp("smc", conduit))
-+ arm_ffa_smccc = arm_ffa_smc;
-+ else if (!strcmp("hvc", conduit))
-+ arm_ffa_smccc = arm_ffa_hvc;
-+ else {
-+ pr_warn("%s: unrecognized FFA conduit\n", __func__);
-+ return -EIO;
-+ }
-+
-+ return 0;
-+}
-+
-+static const struct of_device_id ffa_of_match[] = {
-+ {.compatible = "arm,ffa"},
-+ {},
-+};
-+
-+static int ffa_rxtx_map(uintptr_t tx_page, uintptr_t rx_page)
-+{
-+ struct arm_smcccv1_2_return map_return;
-+
-+ map_return = arm_ffa_smccc(FFA_RXTX_MAP_32, tx_page,
-+ rx_page, 1, 0, 0, 0, 0);
-+
-+ if (map_return.arg0 == FFA_ERROR_32) {
-+ switch ((int)map_return.arg2) {
-+ case FFA_INVALID_PARAMETERS:
-+ return -ENXIO;
-+ case FFA_DENIED:
-+ return -EAGAIN;
-+ case FFA_NO_MEMORY:
-+ return -ENOMEM;
-+ case FFA_NOT_SUPPORTED:
-+ return -ENODEV;
-+
-+ default:
-+ panic("%s: Unhandled return code (%lld)\n", __func__,
-+ map_return.arg2);
-+ }
-+ }
-+
-+ return 0;
-+}
-+
-+static int ffa_version_check(void)
-+{
-+ struct arm_smcccv1_2_return version_return;
-+ u16 major = 1;
-+ u16 minor = 0;
-+ u32 hv_version;
-+
-+ version_return = arm_ffa_smccc(FFA_VERSION_32, ((u32)major<<16)|minor,
-+ 0, 0, 0, 0, 0, 0);
-+
-+ if ((int)version_return.arg0 == FFA_NOT_SUPPORTED) {
-+ pr_err("%s: FFA ABI is not supported at higher exception levels\n",
-+ __func__);
-+ return -ENODEV;
-+ }
-+
-+ hv_version = version_return.arg0;
-+
-+ if ((hv_version>>16) == major)
-+ if ((hv_version & 0xffff) >= minor)
-+ return 0;
-+
-+ pr_err("%s: incompatible FFA ABI at higher exception level (%x)\n",
-+ __func__, hv_version);
-+ return -ENODEV;
-+}
-+
-+static int ffa_probe(struct platform_device *pdev)
-+{
-+ int ret;
-+
-+ ret = ffa_dt_init(pdev->dev.of_node);
-+ if (ret) {
-+ pr_warn("%s: FFA driver initialization failed\n", __func__);
-+ return ret;
-+ }
-+
-+ ret = ffa_version_check();
-+ if (ret)
-+ return ret;
-+
-+ /* Initialize VM ID. */
-+ ret = ffa_id_get(&vm_id);
-+ if (ret) {
-+ pr_warn("%s: failed to obtain own FFA endpoint ID\n", __func__);
-+ return ret;
-+ }
-+
-+ if (ffa_features(FFA_MSG_SEND_DIRECT_REQ_32)) {
-+ pr_err("%s: FFA implementation at EL2 does not support FFA_MSG_SEND_DIRECT_REQ_32\n",
-+ __func__);
-+ return -ENXIO;
-+ }
-+
-+ /* Allocate Rx buffer. */
-+ rx_buffer = alloc_page(GFP_KERNEL);
-+
-+ /*
-+ * Ensure buffer was correctly allocated and that the refcout was
-+ * incremented.
-+ */
-+ if (!rx_buffer || !try_get_page(rx_buffer)) {
-+ pr_err("%s: failed to allocate FFA Rx buffer\n", __func__);
-+ return -ENOMEM;
-+ }
-+
-+ /* Allocate Tx buffer. */
-+ tx_buffer = alloc_page(GFP_KERNEL);
-+
-+ /*
-+ * Ensure buffer was correctly allocated and that the refcout was
-+ * incremented.
-+ */
-+ if (!tx_buffer || !try_get_page(rx_buffer)) {
-+ put_page(rx_buffer);
-+ __free_page(rx_buffer);
-+
-+ pr_err("%s: failed to allocate FFA Tx buffer\n", __func__);
-+ return -ENOMEM;
-+ }
-+
-+ /* Register the RxTx buffers with the FFA supervisor implementation. */
-+ ret = ffa_rxtx_map(page_to_phys(tx_buffer), page_to_phys(rx_buffer));
-+ if (ret) {
-+ put_page(rx_buffer);
-+ put_page(tx_buffer);
-+ __free_page(rx_buffer);
-+ __free_page(tx_buffer);
-+
-+ pr_err("%s: failed to register FFA RxTx buffers\n", __func__);
-+ return ret;
-+ }
-+
-+ return 0;
-+}
-+
-+static struct platform_driver ffa_driver = {
-+ .driver = {
-+ .name = "ffa_protocol",
-+ .of_match_table = ffa_of_match,
-+ },
-+ .probe = ffa_probe,
-+};
-+module_platform_driver(ffa_driver);
-+
-+MODULE_AUTHOR("Arm");
-+MODULE_DESCRIPTION("Arm FFA transport driver");
-+MODULE_LICENSE("GPL v2");
-diff --git a/include/linux/arm-smcccv1_2.h b/include/linux/arm-smcccv1_2.h
-new file mode 100644
-index 000000000000..a622cc352ae1
---- /dev/null
-+++ b/include/linux/arm-smcccv1_2.h
-@@ -0,0 +1,51 @@
-+/* SPDX-License-Identifier: GPL-2.0-only */
-+/*
-+ * Copyright (C) 2019 Arm Ltd.
-+ */
-+
-+//#if defined(ARM64)
-+#if CONFIG_ARM64
-+struct arm_smcccv1_2_return {
-+ u64 arg0;
-+ u64 arg1;
-+ u64 arg2;
-+ u64 arg3;
-+ u64 arg4;
-+ u64 arg5;
-+ u64 arg6;
-+ u64 arg7;
-+};
-+#elif CONFIG_ARM
-+struct arm_smcccv1_2_return {
-+ u32 arg0;
-+ u32 arg1;
-+ u32 arg2;
-+ u32 arg3;
-+ u32 arg4;
-+ u32 arg5;
-+ u32 arg6;
-+ u32 arg7;
-+};
-+#endif
-+
-+/**
-+ * __arm_smcccv1_2_hvc() - make HVC calls
-+ * @a0-a7: arguments passed in registers 0 to 7
-+ * @res: result values from registers 0 to 7
-+ */
-+asmlinkage
-+void __arm_smcccv1_2_hvc(unsigned long a0, unsigned long a1, unsigned long a2,
-+ unsigned long a3, unsigned long a4, unsigned long a5,
-+ unsigned long a6, unsigned long a7,
-+ struct arm_smcccv1_2_return *res);
-+
-+/**
-+ * __arm_smcccv1_2_smc() - make SMC calls
-+ * @a0-a7: arguments passed in registers 0 to 7
-+ * @res: result values from registers 0 to 7
-+ */
-+asmlinkage
-+void __arm_smcccv1_2_smc(unsigned long a0, unsigned long a1, unsigned long a2,
-+ unsigned long a3, unsigned long a4, unsigned long a5,
-+ unsigned long a6, unsigned long a7,
-+ struct arm_smcccv1_2_return *res);
-diff --git a/include/linux/arm_ffa.h b/include/linux/arm_ffa.h
-new file mode 100644
-index 000000000000..d3c80b7f9e07
---- /dev/null
-+++ b/include/linux/arm_ffa.h
-@@ -0,0 +1,235 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * Copyright (C) 2019, 2020 Arm Ltd.
-+ */
-+
-+#ifndef __LINUX_ARM_FFA_H
-+#define __LINUX_ARM_FFA_H
-+
-+#define FFA_ERROR_32 0x84000060
-+#define FFA_SUCCESS_32 0x84000061
-+#define FFA_INTERRUPT_32 0x84000062
-+#define FFA_VERSION_32 0x84000063
-+#define FFA_FEATURES_32 0x84000064
-+#define FFA_RX_RELEASE_32 0x84000065
-+#define FFA_RXTX_MAP_32 0x84000066
-+
-+#define FFA_PARTITION_INFO_GET_32 0x84000068
-+#define FFA_ID_GET_32 0x84000069
-+
-+#define FFA_RUN_32 0x8400006D
-+#define FFA_MSG_SEND_32 0x8400006E
-+#define FFA_MSG_SEND_DIRECT_REQ_32 0x8400006F
-+#define FFA_MSG_SEND_DIRECT_RESP_32 0x84000070
-+#define FFA_MEM_RECLAIM_32 0x84000077
-+#define FFA_MEM_OP_PAUSE_32 0x84000078
-+#define FFA_MEM_OP_RESUME_32 0x84000079
-+
-+#define FFA_MEM_SHARE_64 0xC4000073
-+
-+#define FFA_MEM_FRAG_RX_32 0x8400007A
-+#define FFA_MEM_FRAG_TX_32 0x8400007B
-+
-+/* FFA error codes. */
-+#define FFA_SUCCESS (0)
-+#define FFA_NOT_SUPPORTED (-1)
-+#define FFA_INVALID_PARAMETERS (-2)
-+#define FFA_NO_MEMORY (-3)
-+#define FFA_BUSY (-4)
-+#define FFA_INTERRUPTED (-5)
-+#define FFA_DENIED (-6)
-+#define FFA_RETRY (-7)
-+#define FFA_ABORTED (-8)
-+
-+#define FFA_BASE_GRANULE_SIZE 4096
-+
-+struct scatterlist;
-+
-+enum ffa_mem_permission {
-+ FFA_MEM_R = 0x1,
-+ FFA_MEM_RW = 0x2,
-+ FFA_MEM_XN = 0x4,
-+ FFA_MEM_X = 0x8,
-+};
-+
-+#define FFA_MEMTYPE_OFFSET 4
-+enum ffa_mem_type {
-+ FFA_MEM_DEVICE = 0x1,
-+ FFA_MEM_NORMAL = 0x2,
-+};
-+
-+
-+#define FFA_CACHEABILITY_OFFSET 2
-+enum ffa_mem_cacheability {
-+ FFA_NON_CACHEABLE = 0x1,
-+ FFA_WRITE_BACK = 0x3,
-+};
-+
-+enum ffa_mem_shareability {
-+ FFA_NON_SHAREABLE,
-+ FFA_OUTER_SHAREABLE = 0x2,
-+ FFA_INNER_SHAREABLE = 0x3,
-+};
-+
-+#define FFA_DEVICE_OFFSET 2
-+enum ffa_mem_device_type {
-+ FFA_NGNRNE,
-+ FFA_NGNRE,
-+ FFA_NGRE,
-+ FFA_GRE,
-+};
-+
-+enum mem_clear_t {
-+ FFA_KEEP_MEMORY,
-+ FFA_CLEAR_MEMORY,
-+};
-+
-+typedef u64 ffa_mem_handle_t;
-+
-+/* The type of an FFA endpoint ID */
-+typedef u16 ffa_sp_id_t;
-+
-+struct ffa_mem_region_constituent {
-+ u64 address;
-+ u32 page_count;
-+ u32 reserved_12_15;
-+};
-+
-+struct ffa_composite_memory_region {
-+
-+ uint32_t total_page_count;
-+ uint32_t constituent_count;
-+
-+ uint64_t reserved_0;
-+
-+ struct ffa_mem_region_constituent constituents[];
-+};
-+
-+struct ffa_mem_region_attributes {
-+ ffa_sp_id_t receiver;
-+ u8 attrs;
-+ u32 composite_off;
-+ u64 reserved_8_15;
-+};
-+
-+/* Table 43 */
-+struct ffa_memory_region_attribute {
-+ uint8_t attribute;
-+};
-+
-+struct ffa_mem_region {
-+ u16 sender_id;
-+ struct ffa_memory_region_attribute region_attr;
-+ u8 reserved_0;
-+ u32 flags;
-+ u64 handle;
-+ u64 tag;
-+ u32 reserved_1;
-+ u32 endpoint_count;
-+ struct ffa_mem_region_attributes endpoints[];
-+};
-+
-+static inline struct ffa_composite_memory_region *
-+ffa_get_composite(struct ffa_mem_region *mem_region, u32 num_endpoints)
-+{
-+ struct ffa_composite_memory_region *composite;
-+
-+ composite = (struct ffa_composite_memory_region *)
-+ (&mem_region->endpoints[num_endpoints]);
-+ return composite;
-+}
-+
-+
-+struct ffa_partition_info {
-+ /** The ID of the VM the information is about. */
-+ ffa_sp_id_t id;
-+ /**
-+ * The number of execution contexts implemented by the
-+ * partition.
-+ */
-+ uint16_t execution_context;
-+ /**
-+ * The Partition's properties, e.g. supported messaging
-+ * methods
-+ */
-+ uint32_t partition_properties;
-+};
-+
-+
-+/**
-+ * struct ffa_ops - represents the various FFA protocol operations
-+ * available for an SCPI endpoint.
-+ */
-+struct ffa_ops {
-+ int (*async_msg_send)(ffa_sp_id_t dst_id, u32 len, u32 attributes);
-+ struct arm_smcccv1_2_return
-+ (*sync_msg_send)(ffa_sp_id_t dst_id, u64 w3, u64 w4, u64 w5,
-+ u64 w6, u64 w7);
-+
-+ /**
-+ * Registers a memory region with the FFA implementation.
-+ *
-+ * Params:
-+ * - tag: Implementation defined value.
-+ * - flags:
-+ * - FFA_KEEP_MEMORY: DO not clear the memory region;
-+ * - FFA_CLEAR_MEMORY: Clear the memory region.
-+ * - attrs[]: Array of destination VMs and permissions with which the
-+ * Stage-2 mappings are set.
-+ * - num_attrs: Count of elements pointed to by attrs.
-+ * - sg: scatter list holding the pages to be shared.
-+ * - global_handle: A system-wide unique handle referring to the shared
-+ * set of physical pages being shared.
-+ * - use_tx: select if memorry region description is transmitted in tx
-+ * or in a dynamically allocated buffer. When using the tx buffer a
-+ * global lock on the tx buffer will be held.
-+ *
-+ * Return: 0 in case of success, otherwise a negative value
-+ * (error code).
-+ */
-+ int (*mem_share)(u32 tag, enum mem_clear_t flags,
-+ struct ffa_mem_region_attributes attrs[],
-+ u32 num_attrs, struct scatterlist *sg, u32 nents,
-+ ffa_mem_handle_t *global_handle, bool use_tx);
-+
-+ /**
-+ * Reclaims a memory region previously registered with the FFA
-+ * implementation.
-+ * Params:
-+ * - global_handle: The global identifier of the memory region being
-+ * reclaimed.
-+ * - clear_memory: Set if the memory is meant to be cleared before
-+ * being mapped in the owner's Stage-2.
-+ *
-+ * Return: 0 in case of success, otherwise a negative value
-+ * (error code).
-+ */
-+ int (*mem_reclaim)(ffa_mem_handle_t global_handle,
-+ enum mem_clear_t flags);
-+ /**
-+ * Returns information on a sub-set of partitions within a system
-+ * identified by a UUID.
-+ * Params:
-+ * - uuid0-3: The 128 bit UUID of the desired partition(s) represented
-+ * as 4 32 bit uints in form: uuid0-uuid1-uuid2-uuid3.
-+ * - ffa_partition_info**: A pointer to an array of
-+ * `ffa_parition_info` structs that will be
-+ * allocated and populated with the
-+ * discovered partitions information. The
-+ * caller is responsible for freeing the
-+ * memory allocated by the FFA driver.
-+ * Return: The number of discovered partitions in the system and the
-+ * length of the array of ffa_partition_info structs,
-+ * otherwise a negative value (error code).
-+ */
-+ int (*partition_info_get)(u32 uuid0, u32 uuid1, u32 uuid2, u32 uuid3,
-+ struct ffa_partition_info **buffer);
-+};
-+
-+#if IS_REACHABLE(CONFIG_ARM_FFA_TRANSPORT)
-+struct ffa_ops *get_ffa_ops(void);
-+#else
-+static inline struct ffa_ops *get_ffa_ops(void) { return NULL; }
-+#endif
-+
-+#endif /*__LINUX_ARM_FFA_H*/
---
-2.26.2
-
diff --git a/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.4/tc0/0010-tee-add-support-for-session-s-client-UUID-generation.patch b/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.4/tc0/0010-tee-add-support-for-session-s-client-UUID-generation.patch
deleted file mode 100644
index 269940e..0000000
--- a/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.4/tc0/0010-tee-add-support-for-session-s-client-UUID-generation.patch
+++ /dev/null
@@ -1,252 +0,0 @@
-Upstream-Status: Backport [https://github.com/linaro-swg/linux/commit/e33bcbab16d1c0dd85d72bec275308369ad901f5#diff-317c0445401e56bde9d2ee0e0bb2758b0362a4099dca8e535dd20f1f649ecfc8]
-Signed-off-by: Arunachalam Ganapathy <arunachalam.ganapathy@arm.com>
-
-From 69a50f4234d8fb143d499e92e3f0f67009bae586 Mon Sep 17 00:00:00 2001
-From: =?UTF-8?q?Vesa=20J=C3=A4=C3=A4skel=C3=A4inen?=
- <vesa.jaaskelainen@vaisala.com>
-Date: Wed, 22 Apr 2020 15:28:07 +0300
-Subject: [PATCH] tee: add support for session's client UUID generation
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-TEE Client API defines that from user space only information needed for
-specified login operations is group identifier for group based logins.
-
-REE kernel is expected to formulate trustworthy client UUID and pass that
-to TEE environment. REE kernel is required to verify that provided group
-identifier for group based logins matches calling processes group
-memberships.
-
-TEE specification only defines that the information passed from REE
-environment to TEE environment is encoded into on UUID.
-
-In order to guarantee trustworthiness of client UUID user space is not
-allowed to freely pass client UUID.
-
-UUIDv5 form is used encode variable amount of information needed for
-different login types.
-
-Signed-off-by: Vesa Jääskeläinen <vesa.jaaskelainen@vaisala.com>
-Change-Id: I414f68d7485f95277d292fcb2646cc41bd57e62a
----
- drivers/tee/Kconfig | 1 +
- drivers/tee/tee_core.c | 143 ++++++++++++++++++++++++++++++++++++++++
- include/linux/tee_drv.h | 16 +++++
- 3 files changed, 160 insertions(+)
-
-diff --git a/drivers/tee/Kconfig b/drivers/tee/Kconfig
-index 676ffcb64985..5a56317f3f4e 100644
---- a/drivers/tee/Kconfig
-+++ b/drivers/tee/Kconfig
-@@ -3,6 +3,7 @@
- config TEE
- tristate "Trusted Execution Environment support"
- depends on HAVE_ARM_SMCCC || COMPILE_TEST
-+ select CRYPTO_SHA1
- select DMA_SHARED_BUFFER
- select GENERIC_ALLOCATOR
- help
-diff --git a/drivers/tee/tee_core.c b/drivers/tee/tee_core.c
-index 0f16d9ffd8d1..3d32a2ca48c3 100644
---- a/drivers/tee/tee_core.c
-+++ b/drivers/tee/tee_core.c
-@@ -6,18 +6,33 @@
- #define pr_fmt(fmt) "%s: " fmt, __func__
-
- #include <linux/cdev.h>
-+#include <linux/cred.h>
- #include <linux/fs.h>
- #include <linux/idr.h>
- #include <linux/module.h>
- #include <linux/slab.h>
- #include <linux/tee_drv.h>
- #include <linux/uaccess.h>
-+#include <crypto/hash.h>
-+#include <crypto/sha.h>
- #include "tee_private.h"
-
- #define TEE_NUM_DEVICES 32
-
- #define TEE_IOCTL_PARAM_SIZE(x) (sizeof(struct tee_param) * (x))
-
-+#define TEE_UUID_NS_NAME_SIZE 128
-+
-+/*
-+ * TEE Client UUID name space identifier (UUIDv4)
-+ *
-+ * Value here is random UUID that is allocated as name space identifier for
-+ * forming Client UUID's for TEE environment using UUIDv5 scheme.
-+ */
-+static const uuid_t tee_client_uuid_ns = UUID_INIT(0x58ac9ca0, 0x2086, 0x4683,
-+ 0xa1, 0xb8, 0xec, 0x4b,
-+ 0xc0, 0x8e, 0x01, 0xb6);
-+
- /*
- * Unprivileged devices in the lower half range and privileged devices in
- * the upper half range.
-@@ -111,6 +126,134 @@ static int tee_release(struct inode *inode, struct file *filp)
- return 0;
- }
-
-+/**
-+ * uuid_v5() - Calculate UUIDv5
-+ * @uuid: Resulting UUID
-+ * @ns: Name space ID for UUIDv5 function
-+ * @name: Name for UUIDv5 function
-+ * @size: Size of name
-+ *
-+ * UUIDv5 is specific in RFC 4122.
-+ *
-+ * This implements section (for SHA-1):
-+ * 4.3. Algorithm for Creating a Name-Based UUID
-+ */
-+static int uuid_v5(uuid_t *uuid, const uuid_t *ns, const void *name,
-+ size_t size)
-+{
-+ unsigned char hash[SHA1_DIGEST_SIZE];
-+ struct crypto_shash *shash = NULL;
-+ struct shash_desc *desc = NULL;
-+ int rc;
-+
-+ shash = crypto_alloc_shash("sha1", 0, 0);
-+ if (IS_ERR(shash)) {
-+ rc = PTR_ERR(shash);
-+ pr_err("shash(sha1) allocation failed\n");
-+ return rc;
-+ }
-+
-+ desc = kzalloc(sizeof(*desc) + crypto_shash_descsize(shash),
-+ GFP_KERNEL);
-+ if (IS_ERR(desc)) {
-+ rc = PTR_ERR(desc);
-+ goto out;
-+ }
-+
-+ desc->tfm = shash;
-+
-+ rc = crypto_shash_init(desc);
-+ if (rc < 0)
-+ goto out2;
-+
-+ rc = crypto_shash_update(desc, (const u8 *)ns, sizeof(*ns));
-+ if (rc < 0)
-+ goto out2;
-+
-+ rc = crypto_shash_update(desc, (const u8 *)name, size);
-+ if (rc < 0)
-+ goto out2;
-+
-+ rc = crypto_shash_final(desc, hash);
-+ if (rc < 0)
-+ goto out2;
-+
-+ memcpy(uuid->b, hash, UUID_SIZE);
-+
-+ /* Tag for version 5 */
-+ uuid->b[6] = (hash[6] & 0x0F) | 0x50;
-+ uuid->b[8] = (hash[8] & 0x3F) | 0x80;
-+
-+out2:
-+ kfree(desc);
-+
-+out:
-+ crypto_free_shash(shash);
-+ return rc;
-+}
-+
-+int tee_session_calc_client_uuid(uuid_t *uuid, u32 connection_method,
-+ const u8 connection_data[TEE_IOCTL_UUID_LEN])
-+{
-+ const char *application_id = NULL;
-+ gid_t ns_grp = (gid_t)-1;
-+ kgid_t grp = INVALID_GID;
-+ char *name = NULL;
-+ int rc;
-+
-+ if (connection_method == TEE_IOCTL_LOGIN_PUBLIC) {
-+ /* Nil UUID to be passed to TEE environment */
-+ uuid_copy(uuid, &uuid_null);
-+ return 0;
-+ }
-+
-+ /*
-+ * In Linux environment client UUID is based on UUIDv5.
-+ *
-+ * Determine client UUID with following semantics for 'name':
-+ *
-+ * For TEEC_LOGIN_USER:
-+ * uid=<uid>
-+ *
-+ * For TEEC_LOGIN_GROUP:
-+ * gid=<gid>
-+ *
-+ */
-+
-+ name = kzalloc(TEE_UUID_NS_NAME_SIZE, GFP_KERNEL);
-+ if (!name)
-+ return -ENOMEM;
-+
-+ switch (connection_method) {
-+ case TEE_IOCTL_LOGIN_USER:
-+ scnprintf(name, TEE_UUID_NS_NAME_SIZE, "uid=%x",
-+ current_euid().val);
-+ break;
-+
-+ case TEE_IOCTL_LOGIN_GROUP:
-+ memcpy(&ns_grp, connection_data, sizeof(gid_t));
-+ grp = make_kgid(current_user_ns(), ns_grp);
-+ if (!gid_valid(grp) || !in_egroup_p(grp)) {
-+ rc = -EPERM;
-+ goto out;
-+ }
-+
-+ scnprintf(name, TEE_UUID_NS_NAME_SIZE, "gid=%x", grp.val);
-+ break;
-+
-+ default:
-+ rc = -EINVAL;
-+ goto out;
-+ }
-+
-+ rc = uuid_v5(uuid, &tee_client_uuid_ns, name, strlen(name));
-+out:
-+ kfree(name);
-+
-+ return rc;
-+}
-+EXPORT_SYMBOL_GPL(tee_session_calc_client_uuid);
-+
- static int tee_ioctl_version(struct tee_context *ctx,
- struct tee_ioctl_version_data __user *uvers)
- {
-diff --git a/include/linux/tee_drv.h b/include/linux/tee_drv.h
-index 7a03f68fb982..545a57f61a5e 100644
---- a/include/linux/tee_drv.h
-+++ b/include/linux/tee_drv.h
-@@ -166,6 +166,22 @@ int tee_device_register(struct tee_device *teedev);
- */
- void tee_device_unregister(struct tee_device *teedev);
-
-+/**
-+ * tee_session_calc_client_uuid() - Calculates client UUID for session
-+ * @uuid: Resulting UUID
-+ * @connection_method: Connection method for session (TEE_IOCTL_LOGIN_*)
-+ * @connectuon_data: Connection data for opening session
-+ *
-+ * Based on connection method calculates UUIDv5 based client UUID.
-+ *
-+ * For group based logins verifies that calling process has specified
-+ * credentials.
-+ *
-+ * @return < 0 on failure
-+ */
-+int tee_session_calc_client_uuid(uuid_t *uuid, u32 connection_method,
-+ const u8 connection_data[TEE_IOCTL_UUID_LEN]);
-+
- /**
- * struct tee_shm - shared memory object
- * @teedev: device used to allocate the object
---
-2.26.2
-
diff --git a/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.4/tc0/0011-tee-optee-Add-support-for-session-login-client-UUID-.patch b/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.4/tc0/0011-tee-optee-Add-support-for-session-login-client-UUID-.patch
deleted file mode 100644
index 65d4311..0000000
--- a/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.4/tc0/0011-tee-optee-Add-support-for-session-login-client-UUID-.patch
+++ /dev/null
@@ -1,43 +0,0 @@
-Upstream-Status: Backport [https://github.com/linaro-swg/linux/commit/c5b4312bea5d5e5e3d4f0af640e2ef8a1c1bb167#diff-2d83bca4adf0468bdb51b155a5df495e0226f7971f4150cfffbf043fe3b5a279]
-Signed-off-by: Arunachalam Ganapathy <arunachalam.ganapathy@arm.com>
-
-From c6c4046d8fcd34a4b8da9d844ce592951780ba8c Mon Sep 17 00:00:00 2001
-From: =?UTF-8?q?Vesa=20J=C3=A4=C3=A4skel=C3=A4inen?=
- <vesa.jaaskelainen@vaisala.com>
-Date: Wed, 22 Apr 2020 15:30:39 +0300
-Subject: [PATCH] tee: optee: Add support for session login client UUID
- generation
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-Adds support for client UUID generation for OP-TEE. For group based session
-logins membership is verified.
-
-Signed-off-by: Vesa Jääskeläinen <vesa.jaaskelainen@vaisala.com>
----
- drivers/tee/optee/call.c | 6 +++++-
- 1 file changed, 5 insertions(+), 1 deletion(-)
-
-diff --git a/drivers/tee/optee/call.c b/drivers/tee/optee/call.c
-index cf2367ba08d6..dbed3f480dc0 100644
---- a/drivers/tee/optee/call.c
-+++ b/drivers/tee/optee/call.c
-@@ -233,9 +233,13 @@ int optee_open_session(struct tee_context *ctx,
- msg_arg->params[1].attr = OPTEE_MSG_ATTR_TYPE_VALUE_INPUT |
- OPTEE_MSG_ATTR_META;
- memcpy(&msg_arg->params[0].u.value, arg->uuid, sizeof(arg->uuid));
-- memcpy(&msg_arg->params[1].u.value, arg->uuid, sizeof(arg->clnt_uuid));
- msg_arg->params[1].u.value.c = arg->clnt_login;
-
-+ rc = tee_session_calc_client_uuid((uuid_t *)&msg_arg->params[1].u.value,
-+ arg->clnt_login, arg->clnt_uuid);
-+ if (rc)
-+ goto out;
-+
- rc = optee_to_msg_param(msg_arg->params + 2, arg->num_params, param);
- if (rc)
- goto out;
---
-2.26.2
-
diff --git a/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.4/tc0/0012-driver-optee-Support-for-ffa-transport.patch b/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.4/tc0/0012-driver-optee-Support-for-ffa-transport.patch
deleted file mode 100644
index 40d4ffe..0000000
--- a/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.4/tc0/0012-driver-optee-Support-for-ffa-transport.patch
+++ /dev/null
@@ -1,3150 +0,0 @@
-Upstream-Status: Pending [https://git.kernel.org/pub/scm/linux/kernel/git/sudeep.holla/linux.git/commit/?h=ffa_rel_proto&id=8a0acded67268b7110c69ed5425c56d881716d78]
-Signed-off-by: Arunachalam Ganapathy <arunachalam.ganapathy@arm.com>
-
-From 2e12bf893c180cb1444ca20148983d1c45431c71 Mon Sep 17 00:00:00 2001
-From: Jens Wiklander <jens.wiklander@linaro.org>
-Date: Tue, 30 Oct 2018 21:12:11 +0100
-Subject: [PATCH] driver: optee: Support for ffa transport
-
-FF-A transport support for optee driver. Based on ffa_rel_proto at
-https://git.kernel.org/pub/scm/linux/kernel/git/sudeep.holla/linux.git/log/?h=ffa_rel_proto
-
-Squashed in:
- tee: remove linked list of struct tee_shm
-
- Removes list_shm from struct tee_context since the linked list isn't used
- any longer.
-
- tee: remove unused tee_shm_priv_alloc()
-
- tee_shm_priv_alloc() isn't useful in the current state and it's also not
- not used so remove it.
-
- tee: don't assign shm id for private shms
-
- Private shared memory object must not be referenced from user space. To
- guarantee that don't assign an id to keep the shared memory driver
- private.
-
- tee: remove redundant teedev in struct tee_shm
-
- Since the ctx element in struct tee_shm always is valid has the teedev
- element become redundant so remove it.
-
- tee: add sec_world_id to struct tee_shm
-
- Adds sec_world_id to struct tee_shm which describes a shared memory
- object. sec_world_id can be used by a driver to store an id assigned by
- secure world.
-
- tee: tee_shm_op_mmap(): use TEE_SHM_USER_MAPPED
-
- tee_shm_op_mmap() uses the TEE_SHM_USER_MAPPED flag instead of the
- TEE_SHM_REGISTER flag to tell if a shared memory object is originating
- from registered user space memory.
-
- Set -Og flags for the OPTEE driver compilation.
-
- optee: simplify optee_release()
-
- Simplifies optee_release() with a new helper function,
- optee_close_session_helper() which has been factored out from
- optee_close_session().
-
- A separate optee_release_supp() is added for the supplicant device.
-
- tee: optee: sync optee_msg.h and optee_rpc_cmd.h
-
- Updates to latest optee_msg.h and optee_rpc_cmd.h. There's no changes in
- the ABI. Only some clarifications and a complete specification of RPC
- requests where the latter is now in a separate file, optee_rpc_cmd.h.
-
- Most of the RPC requests are not served by the OP-TEE driver instead
- they are forwarded as opaque requests to tee-supplicant.
-
- tee: export tee_shm_alloc()
-
- Export tee_shm_alloc() using EXPORT_SYMBOL_GPL(). Needed by
- optee_rng_init() and other drivers complied as a module and using OP-TEE
- as a service.
-
- optee: add spci support
-
- Adds support for using SPCI as transport to the OP-TEE driver.
-
- tee: optee: introduce SPCI specific OPTEE_MSG memref
-
- Introduces struct optee_msg_param_smem which carries all information
- needed when OP-TEE is calling SPCI_MEM_RETRIEVE_REQ to get the shared
- memory reference mapped by the hypervisor in S-EL2. Register usage is
- also updated to include the information needed.
-
- This isn't strictly needed without a hypervisor in S-EL2 and OP-TEE
- itself has the SPMC part. However, this is a configuration which
- shouldn't concern normal world.
-
- tee: optee: Use PARTITION_INFO_GET to get SP ID.
-
- Instead of using a hardcoded partition ID for OPTEE, use the
- SPCI_PARTITION_INFO_GET ABI to find the partition ID corresponding to
- the OPTEE UUID.
-
- tee: optee: Update OPTEE for mem_share SPCI
-
- Update OPTEE to pass a scatterlist in the mem_share interface.
-
- tee: Adapt OPTEE to new SPCI mem_share interface
-
- optee: test_spci: Update optee, spci test driver [optee bits]
-
- Enable optee and spci test drivesr to pass a scatterlist* and a nents
- parameter in mem_share.
-
- arm_spci: refactor mem_share implementation for EAC [optee bits]
-
- arm_ffa: optee: Swap spci/SPCI for ffa/FFA. [optee bits]
-
- arm_ffa: rename 1st member of arm_smcccv1_2_return [optee bits]
-
- The smcccv1_2_return.func is renamed to arg0.
-
- tee: add sec_world_id to struct tee_shm
-
- Change the type of sec_world_id member of struct tee_shm to u64 to be
- able to store the 64-bit Global Handle defined in FF-A.
-
- optee: updated for FF-A 1.0
-
- With FF-A 1.0 the ABI to secure world has changed compared to SPCI
- beta1.
-
- The globally unique handle to identify a shared memory object is now 64
- bits wide instead of previous 32. The IDR in struct optee_ffa is
- replaced with a struct rhashtable instead in order to support 64-bit
- keys.
-
- Register usage in the FF-A function has changed compared to SPCI beta1
- so the OP-TEE ABI is updated accordingly. The global handle, aka cookie,
- is now requires 2 registers.
-
- struct optee_msg_param_smem is updated to be able to carry a 64-bit
- global handle while maintaining the same size of the struct. Due to this
- the "page_count" field is dropped.
-
- optee: Update SMCC field name
-
- optee: Update FFA_VERSION from 0.9 to 1.0
-
- optee/call.c: Update SPCI reference to FFA
-
-Signed-off-by: Jens Wiklander <jens.wiklander@linaro.org>
-Signed-off-by: Marc Bonnici <marc.bonnici@arm.com>
-Signed-off-by: Arunachalam Ganapathy <arunachalam.ganapathy@arm.com>
----
- drivers/tee/Makefile | 1 +
- drivers/tee/optee/Makefile | 1 +
- drivers/tee/optee/call.c | 318 ++++++++++---
- drivers/tee/optee/core.c | 735 +++++++++++++++++++++++++-----
- drivers/tee/optee/optee_ffa.h | 201 ++++++++
- drivers/tee/optee/optee_msg.h | 167 ++-----
- drivers/tee/optee/optee_private.h | 61 ++-
- drivers/tee/optee/optee_rpc_cmd.h | 333 ++++++++++++++
- drivers/tee/optee/rpc.c | 147 +++++-
- drivers/tee/optee/shm_pool.c | 50 ++
- drivers/tee/optee/shm_pool.h | 1 +
- drivers/tee/tee_core.c | 1 -
- drivers/tee/tee_shm.c | 85 +---
- include/linux/tee_drv.h | 26 +-
- 14 files changed, 1710 insertions(+), 417 deletions(-)
- create mode 100644 drivers/tee/optee/optee_ffa.h
- create mode 100644 drivers/tee/optee/optee_rpc_cmd.h
-
-diff --git a/drivers/tee/Makefile b/drivers/tee/Makefile
-index 21f51fd88b07..c4fe9f0d3bf8 100644
---- a/drivers/tee/Makefile
-+++ b/drivers/tee/Makefile
-@@ -4,3 +4,4 @@ tee-objs += tee_core.o
- tee-objs += tee_shm.o
- tee-objs += tee_shm_pool.o
- obj-$(CONFIG_OPTEE) += optee/
-+ccflags-y += -Og
-diff --git a/drivers/tee/optee/Makefile b/drivers/tee/optee/Makefile
-index 56263ae3b1d7..57371dc91bba 100644
---- a/drivers/tee/optee/Makefile
-+++ b/drivers/tee/optee/Makefile
-@@ -6,3 +6,4 @@ optee-objs += rpc.o
- optee-objs += supp.o
- optee-objs += shm_pool.o
- optee-objs += device.o
-+ccflags-y += -Og
-diff --git a/drivers/tee/optee/call.c b/drivers/tee/optee/call.c
-index dbed3f480dc0..ac89ab42a43f 100644
---- a/drivers/tee/optee/call.c
-+++ b/drivers/tee/optee/call.c
-@@ -3,16 +3,20 @@
- * Copyright (c) 2015, Linaro Limited
- */
- #include <linux/arm-smccc.h>
-+#include <linux/arm-smcccv1_2.h>
-+#include <linux/arm_ffa.h>
- #include <linux/device.h>
- #include <linux/err.h>
- #include <linux/errno.h>
- #include <linux/mm.h>
-+#include <linux/scatterlist.h>
- #include <linux/slab.h>
- #include <linux/tee_drv.h>
- #include <linux/types.h>
- #include <linux/uaccess.h>
- #include "optee_private.h"
- #include "optee_smc.h"
-+#include "optee_ffa.h"
-
- struct optee_call_waiter {
- struct list_head list_node;
-@@ -122,13 +126,18 @@ static struct optee_session *find_session(struct optee_context_data *ctxdata,
- *
- * Returns return code from secure world, 0 is OK
- */
--u32 optee_do_call_with_arg(struct tee_context *ctx, phys_addr_t parg)
-+int optee_do_call_with_arg(struct tee_context *ctx, struct tee_shm *arg)
- {
- struct optee *optee = tee_get_drvdata(ctx->teedev);
-- struct optee_call_waiter w;
-+ struct optee_call_waiter w = { };
- struct optee_rpc_param param = { };
- struct optee_call_ctx call_ctx = { };
-- u32 ret;
-+ phys_addr_t parg = 0;
-+ int rc = 0;
-+
-+ rc = tee_shm_get_pa(arg, 0, &parg);
-+ if (rc)
-+ return rc;
-
- param.a0 = OPTEE_SMC_CALL_WITH_ARG;
- reg_pair_from_64(¶m.a1, ¶m.a2, parg);
-@@ -155,7 +164,7 @@ u32 optee_do_call_with_arg(struct tee_context *ctx, phys_addr_t parg)
- param.a3 = res.a3;
- optee_handle_rpc(ctx, ¶m, &call_ctx);
- } else {
-- ret = res.a0;
-+ rc = res.a0;
- break;
- }
- }
-@@ -167,16 +176,15 @@ u32 optee_do_call_with_arg(struct tee_context *ctx, phys_addr_t parg)
- */
- optee_cq_wait_final(&optee->call_queue, &w);
-
-- return ret;
-+ return rc;
- }
-
- static struct tee_shm *get_msg_arg(struct tee_context *ctx, size_t num_params,
-- struct optee_msg_arg **msg_arg,
-- phys_addr_t *msg_parg)
-+ struct optee_msg_arg **msg_arg)
- {
-- int rc;
-- struct tee_shm *shm;
-- struct optee_msg_arg *ma;
-+ int rc = 0;
-+ struct tee_shm *shm = NULL;
-+ struct optee_msg_arg *ma = NULL;
-
- shm = tee_shm_alloc(ctx, OPTEE_MSG_GET_ARG_SIZE(num_params),
- TEE_SHM_MAPPED);
-@@ -189,10 +197,6 @@ static struct tee_shm *get_msg_arg(struct tee_context *ctx, size_t num_params,
- goto out;
- }
-
-- rc = tee_shm_get_pa(shm, 0, msg_parg);
-- if (rc)
-- goto out;
--
- memset(ma, 0, OPTEE_MSG_GET_ARG_SIZE(num_params));
- ma->num_params = num_params;
- *msg_arg = ma;
-@@ -209,15 +213,15 @@ int optee_open_session(struct tee_context *ctx,
- struct tee_ioctl_open_session_arg *arg,
- struct tee_param *param)
- {
-+ struct optee *optee = tee_get_drvdata(ctx->teedev);
- struct optee_context_data *ctxdata = ctx->data;
-- int rc;
-- struct tee_shm *shm;
-- struct optee_msg_arg *msg_arg;
-- phys_addr_t msg_parg;
-+ struct optee_msg_arg *msg_arg = NULL;
- struct optee_session *sess = NULL;
-+ struct tee_shm *shm = NULL;
-+ int rc = 0;
-
- /* +2 for the meta parameters added below */
-- shm = get_msg_arg(ctx, arg->num_params + 2, &msg_arg, &msg_parg);
-+ shm = get_msg_arg(ctx, arg->num_params + 2, &msg_arg);
- if (IS_ERR(shm))
- return PTR_ERR(shm);
-
-@@ -240,7 +244,8 @@ int optee_open_session(struct tee_context *ctx,
- if (rc)
- goto out;
-
-- rc = optee_to_msg_param(msg_arg->params + 2, arg->num_params, param);
-+ rc = optee->ops->to_msg_param(optee, msg_arg->params + 2,
-+ arg->num_params, param);
- if (rc)
- goto out;
-
-@@ -250,7 +255,7 @@ int optee_open_session(struct tee_context *ctx,
- goto out;
- }
-
-- if (optee_do_call_with_arg(ctx, msg_parg)) {
-+ if (optee->ops->do_call_with_arg(ctx, shm)) {
- msg_arg->ret = TEEC_ERROR_COMMUNICATION;
- msg_arg->ret_origin = TEEC_ORIGIN_COMMS;
- }
-@@ -265,7 +270,8 @@ int optee_open_session(struct tee_context *ctx,
- kfree(sess);
- }
-
-- if (optee_from_msg_param(param, arg->num_params, msg_arg->params + 2)) {
-+ if (optee->ops->from_msg_param(optee, param, arg->num_params,
-+ msg_arg->params + 2)) {
- arg->ret = TEEC_ERROR_COMMUNICATION;
- arg->ret_origin = TEEC_ORIGIN_COMMS;
- /* Close session again to avoid leakage */
-@@ -281,12 +287,28 @@ int optee_open_session(struct tee_context *ctx,
- return rc;
- }
-
--int optee_close_session(struct tee_context *ctx, u32 session)
-+int optee_close_session_helper(struct tee_context *ctx, u32 session)
-+{
-+ struct optee *optee = tee_get_drvdata(ctx->teedev);
-+ struct optee_msg_arg *msg_arg = NULL;
-+ struct tee_shm *shm = NULL;
-+
-+ shm = get_msg_arg(ctx, 0, &msg_arg);
-+ if (IS_ERR(shm))
-+ return PTR_ERR(shm);
-+
-+ msg_arg->cmd = OPTEE_MSG_CMD_CLOSE_SESSION;
-+ msg_arg->session = session;
-+ optee->ops->do_call_with_arg(ctx, shm);
-+
-+ tee_shm_free(shm);
-+
-+ return 0;
-+}
-+
-+static int remove_session(struct tee_context *ctx, u32 session)
- {
- struct optee_context_data *ctxdata = ctx->data;
-- struct tee_shm *shm;
-- struct optee_msg_arg *msg_arg;
-- phys_addr_t msg_parg;
- struct optee_session *sess;
-
- /* Check that the session is valid and remove it from the list */
-@@ -299,27 +321,28 @@ int optee_close_session(struct tee_context *ctx, u32 session)
- return -EINVAL;
- kfree(sess);
-
-- shm = get_msg_arg(ctx, 0, &msg_arg, &msg_parg);
-- if (IS_ERR(shm))
-- return PTR_ERR(shm);
-+ return 0;
-+}
-
-- msg_arg->cmd = OPTEE_MSG_CMD_CLOSE_SESSION;
-- msg_arg->session = session;
-- optee_do_call_with_arg(ctx, msg_parg);
-+int optee_close_session(struct tee_context *ctx, u32 session)
-+{
-+ int rc = remove_session(ctx, session);
-
-- tee_shm_free(shm);
-- return 0;
-+ if (rc)
-+ return rc;
-+
-+ return optee_close_session_helper(ctx, session);
- }
-
- int optee_invoke_func(struct tee_context *ctx, struct tee_ioctl_invoke_arg *arg,
- struct tee_param *param)
- {
-+ struct optee *optee = tee_get_drvdata(ctx->teedev);
- struct optee_context_data *ctxdata = ctx->data;
-- struct tee_shm *shm;
-- struct optee_msg_arg *msg_arg;
-- phys_addr_t msg_parg;
-- struct optee_session *sess;
-- int rc;
-+ struct optee_msg_arg *msg_arg = NULL;
-+ struct optee_session *sess = NULL;
-+ struct tee_shm *shm = NULL;
-+ int rc = 0;
-
- /* Check that the session is valid */
- mutex_lock(&ctxdata->mutex);
-@@ -328,7 +351,7 @@ int optee_invoke_func(struct tee_context *ctx, struct tee_ioctl_invoke_arg *arg,
- if (!sess)
- return -EINVAL;
-
-- shm = get_msg_arg(ctx, arg->num_params, &msg_arg, &msg_parg);
-+ shm = get_msg_arg(ctx, arg->num_params, &msg_arg);
- if (IS_ERR(shm))
- return PTR_ERR(shm);
- msg_arg->cmd = OPTEE_MSG_CMD_INVOKE_COMMAND;
-@@ -336,16 +359,18 @@ int optee_invoke_func(struct tee_context *ctx, struct tee_ioctl_invoke_arg *arg,
- msg_arg->session = arg->session;
- msg_arg->cancel_id = arg->cancel_id;
-
-- rc = optee_to_msg_param(msg_arg->params, arg->num_params, param);
-+ rc = optee->ops->to_msg_param(optee, msg_arg->params, arg->num_params,
-+ param);
- if (rc)
- goto out;
-
-- if (optee_do_call_with_arg(ctx, msg_parg)) {
-+ if (optee->ops->do_call_with_arg(ctx, shm)) {
- msg_arg->ret = TEEC_ERROR_COMMUNICATION;
- msg_arg->ret_origin = TEEC_ORIGIN_COMMS;
- }
-
-- if (optee_from_msg_param(param, arg->num_params, msg_arg->params)) {
-+ if (optee->ops->from_msg_param(optee, param, arg->num_params,
-+ msg_arg->params)) {
- msg_arg->ret = TEEC_ERROR_COMMUNICATION;
- msg_arg->ret_origin = TEEC_ORIGIN_COMMS;
- }
-@@ -359,11 +384,11 @@ int optee_invoke_func(struct tee_context *ctx, struct tee_ioctl_invoke_arg *arg,
-
- int optee_cancel_req(struct tee_context *ctx, u32 cancel_id, u32 session)
- {
-+ struct optee *optee = tee_get_drvdata(ctx->teedev);
- struct optee_context_data *ctxdata = ctx->data;
-- struct tee_shm *shm;
-- struct optee_msg_arg *msg_arg;
-- phys_addr_t msg_parg;
-- struct optee_session *sess;
-+ struct optee_msg_arg *msg_arg = NULL;
-+ struct optee_session *sess = NULL;
-+ struct tee_shm *shm = NULL;
-
- /* Check that the session is valid */
- mutex_lock(&ctxdata->mutex);
-@@ -372,14 +397,14 @@ int optee_cancel_req(struct tee_context *ctx, u32 cancel_id, u32 session)
- if (!sess)
- return -EINVAL;
-
-- shm = get_msg_arg(ctx, 0, &msg_arg, &msg_parg);
-+ shm = get_msg_arg(ctx, 0, &msg_arg);
- if (IS_ERR(shm))
- return PTR_ERR(shm);
-
- msg_arg->cmd = OPTEE_MSG_CMD_CANCEL;
- msg_arg->session = session;
- msg_arg->cancel_id = cancel_id;
-- optee_do_call_with_arg(ctx, msg_parg);
-+ optee->ops->do_call_with_arg(ctx, shm);
-
- tee_shm_free(shm);
- return 0;
-@@ -442,6 +467,16 @@ void optee_disable_shm_cache(struct optee *optee)
- optee_cq_wait_final(&optee->call_queue, &w);
- }
-
-+/**
-+ * optee_ffa_disable_shm_cache() - Disables caching of some shared memory
-+ * allocation in OP-TEE
-+ * @optee: main service struct
-+ */
-+void optee_ffa_disable_shm_cache(struct optee *optee)
-+{
-+ BUG();
-+}
-+
- #define PAGELIST_ENTRIES_PER_PAGE \
- ((OPTEE_MSG_NONCONTIG_PAGE_SIZE / sizeof(u64)) - 1)
-
-@@ -577,11 +612,11 @@ int optee_shm_register(struct tee_context *ctx, struct tee_shm *shm,
- struct page **pages, size_t num_pages,
- unsigned long start)
- {
-+ struct optee *optee = tee_get_drvdata(ctx->teedev);
-+ struct optee_msg_arg *msg_arg = NULL;
- struct tee_shm *shm_arg = NULL;
-- struct optee_msg_arg *msg_arg;
-- u64 *pages_list;
-- phys_addr_t msg_parg;
-- int rc;
-+ u64 *pages_list = NULL;
-+ int rc = 0;
-
- if (!num_pages)
- return -EINVAL;
-@@ -594,7 +629,7 @@ int optee_shm_register(struct tee_context *ctx, struct tee_shm *shm,
- if (!pages_list)
- return -ENOMEM;
-
-- shm_arg = get_msg_arg(ctx, 1, &msg_arg, &msg_parg);
-+ shm_arg = get_msg_arg(ctx, 1, &msg_arg);
- if (IS_ERR(shm_arg)) {
- rc = PTR_ERR(shm_arg);
- goto out;
-@@ -615,7 +650,7 @@ int optee_shm_register(struct tee_context *ctx, struct tee_shm *shm,
- msg_arg->params->u.tmem.buf_ptr = virt_to_phys(pages_list) |
- (tee_shm_get_page_offset(shm) & (OPTEE_MSG_NONCONTIG_PAGE_SIZE - 1));
-
-- if (optee_do_call_with_arg(ctx, msg_parg) ||
-+ if (optee->ops->do_call_with_arg(ctx, shm) ||
- msg_arg->ret != TEEC_SUCCESS)
- rc = -EINVAL;
-
-@@ -627,12 +662,12 @@ int optee_shm_register(struct tee_context *ctx, struct tee_shm *shm,
-
- int optee_shm_unregister(struct tee_context *ctx, struct tee_shm *shm)
- {
-- struct tee_shm *shm_arg;
-- struct optee_msg_arg *msg_arg;
-- phys_addr_t msg_parg;
-+ struct optee *optee = tee_get_drvdata(ctx->teedev);
-+ struct optee_msg_arg *msg_arg = NULL;
-+ struct tee_shm *shm_arg = NULL;
- int rc = 0;
-
-- shm_arg = get_msg_arg(ctx, 1, &msg_arg, &msg_parg);
-+ shm_arg = get_msg_arg(ctx, 1, &msg_arg);
- if (IS_ERR(shm_arg))
- return PTR_ERR(shm_arg);
-
-@@ -641,7 +676,7 @@ int optee_shm_unregister(struct tee_context *ctx, struct tee_shm *shm)
- msg_arg->params[0].attr = OPTEE_MSG_ATTR_TYPE_RMEM_INPUT;
- msg_arg->params[0].u.rmem.shm_ref = (unsigned long)shm;
-
-- if (optee_do_call_with_arg(ctx, msg_parg) ||
-+ if (optee->ops->do_call_with_arg(ctx, shm) ||
- msg_arg->ret != TEEC_SUCCESS)
- rc = -EINVAL;
- tee_shm_free(shm_arg);
-@@ -663,3 +698,166 @@ int optee_shm_unregister_supp(struct tee_context *ctx, struct tee_shm *shm)
- {
- return 0;
- }
-+
-+#ifdef CONFIG_ARM_FFA_TRANSPORT
-+static int optee_ffa_yielding_call(struct tee_context *ctx, u32 w3, u32 w4,
-+ u32 w5)
-+{
-+ struct optee *optee = tee_get_drvdata(ctx->teedev);
-+ struct arm_smcccv1_2_return ret = { };
-+ const u32 dst = optee->ffa.dst;
-+ struct optee_call_waiter w;
-+ u32 w6 = 0;
-+ u32 w7 = 0;
-+ int rc = 0;
-+
-+ /* Initialize waiter */
-+ optee_cq_wait_init(&optee->call_queue, &w);
-+ while (true) {
-+ ret = optee->ffa.ops->sync_msg_send(dst, w3, w4, w5, w6, w7);
-+
-+ if (ret.arg0) {
-+ pr_err("ret.arg0 %d\n", (int)ret.arg0);
-+ rc = -EIO;
-+ goto done;
-+ }
-+
-+ switch ((int)ret.arg3) {
-+ case FFA_SUCCESS:
-+ break;
-+ case FFA_BUSY:
-+ if (w3 == OPTEE_FFA_YIELDING_CALL_RESUME) {
-+ pr_err("err OPTEE_FFA_YIELDING_CALL_RESUME\n");
-+ rc = -EIO;
-+ goto done;
-+ }
-+
-+ /*
-+ * Out of threads in secure world, wait for a thread
-+ * become available.
-+ */
-+ optee_cq_wait_for_completion(&optee->call_queue, &w);
-+ continue;
-+ default:
-+ pr_err("ret.arg3 0x%llx\n", (u64)ret.arg3);
-+ rc = -EIO;
-+ goto done;
-+ }
-+
-+ if (ret.arg4 == OPTEE_FFA_YIELDING_CALL_RETURN_DONE)
-+ goto done;
-+
-+ might_sleep();
-+ w4 = ret.arg4;
-+ w5 = ret.arg5;
-+ w6 = ret.arg6;
-+ optee_handle_ffa_rpc(ctx, &w4, &w5, &w6);
-+ w3 = OPTEE_FFA_YIELDING_CALL_RESUME;
-+ w7 = ret.arg7;
-+ }
-+done:
-+
-+ /*
-+ * We're done with our thread in secure world, if there's any
-+ * thread waiters wake up one.
-+ */
-+ optee_cq_wait_final(&optee->call_queue, &w);
-+
-+ return rc;
-+}
-+
-+int optee_ffa_do_call_with_arg(struct tee_context *ctx, struct tee_shm *shm)
-+{
-+ if (shm->offset)
-+ return -EINVAL;
-+ return optee_ffa_yielding_call(ctx, OPTEE_FFA_YIELDING_CALL_WITH_ARG,
-+ shm->sec_world_id,
-+ shm->sec_world_id >> 32);
-+}
-+
-+int optee_ffa_shm_register(struct tee_context *ctx, struct tee_shm *shm,
-+ struct page **pages, size_t num_pages,
-+ unsigned long start)
-+{
-+ struct optee *optee = tee_get_drvdata(ctx->teedev);
-+ u64 global_handle = 0;
-+ u32 rc = 0;
-+ struct sg_table sgt;
-+ struct ffa_mem_region_attributes mem_attr = {
-+ .receiver = optee->ffa.dst,
-+ .attrs = FFA_MEM_RW,
-+ };
-+
-+ rc = check_mem_type(start, num_pages);
-+ if (rc)
-+ return rc;
-+
-+ sg_alloc_table_from_pages(&sgt, pages,
-+ num_pages, 0,
-+ num_pages * 4096, GFP_KERNEL);
-+
-+ rc = optee->ffa.ops->mem_share(0, 0, &mem_attr, 1, sgt.sgl, sgt.nents,
-+ &global_handle, true);
-+ if (rc) {
-+ if (rc == FFA_NO_MEMORY)
-+ return -ENOMEM;
-+ return -EINVAL;
-+ }
-+
-+ rc = optee_shm_add_ffa_handle(optee, shm, global_handle);
-+ if (rc) {
-+ optee->ffa.ops->mem_reclaim(global_handle, 0);
-+ return rc;
-+ }
-+
-+ shm->sec_world_id = global_handle;
-+
-+ return 0;
-+}
-+
-+int optee_ffa_shm_unregister(struct tee_context *ctx, struct tee_shm *shm)
-+{
-+ struct optee *optee = tee_get_drvdata(ctx->teedev);
-+ u64 global_handle = shm->sec_world_id;
-+ int rc = 0;
-+
-+ optee_shm_rem_ffa_handle(optee, global_handle);
-+ shm->sec_world_id = 0;
-+
-+ rc = optee_ffa_yielding_call(ctx,
-+ OPTEE_FFA_YIELDING_CALL_UNREGISTER_SHM,
-+ global_handle, global_handle >> 32);
-+ if (rc)
-+ pr_err("OPTEE_FFA_YIELDING_CALL_UNREGISTER_SHM id 0x%llx rc %d\n",
-+ global_handle, rc);
-+
-+ rc = optee->ffa.ops->mem_reclaim(global_handle, 0);
-+ if (rc)
-+ pr_err("mem_reclain: %d", rc);
-+
-+ return rc;
-+}
-+
-+int optee_ffa_shm_unregister_supp(struct tee_context *ctx,
-+ struct tee_shm *shm)
-+{
-+ struct optee *optee = tee_get_drvdata(ctx->teedev);
-+ int rc = 0;
-+
-+ /*
-+ * We're skipping the OPTEE_FFA_YIELDING_CALL_UNREGISTER_SHM call
-+ * since this is OP-TEE freeing via RPC so it has already retired
-+ * this ID.
-+ */
-+
-+ rc = optee->ffa.ops->mem_reclaim(shm->sec_world_id, 0);
-+ if (rc)
-+ pr_err("mem_reclain: %d", rc);
-+
-+ optee_shm_rem_ffa_handle(optee, shm->sec_world_id);
-+
-+ shm->sec_world_id = 0;
-+
-+ return rc;
-+}
-+#endif /*CONFIG_ARM_FFA_TRANSPORT*/
-diff --git a/drivers/tee/optee/core.c b/drivers/tee/optee/core.c
-index b830e0a87fba..4178ae7f914a 100644
---- a/drivers/tee/optee/core.c
-+++ b/drivers/tee/optee/core.c
-@@ -6,6 +6,8 @@
- #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
- #include <linux/arm-smccc.h>
-+#include <linux/arm-smcccv1_2.h>
-+#include <linux/arm_ffa.h>
- #include <linux/errno.h>
- #include <linux/io.h>
- #include <linux/module.h>
-@@ -19,12 +21,157 @@
- #include <linux/uaccess.h>
- #include "optee_private.h"
- #include "optee_smc.h"
-+#include "optee_ffa.h"
- #include "shm_pool.h"
-
- #define DRIVER_NAME "optee"
-+#define SUPPORTED_OPTEE_PARTITIONS 1
-
- #define OPTEE_SHM_NUM_PRIV_PAGES CONFIG_OPTEE_SHM_NUM_PRIV_PAGES
-
-+#ifdef CONFIG_ARM_FFA_TRANSPORT
-+struct shm_rhash {
-+ struct tee_shm *shm;
-+ u64 global_id;
-+ struct rhash_head linkage;
-+};
-+
-+static void rh_free_fn(void *ptr, void *arg)
-+{
-+ kfree(ptr);
-+}
-+
-+static const struct rhashtable_params shm_rhash_params = {
-+ .head_offset = offsetof(struct shm_rhash, linkage),
-+ .key_len = sizeof(u64),
-+ .key_offset = offsetof(struct shm_rhash, global_id),
-+ .automatic_shrinking = true,
-+};
-+
-+struct tee_shm *optee_shm_from_ffa_handle(struct optee *optee, u64 global_id)
-+{
-+ struct shm_rhash *r = NULL;
-+ struct tee_shm *shm = NULL;
-+
-+ mutex_lock(&optee->ffa.mutex);
-+ r = rhashtable_lookup_fast(&optee->ffa.global_ids, &global_id,
-+ shm_rhash_params);
-+ if (r)
-+ shm = r->shm;
-+ mutex_unlock(&optee->ffa.mutex);
-+
-+ return shm;
-+}
-+
-+int optee_shm_add_ffa_handle(struct optee *optee, struct tee_shm *shm,
-+ u64 global_id)
-+{
-+ struct shm_rhash *r = NULL;
-+ int rc = 0;
-+
-+ r = kmalloc(sizeof(*r), GFP_KERNEL);
-+ if (!r)
-+ return -ENOMEM;
-+ r->shm = shm;
-+ r->global_id = global_id;
-+
-+ mutex_lock(&optee->ffa.mutex);
-+ rc = rhashtable_lookup_insert_fast(&optee->ffa.global_ids, &r->linkage,
-+ shm_rhash_params);
-+ mutex_unlock(&optee->ffa.mutex);
-+
-+ if (rc)
-+ kfree(r);
-+
-+ return rc;
-+}
-+
-+int optee_shm_rem_ffa_handle(struct optee *optee, u64 global_id)
-+{
-+ struct shm_rhash *r = NULL;
-+ int rc = -ENOENT;
-+
-+ mutex_lock(&optee->ffa.mutex);
-+ r = rhashtable_lookup_fast(&optee->ffa.global_ids, &global_id,
-+ shm_rhash_params);
-+ if (r) {
-+ rc = rhashtable_remove_fast(&optee->ffa.global_ids,
-+ &r->linkage, shm_rhash_params);
-+ if (!rc)
-+ kfree(r);
-+ }
-+ mutex_unlock(&optee->ffa.mutex);
-+
-+ return rc;
-+}
-+#endif /*CONFIG_ARM_FFA_TRANSPORT*/
-+
-+static void from_msg_param_value(struct tee_param *p, u32 attr,
-+ const struct optee_msg_param *mp)
-+{
-+ p->attr = TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT +
-+ attr - OPTEE_MSG_ATTR_TYPE_VALUE_INPUT;
-+ p->u.value.a = mp->u.value.a;
-+ p->u.value.b = mp->u.value.b;
-+ p->u.value.c = mp->u.value.c;
-+}
-+
-+static int from_msg_param_tmp_mem(struct tee_param *p, u32 attr,
-+ const struct optee_msg_param *mp)
-+{
-+ struct tee_shm *shm = NULL;
-+ phys_addr_t pa = 0;
-+ int rc = 0;
-+
-+ p->attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT +
-+ attr - OPTEE_MSG_ATTR_TYPE_TMEM_INPUT;
-+ p->u.memref.size = mp->u.tmem.size;
-+ shm = (struct tee_shm *)(unsigned long)mp->u.tmem.shm_ref;
-+ if (!shm) {
-+ p->u.memref.shm_offs = 0;
-+ p->u.memref.shm = NULL;
-+ return 0;
-+ }
-+
-+ rc = tee_shm_get_pa(shm, 0, &pa);
-+ if (rc)
-+ return rc;
-+
-+ p->u.memref.shm_offs = mp->u.tmem.buf_ptr - pa;
-+ p->u.memref.shm = shm;
-+
-+ /* Check that the memref is covered by the shm object */
-+ if (p->u.memref.size) {
-+ size_t o = p->u.memref.shm_offs +
-+ p->u.memref.size - 1;
-+
-+ rc = tee_shm_get_pa(shm, o, NULL);
-+ if (rc)
-+ return rc;
-+ }
-+
-+ return 0;
-+}
-+
-+static void from_msg_param_reg_mem(struct tee_param *p, u32 attr,
-+ const struct optee_msg_param *mp)
-+{
-+ struct tee_shm *shm = NULL;
-+
-+ p->attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT +
-+ attr - OPTEE_MSG_ATTR_TYPE_RMEM_INPUT;
-+ p->u.memref.size = mp->u.rmem.size;
-+ shm = (struct tee_shm *)(unsigned long) mp->u.rmem.shm_ref;
-+
-+ if (shm) {
-+ p->u.memref.shm_offs = mp->u.rmem.offs;
-+ p->u.memref.shm = shm;
-+ } else {
-+ p->u.memref.shm_offs = 0;
-+ p->u.memref.shm = NULL;
-+ }
-+}
-+
- /**
- * optee_from_msg_param() - convert from OPTEE_MSG parameters to
- * struct tee_param
-@@ -33,13 +180,12 @@
- * @msg_params: OPTEE_MSG parameters
- * Returns 0 on success or <0 on failure
- */
--int optee_from_msg_param(struct tee_param *params, size_t num_params,
-- const struct optee_msg_param *msg_params)
-+static int optee_from_msg_param(struct optee *optee, struct tee_param *params,
-+ size_t num_params,
-+ const struct optee_msg_param *msg_params)
- {
-- int rc;
-- size_t n;
-- struct tee_shm *shm;
-- phys_addr_t pa;
-+ size_t n = 0;
-+ int rc = 0;
-
- for (n = 0; n < num_params; n++) {
- struct tee_param *p = params + n;
-@@ -54,58 +200,19 @@ int optee_from_msg_param(struct tee_param *params, size_t num_params,
- case OPTEE_MSG_ATTR_TYPE_VALUE_INPUT:
- case OPTEE_MSG_ATTR_TYPE_VALUE_OUTPUT:
- case OPTEE_MSG_ATTR_TYPE_VALUE_INOUT:
-- p->attr = TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT +
-- attr - OPTEE_MSG_ATTR_TYPE_VALUE_INPUT;
-- p->u.value.a = mp->u.value.a;
-- p->u.value.b = mp->u.value.b;
-- p->u.value.c = mp->u.value.c;
-+ from_msg_param_value(p, attr, mp);
- break;
- case OPTEE_MSG_ATTR_TYPE_TMEM_INPUT:
- case OPTEE_MSG_ATTR_TYPE_TMEM_OUTPUT:
- case OPTEE_MSG_ATTR_TYPE_TMEM_INOUT:
-- p->attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT +
-- attr - OPTEE_MSG_ATTR_TYPE_TMEM_INPUT;
-- p->u.memref.size = mp->u.tmem.size;
-- shm = (struct tee_shm *)(unsigned long)
-- mp->u.tmem.shm_ref;
-- if (!shm) {
-- p->u.memref.shm_offs = 0;
-- p->u.memref.shm = NULL;
-- break;
-- }
-- rc = tee_shm_get_pa(shm, 0, &pa);
-+ rc = from_msg_param_tmp_mem(p, attr, mp);
- if (rc)
- return rc;
-- p->u.memref.shm_offs = mp->u.tmem.buf_ptr - pa;
-- p->u.memref.shm = shm;
--
-- /* Check that the memref is covered by the shm object */
-- if (p->u.memref.size) {
-- size_t o = p->u.memref.shm_offs +
-- p->u.memref.size - 1;
--
-- rc = tee_shm_get_pa(shm, o, NULL);
-- if (rc)
-- return rc;
-- }
- break;
- case OPTEE_MSG_ATTR_TYPE_RMEM_INPUT:
- case OPTEE_MSG_ATTR_TYPE_RMEM_OUTPUT:
- case OPTEE_MSG_ATTR_TYPE_RMEM_INOUT:
-- p->attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT +
-- attr - OPTEE_MSG_ATTR_TYPE_RMEM_INPUT;
-- p->u.memref.size = mp->u.rmem.size;
-- shm = (struct tee_shm *)(unsigned long)
-- mp->u.rmem.shm_ref;
--
-- if (!shm) {
-- p->u.memref.shm_offs = 0;
-- p->u.memref.shm = NULL;
-- break;
-- }
-- p->u.memref.shm_offs = mp->u.rmem.offs;
-- p->u.memref.shm = shm;
--
-+ from_msg_param_reg_mem(p, attr, mp);
- break;
-
- default:
-@@ -115,11 +222,21 @@ int optee_from_msg_param(struct tee_param *params, size_t num_params,
- return 0;
- }
-
-+static void to_msg_param_value(struct optee_msg_param *mp,
-+ const struct tee_param *p)
-+{
-+ mp->attr = OPTEE_MSG_ATTR_TYPE_VALUE_INPUT + p->attr -
-+ TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT;
-+ mp->u.value.a = p->u.value.a;
-+ mp->u.value.b = p->u.value.b;
-+ mp->u.value.c = p->u.value.c;
-+}
-+
- static int to_msg_param_tmp_mem(struct optee_msg_param *mp,
- const struct tee_param *p)
- {
-- int rc;
-- phys_addr_t pa;
-+ phys_addr_t pa = 0;
-+ int rc = 0;
-
- mp->attr = OPTEE_MSG_ATTR_TYPE_TMEM_INPUT + p->attr -
- TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT;
-@@ -162,11 +279,12 @@ static int to_msg_param_reg_mem(struct optee_msg_param *mp,
- * @params: subsystem itnernal parameter representation
- * Returns 0 on success or <0 on failure
- */
--int optee_to_msg_param(struct optee_msg_param *msg_params, size_t num_params,
-- const struct tee_param *params)
-+static int optee_to_msg_param(struct optee *optee,
-+ struct optee_msg_param *msg_params,
-+ size_t num_params, const struct tee_param *params)
- {
-- int rc;
-- size_t n;
-+ size_t n = 0;
-+ int rc = 0;
-
- for (n = 0; n < num_params; n++) {
- const struct tee_param *p = params + n;
-@@ -180,11 +298,7 @@ int optee_to_msg_param(struct optee_msg_param *msg_params, size_t num_params,
- case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT:
- case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_OUTPUT:
- case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INOUT:
-- mp->attr = OPTEE_MSG_ATTR_TYPE_VALUE_INPUT + p->attr -
-- TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT;
-- mp->u.value.a = p->u.value.a;
-- mp->u.value.b = p->u.value.b;
-- mp->u.value.c = p->u.value.c;
-+ to_msg_param_value(mp, p);
- break;
- case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT:
- case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT:
-@@ -203,6 +317,137 @@ int optee_to_msg_param(struct optee_msg_param *msg_params, size_t num_params,
- return 0;
- }
-
-+#ifdef CONFIG_ARM_FFA_TRANSPORT
-+static void from_msg_param_ffa_mem(struct optee *optee, struct tee_param *p,
-+ u32 attr, const struct optee_msg_param *mp)
-+{
-+ struct tee_shm *shm = NULL;
-+ u64 offs_high = 0;
-+ u64 offs_low = 0;
-+
-+ p->attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT +
-+ attr - OPTEE_MSG_ATTR_TYPE_SMEM_INPUT;
-+ p->u.memref.size = mp->u.smem.size;
-+ shm = optee_shm_from_ffa_handle(optee, mp->u.smem.global_id);
-+ p->u.memref.shm = shm;
-+ if (shm) {
-+ offs_low = mp->u.smem.offs_low;
-+ offs_high = mp->u.smem.offs_high;
-+ }
-+ p->u.memref.shm_offs = offs_low | offs_high << 32;
-+}
-+
-+/**
-+ * optee_ffa_from_msg_param() - convert from OPTEE_MSG parameters to
-+ * struct tee_param
-+ * @params: subsystem internal parameter representation
-+ * @num_params: number of elements in the parameter arrays
-+ * @msg_params: OPTEE_MSG parameters
-+ * Returns 0 on success or <0 on failure
-+ */
-+static int optee_ffa_from_msg_param(struct optee *optee,
-+ struct tee_param *params,
-+ size_t num_params,
-+ const struct optee_msg_param *msg_params)
-+{
-+ size_t n = 0;
-+
-+ for (n = 0; n < num_params; n++) {
-+ struct tee_param *p = params + n;
-+ const struct optee_msg_param *mp = msg_params + n;
-+ u32 attr = mp->attr & OPTEE_MSG_ATTR_TYPE_MASK;
-+
-+ switch (attr) {
-+ case OPTEE_MSG_ATTR_TYPE_NONE:
-+ p->attr = TEE_IOCTL_PARAM_ATTR_TYPE_NONE;
-+ memset(&p->u, 0, sizeof(p->u));
-+ break;
-+ case OPTEE_MSG_ATTR_TYPE_VALUE_INPUT:
-+ case OPTEE_MSG_ATTR_TYPE_VALUE_OUTPUT:
-+ case OPTEE_MSG_ATTR_TYPE_VALUE_INOUT:
-+ from_msg_param_value(p, attr, mp);
-+ break;
-+ case OPTEE_MSG_ATTR_TYPE_SMEM_INPUT:
-+ case OPTEE_MSG_ATTR_TYPE_SMEM_OUTPUT:
-+ case OPTEE_MSG_ATTR_TYPE_SMEM_INOUT:
-+ from_msg_param_ffa_mem(optee, p, attr, mp);
-+ break;
-+ default:
-+ return -EINVAL;
-+ }
-+ }
-+ return 0;
-+}
-+
-+static int to_msg_param_ffa_mem(struct optee_msg_param *mp,
-+ const struct tee_param *p)
-+{
-+ struct tee_shm *shm = p->u.memref.shm;
-+
-+ mp->attr = OPTEE_MSG_ATTR_TYPE_SMEM_INPUT + p->attr -
-+ TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT;
-+
-+ if (shm) {
-+ u64 shm_offs = p->u.memref.shm_offs;
-+
-+ mp->u.smem.internal_offs = shm->offset;
-+
-+ mp->u.smem.offs_low = shm_offs;
-+ mp->u.smem.offs_high = shm_offs >> 32;
-+ /* Check that the entire offset could be stored. */
-+ if (mp->u.smem.offs_high != shm_offs >> 32)
-+ return -EINVAL;
-+
-+ mp->u.smem.global_id = shm->sec_world_id;
-+ } else {
-+ memset(&mp->u, 0, sizeof(mp->u));
-+ }
-+ mp->u.smem.size = p->u.memref.size;
-+ return 0;
-+}
-+
-+/**
-+ * optee_to_msg_param() - convert from struct tee_params to OPTEE_MSG parameters
-+ * @msg_params: OPTEE_MSG parameters
-+ * @num_params: number of elements in the parameter arrays
-+ * @params: subsystem itnernal parameter representation
-+ * Returns 0 on success or <0 on failure
-+ */
-+static int optee_ffa_to_msg_param(struct optee *optee,
-+ struct optee_msg_param *msg_params,
-+ size_t num_params,
-+ const struct tee_param *params)
-+{
-+ size_t n;
-+
-+ for (n = 0; n < num_params; n++) {
-+ const struct tee_param *p = params + n;
-+ struct optee_msg_param *mp = msg_params + n;
-+
-+ switch (p->attr) {
-+ case TEE_IOCTL_PARAM_ATTR_TYPE_NONE:
-+ mp->attr = TEE_IOCTL_PARAM_ATTR_TYPE_NONE;
-+ memset(&mp->u, 0, sizeof(mp->u));
-+ break;
-+ case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT:
-+ case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_OUTPUT:
-+ case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INOUT:
-+ to_msg_param_value(mp, p);
-+ break;
-+ case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT:
-+ case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT:
-+ case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INOUT:
-+ if (to_msg_param_ffa_mem(mp, p))
-+ return -EINVAL;
-+ break;
-+ default:
-+ return -EINVAL;
-+ }
-+ }
-+ return 0;
-+}
-+#endif /*CONFIG_ARM_FFA_TRANSPORT*/
-+
- static void optee_get_version(struct tee_device *teedev,
- struct tee_ioctl_version_data *vers)
- {
-@@ -218,6 +463,17 @@ static void optee_get_version(struct tee_device *teedev,
- *vers = v;
- }
-
-+static void optee_ffa_get_version(struct tee_device *teedev,
-+ struct tee_ioctl_version_data *vers)
-+{
-+ struct tee_ioctl_version_data v = {
-+ .impl_id = TEE_IMPL_ID_OPTEE,
-+ .impl_caps = TEE_OPTEE_CAP_TZ,
-+ .gen_caps = TEE_GEN_CAP_GP | TEE_GEN_CAP_REG_MEM,
-+ };
-+ *vers = v;
-+}
-+
- static int optee_open(struct tee_context *ctx)
- {
- struct optee_context_data *ctxdata;
-@@ -250,57 +506,41 @@ static int optee_open(struct tee_context *ctx)
- return 0;
- }
-
--static void optee_release(struct tee_context *ctx)
-+static void optee_release_helper(struct tee_context *ctx,
-+ int (*close_session)(struct tee_context *ctx,
-+ u32 session))
- {
- struct optee_context_data *ctxdata = ctx->data;
-- struct tee_device *teedev = ctx->teedev;
-- struct optee *optee = tee_get_drvdata(teedev);
-- struct tee_shm *shm;
-- struct optee_msg_arg *arg = NULL;
-- phys_addr_t parg;
- struct optee_session *sess;
- struct optee_session *sess_tmp;
-
- if (!ctxdata)
- return;
-
-- shm = tee_shm_alloc(ctx, sizeof(struct optee_msg_arg), TEE_SHM_MAPPED);
-- if (!IS_ERR(shm)) {
-- arg = tee_shm_get_va(shm, 0);
-- /*
-- * If va2pa fails for some reason, we can't call into
-- * secure world, only free the memory. Secure OS will leak
-- * sessions and finally refuse more sessions, but we will
-- * at least let normal world reclaim its memory.
-- */
-- if (!IS_ERR(arg))
-- if (tee_shm_va2pa(shm, arg, &parg))
-- arg = NULL; /* prevent usage of parg below */
-- }
--
- list_for_each_entry_safe(sess, sess_tmp, &ctxdata->sess_list,
- list_node) {
- list_del(&sess->list_node);
-- if (!IS_ERR_OR_NULL(arg)) {
-- memset(arg, 0, sizeof(*arg));
-- arg->cmd = OPTEE_MSG_CMD_CLOSE_SESSION;
-- arg->session = sess->session_id;
-- optee_do_call_with_arg(ctx, parg);
-- }
-+ close_session(ctx, sess->session_id);
- kfree(sess);
- }
- kfree(ctxdata);
-+ ctx->data = NULL;
-+}
-
-- if (!IS_ERR(shm))
-- tee_shm_free(shm);
-+static void optee_release(struct tee_context *ctx)
-+{
-+ optee_release_helper(ctx, optee_close_session_helper);
-+}
-
-- ctx->data = NULL;
-+static void optee_release_supp(struct tee_context *ctx)
-+{
-+ struct optee *optee = tee_get_drvdata(ctx->teedev);
-
-- if (teedev == optee->supp_teedev)
-- optee_supp_release(&optee->supp);
-+ optee_release_helper(ctx, optee_close_session_helper);
-+ optee_supp_release(&optee->supp);
- }
-
--static const struct tee_driver_ops optee_ops = {
-+static const struct tee_driver_ops optee_legacy_clnt_ops = {
- .get_version = optee_get_version,
- .open = optee_open,
- .release = optee_release,
-@@ -312,29 +552,36 @@ static const struct tee_driver_ops optee_ops = {
- .shm_unregister = optee_shm_unregister,
- };
-
--static const struct tee_desc optee_desc = {
-- .name = DRIVER_NAME "-clnt",
-- .ops = &optee_ops,
-+static const struct tee_desc optee_legacy_clnt_desc = {
-+ .name = DRIVER_NAME "legacy-clnt",
-+ .ops = &optee_legacy_clnt_ops,
- .owner = THIS_MODULE,
- };
-
--static const struct tee_driver_ops optee_supp_ops = {
-+static const struct tee_driver_ops optee_legacy_supp_ops = {
- .get_version = optee_get_version,
- .open = optee_open,
-- .release = optee_release,
-+ .release = optee_release_supp,
- .supp_recv = optee_supp_recv,
- .supp_send = optee_supp_send,
- .shm_register = optee_shm_register_supp,
- .shm_unregister = optee_shm_unregister_supp,
- };
-
--static const struct tee_desc optee_supp_desc = {
-- .name = DRIVER_NAME "-supp",
-- .ops = &optee_supp_ops,
-+static const struct tee_desc optee_legacy_supp_desc = {
-+ .name = DRIVER_NAME "legacy-supp",
-+ .ops = &optee_legacy_supp_ops,
- .owner = THIS_MODULE,
- .flags = TEE_DESC_PRIVILEGED,
- };
-
-+static const struct optee_ops optee_legacy_ops = {
-+ .do_call_with_arg = optee_do_call_with_arg,
-+ .to_msg_param = optee_to_msg_param,
-+ .from_msg_param = optee_from_msg_param,
-+};
-+
-+
- static bool optee_msg_api_uid_is_optee_api(optee_invoke_fn *invoke_fn)
- {
- struct arm_smccc_res res;
-@@ -534,16 +781,9 @@ static void optee_smccc_hvc(unsigned long a0, unsigned long a1,
- arm_smccc_hvc(a0, a1, a2, a3, a4, a5, a6, a7, res);
- }
-
--static optee_invoke_fn *get_invoke_func(struct device_node *np)
-+static optee_invoke_fn *get_invoke_func(const char *method)
- {
-- const char *method;
-
-- pr_info("probing for conduit method from DT.\n");
--
-- if (of_property_read_string(np, "method", &method)) {
-- pr_warn("missing \"method\" property\n");
-- return ERR_PTR(-ENXIO);
-- }
-
- if (!strcmp("hvc", method))
- return optee_smccc_hvc;
-@@ -554,7 +794,7 @@ static optee_invoke_fn *get_invoke_func(struct device_node *np)
- return ERR_PTR(-EINVAL);
- }
-
--static struct optee *optee_probe(struct device_node *np)
-+static struct optee *optee_probe_legacy(const char *method)
- {
- optee_invoke_fn *invoke_fn;
- struct tee_shm_pool *pool = ERR_PTR(-EINVAL);
-@@ -564,7 +804,7 @@ static struct optee *optee_probe(struct device_node *np)
- u32 sec_caps;
- int rc;
-
-- invoke_fn = get_invoke_func(np);
-+ invoke_fn = get_invoke_func(method);
- if (IS_ERR(invoke_fn))
- return (void *)invoke_fn;
-
-@@ -606,17 +846,18 @@ static struct optee *optee_probe(struct device_node *np)
- goto err;
- }
-
-+ optee->ops = &optee_legacy_ops;
- optee->invoke_fn = invoke_fn;
- optee->sec_caps = sec_caps;
-
-- teedev = tee_device_alloc(&optee_desc, NULL, pool, optee);
-+ teedev = tee_device_alloc(&optee_legacy_clnt_desc, NULL, pool, optee);
- if (IS_ERR(teedev)) {
- rc = PTR_ERR(teedev);
- goto err;
- }
- optee->teedev = teedev;
-
-- teedev = tee_device_alloc(&optee_supp_desc, NULL, pool, optee);
-+ teedev = tee_device_alloc(&optee_legacy_supp_desc, NULL, pool, optee);
- if (IS_ERR(teedev)) {
- rc = PTR_ERR(teedev);
- goto err;
-@@ -662,6 +903,266 @@ static struct optee *optee_probe(struct device_node *np)
- return ERR_PTR(rc);
- }
-
-+#ifdef CONFIG_ARM_FFA_TRANSPORT
-+static bool optee_ffa_api_is_compatbile(struct ffa_ops *ffa_ops, u32 dst)
-+{
-+ struct arm_smcccv1_2_return ret = { };
-+
-+ ret = ffa_ops->sync_msg_send(dst, OPTEE_FFA_GET_API_VERSION,
-+ 0, 0, 0, 0);
-+ if (ret.arg0 != FFA_SUCCESS) {
-+ pr_err("Unexpected return fid 0x%llx", ret.arg0);
-+ return false;
-+ }
-+ if (ret.arg3 != OPTEE_FFA_VERSION_MAJOR ||
-+ ret.arg4 < OPTEE_FFA_VERSION_MINOR) {
-+ pr_err("Incompatible OP-TEE API version %llu.%llu",
-+ ret.arg3, ret.arg4);
-+ return false;
-+ }
-+
-+ ret = ffa_ops->sync_msg_send(dst, OPTEE_FFA_GET_OS_VERSION,
-+ 0, 0, 0, 0);
-+ if (ret.arg0) {
-+ pr_err("Unexpected error 0x%llx", ret.arg0);
-+ return false;
-+ }
-+ if (ret.arg5)
-+ pr_info("revision %llu.%llu (%08llx)",
-+ ret.arg3, ret.arg4, ret.arg5);
-+ else
-+ pr_info("revision %llu.%llu", ret.arg3, ret.arg4);
-+
-+ return true;
-+}
-+
-+static bool optee_ffa_exchange_caps(struct ffa_ops *ffa_ops, u32 dst,
-+ u32 *sec_caps)
-+{
-+ struct arm_smcccv1_2_return ret = { };
-+
-+ ret = ffa_ops->sync_msg_send(dst, OPTEE_FFA_EXCHANGE_CAPABILITIES,
-+ 0, 0, 0, 0);
-+ if (ret.arg0) {
-+ pr_err("Unexpected error 0x%llx", ret.arg0);
-+ return false;
-+ }
-+
-+ *sec_caps = 0;
-+
-+ return true;
-+}
-+
-+static struct tee_shm_pool *optee_ffa_config_dyn_shm(void)
-+{
-+ struct tee_shm_pool_mgr *priv_mgr;
-+ struct tee_shm_pool_mgr *dmabuf_mgr;
-+ void *rc;
-+
-+ rc = optee_ffa_shm_pool_alloc_pages();
-+ if (IS_ERR(rc))
-+ return rc;
-+ priv_mgr = rc;
-+
-+ rc = optee_ffa_shm_pool_alloc_pages();
-+ if (IS_ERR(rc)) {
-+ tee_shm_pool_mgr_destroy(priv_mgr);
-+ return rc;
-+ }
-+ dmabuf_mgr = rc;
-+
-+ rc = tee_shm_pool_alloc(priv_mgr, dmabuf_mgr);
-+ if (IS_ERR(rc)) {
-+ tee_shm_pool_mgr_destroy(priv_mgr);
-+ tee_shm_pool_mgr_destroy(dmabuf_mgr);
-+ }
-+
-+ return rc;
-+}
-+
-+static const struct tee_driver_ops optee_ffa_clnt_ops = {
-+ .get_version = optee_ffa_get_version,
-+ .open = optee_open,
-+ .release = optee_release,
-+ .open_session = optee_open_session,
-+ .close_session = optee_close_session,
-+ .invoke_func = optee_invoke_func,
-+ .cancel_req = optee_cancel_req,
-+ .shm_register = optee_ffa_shm_register,
-+ .shm_unregister = optee_ffa_shm_unregister,
-+};
-+
-+static const struct tee_desc optee_ffa_clnt_desc = {
-+ .name = DRIVER_NAME "ffa-clnt",
-+ .ops = &optee_ffa_clnt_ops,
-+ .owner = THIS_MODULE,
-+};
-+
-+static const struct tee_driver_ops optee_ffa_supp_ops = {
-+ .get_version = optee_ffa_get_version,
-+ .open = optee_open,
-+ .release = optee_release_supp,
-+ .supp_recv = optee_supp_recv,
-+ .supp_send = optee_supp_send,
-+ .shm_register = optee_ffa_shm_register, /* same as for clnt ops */
-+ .shm_unregister = optee_ffa_shm_unregister_supp,
-+};
-+
-+static const struct tee_desc optee_ffa_supp_desc = {
-+ .name = DRIVER_NAME "ffa-supp",
-+ .ops = &optee_ffa_supp_ops,
-+ .owner = THIS_MODULE,
-+ .flags = TEE_DESC_PRIVILEGED,
-+};
-+
-+static const struct optee_ops optee_ffa_ops = {
-+ .do_call_with_arg = optee_ffa_do_call_with_arg,
-+ .to_msg_param = optee_ffa_to_msg_param,
-+ .from_msg_param = optee_ffa_from_msg_param,
-+};
-+
-+static struct optee *optee_probe_ffa(void)
-+{
-+ struct tee_device *teedev = NULL;
-+ struct ffa_ops *ffa_ops = NULL;
-+ struct optee *optee = NULL;
-+ struct ffa_partition_info *partition_info = NULL;
-+ u32 ffa_dst = 0;
-+ u32 sec_caps = 0;
-+ int count = 0;
-+ int rc = 0;
-+
-+ ffa_ops = get_ffa_ops();
-+ if (!ffa_ops) {
-+ pr_warn("failed \"method\" init: ffa\n");
-+ return ERR_PTR(-ENOENT);
-+ }
-+ /* Use OPTEE UUID to retrieve partition ID. */
-+ count = ffa_ops->partition_info_get(OPTEE_MSG_OS_OPTEE_UUID_0,
-+ OPTEE_MSG_OS_OPTEE_UUID_1,
-+ OPTEE_MSG_OS_OPTEE_UUID_2,
-+ OPTEE_MSG_OS_OPTEE_UUID_3,
-+ &partition_info);
-+
-+ /* If count is negative propergate the error code. */
-+ if (count < 0) {
-+ return ERR_PTR(count);
-+ }
-+ /*
-+ * If the function returned sucessfully we must ensure to free the
-+ * allocated memory before exiting.
-+ */
-+
-+ /* Check only a single patition is found.*/
-+ /* TODO: Add support for dealing with multiple partitions. */
-+ if (count > SUPPORTED_OPTEE_PARTITIONS) {
-+ kfree(partition_info);
-+ return ERR_PTR(-EINVAL);
-+ }
-+ ffa_dst = partition_info[0].id;
-+ kfree(partition_info);
-+
-+ if (!optee_ffa_api_is_compatbile(ffa_ops, ffa_dst))
-+ return ERR_PTR(-EINVAL);
-+
-+ if (!optee_ffa_exchange_caps(ffa_ops, ffa_dst, &sec_caps))
-+ return ERR_PTR(-EINVAL);
-+
-+ optee = kzalloc(sizeof(*optee), GFP_KERNEL);
-+ if (!optee) {
-+ rc = -ENOMEM;
-+ goto err;
-+ }
-+ optee->pool = optee_ffa_config_dyn_shm();
-+ if (IS_ERR(optee->pool)) {
-+ rc = PTR_ERR(optee->pool);
-+ optee->pool = NULL;
-+ goto err;
-+ }
-+
-+ optee->ops = &optee_ffa_ops;
-+ optee->ffa.ops = ffa_ops;
-+ optee->ffa.dst = ffa_dst;
-+ optee->sec_caps = sec_caps;
-+
-+ teedev = tee_device_alloc(&optee_ffa_clnt_desc, NULL, optee->pool,
-+ optee);
-+ if (IS_ERR(teedev)) {
-+ rc = PTR_ERR(teedev);
-+ goto err;
-+ }
-+ optee->teedev = teedev;
-+
-+ teedev = tee_device_alloc(&optee_ffa_supp_desc, NULL, optee->pool,
-+ optee);
-+ if (IS_ERR(teedev)) {
-+ rc = PTR_ERR(teedev);
-+ goto err;
-+ }
-+ optee->supp_teedev = teedev;
-+
-+ rc = tee_device_register(optee->teedev);
-+ if (rc)
-+ goto err;
-+
-+ rc = tee_device_register(optee->supp_teedev);
-+ if (rc)
-+ goto err;
-+
-+ rc = rhashtable_init(&optee->ffa.global_ids, &shm_rhash_params);
-+ if (rc)
-+ goto err;
-+ mutex_init(&optee->ffa.mutex);
-+ mutex_init(&optee->call_queue.mutex);
-+ INIT_LIST_HEAD(&optee->call_queue.waiters);
-+ optee_wait_queue_init(&optee->wait_queue);
-+ optee_supp_init(&optee->supp);
-+
-+ return optee;
-+err:
-+ /*
-+ * tee_device_unregister() is safe to call even if the
-+ * devices hasn't been registered with
-+ * tee_device_register() yet.
-+ */
-+ tee_device_unregister(optee->supp_teedev);
-+ tee_device_unregister(optee->teedev);
-+ if (optee->pool)
-+ tee_shm_pool_free(optee->pool);
-+ kfree(optee);
-+ return ERR_PTR(rc);
-+}
-+#endif /*CONFIG_ARM_FFA_TRANSPORT*/
-+
-+static const char *get_conduit_method(struct device_node *np)
-+{
-+ const char *method = NULL;
-+
-+ pr_info("probing for conduit method from DT.\n");
-+
-+ if (of_property_read_string(np, "method", &method)) {
-+ pr_warn("missing \"method\" property\n");
-+ return NULL;
-+ }
-+
-+ return method;
-+}
-+
-+static struct optee *optee_probe(struct device_node *np)
-+{
-+ const char *method = get_conduit_method(np);
-+
-+ if (!method)
-+ return ERR_PTR(-ENXIO);
-+
-+#ifdef CONFIG_ARM_FFA_TRANSPORT
-+ if (!strcmp(method, "ffa"))
-+ return optee_probe_ffa();
-+#endif /*CONFIG_ARM_FFA_TRANSPORT*/
-+
-+ return optee_probe_legacy(method);
-+}
-+
- static void optee_remove(struct optee *optee)
- {
- /*
-@@ -669,7 +1170,10 @@ static void optee_remove(struct optee *optee)
- * reference counters and also avoid wild pointers in secure world
- * into the old shared memory range.
- */
-- optee_disable_shm_cache(optee);
-+ if (optee->invoke_fn)
-+ optee_disable_shm_cache(optee);
-+ else
-+ optee_ffa_disable_shm_cache(optee);
-
- /*
- * The two devices has to be unregistered before we can free the
-@@ -684,6 +1188,13 @@ static void optee_remove(struct optee *optee)
- optee_wait_queue_exit(&optee->wait_queue);
- optee_supp_uninit(&optee->supp);
- mutex_destroy(&optee->call_queue.mutex);
-+#ifdef CONFIG_ARM_FFA_TRANSPORT
-+ if (optee->ffa.ops) {
-+ mutex_destroy(&optee->ffa.mutex);
-+ rhashtable_free_and_destroy(&optee->ffa.global_ids,
-+ rh_free_fn, NULL);
-+ }
-+#endif /*CONFIG_ARM_FFA_TRANSPORT*/
-
- kfree(optee);
- }
-diff --git a/drivers/tee/optee/optee_ffa.h b/drivers/tee/optee/optee_ffa.h
-new file mode 100644
-index 000000000000..768e056ab491
---- /dev/null
-+++ b/drivers/tee/optee/optee_ffa.h
-@@ -0,0 +1,201 @@
-+/* SPDX-License-Identifier: BSD-2-Clause */
-+/*
-+ * Copyright (c) 2019, Linaro Limited
-+ */
-+
-+/*
-+ * This file is exported by OP-TEE and is in kept in sync between secure
-+ * world and normal world kernel driver. We're using ARM FF-A 1.0 EAC
-+ * specification.
-+ */
-+
-+#ifndef __OPTEE_FFA_H
-+#define __OPTEE_FFA_H
-+
-+#include <linux/arm_ffa.h>
-+
-+/*
-+ * Normal world sends requests with FFA_MSG_SEND_DIRECT_REQ and
-+ * responses are returned with FFA_MSG_SEND_DIRECT_RESP for normal
-+ * messages.
-+ *
-+ * All requests with FFA_MSG_SEND_DIRECT_REQ and FFA_MSG_SEND_DIRECT_RESP
-+ * are using the AArch32 SMC calling convention with register usage as
-+ * defined in FF-A specification:
-+ * w0: Function ID (0x8400006F or 0x84000070)
-+ * w1: Source/Destination IDs
-+ * w2: Reserved (MBZ)
-+ * w3-w7: Implementation defined, free to be used below
-+ */
-+
-+#define OPTEE_FFA_VERSION_MAJOR 1
-+#define OPTEE_FFA_VERSION_MINOR 0
-+
-+#define OPTEE_FFA_BLOCKING_CALL(id) (id)
-+#define OPTEE_FFA_YIELDING_CALL_BIT 31
-+#define OPTEE_FFA_YIELDING_CALL(id) ((id) | BIT(OPTEE_FFA_YIELDING_CALL_BIT))
-+
-+/*
-+ * Returns the API version implemented, currently follows the FF-A version.
-+ * Call register usage:
-+ * w3: Service ID, OPTEE_FFA_GET_API_VERSION
-+ * w4-w7: Not used (MBZ)
-+ *
-+ * Return register usage:
-+ * w3: OPTEE_FFA_VERSION_MAJOR
-+ * w4: OPTEE_FFA_VERSION_MINOR
-+ * w5-w7: Not used (MBZ)
-+ */
-+#define OPTEE_FFA_GET_API_VERSION OPTEE_FFA_BLOCKING_CALL(0)
-+
-+/*
-+ * Returns the revision of OP-TEE.
-+ *
-+ * Used by non-secure world to figure out which version of the Trusted OS
-+ * is installed. Note that the returned revision is the revision of the
-+ * Trusted OS, not of the API.
-+ *
-+ * Call register usage:
-+ * w3: Service ID, OPTEE_FFA_GET_OS_VERSION
-+ * w4-w7: Unused (MBZ)
-+ *
-+ * Return register usage:
-+ * w3: CFG_OPTEE_REVISION_MAJOR
-+ * w4: CFG_OPTEE_REVISION_MINOR
-+ * w5: TEE_IMPL_GIT_SHA1 (or zero if not supported)
-+ */
-+#define OPTEE_FFA_GET_OS_VERSION OPTEE_FFA_BLOCKING_CALL(1)
-+
-+/*
-+ * Exchange capabilities between normal world and secure world.
-+ *
-+ * Currently there are no defined capabilities. When features are added new
-+ * capabilities may be added.
-+ *
-+ * Call register usage:
-+ * w3: Service ID, OPTEE_FFA_EXCHANGE_CAPABILITIES
-+ * w4-w7: Note used (MBZ)
-+ *
-+ * Return register usage:
-+ * w3: Error code, 0 on success
-+ * w4: Bit[1:0]: Number of pages of shared memory to register with
-+ * OPTEE_FFA_REGISTER_RPC_SHM to support RPC
-+ * Bit[31:2]: Reserved (MBZ)
-+ * w5-w7: Note used (MBZ)
-+ */
-+#define OPTEE_FFA_EXCHANGE_CAPABILITIES OPTEE_FFA_BLOCKING_CALL(2)
-+
-+/*
-+ * Call with struct optee_msg_arg as argument in the supplied shared memory
-+ * with a zero internal offset and normal cached memory attributes.
-+ * Register usage:
-+ * w3: Service ID, OPTEE_FFA_YIELDING_CALL_WITH_ARG
-+ * w4: Shared memory handle, lower bits
-+ * w5: Shared memory handle, higher bits
-+ * w6: Offset into shared memory pointing to a struct optee_msg_arg
-+ * w7: Not used (MBZ)
-+ *
-+ * Call to register shared memory memory. The data is supplied in shared
-+ * memory with a zero internal offset and normal cached memory attributes.
-+ * The data is formatted as described in FFA 1.0 Beta1 Table 137 "
-+ * Descriptor to retrieve a donated, lent or shared memory region".
-+ * Register usage:
-+ * w3: Service ID, OPTEE_FFA_YIELDING_CALL_REGISTER_SHM
-+ * w4: Shared memory handle, lower bits
-+ * w5: Shared memory handle, higher bits
-+ * w6-w7: Not used (MBZ)
-+ *
-+ * Call unregister shared memory register usage:
-+ * w3: Service ID, OPTEE_FFA_YIELDING_CALL_UNREGISTER_SHM
-+ * w4: Shared memory handle, lower bits
-+ * w5: Shared memory handle, higher bits
-+ * w6-w7: Not used (MBZ)
-+ *
-+ * Resume from RPC register usage:
-+ * w3: Service ID, OPTEE_FFA_YIELDING_CALL_RESUME
-+ * If returning from OPTEE_FFA_YIELDING_CALL_RETURN_ALLOC_SHM:
-+ * w4: Shared memory handle, lower bits
-+ * w5: Shared memory handle, higher bits
-+ * If the allocation failed both w4 and w5 are 0
-+ * w6: Offset into shared memory pointing the table If internal
-+ * offset > 0 then one more page than requested has been allocated.
-+ * else if resuming from another RPC:
-+ * w4-w6: Not used (MBZ)
-+ * w7: Resume info
-+ *
-+ * Normal return (yielding call is completed) register usage:
-+ * w3: Error code, 0 on success
-+ * w4: OPTEE_FFA_YIELDING_CALL_RETURN_DONE
-+ * w5-w7: Not used (MBZ)
-+ *
-+ * Alloc SHM return (RPC from secure world) register usage:
-+ * w3: Error code == 0
-+ * w4: OPTEE_FFA_YIELDING_CALL_RETURN_ALLOC_KERN_SHM or
-+ * OPTEE_FFA_YIELDING_CALL_RETURN_ALLOC_SUPPL_SHM
-+ * allocate kernel private or supplicant memory respectively.
-+ * w5: Number of pages of shared memory
-+ * w6: Not used (MBZ)
-+ * w7: Resume info
-+ *
-+ * Free SHM return (RPC from secure world) register usage:
-+ * w3: Error code == 0
-+ * w4: OPTEE_FFA_YIELDING_CALL_RETURN_FREE_KERN_SHM or
-+ * OPTEE_FFA_YIELDING_CALL_RETURN_FREE_SUPPL_SHM
-+ * free kernel private or supplicant memory respectively.
-+ * w5 Shared memory handle to free, lower bits
-+ * w6 Shared memory handle to free, higher bits
-+ * The handle previously allocated with
-+ * OPTEE_FFA_YIELDING_CALL_RETURN_ALLOC_KERN_SHM or
-+ * OPTEE_FFA_YIELDING_CALL_RETURN_ALLOC_SUPPL_SHM.
-+ * w7: Resume info
-+ *
-+ * RPC cmd return (RPC from secure world) register usage:
-+ * w3: Error code == 0
-+ * w4: OPTEE_FFA_YIELDING_CALL_RETURN_RPC_CMD
-+ * w5: Shared memory handle, lower bits
-+ * w6: Shared memory handle, higher bits
-+ * The handle contains aed the RPC.
-+ * w7: Resume info
-+ *
-+ * RPC interrupt return (RPC from secure world) register usage:
-+ * w3: Error code == 0
-+ * w4: OPTEE_FFA_YIELDING_CALL_RETURN_INTERRUPT
-+ * w5-w6: Not used (MBZ)
-+ * w7: Resume info
-+ *
-+ * Possible error codes in register w3:
-+ * 0: Success
-+ * FFA_DENIED: w4 isn't one of OPTEE_FFA_YIELDING_CALL_START
-+ * OPTEE_FFA_YIELDING_CALL_REGISTER_SHM,
-+ * OPTEE_FFA_YIELDING_CALL_UNREGISTER_SHM or
-+ * OPTEE_FFA_YIELDING_CALL_RESUME
-+ *
-+ * Possible error codes for OPTEE_FFA_YIELDING_CALL_START,
-+ * OPTEE_FFA_YIELDING_CALL_REGISTER_SHM and
-+ * OPTEE_FFA_YIELDING_CALL_UNREGISTER_SHM
-+ * FFA_BUSY: Number of OP-TEE OS threads exceeded,
-+ * try again later
-+ * FFA_DENIED: RPC shared memory object not found
-+ * FFA_INVALID_PARAMETER: Bad shared memory handle or offset into the memory
-+ *
-+ * Possible error codes for OPTEE_FFA_YIELDING_CALL_RESUME
-+ * FFA_INVALID_PARAMETER: Bad resume info
-+ *
-+ */
-+#define OPTEE_FFA_YIELDING_CALL_WITH_ARG OPTEE_FFA_YIELDING_CALL(0)
-+#define OPTEE_FFA_YIELDING_CALL_REGISTER_SHM OPTEE_FFA_YIELDING_CALL(1)
-+#define OPTEE_FFA_YIELDING_CALL_UNREGISTER_SHM OPTEE_FFA_YIELDING_CALL(2)
-+#define OPTEE_FFA_YIELDING_CALL_RESUME OPTEE_FFA_YIELDING_CALL(3)
-+
-+#define OPTEE_FFA_YIELDING_CALL_RETURN_DONE 0
-+#define OPTEE_FFA_YIELDING_CALL_RETURN_ALLOC_KERN_SHM 1
-+#define OPTEE_FFA_YIELDING_CALL_RETURN_ALLOC_SUPPL_SHM 2
-+#define OPTEE_FFA_YIELDING_CALL_RETURN_RESERVED0 3
-+#define OPTEE_FFA_YIELDING_CALL_RETURN_FREE_KERN_SHM 4
-+#define OPTEE_FFA_YIELDING_CALL_RETURN_FREE_SUPPL_SHM 5
-+#define OPTEE_FFA_YIELDING_CALL_RETURN_RESERVED1 6
-+#define OPTEE_FFA_YIELDING_CALL_RETURN_RPC_CMD 7
-+#define OPTEE_FFA_YIELDING_CALL_RETURN_INTERRUPT 8
-+
-+#endif /*__OPTEE_FFA_H*/
-+
-diff --git a/drivers/tee/optee/optee_msg.h b/drivers/tee/optee/optee_msg.h
-index 795bc19ae17a..95ee82c11733 100644
---- a/drivers/tee/optee/optee_msg.h
-+++ b/drivers/tee/optee/optee_msg.h
-@@ -1,6 +1,5 @@
--/* SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) */
- /*
-- * Copyright (c) 2015-2019, Linaro Limited
-+ * Copyright (c) 2015-2020, Linaro Limited
- */
- #ifndef _OPTEE_MSG_H
- #define _OPTEE_MSG_H
-@@ -11,12 +10,6 @@
- /*
- * This file defines the OP-TEE message protocol used to communicate
- * with an instance of OP-TEE running in secure world.
-- *
-- * This file is divided into three sections.
-- * 1. Formatting of messages.
-- * 2. Requests from normal world
-- * 3. Requests from secure world, Remote Procedure Call (RPC), handled by
-- * tee-supplicant.
- */
-
- /*****************************************************************************
-@@ -30,6 +23,9 @@
- #define OPTEE_MSG_ATTR_TYPE_RMEM_INPUT 0x5
- #define OPTEE_MSG_ATTR_TYPE_RMEM_OUTPUT 0x6
- #define OPTEE_MSG_ATTR_TYPE_RMEM_INOUT 0x7
-+#define OPTEE_MSG_ATTR_TYPE_SMEM_INPUT OPTEE_MSG_ATTR_TYPE_RMEM_INPUT
-+#define OPTEE_MSG_ATTR_TYPE_SMEM_OUTPUT OPTEE_MSG_ATTR_TYPE_RMEM_OUTPUT
-+#define OPTEE_MSG_ATTR_TYPE_SMEM_INOUT OPTEE_MSG_ATTR_TYPE_RMEM_INOUT
- #define OPTEE_MSG_ATTR_TYPE_TMEM_INPUT 0x9
- #define OPTEE_MSG_ATTR_TYPE_TMEM_OUTPUT 0xa
- #define OPTEE_MSG_ATTR_TYPE_TMEM_INOUT 0xb
-@@ -54,14 +50,14 @@
- * Every entry in buffer should point to a 4k page beginning (12 least
- * significant bits must be equal to zero).
- *
-- * 12 least significant bints of optee_msg_param.u.tmem.buf_ptr should hold page
-- * offset of the user buffer.
-+ * 12 least significant bits of optee_msg_param.u.tmem.buf_ptr should hold
-+ * page offset of user buffer.
- *
- * So, entries should be placed like members of this structure:
- *
- * struct page_data {
-- * uint64_t pages_array[OPTEE_MSG_NONCONTIG_PAGE_SIZE/sizeof(uint64_t) - 1];
-- * uint64_t next_page_data;
-+ * u64 pages_array[OPTEE_MSG_NONCONTIG_PAGE_SIZE/sizeof(u64) - 1];
-+ * u64 next_page_data;
- * };
- *
- * Structure is designed to exactly fit into the page size
-@@ -129,6 +125,23 @@ struct optee_msg_param_rmem {
- u64 shm_ref;
- };
-
-+/**
-+ * struct optee_msg_param_smem - ffa memory reference parameter
-+ * @offs_lower: Lower bits of offset into shared memory reference
-+ * @offs_upper: Upper bits of offset into shared memory reference
-+ * @internal_offs: Internal offset into the first page of shared memory
-+ * reference
-+ * @size: Size of the buffer
-+ * @global_id: Global identifier of Shared memory
-+ */
-+struct optee_msg_param_smem {
-+ u32 offs_low;
-+ u16 offs_high;
-+ u16 internal_offs;
-+ u64 size;
-+ u64 global_id;
-+};
-+
- /**
- * struct optee_msg_param_value - opaque value parameter
- *
-@@ -145,12 +158,14 @@ struct optee_msg_param_value {
- * @attr: attributes
- * @tmem: parameter by temporary memory reference
- * @rmem: parameter by registered memory reference
-+ * @smem: parameter by ffa registered memory reference
- * @value: parameter by opaque value
- *
- * @attr & OPTEE_MSG_ATTR_TYPE_MASK indicates if tmem, rmem or value is used in
- * the union. OPTEE_MSG_ATTR_TYPE_VALUE_* indicates value,
- * OPTEE_MSG_ATTR_TYPE_TMEM_* indicates @tmem and
-- * OPTEE_MSG_ATTR_TYPE_RMEM_* indicates @rmem,
-+ * OPTEE_MSG_ATTR_TYPE_RMEM_* or the alias PTEE_MSG_ATTR_TYPE_SMEM_* indicates
-+ * @rmem or @smem depending on the conduit.
- * OPTEE_MSG_ATTR_TYPE_NONE indicates that none of the members are used.
- */
- struct optee_msg_param {
-@@ -158,6 +173,7 @@ struct optee_msg_param {
- union {
- struct optee_msg_param_tmem tmem;
- struct optee_msg_param_rmem rmem;
-+ struct optee_msg_param_smem smem;
- struct optee_msg_param_value value;
- } u;
- };
-@@ -176,17 +192,9 @@ struct optee_msg_param {
- * @params: the parameters supplied to the OS Command
- *
- * All normal calls to Trusted OS uses this struct. If cmd requires further
-- * information than what these field holds it can be passed as a parameter
-+ * information than what these fields hold it can be passed as a parameter
- * tagged as meta (setting the OPTEE_MSG_ATTR_META bit in corresponding
-- * attrs field). All parameters tagged as meta has to come first.
-- *
-- * Temp memref parameters can be fragmented if supported by the Trusted OS
-- * (when optee_smc.h is bearer of this protocol this is indicated with
-- * OPTEE_SMC_SEC_CAP_UNREGISTERED_SHM). If a logical memref parameter is
-- * fragmented then has all but the last fragment the
-- * OPTEE_MSG_ATTR_FRAGMENT bit set in attrs. Even if a memref is fragmented
-- * it will still be presented as a single logical memref to the Trusted
-- * Application.
-+ * attrs field). All parameters tagged as meta have to come first.
- */
- struct optee_msg_arg {
- u32 cmd;
-@@ -199,7 +207,7 @@ struct optee_msg_arg {
- u32 num_params;
-
- /* num_params tells the actual number of element in params */
-- struct optee_msg_param params[0];
-+ struct optee_msg_param params[];
- };
-
- /**
-@@ -290,13 +298,10 @@ struct optee_msg_arg {
- * OPTEE_MSG_CMD_REGISTER_SHM registers a shared memory reference. The
- * information is passed as:
- * [in] param[0].attr OPTEE_MSG_ATTR_TYPE_TMEM_INPUT
-- * [| OPTEE_MSG_ATTR_FRAGMENT]
-+ * [| OPTEE_MSG_ATTR_NONCONTIG]
- * [in] param[0].u.tmem.buf_ptr physical address (of first fragment)
- * [in] param[0].u.tmem.size size (of first fragment)
- * [in] param[0].u.tmem.shm_ref holds shared memory reference
-- * ...
-- * The shared memory can optionally be fragmented, temp memrefs can follow
-- * each other with all but the last with the OPTEE_MSG_ATTR_FRAGMENT bit set.
- *
- * OPTEE_MSG_CMD_UNREGISTER_SHM unregisteres a previously registered shared
- * memory reference. The information is passed as:
-@@ -313,110 +318,4 @@ struct optee_msg_arg {
- #define OPTEE_MSG_CMD_UNREGISTER_SHM 5
- #define OPTEE_MSG_FUNCID_CALL_WITH_ARG 0x0004
-
--/*****************************************************************************
-- * Part 3 - Requests from secure world, RPC
-- *****************************************************************************/
--
--/*
-- * All RPC is done with a struct optee_msg_arg as bearer of information,
-- * struct optee_msg_arg::arg holds values defined by OPTEE_MSG_RPC_CMD_* below
-- *
-- * RPC communication with tee-supplicant is reversed compared to normal
-- * client communication desribed above. The supplicant receives requests
-- * and sends responses.
-- */
--
--/*
-- * Load a TA into memory, defined in tee-supplicant
-- */
--#define OPTEE_MSG_RPC_CMD_LOAD_TA 0
--
--/*
-- * Reserved
-- */
--#define OPTEE_MSG_RPC_CMD_RPMB 1
--
--/*
-- * File system access, defined in tee-supplicant
-- */
--#define OPTEE_MSG_RPC_CMD_FS 2
--
--/*
-- * Get time
-- *
-- * Returns number of seconds and nano seconds since the Epoch,
-- * 1970-01-01 00:00:00 +0000 (UTC).
-- *
-- * [out] param[0].u.value.a Number of seconds
-- * [out] param[0].u.value.b Number of nano seconds.
-- */
--#define OPTEE_MSG_RPC_CMD_GET_TIME 3
--
--/*
-- * Wait queue primitive, helper for secure world to implement a wait queue.
-- *
-- * If secure world need to wait for a secure world mutex it issues a sleep
-- * request instead of spinning in secure world. Conversely is a wakeup
-- * request issued when a secure world mutex with a thread waiting thread is
-- * unlocked.
-- *
-- * Waiting on a key
-- * [in] param[0].u.value.a OPTEE_MSG_RPC_WAIT_QUEUE_SLEEP
-- * [in] param[0].u.value.b wait key
-- *
-- * Waking up a key
-- * [in] param[0].u.value.a OPTEE_MSG_RPC_WAIT_QUEUE_WAKEUP
-- * [in] param[0].u.value.b wakeup key
-- */
--#define OPTEE_MSG_RPC_CMD_WAIT_QUEUE 4
--#define OPTEE_MSG_RPC_WAIT_QUEUE_SLEEP 0
--#define OPTEE_MSG_RPC_WAIT_QUEUE_WAKEUP 1
--
--/*
-- * Suspend execution
-- *
-- * [in] param[0].value .a number of milliseconds to suspend
-- */
--#define OPTEE_MSG_RPC_CMD_SUSPEND 5
--
--/*
-- * Allocate a piece of shared memory
-- *
-- * Shared memory can optionally be fragmented, to support that additional
-- * spare param entries are allocated to make room for eventual fragments.
-- * The spare param entries has .attr = OPTEE_MSG_ATTR_TYPE_NONE when
-- * unused. All returned temp memrefs except the last should have the
-- * OPTEE_MSG_ATTR_FRAGMENT bit set in the attr field.
-- *
-- * [in] param[0].u.value.a type of memory one of
-- * OPTEE_MSG_RPC_SHM_TYPE_* below
-- * [in] param[0].u.value.b requested size
-- * [in] param[0].u.value.c required alignment
-- *
-- * [out] param[0].u.tmem.buf_ptr physical address (of first fragment)
-- * [out] param[0].u.tmem.size size (of first fragment)
-- * [out] param[0].u.tmem.shm_ref shared memory reference
-- * ...
-- * [out] param[n].u.tmem.buf_ptr physical address
-- * [out] param[n].u.tmem.size size
-- * [out] param[n].u.tmem.shm_ref shared memory reference (same value
-- * as in param[n-1].u.tmem.shm_ref)
-- */
--#define OPTEE_MSG_RPC_CMD_SHM_ALLOC 6
--/* Memory that can be shared with a non-secure user space application */
--#define OPTEE_MSG_RPC_SHM_TYPE_APPL 0
--/* Memory only shared with non-secure kernel */
--#define OPTEE_MSG_RPC_SHM_TYPE_KERNEL 1
--
--/*
-- * Free shared memory previously allocated with OPTEE_MSG_RPC_CMD_SHM_ALLOC
-- *
-- * [in] param[0].u.value.a type of memory one of
-- * OPTEE_MSG_RPC_SHM_TYPE_* above
-- * [in] param[0].u.value.b value of shared memory reference
-- * returned in param[0].u.tmem.shm_ref
-- * above
-- */
--#define OPTEE_MSG_RPC_CMD_SHM_FREE 7
--
- #endif /* _OPTEE_MSG_H */
-diff --git a/drivers/tee/optee/optee_private.h b/drivers/tee/optee/optee_private.h
-index d9c5037b4e03..d12d9b9f6d33 100644
---- a/drivers/tee/optee/optee_private.h
-+++ b/drivers/tee/optee/optee_private.h
-@@ -7,6 +7,7 @@
- #define OPTEE_PRIVATE_H
-
- #include <linux/arm-smccc.h>
-+#include <linux/rhashtable.h>
- #include <linux/semaphore.h>
- #include <linux/tee_drv.h>
- #include <linux/types.h>
-@@ -17,6 +18,7 @@
- /* Some Global Platform error codes used in this driver */
- #define TEEC_SUCCESS 0x00000000
- #define TEEC_ERROR_BAD_PARAMETERS 0xFFFF0006
-+#define TEEC_ERROR_NOT_SUPPORTED 0xFFFF000A
- #define TEEC_ERROR_COMMUNICATION 0xFFFF000E
- #define TEEC_ERROR_OUT_OF_MEMORY 0xFFFF000C
- #define TEEC_ERROR_SHORT_BUFFER 0xFFFF0010
-@@ -65,6 +67,32 @@ struct optee_supp {
- struct completion reqs_c;
- };
-
-+/**
-+ * struct optee_ffa_data - FFA communication struct
-+ * @dst FFA destination id, the id of OP-TEE in secure world
-+ * @ops FFA operations
-+ * @mutex Serializes access to @global_ids
-+ * @global_ids FF-A shared memory global handle translation
-+ */
-+struct optee_ffa {
-+ u32 dst;
-+ struct ffa_ops *ops;
-+ struct mutex mutex;
-+ struct rhashtable global_ids;
-+};
-+
-+struct optee;
-+struct optee_ops {
-+ int (*do_call_with_arg)(struct tee_context *ctx,
-+ struct tee_shm *shm_arg);
-+ int (*to_msg_param)(struct optee *optee,
-+ struct optee_msg_param *msg_params,
-+ size_t num_params, const struct tee_param *params);
-+ int (*from_msg_param)(struct optee *optee, struct tee_param *params,
-+ size_t num_params,
-+ const struct optee_msg_param *msg_params);
-+};
-+
- /**
- * struct optee - main service struct
- * @supp_teedev: supplicant device
-@@ -82,7 +110,11 @@ struct optee_supp {
- struct optee {
- struct tee_device *supp_teedev;
- struct tee_device *teedev;
-+ const struct optee_ops *ops;
- optee_invoke_fn *invoke_fn;
-+#ifdef CONFIG_ARM_FFA_TRANSPORT
-+ struct optee_ffa ffa;
-+#endif
- struct optee_call_queue call_queue;
- struct optee_wait_queue wait_queue;
- struct optee_supp supp;
-@@ -141,10 +173,11 @@ int optee_supp_recv(struct tee_context *ctx, u32 *func, u32 *num_params,
- int optee_supp_send(struct tee_context *ctx, u32 ret, u32 num_params,
- struct tee_param *param);
-
--u32 optee_do_call_with_arg(struct tee_context *ctx, phys_addr_t parg);
-+int optee_do_call_with_arg(struct tee_context *ctx, struct tee_shm *arg);
- int optee_open_session(struct tee_context *ctx,
- struct tee_ioctl_open_session_arg *arg,
- struct tee_param *param);
-+int optee_close_session_helper(struct tee_context *ctx, u32 session);
- int optee_close_session(struct tee_context *ctx, u32 session);
- int optee_invoke_func(struct tee_context *ctx, struct tee_ioctl_invoke_arg *arg,
- struct tee_param *param);
-@@ -163,11 +196,6 @@ int optee_shm_register_supp(struct tee_context *ctx, struct tee_shm *shm,
- unsigned long start);
- int optee_shm_unregister_supp(struct tee_context *ctx, struct tee_shm *shm);
-
--int optee_from_msg_param(struct tee_param *params, size_t num_params,
-- const struct optee_msg_param *msg_params);
--int optee_to_msg_param(struct optee_msg_param *msg_params, size_t num_params,
-- const struct tee_param *params);
--
- u64 *optee_allocate_pages_list(size_t num_entries);
- void optee_free_pages_list(void *array, size_t num_entries);
- void optee_fill_pages_list(u64 *dst, struct page **pages, int num_pages,
-@@ -175,6 +203,27 @@ void optee_fill_pages_list(u64 *dst, struct page **pages, int num_pages,
-
- int optee_enumerate_devices(void);
-
-+int optee_shm_add_ffa_handle(struct optee *optee, struct tee_shm *shm,
-+ u64 global_id);
-+int optee_shm_rem_ffa_handle(struct optee *optee, u64 global_id);
-+
-+struct tee_shm *optee_shm_from_ffa_handle(struct optee *optee, u64 global_id);
-+void optee_ffa_disable_shm_cache(struct optee *optee);
-+
-+int optee_ffa_shm_register(struct tee_context *ctx, struct tee_shm *shm,
-+ struct page **pages, size_t num_pages,
-+ unsigned long start);
-+int optee_ffa_shm_unregister(struct tee_context *ctx, struct tee_shm *shm);
-+int optee_ffa_shm_register_supp(struct tee_context *ctx, struct tee_shm *shm,
-+ struct page **pages, size_t num_pages,
-+ unsigned long start);
-+int optee_ffa_shm_unregister_supp(struct tee_context *ctx,
-+ struct tee_shm *shm);
-+
-+int optee_ffa_do_call_with_arg(struct tee_context *ctx, struct tee_shm *arg);
-+int optee_ffa_rpc_shm_register(struct tee_context *ctx, struct tee_shm *shm);
-+void optee_handle_ffa_rpc(struct tee_context *ctx, u32 *w4, u32 *w5, u32 *w6);
-+
- /*
- * Small helpers
- */
-diff --git a/drivers/tee/optee/optee_rpc_cmd.h b/drivers/tee/optee/optee_rpc_cmd.h
-new file mode 100644
-index 000000000000..712aa32513d7
---- /dev/null
-+++ b/drivers/tee/optee/optee_rpc_cmd.h
-@@ -0,0 +1,333 @@
-+/* SPDX-License-Identifier: BSD-2-Clause */
-+/*
-+ * Copyright (c) 2016-2018, Linaro Limited
-+ */
-+
-+#ifndef __OPTEE_RPC_CMD_H
-+#define __OPTEE_RPC_CMD_H
-+
-+/*
-+ * All RPC is done with a struct optee_msg_arg as bearer of information,
-+ * struct optee_msg_arg::arg holds values defined by OPTEE_RPC_CMD_* below.
-+ * Only the commands handled by the kernel driver are defined here.
-+ *
-+ * RPC communication with tee-supplicant is reversed compared to normal
-+ * client communication described above. The supplicant receives requests
-+ * and sends responses.
-+ */
-+
-+/*
-+ * Load a TA into memory
-+ *
-+ * Since the size of the TA isn't known in advance the size of the TA is
-+ * can be queried with a NULL buffer.
-+ *
-+ * [in] value[0].a-b UUID
-+ * [out] memref[1] Buffer with TA
-+ */
-+#define OPTEE_RPC_CMD_LOAD_TA 0
-+
-+/*
-+ * Replay Protected Memory Block access
-+ *
-+ * [in] memref[0] Frames to device
-+ * [out] memref[1] Frames from device
-+ */
-+#define OPTEE_RPC_CMD_RPMB 1
-+
-+/*
-+ * File system access, see definition of protocol below
-+ */
-+#define OPTEE_RPC_CMD_FS 2
-+
-+/*
-+ * Get time
-+ *
-+ * Returns number of seconds and nano seconds since the Epoch,
-+ * 1970-01-01 00:00:00 +0000 (UTC).
-+ *
-+ * [out] value[0].a Number of seconds
-+ * [out] value[0].b Number of nano seconds.
-+ */
-+#define OPTEE_RPC_CMD_GET_TIME 3
-+
-+/*
-+ * Wait queue primitive, helper for secure world to implement a wait queue.
-+ *
-+ * If secure world needs to wait for a secure world mutex it issues a sleep
-+ * request instead of spinning in secure world. Conversely is a wakeup
-+ * request issued when a secure world mutex with a thread waiting thread is
-+ * unlocked.
-+ *
-+ * Waiting on a key
-+ * [in] value[0].a OPTEE_RPC_WAIT_QUEUE_SLEEP
-+ * [in] value[0].b Wait key
-+ *
-+ * Waking up a key
-+ * [in] value[0].a OPTEE_RPC_WAIT_QUEUE_WAKEUP
-+ * [in] value[0].b Wakeup key
-+ */
-+#define OPTEE_RPC_CMD_WAIT_QUEUE 4
-+#define OPTEE_RPC_WAIT_QUEUE_SLEEP 0
-+#define OPTEE_RPC_WAIT_QUEUE_WAKEUP 1
-+
-+/*
-+ * Suspend execution
-+ *
-+ * [in] value[0].a Number of milliseconds to suspend
-+ */
-+#define OPTEE_RPC_CMD_SUSPEND 5
-+
-+/*
-+ * Allocate a piece of shared memory
-+ *
-+ * [in] value[0].a Type of memory one of
-+ * OPTEE_RPC_SHM_TYPE_* below
-+ * [in] value[0].b Requested size
-+ * [in] value[0].c Required alignment
-+ * [out] memref[0] Buffer
-+ */
-+#define OPTEE_RPC_CMD_SHM_ALLOC 6
-+/* Memory that can be shared with a non-secure user space application */
-+#define OPTEE_RPC_SHM_TYPE_APPL 0
-+/* Memory only shared with non-secure kernel */
-+#define OPTEE_RPC_SHM_TYPE_KERNEL 1
-+/*
-+ * Memory shared with non-secure kernel and exported to a non-secure user
-+ * space application
-+ */
-+#define OPTEE_RPC_SHM_TYPE_GLOBAL 2
-+
-+/*
-+ * Free shared memory previously allocated with OPTEE_RPC_CMD_SHM_ALLOC
-+ *
-+ * [in] value[0].a Type of memory one of
-+ * OPTEE_RPC_SHM_TYPE_* above
-+ * [in] value[0].b Value of shared memory reference or cookie
-+ */
-+#define OPTEE_RPC_CMD_SHM_FREE 7
-+
-+/* Was OPTEE_RPC_CMD_SQL_FS, which isn't supported any longer */
-+#define OPTEE_RPC_CMD_SQL_FS_RESERVED 8
-+
-+/*
-+ * Send TA profiling information to normal world
-+ *
-+ * [in/out] value[0].a File identifier. Must be set to 0 on
-+ * first call. A value >= 1 will be
-+ * returned on success. Re-use this value
-+ * to append data to the same file.
-+ * [in] memref[1] TA UUID
-+ * [in] memref[2] Profile data
-+ */
-+#define OPTEE_RPC_CMD_GPROF 9
-+
-+/*
-+ * Socket command, see definition of protocol below
-+ */
-+#define OPTEE_RPC_CMD_SOCKET 10
-+
-+/*
-+ * Send TA function graph data to normal world
-+ *
-+ * [in/out] value[0].a File identifier. Must be set to 0 on
-+ * first call. A value >= 1 will be
-+ * returned on success. Re-use this value
-+ * to append data to the same file.
-+ * [in] memref[1] TA UUID
-+ * [in] memref[2] function graph data
-+ */
-+#define OPTEE_RPC_CMD_FTRACE 11
-+
-+/*
-+ * Register timestamp buffer in the linux kernel optee driver
-+ *
-+ * [in] value[0].a Subcommand (register buffer, unregister buffer)
-+ * OPTEE_RPC_CMD_BENCH_REG_* below
-+ * [in] value[0].b Physical address of timestamp buffer
-+ * [in] value[0].c Size of buffer
-+ */
-+#define OPTEE_RPC_CMD_BENCH_REG_NEW 0
-+#define OPTEE_RPC_CMD_BENCH_REG_DEL 1
-+#define OPTEE_RPC_CMD_BENCH_REG 20
-+
-+/*
-+ * Definition of protocol for command OPTEE_RPC_CMD_FS
-+ */
-+
-+/*
-+ * Open a file
-+ *
-+ * [in] value[0].a OPTEE_RPC_FS_OPEN
-+ * [in] memref[1] A string holding the file name
-+ * [out] value[2].a File descriptor of open file
-+ */
-+#define OPTEE_RPC_FS_OPEN 0
-+
-+/*
-+ * Create a file
-+ *
-+ * [in] value[0].a OPTEE_RPC_FS_CREATE
-+ * [in] memref[1] A string holding the file name
-+ * [out] value[2].a File descriptor of open file
-+ */
-+#define OPTEE_RPC_FS_CREATE 1
-+
-+/*
-+ * Close a file
-+ *
-+ * [in] value[0].a OPTEE_RPC_FS_CLOSE
-+ * [in] value[0].b File descriptor of open file.
-+ */
-+#define OPTEE_RPC_FS_CLOSE 2
-+
-+/*
-+ * Read from a file
-+ *
-+ * [in] value[0].a OPTEE_RPC_FS_READ
-+ * [in] value[0].b File descriptor of open file
-+ * [in] value[0].c Offset into file
-+ * [out] memref[1] Buffer to hold returned data
-+ */
-+#define OPTEE_RPC_FS_READ 3
-+
-+/*
-+ * Write to a file
-+ *
-+ * [in] value[0].a OPTEE_RPC_FS_WRITE
-+ * [in] value[0].b File descriptor of open file
-+ * [in] value[0].c Offset into file
-+ * [in] memref[1] Buffer holding data to be written
-+ */
-+#define OPTEE_RPC_FS_WRITE 4
-+
-+/*
-+ * Truncate a file
-+ *
-+ * [in] value[0].a OPTEE_RPC_FS_TRUNCATE
-+ * [in] value[0].b File descriptor of open file
-+ * [in] value[0].c Length of file.
-+ */
-+#define OPTEE_RPC_FS_TRUNCATE 5
-+
-+/*
-+ * Remove a file
-+ *
-+ * [in] value[0].a OPTEE_RPC_FS_REMOVE
-+ * [in] memref[1] A string holding the file name
-+ */
-+#define OPTEE_RPC_FS_REMOVE 6
-+
-+/*
-+ * Rename a file
-+ *
-+ * [in] value[0].a OPTEE_RPC_FS_RENAME
-+ * [in] value[0].b True if existing target should be removed
-+ * [in] memref[1] A string holding the old file name
-+ * [in] memref[2] A string holding the new file name
-+ */
-+#define OPTEE_RPC_FS_RENAME 7
-+
-+/*
-+ * Opens a directory for file listing
-+ *
-+ * [in] value[0].a OPTEE_RPC_FS_OPENDIR
-+ * [in] memref[1] A string holding the name of the directory
-+ * [out] value[2].a Handle to open directory
-+ */
-+#define OPTEE_RPC_FS_OPENDIR 8
-+
-+/*
-+ * Closes a directory handle
-+ *
-+ * [in] value[0].a OPTEE_RPC_FS_CLOSEDIR
-+ * [in] value[0].b Handle to open directory
-+ */
-+#define OPTEE_RPC_FS_CLOSEDIR 9
-+
-+/*
-+ * Read next file name of directory
-+ *
-+ *
-+ * [in] value[0].a OPTEE_RPC_FS_READDIR
-+ * [in] value[0].b Handle to open directory
-+ * [out] memref[1] A string holding the file name
-+ */
-+#define OPTEE_RPC_FS_READDIR 10
-+
-+/* End of definition of protocol for command OPTEE_RPC_CMD_FS */
-+
-+/*
-+ * Definition of protocol for command OPTEE_RPC_CMD_SOCKET
-+ */
-+
-+#define OPTEE_RPC_SOCKET_TIMEOUT_NONBLOCKING 0
-+#define OPTEE_RPC_SOCKET_TIMEOUT_BLOCKING 0xffffffff
-+
-+/*
-+ * Open socket
-+ *
-+ * [in] value[0].a OPTEE_RPC_SOCKET_OPEN
-+ * [in] value[0].b TA instance id
-+ * [in] value[1].a Server port number
-+ * [in] value[1].b Protocol, TEE_ISOCKET_PROTOCOLID_*
-+ * [in] value[1].c Ip version TEE_IP_VERSION_* from tee_ipsocket.h
-+ * [in] memref[2] Server address
-+ * [out] value[3].a Socket handle (32-bit)
-+ */
-+#define OPTEE_RPC_SOCKET_OPEN 0
-+
-+/*
-+ * Close socket
-+ *
-+ * [in] value[0].a OPTEE_RPC_SOCKET_CLOSE
-+ * [in] value[0].b TA instance id
-+ * [in] value[0].c Socket handle
-+ */
-+#define OPTEE_RPC_SOCKET_CLOSE 1
-+
-+/*
-+ * Close all sockets
-+ *
-+ * [in] value[0].a OPTEE_RPC_SOCKET_CLOSE_ALL
-+ * [in] value[0].b TA instance id
-+ */
-+#define OPTEE_RPC_SOCKET_CLOSE_ALL 2
-+
-+/*
-+ * Send data on socket
-+ *
-+ * [in] value[0].a OPTEE_RPC_SOCKET_SEND
-+ * [in] value[0].b TA instance id
-+ * [in] value[0].c Socket handle
-+ * [in] memref[1] Buffer to transmit
-+ * [in] value[2].a Timeout ms or OPTEE_RPC_SOCKET_TIMEOUT_*
-+ * [out] value[2].b Number of transmitted bytes
-+ */
-+#define OPTEE_RPC_SOCKET_SEND 3
-+
-+/*
-+ * Receive data on socket
-+ *
-+ * [in] value[0].a OPTEE_RPC_SOCKET_RECV
-+ * [in] value[0].b TA instance id
-+ * [in] value[0].c Socket handle
-+ * [out] memref[1] Buffer to receive
-+ * [in] value[2].a Timeout ms or OPTEE_RPC_SOCKET_TIMEOUT_*
-+ */
-+#define OPTEE_RPC_SOCKET_RECV 4
-+
-+/*
-+ * Perform IOCTL on socket
-+ *
-+ * [in] value[0].a OPTEE_RPC_SOCKET_IOCTL
-+ * [in] value[0].b TA instance id
-+ * [in] value[0].c Socket handle
-+ * [in/out] memref[1] Buffer
-+ * [in] value[2].a Ioctl command
-+ */
-+#define OPTEE_RPC_SOCKET_IOCTL 5
-+
-+/* End of definition of protocol for command OPTEE_RPC_CMD_SOCKET */
-+
-+#endif /*__OPTEE_RPC_CMD_H*/
-diff --git a/drivers/tee/optee/rpc.c b/drivers/tee/optee/rpc.c
-index b4ade54d1f28..ca5d5d01b58f 100644
---- a/drivers/tee/optee/rpc.c
-+++ b/drivers/tee/optee/rpc.c
-@@ -9,8 +9,11 @@
- #include <linux/device.h>
- #include <linux/slab.h>
- #include <linux/tee_drv.h>
-+#include "optee_msg.h"
- #include "optee_private.h"
-+#include "optee_rpc_cmd.h"
- #include "optee_smc.h"
-+#include "optee_ffa.h"
-
- struct wq_entry {
- struct list_head link;
-@@ -102,10 +105,10 @@ static void handle_rpc_func_cmd_wq(struct optee *optee,
- goto bad;
-
- switch (arg->params[0].u.value.a) {
-- case OPTEE_MSG_RPC_WAIT_QUEUE_SLEEP:
-+ case OPTEE_RPC_WAIT_QUEUE_SLEEP:
- wq_sleep(&optee->wait_queue, arg->params[0].u.value.b);
- break;
-- case OPTEE_MSG_RPC_WAIT_QUEUE_WAKEUP:
-+ case OPTEE_RPC_WAIT_QUEUE_WAKEUP:
- wq_wakeup(&optee->wait_queue, arg->params[0].u.value.b);
- break;
- default:
-@@ -140,10 +143,10 @@ static void handle_rpc_func_cmd_wait(struct optee_msg_arg *arg)
- arg->ret = TEEC_ERROR_BAD_PARAMETERS;
- }
-
--static void handle_rpc_supp_cmd(struct tee_context *ctx,
-+static void handle_rpc_supp_cmd(struct tee_context *ctx, struct optee *optee,
- struct optee_msg_arg *arg)
- {
-- struct tee_param *params;
-+ struct tee_param *params = NULL;
-
- arg->ret_origin = TEEC_ORIGIN_COMMS;
-
-@@ -154,32 +157,36 @@ static void handle_rpc_supp_cmd(struct tee_context *ctx,
- return;
- }
-
-- if (optee_from_msg_param(params, arg->num_params, arg->params)) {
-+ if (optee->ops->from_msg_param(optee, params, arg->num_params,
-+ arg->params)) {
- arg->ret = TEEC_ERROR_BAD_PARAMETERS;
- goto out;
- }
-
- arg->ret = optee_supp_thrd_req(ctx, arg->cmd, arg->num_params, params);
-
-- if (optee_to_msg_param(arg->params, arg->num_params, params))
-+ if (optee->ops->to_msg_param(optee, arg->params, arg->num_params,
-+ params))
- arg->ret = TEEC_ERROR_BAD_PARAMETERS;
- out:
- kfree(params);
- }
-
-+
-+
- static struct tee_shm *cmd_alloc_suppl(struct tee_context *ctx, size_t sz)
- {
-- u32 ret;
-- struct tee_param param;
- struct optee *optee = tee_get_drvdata(ctx->teedev);
-- struct tee_shm *shm;
-+ struct tee_param param = { };
-+ struct tee_shm *shm = NULL;
-+ u32 ret = 0;
-
- param.attr = TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INOUT;
-- param.u.value.a = OPTEE_MSG_RPC_SHM_TYPE_APPL;
-+ param.u.value.a = OPTEE_RPC_SHM_TYPE_APPL;
- param.u.value.b = sz;
- param.u.value.c = 0;
-
-- ret = optee_supp_thrd_req(ctx, OPTEE_MSG_RPC_CMD_SHM_ALLOC, 1, ¶m);
-+ ret = optee_supp_thrd_req(ctx, OPTEE_RPC_CMD_SHM_ALLOC, 1, ¶m);
- if (ret)
- return ERR_PTR(-ENOMEM);
-
-@@ -216,10 +223,10 @@ static void handle_rpc_func_cmd_shm_alloc(struct tee_context *ctx,
-
- sz = arg->params[0].u.value.b;
- switch (arg->params[0].u.value.a) {
-- case OPTEE_MSG_RPC_SHM_TYPE_APPL:
-+ case OPTEE_RPC_SHM_TYPE_APPL:
- shm = cmd_alloc_suppl(ctx, sz);
- break;
-- case OPTEE_MSG_RPC_SHM_TYPE_KERNEL:
-+ case OPTEE_RPC_SHM_TYPE_KERNEL:
- shm = tee_shm_alloc(ctx, sz, TEE_SHM_MAPPED);
- break;
- default:
-@@ -291,7 +298,7 @@ static void cmd_free_suppl(struct tee_context *ctx, struct tee_shm *shm)
- struct tee_param param;
-
- param.attr = TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INOUT;
-- param.u.value.a = OPTEE_MSG_RPC_SHM_TYPE_APPL;
-+ param.u.value.a = OPTEE_RPC_SHM_TYPE_APPL;
- param.u.value.b = tee_shm_get_id(shm);
- param.u.value.c = 0;
-
-@@ -308,7 +315,7 @@ static void cmd_free_suppl(struct tee_context *ctx, struct tee_shm *shm)
- */
- tee_shm_put(shm);
-
-- optee_supp_thrd_req(ctx, OPTEE_MSG_RPC_CMD_SHM_FREE, 1, ¶m);
-+ optee_supp_thrd_req(ctx, OPTEE_RPC_CMD_SHM_FREE, 1, ¶m);
- }
-
- static void handle_rpc_func_cmd_shm_free(struct tee_context *ctx,
-@@ -326,10 +333,10 @@ static void handle_rpc_func_cmd_shm_free(struct tee_context *ctx,
-
- shm = (struct tee_shm *)(unsigned long)arg->params[0].u.value.b;
- switch (arg->params[0].u.value.a) {
-- case OPTEE_MSG_RPC_SHM_TYPE_APPL:
-+ case OPTEE_RPC_SHM_TYPE_APPL:
- cmd_free_suppl(ctx, shm);
- break;
-- case OPTEE_MSG_RPC_SHM_TYPE_KERNEL:
-+ case OPTEE_RPC_SHM_TYPE_KERNEL:
- tee_shm_free(shm);
- break;
- default:
-@@ -357,7 +364,7 @@ static void handle_rpc_func_cmd(struct tee_context *ctx, struct optee *optee,
- struct tee_shm *shm,
- struct optee_call_ctx *call_ctx)
- {
-- struct optee_msg_arg *arg;
-+ struct optee_msg_arg *arg = NULL;
-
- arg = tee_shm_get_va(shm, 0);
- if (IS_ERR(arg)) {
-@@ -366,24 +373,24 @@ static void handle_rpc_func_cmd(struct tee_context *ctx, struct optee *optee,
- }
-
- switch (arg->cmd) {
-- case OPTEE_MSG_RPC_CMD_GET_TIME:
-+ case OPTEE_RPC_CMD_GET_TIME:
- handle_rpc_func_cmd_get_time(arg);
- break;
-- case OPTEE_MSG_RPC_CMD_WAIT_QUEUE:
-+ case OPTEE_RPC_CMD_WAIT_QUEUE:
- handle_rpc_func_cmd_wq(optee, arg);
- break;
-- case OPTEE_MSG_RPC_CMD_SUSPEND:
-+ case OPTEE_RPC_CMD_SUSPEND:
- handle_rpc_func_cmd_wait(arg);
- break;
-- case OPTEE_MSG_RPC_CMD_SHM_ALLOC:
-+ case OPTEE_RPC_CMD_SHM_ALLOC:
- free_pages_list(call_ctx);
- handle_rpc_func_cmd_shm_alloc(ctx, arg, call_ctx);
- break;
-- case OPTEE_MSG_RPC_CMD_SHM_FREE:
-+ case OPTEE_RPC_CMD_SHM_FREE:
- handle_rpc_func_cmd_shm_free(ctx, arg);
- break;
- default:
-- handle_rpc_supp_cmd(ctx, arg);
-+ handle_rpc_supp_cmd(ctx, optee, arg);
- }
- }
-
-@@ -441,3 +448,95 @@ void optee_handle_rpc(struct tee_context *ctx, struct optee_rpc_param *param,
-
- param->a0 = OPTEE_SMC_CALL_RETURN_FROM_RPC;
- }
-+
-+#ifdef CONFIG_ARM_FFA_TRANSPORT
-+static void handle_ffa_rpc_func_cmd(struct tee_context *ctx,
-+ struct optee *optee,
-+ struct optee_msg_arg *arg)
-+{
-+ switch (arg->cmd) {
-+ case OPTEE_RPC_CMD_GET_TIME:
-+ handle_rpc_func_cmd_get_time(arg);
-+ break;
-+ case OPTEE_RPC_CMD_WAIT_QUEUE:
-+ handle_rpc_func_cmd_wq(optee, arg);
-+ break;
-+ case OPTEE_RPC_CMD_SUSPEND:
-+ handle_rpc_func_cmd_wait(arg);
-+ break;
-+ case OPTEE_RPC_CMD_SHM_ALLOC:
-+ case OPTEE_RPC_CMD_SHM_FREE:
-+ pr_err("%s: RPC cmd 0x%x: not supported\n", __func__,
-+ arg->cmd);
-+ arg->ret = TEEC_ERROR_NOT_SUPPORTED;
-+ break;
-+ default:
-+ handle_rpc_supp_cmd(ctx, optee, arg);
-+ }
-+}
-+
-+void optee_handle_ffa_rpc(struct tee_context *ctx, u32 *w4, u32 *w5, u32 *w6)
-+{
-+ struct optee *optee = tee_get_drvdata(ctx->teedev);
-+ struct tee_shm *shm = NULL;
-+ struct optee_msg_arg *rpc_arg = NULL;
-+ u64 global_handle = 0;
-+ u32 cmd = *w4;
-+
-+ switch (cmd) {
-+ case OPTEE_FFA_YIELDING_CALL_RETURN_ALLOC_KERN_SHM:
-+ case OPTEE_FFA_YIELDING_CALL_RETURN_ALLOC_SUPPL_SHM:
-+ if (cmd == OPTEE_FFA_YIELDING_CALL_RETURN_ALLOC_KERN_SHM)
-+ shm = tee_shm_alloc(ctx, *w5 * PAGE_SIZE,
-+ TEE_SHM_MAPPED);
-+ else
-+ shm = cmd_alloc_suppl(ctx, *w5 * PAGE_SIZE);
-+
-+ if (IS_ERR_OR_NULL(shm))
-+ break;
-+
-+ *w4 = shm->sec_world_id;
-+ *w5 = shm->sec_world_id >> 32;
-+ *w6 = shm->offset;
-+ return;
-+ case OPTEE_FFA_YIELDING_CALL_RETURN_FREE_KERN_SHM:
-+ case OPTEE_FFA_YIELDING_CALL_RETURN_FREE_SUPPL_SHM:
-+ global_handle = *w5 | ((u64)*w6 << 32);
-+ shm = optee_shm_from_ffa_handle(optee, global_handle);
-+ if (!shm) {
-+ pr_err("Invalid global handle 0x%llx\n", global_handle);
-+ break;
-+ }
-+ if (cmd == OPTEE_FFA_YIELDING_CALL_RETURN_FREE_KERN_SHM)
-+ tee_shm_free(shm);
-+ else
-+ cmd_free_suppl(ctx, shm);
-+ break;
-+ case OPTEE_FFA_YIELDING_CALL_RETURN_RPC_CMD:
-+ global_handle = *w5 | ((u64)*w6 << 32);
-+ shm = optee_shm_from_ffa_handle(optee, global_handle);
-+ if (!shm) {
-+ pr_err("Invalid global handle 0x%llx\n", global_handle);
-+ break;
-+ }
-+ rpc_arg = tee_shm_get_va(shm, 0);
-+ if (IS_ERR(rpc_arg)) {
-+ pr_err("Invalid offset 0 for global handle 0x%llx\n",
-+ global_handle);
-+ break;
-+ }
-+ handle_ffa_rpc_func_cmd(ctx, optee, rpc_arg);
-+ break;
-+ case OPTEE_FFA_YIELDING_CALL_RETURN_INTERRUPT:
-+ /* Interrupt delivered by now */
-+ break;
-+ default:
-+ pr_warn("Unknown RPC func 0x%x\n", cmd);
-+ break;
-+ }
-+
-+ *w4 = 0;
-+ *w5 = 0;
-+ *w6 = 0;
-+}
-+#endif /*CONFIG_ARM_FFA_TRANSPORT*/
-diff --git a/drivers/tee/optee/shm_pool.c b/drivers/tee/optee/shm_pool.c
-index d767eebf30bd..ffc6821f6ce3 100644
---- a/drivers/tee/optee/shm_pool.c
-+++ b/drivers/tee/optee/shm_pool.c
-@@ -87,3 +87,53 @@ struct tee_shm_pool_mgr *optee_shm_pool_alloc_pages(void)
-
- return mgr;
- }
-+
-+#ifdef CONFIG_ARM_FFA_TRANSPORT
-+static int pool_ffa_op_alloc(struct tee_shm_pool_mgr *poolm,
-+ struct tee_shm *shm, size_t size)
-+{
-+ unsigned int order = get_order(size);
-+ struct page *page;
-+ int rc = 0;
-+
-+ page = alloc_pages(GFP_KERNEL | __GFP_ZERO, order);
-+ if (!page)
-+ return -ENOMEM;
-+
-+ shm->kaddr = page_address(page);
-+ shm->paddr = page_to_phys(page);
-+ shm->size = PAGE_SIZE << order;
-+
-+ shm->flags |= TEE_SHM_REGISTER;
-+ rc = optee_ffa_shm_register(shm->ctx, shm, &page, 1 << order,
-+ (unsigned long)shm->kaddr);
-+
-+ return rc;
-+}
-+
-+static void pool_ffa_op_free(struct tee_shm_pool_mgr *poolm,
-+ struct tee_shm *shm)
-+{
-+ optee_ffa_shm_unregister(shm->ctx, shm);
-+ free_pages((unsigned long)shm->kaddr, get_order(shm->size));
-+ shm->kaddr = NULL;
-+}
-+
-+static const struct tee_shm_pool_mgr_ops pool_ffa_ops = {
-+ .alloc = pool_ffa_op_alloc,
-+ .free = pool_ffa_op_free,
-+ .destroy_poolmgr = pool_op_destroy_poolmgr,
-+};
-+
-+struct tee_shm_pool_mgr *optee_ffa_shm_pool_alloc_pages(void)
-+{
-+ struct tee_shm_pool_mgr *mgr = kzalloc(sizeof(*mgr), GFP_KERNEL);
-+
-+ if (!mgr)
-+ return ERR_PTR(-ENOMEM);
-+
-+ mgr->ops = &pool_ffa_ops;
-+
-+ return mgr;
-+}
-+#endif /*CONFIG_ARM_FFA_TRANSPORT*/
-diff --git a/drivers/tee/optee/shm_pool.h b/drivers/tee/optee/shm_pool.h
-index 28109d991c4b..34c5fd74a3ff 100644
---- a/drivers/tee/optee/shm_pool.h
-+++ b/drivers/tee/optee/shm_pool.h
-@@ -10,5 +10,6 @@
- #include <linux/tee_drv.h>
-
- struct tee_shm_pool_mgr *optee_shm_pool_alloc_pages(void);
-+struct tee_shm_pool_mgr *optee_ffa_shm_pool_alloc_pages(void);
-
- #endif
-diff --git a/drivers/tee/tee_core.c b/drivers/tee/tee_core.c
-index 3d32a2ca48c3..974fe7081225 100644
---- a/drivers/tee/tee_core.c
-+++ b/drivers/tee/tee_core.c
-@@ -59,7 +59,6 @@ static struct tee_context *teedev_open(struct tee_device *teedev)
-
- kref_init(&ctx->refcount);
- ctx->teedev = teedev;
-- INIT_LIST_HEAD(&ctx->list_shm);
- rc = teedev->desc->ops->open(ctx);
- if (rc)
- goto err;
-diff --git a/drivers/tee/tee_shm.c b/drivers/tee/tee_shm.c
-index 09ddcd06c715..deb22f877881 100644
---- a/drivers/tee/tee_shm.c
-+++ b/drivers/tee/tee_shm.c
-@@ -13,13 +13,13 @@
-
- static void tee_shm_release(struct tee_shm *shm)
- {
-- struct tee_device *teedev = shm->teedev;
-+ struct tee_device *teedev = shm->ctx->teedev;
-
-- mutex_lock(&teedev->mutex);
-- idr_remove(&teedev->idr, shm->id);
-- if (shm->ctx)
-- list_del(&shm->link);
-- mutex_unlock(&teedev->mutex);
-+ if (shm->flags & TEE_SHM_DMA_BUF) {
-+ mutex_lock(&teedev->mutex);
-+ idr_remove(&teedev->idr, shm->id);
-+ mutex_unlock(&teedev->mutex);
-+ }
-
- if (shm->flags & TEE_SHM_POOL) {
- struct tee_shm_pool_mgr *poolm;
-@@ -44,8 +44,7 @@ static void tee_shm_release(struct tee_shm *shm)
- kfree(shm->pages);
- }
-
-- if (shm->ctx)
-- teedev_ctx_put(shm->ctx);
-+ teedev_ctx_put(shm->ctx);
-
- kfree(shm);
-
-@@ -82,7 +81,7 @@ static int tee_shm_op_mmap(struct dma_buf *dmabuf, struct vm_area_struct *vma)
- size_t size = vma->vm_end - vma->vm_start;
-
- /* Refuse sharing shared memory provided by application */
-- if (shm->flags & TEE_SHM_REGISTER)
-+ if (shm->flags & TEE_SHM_USER_MAPPED)
- return -EINVAL;
-
- return remap_pfn_range(vma, vma->vm_start, shm->paddr >> PAGE_SHIFT,
-@@ -97,20 +96,14 @@ static const struct dma_buf_ops tee_shm_dma_buf_ops = {
- .mmap = tee_shm_op_mmap,
- };
-
--static struct tee_shm *__tee_shm_alloc(struct tee_context *ctx,
-- struct tee_device *teedev,
-- size_t size, u32 flags)
-+struct tee_shm *tee_shm_alloc(struct tee_context *ctx, size_t size, u32 flags)
- {
-+ struct tee_device *teedev = ctx->teedev;
- struct tee_shm_pool_mgr *poolm = NULL;
- struct tee_shm *shm;
- void *ret;
- int rc;
-
-- if (ctx && ctx->teedev != teedev) {
-- dev_err(teedev->dev.parent, "ctx and teedev mismatch\n");
-- return ERR_PTR(-EINVAL);
-- }
--
- if (!(flags & TEE_SHM_MAPPED)) {
- dev_err(teedev->dev.parent,
- "only mapped allocations supported\n");
-@@ -138,7 +131,6 @@ static struct tee_shm *__tee_shm_alloc(struct tee_context *ctx,
- }
-
- shm->flags = flags | TEE_SHM_POOL;
-- shm->teedev = teedev;
- shm->ctx = ctx;
- if (flags & TEE_SHM_DMA_BUF)
- poolm = teedev->pool->dma_buf_mgr;
-@@ -151,17 +143,18 @@ static struct tee_shm *__tee_shm_alloc(struct tee_context *ctx,
- goto err_kfree;
- }
-
-- mutex_lock(&teedev->mutex);
-- shm->id = idr_alloc(&teedev->idr, shm, 1, 0, GFP_KERNEL);
-- mutex_unlock(&teedev->mutex);
-- if (shm->id < 0) {
-- ret = ERR_PTR(shm->id);
-- goto err_pool_free;
-- }
-
- if (flags & TEE_SHM_DMA_BUF) {
- DEFINE_DMA_BUF_EXPORT_INFO(exp_info);
-
-+ mutex_lock(&teedev->mutex);
-+ shm->id = idr_alloc(&teedev->idr, shm, 1, 0, GFP_KERNEL);
-+ mutex_unlock(&teedev->mutex);
-+ if (shm->id < 0) {
-+ ret = ERR_PTR(shm->id);
-+ goto err_pool_free;
-+ }
-+
- exp_info.ops = &tee_shm_dma_buf_ops;
- exp_info.size = shm->size;
- exp_info.flags = O_RDWR;
-@@ -174,18 +167,16 @@ static struct tee_shm *__tee_shm_alloc(struct tee_context *ctx,
- }
- }
-
-- if (ctx) {
-+ if (ctx)
- teedev_ctx_get(ctx);
-- mutex_lock(&teedev->mutex);
-- list_add_tail(&shm->link, &ctx->list_shm);
-- mutex_unlock(&teedev->mutex);
-- }
-
- return shm;
- err_rem:
-- mutex_lock(&teedev->mutex);
-- idr_remove(&teedev->idr, shm->id);
-- mutex_unlock(&teedev->mutex);
-+ if (flags & TEE_SHM_DMA_BUF) {
-+ mutex_lock(&teedev->mutex);
-+ idr_remove(&teedev->idr, shm->id);
-+ mutex_unlock(&teedev->mutex);
-+ }
- err_pool_free:
- poolm->ops->free(poolm, shm);
- err_kfree:
-@@ -194,31 +185,8 @@ static struct tee_shm *__tee_shm_alloc(struct tee_context *ctx,
- tee_device_put(teedev);
- return ret;
- }
--
--/**
-- * tee_shm_alloc() - Allocate shared memory
-- * @ctx: Context that allocates the shared memory
-- * @size: Requested size of shared memory
-- * @flags: Flags setting properties for the requested shared memory.
-- *
-- * Memory allocated as global shared memory is automatically freed when the
-- * TEE file pointer is closed. The @flags field uses the bits defined by
-- * TEE_SHM_* in <linux/tee_drv.h>. TEE_SHM_MAPPED must currently always be
-- * set. If TEE_SHM_DMA_BUF global shared memory will be allocated and
-- * associated with a dma-buf handle, else driver private memory.
-- */
--struct tee_shm *tee_shm_alloc(struct tee_context *ctx, size_t size, u32 flags)
--{
-- return __tee_shm_alloc(ctx, ctx->teedev, size, flags);
--}
- EXPORT_SYMBOL_GPL(tee_shm_alloc);
-
--struct tee_shm *tee_shm_priv_alloc(struct tee_device *teedev, size_t size)
--{
-- return __tee_shm_alloc(NULL, teedev, size, TEE_SHM_MAPPED);
--}
--EXPORT_SYMBOL_GPL(tee_shm_priv_alloc);
--
- struct tee_shm *tee_shm_register(struct tee_context *ctx, unsigned long addr,
- size_t length, u32 flags)
- {
-@@ -251,7 +219,6 @@ struct tee_shm *tee_shm_register(struct tee_context *ctx, unsigned long addr,
- }
-
- shm->flags = flags | TEE_SHM_REGISTER;
-- shm->teedev = teedev;
- shm->ctx = ctx;
- shm->id = -1;
- addr = untagged_addr(addr);
-@@ -307,10 +274,6 @@ struct tee_shm *tee_shm_register(struct tee_context *ctx, unsigned long addr,
- }
- }
-
-- mutex_lock(&teedev->mutex);
-- list_add_tail(&shm->link, &ctx->list_shm);
-- mutex_unlock(&teedev->mutex);
--
- return shm;
- err:
- if (shm) {
-diff --git a/include/linux/tee_drv.h b/include/linux/tee_drv.h
-index 545a57f61a5e..407c27c11b2b 100644
---- a/include/linux/tee_drv.h
-+++ b/include/linux/tee_drv.h
-@@ -49,7 +49,6 @@ struct tee_shm_pool;
- */
- struct tee_context {
- struct tee_device *teedev;
-- struct list_head list_shm;
- void *data;
- struct kref refcount;
- bool releasing;
-@@ -184,9 +183,7 @@ int tee_session_calc_client_uuid(uuid_t *uuid, u32 connection_method,
-
- /**
- * struct tee_shm - shared memory object
-- * @teedev: device used to allocate the object
-- * @ctx: context using the object, if NULL the context is gone
-- * @link link element
-+ * @ctx: context using the object
- * @paddr: physical address of the shared memory
- * @kaddr: virtual address of the shared memory
- * @size: size of shared memory
-@@ -195,15 +192,17 @@ int tee_session_calc_client_uuid(uuid_t *uuid, u32 connection_method,
- * @num_pages: number of locked pages
- * @dmabuf: dmabuf used to for exporting to user space
- * @flags: defined by TEE_SHM_* in tee_drv.h
-- * @id: unique id of a shared memory object on this device
-+ * @id: unique id of a shared memory object on this device, shared
-+ * with user space
-+ * @sec_world_id:
-+ * secure world assigned id of this shared memory object, not
-+ * used by all drivers
- *
- * This pool is only supposed to be accessed directly from the TEE
- * subsystem and from drivers that implements their own shm pool manager.
- */
- struct tee_shm {
-- struct tee_device *teedev;
- struct tee_context *ctx;
-- struct list_head link;
- phys_addr_t paddr;
- void *kaddr;
- size_t size;
-@@ -213,6 +212,7 @@ struct tee_shm {
- struct dma_buf *dmabuf;
- u32 flags;
- int id;
-+ u64 sec_world_id;
- };
-
- /**
-@@ -334,18 +334,6 @@ void *tee_get_drvdata(struct tee_device *teedev);
- */
- struct tee_shm *tee_shm_alloc(struct tee_context *ctx, size_t size, u32 flags);
-
--/**
-- * tee_shm_priv_alloc() - Allocate shared memory privately
-- * @dev: Device that allocates the shared memory
-- * @size: Requested size of shared memory
-- *
-- * Allocates shared memory buffer that is not associated with any client
-- * context. Such buffers are owned by TEE driver and used for internal calls.
-- *
-- * @returns a pointer to 'struct tee_shm'
-- */
--struct tee_shm *tee_shm_priv_alloc(struct tee_device *teedev, size_t size);
--
- /**
- * tee_shm_register() - Register shared memory buffer
- * @ctx: Context that registers the shared memory
---
-2.26.2
-
diff --git a/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.4/tc0/0013-tee-optee-fix-mem-handle-removal-in-ffa_shm_unregist.patch b/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.4/tc0/0013-tee-optee-fix-mem-handle-removal-in-ffa_shm_unregist.patch
deleted file mode 100644
index ad2c945..0000000
--- a/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.4/tc0/0013-tee-optee-fix-mem-handle-removal-in-ffa_shm_unregist.patch
+++ /dev/null
@@ -1,51 +0,0 @@
-From 957e0145899813017a6a2b7f863a4a2b4e4b75aa Mon Sep 17 00:00:00 2001
-From: Arunachalam Ganapathy <arunachalam.ganapathy@arm.com>
-Date: Tue, 5 Jan 2021 09:27:41 +0000
-Subject: [PATCH] tee: optee: fix mem handle removal in ffa_shm_unregister
-
-Remove ffa memory handle before calling mem_reclaim. This enables the
-handle to be re-used by another thread once mem_claim for that handle
-is completed.
-
-Signed-off-by: Arunachalam Ganapathy <arunachalam.ganapathy@arm.com>
-Change-Id: I7294bd71f2bbc28514eaa09ae757dd216bc7df45
-
-Upstream-Status: Pending [Not submitted to upstream yet]
----
- drivers/tee/optee/call.c | 10 +++++-----
- 1 file changed, 5 insertions(+), 5 deletions(-)
-
-diff --git a/drivers/tee/optee/call.c b/drivers/tee/optee/call.c
-index ac89ab42a43f..9c9480add0b5 100644
---- a/drivers/tee/optee/call.c
-+++ b/drivers/tee/optee/call.c
-@@ -843,6 +843,10 @@ int optee_ffa_shm_unregister_supp(struct tee_context *ctx,
- {
- struct optee *optee = tee_get_drvdata(ctx->teedev);
- int rc = 0;
-+ u64 handle = shm->sec_world_id;
-+
-+ optee_shm_rem_ffa_handle(optee, handle);
-+ shm->sec_world_id = 0;
-
- /*
- * We're skipping the OPTEE_FFA_YIELDING_CALL_UNREGISTER_SHM call
-@@ -850,14 +854,10 @@ int optee_ffa_shm_unregister_supp(struct tee_context *ctx,
- * this ID.
- */
-
-- rc = optee->ffa.ops->mem_reclaim(shm->sec_world_id, 0);
-+ rc = optee->ffa.ops->mem_reclaim(handle, 0);
- if (rc)
- pr_err("mem_reclain: %d", rc);
-
-- optee_shm_rem_ffa_handle(optee, shm->sec_world_id);
--
-- shm->sec_world_id = 0;
--
- return rc;
- }
- #endif /*CONFIG_ARM_FFA_TRANSPORT*/
---
-2.26.2
-
diff --git a/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.4/tc0/0014-arm64-Add-support-for-asymmetric-AArch32-EL0-configu.patch b/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.4/tc0/0014-arm64-Add-support-for-asymmetric-AArch32-EL0-configu.patch
deleted file mode 100644
index 7ca9c07..0000000
--- a/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.4/tc0/0014-arm64-Add-support-for-asymmetric-AArch32-EL0-configu.patch
+++ /dev/null
@@ -1,462 +0,0 @@
-Upstream-Status: Backport [http://www.linux-arm.org/git?p=linux-power.git;a=commit;h=ce7d6e205568b7949ff26f2b3c65dc4db1c15b96]
-Signed-off-by: Usama Arif <usama.arif@arm.com>
-
-From 0316669bc2a0e1279427b7a3ed01313b70544756 Mon Sep 17 00:00:00 2001
-From: Catalin Marinas <catalin.marinas@arm.com>
-Date: Thu, 20 Jun 2019 17:59:25 +0100
-Subject: [PATCH 1/2] arm64: Add support for asymmetric AArch32 EL0
- configurations
-
-There is a non-negligible chance that we may see asymmetric big.LITTLE
-configurations where only the LITTLE CPUs have AArch32 support at EL0.
-While Linux currently handles such configurations by not allowing
-AArch32 tasks, there is a strong marketing push to investigate the
-possibility of allowing compat applications. This patch is aimed to
-facilitate internal testing and NOT FOR UPSTREAM.
-
-When the CONFIG_ASYMMETRIC_AARCH32 option is enabled (EXPERT), the type
-of the ARM64_HAS_32BIT_EL0 capability becomes WEAK_LOCAL_CPU_FEATURE.
-The kernel will now return true for system_supports_32bit_el0() and
-32-bit tasks will be migrated to the capable CPUs during
-do_notify_resume(). If the last CPU supporting 32-bit is offlined, the
-kernel will SIGKILL any scheduled 32-bit tasks (the alternative is to
-prevent offlining through a new .cpu_disable feature entry).
-
-In addition to the relaxation of the ARM64_HAS_32BIT_EL0 capability,
-this patch factors out the 32-bit cpuinfo and features setting into
-separate functions: __cpuinfo_store_cpu_32bit(),
-init_cpu_32bit_features(). The cpuinfo of the booting CPU
-(boot_cpu_data) is now updated on the first 32-bit capable CPU even if
-it is a secondary one. The ID_AA64PFR0_EL0_64BIT_ONLY feature is relaxed
-to FTR_NONSTRICT and FTR_HIGHER_SAFE when the asymmetric AArch32 support
-is enabled. The compat_elf_hwcaps are only verified for the
-AArch32-capable CPUs to still allow hotplugging AArch64-only CPUs.
-
-Cc: Suzuki K Poulose <Suzuki.Poulose@arm.com>
-Cc: Morten Rasmussen <Morten.Rasmussen@arm.com>
-Cc: Valentin Schneider <valentin.schneider@arm.com>
-Cc: Qais Yousef <qais.yousef@arm.com>
-Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
-Signed-off-by: Qais Yousef <qais.yousef@arm.com>
----
- arch/arm64/Kconfig | 13 ++++++
- arch/arm64/include/asm/cpu.h | 2 +
- arch/arm64/include/asm/cpufeature.h | 3 ++
- arch/arm64/include/asm/thread_info.h | 5 ++-
- arch/arm64/kernel/cpufeature.c | 64 ++++++++++++++++++----------
- arch/arm64/kernel/cpuinfo.c | 61 +++++++++++++++++---------
- arch/arm64/kernel/process.c | 17 ++++++++
- arch/arm64/kernel/signal.c | 30 ++++++++++++-
- 8 files changed, 150 insertions(+), 45 deletions(-)
-
-diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
-index 71d23b5d10d4..068e9e9ffc40 100644
---- a/arch/arm64/Kconfig
-+++ b/arch/arm64/Kconfig
-@@ -1680,6 +1680,19 @@ config DMI
-
- endmenu
-
-+config ASYMMETRIC_AARCH32
-+ bool "Allow support for asymmetric AArch32 support"
-+ depends on COMPAT && EXPERT && !KVM
-+ help
-+ Enable this option to allow support for asymmetric AArch32 EL0
-+ CPU configurations. Once the AArch32 EL0 support is detected
-+ on a CPU, the feature is made available to user space to allow
-+ the execution of 32-bit (compat) applications by migrating
-+ them to the capable CPUs. Offlining such CPUs leads to 32-bit
-+ applications being killed.
-+
-+ If unsure say N.
-+
- config SYSVIPC_COMPAT
- def_bool y
- depends on COMPAT && SYSVIPC
-diff --git a/arch/arm64/include/asm/cpu.h b/arch/arm64/include/asm/cpu.h
-index d72d995b7e25..39dbf5827070 100644
---- a/arch/arm64/include/asm/cpu.h
-+++ b/arch/arm64/include/asm/cpu.h
-@@ -15,6 +15,7 @@
- struct cpuinfo_arm64 {
- struct cpu cpu;
- struct kobject kobj;
-+ bool aarch32_valid;
- u32 reg_ctr;
- u32 reg_cntfrq;
- u32 reg_dczid;
-@@ -60,6 +61,7 @@ void cpuinfo_store_cpu(void);
- void __init cpuinfo_store_boot_cpu(void);
-
- void __init init_cpu_features(struct cpuinfo_arm64 *info);
-+void init_cpu_32bit_features(struct cpuinfo_arm64 *info);
- void update_cpu_features(int cpu, struct cpuinfo_arm64 *info,
- struct cpuinfo_arm64 *boot);
-
-diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
-index 9cde5d2e768f..d00d673d423b 100644
---- a/arch/arm64/include/asm/cpufeature.h
-+++ b/arch/arm64/include/asm/cpufeature.h
-@@ -17,6 +17,7 @@
- #ifndef __ASSEMBLY__
-
- #include <linux/bug.h>
-+#include <linux/cpumask.h>
- #include <linux/jump_label.h>
- #include <linux/kernel.h>
-
-@@ -370,6 +371,8 @@ cpucap_multi_entry_cap_matches(const struct arm64_cpu_capabilities *entry,
- return false;
- }
-
-+extern cpumask_t aarch32_el0_mask;
-+
- extern DECLARE_BITMAP(cpu_hwcaps, ARM64_NCAPS);
- extern struct static_key_false cpu_hwcap_keys[ARM64_NCAPS];
- extern struct static_key_false arm64_const_caps_ready;
-diff --git a/arch/arm64/include/asm/thread_info.h b/arch/arm64/include/asm/thread_info.h
-index 8c73764b9ed2..54a4c912a7ab 100644
---- a/arch/arm64/include/asm/thread_info.h
-+++ b/arch/arm64/include/asm/thread_info.h
-@@ -66,6 +66,7 @@ void arch_release_task_struct(struct task_struct *tsk);
- #define TIF_FOREIGN_FPSTATE 3 /* CPU's FP state is not current's */
- #define TIF_UPROBE 4 /* uprobe breakpoint or singlestep */
- #define TIF_FSCHECK 5 /* Check FS is USER_DS on return */
-+#define TIF_SET_32BIT_AFFINITY 6 /* set thread affinity for asymmetric AArch32 */
- #define TIF_NOHZ 7
- #define TIF_SYSCALL_TRACE 8 /* syscall trace active */
- #define TIF_SYSCALL_AUDIT 9 /* syscall auditing */
-@@ -95,11 +96,13 @@ void arch_release_task_struct(struct task_struct *tsk);
- #define _TIF_UPROBE (1 << TIF_UPROBE)
- #define _TIF_FSCHECK (1 << TIF_FSCHECK)
- #define _TIF_32BIT (1 << TIF_32BIT)
-+#define _TIF_SET_32BIT_AFFINITY (1 << TIF_SET_32BIT_AFFINITY)
- #define _TIF_SVE (1 << TIF_SVE)
-
- #define _TIF_WORK_MASK (_TIF_NEED_RESCHED | _TIF_SIGPENDING | \
- _TIF_NOTIFY_RESUME | _TIF_FOREIGN_FPSTATE | \
-- _TIF_UPROBE | _TIF_FSCHECK)
-+ _TIF_UPROBE | _TIF_FSCHECK | \
-+ _TIF_SET_32BIT_AFFINITY)
-
- #define _TIF_SYSCALL_WORK (_TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT | \
- _TIF_SYSCALL_TRACEPOINT | _TIF_SECCOMP | \
-diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
-index da92693b202c..c0d656cfe5b8 100644
---- a/arch/arm64/kernel/cpufeature.c
-+++ b/arch/arm64/kernel/cpufeature.c
-@@ -8,7 +8,6 @@
- #define pr_fmt(fmt) "CPU features: " fmt
-
- #include <linux/bsearch.h>
--#include <linux/cpumask.h>
- #include <linux/crash_dump.h>
- #include <linux/sort.h>
- #include <linux/stop_machine.h>
-@@ -164,7 +163,11 @@ static const struct arm64_ftr_bits ftr_id_aa64pfr0[] = {
- ARM64_FTR_BITS(FTR_HIDDEN, FTR_NONSTRICT, FTR_LOWER_SAFE, ID_AA64PFR0_EL3_SHIFT, 4, 0),
- ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64PFR0_EL2_SHIFT, 4, 0),
- ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64PFR0_EL1_SHIFT, 4, ID_AA64PFR0_EL1_64BIT_ONLY),
-+#ifndef CONFIG_ASYMMETRIC_AARCH32
- ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64PFR0_EL0_SHIFT, 4, ID_AA64PFR0_EL0_64BIT_ONLY),
-+#else
-+ ARM64_FTR_BITS(FTR_HIDDEN, FTR_NONSTRICT, FTR_HIGHER_SAFE, ID_AA64PFR0_EL0_SHIFT, 4, ID_AA64PFR0_EL0_64BIT_ONLY),
-+#endif
- ARM64_FTR_END,
- };
-
-@@ -509,7 +512,7 @@ static void __init sort_ftr_regs(void)
- * Any bits that are not covered by an arm64_ftr_bits entry are considered
- * RES0 for the system-wide value, and must strictly match.
- */
--static void __init init_cpu_ftr_reg(u32 sys_reg, u64 new)
-+static void init_cpu_ftr_reg(u32 sys_reg, u64 new)
- {
- u64 val = 0;
- u64 strict_mask = ~0x0ULL;
-@@ -590,25 +593,6 @@ void __init init_cpu_features(struct cpuinfo_arm64 *info)
- init_cpu_ftr_reg(SYS_ID_AA64PFR1_EL1, info->reg_id_aa64pfr1);
- init_cpu_ftr_reg(SYS_ID_AA64ZFR0_EL1, info->reg_id_aa64zfr0);
-
-- if (id_aa64pfr0_32bit_el0(info->reg_id_aa64pfr0)) {
-- init_cpu_ftr_reg(SYS_ID_DFR0_EL1, info->reg_id_dfr0);
-- init_cpu_ftr_reg(SYS_ID_ISAR0_EL1, info->reg_id_isar0);
-- init_cpu_ftr_reg(SYS_ID_ISAR1_EL1, info->reg_id_isar1);
-- init_cpu_ftr_reg(SYS_ID_ISAR2_EL1, info->reg_id_isar2);
-- init_cpu_ftr_reg(SYS_ID_ISAR3_EL1, info->reg_id_isar3);
-- init_cpu_ftr_reg(SYS_ID_ISAR4_EL1, info->reg_id_isar4);
-- init_cpu_ftr_reg(SYS_ID_ISAR5_EL1, info->reg_id_isar5);
-- init_cpu_ftr_reg(SYS_ID_MMFR0_EL1, info->reg_id_mmfr0);
-- init_cpu_ftr_reg(SYS_ID_MMFR1_EL1, info->reg_id_mmfr1);
-- init_cpu_ftr_reg(SYS_ID_MMFR2_EL1, info->reg_id_mmfr2);
-- init_cpu_ftr_reg(SYS_ID_MMFR3_EL1, info->reg_id_mmfr3);
-- init_cpu_ftr_reg(SYS_ID_PFR0_EL1, info->reg_id_pfr0);
-- init_cpu_ftr_reg(SYS_ID_PFR1_EL1, info->reg_id_pfr1);
-- init_cpu_ftr_reg(SYS_MVFR0_EL1, info->reg_mvfr0);
-- init_cpu_ftr_reg(SYS_MVFR1_EL1, info->reg_mvfr1);
-- init_cpu_ftr_reg(SYS_MVFR2_EL1, info->reg_mvfr2);
-- }
--
- if (id_aa64pfr0_sve(info->reg_id_aa64pfr0)) {
- init_cpu_ftr_reg(SYS_ZCR_EL1, info->reg_zcr);
- sve_init_vq_map();
-@@ -627,6 +611,26 @@ void __init init_cpu_features(struct cpuinfo_arm64 *info)
- setup_boot_cpu_capabilities();
- }
-
-+void init_cpu_32bit_features(struct cpuinfo_arm64 *info)
-+{
-+ init_cpu_ftr_reg(SYS_ID_DFR0_EL1, info->reg_id_dfr0);
-+ init_cpu_ftr_reg(SYS_ID_ISAR0_EL1, info->reg_id_isar0);
-+ init_cpu_ftr_reg(SYS_ID_ISAR1_EL1, info->reg_id_isar1);
-+ init_cpu_ftr_reg(SYS_ID_ISAR2_EL1, info->reg_id_isar2);
-+ init_cpu_ftr_reg(SYS_ID_ISAR3_EL1, info->reg_id_isar3);
-+ init_cpu_ftr_reg(SYS_ID_ISAR4_EL1, info->reg_id_isar4);
-+ init_cpu_ftr_reg(SYS_ID_ISAR5_EL1, info->reg_id_isar5);
-+ init_cpu_ftr_reg(SYS_ID_MMFR0_EL1, info->reg_id_mmfr0);
-+ init_cpu_ftr_reg(SYS_ID_MMFR1_EL1, info->reg_id_mmfr1);
-+ init_cpu_ftr_reg(SYS_ID_MMFR2_EL1, info->reg_id_mmfr2);
-+ init_cpu_ftr_reg(SYS_ID_MMFR3_EL1, info->reg_id_mmfr3);
-+ init_cpu_ftr_reg(SYS_ID_PFR0_EL1, info->reg_id_pfr0);
-+ init_cpu_ftr_reg(SYS_ID_PFR1_EL1, info->reg_id_pfr1);
-+ init_cpu_ftr_reg(SYS_MVFR0_EL1, info->reg_mvfr0);
-+ init_cpu_ftr_reg(SYS_MVFR1_EL1, info->reg_mvfr1);
-+ init_cpu_ftr_reg(SYS_MVFR2_EL1, info->reg_mvfr2);
-+}
-+
- static void update_cpu_ftr_reg(struct arm64_ftr_reg *reg, u64 new)
- {
- const struct arm64_ftr_bits *ftrp;
-@@ -1264,6 +1268,16 @@ static bool can_use_gic_priorities(const struct arm64_cpu_capabilities *entry,
- }
- #endif
-
-+#ifdef CONFIG_ASYMMETRIC_AARCH32
-+cpumask_t aarch32_el0_mask;
-+
-+static void cpu_enable_aarch32_el0(struct arm64_cpu_capabilities const *cap)
-+{
-+ if (has_cpuid_feature(cap, SCOPE_LOCAL_CPU))
-+ cpumask_set_cpu(smp_processor_id(), &aarch32_el0_mask);
-+}
-+#endif
-+
- static const struct arm64_cpu_capabilities arm64_features[] = {
- {
- .desc = "GIC system register CPU interface",
-@@ -1340,7 +1354,12 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
- {
- .desc = "32-bit EL0 Support",
- .capability = ARM64_HAS_32BIT_EL0,
-+#ifndef CONFIG_ASYMMETRIC_AARCH32
- .type = ARM64_CPUCAP_SYSTEM_FEATURE,
-+#else
-+ .type = ARM64_CPUCAP_WEAK_LOCAL_CPU_FEATURE,
-+ .cpu_enable = cpu_enable_aarch32_el0,
-+#endif
- .matches = has_cpuid_feature,
- .sys_reg = SYS_ID_AA64PFR0_EL1,
- .sign = FTR_UNSIGNED,
-@@ -1983,7 +2002,8 @@ static void verify_local_cpu_capabilities(void)
-
- verify_local_elf_hwcaps(arm64_elf_hwcaps);
-
-- if (system_supports_32bit_el0())
-+ if (system_supports_32bit_el0() &&
-+ this_cpu_has_cap(ARM64_HAS_32BIT_EL0))
- verify_local_elf_hwcaps(compat_elf_hwcaps);
-
- if (system_supports_sve())
-diff --git a/arch/arm64/kernel/cpuinfo.c b/arch/arm64/kernel/cpuinfo.c
-index 05933c065732..bda37687bb66 100644
---- a/arch/arm64/kernel/cpuinfo.c
-+++ b/arch/arm64/kernel/cpuinfo.c
-@@ -351,27 +351,6 @@ static void __cpuinfo_store_cpu(struct cpuinfo_arm64 *info)
- info->reg_id_aa64pfr1 = read_cpuid(ID_AA64PFR1_EL1);
- info->reg_id_aa64zfr0 = read_cpuid(ID_AA64ZFR0_EL1);
-
-- /* Update the 32bit ID registers only if AArch32 is implemented */
-- if (id_aa64pfr0_32bit_el0(info->reg_id_aa64pfr0)) {
-- info->reg_id_dfr0 = read_cpuid(ID_DFR0_EL1);
-- info->reg_id_isar0 = read_cpuid(ID_ISAR0_EL1);
-- info->reg_id_isar1 = read_cpuid(ID_ISAR1_EL1);
-- info->reg_id_isar2 = read_cpuid(ID_ISAR2_EL1);
-- info->reg_id_isar3 = read_cpuid(ID_ISAR3_EL1);
-- info->reg_id_isar4 = read_cpuid(ID_ISAR4_EL1);
-- info->reg_id_isar5 = read_cpuid(ID_ISAR5_EL1);
-- info->reg_id_mmfr0 = read_cpuid(ID_MMFR0_EL1);
-- info->reg_id_mmfr1 = read_cpuid(ID_MMFR1_EL1);
-- info->reg_id_mmfr2 = read_cpuid(ID_MMFR2_EL1);
-- info->reg_id_mmfr3 = read_cpuid(ID_MMFR3_EL1);
-- info->reg_id_pfr0 = read_cpuid(ID_PFR0_EL1);
-- info->reg_id_pfr1 = read_cpuid(ID_PFR1_EL1);
--
-- info->reg_mvfr0 = read_cpuid(MVFR0_EL1);
-- info->reg_mvfr1 = read_cpuid(MVFR1_EL1);
-- info->reg_mvfr2 = read_cpuid(MVFR2_EL1);
-- }
--
- if (IS_ENABLED(CONFIG_ARM64_SVE) &&
- id_aa64pfr0_sve(info->reg_id_aa64pfr0))
- info->reg_zcr = read_zcr_features();
-@@ -379,10 +358,46 @@ static void __cpuinfo_store_cpu(struct cpuinfo_arm64 *info)
- cpuinfo_detect_icache_policy(info);
- }
-
-+static void __cpuinfo_store_cpu_32bit(struct cpuinfo_arm64 *info)
-+{
-+ info->aarch32_valid = true;
-+
-+ info->reg_id_dfr0 = read_cpuid(ID_DFR0_EL1);
-+ info->reg_id_isar0 = read_cpuid(ID_ISAR0_EL1);
-+ info->reg_id_isar1 = read_cpuid(ID_ISAR1_EL1);
-+ info->reg_id_isar2 = read_cpuid(ID_ISAR2_EL1);
-+ info->reg_id_isar3 = read_cpuid(ID_ISAR3_EL1);
-+ info->reg_id_isar4 = read_cpuid(ID_ISAR4_EL1);
-+ info->reg_id_isar5 = read_cpuid(ID_ISAR5_EL1);
-+ info->reg_id_mmfr0 = read_cpuid(ID_MMFR0_EL1);
-+ info->reg_id_mmfr1 = read_cpuid(ID_MMFR1_EL1);
-+ info->reg_id_mmfr2 = read_cpuid(ID_MMFR2_EL1);
-+ info->reg_id_mmfr3 = read_cpuid(ID_MMFR3_EL1);
-+ info->reg_id_pfr0 = read_cpuid(ID_PFR0_EL1);
-+ info->reg_id_pfr1 = read_cpuid(ID_PFR1_EL1);
-+
-+ info->reg_mvfr0 = read_cpuid(MVFR0_EL1);
-+ info->reg_mvfr1 = read_cpuid(MVFR1_EL1);
-+ info->reg_mvfr2 = read_cpuid(MVFR2_EL1);
-+}
-+
- void cpuinfo_store_cpu(void)
- {
- struct cpuinfo_arm64 *info = this_cpu_ptr(&cpu_data);
- __cpuinfo_store_cpu(info);
-+ if (id_aa64pfr0_32bit_el0(info->reg_id_aa64pfr0))
-+ __cpuinfo_store_cpu_32bit(info);
-+ /*
-+ * With asymmetric AArch32 support, populate the boot CPU information
-+ * on the first 32-bit capable secondary CPU if the primary one
-+ * skipped this step.
-+ */
-+ if (IS_ENABLED(CONFIG_ASYMMETRIC_AARCH32) &&
-+ !boot_cpu_data.aarch32_valid &&
-+ id_aa64pfr0_32bit_el0(info->reg_id_aa64pfr0)) {
-+ __cpuinfo_store_cpu_32bit(&boot_cpu_data);
-+ init_cpu_32bit_features(&boot_cpu_data);
-+ }
- update_cpu_features(smp_processor_id(), info, &boot_cpu_data);
- }
-
-@@ -390,9 +405,13 @@ void __init cpuinfo_store_boot_cpu(void)
- {
- struct cpuinfo_arm64 *info = &per_cpu(cpu_data, 0);
- __cpuinfo_store_cpu(info);
-+ if (id_aa64pfr0_32bit_el0(info->reg_id_aa64pfr0))
-+ __cpuinfo_store_cpu_32bit(info);
-
- boot_cpu_data = *info;
- init_cpu_features(&boot_cpu_data);
-+ if (id_aa64pfr0_32bit_el0(boot_cpu_data.reg_id_aa64pfr0))
-+ init_cpu_32bit_features(&boot_cpu_data);
- }
-
- device_initcall(cpuinfo_regs_init);
-diff --git a/arch/arm64/kernel/process.c b/arch/arm64/kernel/process.c
-index cc1d8b1025b1..35f0c93699ce 100644
---- a/arch/arm64/kernel/process.c
-+++ b/arch/arm64/kernel/process.c
-@@ -494,6 +494,15 @@ static void entry_task_switch(struct task_struct *next)
- __this_cpu_write(__entry_task, next);
- }
-
-+static void aarch32_thread_switch(struct task_struct *next)
-+{
-+ struct thread_info *ti = task_thread_info(next);
-+
-+ if (IS_ENABLED(CONFIG_ASYMMETRIC_AARCH32) && is_compat_thread(ti) &&
-+ !cpumask_test_cpu(smp_processor_id(), &aarch32_el0_mask))
-+ set_ti_thread_flag(ti, TIF_SET_32BIT_AFFINITY);
-+}
-+
- /*
- * Thread switching.
- */
-@@ -511,6 +520,7 @@ __notrace_funcgraph struct task_struct *__switch_to(struct task_struct *prev,
- ptrauth_thread_switch(next);
- ssbs_thread_switch(next);
- scs_overflow_check(next);
-+ aarch32_thread_switch(next);
-
- /*
- * Complete any pending TLB or cache maintenance on this CPU in case
-@@ -569,6 +579,13 @@ void arch_setup_new_exec(void)
- current->mm->context.flags = is_compat_task() ? MMCF_AARCH32 : 0;
-
- ptrauth_thread_init_user(current);
-+
-+ /*
-+ * If exec'ing a 32-bit task, force the asymmetric 32-bit feature
-+ * check as the task may not go through a switch_to() call.
-+ */
-+ if (IS_ENABLED(CONFIG_ASYMMETRIC_AARCH32) && is_compat_task())
-+ set_thread_flag(TIF_SET_32BIT_AFFINITY);
- }
-
- #ifdef CONFIG_ARM64_TAGGED_ADDR_ABI
-diff --git a/arch/arm64/kernel/signal.c b/arch/arm64/kernel/signal.c
-index dd2cdc0d5be2..d8cdd3211d68 100644
---- a/arch/arm64/kernel/signal.c
-+++ b/arch/arm64/kernel/signal.c
-@@ -8,6 +8,7 @@
-
- #include <linux/cache.h>
- #include <linux/compat.h>
-+#include <linux/cpumask.h>
- #include <linux/errno.h>
- #include <linux/kernel.h>
- #include <linux/signal.h>
-@@ -896,6 +897,29 @@ static void do_signal(struct pt_regs *regs)
- restore_saved_sigmask();
- }
-
-+static void set_32bit_cpus_allowed(void)
-+{
-+ int ret;
-+
-+ /*
-+ * Try to honour as best as possible whatever affinity request this
-+ * task has. If it spans no compatible CPU, disregard it entirely.
-+ */
-+ if (cpumask_intersects(current->cpus_ptr, &aarch32_el0_mask)) {
-+ cpumask_t cpus_allowed;
-+
-+ cpumask_and(&cpus_allowed, current->cpus_ptr, &aarch32_el0_mask);
-+ ret = set_cpus_allowed_ptr(current, &cpus_allowed);
-+ } else {
-+ ret = set_cpus_allowed_ptr(current, &aarch32_el0_mask);
-+ }
-+
-+ if (ret) {
-+ pr_warn_once("No CPUs capable of running 32-bit tasks\n");
-+ force_sig(SIGKILL);
-+ }
-+}
-+
- asmlinkage void do_notify_resume(struct pt_regs *regs,
- unsigned long thread_flags)
- {
-@@ -910,7 +934,11 @@ asmlinkage void do_notify_resume(struct pt_regs *regs,
- /* Check valid user FS if needed */
- addr_limit_user_check();
-
-- if (thread_flags & _TIF_NEED_RESCHED) {
-+ if (IS_ENABLED(CONFIG_ASYMMETRIC_AARCH32) &&
-+ thread_flags & _TIF_SET_32BIT_AFFINITY) {
-+ clear_thread_flag(TIF_SET_32BIT_AFFINITY);
-+ set_32bit_cpus_allowed();
-+ } else if (thread_flags & _TIF_NEED_RESCHED) {
- /* Unmask Debug and SError for the next task */
- local_daif_restore(DAIF_PROCCTX_NOIRQ);
-
---
-2.29.2
-
diff --git a/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.4/tc0/0015-arm64-smp-Prevent-hotplugging-the-last-AArch32-able-.patch b/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.4/tc0/0015-arm64-smp-Prevent-hotplugging-the-last-AArch32-able-.patch
deleted file mode 100644
index 774721e..0000000
--- a/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.4/tc0/0015-arm64-smp-Prevent-hotplugging-the-last-AArch32-able-.patch
+++ /dev/null
@@ -1,89 +0,0 @@
-Upstream-Status: Backport [http://www.linux-arm.org/git?p=linux-power.git;a=commit;h=e6b567c1cc07dd1690e5d34b6a93ab9819ab2eeb]
-Signed-off-by: Usama Arif <usama.arif@arm.com>
-
-From d6acb605de7d40c295ada9b1f4c8336e4db71ae4 Mon Sep 17 00:00:00 2001
-From: Valentin Schneider <valentin.schneider@arm.com>
-Date: Thu, 5 Sep 2019 17:53:19 +0100
-Subject: [PATCH 2/2] arm64: smp: Prevent hotplugging the last AArch32-able CPU
-
-EL0 AArch32 tasks are now sigkilled when they can't run on any
-compatible CPU, either because there aren't any left (hotplug) or
-because they aren't allowed to run on those left (task affinity).
-
-However, it has been deemed valuable to prevent the loss of
-functionality resulting in offlining the last AArch32-compatible CPU.
-
-Add arch-specific hook in _cpu_down() that allows checking whether we
-can offline a cpu or not and use that hook to veto offlining the last
-AArch32 CPU.
-
-Signed-off-by: Valentin Schneider <valentin.schneider@arm.com>
-Signed-off-by: Qais Yousef <qais.yousef@arm.com>
----
- arch/arm64/kernel/smp.c | 22 ++++++++++++++++++++++
- kernel/cpu.c | 9 +++++++++
- 2 files changed, 31 insertions(+)
-
-diff --git a/arch/arm64/kernel/smp.c b/arch/arm64/kernel/smp.c
-index 038ce6263d1c..c8ab4ee29f32 100644
---- a/arch/arm64/kernel/smp.c
-+++ b/arch/arm64/kernel/smp.c
-@@ -85,6 +85,28 @@ static inline int op_cpu_kill(unsigned int cpu)
- }
- #endif
-
-+bool arch_allows_cpu_disable(int cpu, int tasks_frozen,
-+ enum cpuhp_state target)
-+{
-+ /*
-+ * Don't let the last AArch32-compatible CPU go down unless the request
-+ * is related to suspend (!tasks_frozen) then allow it to be offlined
-+ * or we'll break suspend-to-ram functionality.
-+ */
-+ if (IS_ENABLED(CONFIG_ASYMMETRIC_AARCH32) &&
-+ !cpumask_empty(&aarch32_el0_mask) &&
-+ !tasks_frozen) {
-+ cpumask_t online;
-+
-+ cpumask_and(&online, &aarch32_el0_mask, cpu_online_mask);
-+
-+ if (cpumask_weight(&online) == 1)
-+ return false;
-+ }
-+
-+ return true;
-+}
-+
-
- /*
- * Boot a secondary CPU, and assign it the specified idle task.
-diff --git a/kernel/cpu.c b/kernel/cpu.c
-index 261b5098f81c..4fae9b61f442 100644
---- a/kernel/cpu.c
-+++ b/kernel/cpu.c
-@@ -134,6 +134,12 @@ static struct cpuhp_step *cpuhp_get_step(enum cpuhp_state state)
- return cpuhp_hp_states + state;
- }
-
-+bool __weak arch_allows_cpu_disable(int cpu, int tasks_frozen,
-+ enum cpuhp_state target)
-+{
-+ return true;
-+}
-+
- /**
- * cpuhp_invoke_callback _ Invoke the callbacks for a given state
- * @cpu: The cpu for which the callback should be invoked
-@@ -985,6 +991,9 @@ static int __ref _cpu_down(unsigned int cpu, int tasks_frozen,
- if (!cpu_present(cpu))
- return -EINVAL;
-
-+ if (!arch_allows_cpu_disable(cpu, tasks_frozen, target))
-+ return -EBUSY;
-+
- cpus_write_lock();
-
- cpuhp_tasks_frozen = tasks_frozen;
---
-2.29.2
-
diff --git a/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack_5.4.bbappend b/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack_5.10.bbappend
similarity index 100%
rename from meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack_5.4.bbappend
rename to meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack_5.10.bbappend
diff --git a/meta-arm/recipes-kernel/linux/linux-arm64-ack.inc b/meta-arm/recipes-kernel/linux/linux-arm64-ack.inc
index a9d561b..261e08b 100644
--- a/meta-arm/recipes-kernel/linux/linux-arm64-ack.inc
+++ b/meta-arm/recipes-kernel/linux/linux-arm64-ack.inc
@@ -1,12 +1,12 @@
# SPDX-License-Identifier: Apache-2.0
#
-# Copyright (c) 2020 Arm Limited
+# Copyright (c) 2021 Arm Limited
#
DESCRIPTION = "Linux Android Common Kernel"
SECTION = "kernel"
LICENSE = "GPLv2"
-LIC_FILES_CHKSUM = "file://${S}/COPYING;md5=bbea815ee2795b2f4230826c0c6b8814"
+LIC_FILES_CHKSUM = "file://${S}/COPYING;md5=6bc538ed5bd9a7fc9398086aedcd7e46"
require recipes-kernel/linux/linux-yocto.inc
diff --git a/meta-arm/recipes-kernel/linux/linux-arm64-ack/0001-perf-cs-etm-Move-definition-of-traceid_list-global-v.patch b/meta-arm/recipes-kernel/linux/linux-arm64-ack/0001-perf-cs-etm-Move-definition-of-traceid_list-global-v.patch
deleted file mode 100644
index 94ab435..0000000
--- a/meta-arm/recipes-kernel/linux/linux-arm64-ack/0001-perf-cs-etm-Move-definition-of-traceid_list-global-v.patch
+++ /dev/null
@@ -1,69 +0,0 @@
-Upstream-Status: Backport
-Signed-off-by: Ross Burton <ross.burton@arm.com>
-
-From 28c69b683210b5d5321ceb71e44a77bc31a32c8a Mon Sep 17 00:00:00 2001
-From: Leo Yan <leo.yan@linaro.org>
-Date: Tue, 5 May 2020 21:36:42 +0800
-Subject: [PATCH 1/4] perf cs-etm: Move definition of 'traceid_list' global
- variable from header file
-
-The variable 'traceid_list' is defined in the header file cs-etm.h,
-if multiple C files include cs-etm.h the compiler might complaint for
-multiple definition of 'traceid_list'.
-
-To fix multiple definition error, move the definition of 'traceid_list'
-into cs-etm.c.
-
-Fixes: cd8bfd8c973e ("perf tools: Add processing of coresight metadata")
-Reported-by: Thomas Backlund <tmb@mageia.org>
-Signed-off-by: Leo Yan <leo.yan@linaro.org>
-Reviewed-by: Mathieu Poirier <mathieu.poirier@linaro.org>
-Reviewed-by: Mike Leach <mike.leach@linaro.org>
-Tested-by: Mike Leach <mike.leach@linaro.org>
-Tested-by: Thomas Backlund <tmb@mageia.org>
-Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
-Cc: Jiri Olsa <jolsa@redhat.com>
-Cc: Mark Rutland <mark.rutland@arm.com>
-Cc: Namhyung Kim <namhyung@kernel.org>
-Cc: Peter Zijlstra <peterz@infradead.org>
-Cc: Suzuki Poulouse <suzuki.poulose@arm.com>
-Cc: Tor Jeremiassen <tor@ti.com>
-Cc: linux-arm-kernel@lists.infradead.org
-Link: http://lore.kernel.org/lkml/20200505133642.4756-1-leo.yan@linaro.org
-Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
----
- tools/perf/util/cs-etm.c | 3 +++
- tools/perf/util/cs-etm.h | 3 ---
- 2 files changed, 3 insertions(+), 3 deletions(-)
-
-diff --git a/tools/perf/util/cs-etm.c b/tools/perf/util/cs-etm.c
-index f5f855fff412..50de6a1ed0ce 100644
---- a/tools/perf/util/cs-etm.c
-+++ b/tools/perf/util/cs-etm.c
-@@ -94,6 +94,9 @@ struct cs_etm_queue {
- struct cs_etm_traceid_queue **traceid_queues;
- };
-
-+/* RB tree for quick conversion between traceID and metadata pointers */
-+static struct intlist *traceid_list;
-+
- static int cs_etm__update_queues(struct cs_etm_auxtrace *etm);
- static int cs_etm__process_queues(struct cs_etm_auxtrace *etm);
- static int cs_etm__process_timeless_queues(struct cs_etm_auxtrace *etm,
-diff --git a/tools/perf/util/cs-etm.h b/tools/perf/util/cs-etm.h
-index 650ecc2a6349..4ad925d6d799 100644
---- a/tools/perf/util/cs-etm.h
-+++ b/tools/perf/util/cs-etm.h
-@@ -114,9 +114,6 @@ enum cs_etm_isa {
- CS_ETM_ISA_T32,
- };
-
--/* RB tree for quick conversion between traceID and metadata pointers */
--struct intlist *traceid_list;
--
- struct cs_etm_queue;
-
- struct cs_etm_packet {
---
-2.25.1
-
diff --git a/meta-arm/recipes-kernel/linux/linux-arm64-ack/0002-perf-tests-bp_account-Make-global-variable-static.patch b/meta-arm/recipes-kernel/linux/linux-arm64-ack/0002-perf-tests-bp_account-Make-global-variable-static.patch
deleted file mode 100644
index 142d4b7..0000000
--- a/meta-arm/recipes-kernel/linux/linux-arm64-ack/0002-perf-tests-bp_account-Make-global-variable-static.patch
+++ /dev/null
@@ -1,43 +0,0 @@
-Upstream-Status: Backport
-Signed-off-by: Ross Burton <ross.burton@arm.com>
-
-From b28dc646b4c5cd3844bd591af841494dd1de0a9f Mon Sep 17 00:00:00 2001
-From: Arnaldo Carvalho de Melo <acme@redhat.com>
-Date: Mon, 2 Mar 2020 11:13:19 -0300
-Subject: [PATCH 2/4] perf tests bp_account: Make global variable static
-
-To fix the build with newer gccs, that without this patch exit with:
-
- LD /tmp/build/perf/tests/perf-in.o
- ld: /tmp/build/perf/tests/bp_account.o:/git/perf/tools/perf/tests/bp_account.c:22: multiple definition of `the_var'; /tmp/build/perf/tests/bp_signal.o:/git/perf/tools/perf/tests/bp_signal.c:38: first defined here
- make[4]: *** [/git/perf/tools/build/Makefile.build:145: /tmp/build/perf/tests/perf-in.o] Error 1
-
-First noticed in fedora:rawhide/32 with:
-
- [perfbuilder@a5ff49d6e6e4 ~]$ gcc --version
- gcc (GCC) 10.0.1 20200216 (Red Hat 10.0.1-0.8)
-
-Reported-by: Jiri Olsa <jolsa@kernel.org>
-Cc: Adrian Hunter <adrian.hunter@intel.com>
-Cc: Namhyung Kim <namhyung@kernel.org>
-Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
----
- tools/perf/tests/bp_account.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/tools/perf/tests/bp_account.c b/tools/perf/tests/bp_account.c
-index 016bba2c142d..55a9de311d7b 100644
---- a/tools/perf/tests/bp_account.c
-+++ b/tools/perf/tests/bp_account.c
-@@ -23,7 +23,7 @@
- #include "../perf-sys.h"
- #include "cloexec.h"
-
--volatile long the_var;
-+static volatile long the_var;
-
- static noinline int test_function(void)
- {
---
-2.25.1
-
diff --git a/meta-arm/recipes-kernel/linux/linux-arm64-ack/0003-perf-bench-Share-some-global-variables-to-fix-build-.patch b/meta-arm/recipes-kernel/linux/linux-arm64-ack/0003-perf-bench-Share-some-global-variables-to-fix-build-.patch
deleted file mode 100644
index 965cc38..0000000
--- a/meta-arm/recipes-kernel/linux/linux-arm64-ack/0003-perf-bench-Share-some-global-variables-to-fix-build-.patch
+++ /dev/null
@@ -1,240 +0,0 @@
-Upstream-Status: Backport
-Signed-off-by: Ross Burton <ross.burton@arm.com>
-
-From e6ae6031755b6781af42af28f11186bb18e94842 Mon Sep 17 00:00:00 2001
-From: Arnaldo Carvalho de Melo <acme@redhat.com>
-Date: Mon, 2 Mar 2020 12:09:38 -0300
-Subject: [PATCH 3/4] perf bench: Share some global variables to fix build with
- gcc 10
-
-Noticed with gcc 10 (fedora rawhide) that those variables were not being
-declared as static, so end up with:
-
- ld: /tmp/build/perf/bench/epoll-wait.o:/git/perf/tools/perf/bench/epoll-wait.c:93: multiple definition of `end'; /tmp/build/perf/bench/futex-hash.o:/git/perf/tools/perf/bench/futex-hash.c:40: first defined here
- ld: /tmp/build/perf/bench/epoll-wait.o:/git/perf/tools/perf/bench/epoll-wait.c:93: multiple definition of `start'; /tmp/build/perf/bench/futex-hash.o:/git/perf/tools/perf/bench/futex-hash.c:40: first defined here
- ld: /tmp/build/perf/bench/epoll-wait.o:/git/perf/tools/perf/bench/epoll-wait.c:93: multiple definition of `runtime'; /tmp/build/perf/bench/futex-hash.o:/git/perf/tools/perf/bench/futex-hash.c:40: first defined here
- ld: /tmp/build/perf/bench/epoll-ctl.o:/git/perf/tools/perf/bench/epoll-ctl.c:38: multiple definition of `end'; /tmp/build/perf/bench/futex-hash.o:/git/perf/tools/perf/bench/futex-hash.c:40: first defined here
- ld: /tmp/build/perf/bench/epoll-ctl.o:/git/perf/tools/perf/bench/epoll-ctl.c:38: multiple definition of `start'; /tmp/build/perf/bench/futex-hash.o:/git/perf/tools/perf/bench/futex-hash.c:40: first defined here
- ld: /tmp/build/perf/bench/epoll-ctl.o:/git/perf/tools/perf/bench/epoll-ctl.c:38: multiple definition of `runtime'; /tmp/build/perf/bench/futex-hash.o:/git/perf/tools/perf/bench/futex-hash.c:40: first defined here
- make[4]: *** [/git/perf/tools/build/Makefile.build:145: /tmp/build/perf/bench/perf-in.o] Error 1
-
-Prefix those with bench__ and add them to bench/bench.h, so that we can
-share those on the tools needing to access those variables from signal
-handlers.
-
-Acked-by: Thomas Gleixner <tglx@linutronix.de>
-Cc: Adrian Hunter <adrian.hunter@intel.com>
-Cc: Davidlohr Bueso <dave@stgolabs.net>
-Cc: Jiri Olsa <jolsa@kernel.org>
-Cc: Namhyung Kim <namhyung@kernel.org>
-Link: http://lore.kernel.org/lkml/20200303155811.GD13702@kernel.org
-Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
----
- tools/perf/bench/bench.h | 4 ++++
- tools/perf/bench/epoll-ctl.c | 7 +++----
- tools/perf/bench/epoll-wait.c | 11 +++++------
- tools/perf/bench/futex-hash.c | 12 ++++++------
- tools/perf/bench/futex-lock-pi.c | 11 +++++------
- 5 files changed, 23 insertions(+), 22 deletions(-)
-
-diff --git a/tools/perf/bench/bench.h b/tools/perf/bench/bench.h
-index fddb3ced9db6..4aa6de1aa67d 100644
---- a/tools/perf/bench/bench.h
-+++ b/tools/perf/bench/bench.h
-@@ -2,6 +2,10 @@
- #ifndef BENCH_H
- #define BENCH_H
-
-+#include <sys/time.h>
-+
-+extern struct timeval bench__start, bench__end, bench__runtime;
-+
- /*
- * The madvise transparent hugepage constants were added in glibc
- * 2.13. For compatibility with older versions of glibc, define these
-diff --git a/tools/perf/bench/epoll-ctl.c b/tools/perf/bench/epoll-ctl.c
-index bb617e568841..a7526c05df38 100644
---- a/tools/perf/bench/epoll-ctl.c
-+++ b/tools/perf/bench/epoll-ctl.c
-@@ -35,7 +35,6 @@
-
- static unsigned int nthreads = 0;
- static unsigned int nsecs = 8;
--struct timeval start, end, runtime;
- static bool done, __verbose, randomize;
-
- /*
-@@ -94,8 +93,8 @@ static void toggle_done(int sig __maybe_unused,
- {
- /* inform all threads that we're done for the day */
- done = true;
-- gettimeofday(&end, NULL);
-- timersub(&end, &start, &runtime);
-+ gettimeofday(&bench__end, NULL);
-+ timersub(&bench__end, &bench__start, &bench__runtime);
- }
-
- static void nest_epollfd(void)
-@@ -361,7 +360,7 @@ int bench_epoll_ctl(int argc, const char **argv)
-
- threads_starting = nthreads;
-
-- gettimeofday(&start, NULL);
-+ gettimeofday(&bench__start, NULL);
-
- do_threads(worker, cpu);
-
-diff --git a/tools/perf/bench/epoll-wait.c b/tools/perf/bench/epoll-wait.c
-index 7af694437f4e..d1c5cb526b9f 100644
---- a/tools/perf/bench/epoll-wait.c
-+++ b/tools/perf/bench/epoll-wait.c
-@@ -90,7 +90,6 @@
-
- static unsigned int nthreads = 0;
- static unsigned int nsecs = 8;
--struct timeval start, end, runtime;
- static bool wdone, done, __verbose, randomize, nonblocking;
-
- /*
-@@ -276,8 +275,8 @@ static void toggle_done(int sig __maybe_unused,
- {
- /* inform all threads that we're done for the day */
- done = true;
-- gettimeofday(&end, NULL);
-- timersub(&end, &start, &runtime);
-+ gettimeofday(&bench__end, NULL);
-+ timersub(&bench__end, &bench__start, &bench__runtime);
- }
-
- static void print_summary(void)
-@@ -287,7 +286,7 @@ static void print_summary(void)
-
- printf("\nAveraged %ld operations/sec (+- %.2f%%), total secs = %d\n",
- avg, rel_stddev_stats(stddev, avg),
-- (int) runtime.tv_sec);
-+ (int)bench__runtime.tv_sec);
- }
-
- static int do_threads(struct worker *worker, struct perf_cpu_map *cpu)
-@@ -479,7 +478,7 @@ int bench_epoll_wait(int argc, const char **argv)
-
- threads_starting = nthreads;
-
-- gettimeofday(&start, NULL);
-+ gettimeofday(&bench__start, NULL);
-
- do_threads(worker, cpu);
-
-@@ -519,7 +518,7 @@ int bench_epoll_wait(int argc, const char **argv)
- qsort(worker, nthreads, sizeof(struct worker), cmpworker);
-
- for (i = 0; i < nthreads; i++) {
-- unsigned long t = worker[i].ops/runtime.tv_sec;
-+ unsigned long t = worker[i].ops / bench__runtime.tv_sec;
-
- update_stats(&throughput_stats, t);
-
-diff --git a/tools/perf/bench/futex-hash.c b/tools/perf/bench/futex-hash.c
-index 8ba0c3330a9a..21776862e940 100644
---- a/tools/perf/bench/futex-hash.c
-+++ b/tools/perf/bench/futex-hash.c
-@@ -37,7 +37,7 @@ static unsigned int nfutexes = 1024;
- static bool fshared = false, done = false, silent = false;
- static int futex_flag = 0;
-
--struct timeval start, end, runtime;
-+struct timeval bench__start, bench__end, bench__runtime;
- static pthread_mutex_t thread_lock;
- static unsigned int threads_starting;
- static struct stats throughput_stats;
-@@ -103,8 +103,8 @@ static void toggle_done(int sig __maybe_unused,
- {
- /* inform all threads that we're done for the day */
- done = true;
-- gettimeofday(&end, NULL);
-- timersub(&end, &start, &runtime);
-+ gettimeofday(&bench__end, NULL);
-+ timersub(&bench__end, &bench__start, &bench__runtime);
- }
-
- static void print_summary(void)
-@@ -114,7 +114,7 @@ static void print_summary(void)
-
- printf("%sAveraged %ld operations/sec (+- %.2f%%), total secs = %d\n",
- !silent ? "\n" : "", avg, rel_stddev_stats(stddev, avg),
-- (int) runtime.tv_sec);
-+ (int)bench__runtime.tv_sec);
- }
-
- int bench_futex_hash(int argc, const char **argv)
-@@ -161,7 +161,7 @@ int bench_futex_hash(int argc, const char **argv)
-
- threads_starting = nthreads;
- pthread_attr_init(&thread_attr);
-- gettimeofday(&start, NULL);
-+ gettimeofday(&bench__start, NULL);
- for (i = 0; i < nthreads; i++) {
- worker[i].tid = i;
- worker[i].futex = calloc(nfutexes, sizeof(*worker[i].futex));
-@@ -204,7 +204,7 @@ int bench_futex_hash(int argc, const char **argv)
- pthread_mutex_destroy(&thread_lock);
-
- for (i = 0; i < nthreads; i++) {
-- unsigned long t = worker[i].ops/runtime.tv_sec;
-+ unsigned long t = worker[i].ops / bench__runtime.tv_sec;
- update_stats(&throughput_stats, t);
- if (!silent) {
- if (nfutexes == 1)
-diff --git a/tools/perf/bench/futex-lock-pi.c b/tools/perf/bench/futex-lock-pi.c
-index d0cae8125423..30d97121dc4f 100644
---- a/tools/perf/bench/futex-lock-pi.c
-+++ b/tools/perf/bench/futex-lock-pi.c
-@@ -37,7 +37,6 @@ static bool silent = false, multi = false;
- static bool done = false, fshared = false;
- static unsigned int nthreads = 0;
- static int futex_flag = 0;
--struct timeval start, end, runtime;
- static pthread_mutex_t thread_lock;
- static unsigned int threads_starting;
- static struct stats throughput_stats;
-@@ -64,7 +63,7 @@ static void print_summary(void)
-
- printf("%sAveraged %ld operations/sec (+- %.2f%%), total secs = %d\n",
- !silent ? "\n" : "", avg, rel_stddev_stats(stddev, avg),
-- (int) runtime.tv_sec);
-+ (int)bench__runtime.tv_sec);
- }
-
- static void toggle_done(int sig __maybe_unused,
-@@ -73,8 +72,8 @@ static void toggle_done(int sig __maybe_unused,
- {
- /* inform all threads that we're done for the day */
- done = true;
-- gettimeofday(&end, NULL);
-- timersub(&end, &start, &runtime);
-+ gettimeofday(&bench__end, NULL);
-+ timersub(&bench__end, &bench__start, &bench__runtime);
- }
-
- static void *workerfn(void *arg)
-@@ -185,7 +184,7 @@ int bench_futex_lock_pi(int argc, const char **argv)
-
- threads_starting = nthreads;
- pthread_attr_init(&thread_attr);
-- gettimeofday(&start, NULL);
-+ gettimeofday(&bench__start, NULL);
-
- create_threads(worker, thread_attr, cpu);
- pthread_attr_destroy(&thread_attr);
-@@ -211,7 +210,7 @@ int bench_futex_lock_pi(int argc, const char **argv)
- pthread_mutex_destroy(&thread_lock);
-
- for (i = 0; i < nthreads; i++) {
-- unsigned long t = worker[i].ops/runtime.tv_sec;
-+ unsigned long t = worker[i].ops / bench__runtime.tv_sec;
-
- update_stats(&throughput_stats, t);
- if (!silent)
---
-2.25.1
-
diff --git a/meta-arm/recipes-kernel/linux/linux-arm64-ack/0004-libtraceevent-Fix-build-with-binutils-2.35.patch b/meta-arm/recipes-kernel/linux/linux-arm64-ack/0004-libtraceevent-Fix-build-with-binutils-2.35.patch
deleted file mode 100644
index 5e18157..0000000
--- a/meta-arm/recipes-kernel/linux/linux-arm64-ack/0004-libtraceevent-Fix-build-with-binutils-2.35.patch
+++ /dev/null
@@ -1,39 +0,0 @@
-Upstream-Status: Backport
-Signed-off-by: Ross Burton <ross.burton@arm.com>
-
-From c2c2c58915def6cda401d1782048d23b2b02ed85 Mon Sep 17 00:00:00 2001
-From: Ben Hutchings <ben@decadent.org.uk>
-Date: Sat, 25 Jul 2020 02:06:23 +0100
-Subject: [PATCH 4/4] libtraceevent: Fix build with binutils 2.35
-
-In binutils 2.35, 'nm -D' changed to show symbol versions along with
-symbol names, with the usual @@ separator. When generating
-libtraceevent-dynamic-list we need just the names, so strip off the
-version suffix if present.
-
-Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
-Tested-by: Salvatore Bonaccorso <carnil@debian.org>
-Reviewed-by: Steven Rostedt <rostedt@goodmis.org>
-Cc: linux-trace-devel@vger.kernel.org
-Cc: stable@vger.kernel.org
-Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
----
- tools/lib/traceevent/plugins/Makefile | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/tools/lib/traceevent/plugins/Makefile b/tools/lib/traceevent/plugins/Makefile
-index f440989fa55e..23c3535bcbd6 100644
---- a/tools/lib/traceevent/plugins/Makefile
-+++ b/tools/lib/traceevent/plugins/Makefile
-@@ -196,7 +196,7 @@ define do_generate_dynamic_list_file
- xargs echo "U w W" | tr 'w ' 'W\n' | sort -u | xargs echo`;\
- if [ "$$symbol_type" = "U W" ];then \
- (echo '{'; \
-- $(NM) -u -D $1 | awk 'NF>1 {print "\t"$$2";"}' | sort -u;\
-+ $(NM) -u -D $1 | awk 'NF>1 {sub("@.*", "", $$2); print "\t"$$2";"}' | sort -u;\
- echo '};'; \
- ) > $2; \
- else \
---
-2.25.1
-
diff --git a/meta-arm/recipes-kernel/linux/linux-arm64-ack_5.10.bb b/meta-arm/recipes-kernel/linux/linux-arm64-ack_5.10.bb
new file mode 100644
index 0000000..e71bdd0
--- /dev/null
+++ b/meta-arm/recipes-kernel/linux/linux-arm64-ack_5.10.bb
@@ -0,0 +1,12 @@
+# SPDX-License-Identifier: Apache-2.0
+#
+# Copyright (c) 2021 Arm Limited
+#
+require linux-arm64-ack.inc
+
+SRC_URI = " \
+ git://android.googlesource.com/kernel/common.git;protocol=https;branch=android12-5.10-lts \
+ "
+
+# tag: ASB-2021-06-05_12-5.10
+SRCREV = "00dc4c64e6592a2e469f7886a6a927778c4a2806"
diff --git a/meta-arm/recipes-kernel/linux/linux-arm64-ack_5.4.bb b/meta-arm/recipes-kernel/linux/linux-arm64-ack_5.4.bb
deleted file mode 100644
index aab2fd1..0000000
--- a/meta-arm/recipes-kernel/linux/linux-arm64-ack_5.4.bb
+++ /dev/null
@@ -1,16 +0,0 @@
-# SPDX-License-Identifier: Apache-2.0
-#
-# Copyright (c) 2020 Arm Limited
-#
-require linux-arm64-ack.inc
-
-SRC_URI = " \
- git://android.googlesource.com/kernel/common.git;protocol=https;branch=android11-5.4-lts \
- file://0001-perf-cs-etm-Move-definition-of-traceid_list-global-v.patch \
- file://0002-perf-tests-bp_account-Make-global-variable-static.patch \
- file://0003-perf-bench-Share-some-global-variables-to-fix-build-.patch \
- file://0004-libtraceevent-Fix-build-with-binutils-2.35.patch \
- "
-
-# ASB-2020-07-05_5.4-stable tag commit
-SRCREV = "056684c0d252f75c13be4abb7408f692eedab653"
--
2.29.2
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH 2/6] arm-bsp/linux: add ffa driver to TC0
2021-07-22 11:32 [PATCH 1/6] arm: update Android common kernel Arunachalam Ganapathy
@ 2021-07-22 11:32 ` Arunachalam Ganapathy
2021-07-22 11:32 ` [PATCH 3/6] arm-bsp/tc0: Update optee to 3.14.0 Arunachalam Ganapathy
` (3 subsequent siblings)
4 siblings, 0 replies; 6+ messages in thread
From: Arunachalam Ganapathy @ 2021-07-22 11:32 UTC (permalink / raw)
To: meta-arm; +Cc: nd, Arunachalam Ganapathy
This includes the initial version of ffa driver and optee driver
support for FF-A to ACK 5.10
Signed-off-by: Arunachalam Ganapathy <arunachalam.ganapathy@arm.com>
Change-Id: I8a2c6d0e26422bd2183f3c1f370b0c08eeba7c1e
---
.../linux/linux-arm-platforms.inc | 13 +
...support-for-SMCCCv1.2-extended-input.patch | 188 +++
...-Add-initial-FFA-bus-support-for-dev.patch | 420 ++++++
...a-Add-initial-Arm-FFA-driver-support.patch | 415 ++++++
...-Add-support-for-SMCCC-as-transport-.patch | 115 ++
...-Setup-in-kernel-users-of-FFA-partit.patch | 398 ++++++
..._ffa-Add-support-for-MEM_-interfaces.patch | 406 ++++++
...e-add-sec_world_id-to-struct-tee_shm.patch | 44 +
.../0016-optee-simplify-optee_release.patch | 179 +++
| 644 +++++++++
...actor-driver-with-internal-callbacks.patch | 720 ++++++++++
.../0019-optee-add-a-FF-A-memory-pool.patch | 131 ++
.../tc0/0020-optee-add-FF-A-support.patch | 1269 +++++++++++++++++
...-optee-hack-for-UUID-endianess-issue.patch | 58 +
14 files changed, 5000 insertions(+)
create mode 100644 meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc0/0009-arm64-smccc-Add-support-for-SMCCCv1.2-extended-input.patch
create mode 100644 meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc0/0010-firmware-arm_ffa-Add-initial-FFA-bus-support-for-dev.patch
create mode 100644 meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc0/0011-firmware-arm_ffa-Add-initial-Arm-FFA-driver-support.patch
create mode 100644 meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc0/0012-firmware-arm_ffa-Add-support-for-SMCCC-as-transport-.patch
create mode 100644 meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc0/0013-firmware-arm_ffa-Setup-in-kernel-users-of-FFA-partit.patch
create mode 100644 meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc0/0014-firmware-arm_ffa-Add-support-for-MEM_-interfaces.patch
create mode 100644 meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc0/0015-tee-add-sec_world_id-to-struct-tee_shm.patch
create mode 100644 meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc0/0016-optee-simplify-optee_release.patch
create mode 100644 meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc0/0017-optee-sync-OP-TEE-headers.patch
create mode 100644 meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc0/0018-optee-refactor-driver-with-internal-callbacks.patch
create mode 100644 meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc0/0019-optee-add-a-FF-A-memory-pool.patch
create mode 100644 meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc0/0020-optee-add-FF-A-support.patch
create mode 100644 meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc0/0021-drivers-optee-hack-for-UUID-endianess-issue.patch
diff --git a/meta-arm-bsp/recipes-kernel/linux/linux-arm-platforms.inc b/meta-arm-bsp/recipes-kernel/linux/linux-arm-platforms.inc
index 0a679da..ef87fd6 100644
--- a/meta-arm-bsp/recipes-kernel/linux/linux-arm-platforms.inc
+++ b/meta-arm-bsp/recipes-kernel/linux/linux-arm-platforms.inc
@@ -85,6 +85,19 @@ SRC_URI_append_tc0 = " \
file://0006-mailbox-arm_mhuv2-Fix-sparse-warnings.patch \
file://0007-mailbox-arm_mhuv2-make-remove-callback-return-void.patch \
file://0008-mailbox-arm_mhuv2-Skip-calling-kfree-with-invalid-po.patch \
+ file://0009-arm64-smccc-Add-support-for-SMCCCv1.2-extended-input.patch \
+ file://0010-firmware-arm_ffa-Add-initial-FFA-bus-support-for-dev.patch \
+ file://0011-firmware-arm_ffa-Add-initial-Arm-FFA-driver-support.patch \
+ file://0012-firmware-arm_ffa-Add-support-for-SMCCC-as-transport-.patch \
+ file://0013-firmware-arm_ffa-Setup-in-kernel-users-of-FFA-partit.patch \
+ file://0014-firmware-arm_ffa-Add-support-for-MEM_-interfaces.patch \
+ file://0015-tee-add-sec_world_id-to-struct-tee_shm.patch \
+ file://0016-optee-simplify-optee_release.patch \
+ file://0017-optee-sync-OP-TEE-headers.patch \
+ file://0018-optee-refactor-driver-with-internal-callbacks.patch \
+ file://0019-optee-add-a-FF-A-memory-pool.patch \
+ file://0020-optee-add-FF-A-support.patch \
+ file://0021-drivers-optee-hack-for-UUID-endianess-issue.patch \
"
#
diff --git a/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc0/0009-arm64-smccc-Add-support-for-SMCCCv1.2-extended-input.patch b/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc0/0009-arm64-smccc-Add-support-for-SMCCCv1.2-extended-input.patch
new file mode 100644
index 0000000..ddcc488
--- /dev/null
+++ b/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc0/0009-arm64-smccc-Add-support-for-SMCCCv1.2-extended-input.patch
@@ -0,0 +1,188 @@
+From 6cc4b54570d508413982d86bf68f60ccdb8687f8 Mon Sep 17 00:00:00 2001
+From: Sudeep Holla <sudeep.holla@arm.com>
+Date: Fri, 30 Apr 2021 11:24:24 +0100
+Subject: [PATCH 01/14] arm64: smccc: Add support for SMCCCv1.2 extended
+ input/output registers
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+SMCCC v1.2 allows x8-x17 to be used as parameter registers and x4—x17
+to be used as result registers in SMC64/HVC64. Arm Firmware Framework
+for Armv8-A specification makes use of x0-x7 as parameter and result
+registers. There are other users like Hyper-V who intend to use beyond
+x0-x7 as well.
+
+Current SMCCC interface in the kernel just use x0-x7 as parameter and
+x0-x3 as result registers as required by SMCCCv1.0. Let us add new
+interface to support this extended set of input/output registers namely
+x0-x17 as both parameter and result registers.
+
+Acked-by: Mark Rutland <mark.rutland@arm.com>
+Tested-by: Michael Kelley <mikelley@microsoft.com>
+Reviewed-by: Michael Kelley <mikelley@microsoft.com>
+Cc: Will Deacon <will@kernel.org>
+Cc: Catalin Marinas <catalin.marinas@arm.com>
+Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
+
+Upstream-Status: Backport [https://git.kernel.org/pub/scm/linux/kernel/git/sudeep.holla/linux.git/commit/?h=v5.10/ffa&id=d3d7f68912d370e80f7c293e04c8fecf76d704c5]
+---
+ arch/arm64/kernel/asm-offsets.c | 9 ++++++
+ arch/arm64/kernel/smccc-call.S | 57 +++++++++++++++++++++++++++++++++
+ include/linux/arm-smccc.h | 55 +++++++++++++++++++++++++++++++
+ 3 files changed, 121 insertions(+)
+
+diff --git a/arch/arm64/kernel/asm-offsets.c b/arch/arm64/kernel/asm-offsets.c
+index f396d951ee54..6545c497064e 100644
+--- a/arch/arm64/kernel/asm-offsets.c
++++ b/arch/arm64/kernel/asm-offsets.c
+@@ -138,6 +138,15 @@ int main(void)
+ DEFINE(ARM_SMCCC_RES_X2_OFFS, offsetof(struct arm_smccc_res, a2));
+ DEFINE(ARM_SMCCC_QUIRK_ID_OFFS, offsetof(struct arm_smccc_quirk, id));
+ DEFINE(ARM_SMCCC_QUIRK_STATE_OFFS, offsetof(struct arm_smccc_quirk, state));
++ DEFINE(ARM_SMCCC_1_2_REGS_X0_OFFS, offsetof(struct arm_smccc_1_2_regs, a0));
++ DEFINE(ARM_SMCCC_1_2_REGS_X2_OFFS, offsetof(struct arm_smccc_1_2_regs, a2));
++ DEFINE(ARM_SMCCC_1_2_REGS_X4_OFFS, offsetof(struct arm_smccc_1_2_regs, a4));
++ DEFINE(ARM_SMCCC_1_2_REGS_X6_OFFS, offsetof(struct arm_smccc_1_2_regs, a6));
++ DEFINE(ARM_SMCCC_1_2_REGS_X8_OFFS, offsetof(struct arm_smccc_1_2_regs, a8));
++ DEFINE(ARM_SMCCC_1_2_REGS_X10_OFFS, offsetof(struct arm_smccc_1_2_regs, a10));
++ DEFINE(ARM_SMCCC_1_2_REGS_X12_OFFS, offsetof(struct arm_smccc_1_2_regs, a12));
++ DEFINE(ARM_SMCCC_1_2_REGS_X14_OFFS, offsetof(struct arm_smccc_1_2_regs, a14));
++ DEFINE(ARM_SMCCC_1_2_REGS_X16_OFFS, offsetof(struct arm_smccc_1_2_regs, a16));
+ BLANK();
+ DEFINE(HIBERN_PBE_ORIG, offsetof(struct pbe, orig_address));
+ DEFINE(HIBERN_PBE_ADDR, offsetof(struct pbe, address));
+diff --git a/arch/arm64/kernel/smccc-call.S b/arch/arm64/kernel/smccc-call.S
+index d62447964ed9..2def9d0dd3dd 100644
+--- a/arch/arm64/kernel/smccc-call.S
++++ b/arch/arm64/kernel/smccc-call.S
+@@ -43,3 +43,60 @@ SYM_FUNC_START(__arm_smccc_hvc)
+ SMCCC hvc
+ SYM_FUNC_END(__arm_smccc_hvc)
+ EXPORT_SYMBOL(__arm_smccc_hvc)
++
++ .macro SMCCC_1_2 instr
++ /* Save `res` and free a GPR that won't be clobbered */
++ stp x1, x19, [sp, #-16]!
++
++ /* Ensure `args` won't be clobbered while loading regs in next step */
++ mov x19, x0
++
++ /* Load the registers x0 - x17 from the struct arm_smccc_1_2_regs */
++ ldp x0, x1, [x19, #ARM_SMCCC_1_2_REGS_X0_OFFS]
++ ldp x2, x3, [x19, #ARM_SMCCC_1_2_REGS_X2_OFFS]
++ ldp x4, x5, [x19, #ARM_SMCCC_1_2_REGS_X4_OFFS]
++ ldp x6, x7, [x19, #ARM_SMCCC_1_2_REGS_X6_OFFS]
++ ldp x8, x9, [x19, #ARM_SMCCC_1_2_REGS_X8_OFFS]
++ ldp x10, x11, [x19, #ARM_SMCCC_1_2_REGS_X10_OFFS]
++ ldp x12, x13, [x19, #ARM_SMCCC_1_2_REGS_X12_OFFS]
++ ldp x14, x15, [x19, #ARM_SMCCC_1_2_REGS_X14_OFFS]
++ ldp x16, x17, [x19, #ARM_SMCCC_1_2_REGS_X16_OFFS]
++
++ \instr #0
++
++ /* Load the `res` from the stack */
++ ldr x19, [sp]
++
++ /* Store the registers x0 - x17 into the result structure */
++ stp x0, x1, [x19, #ARM_SMCCC_1_2_REGS_X0_OFFS]
++ stp x2, x3, [x19, #ARM_SMCCC_1_2_REGS_X2_OFFS]
++ stp x4, x5, [x19, #ARM_SMCCC_1_2_REGS_X4_OFFS]
++ stp x6, x7, [x19, #ARM_SMCCC_1_2_REGS_X6_OFFS]
++ stp x8, x9, [x19, #ARM_SMCCC_1_2_REGS_X8_OFFS]
++ stp x10, x11, [x19, #ARM_SMCCC_1_2_REGS_X10_OFFS]
++ stp x12, x13, [x19, #ARM_SMCCC_1_2_REGS_X12_OFFS]
++ stp x14, x15, [x19, #ARM_SMCCC_1_2_REGS_X14_OFFS]
++ stp x16, x17, [x19, #ARM_SMCCC_1_2_REGS_X16_OFFS]
++
++ /* Restore original x19 */
++ ldp xzr, x19, [sp], #16
++ ret
++.endm
++
++/*
++ * void arm_smccc_1_2_hvc(const struct arm_smccc_1_2_regs *args,
++ * struct arm_smccc_1_2_regs *res);
++ */
++SYM_FUNC_START(arm_smccc_1_2_hvc)
++ SMCCC_1_2 hvc
++SYM_FUNC_END(arm_smccc_1_2_hvc)
++EXPORT_SYMBOL(arm_smccc_1_2_hvc)
++
++/*
++ * void arm_smccc_1_2_smc(const struct arm_smccc_1_2_regs *args,
++ * struct arm_smccc_1_2_regs *res);
++ */
++SYM_FUNC_START(arm_smccc_1_2_smc)
++ SMCCC_1_2 smc
++SYM_FUNC_END(arm_smccc_1_2_smc)
++EXPORT_SYMBOL(arm_smccc_1_2_smc)
+diff --git a/include/linux/arm-smccc.h b/include/linux/arm-smccc.h
+index 62c54234576c..c8eb24af3c62 100644
+--- a/include/linux/arm-smccc.h
++++ b/include/linux/arm-smccc.h
+@@ -186,6 +186,61 @@ struct arm_smccc_res {
+ unsigned long a3;
+ };
+
++#ifdef CONFIG_ARM64
++/**
++ * struct arm_smccc_1_2_regs - Arguments for or Results from SMC/HVC call
++ * @a0-a17 argument values from registers 0 to 17
++ */
++struct arm_smccc_1_2_regs {
++ unsigned long a0;
++ unsigned long a1;
++ unsigned long a2;
++ unsigned long a3;
++ unsigned long a4;
++ unsigned long a5;
++ unsigned long a6;
++ unsigned long a7;
++ unsigned long a8;
++ unsigned long a9;
++ unsigned long a10;
++ unsigned long a11;
++ unsigned long a12;
++ unsigned long a13;
++ unsigned long a14;
++ unsigned long a15;
++ unsigned long a16;
++ unsigned long a17;
++};
++
++/**
++ * arm_smccc_1_2_hvc() - make HVC calls
++ * @args: arguments passed via struct arm_smccc_1_2_regs
++ * @res: result values via struct arm_smccc_1_2_regs
++ *
++ * This function is used to make HVC calls following SMC Calling Convention
++ * v1.2 or above. The content of the supplied param are copied from the
++ * structure to registers prior to the HVC instruction. The return values
++ * are updated with the content from registers on return from the HVC
++ * instruction.
++ */
++asmlinkage void arm_smccc_1_2_hvc(const struct arm_smccc_1_2_regs *args,
++ struct arm_smccc_1_2_regs *res);
++
++/**
++ * arm_smccc_1_2_smc() - make SMC calls
++ * @args: arguments passed via struct arm_smccc_1_2_regs
++ * @res: result values via struct arm_smccc_1_2_regs
++ *
++ * This function is used to make SMC calls following SMC Calling Convention
++ * v1.2 or above. The content of the supplied param are copied from the
++ * structure to registers prior to the SMC instruction. The return values
++ * are updated with the content from registers on return from the SMC
++ * instruction.
++ */
++asmlinkage void arm_smccc_1_2_smc(const struct arm_smccc_1_2_regs *args,
++ struct arm_smccc_1_2_regs *res);
++#endif
++
+ /**
+ * struct arm_smccc_quirk - Contains quirk information
+ * @id: quirk identification
+--
+2.29.2
+
diff --git a/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc0/0010-firmware-arm_ffa-Add-initial-FFA-bus-support-for-dev.patch b/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc0/0010-firmware-arm_ffa-Add-initial-FFA-bus-support-for-dev.patch
new file mode 100644
index 0000000..1083ffe
--- /dev/null
+++ b/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc0/0010-firmware-arm_ffa-Add-initial-FFA-bus-support-for-dev.patch
@@ -0,0 +1,420 @@
+From 12e789c445956198f2c09798ecfc44fb2ff98b8e Mon Sep 17 00:00:00 2001
+From: Sudeep Holla <sudeep.holla@arm.com>
+Date: Fri, 30 Apr 2021 11:24:33 +0100
+Subject: [PATCH 02/14] firmware: arm_ffa: Add initial FFA bus support for
+ device enumeration
+
+The Arm FF for Armv8-A specification has concept of endpoints or
+partitions. In the Normal world, a partition could be a VM when
+the Virtualization extension is enabled or the kernel itself.
+
+In order to handle multiple partitions, we can create a FFA device for
+each such partition on a dedicated FFA bus. Similarly, different drivers
+requiring FFA transport can be registered on the same bus. We can match
+the device and drivers using UUID. This is mostly for the in-kernel
+users with FFA drivers.
+
+Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
+
+Upstream-Status: Backport [https://git.kernel.org/pub/scm/linux/kernel/git/sudeep.holla/linux.git/commit/?h=v5.10/ffa&id=6c31a912d7cf9042d80b24f431f0739d53a7262d]
+---
+ MAINTAINERS | 7 +
+ drivers/firmware/Kconfig | 1 +
+ drivers/firmware/Makefile | 1 +
+ drivers/firmware/arm_ffa/Kconfig | 16 +++
+ drivers/firmware/arm_ffa/Makefile | 4 +
+ drivers/firmware/arm_ffa/bus.c | 207 ++++++++++++++++++++++++++++++
+ include/linux/arm_ffa.h | 91 +++++++++++++
+ 7 files changed, 327 insertions(+)
+ create mode 100644 drivers/firmware/arm_ffa/Kconfig
+ create mode 100644 drivers/firmware/arm_ffa/Makefile
+ create mode 100644 drivers/firmware/arm_ffa/bus.c
+ create mode 100644 include/linux/arm_ffa.h
+
+diff --git a/MAINTAINERS b/MAINTAINERS
+index 5234423c477a..d5fdc9e68c89 100644
+--- a/MAINTAINERS
++++ b/MAINTAINERS
+@@ -6847,6 +6847,13 @@ F: include/linux/firewire.h
+ F: include/uapi/linux/firewire*.h
+ F: tools/firewire/
+
++FIRMWARE FRAMEWORK FOR ARMV8-A
++M: Sudeep Holla <sudeep.holla@arm.com>
++L: linux-arm-kernel@lists.infradead.org
++S: Maintained
++F: drivers/firmware/arm_ffa/
++F: include/linux/arm_ffa.h
++
+ FIRMWARE LOADER (request_firmware)
+ M: Luis Chamberlain <mcgrof@kernel.org>
+ L: linux-kernel@vger.kernel.org
+diff --git a/drivers/firmware/Kconfig b/drivers/firmware/Kconfig
+index bfef3d8d14e7..90e6dd32f2cd 100644
+--- a/drivers/firmware/Kconfig
++++ b/drivers/firmware/Kconfig
+@@ -296,6 +296,7 @@ config TURRIS_MOX_RWTM
+ other manufacturing data and also utilize the Entropy Bit Generator
+ for hardware random number generation.
+
++source "drivers/firmware/arm_ffa/Kconfig"
+ source "drivers/firmware/broadcom/Kconfig"
+ source "drivers/firmware/google/Kconfig"
+ source "drivers/firmware/efi/Kconfig"
+diff --git a/drivers/firmware/Makefile b/drivers/firmware/Makefile
+index 523173cbff33..3c2af2e98def 100644
+--- a/drivers/firmware/Makefile
++++ b/drivers/firmware/Makefile
+@@ -23,6 +23,7 @@ obj-$(CONFIG_TI_SCI_PROTOCOL) += ti_sci.o
+ obj-$(CONFIG_TRUSTED_FOUNDATIONS) += trusted_foundations.o
+ obj-$(CONFIG_TURRIS_MOX_RWTM) += turris-mox-rwtm.o
+
++obj-y += arm_ffa/
+ obj-y += arm_scmi/
+ obj-y += broadcom/
+ obj-y += meson/
+diff --git a/drivers/firmware/arm_ffa/Kconfig b/drivers/firmware/arm_ffa/Kconfig
+new file mode 100644
+index 000000000000..261a3660650a
+--- /dev/null
++++ b/drivers/firmware/arm_ffa/Kconfig
+@@ -0,0 +1,16 @@
++# SPDX-License-Identifier: GPL-2.0-only
++config ARM_FFA_TRANSPORT
++ tristate "Arm Firmware Framework for Armv8-A"
++ depends on OF
++ depends on ARM64
++ default n
++ help
++ This Firmware Framework(FF) for Arm A-profile processors describes
++ interfaces that standardize communication between the various
++ software images which includes communication between images in
++ the Secure world and Normal world. It also leverages the
++ virtualization extension to isolate software images provided
++ by an ecosystem of vendors from each other.
++
++ This driver provides interface for all the client drivers making
++ use of the features offered by ARM FF-A.
+diff --git a/drivers/firmware/arm_ffa/Makefile b/drivers/firmware/arm_ffa/Makefile
+new file mode 100644
+index 000000000000..bfe4323a8784
+--- /dev/null
++++ b/drivers/firmware/arm_ffa/Makefile
+@@ -0,0 +1,4 @@
++# SPDX-License-Identifier: GPL-2.0-only
++ffa-bus-y = bus.o
++ffa-module-objs := $(ffa-bus-y)
++obj-$(CONFIG_ARM_FFA_TRANSPORT) = ffa-module.o
+diff --git a/drivers/firmware/arm_ffa/bus.c b/drivers/firmware/arm_ffa/bus.c
+new file mode 100644
+index 000000000000..b743fb2256e9
+--- /dev/null
++++ b/drivers/firmware/arm_ffa/bus.c
+@@ -0,0 +1,207 @@
++// SPDX-License-Identifier: GPL-2.0
++/*
++ * Copyright (C) 2020 ARM Ltd.
++ */
++
++#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
++
++#include <linux/arm_ffa.h>
++#include <linux/device.h>
++#include <linux/fs.h>
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/slab.h>
++#include <linux/types.h>
++
++static int ffa_device_match(struct device *dev, struct device_driver *drv)
++{
++ const struct ffa_device_id *id_table;
++ struct ffa_device *ffa_dev;
++
++ id_table = to_ffa_driver(drv)->id_table;
++ ffa_dev = to_ffa_dev(dev);
++
++ while (!uuid_is_null(&id_table->uuid)) {
++ if (uuid_equal(&ffa_dev->uuid, &id_table->uuid))
++ return 1;
++ id_table++;
++ }
++
++ return 0;
++}
++
++static int ffa_device_probe(struct device *dev)
++{
++ struct ffa_driver *ffa_drv = to_ffa_driver(dev->driver);
++ struct ffa_device *ffa_dev = to_ffa_dev(dev);
++
++ if (!ffa_device_match(dev, dev->driver))
++ return -ENODEV;
++
++ return ffa_drv->probe(ffa_dev);
++}
++
++static int ffa_device_uevent(struct device *dev, struct kobj_uevent_env *env)
++{
++ struct ffa_device *ffa_dev = to_ffa_dev(dev);
++
++ return add_uevent_var(env, "MODALIAS=arm_ffa:%04x:%pUb",
++ ffa_dev->vm_id, &ffa_dev->uuid);
++}
++
++static ssize_t partition_id_show(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct ffa_device *ffa_dev = to_ffa_dev(dev);
++
++ return sprintf(buf, "0x%04x\n", ffa_dev->vm_id);
++}
++static DEVICE_ATTR_RO(partition_id);
++
++static ssize_t uuid_show(struct device *dev, struct device_attribute *attr,
++ char *buf)
++{
++ struct ffa_device *ffa_dev = to_ffa_dev(dev);
++
++ return sprintf(buf, "%pUb\n", &ffa_dev->uuid);
++}
++static DEVICE_ATTR_RO(uuid);
++
++static struct attribute *ffa_device_attributes_attrs[] = {
++ &dev_attr_partition_id.attr,
++ &dev_attr_uuid.attr,
++ NULL,
++};
++ATTRIBUTE_GROUPS(ffa_device_attributes);
++
++struct bus_type ffa_bus_type = {
++ .name = "arm_ffa",
++ .match = ffa_device_match,
++ .probe = ffa_device_probe,
++ .uevent = ffa_device_uevent,
++ .dev_groups = ffa_device_attributes_groups,
++};
++EXPORT_SYMBOL_GPL(ffa_bus_type);
++
++int ffa_driver_register(struct ffa_driver *driver, struct module *owner,
++ const char *mod_name)
++{
++ int ret;
++
++ driver->driver.bus = &ffa_bus_type;
++ driver->driver.name = driver->name;
++ driver->driver.owner = owner;
++ driver->driver.mod_name = mod_name;
++
++ ret = driver_register(&driver->driver);
++ if (!ret)
++ pr_debug("registered new ffa driver %s\n", driver->name);
++
++ return ret;
++}
++EXPORT_SYMBOL_GPL(ffa_driver_register);
++
++void ffa_driver_unregister(struct ffa_driver *driver)
++{
++ driver_unregister(&driver->driver);
++}
++EXPORT_SYMBOL_GPL(ffa_driver_unregister);
++
++static void ffa_release_device(struct device *dev)
++{
++ struct ffa_device *ffa_dev = to_ffa_dev(dev);
++
++ kfree(ffa_dev);
++}
++
++static int __ffa_devices_unregister(struct device *dev, void *data)
++{
++ ffa_release_device(dev);
++
++ return 0;
++}
++
++static void ffa_devices_unregister(void)
++{
++ bus_for_each_dev(&ffa_bus_type, NULL, NULL,
++ __ffa_devices_unregister);
++}
++
++bool ffa_device_is_valid(struct ffa_device *ffa_dev)
++{
++ bool valid = false;
++ struct device *dev = NULL;
++ struct ffa_device *tmp_dev;
++
++ do {
++ dev = bus_find_next_device(&ffa_bus_type, dev);
++ tmp_dev = to_ffa_dev(dev);
++ if (tmp_dev == ffa_dev) {
++ valid = true;
++ break;
++ }
++ put_device(dev);
++ } while (dev);
++
++ put_device(dev);
++
++ return valid;
++}
++
++struct ffa_device *ffa_device_register(const uuid_t *uuid, int vm_id)
++{
++ int ret;
++ struct device *dev;
++ struct ffa_device *ffa_dev;
++
++ ffa_dev = kzalloc(sizeof(*ffa_dev), GFP_KERNEL);
++ if (!ffa_dev)
++ return NULL;
++
++ dev = &ffa_dev->dev;
++ dev->bus = &ffa_bus_type;
++ dev->release = ffa_release_device;
++ dev_set_name(&ffa_dev->dev, "arm-ffa-%04x", vm_id);
++
++ ffa_dev->vm_id = vm_id;
++ uuid_copy(&ffa_dev->uuid, uuid);
++
++ ret = device_register(&ffa_dev->dev);
++ if (ret) {
++ dev_err(dev, "unable to register device %s err=%d\n",
++ dev_name(dev), ret);
++ put_device(dev);
++ return NULL;
++ }
++
++ return ffa_dev;
++}
++EXPORT_SYMBOL_GPL(ffa_device_register);
++
++void ffa_device_unregister(struct ffa_device *ffa_dev)
++{
++ if (!ffa_dev)
++ return;
++
++ device_unregister(&ffa_dev->dev);
++}
++EXPORT_SYMBOL_GPL(ffa_device_unregister);
++
++static int __init arm_ffa_bus_init(void)
++{
++ return bus_register(&ffa_bus_type);
++}
++module_init(arm_ffa_bus_init);
++
++static void __exit arm_ffa_bus_exit(void)
++{
++ ffa_devices_unregister();
++ bus_unregister(&ffa_bus_type);
++}
++
++module_exit(arm_ffa_bus_exit);
++
++MODULE_ALIAS("arm-ffa-bus");
++MODULE_AUTHOR("Sudeep Holla <sudeep.holla@arm.com>");
++MODULE_DESCRIPTION("Arm FF-A bus driver");
++MODULE_LICENSE("GPL v2");
+diff --git a/include/linux/arm_ffa.h b/include/linux/arm_ffa.h
+new file mode 100644
+index 000000000000..aaff89364541
+--- /dev/null
++++ b/include/linux/arm_ffa.h
+@@ -0,0 +1,91 @@
++/* SPDX-License-Identifier: GPL-2.0-only */
++/*
++ * Copyright (C) 2020 ARM Ltd.
++ */
++
++#ifndef _LINUX_ARM_FFA_H
++#define _LINUX_ARM_FFA_H
++
++#include <linux/cdev.h>
++#include <linux/device.h>
++#include <linux/module.h>
++#include <linux/types.h>
++#include <linux/uuid.h>
++
++/* FFA Bus/Device/Driver related */
++struct ffa_device {
++ int vm_id;
++ uuid_t uuid;
++ struct device dev;
++};
++
++#define to_ffa_dev(d) container_of(d, struct ffa_device, dev)
++
++struct ffa_device_id {
++ uuid_t uuid;
++};
++
++struct ffa_driver {
++ const char *name;
++ int (*probe)(struct ffa_device *sdev);
++ void (*remove)(struct ffa_device *sdev);
++ const struct ffa_device_id *id_table;
++
++ struct device_driver driver;
++};
++
++#define to_ffa_driver(d) container_of(d, struct ffa_driver, driver)
++
++static inline void ffa_dev_set_drvdata(struct ffa_device *fdev, void *data)
++{
++ fdev->dev.driver_data = data;
++}
++
++#if IS_REACHABLE(CONFIG_ARM_FFA_TRANSPORT)
++struct ffa_device *ffa_device_register(const uuid_t *uuid, int vm_id);
++void ffa_device_unregister(struct ffa_device *ffa_dev);
++int ffa_driver_register(struct ffa_driver *driver, struct module *owner,
++ const char *mod_name);
++void ffa_driver_unregister(struct ffa_driver *driver);
++bool ffa_device_is_valid(struct ffa_device *ffa_dev);
++
++#else
++static inline
++struct ffa_device *ffa_device_register(const uuid_t *uuid, int vm_id)
++{
++ return NULL;
++}
++
++static inline void ffa_device_unregister(struct ffa_device *dev) {}
++
++static inline int
++ffa_driver_register(struct ffa_driver *driver, struct module *owner,
++ const char *mod_name)
++{
++ return -EINVAL;
++}
++
++static inline void ffa_driver_unregister(struct ffa_driver *driver) {}
++
++static inline
++bool ffa_device_is_valid(struct ffa_device *ffa_dev) { return false; }
++
++#endif /* CONFIG_ARM_FFA_TRANSPORT */
++
++#define ffa_register(driver) \
++ ffa_driver_register(driver, THIS_MODULE, KBUILD_MODNAME)
++#define ffa_unregister(driver) \
++ ffa_driver_unregister(driver)
++
++/**
++ * module_ffa_driver() - Helper macro for registering a psa_ffa driver
++ * @__ffa_driver: ffa_driver structure
++ *
++ * Helper macro for psa_ffa drivers to set up proper module init / exit
++ * functions. Replaces module_init() and module_exit() and keeps people from
++ * printing pointless things to the kernel log when their driver is loaded.
++ */
++#define module_ffa_driver(__ffa_driver) \
++ module_driver(__ffa_driver, ffa_register, ffa_unregister)
++
++#endif /* _LINUX_ARM_FFA_H */
+--
+2.29.2
+
diff --git a/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc0/0011-firmware-arm_ffa-Add-initial-Arm-FFA-driver-support.patch b/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc0/0011-firmware-arm_ffa-Add-initial-Arm-FFA-driver-support.patch
new file mode 100644
index 0000000..5236c23
--- /dev/null
+++ b/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc0/0011-firmware-arm_ffa-Add-initial-Arm-FFA-driver-support.patch
@@ -0,0 +1,415 @@
+From 09e109d71c11f6c990d272cf5cc2c5515f184705 Mon Sep 17 00:00:00 2001
+From: Sudeep Holla <sudeep.holla@arm.com>
+Date: Fri, 30 Apr 2021 11:24:39 +0100
+Subject: [PATCH 03/14] firmware: arm_ffa: Add initial Arm FFA driver support
+
+This just add a basic driver that sets up the transport(e.g. SMCCC),
+checks the FFA version implemented, get the partition ID for self and
+sets up the Tx/Rx buffers for communication.
+
+Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
+
+Upstream-Status: Backport [https://git.kernel.org/pub/scm/linux/kernel/git/sudeep.holla/linux.git/commit/?h=v5.10/ffa&id=13201f9a97be567e8c18fec5e357561f41d9b5f6]
+---
+ drivers/firmware/arm_ffa/Makefile | 3 +-
+ drivers/firmware/arm_ffa/bus.c | 14 +-
+ drivers/firmware/arm_ffa/common.h | 24 +++
+ drivers/firmware/arm_ffa/driver.c | 307 ++++++++++++++++++++++++++++++
+ 4 files changed, 337 insertions(+), 11 deletions(-)
+ create mode 100644 drivers/firmware/arm_ffa/common.h
+ create mode 100644 drivers/firmware/arm_ffa/driver.c
+
+diff --git a/drivers/firmware/arm_ffa/Makefile b/drivers/firmware/arm_ffa/Makefile
+index bfe4323a8784..82d0d35c5324 100644
+--- a/drivers/firmware/arm_ffa/Makefile
++++ b/drivers/firmware/arm_ffa/Makefile
+@@ -1,4 +1,5 @@
+ # SPDX-License-Identifier: GPL-2.0-only
+ ffa-bus-y = bus.o
+-ffa-module-objs := $(ffa-bus-y)
++ffa-driver-y = driver.o
++ffa-module-objs := $(ffa-bus-y) $(ffa-driver-y)
+ obj-$(CONFIG_ARM_FFA_TRANSPORT) = ffa-module.o
+diff --git a/drivers/firmware/arm_ffa/bus.c b/drivers/firmware/arm_ffa/bus.c
+index b743fb2256e9..58441266e60d 100644
+--- a/drivers/firmware/arm_ffa/bus.c
++++ b/drivers/firmware/arm_ffa/bus.c
+@@ -13,6 +13,8 @@
+ #include <linux/slab.h>
+ #include <linux/types.h>
+
++#include "common.h"
++
+ static int ffa_device_match(struct device *dev, struct device_driver *drv)
+ {
+ const struct ffa_device_id *id_table;
+@@ -187,21 +189,13 @@ void ffa_device_unregister(struct ffa_device *ffa_dev)
+ }
+ EXPORT_SYMBOL_GPL(ffa_device_unregister);
+
+-static int __init arm_ffa_bus_init(void)
++int __init arm_ffa_bus_init(void)
+ {
+ return bus_register(&ffa_bus_type);
+ }
+-module_init(arm_ffa_bus_init);
+
+-static void __exit arm_ffa_bus_exit(void)
++void __exit arm_ffa_bus_exit(void)
+ {
+ ffa_devices_unregister();
+ bus_unregister(&ffa_bus_type);
+ }
+-
+-module_exit(arm_ffa_bus_exit);
+-
+-MODULE_ALIAS("arm-ffa-bus");
+-MODULE_AUTHOR("Sudeep Holla <sudeep.holla@arm.com>");
+-MODULE_DESCRIPTION("Arm FF-A bus driver");
+-MODULE_LICENSE("GPL v2");
+diff --git a/drivers/firmware/arm_ffa/common.h b/drivers/firmware/arm_ffa/common.h
+new file mode 100644
+index 000000000000..9195f66f826c
+--- /dev/null
++++ b/drivers/firmware/arm_ffa/common.h
+@@ -0,0 +1,24 @@
++/* SPDX-License-Identifier: GPL-2.0 */
++/*
++ * Copyright (C) 2020 ARM Ltd.
++ */
++
++#ifndef _FFA_COMMON_H
++#define _FFA_COMMON_H
++
++#include <linux/arm-smccc.h>
++#include <linux/err.h>
++
++typedef struct arm_smccc_1_2_regs ffa_value_t;
++
++typedef void (ffa_fn)(ffa_value_t, ffa_value_t *);
++
++int __init arm_ffa_bus_init(void);
++void __exit arm_ffa_bus_exit(void);
++
++static inline int __init ffa_transport_init(ffa_fn **invoke_ffa_fn)
++{
++ return -EOPNOTSUPP;
++}
++
++#endif /* _FFA_COMMON_H */
+diff --git a/drivers/firmware/arm_ffa/driver.c b/drivers/firmware/arm_ffa/driver.c
+new file mode 100644
+index 000000000000..d74f03b773d2
+--- /dev/null
++++ b/drivers/firmware/arm_ffa/driver.c
+@@ -0,0 +1,307 @@
++// SPDX-License-Identifier: GPL-2.0-only
++/*
++ * Arm Firmware Framework for ARMv8-A(FFA) interface driver
++ *
++ * The Arm FFA specification[1] describes a software architecture to
++ * leverages the virtualization extension to isolate software images
++ * provided by an ecosystem of vendors from each other and describes
++ * interfaces that standardize communication between the various software
++ * images including communication between images in the Secure world and
++ * Normal world. Any Hypervisor could use the FFA interfaces to enable
++ * communication between VMs it manages.
++ *
++ * The Hypervisor a.k.a Partition managers in FFA terminology can assign
++ * system resources(Memory regions, Devices, CPU cycles) to the partitions
++ * and manage isolation amongst them.
++ *
++ * [1] https://developer.arm.com/docs/den0077/latest
++ *
++ * Copyright (C) 2020 Arm Ltd.
++ */
++
++#define DRIVER_NAME "ARM FF-A"
++#define pr_fmt(fmt) DRIVER_NAME ": " fmt
++
++#include <linux/arm_ffa.h>
++#include <linux/bitfield.h>
++#include <linux/io.h>
++#include <linux/module.h>
++#include <linux/slab.h>
++
++#include "common.h"
++
++#define FFA_DRIVER_VERSION FFA_VERSION_1_0
++
++#define FFA_SMC(calling_convention, func_num) \
++ ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, (calling_convention), \
++ ARM_SMCCC_OWNER_STANDARD, (func_num))
++
++#define FFA_SMC_32(func_num) FFA_SMC(ARM_SMCCC_SMC_32, (func_num))
++#define FFA_SMC_64(func_num) FFA_SMC(ARM_SMCCC_SMC_64, (func_num))
++
++#define FFA_ERROR FFA_SMC_32(0x60)
++#define FFA_SUCCESS FFA_SMC_32(0x61)
++#define FFA_INTERRUPT FFA_SMC_32(0x62)
++#define FFA_VERSION FFA_SMC_32(0x63)
++#define FFA_FEATURES FFA_SMC_32(0x64)
++#define FFA_RX_RELEASE FFA_SMC_32(0x65)
++#define FFA_RXTX_MAP FFA_SMC_32(0x66)
++#define FFA_FN64_RXTX_MAP FFA_SMC_64(0x66)
++#define FFA_RXTX_UNMAP FFA_SMC_32(0x67)
++#define FFA_PARTITION_INFO_GET FFA_SMC_32(0x68)
++#define FFA_ID_GET FFA_SMC_32(0x69)
++#define FFA_MSG_POLL FFA_SMC_32(0x6A)
++#define FFA_MSG_WAIT FFA_SMC_32(0x6B)
++#define FFA_YIELD FFA_SMC_32(0x6C)
++#define FFA_RUN FFA_SMC_32(0x6D)
++#define FFA_MSG_SEND FFA_SMC_32(0x6E)
++#define FFA_MSG_SEND_DIRECT_REQ FFA_SMC_32(0x6F)
++#define FFA_FN64_MSG_SEND_DIRECT_REQ FFA_SMC_64(0x6F)
++#define FFA_MSG_SEND_DIRECT_RESP FFA_SMC_32(0x70)
++#define FFA_FN64_MSG_SEND_DIRECT_RESP FFA_SMC_64(0x70)
++#define FFA_MEM_DONATE FFA_SMC_32(0x71)
++#define FFA_FN64_MEM_DONATE FFA_SMC_64(0x71)
++#define FFA_MEM_LEND FFA_SMC_32(0x72)
++#define FFA_FN64_MEM_LEND FFA_SMC_64(0x72)
++#define FFA_MEM_SHARE FFA_SMC_32(0x73)
++#define FFA_FN64_MEM_SHARE FFA_SMC_64(0x73)
++#define FFA_MEM_RETRIEVE_REQ FFA_SMC_32(0x74)
++#define FFA_FN64_MEM_RETRIEVE_REQ FFA_SMC_64(0x74)
++#define FFA_MEM_RETRIEVE_RESP FFA_SMC_32(0x75)
++#define FFA_MEM_RELINQUISH FFA_SMC_32(0x76)
++#define FFA_MEM_RECLAIM FFA_SMC_32(0x77)
++#define FFA_MEM_OP_PAUSE FFA_SMC_32(0x78)
++#define FFA_MEM_OP_RESUME FFA_SMC_32(0x79)
++#define FFA_MEM_FRAG_RX FFA_SMC_32(0x7A)
++#define FFA_MEM_FRAG_TX FFA_SMC_32(0x7B)
++#define FFA_NORMAL_WORLD_RESUME FFA_SMC_32(0x7C)
++
++/*
++ * For some calls it is necessary to use SMC64 to pass or return 64-bit values.
++ * For such calls FFA_FN_NATIVE(name) will choose the appropriate
++ * (native-width) function ID.
++ */
++#ifdef CONFIG_64BIT
++#define FFA_FN_NATIVE(name) FFA_FN64_##name
++#else
++#define FFA_FN_NATIVE(name) FFA_##name
++#endif
++
++/* FFA error codes. */
++#define FFA_RET_SUCCESS (0)
++#define FFA_RET_NOT_SUPPORTED (-1)
++#define FFA_RET_INVALID_PARAMETERS (-2)
++#define FFA_RET_NO_MEMORY (-3)
++#define FFA_RET_BUSY (-4)
++#define FFA_RET_INTERRUPTED (-5)
++#define FFA_RET_DENIED (-6)
++#define FFA_RET_RETRY (-7)
++#define FFA_RET_ABORTED (-8)
++
++#define MAJOR_VERSION_MASK GENMASK(30, 16)
++#define MINOR_VERSION_MASK GENMASK(15, 0)
++#define MAJOR_VERSION(x) ((u16)(FIELD_GET(MAJOR_VERSION_MASK, (x))))
++#define MINOR_VERSION(x) ((u16)(FIELD_GET(MINOR_VERSION_MASK, (x))))
++#define PACK_VERSION_INFO(major, minor) \
++ (FIELD_PREP(MAJOR_VERSION_MASK, (major)) | \
++ FIELD_PREP(MINOR_VERSION_MASK, (minor)))
++#define FFA_VERSION_1_0 PACK_VERSION_INFO(1, 0)
++#define FFA_MIN_VERSION FFA_VERSION_1_0
++
++#define SENDER_ID_MASK GENMASK(31, 16)
++#define RECEIVER_ID_MASK GENMASK(15, 0)
++#define SENDER_ID(x) ((u16)(FIELD_GET(SENDER_ID_MASK, (x))))
++#define RECEIVER_ID(x) ((u16)(FIELD_GET(RECEIVER_ID_MASK, (x))))
++#define PACK_TARGET_INFO(s, r) \
++ (FIELD_PREP(SENDER_ID_MASK, (s)) | FIELD_PREP(RECEIVER_ID_MASK, (r)))
++
++/**
++ * FF-A specification mentions explicitly about '4K pages'. This should
++ * not be confused with the kernel PAGE_SIZE, which is the translation
++ * granule kernel is configured and may be one among 4K, 16K and 64K.
++ */
++#define FFA_PAGE_SIZE SZ_4K
++/*
++ * Keeping RX TX buffer size as 4K for now
++ * 64K may be preferred to keep it min a page in 64K PAGE_SIZE config
++ */
++#define RXTX_BUFFER_SIZE SZ_4K
++
++static ffa_fn *invoke_ffa_fn;
++
++static const int ffa_linux_errmap[] = {
++ /* better than switch case as long as return value is continuous */
++ 0, /* FFA_RET_SUCCESS */
++ -EOPNOTSUPP, /* FFA_RET_NOT_SUPPORTED */
++ -EINVAL, /* FFA_RET_INVALID_PARAMETERS */
++ -ENOMEM, /* FFA_RET_NO_MEMORY */
++ -EBUSY, /* FFA_RET_BUSY */
++ -EINTR, /* FFA_RET_INTERRUPTED */
++ -EACCES, /* FFA_RET_DENIED */
++ -EAGAIN, /* FFA_RET_RETRY */
++ -ECANCELED, /* FFA_RET_ABORTED */
++};
++
++static inline int ffa_to_linux_errno(int errno)
++{
++ if (errno < FFA_RET_SUCCESS && errno >= -ARRAY_SIZE(ffa_linux_errmap))
++ return ffa_linux_errmap[-errno];
++ return -EINVAL;
++}
++
++struct ffa_drv_info {
++ u32 version;
++ u16 vm_id;
++ struct mutex rx_lock; /* lock to protect Rx buffer */
++ struct mutex tx_lock; /* lock to protect Tx buffer */
++ void *rx_buffer;
++ void *tx_buffer;
++};
++
++static struct ffa_drv_info *drv_info;
++
++static int ffa_version_check(u32 *version)
++{
++ ffa_value_t ver;
++
++ invoke_ffa_fn((ffa_value_t){
++ .a0 = FFA_VERSION, .a1 = FFA_DRIVER_VERSION,
++ }, &ver);
++
++ if (ver.a0 == FFA_RET_NOT_SUPPORTED) {
++ pr_info("FFA_VERSION returned not supported\n");
++ return -EOPNOTSUPP;
++ }
++
++ if (ver.a0 < FFA_MIN_VERSION || ver.a0 > FFA_DRIVER_VERSION) {
++ pr_err("Incompatible version %d.%d found\n",
++ MAJOR_VERSION(ver.a0), MINOR_VERSION(ver.a0));
++ return -EINVAL;
++ }
++
++ *version = ver.a0;
++ pr_info("Version %d.%d found\n", MAJOR_VERSION(ver.a0),
++ MINOR_VERSION(ver.a0));
++ return 0;
++}
++
++static int ffa_rxtx_map(phys_addr_t tx_buf, phys_addr_t rx_buf, u32 pg_cnt)
++{
++ ffa_value_t ret;
++
++ invoke_ffa_fn((ffa_value_t){
++ .a0 = FFA_FN_NATIVE(RXTX_MAP),
++ .a1 = tx_buf, .a2 = rx_buf, .a3 = pg_cnt,
++ }, &ret);
++
++ if (ret.a0 == FFA_ERROR)
++ return ffa_to_linux_errno((int)ret.a2);
++
++ return 0;
++}
++
++static int ffa_rxtx_unmap(u16 vm_id)
++{
++ ffa_value_t ret;
++
++ invoke_ffa_fn((ffa_value_t){
++ .a0 = FFA_RXTX_UNMAP, .a1 = PACK_TARGET_INFO(vm_id, 0),
++ }, &ret);
++
++ if (ret.a0 == FFA_ERROR)
++ return ffa_to_linux_errno((int)ret.a2);
++
++ return 0;
++}
++
++#define VM_ID_MASK GENMASK(15, 0)
++static int ffa_id_get(u16 *vm_id)
++{
++ ffa_value_t id;
++
++ invoke_ffa_fn((ffa_value_t){
++ .a0 = FFA_ID_GET,
++ }, &id);
++
++ if (id.a0 == FFA_ERROR)
++ return ffa_to_linux_errno((int)id.a2);
++
++ *vm_id = FIELD_GET(VM_ID_MASK, (id.a2));
++
++ return 0;
++}
++
++static int __init ffa_init(void)
++{
++ int ret;
++
++ ret = arm_ffa_bus_init();
++ if (ret)
++ return ret;
++
++ ret = ffa_transport_init(&invoke_ffa_fn);
++ if (ret)
++ return ret;
++
++ drv_info = kzalloc(sizeof(*drv_info), GFP_KERNEL);
++ if (!drv_info)
++ return -ENOMEM;
++
++ ret = ffa_version_check(&drv_info->version);
++ if (ret)
++ goto free_drv_info;
++
++ if (ffa_id_get(&drv_info->vm_id)) {
++ pr_err("failed to obtain VM id for self\n");
++ ret = -ENODEV;
++ goto free_drv_info;
++ }
++
++ drv_info->rx_buffer = alloc_pages_exact(RXTX_BUFFER_SIZE, GFP_KERNEL);
++ if (!drv_info->rx_buffer) {
++ ret = -ENOMEM;
++ goto free_pages;
++ }
++
++ drv_info->tx_buffer = alloc_pages_exact(RXTX_BUFFER_SIZE, GFP_KERNEL);
++ if (!drv_info->tx_buffer) {
++ ret = -ENOMEM;
++ goto free_pages;
++ }
++
++ ret = ffa_rxtx_map(virt_to_phys(drv_info->tx_buffer),
++ virt_to_phys(drv_info->rx_buffer),
++ RXTX_BUFFER_SIZE / FFA_PAGE_SIZE);
++ if (ret) {
++ pr_err("failed to register FFA RxTx buffers\n");
++ goto free_pages;
++ }
++
++ mutex_init(&drv_info->rx_lock);
++ mutex_init(&drv_info->tx_lock);
++
++ return 0;
++free_pages:
++ if (drv_info->tx_buffer)
++ free_pages_exact(drv_info->tx_buffer, RXTX_BUFFER_SIZE);
++ free_pages_exact(drv_info->rx_buffer, RXTX_BUFFER_SIZE);
++free_drv_info:
++ kfree(drv_info);
++ return ret;
++}
++module_init(ffa_init);
++
++static void __exit ffa_exit(void)
++{
++ ffa_rxtx_unmap(drv_info->vm_id);
++ free_pages_exact(drv_info->tx_buffer, RXTX_BUFFER_SIZE);
++ free_pages_exact(drv_info->rx_buffer, RXTX_BUFFER_SIZE);
++ kfree(drv_info);
++ arm_ffa_bus_exit();
++}
++module_exit(ffa_exit);
++
++MODULE_ALIAS("arm-ffa");
++MODULE_AUTHOR("Sudeep Holla <sudeep.holla@arm.com>");
++MODULE_DESCRIPTION("Arm FF-A interface driver");
++MODULE_LICENSE("GPL v2");
+--
+2.29.2
+
diff --git a/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc0/0012-firmware-arm_ffa-Add-support-for-SMCCC-as-transport-.patch b/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc0/0012-firmware-arm_ffa-Add-support-for-SMCCC-as-transport-.patch
new file mode 100644
index 0000000..27964e1
--- /dev/null
+++ b/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc0/0012-firmware-arm_ffa-Add-support-for-SMCCC-as-transport-.patch
@@ -0,0 +1,115 @@
+From a4e518ab87ffdff5bbfa629334dff4a37524e579 Mon Sep 17 00:00:00 2001
+From: Sudeep Holla <sudeep.holla@arm.com>
+Date: Fri, 30 Apr 2021 11:24:43 +0100
+Subject: [PATCH 04/14] firmware: arm_ffa: Add support for SMCCC as transport
+ to FFA driver
+
+There are requests to keep the transport separate in order to allow
+other possible transports like virtio. So let us keep the SMCCC transport
+specific routines abstracted.
+
+It is kept simple for now. Once we add another transport, we can develop
+better abstraction.
+
+Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
+
+Upstream-Status: Backport [https://git.kernel.org/pub/scm/linux/kernel/git/sudeep.holla/linux.git/commit/?h=v5.10/ffa&id=ba0c60e85cb3773a9e172425bd14d76cf9d6e67b]
+---
+ drivers/firmware/arm_ffa/Kconfig | 5 ++++
+ drivers/firmware/arm_ffa/Makefile | 3 ++-
+ drivers/firmware/arm_ffa/common.h | 4 ++++
+ drivers/firmware/arm_ffa/smccc.c | 39 +++++++++++++++++++++++++++++++
+ 4 files changed, 50 insertions(+), 1 deletion(-)
+ create mode 100644 drivers/firmware/arm_ffa/smccc.c
+
+diff --git a/drivers/firmware/arm_ffa/Kconfig b/drivers/firmware/arm_ffa/Kconfig
+index 261a3660650a..5e3ae5cf82e8 100644
+--- a/drivers/firmware/arm_ffa/Kconfig
++++ b/drivers/firmware/arm_ffa/Kconfig
+@@ -14,3 +14,8 @@ config ARM_FFA_TRANSPORT
+
+ This driver provides interface for all the client drivers making
+ use of the features offered by ARM FF-A.
++
++config ARM_FFA_SMCCC
++ bool
++ default ARM_FFA_TRANSPORT
++ depends on ARM64 && HAVE_ARM_SMCCC_DISCOVERY
+diff --git a/drivers/firmware/arm_ffa/Makefile b/drivers/firmware/arm_ffa/Makefile
+index 82d0d35c5324..9d9f37523200 100644
+--- a/drivers/firmware/arm_ffa/Makefile
++++ b/drivers/firmware/arm_ffa/Makefile
+@@ -1,5 +1,6 @@
+ # SPDX-License-Identifier: GPL-2.0-only
+ ffa-bus-y = bus.o
+ ffa-driver-y = driver.o
+-ffa-module-objs := $(ffa-bus-y) $(ffa-driver-y)
++ffa-transport-$(CONFIG_ARM_FFA_SMCCC) += smccc.o
++ffa-module-objs := $(ffa-bus-y) $(ffa-driver-y) $(ffa-transport-y)
+ obj-$(CONFIG_ARM_FFA_TRANSPORT) = ffa-module.o
+diff --git a/drivers/firmware/arm_ffa/common.h b/drivers/firmware/arm_ffa/common.h
+index 9195f66f826c..842451666827 100644
+--- a/drivers/firmware/arm_ffa/common.h
++++ b/drivers/firmware/arm_ffa/common.h
+@@ -16,9 +16,13 @@ typedef void (ffa_fn)(ffa_value_t, ffa_value_t *);
+ int __init arm_ffa_bus_init(void);
+ void __exit arm_ffa_bus_exit(void);
+
++#ifdef CONFIG_ARM_FFA_SMCCC
++int __init ffa_transport_init(ffa_fn **invoke_ffa_fn);
++#else
+ static inline int __init ffa_transport_init(ffa_fn **invoke_ffa_fn)
+ {
+ return -EOPNOTSUPP;
+ }
++#endif
+
+ #endif /* _FFA_COMMON_H */
+diff --git a/drivers/firmware/arm_ffa/smccc.c b/drivers/firmware/arm_ffa/smccc.c
+new file mode 100644
+index 000000000000..22c34b788769
+--- /dev/null
++++ b/drivers/firmware/arm_ffa/smccc.c
+@@ -0,0 +1,39 @@
++// SPDX-License-Identifier: GPL-2.0-only
++/*
++ * Copyright (C) 2020 ARM Ltd.
++ */
++
++#include <linux/printk.h>
++
++#include "common.h"
++
++static void __arm_ffa_fn_smc(ffa_value_t args, ffa_value_t *res)
++{
++ arm_smccc_1_2_smc(&args, res);
++}
++
++static void __arm_ffa_fn_hvc(ffa_value_t args, ffa_value_t *res)
++{
++ arm_smccc_1_2_hvc(&args, res);
++}
++
++int __init ffa_transport_init(ffa_fn **invoke_ffa_fn)
++{
++ enum arm_smccc_conduit conduit;
++
++ if (arm_smccc_get_version() < ARM_SMCCC_VERSION_1_2)
++ return -EOPNOTSUPP;
++
++ conduit = arm_smccc_1_1_get_conduit();
++ if (conduit == SMCCC_CONDUIT_NONE) {
++ pr_err("%s: invalid SMCCC conduit\n", __func__);
++ return -EOPNOTSUPP;
++ }
++
++ if (conduit == SMCCC_CONDUIT_SMC)
++ *invoke_ffa_fn = __arm_ffa_fn_smc;
++ else
++ *invoke_ffa_fn = __arm_ffa_fn_hvc;
++
++ return 0;
++}
+--
+2.29.2
+
diff --git a/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc0/0013-firmware-arm_ffa-Setup-in-kernel-users-of-FFA-partit.patch b/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc0/0013-firmware-arm_ffa-Setup-in-kernel-users-of-FFA-partit.patch
new file mode 100644
index 0000000..af28a68
--- /dev/null
+++ b/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc0/0013-firmware-arm_ffa-Setup-in-kernel-users-of-FFA-partit.patch
@@ -0,0 +1,398 @@
+From 4eff52bdae3113edf0256bfd1e986866f7282365 Mon Sep 17 00:00:00 2001
+From: Sudeep Holla <sudeep.holla@arm.com>
+Date: Fri, 30 Apr 2021 11:24:48 +0100
+Subject: [PATCH 05/14] firmware: arm_ffa: Setup in-kernel users of FFA
+ partitions
+
+Parse the FFA nodes from the device-tree and register all the partitions
+whose services will be used in the kernel.
+
+In order to also enable in-kernel users of FFA interface, let us add
+simple set of operations for such devices.
+
+The in-kernel users are registered without the character device interface.
+
+Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
+
+Upstream-Status: Backport [https://git.kernel.org/pub/scm/linux/kernel/git/sudeep.holla/linux.git/commit/?h=v5.10/ffa&id=f9a344783c03e17cf58f9846e5f689cd5233a844]
+---
+ drivers/firmware/arm_ffa/bus.c | 9 ++
+ drivers/firmware/arm_ffa/common.h | 3 +
+ drivers/firmware/arm_ffa/driver.c | 213 ++++++++++++++++++++++++++++++
+ include/linux/arm_ffa.h | 38 +++++-
+ 4 files changed, 262 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/firmware/arm_ffa/bus.c b/drivers/firmware/arm_ffa/bus.c
+index 58441266e60d..da23100c2e39 100644
+--- a/drivers/firmware/arm_ffa/bus.c
++++ b/drivers/firmware/arm_ffa/bus.c
+@@ -24,6 +24,15 @@ static int ffa_device_match(struct device *dev, struct device_driver *drv)
+ ffa_dev = to_ffa_dev(dev);
+
+ while (!uuid_is_null(&id_table->uuid)) {
++ /*
++ * FF-A v1.0 doesn't provide discovery of UUIDs, just the
++ * partition IDs, so fetch the partitions IDs for this
++ * id_table UUID and assign the UUID to the device if the
++ * partition ID matches
++ */
++ if (uuid_is_null(&ffa_dev->uuid))
++ ffa_device_match_uuid(ffa_dev, &id_table->uuid);
++
+ if (uuid_equal(&ffa_dev->uuid, &id_table->uuid))
+ return 1;
+ id_table++;
+diff --git a/drivers/firmware/arm_ffa/common.h b/drivers/firmware/arm_ffa/common.h
+index 842451666827..80ad71f02235 100644
+--- a/drivers/firmware/arm_ffa/common.h
++++ b/drivers/firmware/arm_ffa/common.h
+@@ -6,6 +6,7 @@
+ #ifndef _FFA_COMMON_H
+ #define _FFA_COMMON_H
+
++#include <linux/arm_ffa.h>
+ #include <linux/arm-smccc.h>
+ #include <linux/err.h>
+
+@@ -15,6 +16,8 @@ typedef void (ffa_fn)(ffa_value_t, ffa_value_t *);
+
+ int __init arm_ffa_bus_init(void);
+ void __exit arm_ffa_bus_exit(void);
++bool ffa_device_is_valid(struct ffa_device *ffa_dev);
++void ffa_device_match_uuid(struct ffa_device *ffa_dev, const uuid_t *uuid);
+
+ #ifdef CONFIG_ARM_FFA_SMCCC
+ int __init ffa_transport_init(ffa_fn **invoke_ffa_fn);
+diff --git a/drivers/firmware/arm_ffa/driver.c b/drivers/firmware/arm_ffa/driver.c
+index d74f03b773d2..cefbb3edf142 100644
+--- a/drivers/firmware/arm_ffa/driver.c
++++ b/drivers/firmware/arm_ffa/driver.c
+@@ -24,9 +24,12 @@
+
+ #include <linux/arm_ffa.h>
+ #include <linux/bitfield.h>
++#include <linux/device.h>
+ #include <linux/io.h>
++#include <linux/kernel.h>
+ #include <linux/module.h>
+ #include <linux/slab.h>
++#include <linux/uuid.h>
+
+ #include "common.h"
+
+@@ -185,6 +188,22 @@ static int ffa_version_check(u32 *version)
+ return 0;
+ }
+
++static int ffa_rx_release(void)
++{
++ ffa_value_t ret;
++
++ invoke_ffa_fn((ffa_value_t){
++ .a0 = FFA_RX_RELEASE,
++ }, &ret);
++
++ if (ret.a0 == FFA_ERROR)
++ return ffa_to_linux_errno((int)ret.a2);
++
++ /* check for ret.a0 == FFA_RX_RELEASE ? */
++
++ return 0;
++}
++
+ static int ffa_rxtx_map(phys_addr_t tx_buf, phys_addr_t rx_buf, u32 pg_cnt)
+ {
+ ffa_value_t ret;
+@@ -214,6 +233,64 @@ static int ffa_rxtx_unmap(u16 vm_id)
+ return 0;
+ }
+
++/* buffer must be sizeof(struct ffa_partition_info) * num_partitions */
++static int
++__ffa_partition_info_get(u32 uuid0, u32 uuid1, u32 uuid2, u32 uuid3,
++ struct ffa_partition_info *buffer, int num_partitions)
++{
++ int count;
++ ffa_value_t partition_info;
++
++ mutex_lock(&drv_info->rx_lock);
++ invoke_ffa_fn((ffa_value_t){
++ .a0 = FFA_PARTITION_INFO_GET,
++ .a1 = uuid0, .a2 = uuid1, .a3 = uuid2, .a4 = uuid3,
++ }, &partition_info);
++
++ if (partition_info.a0 == FFA_ERROR) {
++ mutex_unlock(&drv_info->rx_lock);
++ return ffa_to_linux_errno((int)partition_info.a2);
++ }
++
++ count = partition_info.a2;
++
++ if (buffer && count <= num_partitions)
++ memcpy(buffer, drv_info->rx_buffer, sizeof(*buffer) * count);
++
++ ffa_rx_release();
++
++ mutex_unlock(&drv_info->rx_lock);
++
++ return count;
++}
++
++/* buffer is allocated and caller must free the same if returned count > 0 */
++static int
++ffa_partition_probe(const uuid_t *uuid, struct ffa_partition_info **buffer)
++{
++ int count;
++ u32 uuid0_4[4];
++ struct ffa_partition_info *pbuf;
++
++ export_uuid((u8 *)uuid0_4, uuid);
++ count = __ffa_partition_info_get(uuid0_4[0], uuid0_4[1], uuid0_4[2],
++ uuid0_4[3], NULL, 0);
++ if (count <= 0)
++ return count;
++
++ pbuf = kcalloc(count, sizeof(*pbuf), GFP_KERNEL);
++ if (!pbuf)
++ return -ENOMEM;
++
++ count = __ffa_partition_info_get(uuid0_4[0], uuid0_4[1], uuid0_4[2],
++ uuid0_4[3], pbuf, count);
++ if (count <= 0)
++ kfree(pbuf);
++
++ *buffer = pbuf;
++ return count;
++}
++
+ #define VM_ID_MASK GENMASK(15, 0)
+ static int ffa_id_get(u16 *vm_id)
+ {
+@@ -231,6 +308,140 @@ static int ffa_id_get(u16 *vm_id)
+ return 0;
+ }
+
++static int ffa_msg_send_direct_req(u16 src_id, u16 dst_id, bool mode_32bit,
++ struct ffa_send_direct_data *data)
++{
++ u32 req_id, resp_id, src_dst_ids = PACK_TARGET_INFO(src_id, dst_id);
++ ffa_value_t ret;
++
++ if (mode_32bit) {
++ req_id = FFA_MSG_SEND_DIRECT_REQ;
++ resp_id = FFA_MSG_SEND_DIRECT_RESP;
++ } else {
++ req_id = FFA_FN_NATIVE(MSG_SEND_DIRECT_REQ);
++ resp_id = FFA_FN_NATIVE(MSG_SEND_DIRECT_RESP);
++ }
++
++ invoke_ffa_fn((ffa_value_t){
++ .a0 = req_id, .a1 = src_dst_ids, .a2 = 0,
++ .a3 = data->data0, .a4 = data->data1, .a5 = data->data2,
++ .a6 = data->data3, .a7 = data->data4,
++ }, &ret);
++
++ while (ret.a0 == FFA_INTERRUPT)
++ invoke_ffa_fn((ffa_value_t){
++ .a0 = FFA_RUN, .a1 = ret.a1,
++ }, &ret);
++
++ if (ret.a0 == FFA_ERROR)
++ return ffa_to_linux_errno((int)ret.a2);
++
++ if (ret.a0 == resp_id) {
++ data->data0 = ret.a3;
++ data->data1 = ret.a4;
++ data->data2 = ret.a5;
++ data->data3 = ret.a6;
++ data->data4 = ret.a7;
++ return 0;
++ }
++
++ return -EINVAL;
++}
++
++static u32 ffa_api_version_get(void)
++{
++ return drv_info->version;
++}
++
++static int ffa_partition_info_get(const char *uuid_str,
++ struct ffa_partition_info *buffer)
++{
++ int count;
++ uuid_t uuid;
++ struct ffa_partition_info *pbuf;
++
++ if (uuid_parse(uuid_str, &uuid)) {
++ pr_err("invalid uuid (%s)\n", uuid_str);
++ return -ENODEV;
++ }
++
++ count = ffa_partition_probe(&uuid_null, &pbuf);
++ if (count <= 0)
++ return -ENOENT;
++
++ memcpy(buffer, pbuf, sizeof(*pbuf) * count);
++ kfree(pbuf);
++ return 0;
++}
++
++static void ffa_mode_32bit_set(struct ffa_device *dev)
++{
++ dev->mode_32bit = true;
++}
++
++static int ffa_sync_send_receive(struct ffa_device *dev,
++ struct ffa_send_direct_data *data)
++{
++ return ffa_msg_send_direct_req(drv_info->vm_id, dev->vm_id,
++ dev->mode_32bit, data);
++}
++
++static const struct ffa_dev_ops ffa_ops = {
++ .api_version_get = ffa_api_version_get,
++ .partition_info_get = ffa_partition_info_get,
++ .mode_32bit_set = ffa_mode_32bit_set,
++ .sync_send_receive = ffa_sync_send_receive,
++};
++
++const struct ffa_dev_ops *ffa_dev_ops_get(struct ffa_device *dev)
++{
++ if (ffa_device_is_valid(dev))
++ return &ffa_ops;
++
++ return NULL;
++}
++EXPORT_SYMBOL_GPL(ffa_dev_ops_get);
++
++void ffa_device_match_uuid(struct ffa_device *ffa_dev, const uuid_t *uuid)
++{
++ int count, idx;
++ struct ffa_partition_info *pbuf, *tpbuf;
++
++ count = ffa_partition_probe(uuid, &pbuf);
++ if (count <= 0)
++ return;
++
++ for (idx = 0, tpbuf = pbuf; idx < count; idx++, tpbuf++)
++ if (tpbuf->id == ffa_dev->vm_id)
++ uuid_copy(&ffa_dev->uuid, uuid);
++ kfree(pbuf);
++}
++
++static void ffa_setup_partitions(void)
++{
++ int count, idx;
++ struct ffa_device *ffa_dev;
++ struct ffa_partition_info *pbuf, *tpbuf;
++
++ count = ffa_partition_probe(&uuid_null, &pbuf);
++ if (count <= 0) {
++ pr_info("%s: No partitions found, error %d\n", __func__, count);
++ return;
++ }
++
++ for (idx = 0, tpbuf = pbuf; idx < count; idx++, tpbuf++) {
++ ffa_dev = ffa_device_register(&uuid_null, tpbuf->id);
++ if (!ffa_dev) {
++ pr_err("%s: failed to register partition ID 0x%x\n",
++ __func__, tpbuf->id);
++ continue;
++ }
++
++ ffa_dev_set_drvdata(ffa_dev, drv_info);
++ }
++ kfree(pbuf);
++}
++
+ static int __init ffa_init(void)
+ {
+ int ret;
+@@ -280,6 +491,8 @@ static int __init ffa_init(void)
+ mutex_init(&drv_info->rx_lock);
+ mutex_init(&drv_info->tx_lock);
+
++ ffa_setup_partitions();
++
+ return 0;
+ free_pages:
+ if (drv_info->tx_buffer)
+diff --git a/include/linux/arm_ffa.h b/include/linux/arm_ffa.h
+index aaff89364541..b242fbbce4f0 100644
+--- a/include/linux/arm_ffa.h
++++ b/include/linux/arm_ffa.h
+@@ -6,7 +6,6 @@
+ #ifndef _LINUX_ARM_FFA_H
+ #define _LINUX_ARM_FFA_H
+
+-#include <linux/cdev.h>
+ #include <linux/device.h>
+ #include <linux/module.h>
+ #include <linux/types.h>
+@@ -15,6 +14,7 @@
+ /* FFA Bus/Device/Driver related */
+ struct ffa_device {
+ int vm_id;
++ bool mode_32bit;
+ uuid_t uuid;
+ struct device dev;
+ };
+@@ -48,6 +48,7 @@ int ffa_driver_register(struct ffa_driver *driver, struct module *owner,
+ const char *mod_name);
+ void ffa_driver_unregister(struct ffa_driver *driver);
+ bool ffa_device_is_valid(struct ffa_device *ffa_dev);
++const struct ffa_dev_ops *ffa_dev_ops_get(struct ffa_device *dev);
+
+ #else
+ static inline
+@@ -70,6 +71,10 @@ static inline void ffa_driver_unregister(struct ffa_driver *driver) {}
+ static inline
+ bool ffa_device_is_valid(struct ffa_device *ffa_dev) { return false; }
+
++const struct ffa_dev_ops *ffa_dev_ops_get(struct ffa_device *dev)
++{
++ return NULL;
++}
+ #endif /* CONFIG_ARM_FFA_TRANSPORT */
+
+ #define ffa_register(driver) \
+@@ -88,4 +93,35 @@ bool ffa_device_is_valid(struct ffa_device *ffa_dev) { return false; }
+ #define module_ffa_driver(__ffa_driver) \
+ module_driver(__ffa_driver, ffa_register, ffa_unregister)
+
++/* FFA transport related */
++struct ffa_partition_info {
++ u16 id;
++ u16 exec_ctxt;
++/* partition supports receipt of direct requests */
++#define FFA_PARTITION_DIRECT_RECV BIT(0)
++/* partition can send direct requests. */
++#define FFA_PARTITION_DIRECT_SEND BIT(1)
++/* partition can send and receive indirect messages. */
++#define FFA_PARTITION_INDIRECT_MSG BIT(2)
++ u32 properties;
++};
++
++/* For use with FFA_MSG_SEND_DIRECT_{REQ,RESP} which pass data via registers */
++struct ffa_send_direct_data {
++ unsigned long data0; /* w3/x3 */
++ unsigned long data1; /* w4/x4 */
++ unsigned long data2; /* w5/x5 */
++ unsigned long data3; /* w6/x6 */
++ unsigned long data4; /* w7/x7 */
++};
++
++struct ffa_dev_ops {
++ u32 (*api_version_get)(void);
++ int (*partition_info_get)(const char *uuid_str,
++ struct ffa_partition_info *buffer);
++ void (*mode_32bit_set)(struct ffa_device *dev);
++ int (*sync_send_receive)(struct ffa_device *dev,
++ struct ffa_send_direct_data *data);
++};
++
+ #endif /* _LINUX_ARM_FFA_H */
+--
+2.29.2
+
diff --git a/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc0/0014-firmware-arm_ffa-Add-support-for-MEM_-interfaces.patch b/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc0/0014-firmware-arm_ffa-Add-support-for-MEM_-interfaces.patch
new file mode 100644
index 0000000..a9ff1fc
--- /dev/null
+++ b/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc0/0014-firmware-arm_ffa-Add-support-for-MEM_-interfaces.patch
@@ -0,0 +1,406 @@
+From 6795f86f52751608a03cc6de0dda8e28a5c68cd1 Mon Sep 17 00:00:00 2001
+From: Sudeep Holla <sudeep.holla@arm.com>
+Date: Fri, 30 Apr 2021 11:24:51 +0100
+Subject: [PATCH 06/14] firmware: arm_ffa: Add support for MEM_* interfaces
+
+Most of the MEM_* APIs share the same parameters, so they can be
+generalised. Currently only MEM_SHARE is implemented and the user space
+interface for that is not added yet.
+
+Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
+
+Upstream-Status: Backport [https://git.kernel.org/pub/scm/linux/kernel/git/sudeep.holla/linux.git/commit/?h=v5.10/ffa&id=f27cbd0b3f83cb40ff7385f00d05afe1be7577b2]
+---
+ drivers/firmware/arm_ffa/driver.c | 199 ++++++++++++++++++++++++++++++
+ include/linux/arm_ffa.h | 139 +++++++++++++++++++++
+ 2 files changed, 338 insertions(+)
+
+diff --git a/drivers/firmware/arm_ffa/driver.c b/drivers/firmware/arm_ffa/driver.c
+index cefbb3edf142..056a3fca14d1 100644
+--- a/drivers/firmware/arm_ffa/driver.c
++++ b/drivers/firmware/arm_ffa/driver.c
+@@ -28,6 +28,8 @@
+ #include <linux/io.h>
+ #include <linux/kernel.h>
+ #include <linux/module.h>
++#include <linux/mm.h>
++#include <linux/scatterlist.h>
+ #include <linux/slab.h>
+ #include <linux/uuid.h>
+
+@@ -348,6 +350,192 @@ static int ffa_msg_send_direct_req(u16 src_id, u16 dst_id, bool mode_32bit,
+ return -EINVAL;
+ }
+
++static int ffa_mem_first_frag(u32 func_id, phys_addr_t buf, u32 buf_sz,
++ u32 frag_len, u32 len, u64 *handle)
++{
++ ffa_value_t ret;
++
++ invoke_ffa_fn((ffa_value_t){
++ .a0 = func_id, .a1 = len, .a2 = frag_len,
++ .a3 = buf, .a4 = buf_sz,
++ }, &ret);
++
++ while (ret.a0 == FFA_MEM_OP_PAUSE)
++ invoke_ffa_fn((ffa_value_t){
++ .a0 = FFA_MEM_OP_RESUME,
++ .a1 = ret.a1, .a2 = ret.a2,
++ }, &ret);
++
++ if (ret.a0 == FFA_ERROR)
++ return ffa_to_linux_errno((int)ret.a2);
++
++ if (ret.a0 != FFA_SUCCESS)
++ return -EOPNOTSUPP;
++
++ if (handle)
++ *handle = PACK_HANDLE(ret.a2, ret.a3);
++
++ return frag_len;
++}
++
++static int ffa_mem_next_frag(u64 handle, u32 frag_len)
++{
++ ffa_value_t ret;
++
++ invoke_ffa_fn((ffa_value_t){
++ .a0 = FFA_MEM_FRAG_TX,
++ .a1 = HANDLE_LOW(handle), .a2 = HANDLE_HIGH(handle),
++ .a3 = frag_len,
++ }, &ret);
++
++ while (ret.a0 == FFA_MEM_OP_PAUSE)
++ invoke_ffa_fn((ffa_value_t){
++ .a0 = FFA_MEM_OP_RESUME,
++ .a1 = ret.a1, .a2 = ret.a2,
++ }, &ret);
++
++ if (ret.a0 == FFA_ERROR)
++ return ffa_to_linux_errno((int)ret.a2);
++
++ if (ret.a0 != FFA_MEM_FRAG_RX)
++ return -EOPNOTSUPP;
++
++ return ret.a3;
++}
++
++static int
++ffa_transmit_fragment(u32 func_id, phys_addr_t buf, u32 buf_sz, u32 frag_len,
++ u32 len, u64 *handle, bool first)
++{
++ if (!first)
++ return ffa_mem_next_frag(*handle, frag_len);
++
++ return ffa_mem_first_frag(func_id, buf, buf_sz, frag_len, len, handle);
++}
++
++static u32 ffa_get_num_pages_sg(struct scatterlist *sg)
++{
++ u32 num_pages = 0;
++
++ do {
++ num_pages += sg->length / FFA_PAGE_SIZE;
++ } while ((sg = sg_next(sg)));
++
++ return num_pages;
++}
++
++static int
++ffa_setup_and_transmit(u32 func_id, void *buffer, u32 max_fragsize,
++ struct ffa_mem_ops_args *args)
++{
++ int rc = 0;
++ bool first = true;
++ phys_addr_t addr = 0;
++ struct ffa_composite_mem_region *composite;
++ struct ffa_mem_region_addr_range *constituents;
++ struct ffa_mem_region_attributes *ep_mem_access;
++ struct ffa_mem_region *mem_region = buffer;
++ u32 idx, frag_len, length, buf_sz = 0, num_entries = sg_nents(args->sg);
++
++ mem_region->tag = args->tag;
++ mem_region->flags = args->flags;
++ mem_region->sender_id = drv_info->vm_id;
++ mem_region->attributes = FFA_MEM_NORMAL | FFA_MEM_WRITE_BACK |
++ FFA_MEM_INNER_SHAREABLE;
++ ep_mem_access = &mem_region->ep_mem_access[0];
++
++ for (idx = 0; idx < args->nattrs; idx++, ep_mem_access++) {
++ ep_mem_access->receiver = args->attrs[idx].receiver;
++ ep_mem_access->attrs = args->attrs[idx].attrs;
++ ep_mem_access->composite_off = COMPOSITE_OFFSET(args->nattrs);
++ }
++ mem_region->ep_count = args->nattrs;
++
++ composite = buffer + COMPOSITE_OFFSET(args->nattrs);
++ composite->total_pg_cnt = ffa_get_num_pages_sg(args->sg);
++ composite->addr_range_cnt = num_entries;
++
++ length = COMPOSITE_CONSTITUENTS_OFFSET(args->nattrs, num_entries);
++ frag_len = COMPOSITE_CONSTITUENTS_OFFSET(args->nattrs, 0);
++ if (frag_len > max_fragsize)
++ return -ENXIO;
++
++ if (!args->use_txbuf) {
++ addr = virt_to_phys(buffer);
++ buf_sz = max_fragsize / FFA_PAGE_SIZE;
++ }
++
++ constituents = buffer + frag_len;
++ idx = 0;
++ do {
++ if (frag_len == max_fragsize) {
++ rc = ffa_transmit_fragment(func_id, addr, buf_sz,
++ frag_len, length,
++ &args->g_handle, first);
++ if (rc < 0)
++ return -ENXIO;
++
++ first = false;
++ idx = 0;
++ frag_len = 0;
++ constituents = buffer;
++ }
++
++ if ((void *)constituents - buffer > max_fragsize) {
++ pr_err("Memory Region Fragment > Tx Buffer size\n");
++ return -EFAULT;
++ }
++
++ constituents->address = sg_phys(args->sg);
++ constituents->pg_cnt = args->sg->length / FFA_PAGE_SIZE;
++ constituents++;
++ frag_len += sizeof(struct ffa_mem_region_addr_range);
++ } while ((args->sg = sg_next(args->sg)));
++
++ return ffa_transmit_fragment(func_id, addr, buf_sz, frag_len,
++ length, &args->g_handle, first);
++}
++
++static int ffa_memory_ops(u32 func_id, struct ffa_mem_ops_args *args)
++{
++ int ret;
++ void *buffer;
++
++ if (!args->use_txbuf) {
++ buffer = alloc_pages_exact(RXTX_BUFFER_SIZE, GFP_KERNEL);
++ if (!buffer)
++ return -ENOMEM;
++ } else {
++ buffer = drv_info->tx_buffer;
++ mutex_lock(&drv_info->tx_lock);
++ }
++
++ ret = ffa_setup_and_transmit(func_id, buffer, RXTX_BUFFER_SIZE, args);
++
++ if (args->use_txbuf)
++ mutex_unlock(&drv_info->tx_lock);
++ else
++ free_pages_exact(buffer, RXTX_BUFFER_SIZE);
++
++ return ret < 0 ? ret : 0;
++}
++
++static int ffa_memory_reclaim(u64 g_handle, u32 flags)
++{
++ ffa_value_t ret;
++
++ invoke_ffa_fn((ffa_value_t){
++ .a0 = FFA_MEM_RECLAIM,
++ .a1 = HANDLE_LOW(g_handle), .a2 = HANDLE_HIGH(g_handle),
++ .a3 = flags,
++ }, &ret);
++
++ if (ret.a0 == FFA_ERROR)
++ return ffa_to_linux_errno((int)ret.a2);
++
++ return 0;
++}
++
+ static u32 ffa_api_version_get(void)
+ {
+ return drv_info->version;
+@@ -386,11 +574,22 @@ static int ffa_sync_send_receive(struct ffa_device *dev,
+ dev->mode_32bit, data);
+ }
+
++static int
++ffa_memory_share(struct ffa_device *dev, struct ffa_mem_ops_args *args)
++{
++ if (dev->mode_32bit)
++ return ffa_memory_ops(FFA_MEM_SHARE, args);
++
++ return ffa_memory_ops(FFA_FN_NATIVE(MEM_SHARE), args);
++}
++
+ static const struct ffa_dev_ops ffa_ops = {
+ .api_version_get = ffa_api_version_get,
+ .partition_info_get = ffa_partition_info_get,
+ .mode_32bit_set = ffa_mode_32bit_set,
+ .sync_send_receive = ffa_sync_send_receive,
++ .memory_reclaim = ffa_memory_reclaim,
++ .memory_share = ffa_memory_share,
+ };
+
+ const struct ffa_dev_ops *ffa_dev_ops_get(struct ffa_device *dev)
+diff --git a/include/linux/arm_ffa.h b/include/linux/arm_ffa.h
+index b242fbbce4f0..6dc0f4e425b9 100644
+--- a/include/linux/arm_ffa.h
++++ b/include/linux/arm_ffa.h
+@@ -115,6 +115,142 @@ struct ffa_send_direct_data {
+ unsigned long data4; /* w7/x7 */
+ };
+
++struct ffa_mem_region_addr_range {
++ /* The base IPA of the constituent memory region, aligned to 4 kiB */
++ u64 address;
++ /* The number of 4 kiB pages in the constituent memory region. */
++ u32 pg_cnt;
++ u32 reserved;
++};
++
++struct ffa_composite_mem_region {
++ /*
++ * The total number of 4 kiB pages included in this memory region. This
++ * must be equal to the sum of page counts specified in each
++ * `struct ffa_mem_region_addr_range`.
++ */
++ u32 total_pg_cnt;
++ /* The number of constituents included in this memory region range */
++ u32 addr_range_cnt;
++ u64 reserved;
++ /** An array of `addr_range_cnt` memory region constituents. */
++ struct ffa_mem_region_addr_range constituents[];
++};
++
++struct ffa_mem_region_attributes {
++ /* The ID of the VM to which the memory is being given or shared. */
++ u16 receiver;
++ /*
++ * The permissions with which the memory region should be mapped in the
++ * receiver's page table.
++ */
++#define FFA_MEM_EXEC BIT(3)
++#define FFA_MEM_NO_EXEC BIT(2)
++#define FFA_MEM_RW BIT(1)
++#define FFA_MEM_RO BIT(0)
++ u8 attrs;
++ /*
++ * Flags used during FFA_MEM_RETRIEVE_REQ and FFA_MEM_RETRIEVE_RESP
++ * for memory regions with multiple borrowers.
++ */
++#define FFA_MEM_RETRIEVE_SELF_BORROWER BIT(0)
++ u8 flag;
++ u32 composite_off;
++ /*
++ * Offset in bytes from the start of the outer `ffa_memory_region` to
++ * an `struct ffa_mem_region_addr_range`.
++ */
++ u64 reserved;
++};
++
++struct ffa_mem_region {
++ /* The ID of the VM/owner which originally sent the memory region */
++ u16 sender_id;
++#define FFA_MEM_NORMAL BIT(5)
++#define FFA_MEM_DEVICE BIT(4)
++
++#define FFA_MEM_WRITE_BACK (3 << 2)
++#define FFA_MEM_NON_CACHEABLE (1 << 2)
++
++#define FFA_DEV_nGnRnE (0 << 2)
++#define FFA_DEV_nGnRE (1 << 2)
++#define FFA_DEV_nGRE (2 << 2)
++#define FFA_DEV_GRE (3 << 2)
++
++#define FFA_MEM_NON_SHAREABLE (0)
++#define FFA_MEM_OUTER_SHAREABLE (2)
++#define FFA_MEM_INNER_SHAREABLE (3)
++ u8 attributes;
++ u8 reserved_0;
++/*
++ * Clear memory region contents after unmapping it from the sender and
++ * before mapping it for any receiver.
++ */
++#define FFA_MEM_CLEAR BIT(0)
++/*
++ * Whether the hypervisor may time slice the memory sharing or retrieval
++ * operation.
++ */
++#define FFA_TIME_SLICE_ENABLE BIT(1)
++
++#define FFA_MEM_RETRIEVE_TYPE_IN_RESP (0 << 3)
++#define FFA_MEM_RETRIEVE_TYPE_SHARE (1 << 3)
++#define FFA_MEM_RETRIEVE_TYPE_LEND (2 << 3)
++#define FFA_MEM_RETRIEVE_TYPE_DONATE (3 << 3)
++
++#define FFA_MEM_RETRIEVE_ADDR_ALIGN_HINT BIT(9)
++#define FFA_MEM_RETRIEVE_ADDR_ALIGN(x) ((x) << 5)
++ /* Flags to control behaviour of the transaction. */
++ u32 flags;
++#define HANDLE_LOW_MASK GENMASK_ULL(31, 0)
++#define HANDLE_HIGH_MASK GENMASK_ULL(63, 32)
++#define HANDLE_LOW(x) ((u32)(FIELD_GET(HANDLE_LOW_MASK, (x))))
++#define HANDLE_HIGH(x) ((u32)(FIELD_GET(HANDLE_HIGH_MASK, (x))))
++
++#define PACK_HANDLE(l, h) \
++ (FIELD_PREP(HANDLE_LOW_MASK, (l)) | FIELD_PREP(HANDLE_HIGH_MASK, (h)))
++ /*
++ * A globally-unique ID assigned by the hypervisor for a region
++ * of memory being sent between VMs.
++ */
++ u64 handle;
++ /*
++ * An implementation defined value associated with the receiver and the
++ * memory region.
++ */
++ u64 tag;
++ u32 reserved_1;
++ /*
++ * The number of `ffa_mem_region_attributes` entries included in this
++ * transaction.
++ */
++ u32 ep_count;
++ /*
++ * An array of endpoint memory access descriptors.
++ * Each one specifies a memory region offset, an endpoint and the
++ * attributes with which this memory region should be mapped in that
++ * endpoint's page table.
++ */
++ struct ffa_mem_region_attributes ep_mem_access[];
++};
++
++#define COMPOSITE_OFFSET(x) \
++ (offsetof(struct ffa_mem_region, ep_mem_access[x]))
++#define CONSTITUENTS_OFFSET(x) \
++ (offsetof(struct ffa_composite_mem_region, constituents[x]))
++#define COMPOSITE_CONSTITUENTS_OFFSET(x, y) \
++ (COMPOSITE_OFFSET(x) + CONSTITUENTS_OFFSET(y))
++
++struct ffa_mem_ops_args {
++ bool use_txbuf;
++ u32 nattrs;
++ u32 flags;
++ u64 tag;
++ u64 g_handle;
++ struct scatterlist *sg;
++ struct ffa_mem_region_attributes *attrs;
++};
++
+ struct ffa_dev_ops {
+ u32 (*api_version_get)(void);
+ int (*partition_info_get)(const char *uuid_str,
+@@ -122,6 +258,9 @@ struct ffa_dev_ops {
+ void (*mode_32bit_set)(struct ffa_device *dev);
+ int (*sync_send_receive)(struct ffa_device *dev,
+ struct ffa_send_direct_data *data);
++ int (*memory_reclaim)(u64 g_handle, u32 flags);
++ int (*memory_share)(struct ffa_device *dev,
++ struct ffa_mem_ops_args *args);
+ };
+
+ #endif /* _LINUX_ARM_FFA_H */
+--
+2.29.2
+
diff --git a/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc0/0015-tee-add-sec_world_id-to-struct-tee_shm.patch b/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc0/0015-tee-add-sec_world_id-to-struct-tee_shm.patch
new file mode 100644
index 0000000..286d6f8
--- /dev/null
+++ b/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc0/0015-tee-add-sec_world_id-to-struct-tee_shm.patch
@@ -0,0 +1,44 @@
+From 0f6e0009dc123faa5630bc02977674e182c5938c Mon Sep 17 00:00:00 2001
+From: Jens Wiklander <jens.wiklander@linaro.org>
+Date: Thu, 25 Mar 2021 15:08:44 +0100
+Subject: [PATCH 07/14] tee: add sec_world_id to struct tee_shm
+
+Adds sec_world_id to struct tee_shm which describes a shared memory
+object. sec_world_id can be used by a driver to store an id assigned by
+secure world.
+
+Signed-off-by: Jens Wiklander <jens.wiklander@linaro.org>
+
+Upstream-Status: Pending [Not submitted to upstream yet]
+---
+ include/linux/tee_drv.h | 7 ++++++-
+ 1 file changed, 6 insertions(+), 1 deletion(-)
+
+diff --git a/include/linux/tee_drv.h b/include/linux/tee_drv.h
+index cdd049a724b1..93d836fded8b 100644
+--- a/include/linux/tee_drv.h
++++ b/include/linux/tee_drv.h
+@@ -196,7 +196,11 @@ int tee_session_calc_client_uuid(uuid_t *uuid, u32 connection_method,
+ * @num_pages: number of locked pages
+ * @dmabuf: dmabuf used to for exporting to user space
+ * @flags: defined by TEE_SHM_* in tee_drv.h
+- * @id: unique id of a shared memory object on this device
++ * @id: unique id of a shared memory object on this device, shared
++ * with user space
++ * @sec_world_id:
++ * secure world assigned id of this shared memory object, not
++ * used by all drivers
+ *
+ * This pool is only supposed to be accessed directly from the TEE
+ * subsystem and from drivers that implements their own shm pool manager.
+@@ -212,6 +216,7 @@ struct tee_shm {
+ struct dma_buf *dmabuf;
+ u32 flags;
+ int id;
++ u64 sec_world_id;
+ };
+
+ /**
+--
+2.29.2
+
diff --git a/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc0/0016-optee-simplify-optee_release.patch b/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc0/0016-optee-simplify-optee_release.patch
new file mode 100644
index 0000000..6fe573d
--- /dev/null
+++ b/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc0/0016-optee-simplify-optee_release.patch
@@ -0,0 +1,179 @@
+From 0c25ca5835725220605f3dbf6225dcf22923cc0f Mon Sep 17 00:00:00 2001
+From: Jens Wiklander <jens.wiklander@linaro.org>
+Date: Thu, 25 Mar 2021 15:08:46 +0100
+Subject: [PATCH 08/14] optee: simplify optee_release()
+
+Simplifies optee_release() with a new helper function,
+optee_close_session_helper() which has been factored out from
+optee_close_session().
+
+A separate optee_release_supp() is added for the supplicant device.
+
+Signed-off-by: Jens Wiklander <jens.wiklander@linaro.org>
+
+Upstream-Status: Pending [Not submitted to upstream yet]
+---
+ drivers/tee/optee/call.c | 31 ++++++++++-------
+ drivers/tee/optee/core.c | 55 +++++++++++--------------------
+ drivers/tee/optee/optee_private.h | 1 +
+ 3 files changed, 39 insertions(+), 48 deletions(-)
+
+diff --git a/drivers/tee/optee/call.c b/drivers/tee/optee/call.c
+index 780d7c4fd756..c0eca4d7d7f2 100644
+--- a/drivers/tee/optee/call.c
++++ b/drivers/tee/optee/call.c
+@@ -283,12 +283,28 @@ int optee_open_session(struct tee_context *ctx,
+ return rc;
+ }
+
+-int optee_close_session(struct tee_context *ctx, u32 session)
++int optee_close_session_helper(struct tee_context *ctx, u32 session)
+ {
+- struct optee_context_data *ctxdata = ctx->data;
+ struct tee_shm *shm;
+ struct optee_msg_arg *msg_arg;
+ phys_addr_t msg_parg;
++
++ shm = get_msg_arg(ctx, 0, &msg_arg, &msg_parg);
++ if (IS_ERR(shm))
++ return PTR_ERR(shm);
++
++ msg_arg->cmd = OPTEE_MSG_CMD_CLOSE_SESSION;
++ msg_arg->session = session;
++ optee_do_call_with_arg(ctx, msg_parg);
++
++ tee_shm_free(shm);
++
++ return 0;
++}
++
++int optee_close_session(struct tee_context *ctx, u32 session)
++{
++ struct optee_context_data *ctxdata = ctx->data;
+ struct optee_session *sess;
+
+ /* Check that the session is valid and remove it from the list */
+@@ -301,16 +317,7 @@ int optee_close_session(struct tee_context *ctx, u32 session)
+ return -EINVAL;
+ kfree(sess);
+
+- shm = get_msg_arg(ctx, 0, &msg_arg, &msg_parg);
+- if (IS_ERR(shm))
+- return PTR_ERR(shm);
+-
+- msg_arg->cmd = OPTEE_MSG_CMD_CLOSE_SESSION;
+- msg_arg->session = session;
+- optee_do_call_with_arg(ctx, msg_parg);
+-
+- tee_shm_free(shm);
+- return 0;
++ return optee_close_session_helper(ctx, session);
+ }
+
+ int optee_invoke_func(struct tee_context *ctx, struct tee_ioctl_invoke_arg *arg,
+diff --git a/drivers/tee/optee/core.c b/drivers/tee/optee/core.c
+index 63542c1cc291..e39c6d290d83 100644
+--- a/drivers/tee/optee/core.c
++++ b/drivers/tee/optee/core.c
+@@ -263,59 +263,42 @@ static int optee_open(struct tee_context *ctx)
+ return 0;
+ }
+
+-static void optee_release(struct tee_context *ctx)
++static void optee_release_helper(struct tee_context *ctx,
++ int (*close_session)(struct tee_context *ctx,
++ u32 session))
+ {
+ struct optee_context_data *ctxdata = ctx->data;
+- struct tee_device *teedev = ctx->teedev;
+- struct optee *optee = tee_get_drvdata(teedev);
+- struct tee_shm *shm;
+- struct optee_msg_arg *arg = NULL;
+- phys_addr_t parg;
+ struct optee_session *sess;
+ struct optee_session *sess_tmp;
+
+ if (!ctxdata)
+ return;
+
+- shm = tee_shm_alloc(ctx, sizeof(struct optee_msg_arg), TEE_SHM_MAPPED);
+- if (!IS_ERR(shm)) {
+- arg = tee_shm_get_va(shm, 0);
+- /*
+- * If va2pa fails for some reason, we can't call into
+- * secure world, only free the memory. Secure OS will leak
+- * sessions and finally refuse more sessions, but we will
+- * at least let normal world reclaim its memory.
+- */
+- if (!IS_ERR(arg))
+- if (tee_shm_va2pa(shm, arg, &parg))
+- arg = NULL; /* prevent usage of parg below */
+- }
+-
+ list_for_each_entry_safe(sess, sess_tmp, &ctxdata->sess_list,
+ list_node) {
+ list_del(&sess->list_node);
+- if (!IS_ERR_OR_NULL(arg)) {
+- memset(arg, 0, sizeof(*arg));
+- arg->cmd = OPTEE_MSG_CMD_CLOSE_SESSION;
+- arg->session = sess->session_id;
+- optee_do_call_with_arg(ctx, parg);
+- }
++ close_session(ctx, sess->session_id);
+ kfree(sess);
+ }
+ kfree(ctxdata);
++ ctx->data = NULL;
++}
+
+- if (!IS_ERR(shm))
+- tee_shm_free(shm);
++static void optee_release(struct tee_context *ctx)
++{
++ optee_release_helper(ctx, optee_close_session_helper);
++}
+
+- ctx->data = NULL;
++static void optee_release_supp(struct tee_context *ctx)
++{
++ struct optee *optee = tee_get_drvdata(ctx->teedev);
+
+- if (teedev == optee->supp_teedev) {
+- if (optee->scan_bus_wq) {
+- destroy_workqueue(optee->scan_bus_wq);
+- optee->scan_bus_wq = NULL;
+- }
+- optee_supp_release(&optee->supp);
++ optee_release_helper(ctx, optee_close_session_helper);
++ if (optee->scan_bus_wq) {
++ destroy_workqueue(optee->scan_bus_wq);
++ optee->scan_bus_wq = NULL;
+ }
++ optee_supp_release(&optee->supp);
+ }
+
+ static const struct tee_driver_ops optee_ops = {
+@@ -339,7 +322,7 @@ static const struct tee_desc optee_desc = {
+ static const struct tee_driver_ops optee_supp_ops = {
+ .get_version = optee_get_version,
+ .open = optee_open,
+- .release = optee_release,
++ .release = optee_release_supp,
+ .supp_recv = optee_supp_recv,
+ .supp_send = optee_supp_send,
+ .shm_register = optee_shm_register_supp,
+diff --git a/drivers/tee/optee/optee_private.h b/drivers/tee/optee/optee_private.h
+index e25b216a14ef..2b63b796645e 100644
+--- a/drivers/tee/optee/optee_private.h
++++ b/drivers/tee/optee/optee_private.h
+@@ -152,6 +152,7 @@ u32 optee_do_call_with_arg(struct tee_context *ctx, phys_addr_t parg);
+ int optee_open_session(struct tee_context *ctx,
+ struct tee_ioctl_open_session_arg *arg,
+ struct tee_param *param);
++int optee_close_session_helper(struct tee_context *ctx, u32 session);
+ int optee_close_session(struct tee_context *ctx, u32 session);
+ int optee_invoke_func(struct tee_context *ctx, struct tee_ioctl_invoke_arg *arg,
+ struct tee_param *param);
+--
+2.29.2
+
--git a/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc0/0017-optee-sync-OP-TEE-headers.patch b/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc0/0017-optee-sync-OP-TEE-headers.patch
new file mode 100644
index 0000000..a8797a3
--- /dev/null
+++ b/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc0/0017-optee-sync-OP-TEE-headers.patch
@@ -0,0 +1,644 @@
+From c325e66e1cbacc074051034ce7e40b3e0e987c99 Mon Sep 17 00:00:00 2001
+From: Jens Wiklander <jens.wiklander@linaro.org>
+Date: Wed, 20 Jan 2021 11:14:12 +0100
+Subject: [PATCH 09/14] optee: sync OP-TEE headers
+
+Pulls in updates in the internal headers from OP-TEE OS [1]. A few
+defines has been shortened, hence the changes in rpc.c. Defines not used
+by the driver in tee_rpc_cmd.h has been filtered out.
+
+Note that this does not change the ABI.
+
+Link: [1] https://github.com/OP-TEE/optee_os
+Reviewed-by: Sumit Garg <sumit.garg@linaro.org>
+Signed-off-by: Jens Wiklander <jens.wiklander@linaro.org>
+Change-Id: I5d20a22a3f38bfc9d232279d5f00505c4d3ba965
+
+Upstream-Status: Backport [https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v5.13-rc7&id=617d8e8b347edcee6da38df0aeb671fc9c9ba19c]
+---
+ drivers/tee/optee/optee_msg.h | 156 ++----------------------------
+ drivers/tee/optee/optee_rpc_cmd.h | 103 ++++++++++++++++++++
+ drivers/tee/optee/optee_smc.h | 70 +++++++++-----
+ drivers/tee/optee/rpc.c | 39 ++++----
+ 4 files changed, 179 insertions(+), 189 deletions(-)
+ create mode 100644 drivers/tee/optee/optee_rpc_cmd.h
+
+diff --git a/drivers/tee/optee/optee_msg.h b/drivers/tee/optee/optee_msg.h
+index 7b2d919da2ac..1e1341a5eaf2 100644
+--- a/drivers/tee/optee/optee_msg.h
++++ b/drivers/tee/optee/optee_msg.h
+@@ -1,6 +1,6 @@
+ /* SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) */
+ /*
+- * Copyright (c) 2015-2019, Linaro Limited
++ * Copyright (c) 2015-2021, Linaro Limited
+ */
+ #ifndef _OPTEE_MSG_H
+ #define _OPTEE_MSG_H
+@@ -12,11 +12,9 @@
+ * This file defines the OP-TEE message protocol used to communicate
+ * with an instance of OP-TEE running in secure world.
+ *
+- * This file is divided into three sections.
++ * This file is divided into two sections.
+ * 1. Formatting of messages.
+ * 2. Requests from normal world
+- * 3. Requests from secure world, Remote Procedure Call (RPC), handled by
+- * tee-supplicant.
+ */
+
+ /*****************************************************************************
+@@ -54,8 +52,8 @@
+ * Every entry in buffer should point to a 4k page beginning (12 least
+ * significant bits must be equal to zero).
+ *
+- * 12 least significant bints of optee_msg_param.u.tmem.buf_ptr should hold page
+- * offset of the user buffer.
++ * 12 least significant bits of optee_msg_param.u.tmem.buf_ptr should hold
++ * page offset of user buffer.
+ *
+ * So, entries should be placed like members of this structure:
+ *
+@@ -176,17 +174,9 @@ struct optee_msg_param {
+ * @params: the parameters supplied to the OS Command
+ *
+ * All normal calls to Trusted OS uses this struct. If cmd requires further
+- * information than what these field holds it can be passed as a parameter
++ * information than what these fields hold it can be passed as a parameter
+ * tagged as meta (setting the OPTEE_MSG_ATTR_META bit in corresponding
+- * attrs field). All parameters tagged as meta has to come first.
+- *
+- * Temp memref parameters can be fragmented if supported by the Trusted OS
+- * (when optee_smc.h is bearer of this protocol this is indicated with
+- * OPTEE_SMC_SEC_CAP_UNREGISTERED_SHM). If a logical memref parameter is
+- * fragmented then has all but the last fragment the
+- * OPTEE_MSG_ATTR_FRAGMENT bit set in attrs. Even if a memref is fragmented
+- * it will still be presented as a single logical memref to the Trusted
+- * Application.
++ * attrs field). All parameters tagged as meta have to come first.
+ */
+ struct optee_msg_arg {
+ u32 cmd;
+@@ -290,15 +280,12 @@ struct optee_msg_arg {
+ * OPTEE_MSG_CMD_REGISTER_SHM registers a shared memory reference. The
+ * information is passed as:
+ * [in] param[0].attr OPTEE_MSG_ATTR_TYPE_TMEM_INPUT
+- * [| OPTEE_MSG_ATTR_FRAGMENT]
++ * [| OPTEE_MSG_ATTR_NONCONTIG]
+ * [in] param[0].u.tmem.buf_ptr physical address (of first fragment)
+ * [in] param[0].u.tmem.size size (of first fragment)
+ * [in] param[0].u.tmem.shm_ref holds shared memory reference
+- * ...
+- * The shared memory can optionally be fragmented, temp memrefs can follow
+- * each other with all but the last with the OPTEE_MSG_ATTR_FRAGMENT bit set.
+ *
+- * OPTEE_MSG_CMD_UNREGISTER_SHM unregisteres a previously registered shared
++ * OPTEE_MSG_CMD_UNREGISTER_SHM unregisters a previously registered shared
+ * memory reference. The information is passed as:
+ * [in] param[0].attr OPTEE_MSG_ATTR_TYPE_RMEM_INPUT
+ * [in] param[0].u.rmem.shm_ref holds shared memory reference
+@@ -313,131 +300,4 @@ struct optee_msg_arg {
+ #define OPTEE_MSG_CMD_UNREGISTER_SHM 5
+ #define OPTEE_MSG_FUNCID_CALL_WITH_ARG 0x0004
+
+-/*****************************************************************************
+- * Part 3 - Requests from secure world, RPC
+- *****************************************************************************/
+-
+-/*
+- * All RPC is done with a struct optee_msg_arg as bearer of information,
+- * struct optee_msg_arg::arg holds values defined by OPTEE_MSG_RPC_CMD_* below
+- *
+- * RPC communication with tee-supplicant is reversed compared to normal
+- * client communication desribed above. The supplicant receives requests
+- * and sends responses.
+- */
+-
+-/*
+- * Load a TA into memory, defined in tee-supplicant
+- */
+-#define OPTEE_MSG_RPC_CMD_LOAD_TA 0
+-
+-/*
+- * Reserved
+- */
+-#define OPTEE_MSG_RPC_CMD_RPMB 1
+-
+-/*
+- * File system access, defined in tee-supplicant
+- */
+-#define OPTEE_MSG_RPC_CMD_FS 2
+-
+-/*
+- * Get time
+- *
+- * Returns number of seconds and nano seconds since the Epoch,
+- * 1970-01-01 00:00:00 +0000 (UTC).
+- *
+- * [out] param[0].u.value.a Number of seconds
+- * [out] param[0].u.value.b Number of nano seconds.
+- */
+-#define OPTEE_MSG_RPC_CMD_GET_TIME 3
+-
+-/*
+- * Wait queue primitive, helper for secure world to implement a wait queue.
+- *
+- * If secure world need to wait for a secure world mutex it issues a sleep
+- * request instead of spinning in secure world. Conversely is a wakeup
+- * request issued when a secure world mutex with a thread waiting thread is
+- * unlocked.
+- *
+- * Waiting on a key
+- * [in] param[0].u.value.a OPTEE_MSG_RPC_WAIT_QUEUE_SLEEP
+- * [in] param[0].u.value.b wait key
+- *
+- * Waking up a key
+- * [in] param[0].u.value.a OPTEE_MSG_RPC_WAIT_QUEUE_WAKEUP
+- * [in] param[0].u.value.b wakeup key
+- */
+-#define OPTEE_MSG_RPC_CMD_WAIT_QUEUE 4
+-#define OPTEE_MSG_RPC_WAIT_QUEUE_SLEEP 0
+-#define OPTEE_MSG_RPC_WAIT_QUEUE_WAKEUP 1
+-
+-/*
+- * Suspend execution
+- *
+- * [in] param[0].value .a number of milliseconds to suspend
+- */
+-#define OPTEE_MSG_RPC_CMD_SUSPEND 5
+-
+-/*
+- * Allocate a piece of shared memory
+- *
+- * Shared memory can optionally be fragmented, to support that additional
+- * spare param entries are allocated to make room for eventual fragments.
+- * The spare param entries has .attr = OPTEE_MSG_ATTR_TYPE_NONE when
+- * unused. All returned temp memrefs except the last should have the
+- * OPTEE_MSG_ATTR_FRAGMENT bit set in the attr field.
+- *
+- * [in] param[0].u.value.a type of memory one of
+- * OPTEE_MSG_RPC_SHM_TYPE_* below
+- * [in] param[0].u.value.b requested size
+- * [in] param[0].u.value.c required alignment
+- *
+- * [out] param[0].u.tmem.buf_ptr physical address (of first fragment)
+- * [out] param[0].u.tmem.size size (of first fragment)
+- * [out] param[0].u.tmem.shm_ref shared memory reference
+- * ...
+- * [out] param[n].u.tmem.buf_ptr physical address
+- * [out] param[n].u.tmem.size size
+- * [out] param[n].u.tmem.shm_ref shared memory reference (same value
+- * as in param[n-1].u.tmem.shm_ref)
+- */
+-#define OPTEE_MSG_RPC_CMD_SHM_ALLOC 6
+-/* Memory that can be shared with a non-secure user space application */
+-#define OPTEE_MSG_RPC_SHM_TYPE_APPL 0
+-/* Memory only shared with non-secure kernel */
+-#define OPTEE_MSG_RPC_SHM_TYPE_KERNEL 1
+-
+-/*
+- * Free shared memory previously allocated with OPTEE_MSG_RPC_CMD_SHM_ALLOC
+- *
+- * [in] param[0].u.value.a type of memory one of
+- * OPTEE_MSG_RPC_SHM_TYPE_* above
+- * [in] param[0].u.value.b value of shared memory reference
+- * returned in param[0].u.tmem.shm_ref
+- * above
+- */
+-#define OPTEE_MSG_RPC_CMD_SHM_FREE 7
+-
+-/*
+- * Access a device on an i2c bus
+- *
+- * [in] param[0].u.value.a mode: RD(0), WR(1)
+- * [in] param[0].u.value.b i2c adapter
+- * [in] param[0].u.value.c i2c chip
+- *
+- * [in] param[1].u.value.a i2c control flags
+- *
+- * [in/out] memref[2] buffer to exchange the transfer data
+- * with the secure world
+- *
+- * [out] param[3].u.value.a bytes transferred by the driver
+- */
+-#define OPTEE_MSG_RPC_CMD_I2C_TRANSFER 21
+-/* I2C master transfer modes */
+-#define OPTEE_MSG_RPC_CMD_I2C_TRANSFER_RD 0
+-#define OPTEE_MSG_RPC_CMD_I2C_TRANSFER_WR 1
+-/* I2C master control flags */
+-#define OPTEE_MSG_RPC_CMD_I2C_FLAGS_TEN_BIT BIT(0)
+-
+ #endif /* _OPTEE_MSG_H */
+diff --git a/drivers/tee/optee/optee_rpc_cmd.h b/drivers/tee/optee/optee_rpc_cmd.h
+new file mode 100644
+index 000000000000..b8275140cef8
+--- /dev/null
++++ b/drivers/tee/optee/optee_rpc_cmd.h
+@@ -0,0 +1,103 @@
++/* SPDX-License-Identifier: BSD-2-Clause */
++/*
++ * Copyright (c) 2016-2021, Linaro Limited
++ */
++
++#ifndef __OPTEE_RPC_CMD_H
++#define __OPTEE_RPC_CMD_H
++
++/*
++ * All RPC is done with a struct optee_msg_arg as bearer of information,
++ * struct optee_msg_arg::arg holds values defined by OPTEE_RPC_CMD_* below.
++ * Only the commands handled by the kernel driver are defined here.
++ *
++ * RPC communication with tee-supplicant is reversed compared to normal
++ * client communication described above. The supplicant receives requests
++ * and sends responses.
++ */
++
++/*
++ * Get time
++ *
++ * Returns number of seconds and nano seconds since the Epoch,
++ * 1970-01-01 00:00:00 +0000 (UTC).
++ *
++ * [out] value[0].a Number of seconds
++ * [out] value[0].b Number of nano seconds.
++ */
++#define OPTEE_RPC_CMD_GET_TIME 3
++
++/*
++ * Wait queue primitive, helper for secure world to implement a wait queue.
++ *
++ * If secure world needs to wait for a secure world mutex it issues a sleep
++ * request instead of spinning in secure world. Conversely is a wakeup
++ * request issued when a secure world mutex with a thread waiting thread is
++ * unlocked.
++ *
++ * Waiting on a key
++ * [in] value[0].a OPTEE_RPC_WAIT_QUEUE_SLEEP
++ * [in] value[0].b Wait key
++ *
++ * Waking up a key
++ * [in] value[0].a OPTEE_RPC_WAIT_QUEUE_WAKEUP
++ * [in] value[0].b Wakeup key
++ */
++#define OPTEE_RPC_CMD_WAIT_QUEUE 4
++#define OPTEE_RPC_WAIT_QUEUE_SLEEP 0
++#define OPTEE_RPC_WAIT_QUEUE_WAKEUP 1
++
++/*
++ * Suspend execution
++ *
++ * [in] value[0].a Number of milliseconds to suspend
++ */
++#define OPTEE_RPC_CMD_SUSPEND 5
++
++/*
++ * Allocate a piece of shared memory
++ *
++ * [in] value[0].a Type of memory one of
++ * OPTEE_RPC_SHM_TYPE_* below
++ * [in] value[0].b Requested size
++ * [in] value[0].c Required alignment
++ * [out] memref[0] Buffer
++ */
++#define OPTEE_RPC_CMD_SHM_ALLOC 6
++/* Memory that can be shared with a non-secure user space application */
++#define OPTEE_RPC_SHM_TYPE_APPL 0
++/* Memory only shared with non-secure kernel */
++#define OPTEE_RPC_SHM_TYPE_KERNEL 1
++
++/*
++ * Free shared memory previously allocated with OPTEE_RPC_CMD_SHM_ALLOC
++ *
++ * [in] value[0].a Type of memory one of
++ * OPTEE_RPC_SHM_TYPE_* above
++ * [in] value[0].b Value of shared memory reference or cookie
++ */
++#define OPTEE_RPC_CMD_SHM_FREE 7
++
++/*
++ * Issue master requests (read and write operations) to an I2C chip.
++ *
++ * [in] value[0].a Transfer mode (OPTEE_RPC_I2C_TRANSFER_*)
++ * [in] value[0].b The I2C bus (a.k.a adapter).
++ * 16 bit field.
++ * [in] value[0].c The I2C chip (a.k.a address).
++ * 16 bit field (either 7 or 10 bit effective).
++ * [in] value[1].a The I2C master control flags (ie, 10 bit address).
++ * 16 bit field.
++ * [in/out] memref[2] Buffer used for data transfers.
++ * [out] value[3].a Number of bytes transferred by the REE.
++ */
++#define OPTEE_RPC_CMD_I2C_TRANSFER 21
++
++/* I2C master transfer modes */
++#define OPTEE_RPC_I2C_TRANSFER_RD 0
++#define OPTEE_RPC_I2C_TRANSFER_WR 1
++
++/* I2C master control flags */
++#define OPTEE_RPC_I2C_FLAGS_TEN_BIT BIT(0)
++
++#endif /*__OPTEE_RPC_CMD_H*/
+diff --git a/drivers/tee/optee/optee_smc.h b/drivers/tee/optee/optee_smc.h
+index 777ad54d4c2c..821e1c30c150 100644
+--- a/drivers/tee/optee/optee_smc.h
++++ b/drivers/tee/optee/optee_smc.h
+@@ -1,6 +1,6 @@
+ /* SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) */
+ /*
+- * Copyright (c) 2015-2019, Linaro Limited
++ * Copyright (c) 2015-2021, Linaro Limited
+ */
+ #ifndef OPTEE_SMC_H
+ #define OPTEE_SMC_H
+@@ -39,10 +39,10 @@
+ /*
+ * Function specified by SMC Calling convention
+ *
+- * Return one of the following UIDs if using API specified in this file
+- * without further extentions:
+- * 65cb6b93-af0c-4617-8ed6-644a8d1140f8
+- * see also OPTEE_SMC_UID_* in optee_msg.h
++ * Return the following UID if using API specified in this file
++ * without further extensions:
++ * 384fb3e0-e7f8-11e3-af63-0002a5d5c51b.
++ * see also OPTEE_MSG_UID_* in optee_msg.h
+ */
+ #define OPTEE_SMC_FUNCID_CALLS_UID OPTEE_MSG_FUNCID_CALLS_UID
+ #define OPTEE_SMC_CALLS_UID \
+@@ -53,7 +53,7 @@
+ /*
+ * Function specified by SMC Calling convention
+ *
+- * Returns 2.0 if using API specified in this file without further extentions.
++ * Returns 2.0 if using API specified in this file without further extensions.
+ * see also OPTEE_MSG_REVISION_* in optee_msg.h
+ */
+ #define OPTEE_SMC_FUNCID_CALLS_REVISION OPTEE_MSG_FUNCID_CALLS_REVISION
+@@ -109,8 +109,8 @@ struct optee_smc_call_get_os_revision_result {
+ *
+ * Call register usage:
+ * a0 SMC Function ID, OPTEE_SMC*CALL_WITH_ARG
+- * a1 Upper 32bit of a 64bit physical pointer to a struct optee_msg_arg
+- * a2 Lower 32bit of a 64bit physical pointer to a struct optee_msg_arg
++ * a1 Upper 32 bits of a 64-bit physical pointer to a struct optee_msg_arg
++ * a2 Lower 32 bits of a 64-bit physical pointer to a struct optee_msg_arg
+ * a3 Cache settings, not used if physical pointer is in a predefined shared
+ * memory area else per OPTEE_SMC_SHM_*
+ * a4-6 Not used
+@@ -214,8 +214,9 @@ struct optee_smc_get_shm_config_result {
+ * secure world accepts command buffers located in any parts of non-secure RAM
+ */
+ #define OPTEE_SMC_SEC_CAP_DYNAMIC_SHM BIT(2)
+-
+-/* Secure world supports Shared Memory with a NULL buffer reference */
++/* Secure world is built with virtualization support */
++#define OPTEE_SMC_SEC_CAP_VIRTUALIZATION BIT(3)
++/* Secure world supports Shared Memory with a NULL reference */
+ #define OPTEE_SMC_SEC_CAP_MEMREF_NULL BIT(4)
+
+ #define OPTEE_SMC_FUNCID_EXCHANGE_CAPABILITIES 9
+@@ -245,8 +246,8 @@ struct optee_smc_exchange_capabilities_result {
+ *
+ * Normal return register usage:
+ * a0 OPTEE_SMC_RETURN_OK
+- * a1 Upper 32bit of a 64bit Shared memory cookie
+- * a2 Lower 32bit of a 64bit Shared memory cookie
++ * a1 Upper 32 bits of a 64-bit Shared memory cookie
++ * a2 Lower 32 bits of a 64-bit Shared memory cookie
+ * a3-7 Preserved
+ *
+ * Cache empty return register usage:
+@@ -293,6 +294,31 @@ struct optee_smc_disable_shm_cache_result {
+ #define OPTEE_SMC_ENABLE_SHM_CACHE \
+ OPTEE_SMC_FAST_CALL_VAL(OPTEE_SMC_FUNCID_ENABLE_SHM_CACHE)
+
++/*
++ * Query OP-TEE about number of supported threads
++ *
++ * Normal World OS or Hypervisor issues this call to find out how many
++ * threads OP-TEE supports. That is how many standard calls can be issued
++ * in parallel before OP-TEE will return OPTEE_SMC_RETURN_ETHREAD_LIMIT.
++ *
++ * Call requests usage:
++ * a0 SMC Function ID, OPTEE_SMC_GET_THREAD_COUNT
++ * a1-6 Not used
++ * a7 Hypervisor Client ID register
++ *
++ * Normal return register usage:
++ * a0 OPTEE_SMC_RETURN_OK
++ * a1 Number of threads
++ * a2-7 Preserved
++ *
++ * Error return:
++ * a0 OPTEE_SMC_RETURN_UNKNOWN_FUNCTION Requested call is not implemented
++ * a1-7 Preserved
++ */
++#define OPTEE_SMC_FUNCID_GET_THREAD_COUNT 15
++#define OPTEE_SMC_GET_THREAD_COUNT \
++ OPTEE_SMC_FAST_CALL_VAL(OPTEE_SMC_FUNCID_GET_THREAD_COUNT)
++
+ /*
+ * Resume from RPC (for example after processing a foreign interrupt)
+ *
+@@ -341,16 +367,16 @@ struct optee_smc_disable_shm_cache_result {
+ *
+ * "Return" register usage:
+ * a0 SMC Function ID, OPTEE_SMC_CALL_RETURN_FROM_RPC.
+- * a1 Upper 32bits of 64bit physical pointer to allocated
++ * a1 Upper 32 bits of 64-bit physical pointer to allocated
+ * memory, (a1 == 0 && a2 == 0) if size was 0 or if memory can't
+ * be allocated.
+- * a2 Lower 32bits of 64bit physical pointer to allocated
++ * a2 Lower 32 bits of 64-bit physical pointer to allocated
+ * memory, (a1 == 0 && a2 == 0) if size was 0 or if memory can't
+ * be allocated
+ * a3 Preserved
+- * a4 Upper 32bits of 64bit Shared memory cookie used when freeing
++ * a4 Upper 32 bits of 64-bit Shared memory cookie used when freeing
+ * the memory or doing an RPC
+- * a5 Lower 32bits of 64bit Shared memory cookie used when freeing
++ * a5 Lower 32 bits of 64-bit Shared memory cookie used when freeing
+ * the memory or doing an RPC
+ * a6-7 Preserved
+ */
+@@ -363,9 +389,9 @@ struct optee_smc_disable_shm_cache_result {
+ *
+ * "Call" register usage:
+ * a0 This value, OPTEE_SMC_RETURN_RPC_FREE
+- * a1 Upper 32bits of 64bit shared memory cookie belonging to this
++ * a1 Upper 32 bits of 64-bit shared memory cookie belonging to this
+ * argument memory
+- * a2 Lower 32bits of 64bit shared memory cookie belonging to this
++ * a2 Lower 32 bits of 64-bit shared memory cookie belonging to this
+ * argument memory
+ * a3-7 Resume information, must be preserved
+ *
+@@ -379,7 +405,7 @@ struct optee_smc_disable_shm_cache_result {
+ OPTEE_SMC_RPC_VAL(OPTEE_SMC_RPC_FUNC_FREE)
+
+ /*
+- * Deliver foreign interrupt to normal world.
++ * Deliver a foreign interrupt in normal world.
+ *
+ * "Call" register usage:
+ * a0 OPTEE_SMC_RETURN_RPC_FOREIGN_INTR
+@@ -389,7 +415,7 @@ struct optee_smc_disable_shm_cache_result {
+ * a0 SMC Function ID, OPTEE_SMC_CALL_RETURN_FROM_RPC.
+ * a1-7 Preserved
+ */
+-#define OPTEE_SMC_RPC_FUNC_FOREIGN_INTR 4
++#define OPTEE_SMC_RPC_FUNC_FOREIGN_INTR 4
+ #define OPTEE_SMC_RETURN_RPC_FOREIGN_INTR \
+ OPTEE_SMC_RPC_VAL(OPTEE_SMC_RPC_FUNC_FOREIGN_INTR)
+
+@@ -405,10 +431,10 @@ struct optee_smc_disable_shm_cache_result {
+ *
+ * "Call" register usage:
+ * a0 OPTEE_SMC_RETURN_RPC_CMD
+- * a1 Upper 32bit of a 64bit Shared memory cookie holding a
++ * a1 Upper 32 bits of a 64-bit Shared memory cookie holding a
+ * struct optee_msg_arg, must be preserved, only the data should
+ * be updated
+- * a2 Lower 32bit of a 64bit Shared memory cookie holding a
++ * a2 Lower 32 bits of a 64-bit Shared memory cookie holding a
+ * struct optee_msg_arg, must be preserved, only the data should
+ * be updated
+ * a3-7 Resume information, must be preserved
+diff --git a/drivers/tee/optee/rpc.c b/drivers/tee/optee/rpc.c
+index 6cbb3643c6c4..1849180b0278 100644
+--- a/drivers/tee/optee/rpc.c
++++ b/drivers/tee/optee/rpc.c
+@@ -12,6 +12,7 @@
+ #include <linux/tee_drv.h>
+ #include "optee_private.h"
+ #include "optee_smc.h"
++#include "optee_rpc_cmd.h"
+
+ struct wq_entry {
+ struct list_head link;
+@@ -90,7 +91,7 @@ static void handle_rpc_func_cmd_i2c_transfer(struct tee_context *ctx,
+ if (!adapter)
+ goto bad;
+
+- if (params[1].u.value.a & OPTEE_MSG_RPC_CMD_I2C_FLAGS_TEN_BIT) {
++ if (params[1].u.value.a & OPTEE_RPC_I2C_FLAGS_TEN_BIT) {
+ if (!i2c_check_functionality(adapter,
+ I2C_FUNC_10BIT_ADDR)) {
+ i2c_put_adapter(adapter);
+@@ -105,10 +106,10 @@ static void handle_rpc_func_cmd_i2c_transfer(struct tee_context *ctx,
+ msg.len = params[2].u.memref.size;
+
+ switch (params[0].u.value.a) {
+- case OPTEE_MSG_RPC_CMD_I2C_TRANSFER_RD:
++ case OPTEE_RPC_I2C_TRANSFER_RD:
+ msg.flags |= I2C_M_RD;
+ break;
+- case OPTEE_MSG_RPC_CMD_I2C_TRANSFER_WR:
++ case OPTEE_RPC_I2C_TRANSFER_WR:
+ break;
+ default:
+ i2c_put_adapter(adapter);
+@@ -195,10 +196,10 @@ static void handle_rpc_func_cmd_wq(struct optee *optee,
+ goto bad;
+
+ switch (arg->params[0].u.value.a) {
+- case OPTEE_MSG_RPC_WAIT_QUEUE_SLEEP:
++ case OPTEE_RPC_WAIT_QUEUE_SLEEP:
+ wq_sleep(&optee->wait_queue, arg->params[0].u.value.b);
+ break;
+- case OPTEE_MSG_RPC_WAIT_QUEUE_WAKEUP:
++ case OPTEE_RPC_WAIT_QUEUE_WAKEUP:
+ wq_wakeup(&optee->wait_queue, arg->params[0].u.value.b);
+ break;
+ default:
+@@ -268,11 +269,11 @@ static struct tee_shm *cmd_alloc_suppl(struct tee_context *ctx, size_t sz)
+ struct tee_shm *shm;
+
+ param.attr = TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INOUT;
+- param.u.value.a = OPTEE_MSG_RPC_SHM_TYPE_APPL;
++ param.u.value.a = OPTEE_RPC_SHM_TYPE_APPL;
+ param.u.value.b = sz;
+ param.u.value.c = 0;
+
+- ret = optee_supp_thrd_req(ctx, OPTEE_MSG_RPC_CMD_SHM_ALLOC, 1, ¶m);
++ ret = optee_supp_thrd_req(ctx, OPTEE_RPC_CMD_SHM_ALLOC, 1, ¶m);
+ if (ret)
+ return ERR_PTR(-ENOMEM);
+
+@@ -309,10 +310,10 @@ static void handle_rpc_func_cmd_shm_alloc(struct tee_context *ctx,
+
+ sz = arg->params[0].u.value.b;
+ switch (arg->params[0].u.value.a) {
+- case OPTEE_MSG_RPC_SHM_TYPE_APPL:
++ case OPTEE_RPC_SHM_TYPE_APPL:
+ shm = cmd_alloc_suppl(ctx, sz);
+ break;
+- case OPTEE_MSG_RPC_SHM_TYPE_KERNEL:
++ case OPTEE_RPC_SHM_TYPE_KERNEL:
+ shm = tee_shm_alloc(ctx, sz, TEE_SHM_MAPPED);
+ break;
+ default:
+@@ -384,7 +385,7 @@ static void cmd_free_suppl(struct tee_context *ctx, struct tee_shm *shm)
+ struct tee_param param;
+
+ param.attr = TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INOUT;
+- param.u.value.a = OPTEE_MSG_RPC_SHM_TYPE_APPL;
++ param.u.value.a = OPTEE_RPC_SHM_TYPE_APPL;
+ param.u.value.b = tee_shm_get_id(shm);
+ param.u.value.c = 0;
+
+@@ -401,7 +402,7 @@ static void cmd_free_suppl(struct tee_context *ctx, struct tee_shm *shm)
+ */
+ tee_shm_put(shm);
+
+- optee_supp_thrd_req(ctx, OPTEE_MSG_RPC_CMD_SHM_FREE, 1, ¶m);
++ optee_supp_thrd_req(ctx, OPTEE_RPC_CMD_SHM_FREE, 1, ¶m);
+ }
+
+ static void handle_rpc_func_cmd_shm_free(struct tee_context *ctx,
+@@ -419,10 +420,10 @@ static void handle_rpc_func_cmd_shm_free(struct tee_context *ctx,
+
+ shm = (struct tee_shm *)(unsigned long)arg->params[0].u.value.b;
+ switch (arg->params[0].u.value.a) {
+- case OPTEE_MSG_RPC_SHM_TYPE_APPL:
++ case OPTEE_RPC_SHM_TYPE_APPL:
+ cmd_free_suppl(ctx, shm);
+ break;
+- case OPTEE_MSG_RPC_SHM_TYPE_KERNEL:
++ case OPTEE_RPC_SHM_TYPE_KERNEL:
+ tee_shm_free(shm);
+ break;
+ default:
+@@ -459,23 +460,23 @@ static void handle_rpc_func_cmd(struct tee_context *ctx, struct optee *optee,
+ }
+
+ switch (arg->cmd) {
+- case OPTEE_MSG_RPC_CMD_GET_TIME:
++ case OPTEE_RPC_CMD_GET_TIME:
+ handle_rpc_func_cmd_get_time(arg);
+ break;
+- case OPTEE_MSG_RPC_CMD_WAIT_QUEUE:
++ case OPTEE_RPC_CMD_WAIT_QUEUE:
+ handle_rpc_func_cmd_wq(optee, arg);
+ break;
+- case OPTEE_MSG_RPC_CMD_SUSPEND:
++ case OPTEE_RPC_CMD_SUSPEND:
+ handle_rpc_func_cmd_wait(arg);
+ break;
+- case OPTEE_MSG_RPC_CMD_SHM_ALLOC:
++ case OPTEE_RPC_CMD_SHM_ALLOC:
+ free_pages_list(call_ctx);
+ handle_rpc_func_cmd_shm_alloc(ctx, arg, call_ctx);
+ break;
+- case OPTEE_MSG_RPC_CMD_SHM_FREE:
++ case OPTEE_RPC_CMD_SHM_FREE:
+ handle_rpc_func_cmd_shm_free(ctx, arg);
+ break;
+- case OPTEE_MSG_RPC_CMD_I2C_TRANSFER:
++ case OPTEE_RPC_CMD_I2C_TRANSFER:
+ handle_rpc_func_cmd_i2c_transfer(ctx, arg);
+ break;
+ default:
+--
+2.29.2
+
diff --git a/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc0/0018-optee-refactor-driver-with-internal-callbacks.patch b/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc0/0018-optee-refactor-driver-with-internal-callbacks.patch
new file mode 100644
index 0000000..3c7d7fd
--- /dev/null
+++ b/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc0/0018-optee-refactor-driver-with-internal-callbacks.patch
@@ -0,0 +1,720 @@
+From ca74085bd229be214f9bb9eec33f84a8f0a9090c Mon Sep 17 00:00:00 2001
+From: Jens Wiklander <jens.wiklander@linaro.org>
+Date: Thu, 25 Mar 2021 15:08:50 +0100
+Subject: [PATCH 10/14] optee: refactor driver with internal callbacks
+
+The OP-TEE driver is refactored with three internal callbacks replacing
+direct calls to optee_from_msg_param(), optee_to_msg_param() and
+optee_do_call_with_arg().
+
+These functions a central to communicating with OP-TEE in secure world
+by using the SMC Calling Convention directly.
+
+This refactoring makes room for using other primitives to communicate
+with OP-TEE in secure world while being able to reuse as much as
+possible from the present driver.
+
+Signed-off-by: Jens Wiklander <jens.wiklander@linaro.org>
+
+Upstream-Status: Pending [Not submitted to upstream yet]
+---
+ drivers/tee/optee/call.c | 86 +++++++++--------
+ drivers/tee/optee/core.c | 148 ++++++++++++++++++++----------
+ drivers/tee/optee/optee_private.h | 35 +++++--
+ drivers/tee/optee/rpc.c | 19 ++--
+ 4 files changed, 182 insertions(+), 106 deletions(-)
+
+diff --git a/drivers/tee/optee/call.c b/drivers/tee/optee/call.c
+index c0eca4d7d7f2..1439ab896cd0 100644
+--- a/drivers/tee/optee/call.c
++++ b/drivers/tee/optee/call.c
+@@ -1,6 +1,6 @@
+ // SPDX-License-Identifier: GPL-2.0-only
+ /*
+- * Copyright (c) 2015, Linaro Limited
++ * Copyright (c) 2015-2021, Linaro Limited
+ */
+ #include <linux/arm-smccc.h>
+ #include <linux/device.h>
+@@ -116,20 +116,25 @@ static struct optee_session *find_session(struct optee_context_data *ctxdata,
+ /**
+ * optee_do_call_with_arg() - Do an SMC to OP-TEE in secure world
+ * @ctx: calling context
+- * @parg: physical address of message to pass to secure world
++ * @arg: shared memory holding the message to pass to secure world
+ *
+ * Does and SMC to OP-TEE in secure world and handles eventual resulting
+ * Remote Procedure Calls (RPC) from OP-TEE.
+ *
+ * Returns return code from secure world, 0 is OK
+ */
+-u32 optee_do_call_with_arg(struct tee_context *ctx, phys_addr_t parg)
++int optee_do_call_with_arg(struct tee_context *ctx, struct tee_shm *arg)
+ {
+ struct optee *optee = tee_get_drvdata(ctx->teedev);
+ struct optee_call_waiter w;
+ struct optee_rpc_param param = { };
+ struct optee_call_ctx call_ctx = { };
+- u32 ret;
++ phys_addr_t parg;
++ int rc;
++
++ rc = tee_shm_get_pa(arg, 0, &parg);
++ if (rc)
++ return rc;
+
+ param.a0 = OPTEE_SMC_CALL_WITH_ARG;
+ reg_pair_from_64(¶m.a1, ¶m.a2, parg);
+@@ -157,7 +162,7 @@ u32 optee_do_call_with_arg(struct tee_context *ctx, phys_addr_t parg)
+ param.a3 = res.a3;
+ optee_handle_rpc(ctx, ¶m, &call_ctx);
+ } else {
+- ret = res.a0;
++ rc = res.a0;
+ break;
+ }
+ }
+@@ -169,14 +174,12 @@ u32 optee_do_call_with_arg(struct tee_context *ctx, phys_addr_t parg)
+ */
+ optee_cq_wait_final(&optee->call_queue, &w);
+
+- return ret;
++ return rc;
+ }
+
+ static struct tee_shm *get_msg_arg(struct tee_context *ctx, size_t num_params,
+- struct optee_msg_arg **msg_arg,
+- phys_addr_t *msg_parg)
++ struct optee_msg_arg **msg_arg)
+ {
+- int rc;
+ struct tee_shm *shm;
+ struct optee_msg_arg *ma;
+
+@@ -187,22 +190,13 @@ static struct tee_shm *get_msg_arg(struct tee_context *ctx, size_t num_params,
+
+ ma = tee_shm_get_va(shm, 0);
+ if (IS_ERR(ma)) {
+- rc = PTR_ERR(ma);
+- goto out;
++ tee_shm_free(shm);
++ return (void *)ma;
+ }
+
+- rc = tee_shm_get_pa(shm, 0, msg_parg);
+- if (rc)
+- goto out;
+-
+ memset(ma, 0, OPTEE_MSG_GET_ARG_SIZE(num_params));
+ ma->num_params = num_params;
+ *msg_arg = ma;
+-out:
+- if (rc) {
+- tee_shm_free(shm);
+- return ERR_PTR(rc);
+- }
+
+ return shm;
+ }
+@@ -211,15 +205,15 @@ int optee_open_session(struct tee_context *ctx,
+ struct tee_ioctl_open_session_arg *arg,
+ struct tee_param *param)
+ {
++ struct optee *optee = tee_get_drvdata(ctx->teedev);
+ struct optee_context_data *ctxdata = ctx->data;
+ int rc;
+ struct tee_shm *shm;
+ struct optee_msg_arg *msg_arg;
+- phys_addr_t msg_parg;
+ struct optee_session *sess = NULL;
+
+ /* +2 for the meta parameters added below */
+- shm = get_msg_arg(ctx, arg->num_params + 2, &msg_arg, &msg_parg);
++ shm = get_msg_arg(ctx, arg->num_params + 2, &msg_arg);
+ if (IS_ERR(shm))
+ return PTR_ERR(shm);
+
+@@ -242,7 +236,8 @@ int optee_open_session(struct tee_context *ctx,
+ if (rc)
+ goto out;
+
+- rc = optee_to_msg_param(msg_arg->params + 2, arg->num_params, param);
++ rc = optee->ops->to_msg_param(optee, msg_arg->params + 2,
++ arg->num_params, param);
+ if (rc)
+ goto out;
+
+@@ -252,7 +247,7 @@ int optee_open_session(struct tee_context *ctx,
+ goto out;
+ }
+
+- if (optee_do_call_with_arg(ctx, msg_parg)) {
++ if (optee->ops->do_call_with_arg(ctx, shm)) {
+ msg_arg->ret = TEEC_ERROR_COMMUNICATION;
+ msg_arg->ret_origin = TEEC_ORIGIN_COMMS;
+ }
+@@ -267,7 +262,8 @@ int optee_open_session(struct tee_context *ctx,
+ kfree(sess);
+ }
+
+- if (optee_from_msg_param(param, arg->num_params, msg_arg->params + 2)) {
++ if (optee->ops->from_msg_param(optee, param, arg->num_params,
++ msg_arg->params + 2)) {
+ arg->ret = TEEC_ERROR_COMMUNICATION;
+ arg->ret_origin = TEEC_ORIGIN_COMMS;
+ /* Close session again to avoid leakage */
+@@ -286,16 +282,16 @@ int optee_open_session(struct tee_context *ctx,
+ int optee_close_session_helper(struct tee_context *ctx, u32 session)
+ {
+ struct tee_shm *shm;
++ struct optee *optee = tee_get_drvdata(ctx->teedev);
+ struct optee_msg_arg *msg_arg;
+- phys_addr_t msg_parg;
+
+- shm = get_msg_arg(ctx, 0, &msg_arg, &msg_parg);
++ shm = get_msg_arg(ctx, 0, &msg_arg);
+ if (IS_ERR(shm))
+ return PTR_ERR(shm);
+
+ msg_arg->cmd = OPTEE_MSG_CMD_CLOSE_SESSION;
+ msg_arg->session = session;
+- optee_do_call_with_arg(ctx, msg_parg);
++ optee->ops->do_call_with_arg(ctx, shm);
+
+ tee_shm_free(shm);
+
+@@ -323,10 +319,10 @@ int optee_close_session(struct tee_context *ctx, u32 session)
+ int optee_invoke_func(struct tee_context *ctx, struct tee_ioctl_invoke_arg *arg,
+ struct tee_param *param)
+ {
++ struct optee *optee = tee_get_drvdata(ctx->teedev);
+ struct optee_context_data *ctxdata = ctx->data;
+ struct tee_shm *shm;
+ struct optee_msg_arg *msg_arg;
+- phys_addr_t msg_parg;
+ struct optee_session *sess;
+ int rc;
+
+@@ -337,7 +333,7 @@ int optee_invoke_func(struct tee_context *ctx, struct tee_ioctl_invoke_arg *arg,
+ if (!sess)
+ return -EINVAL;
+
+- shm = get_msg_arg(ctx, arg->num_params, &msg_arg, &msg_parg);
++ shm = get_msg_arg(ctx, arg->num_params, &msg_arg);
+ if (IS_ERR(shm))
+ return PTR_ERR(shm);
+ msg_arg->cmd = OPTEE_MSG_CMD_INVOKE_COMMAND;
+@@ -345,16 +341,18 @@ int optee_invoke_func(struct tee_context *ctx, struct tee_ioctl_invoke_arg *arg,
+ msg_arg->session = arg->session;
+ msg_arg->cancel_id = arg->cancel_id;
+
+- rc = optee_to_msg_param(msg_arg->params, arg->num_params, param);
++ rc = optee->ops->to_msg_param(optee, msg_arg->params, arg->num_params,
++ param);
+ if (rc)
+ goto out;
+
+- if (optee_do_call_with_arg(ctx, msg_parg)) {
++ if (optee->ops->do_call_with_arg(ctx, shm)) {
+ msg_arg->ret = TEEC_ERROR_COMMUNICATION;
+ msg_arg->ret_origin = TEEC_ORIGIN_COMMS;
+ }
+
+- if (optee_from_msg_param(param, arg->num_params, msg_arg->params)) {
++ if (optee->ops->from_msg_param(optee, param, arg->num_params,
++ msg_arg->params)) {
+ msg_arg->ret = TEEC_ERROR_COMMUNICATION;
+ msg_arg->ret_origin = TEEC_ORIGIN_COMMS;
+ }
+@@ -368,10 +366,10 @@ int optee_invoke_func(struct tee_context *ctx, struct tee_ioctl_invoke_arg *arg,
+
+ int optee_cancel_req(struct tee_context *ctx, u32 cancel_id, u32 session)
+ {
++ struct optee *optee = tee_get_drvdata(ctx->teedev);
+ struct optee_context_data *ctxdata = ctx->data;
+ struct tee_shm *shm;
+ struct optee_msg_arg *msg_arg;
+- phys_addr_t msg_parg;
+ struct optee_session *sess;
+
+ /* Check that the session is valid */
+@@ -381,14 +379,14 @@ int optee_cancel_req(struct tee_context *ctx, u32 cancel_id, u32 session)
+ if (!sess)
+ return -EINVAL;
+
+- shm = get_msg_arg(ctx, 0, &msg_arg, &msg_parg);
++ shm = get_msg_arg(ctx, 0, &msg_arg);
+ if (IS_ERR(shm))
+ return PTR_ERR(shm);
+
+ msg_arg->cmd = OPTEE_MSG_CMD_CANCEL;
+ msg_arg->session = session;
+ msg_arg->cancel_id = cancel_id;
+- optee_do_call_with_arg(ctx, msg_parg);
++ optee->ops->do_call_with_arg(ctx, shm);
+
+ tee_shm_free(shm);
+ return 0;
+@@ -587,10 +585,10 @@ int optee_shm_register(struct tee_context *ctx, struct tee_shm *shm,
+ struct page **pages, size_t num_pages,
+ unsigned long start)
+ {
+- struct tee_shm *shm_arg = NULL;
++ struct optee *optee = tee_get_drvdata(ctx->teedev);
+ struct optee_msg_arg *msg_arg;
++ struct tee_shm *shm_arg;
+ u64 *pages_list;
+- phys_addr_t msg_parg;
+ int rc;
+
+ if (!num_pages)
+@@ -604,7 +602,7 @@ int optee_shm_register(struct tee_context *ctx, struct tee_shm *shm,
+ if (!pages_list)
+ return -ENOMEM;
+
+- shm_arg = get_msg_arg(ctx, 1, &msg_arg, &msg_parg);
++ shm_arg = get_msg_arg(ctx, 1, &msg_arg);
+ if (IS_ERR(shm_arg)) {
+ rc = PTR_ERR(shm_arg);
+ goto out;
+@@ -625,7 +623,7 @@ int optee_shm_register(struct tee_context *ctx, struct tee_shm *shm,
+ msg_arg->params->u.tmem.buf_ptr = virt_to_phys(pages_list) |
+ (tee_shm_get_page_offset(shm) & (OPTEE_MSG_NONCONTIG_PAGE_SIZE - 1));
+
+- if (optee_do_call_with_arg(ctx, msg_parg) ||
++ if (optee->ops->do_call_with_arg(ctx, shm) ||
+ msg_arg->ret != TEEC_SUCCESS)
+ rc = -EINVAL;
+
+@@ -637,12 +635,12 @@ int optee_shm_register(struct tee_context *ctx, struct tee_shm *shm,
+
+ int optee_shm_unregister(struct tee_context *ctx, struct tee_shm *shm)
+ {
+- struct tee_shm *shm_arg;
++ struct optee *optee = tee_get_drvdata(ctx->teedev);
+ struct optee_msg_arg *msg_arg;
+- phys_addr_t msg_parg;
++ struct tee_shm *shm_arg;
+ int rc = 0;
+
+- shm_arg = get_msg_arg(ctx, 1, &msg_arg, &msg_parg);
++ shm_arg = get_msg_arg(ctx, 1, &msg_arg);
+ if (IS_ERR(shm_arg))
+ return PTR_ERR(shm_arg);
+
+@@ -651,7 +649,7 @@ int optee_shm_unregister(struct tee_context *ctx, struct tee_shm *shm)
+ msg_arg->params[0].attr = OPTEE_MSG_ATTR_TYPE_RMEM_INPUT;
+ msg_arg->params[0].u.rmem.shm_ref = (unsigned long)shm;
+
+- if (optee_do_call_with_arg(ctx, msg_parg) ||
++ if (optee->ops->do_call_with_arg(ctx, shm) ||
+ msg_arg->ret != TEEC_SUCCESS)
+ rc = -EINVAL;
+ tee_shm_free(shm_arg);
+diff --git a/drivers/tee/optee/core.c b/drivers/tee/optee/core.c
+index e39c6d290d83..ab602bb8e14a 100644
+--- a/drivers/tee/optee/core.c
++++ b/drivers/tee/optee/core.c
+@@ -1,6 +1,6 @@
+ // SPDX-License-Identifier: GPL-2.0-only
+ /*
+- * Copyright (c) 2015, Linaro Limited
++ * Copyright (c) 2015-2021, Linaro Limited
+ */
+
+ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+@@ -26,21 +26,87 @@
+
+ #define OPTEE_SHM_NUM_PRIV_PAGES CONFIG_OPTEE_SHM_NUM_PRIV_PAGES
+
++static void from_msg_param_value(struct tee_param *p, u32 attr,
++ const struct optee_msg_param *mp)
++{
++ p->attr = TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT +
++ attr - OPTEE_MSG_ATTR_TYPE_VALUE_INPUT;
++ p->u.value.a = mp->u.value.a;
++ p->u.value.b = mp->u.value.b;
++ p->u.value.c = mp->u.value.c;
++}
++
++static int from_msg_param_tmp_mem(struct tee_param *p, u32 attr,
++ const struct optee_msg_param *mp)
++{
++ struct tee_shm *shm;
++ phys_addr_t pa;
++ int rc;
++
++ p->attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT +
++ attr - OPTEE_MSG_ATTR_TYPE_TMEM_INPUT;
++ p->u.memref.size = mp->u.tmem.size;
++ shm = (struct tee_shm *)(unsigned long)mp->u.tmem.shm_ref;
++ if (!shm) {
++ p->u.memref.shm_offs = 0;
++ p->u.memref.shm = NULL;
++ return 0;
++ }
++
++ rc = tee_shm_get_pa(shm, 0, &pa);
++ if (rc)
++ return rc;
++
++ p->u.memref.shm_offs = mp->u.tmem.buf_ptr - pa;
++ p->u.memref.shm = shm;
++
++ /* Check that the memref is covered by the shm object */
++ if (p->u.memref.size) {
++ size_t o = p->u.memref.shm_offs +
++ p->u.memref.size - 1;
++
++ rc = tee_shm_get_pa(shm, o, NULL);
++ if (rc)
++ return rc;
++ }
++
++ return 0;
++}
++
++static void from_msg_param_reg_mem(struct tee_param *p, u32 attr,
++ const struct optee_msg_param *mp)
++{
++ struct tee_shm *shm;
++
++ p->attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT +
++ attr - OPTEE_MSG_ATTR_TYPE_RMEM_INPUT;
++ p->u.memref.size = mp->u.rmem.size;
++ shm = (struct tee_shm *)(unsigned long)mp->u.rmem.shm_ref;
++
++ if (shm) {
++ p->u.memref.shm_offs = mp->u.rmem.offs;
++ p->u.memref.shm = shm;
++ } else {
++ p->u.memref.shm_offs = 0;
++ p->u.memref.shm = NULL;
++ }
++}
++
+ /**
+ * optee_from_msg_param() - convert from OPTEE_MSG parameters to
+ * struct tee_param
++ * @optee: main service struct
+ * @params: subsystem internal parameter representation
+ * @num_params: number of elements in the parameter arrays
+ * @msg_params: OPTEE_MSG parameters
+ * Returns 0 on success or <0 on failure
+ */
+-int optee_from_msg_param(struct tee_param *params, size_t num_params,
+- const struct optee_msg_param *msg_params)
++static int optee_from_msg_param(struct optee *optee, struct tee_param *params,
++ size_t num_params,
++ const struct optee_msg_param *msg_params)
+ {
+ int rc;
+ size_t n;
+- struct tee_shm *shm;
+- phys_addr_t pa;
+
+ for (n = 0; n < num_params; n++) {
+ struct tee_param *p = params + n;
+@@ -55,48 +121,19 @@ int optee_from_msg_param(struct tee_param *params, size_t num_params,
+ case OPTEE_MSG_ATTR_TYPE_VALUE_INPUT:
+ case OPTEE_MSG_ATTR_TYPE_VALUE_OUTPUT:
+ case OPTEE_MSG_ATTR_TYPE_VALUE_INOUT:
+- p->attr = TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT +
+- attr - OPTEE_MSG_ATTR_TYPE_VALUE_INPUT;
+- p->u.value.a = mp->u.value.a;
+- p->u.value.b = mp->u.value.b;
+- p->u.value.c = mp->u.value.c;
++ from_msg_param_value(p, attr, mp);
+ break;
+ case OPTEE_MSG_ATTR_TYPE_TMEM_INPUT:
+ case OPTEE_MSG_ATTR_TYPE_TMEM_OUTPUT:
+ case OPTEE_MSG_ATTR_TYPE_TMEM_INOUT:
+- p->attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT +
+- attr - OPTEE_MSG_ATTR_TYPE_TMEM_INPUT;
+- p->u.memref.size = mp->u.tmem.size;
+- shm = (struct tee_shm *)(unsigned long)
+- mp->u.tmem.shm_ref;
+- if (!shm) {
+- p->u.memref.shm_offs = 0;
+- p->u.memref.shm = NULL;
+- break;
+- }
+- rc = tee_shm_get_pa(shm, 0, &pa);
++ rc = from_msg_param_tmp_mem(p, attr, mp);
+ if (rc)
+ return rc;
+- p->u.memref.shm_offs = mp->u.tmem.buf_ptr - pa;
+- p->u.memref.shm = shm;
+ break;
+ case OPTEE_MSG_ATTR_TYPE_RMEM_INPUT:
+ case OPTEE_MSG_ATTR_TYPE_RMEM_OUTPUT:
+ case OPTEE_MSG_ATTR_TYPE_RMEM_INOUT:
+- p->attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT +
+- attr - OPTEE_MSG_ATTR_TYPE_RMEM_INPUT;
+- p->u.memref.size = mp->u.rmem.size;
+- shm = (struct tee_shm *)(unsigned long)
+- mp->u.rmem.shm_ref;
+-
+- if (!shm) {
+- p->u.memref.shm_offs = 0;
+- p->u.memref.shm = NULL;
+- break;
+- }
+- p->u.memref.shm_offs = mp->u.rmem.offs;
+- p->u.memref.shm = shm;
+-
++ from_msg_param_reg_mem(p, attr, mp);
+ break;
+
+ default:
+@@ -106,6 +143,16 @@ int optee_from_msg_param(struct tee_param *params, size_t num_params,
+ return 0;
+ }
+
++static void to_msg_param_value(struct optee_msg_param *mp,
++ const struct tee_param *p)
++{
++ mp->attr = OPTEE_MSG_ATTR_TYPE_VALUE_INPUT + p->attr -
++ TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT;
++ mp->u.value.a = p->u.value.a;
++ mp->u.value.b = p->u.value.b;
++ mp->u.value.c = p->u.value.c;
++}
++
+ static int to_msg_param_tmp_mem(struct optee_msg_param *mp,
+ const struct tee_param *p)
+ {
+@@ -148,13 +195,15 @@ static int to_msg_param_reg_mem(struct optee_msg_param *mp,
+
+ /**
+ * optee_to_msg_param() - convert from struct tee_params to OPTEE_MSG parameters
++ * @optee: main service struct
+ * @msg_params: OPTEE_MSG parameters
+ * @num_params: number of elements in the parameter arrays
+ * @params: subsystem itnernal parameter representation
+ * Returns 0 on success or <0 on failure
+ */
+-int optee_to_msg_param(struct optee_msg_param *msg_params, size_t num_params,
+- const struct tee_param *params)
++static int optee_to_msg_param(struct optee *optee,
++ struct optee_msg_param *msg_params,
++ size_t num_params, const struct tee_param *params)
+ {
+ int rc;
+ size_t n;
+@@ -171,11 +220,7 @@ int optee_to_msg_param(struct optee_msg_param *msg_params, size_t num_params,
+ case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT:
+ case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_OUTPUT:
+ case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INOUT:
+- mp->attr = OPTEE_MSG_ATTR_TYPE_VALUE_INPUT + p->attr -
+- TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT;
+- mp->u.value.a = p->u.value.a;
+- mp->u.value.b = p->u.value.b;
+- mp->u.value.c = p->u.value.c;
++ to_msg_param_value(mp, p);
+ break;
+ case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT:
+ case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT:
+@@ -301,7 +346,7 @@ static void optee_release_supp(struct tee_context *ctx)
+ optee_supp_release(&optee->supp);
+ }
+
+-static const struct tee_driver_ops optee_ops = {
++static const struct tee_driver_ops optee_clnt_ops = {
+ .get_version = optee_get_version,
+ .open = optee_open,
+ .release = optee_release,
+@@ -313,9 +358,9 @@ static const struct tee_driver_ops optee_ops = {
+ .shm_unregister = optee_shm_unregister,
+ };
+
+-static const struct tee_desc optee_desc = {
++static const struct tee_desc optee_clnt_desc = {
+ .name = DRIVER_NAME "-clnt",
+- .ops = &optee_ops,
++ .ops = &optee_clnt_ops,
+ .owner = THIS_MODULE,
+ };
+
+@@ -336,6 +381,12 @@ static const struct tee_desc optee_supp_desc = {
+ .flags = TEE_DESC_PRIVILEGED,
+ };
+
++static const struct optee_ops optee_ops = {
++ .do_call_with_arg = optee_do_call_with_arg,
++ .to_msg_param = optee_to_msg_param,
++ .from_msg_param = optee_from_msg_param,
++};
++
+ static bool optee_msg_api_uid_is_optee_api(optee_invoke_fn *invoke_fn)
+ {
+ struct arm_smccc_res res;
+@@ -637,10 +688,11 @@ static int optee_probe(struct platform_device *pdev)
+ goto err;
+ }
+
++ optee->ops = &optee_ops;
+ optee->invoke_fn = invoke_fn;
+ optee->sec_caps = sec_caps;
+
+- teedev = tee_device_alloc(&optee_desc, NULL, pool, optee);
++ teedev = tee_device_alloc(&optee_clnt_desc, NULL, pool, optee);
+ if (IS_ERR(teedev)) {
+ rc = PTR_ERR(teedev);
+ goto err;
+diff --git a/drivers/tee/optee/optee_private.h b/drivers/tee/optee/optee_private.h
+index 2b63b796645e..c5741e96e967 100644
+--- a/drivers/tee/optee/optee_private.h
++++ b/drivers/tee/optee/optee_private.h
+@@ -1,6 +1,6 @@
+ /* SPDX-License-Identifier: GPL-2.0-only */
+ /*
+- * Copyright (c) 2015, Linaro Limited
++ * Copyright (c) 2015-2021, Linaro Limited
+ */
+
+ #ifndef OPTEE_PRIVATE_H
+@@ -66,9 +66,34 @@ struct optee_supp {
+ struct completion reqs_c;
+ };
+
++struct optee;
++
++/**
++ * struct optee_ops - OP-TEE driver internal operations
++ * @do_call_with_arg: enters OP-TEE in secure world
++ * @to_msg_param: converts from struct tee_param to OPTEE_MSG parameters
++ * @from_msg_param: converts from OPTEE_MSG parameters to struct tee_param
++ *
++ * These OPs are only supposed to be used internally in the OP-TEE driver
++ * as a way of abstracting the different methogs of entering OP-TEE in
++ * secure world.
++ */
++struct optee_ops {
++ int (*do_call_with_arg)(struct tee_context *ctx,
++ struct tee_shm *shm_arg);
++ int (*to_msg_param)(struct optee *optee,
++ struct optee_msg_param *msg_params,
++ size_t num_params, const struct tee_param *params);
++ int (*from_msg_param)(struct optee *optee, struct tee_param *params,
++ size_t num_params,
++ const struct optee_msg_param *msg_params);
++};
++
+ /**
+ * struct optee - main service struct
+ * @supp_teedev: supplicant device
++ * @ops: internal callbacks for different ways to reach secure
++ * world
+ * @teedev: client device
+ * @invoke_fn: function to issue smc or hvc
+ * @call_queue: queue of threads waiting to call @invoke_fn
+@@ -86,6 +111,7 @@ struct optee_supp {
+ struct optee {
+ struct tee_device *supp_teedev;
+ struct tee_device *teedev;
++ const struct optee_ops *ops;
+ optee_invoke_fn *invoke_fn;
+ struct optee_call_queue call_queue;
+ struct optee_wait_queue wait_queue;
+@@ -148,7 +174,7 @@ int optee_supp_recv(struct tee_context *ctx, u32 *func, u32 *num_params,
+ int optee_supp_send(struct tee_context *ctx, u32 ret, u32 num_params,
+ struct tee_param *param);
+
+-u32 optee_do_call_with_arg(struct tee_context *ctx, phys_addr_t parg);
++int optee_do_call_with_arg(struct tee_context *ctx, struct tee_shm *arg);
+ int optee_open_session(struct tee_context *ctx,
+ struct tee_ioctl_open_session_arg *arg,
+ struct tee_param *param);
+@@ -171,11 +197,6 @@ int optee_shm_register_supp(struct tee_context *ctx, struct tee_shm *shm,
+ unsigned long start);
+ int optee_shm_unregister_supp(struct tee_context *ctx, struct tee_shm *shm);
+
+-int optee_from_msg_param(struct tee_param *params, size_t num_params,
+- const struct optee_msg_param *msg_params);
+-int optee_to_msg_param(struct optee_msg_param *msg_params, size_t num_params,
+- const struct tee_param *params);
+-
+ u64 *optee_allocate_pages_list(size_t num_entries);
+ void optee_free_pages_list(void *array, size_t num_entries);
+ void optee_fill_pages_list(u64 *dst, struct page **pages, int num_pages,
+diff --git a/drivers/tee/optee/rpc.c b/drivers/tee/optee/rpc.c
+index 1849180b0278..39562fb6841e 100644
+--- a/drivers/tee/optee/rpc.c
++++ b/drivers/tee/optee/rpc.c
+@@ -1,6 +1,6 @@
+ // SPDX-License-Identifier: GPL-2.0-only
+ /*
+- * Copyright (c) 2015-2016, Linaro Limited
++ * Copyright (c) 2015-2021, Linaro Limited
+ */
+
+ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+@@ -55,6 +55,7 @@ static void handle_rpc_func_cmd_get_time(struct optee_msg_arg *arg)
+ static void handle_rpc_func_cmd_i2c_transfer(struct tee_context *ctx,
+ struct optee_msg_arg *arg)
+ {
++ struct optee *optee = tee_get_drvdata(ctx->teedev);
+ struct tee_param *params;
+ struct i2c_adapter *adapter;
+ struct i2c_msg msg = { };
+@@ -79,7 +80,8 @@ static void handle_rpc_func_cmd_i2c_transfer(struct tee_context *ctx,
+ return;
+ }
+
+- if (optee_from_msg_param(params, arg->num_params, arg->params))
++ if (optee->ops->from_msg_param(optee, params, arg->num_params,
++ arg->params))
+ goto bad;
+
+ for (i = 0; i < arg->num_params; i++) {
+@@ -122,7 +124,8 @@ static void handle_rpc_func_cmd_i2c_transfer(struct tee_context *ctx,
+ arg->ret = TEEC_ERROR_COMMUNICATION;
+ } else {
+ params[3].u.value.a = msg.len;
+- if (optee_to_msg_param(arg->params, arg->num_params, params))
++ if (optee->ops->to_msg_param(optee, arg->params,
++ arg->num_params, params))
+ arg->ret = TEEC_ERROR_BAD_PARAMETERS;
+ else
+ arg->ret = TEEC_SUCCESS;
+@@ -234,7 +237,7 @@ static void handle_rpc_func_cmd_wait(struct optee_msg_arg *arg)
+ arg->ret = TEEC_ERROR_BAD_PARAMETERS;
+ }
+
+-static void handle_rpc_supp_cmd(struct tee_context *ctx,
++static void handle_rpc_supp_cmd(struct tee_context *ctx, struct optee *optee,
+ struct optee_msg_arg *arg)
+ {
+ struct tee_param *params;
+@@ -248,14 +251,16 @@ static void handle_rpc_supp_cmd(struct tee_context *ctx,
+ return;
+ }
+
+- if (optee_from_msg_param(params, arg->num_params, arg->params)) {
++ if (optee->ops->from_msg_param(optee, params, arg->num_params,
++ arg->params)) {
+ arg->ret = TEEC_ERROR_BAD_PARAMETERS;
+ goto out;
+ }
+
+ arg->ret = optee_supp_thrd_req(ctx, arg->cmd, arg->num_params, params);
+
+- if (optee_to_msg_param(arg->params, arg->num_params, params))
++ if (optee->ops->to_msg_param(optee, arg->params, arg->num_params,
++ params))
+ arg->ret = TEEC_ERROR_BAD_PARAMETERS;
+ out:
+ kfree(params);
+@@ -480,7 +485,7 @@ static void handle_rpc_func_cmd(struct tee_context *ctx, struct optee *optee,
+ handle_rpc_func_cmd_i2c_transfer(ctx, arg);
+ break;
+ default:
+- handle_rpc_supp_cmd(ctx, arg);
++ handle_rpc_supp_cmd(ctx, optee, arg);
+ }
+ }
+
+--
+2.29.2
+
diff --git a/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc0/0019-optee-add-a-FF-A-memory-pool.patch b/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc0/0019-optee-add-a-FF-A-memory-pool.patch
new file mode 100644
index 0000000..fc6ba04
--- /dev/null
+++ b/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc0/0019-optee-add-a-FF-A-memory-pool.patch
@@ -0,0 +1,131 @@
+From 69f802594252a0745ba4e798012a0fb6524b6267 Mon Sep 17 00:00:00 2001
+From: Jens Wiklander <jens.wiklander@linaro.org>
+Date: Thu, 25 Mar 2021 15:08:52 +0100
+Subject: [PATCH 11/14] optee: add a FF-A memory pool
+
+Adds a memory pool to be used when the driver uses FF-A [1] as transport
+layer.
+
+[1] https://developer.arm.com/documentation/den0077/latest
+Signed-off-by: Jens Wiklander <jens.wiklander@linaro.org>
+
+Upstream-Status: Pending [Not submitted to upstream yet]
+---
+ drivers/tee/optee/shm_pool.c | 65 +++++++++++++++++++++++++++++++++---
+ drivers/tee/optee/shm_pool.h | 1 +
+ 2 files changed, 61 insertions(+), 5 deletions(-)
+
+diff --git a/drivers/tee/optee/shm_pool.c b/drivers/tee/optee/shm_pool.c
+index d767eebf30bd..d2116cb39c8b 100644
+--- a/drivers/tee/optee/shm_pool.c
++++ b/drivers/tee/optee/shm_pool.c
+@@ -12,8 +12,14 @@
+ #include "optee_smc.h"
+ #include "shm_pool.h"
+
+-static int pool_op_alloc(struct tee_shm_pool_mgr *poolm,
+- struct tee_shm *shm, size_t size)
++static int
++pool_op_alloc_helper(struct tee_shm_pool_mgr *poolm,
++ struct tee_shm *shm, size_t size,
++ int (*shm_register)(struct tee_context *ctx,
++ struct tee_shm *shm,
++ struct page **pages,
++ size_t num_pages,
++ unsigned long start))
+ {
+ unsigned int order = get_order(size);
+ struct page *page;
+@@ -27,7 +33,7 @@ static int pool_op_alloc(struct tee_shm_pool_mgr *poolm,
+ shm->paddr = page_to_phys(page);
+ shm->size = PAGE_SIZE << order;
+
+- if (shm->flags & TEE_SHM_DMA_BUF) {
++ if (shm_register) {
+ unsigned int nr_pages = 1 << order, i;
+ struct page **pages;
+
+@@ -41,14 +47,23 @@ static int pool_op_alloc(struct tee_shm_pool_mgr *poolm,
+ }
+
+ shm->flags |= TEE_SHM_REGISTER;
+- rc = optee_shm_register(shm->ctx, shm, pages, nr_pages,
+- (unsigned long)shm->kaddr);
++ rc = shm_register(shm->ctx, shm, pages, nr_pages,
++ (unsigned long)shm->kaddr);
+ kfree(pages);
+ }
+
+ return rc;
+ }
+
++static int pool_op_alloc(struct tee_shm_pool_mgr *poolm,
++ struct tee_shm *shm, size_t size)
++{
++ if (!(shm->flags & TEE_SHM_DMA_BUF))
++ return pool_op_alloc_helper(poolm, shm, size, NULL);
++
++ return pool_op_alloc_helper(poolm, shm, size, optee_shm_register);
++}
++
+ static void pool_op_free(struct tee_shm_pool_mgr *poolm,
+ struct tee_shm *shm)
+ {
+@@ -87,3 +102,43 @@ struct tee_shm_pool_mgr *optee_shm_pool_alloc_pages(void)
+
+ return mgr;
+ }
++
++#ifdef CONFIG_ARM_FFA_TRANSPORT
++static int pool_ffa_op_alloc(struct tee_shm_pool_mgr *poolm,
++ struct tee_shm *shm, size_t size)
++{
++ return pool_op_alloc_helper(poolm, shm, size, optee_ffa_shm_register);
++}
++
++static void pool_ffa_op_free(struct tee_shm_pool_mgr *poolm,
++ struct tee_shm *shm)
++{
++ optee_ffa_shm_unregister(shm->ctx, shm);
++ free_pages((unsigned long)shm->kaddr, get_order(shm->size));
++ shm->kaddr = NULL;
++}
++
++static const struct tee_shm_pool_mgr_ops pool_ffa_ops = {
++ .alloc = pool_ffa_op_alloc,
++ .free = pool_ffa_op_free,
++ .destroy_poolmgr = pool_op_destroy_poolmgr,
++};
++
++/**
++ * optee_ffa_shm_pool_alloc_pages() - create page-based allocator pool
++ *
++ * This pool is used with OP-TEE over FF-A. In this case command buffers
++ * and such are allocated from kernel's own memory.
++ */
++struct tee_shm_pool_mgr *optee_ffa_shm_pool_alloc_pages(void)
++{
++ struct tee_shm_pool_mgr *mgr = kzalloc(sizeof(*mgr), GFP_KERNEL);
++
++ if (!mgr)
++ return ERR_PTR(-ENOMEM);
++
++ mgr->ops = &pool_ffa_ops;
++
++ return mgr;
++}
++#endif /*CONFIG_ARM_FFA_TRANSPORT*/
+diff --git a/drivers/tee/optee/shm_pool.h b/drivers/tee/optee/shm_pool.h
+index 28109d991c4b..34c5fd74a3ff 100644
+--- a/drivers/tee/optee/shm_pool.h
++++ b/drivers/tee/optee/shm_pool.h
+@@ -10,5 +10,6 @@
+ #include <linux/tee_drv.h>
+
+ struct tee_shm_pool_mgr *optee_shm_pool_alloc_pages(void);
++struct tee_shm_pool_mgr *optee_ffa_shm_pool_alloc_pages(void);
+
+ #endif
+--
+2.29.2
+
diff --git a/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc0/0020-optee-add-FF-A-support.patch b/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc0/0020-optee-add-FF-A-support.patch
new file mode 100644
index 0000000..6c4e4e6
--- /dev/null
+++ b/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc0/0020-optee-add-FF-A-support.patch
@@ -0,0 +1,1269 @@
+From c7fedcabea2762c23a9e22cd5f5e4bb0de1f5081 Mon Sep 17 00:00:00 2001
+From: Jens Wiklander <jens.wiklander@linaro.org>
+Date: Thu, 25 Mar 2021 15:08:53 +0100
+Subject: [PATCH 12/14] optee: add FF-A support
+
+Adds support for using FF-A [1] as transport to the OP-TEE driver.
+
+Introduces struct optee_msg_param_fmem which carries all information
+needed when OP-TEE is calling FFA_MEM_RETRIEVE_REQ to get the shared
+memory reference mapped by the hypervisor in S-EL2. Register usage is
+also updated to include the information needed.
+
+The FF-A part of this driver is enabled if CONFIG_ARM_FFA_TRANSPORT is
+enabled.
+
+[1] https://developer.arm.com/documentation/den0077/latest
+Signed-off-by: Jens Wiklander <jens.wiklander@linaro.org>
+
+Upstream-Status: Pending [Not submitted to upstream yet]
+---
+ drivers/tee/optee/call.c | 212 ++++++++++++-
+ drivers/tee/optee/core.c | 486 +++++++++++++++++++++++++++++-
+ drivers/tee/optee/optee_ffa.h | 153 ++++++++++
+ drivers/tee/optee/optee_msg.h | 27 +-
+ drivers/tee/optee/optee_private.h | 52 ++++
+ drivers/tee/optee/rpc.c | 118 ++++++++
+ 6 files changed, 1040 insertions(+), 8 deletions(-)
+ create mode 100644 drivers/tee/optee/optee_ffa.h
+
+diff --git a/drivers/tee/optee/call.c b/drivers/tee/optee/call.c
+index 1439ab896cd0..3d03a79dd246 100644
+--- a/drivers/tee/optee/call.c
++++ b/drivers/tee/optee/call.c
+@@ -3,15 +3,18 @@
+ * Copyright (c) 2015-2021, Linaro Limited
+ */
+ #include <linux/arm-smccc.h>
++#include <linux/arm_ffa.h>
+ #include <linux/device.h>
+ #include <linux/err.h>
+ #include <linux/errno.h>
+ #include <linux/mm.h>
+ #include <linux/sched.h>
++#include <linux/scatterlist.h>
+ #include <linux/slab.h>
+ #include <linux/tee_drv.h>
+ #include <linux/types.h>
+ #include <linux/uaccess.h>
++#include "optee_ffa.h"
+ #include "optee_private.h"
+ #include "optee_smc.h"
+
+@@ -180,11 +183,21 @@ int optee_do_call_with_arg(struct tee_context *ctx, struct tee_shm *arg)
+ static struct tee_shm *get_msg_arg(struct tee_context *ctx, size_t num_params,
+ struct optee_msg_arg **msg_arg)
+ {
++ struct optee *optee = tee_get_drvdata(ctx->teedev);
++ size_t sz = OPTEE_MSG_GET_ARG_SIZE(num_params);
+ struct tee_shm *shm;
+ struct optee_msg_arg *ma;
+
+- shm = tee_shm_alloc(ctx, OPTEE_MSG_GET_ARG_SIZE(num_params),
+- TEE_SHM_MAPPED);
++ /*
++ * rpc_arg_count is set to the number of allocated parameters in
++ * the RPC argument struct if a second MSG arg struct is expected.
++ * The second arg struct will then be used for RPC. So far only
++ * enabled when using FF-A as transport layer.
++ */
++ if (optee->rpc_arg_count)
++ sz += OPTEE_MSG_GET_ARG_SIZE(optee->rpc_arg_count);
++
++ shm = tee_shm_alloc(ctx, sz, TEE_SHM_MAPPED);
+ if (IS_ERR(shm))
+ return shm;
+
+@@ -671,3 +684,198 @@ int optee_shm_unregister_supp(struct tee_context *ctx, struct tee_shm *shm)
+ {
+ return 0;
+ }
++
++#ifdef CONFIG_ARM_FFA_TRANSPORT
++static int optee_ffa_yielding_call(struct tee_context *ctx,
++ struct ffa_send_direct_data *data,
++ struct optee_msg_arg *rpc_arg)
++{
++ struct optee *optee = tee_get_drvdata(ctx->teedev);
++ const struct ffa_dev_ops *ffa_ops = optee->ffa.ffa_ops;
++ struct ffa_device *ffa_dev = optee->ffa.ffa_dev;
++ struct optee_call_waiter w;
++ u32 cmd = data->data0;
++ u32 w4 = data->data1;
++ u32 w5 = data->data2;
++ u32 w6 = data->data3;
++ int rc;
++
++ /* Initialize waiter */
++ optee_cq_wait_init(&optee->call_queue, &w);
++ while (true) {
++ rc = ffa_ops->sync_send_receive(ffa_dev, data);
++ if (rc)
++ goto done;
++
++ switch ((int)data->data0) {
++ case TEEC_SUCCESS:
++ break;
++ case TEEC_ERROR_BUSY:
++ if (cmd == OPTEE_FFA_YIELDING_CALL_RESUME) {
++ rc = -EIO;
++ goto done;
++ }
++
++ /*
++ * Out of threads in secure world, wait for a thread
++ * become available.
++ */
++ optee_cq_wait_for_completion(&optee->call_queue, &w);
++ data->data0 = cmd;
++ data->data1 = w4;
++ data->data2 = w5;
++ data->data3 = w6;
++ continue;
++ default:
++ rc = -EIO;
++ goto done;
++ }
++
++ if (data->data1 == OPTEE_FFA_YIELDING_CALL_RETURN_DONE)
++ goto done;
++
++ /*
++ * OP-TEE has returned with a RPC request.
++ *
++ * Note that data->data4 (passed in register w7) is already
++ * filled in by ffa_ops->sync_send_receive() returning
++ * above.
++ */
++ cond_resched();
++ optee_handle_ffa_rpc(ctx, data->data1, rpc_arg);
++ cmd = OPTEE_FFA_YIELDING_CALL_RESUME;
++ data->data0 = cmd;
++ data->data1 = 0;
++ data->data2 = 0;
++ data->data3 = 0;
++ }
++done:
++ /*
++ * We're done with our thread in secure world, if there's any
++ * thread waiters wake up one.
++ */
++ optee_cq_wait_final(&optee->call_queue, &w);
++
++ return rc;
++}
++
++/**
++ * optee_ffa_do_call_with_arg() - Do a FF-A call to enter OP-TEE in secure world
++ * @ctx: calling context
++ * @shm: shared memory holding the message to pass to secure world
++ *
++ * Does a FF-A call to OP-TEE in secure world and handles eventual resulting
++ * Remote Procedure Calls (RPC) from OP-TEE.
++ *
++ * Returns return code from FF-A, 0 is OK
++ */
++
++int optee_ffa_do_call_with_arg(struct tee_context *ctx, struct tee_shm *shm)
++{
++ struct ffa_send_direct_data data = {
++ .data0 = OPTEE_FFA_YIELDING_CALL_WITH_ARG,
++ .data1 = (u32)shm->sec_world_id,
++ .data2 = (u32)(shm->sec_world_id >> 32),
++ .data3 = shm->offset,
++ };
++ struct optee_msg_arg *arg = tee_shm_get_va(shm, 0);
++ unsigned int rpc_arg_offs = OPTEE_MSG_GET_ARG_SIZE(arg->num_params);
++ struct optee_msg_arg *rpc_arg = tee_shm_get_va(shm, rpc_arg_offs);
++
++ return optee_ffa_yielding_call(ctx, &data, rpc_arg);
++}
++
++int optee_ffa_shm_register(struct tee_context *ctx, struct tee_shm *shm,
++ struct page **pages, size_t num_pages,
++ unsigned long start)
++{
++ struct optee *optee = tee_get_drvdata(ctx->teedev);
++ const struct ffa_dev_ops *ffa_ops = optee->ffa.ffa_ops;
++ struct ffa_device *ffa_dev = optee->ffa.ffa_dev;
++ struct ffa_mem_region_attributes mem_attr = {
++ .receiver = ffa_dev->vm_id,
++ .attrs = FFA_MEM_RW,
++ };
++ struct ffa_mem_ops_args args = {
++ .use_txbuf = true,
++ .attrs = &mem_attr,
++ .nattrs = 1,
++ };
++ struct sg_table sgt;
++ int rc;
++
++ rc = check_mem_type(start, num_pages);
++ if (rc)
++ return rc;
++
++ rc = sg_alloc_table_from_pages(&sgt, pages, num_pages, 0,
++ num_pages * PAGE_SIZE, GFP_KERNEL);
++ if (rc)
++ return rc;
++ args.sg = sgt.sgl;
++ rc = ffa_ops->memory_share(ffa_dev, &args);
++ sg_free_table(&sgt);
++ if (rc)
++ return rc;
++
++ rc = optee_shm_add_ffa_handle(optee, shm, args.g_handle);
++ if (rc) {
++ ffa_ops->memory_reclaim(args.g_handle, 0);
++ return rc;
++ }
++
++ shm->sec_world_id = args.g_handle;
++
++ return 0;
++}
++
++int optee_ffa_shm_unregister(struct tee_context *ctx, struct tee_shm *shm)
++{
++ struct optee *optee = tee_get_drvdata(ctx->teedev);
++ const struct ffa_dev_ops *ffa_ops = optee->ffa.ffa_ops;
++ struct ffa_device *ffa_dev = optee->ffa.ffa_dev;
++ u64 global_handle = shm->sec_world_id;
++ struct ffa_send_direct_data data = {
++ .data0 = OPTEE_FFA_UNREGISTER_SHM,
++ .data1 = (u32)global_handle,
++ .data2 = (u32)(global_handle >> 32)
++ };
++ int rc;
++
++ optee_shm_rem_ffa_handle(optee, global_handle);
++ shm->sec_world_id = 0;
++
++ rc = ffa_ops->sync_send_receive(ffa_dev, &data);
++ if (rc)
++ pr_err("Unregister SHM id 0x%llx rc %d\n", global_handle, rc);
++
++ rc = ffa_ops->memory_reclaim(global_handle, 0);
++ if (rc)
++ pr_err("mem_reclain: 0x%llx %d", global_handle, rc);
++
++ return rc;
++}
++
++int optee_ffa_shm_unregister_supp(struct tee_context *ctx, struct tee_shm *shm)
++{
++ struct optee *optee = tee_get_drvdata(ctx->teedev);
++ const struct ffa_dev_ops *ffa_ops = optee->ffa.ffa_ops;
++ u64 global_handle = shm->sec_world_id;
++ int rc;
++
++ /*
++ * We're skipping the OPTEE_FFA_YIELDING_CALL_UNREGISTER_SHM call
++ * since this is OP-TEE freeing via RPC so it has already retired
++ * this ID.
++ */
++
++ optee_shm_rem_ffa_handle(optee, global_handle);
++ rc = ffa_ops->memory_reclaim(global_handle, 0);
++ if (rc)
++ pr_err("mem_reclain: 0x%llx %d", global_handle, rc);
++
++ shm->sec_world_id = 0;
++
++ return rc;
++}
++#endif /*CONFIG_ARM_FFA_TRANSPORT*/
+diff --git a/drivers/tee/optee/core.c b/drivers/tee/optee/core.c
+index ab602bb8e14a..b9719c60dc48 100644
+--- a/drivers/tee/optee/core.c
++++ b/drivers/tee/optee/core.c
+@@ -6,6 +6,7 @@
+ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+ #include <linux/arm-smccc.h>
++#include <linux/arm_ffa.h>
+ #include <linux/errno.h>
+ #include <linux/io.h>
+ #include <linux/module.h>
+@@ -20,6 +21,7 @@
+ #include <linux/workqueue.h>
+ #include "optee_private.h"
+ #include "optee_smc.h"
++#include "optee_ffa.h"
+ #include "shm_pool.h"
+
+ #define DRIVER_NAME "optee"
+@@ -299,10 +301,9 @@ static int optee_open(struct tee_context *ctx)
+ mutex_init(&ctxdata->mutex);
+ INIT_LIST_HEAD(&ctxdata->sess_list);
+
+- if (optee->sec_caps & OPTEE_SMC_SEC_CAP_MEMREF_NULL)
+- ctx->cap_memref_null = true;
+- else
+- ctx->cap_memref_null = false;
++ ctx->cap_memref_null = optee_is_ffa_based(optee) ||
++ (optee->sec_caps &
++ OPTEE_SMC_SEC_CAP_MEMREF_NULL);
+
+ ctx->data = ctxdata;
+ return 0;
+@@ -567,6 +568,472 @@ optee_config_shm_memremap(optee_invoke_fn *invoke_fn, void **memremaped_shm)
+ return rc;
+ }
+
++#ifdef CONFIG_ARM_FFA_TRANSPORT
++static void optee_ffa_get_version(struct tee_device *teedev,
++ struct tee_ioctl_version_data *vers)
++{
++ struct tee_ioctl_version_data v = {
++ .impl_id = TEE_IMPL_ID_OPTEE,
++ .impl_caps = TEE_OPTEE_CAP_TZ,
++ .gen_caps = TEE_GEN_CAP_GP | TEE_GEN_CAP_REG_MEM |
++ TEE_GEN_CAP_MEMREF_NULL,
++ };
++
++ *vers = v;
++}
++
++struct shm_rhash {
++ struct tee_shm *shm;
++ u64 global_id;
++ struct rhash_head linkage;
++};
++
++static void rh_free_fn(void *ptr, void *arg)
++{
++ kfree(ptr);
++}
++
++static const struct rhashtable_params shm_rhash_params = {
++ .head_offset = offsetof(struct shm_rhash, linkage),
++ .key_len = sizeof(u64),
++ .key_offset = offsetof(struct shm_rhash, global_id),
++ .automatic_shrinking = true,
++};
++
++struct tee_shm *optee_shm_from_ffa_handle(struct optee *optee, u64 global_id)
++{
++ struct tee_shm *shm = NULL;
++ struct shm_rhash *r;
++
++ mutex_lock(&optee->ffa.mutex);
++ r = rhashtable_lookup_fast(&optee->ffa.global_ids, &global_id,
++ shm_rhash_params);
++ if (r)
++ shm = r->shm;
++ mutex_unlock(&optee->ffa.mutex);
++
++ return shm;
++}
++
++int optee_shm_add_ffa_handle(struct optee *optee, struct tee_shm *shm,
++ u64 global_id)
++{
++ struct shm_rhash *r;
++ int rc;
++
++ r = kmalloc(sizeof(*r), GFP_KERNEL);
++ if (!r)
++ return -ENOMEM;
++ r->shm = shm;
++ r->global_id = global_id;
++
++ mutex_lock(&optee->ffa.mutex);
++ rc = rhashtable_lookup_insert_fast(&optee->ffa.global_ids, &r->linkage,
++ shm_rhash_params);
++ mutex_unlock(&optee->ffa.mutex);
++
++ if (rc)
++ kfree(r);
++
++ return rc;
++}
++
++int optee_shm_rem_ffa_handle(struct optee *optee, u64 global_id)
++{
++ struct shm_rhash *r;
++ int rc = -ENOENT;
++
++ mutex_lock(&optee->ffa.mutex);
++ r = rhashtable_lookup_fast(&optee->ffa.global_ids, &global_id,
++ shm_rhash_params);
++ if (r)
++ rc = rhashtable_remove_fast(&optee->ffa.global_ids,
++ &r->linkage, shm_rhash_params);
++ mutex_unlock(&optee->ffa.mutex);
++
++ if (!rc)
++ kfree(r);
++
++ return rc;
++}
++
++static void from_msg_param_ffa_mem(struct optee *optee, struct tee_param *p,
++ u32 attr, const struct optee_msg_param *mp)
++{
++ struct tee_shm *shm = NULL;
++ u64 offs_high = 0;
++ u64 offs_low = 0;
++
++ p->attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT +
++ attr - OPTEE_MSG_ATTR_TYPE_FMEM_INPUT;
++ p->u.memref.size = mp->u.fmem.size;
++
++ if (mp->u.fmem.global_id != OPTEE_MSG_FMEM_INVALID_GLOBAL_ID)
++ shm = optee_shm_from_ffa_handle(optee, mp->u.fmem.global_id);
++ p->u.memref.shm = shm;
++
++ if (shm) {
++ offs_low = mp->u.fmem.offs_low;
++ offs_high = mp->u.fmem.offs_high;
++ }
++ p->u.memref.shm_offs = offs_low | offs_high << 32;
++}
++
++/**
++ * optee_ffa_from_msg_param() - convert from OPTEE_MSG parameters to
++ * struct tee_param
++ * @optee: main service struct
++ * @params: subsystem internal parameter representation
++ * @num_params: number of elements in the parameter arrays
++ * @msg_params: OPTEE_MSG parameters
++ *
++ * Returns 0 on success or <0 on failure
++ */
++static int optee_ffa_from_msg_param(struct optee *optee,
++ struct tee_param *params, size_t num_params,
++ const struct optee_msg_param *msg_params)
++{
++ size_t n;
++
++ for (n = 0; n < num_params; n++) {
++ struct tee_param *p = params + n;
++ const struct optee_msg_param *mp = msg_params + n;
++ u32 attr = mp->attr & OPTEE_MSG_ATTR_TYPE_MASK;
++
++ switch (attr) {
++ case OPTEE_MSG_ATTR_TYPE_NONE:
++ p->attr = TEE_IOCTL_PARAM_ATTR_TYPE_NONE;
++ memset(&p->u, 0, sizeof(p->u));
++ break;
++ case OPTEE_MSG_ATTR_TYPE_VALUE_INPUT:
++ case OPTEE_MSG_ATTR_TYPE_VALUE_OUTPUT:
++ case OPTEE_MSG_ATTR_TYPE_VALUE_INOUT:
++ from_msg_param_value(p, attr, mp);
++ break;
++ case OPTEE_MSG_ATTR_TYPE_FMEM_INPUT:
++ case OPTEE_MSG_ATTR_TYPE_FMEM_OUTPUT:
++ case OPTEE_MSG_ATTR_TYPE_FMEM_INOUT:
++ from_msg_param_ffa_mem(optee, p, attr, mp);
++ break;
++ default:
++ return -EINVAL;
++ }
++ }
++
++ return 0;
++}
++
++static int to_msg_param_ffa_mem(struct optee_msg_param *mp,
++ const struct tee_param *p)
++{
++ struct tee_shm *shm = p->u.memref.shm;
++
++ mp->attr = OPTEE_MSG_ATTR_TYPE_FMEM_INPUT + p->attr -
++ TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT;
++
++ if (shm) {
++ u64 shm_offs = p->u.memref.shm_offs;
++
++ mp->u.fmem.internal_offs = shm->offset;
++
++ mp->u.fmem.offs_low = shm_offs;
++ mp->u.fmem.offs_high = shm_offs >> 32;
++ /* Check that the entire offset could be stored. */
++ if (mp->u.fmem.offs_high != shm_offs >> 32)
++ return -EINVAL;
++
++ mp->u.fmem.global_id = shm->sec_world_id;
++ } else {
++ memset(&mp->u, 0, sizeof(mp->u));
++ mp->u.fmem.global_id = OPTEE_MSG_FMEM_INVALID_GLOBAL_ID;
++ }
++ mp->u.fmem.size = p->u.memref.size;
++
++ return 0;
++}
++
++/**
++ * optee_ffa_to_msg_param() - convert from struct tee_params to OPTEE_MSG
++ * parameters
++ * @optee: main service struct
++ * @msg_params: OPTEE_MSG parameters
++ * @num_params: number of elements in the parameter arrays
++ * @params: subsystem itnernal parameter representation
++ * Returns 0 on success or <0 on failure
++ */
++static int optee_ffa_to_msg_param(struct optee *optee,
++ struct optee_msg_param *msg_params,
++ size_t num_params,
++ const struct tee_param *params)
++{
++ size_t n;
++
++ for (n = 0; n < num_params; n++) {
++ const struct tee_param *p = params + n;
++ struct optee_msg_param *mp = msg_params + n;
++
++ switch (p->attr) {
++ case TEE_IOCTL_PARAM_ATTR_TYPE_NONE:
++ mp->attr = TEE_IOCTL_PARAM_ATTR_TYPE_NONE;
++ memset(&mp->u, 0, sizeof(mp->u));
++ break;
++ case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT:
++ case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_OUTPUT:
++ case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INOUT:
++ to_msg_param_value(mp, p);
++ break;
++ case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT:
++ case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT:
++ case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INOUT:
++ if (to_msg_param_ffa_mem(mp, p))
++ return -EINVAL;
++ break;
++ default:
++ return -EINVAL;
++ }
++ }
++
++ return 0;
++}
++
++static bool optee_ffa_api_is_compatbile(struct ffa_device *ffa_dev,
++ const struct ffa_dev_ops *ops)
++{
++ struct ffa_send_direct_data data = { OPTEE_FFA_GET_API_VERSION };
++ int rc;
++
++ ops->mode_32bit_set(ffa_dev);
++
++ rc = ops->sync_send_receive(ffa_dev, &data);
++ if (rc) {
++ pr_err("Unexpected error %d\n", rc);
++ return false;
++ }
++ if (data.data0 != OPTEE_FFA_VERSION_MAJOR ||
++ data.data1 < OPTEE_FFA_VERSION_MINOR) {
++ pr_err("Incompatible OP-TEE API version %lu.%lu",
++ data.data0, data.data1);
++ return false;
++ }
++
++ data = (struct ffa_send_direct_data){ OPTEE_FFA_GET_OS_VERSION };
++ rc = ops->sync_send_receive(ffa_dev, &data);
++ if (rc) {
++ pr_err("Unexpected error %d\n", rc);
++ return false;
++ }
++ if (data.data2)
++ pr_info("revision %lu.%lu (%08lx)",
++ data.data0, data.data1, data.data2);
++ else
++ pr_info("revision %lu.%lu", data.data0, data.data1);
++
++ return true;
++}
++
++static bool optee_ffa_exchange_caps(struct ffa_device *ffa_dev,
++ const struct ffa_dev_ops *ops,
++ u32 *sec_caps, unsigned int *rpc_arg_count)
++{
++ struct ffa_send_direct_data data = { OPTEE_FFA_EXCHANGE_CAPABILITIES };
++ int rc;
++
++ rc = ops->sync_send_receive(ffa_dev, &data);
++ if (rc) {
++ pr_err("Unexpected error %d", rc);
++ return false;
++ }
++ if (data.data0) {
++ pr_err("Unexpected exchange error %lu", data.data0);
++ return false;
++ }
++
++ *sec_caps = 0;
++ *rpc_arg_count = (u8)data.data1;
++
++ return true;
++}
++
++static struct tee_shm_pool *optee_ffa_config_dyn_shm(void)
++{
++ struct tee_shm_pool_mgr *priv_mgr;
++ struct tee_shm_pool_mgr *dmabuf_mgr;
++ void *rc;
++
++ rc = optee_ffa_shm_pool_alloc_pages();
++ if (IS_ERR(rc))
++ return rc;
++ priv_mgr = rc;
++
++ rc = optee_ffa_shm_pool_alloc_pages();
++ if (IS_ERR(rc)) {
++ tee_shm_pool_mgr_destroy(priv_mgr);
++ return rc;
++ }
++ dmabuf_mgr = rc;
++
++ rc = tee_shm_pool_alloc(priv_mgr, dmabuf_mgr);
++ if (IS_ERR(rc)) {
++ tee_shm_pool_mgr_destroy(priv_mgr);
++ tee_shm_pool_mgr_destroy(dmabuf_mgr);
++ }
++
++ return rc;
++}
++
++static const struct tee_driver_ops optee_ffa_clnt_ops = {
++ .get_version = optee_ffa_get_version,
++ .open = optee_open,
++ .release = optee_release,
++ .open_session = optee_open_session,
++ .close_session = optee_close_session,
++ .invoke_func = optee_invoke_func,
++ .cancel_req = optee_cancel_req,
++ .shm_register = optee_ffa_shm_register,
++ .shm_unregister = optee_ffa_shm_unregister,
++};
++
++static const struct tee_desc optee_ffa_clnt_desc = {
++ .name = DRIVER_NAME "ffa-clnt",
++ .ops = &optee_ffa_clnt_ops,
++ .owner = THIS_MODULE,
++};
++
++static const struct tee_driver_ops optee_ffa_supp_ops = {
++ .get_version = optee_ffa_get_version,
++ .open = optee_open,
++ .release = optee_release_supp,
++ .supp_recv = optee_supp_recv,
++ .supp_send = optee_supp_send,
++ .shm_register = optee_ffa_shm_register, /* same as for clnt ops */
++ .shm_unregister = optee_ffa_shm_unregister_supp,
++};
++
++static const struct tee_desc optee_ffa_supp_desc = {
++ .name = DRIVER_NAME "ffa-supp",
++ .ops = &optee_ffa_supp_ops,
++ .owner = THIS_MODULE,
++ .flags = TEE_DESC_PRIVILEGED,
++};
++
++static const struct optee_ops optee_ffa_ops = {
++ .do_call_with_arg = optee_ffa_do_call_with_arg,
++ .to_msg_param = optee_ffa_to_msg_param,
++ .from_msg_param = optee_ffa_from_msg_param,
++};
++
++static void optee_ffa_remove(struct ffa_device *ffa_dev)
++{
++ (void)ffa_dev;
++}
++
++static int optee_ffa_probe(struct ffa_device *ffa_dev)
++{
++ const struct ffa_dev_ops *ffa_ops;
++ unsigned int rpc_arg_count;
++ struct tee_device *teedev;
++ struct optee *optee;
++ u32 sec_caps;
++ int rc;
++
++ ffa_ops = ffa_dev_ops_get(ffa_dev);
++ if (!ffa_ops) {
++ pr_warn("failed \"method\" init: ffa\n");
++ return -ENOENT;
++ }
++
++ if (!optee_ffa_api_is_compatbile(ffa_dev, ffa_ops))
++ return -EINVAL;
++
++ if (!optee_ffa_exchange_caps(ffa_dev, ffa_ops, &sec_caps,
++ &rpc_arg_count))
++ return -EINVAL;
++
++ optee = kzalloc(sizeof(*optee), GFP_KERNEL);
++ if (!optee) {
++ rc = -ENOMEM;
++ goto err;
++ }
++ optee->pool = optee_ffa_config_dyn_shm();
++ if (IS_ERR(optee->pool)) {
++ rc = PTR_ERR(optee->pool);
++ optee->pool = NULL;
++ goto err;
++ }
++
++ optee->ops = &optee_ffa_ops;
++ optee->ffa.ffa_dev = ffa_dev;
++ optee->ffa.ffa_ops = ffa_ops;
++ optee->sec_caps = sec_caps;
++ optee->rpc_arg_count = rpc_arg_count;
++
++ teedev = tee_device_alloc(&optee_ffa_clnt_desc, NULL, optee->pool,
++ optee);
++ if (IS_ERR(teedev)) {
++ rc = PTR_ERR(teedev);
++ goto err;
++ }
++ optee->teedev = teedev;
++
++ teedev = tee_device_alloc(&optee_ffa_supp_desc, NULL, optee->pool,
++ optee);
++ if (IS_ERR(teedev)) {
++ rc = PTR_ERR(teedev);
++ goto err;
++ }
++ optee->supp_teedev = teedev;
++
++ rc = tee_device_register(optee->teedev);
++ if (rc)
++ goto err;
++
++ rc = tee_device_register(optee->supp_teedev);
++ if (rc)
++ goto err;
++
++ rc = rhashtable_init(&optee->ffa.global_ids, &shm_rhash_params);
++ if (rc)
++ goto err;
++ mutex_init(&optee->ffa.mutex);
++ mutex_init(&optee->call_queue.mutex);
++ INIT_LIST_HEAD(&optee->call_queue.waiters);
++ optee_wait_queue_init(&optee->wait_queue);
++ optee_supp_init(&optee->supp);
++ ffa_dev_set_drvdata(ffa_dev, optee);
++
++ pr_info("initialized driver\n");
++ return 0;
++err:
++ /*
++ * tee_device_unregister() is safe to call even if the
++ * devices hasn't been registered with
++ * tee_device_register() yet.
++ */
++ tee_device_unregister(optee->supp_teedev);
++ tee_device_unregister(optee->teedev);
++ if (optee->pool)
++ tee_shm_pool_free(optee->pool);
++ kfree(optee);
++ return rc;
++}
++
++static const struct ffa_device_id optee_ffa_device_id[] = {
++ /* 486178e0-e7f8-11e3-bc5e0002a5d5c51b */
++ { UUID_INIT(0x486178e0, 0xe7f8, 0x11e3,
++ 0xbc, 0x5e, 0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b) },
++ {}
++};
++
++static struct ffa_driver optee_ffa_driver = {
++ .name = "optee",
++ .probe = optee_ffa_probe,
++ .remove = optee_ffa_remove,
++ .id_table = optee_ffa_device_id,
++};
++
++module_ffa_driver(optee_ffa_driver);
++#endif /*CONFIG_ARM_FFA_TRANSPORT*/
++
+ /* Simple wrapper functions to be able to use a function pointer */
+ static void optee_smccc_smc(unsigned long a0, unsigned long a1,
+ unsigned long a2, unsigned long a3,
+@@ -615,7 +1082,8 @@ static int optee_remove(struct platform_device *pdev)
+ * reference counters and also avoid wild pointers in secure world
+ * into the old shared memory range.
+ */
+- optee_disable_shm_cache(optee);
++ if (!optee_is_ffa_based(optee))
++ optee_disable_shm_cache(optee);
+
+ /*
+ * The two devices have to be unregistered before we can free the
+@@ -631,6 +1099,14 @@ static int optee_remove(struct platform_device *pdev)
+ optee_supp_uninit(&optee->supp);
+ mutex_destroy(&optee->call_queue.mutex);
+
++#ifdef CONFIG_ARM_FFA_TRANSPORT
++ if (optee->ffa.ffa_ops) {
++ mutex_destroy(&optee->ffa.mutex);
++ rhashtable_free_and_destroy(&optee->ffa.global_ids,
++ rh_free_fn, NULL);
++ }
++#endif /*CONFIG_ARM_FFA_TRANSPORT*/
++
+ kfree(optee);
+
+ return 0;
+diff --git a/drivers/tee/optee/optee_ffa.h b/drivers/tee/optee/optee_ffa.h
+new file mode 100644
+index 000000000000..ee3a03fc392c
+--- /dev/null
++++ b/drivers/tee/optee/optee_ffa.h
+@@ -0,0 +1,153 @@
++/* SPDX-License-Identifier: BSD-2-Clause */
++/*
++ * Copyright (c) 2019-2021, Linaro Limited
++ */
++
++/*
++ * This file is exported by OP-TEE and is kept in sync between secure world
++ * and normal world drivers. We're using ARM FF-A 1.0 specification.
++ */
++
++#ifndef __OPTEE_FFA_H
++#define __OPTEE_FFA_H
++
++#include <linux/arm_ffa.h>
++
++/*
++ * Normal world sends requests with FFA_MSG_SEND_DIRECT_REQ and
++ * responses are returned with FFA_MSG_SEND_DIRECT_RESP for normal
++ * messages.
++ *
++ * All requests with FFA_MSG_SEND_DIRECT_REQ and FFA_MSG_SEND_DIRECT_RESP
++ * are using the AArch32 SMC calling convention with register usage as
++ * defined in FF-A specification:
++ * w0: Function ID (0x8400006F or 0x84000070)
++ * w1: Source/Destination IDs
++ * w2: Reserved (MBZ)
++ * w3-w7: Implementation defined, free to be used below
++ */
++
++#define OPTEE_FFA_VERSION_MAJOR 1
++#define OPTEE_FFA_VERSION_MINOR 0
++
++#define OPTEE_FFA_BLOCKING_CALL(id) (id)
++#define OPTEE_FFA_YIELDING_CALL_BIT 31
++#define OPTEE_FFA_YIELDING_CALL(id) ((id) | BIT(OPTEE_FFA_YIELDING_CALL_BIT))
++
++/*
++ * Returns the API version implemented, currently follows the FF-A version.
++ * Call register usage:
++ * w3: Service ID, OPTEE_FFA_GET_API_VERSION
++ * w4-w7: Not used (MBZ)
++ *
++ * Return register usage:
++ * w3: OPTEE_FFA_VERSION_MAJOR
++ * w4: OPTEE_FFA_VERSION_MINOR
++ * w5-w7: Not used (MBZ)
++ */
++#define OPTEE_FFA_GET_API_VERSION OPTEE_FFA_BLOCKING_CALL(0)
++
++/*
++ * Returns the revision of OP-TEE.
++ *
++ * Used by non-secure world to figure out which version of the Trusted OS
++ * is installed. Note that the returned revision is the revision of the
++ * Trusted OS, not of the API.
++ *
++ * Call register usage:
++ * w3: Service ID, OPTEE_FFA_GET_OS_VERSION
++ * w4-w7: Unused (MBZ)
++ *
++ * Return register usage:
++ * w3: CFG_OPTEE_REVISION_MAJOR
++ * w4: CFG_OPTEE_REVISION_MINOR
++ * w5: TEE_IMPL_GIT_SHA1 (or zero if not supported)
++ */
++#define OPTEE_FFA_GET_OS_VERSION OPTEE_FFA_BLOCKING_CALL(1)
++
++/*
++ * Exchange capabilities between normal world and secure world.
++ *
++ * Currently there are no defined capabilities. When features are added new
++ * capabilities may be added.
++ *
++ * Call register usage:
++ * w3: Service ID, OPTEE_FFA_EXCHANGE_CAPABILITIES
++ * w4-w7: Note used (MBZ)
++ *
++ * Return register usage:
++ * w3: Error code, 0 on success
++ * w4: Bit[7:0]: Number of parameters needed for RPC to be supplied
++ * as the second MSG arg struct for
++ * OPTEE_FFA_YIELDING_CALL_WITH_ARG.
++ * Bit[31:8]: Reserved (MBZ)
++ * w5-w7: Note used (MBZ)
++ */
++#define OPTEE_FFA_EXCHANGE_CAPABILITIES OPTEE_FFA_BLOCKING_CALL(2)
++
++/*
++ * Unregister shared memory
++ *
++ * Call register usage:
++ * w3: Service ID, OPTEE_FFA_YIELDING_CALL_UNREGISTER_SHM
++ * w4: Shared memory handle, lower bits
++ * w5: Shared memory handle, higher bits
++ * w6-w7: Not used (MBZ)
++ *
++ * Return register usage:
++ * w3: Error code, 0 on success
++ * w4-w7: Note used (MBZ)
++ */
++#define OPTEE_FFA_UNREGISTER_SHM OPTEE_FFA_BLOCKING_CALL(3)
++
++/*
++ * Call with struct optee_msg_arg as argument in the supplied shared memory
++ * with a zero internal offset and normal cached memory attributes.
++ * Register usage:
++ * w3: Service ID, OPTEE_FFA_YIELDING_CALL_WITH_ARG
++ * w4: Lower 32 bits of a 64-bit Shared memory handle
++ * w5: Upper 32 bits of a 64-bit Shared memory handle
++ * w6: Offset into shared memory pointing to a struct optee_msg_arg
++ * right after the parameters of this struct (at offset
++ * OPTEE_MSG_GET_ARG_SIZE(num_params) follows a struct optee_msg_arg
++ * for RPC, this struct has reserved space for the number of RPC
++ * parameters as returned by OPTEE_FFA_EXCHANGE_CAPABILITIES.
++ * w7: Not used (MBZ)
++ * Resume from RPC. Register usage:
++ * w3: Service ID, OPTEE_FFA_YIELDING_CALL_RESUME
++ * w4-w6: Not used (MBZ)
++ * w7: Resume info
++ *
++ * Normal return (yielding call is completed). Register usage:
++ * w3: Error code, 0 on success
++ * w4: OPTEE_FFA_YIELDING_CALL_RETURN_DONE
++ * w5-w7: Not used (MBZ)
++ *
++ * RPC interrupt return (RPC from secure world). Register usage:
++ * w3: Error code == 0
++ * w4: Any defined RPC code but OPTEE_FFA_YIELDING_CALL_RETURN_DONE
++ * w5-w6: Not used (MBZ)
++ * w7: Resume info
++ *
++ * Possible error codes in register w3:
++ * 0: Success
++ * FFA_DENIED: w4 isn't one of OPTEE_FFA_YIELDING_CALL_START
++ * OPTEE_FFA_YIELDING_CALL_RESUME
++ *
++ * Possible error codes for OPTEE_FFA_YIELDING_CALL_START,
++ * FFA_BUSY: Number of OP-TEE OS threads exceeded,
++ * try again later
++ * FFA_DENIED: RPC shared memory object not found
++ * FFA_INVALID_PARAMETER: Bad shared memory handle or offset into the memory
++ *
++ * Possible error codes for OPTEE_FFA_YIELDING_CALL_RESUME
++ * FFA_INVALID_PARAMETER: Bad resume info
++ */
++#define OPTEE_FFA_YIELDING_CALL_WITH_ARG OPTEE_FFA_YIELDING_CALL(0)
++#define OPTEE_FFA_YIELDING_CALL_RESUME OPTEE_FFA_YIELDING_CALL(1)
++
++#define OPTEE_FFA_YIELDING_CALL_RETURN_DONE 0
++#define OPTEE_FFA_YIELDING_CALL_RETURN_RPC_CMD 1
++#define OPTEE_FFA_YIELDING_CALL_RETURN_INTERRUPT 2
++
++#endif /*__OPTEE_FFA_H*/
+diff --git a/drivers/tee/optee/optee_msg.h b/drivers/tee/optee/optee_msg.h
+index 1e1341a5eaf2..62348cee3e33 100644
+--- a/drivers/tee/optee/optee_msg.h
++++ b/drivers/tee/optee/optee_msg.h
+@@ -28,6 +28,9 @@
+ #define OPTEE_MSG_ATTR_TYPE_RMEM_INPUT 0x5
+ #define OPTEE_MSG_ATTR_TYPE_RMEM_OUTPUT 0x6
+ #define OPTEE_MSG_ATTR_TYPE_RMEM_INOUT 0x7
++#define OPTEE_MSG_ATTR_TYPE_FMEM_INPUT OPTEE_MSG_ATTR_TYPE_RMEM_INPUT
++#define OPTEE_MSG_ATTR_TYPE_FMEM_OUTPUT OPTEE_MSG_ATTR_TYPE_RMEM_OUTPUT
++#define OPTEE_MSG_ATTR_TYPE_FMEM_INOUT OPTEE_MSG_ATTR_TYPE_RMEM_INOUT
+ #define OPTEE_MSG_ATTR_TYPE_TMEM_INPUT 0x9
+ #define OPTEE_MSG_ATTR_TYPE_TMEM_OUTPUT 0xa
+ #define OPTEE_MSG_ATTR_TYPE_TMEM_INOUT 0xb
+@@ -96,6 +99,8 @@
+ */
+ #define OPTEE_MSG_NONCONTIG_PAGE_SIZE 4096
+
++#define OPTEE_MSG_FMEM_INVALID_GLOBAL_ID 0xffffffffffffffff
++
+ /**
+ * struct optee_msg_param_tmem - temporary memory reference parameter
+ * @buf_ptr: Address of the buffer
+@@ -127,6 +132,23 @@ struct optee_msg_param_rmem {
+ u64 shm_ref;
+ };
+
++/**
++ * struct optee_msg_param_fmem - ffa memory reference parameter
++ * @offs_lower: Lower bits of offset into shared memory reference
++ * @offs_upper: Upper bits of offset into shared memory reference
++ * @internal_offs: Internal offset into the first page of shared memory
++ * reference
++ * @size: Size of the buffer
++ * @global_id: Global identifier of Shared memory
++ */
++struct optee_msg_param_fmem {
++ u32 offs_low;
++ u16 offs_high;
++ u16 internal_offs;
++ u64 size;
++ u64 global_id;
++};
++
+ /**
+ * struct optee_msg_param_value - opaque value parameter
+ *
+@@ -143,12 +165,14 @@ struct optee_msg_param_value {
+ * @attr: attributes
+ * @tmem: parameter by temporary memory reference
+ * @rmem: parameter by registered memory reference
++ * @fmem: parameter by ffa registered memory reference
+ * @value: parameter by opaque value
+ *
+ * @attr & OPTEE_MSG_ATTR_TYPE_MASK indicates if tmem, rmem or value is used in
+ * the union. OPTEE_MSG_ATTR_TYPE_VALUE_* indicates value,
+ * OPTEE_MSG_ATTR_TYPE_TMEM_* indicates @tmem and
+- * OPTEE_MSG_ATTR_TYPE_RMEM_* indicates @rmem,
++ * OPTEE_MSG_ATTR_TYPE_RMEM_* or the alias PTEE_MSG_ATTR_TYPE_FMEM_* indicates
++ * @rmem or @fmem depending on the conduit.
+ * OPTEE_MSG_ATTR_TYPE_NONE indicates that none of the members are used.
+ */
+ struct optee_msg_param {
+@@ -156,6 +180,7 @@ struct optee_msg_param {
+ union {
+ struct optee_msg_param_tmem tmem;
+ struct optee_msg_param_rmem rmem;
++ struct optee_msg_param_fmem fmem;
+ struct optee_msg_param_value value;
+ } u;
+ };
+diff --git a/drivers/tee/optee/optee_private.h b/drivers/tee/optee/optee_private.h
+index c5741e96e967..1ffe74e66d15 100644
+--- a/drivers/tee/optee/optee_private.h
++++ b/drivers/tee/optee/optee_private.h
+@@ -7,6 +7,7 @@
+ #define OPTEE_PRIVATE_H
+
+ #include <linux/arm-smccc.h>
++#include <linux/rhashtable.h>
+ #include <linux/semaphore.h>
+ #include <linux/tee_drv.h>
+ #include <linux/types.h>
+@@ -20,6 +21,7 @@
+ #define TEEC_ERROR_NOT_SUPPORTED 0xFFFF000A
+ #define TEEC_ERROR_COMMUNICATION 0xFFFF000E
+ #define TEEC_ERROR_OUT_OF_MEMORY 0xFFFF000C
++#define TEEC_ERROR_BUSY 0xFFFF000D
+ #define TEEC_ERROR_SHORT_BUFFER 0xFFFF0010
+
+ #define TEEC_ORIGIN_COMMS 0x00000002
+@@ -66,6 +68,22 @@ struct optee_supp {
+ struct completion reqs_c;
+ };
+
++/**
++ * struct optee_ffa_data - FFA communication struct
++ * @ffa_dev FFA device, contains the destination id, the id of
++ * OP-TEE in secure world
++ * @ffa_ops FFA operations
++ * @mutex Serializes access to @global_ids
++ * @global_ids FF-A shared memory global handle translation
++ */
++struct optee_ffa {
++ struct ffa_device *ffa_dev;
++ const struct ffa_dev_ops *ffa_ops;
++ /* Serializes access to @global_ids */
++ struct mutex mutex;
++ struct rhashtable global_ids;
++};
++
+ struct optee;
+
+ /**
+@@ -113,11 +131,15 @@ struct optee {
+ struct tee_device *teedev;
+ const struct optee_ops *ops;
+ optee_invoke_fn *invoke_fn;
++#ifdef CONFIG_ARM_FFA_TRANSPORT
++ struct optee_ffa ffa;
++#endif
+ struct optee_call_queue call_queue;
+ struct optee_wait_queue wait_queue;
+ struct optee_supp supp;
+ struct tee_shm_pool *pool;
+ void *memremaped_shm;
++ unsigned int rpc_arg_count;
+ u32 sec_caps;
+ bool scan_bus_done;
+ struct workqueue_struct *scan_bus_wq;
+@@ -206,6 +228,36 @@ void optee_fill_pages_list(u64 *dst, struct page **pages, int num_pages,
+ #define PTA_CMD_GET_DEVICES_SUPP 0x1
+ int optee_enumerate_devices(u32 func);
+
++int optee_shm_add_ffa_handle(struct optee *optee, struct tee_shm *shm,
++ u64 global_id);
++int optee_shm_rem_ffa_handle(struct optee *optee, u64 global_id);
++
++struct tee_shm *optee_shm_from_ffa_handle(struct optee *optee, u64 global_id);
++
++int optee_ffa_shm_register(struct tee_context *ctx, struct tee_shm *shm,
++ struct page **pages, size_t num_pages,
++ unsigned long start);
++int optee_ffa_shm_unregister(struct tee_context *ctx, struct tee_shm *shm);
++int optee_ffa_shm_register_supp(struct tee_context *ctx, struct tee_shm *shm,
++ struct page **pages, size_t num_pages,
++ unsigned long start);
++int optee_ffa_shm_unregister_supp(struct tee_context *ctx,
++ struct tee_shm *shm);
++
++int optee_ffa_do_call_with_arg(struct tee_context *ctx, struct tee_shm *arg);
++int optee_ffa_rpc_shm_register(struct tee_context *ctx, struct tee_shm *shm);
++void optee_handle_ffa_rpc(struct tee_context *ctx, u32 cmd,
++ struct optee_msg_arg *arg);
++
++static inline bool optee_is_ffa_based(struct optee *optee)
++{
++#ifdef CONFIG_ARM_FFA_TRANSPORT
++ return optee->ffa.ffa_ops;
++#else
++ return false;
++#endif
++}
++
+ /*
+ * Small helpers
+ */
+diff --git a/drivers/tee/optee/rpc.c b/drivers/tee/optee/rpc.c
+index 39562fb6841e..865a9ab3cf65 100644
+--- a/drivers/tee/optee/rpc.c
++++ b/drivers/tee/optee/rpc.c
+@@ -10,6 +10,7 @@
+ #include <linux/i2c.h>
+ #include <linux/slab.h>
+ #include <linux/tee_drv.h>
++#include "optee_ffa.h"
+ #include "optee_private.h"
+ #include "optee_smc.h"
+ #include "optee_rpc_cmd.h"
+@@ -543,3 +544,120 @@ void optee_handle_rpc(struct tee_context *ctx, struct optee_rpc_param *param,
+
+ param->a0 = OPTEE_SMC_CALL_RETURN_FROM_RPC;
+ }
++
++#ifdef CONFIG_ARM_FFA_TRANSPORT
++static void handle_ffa_rpc_func_cmd_shm_alloc(struct tee_context *ctx,
++ struct optee_msg_arg *arg)
++{
++ struct tee_shm *shm;
++
++ if (arg->num_params != 1 ||
++ arg->params[0].attr != OPTEE_MSG_ATTR_TYPE_VALUE_INPUT) {
++ arg->ret = TEEC_ERROR_BAD_PARAMETERS;
++ return;
++ }
++
++ switch (arg->params[0].u.value.a) {
++ case OPTEE_RPC_SHM_TYPE_APPL:
++ shm = cmd_alloc_suppl(ctx, arg->params[0].u.value.b);
++ break;
++ case OPTEE_RPC_SHM_TYPE_KERNEL:
++ shm = tee_shm_alloc(ctx, arg->params[0].u.value.b,
++ TEE_SHM_MAPPED);
++ break;
++ default:
++ arg->ret = TEEC_ERROR_BAD_PARAMETERS;
++ return;
++ }
++
++ if (IS_ERR(shm)) {
++ arg->ret = TEEC_ERROR_OUT_OF_MEMORY;
++ return;
++ }
++
++ arg->params[0] = (struct optee_msg_param){
++ .attr = OPTEE_MSG_ATTR_TYPE_FMEM_OUTPUT,
++ .u.fmem.size = tee_shm_get_size(shm),
++ .u.fmem.global_id = shm->sec_world_id,
++ .u.fmem.internal_offs = shm->offset,
++ };
++
++ arg->ret = TEEC_SUCCESS;
++}
++
++static void handle_ffa_rpc_func_cmd_shm_free(struct tee_context *ctx,
++ struct optee *optee,
++ struct optee_msg_arg *arg)
++{
++ struct tee_shm *shm;
++
++ if (arg->num_params != 1 ||
++ arg->params[0].attr != OPTEE_MSG_ATTR_TYPE_VALUE_INPUT)
++ goto err_bad_param;
++
++ shm = optee_shm_from_ffa_handle(optee, arg->params[0].u.value.b);
++ if (!shm)
++ goto err_bad_param;
++ switch (arg->params[0].u.value.a) {
++ case OPTEE_RPC_SHM_TYPE_APPL:
++ cmd_free_suppl(ctx, shm);
++ break;
++ case OPTEE_RPC_SHM_TYPE_KERNEL:
++ tee_shm_free(shm);
++ break;
++ default:
++ goto err_bad_param;
++ }
++ arg->ret = TEEC_SUCCESS;
++ return;
++
++err_bad_param:
++ arg->ret = TEEC_ERROR_BAD_PARAMETERS;
++}
++
++static void handle_ffa_rpc_func_cmd(struct tee_context *ctx,
++ struct optee_msg_arg *arg)
++{
++ struct optee *optee = tee_get_drvdata(ctx->teedev);
++
++ arg->ret_origin = TEEC_ORIGIN_COMMS;
++ switch (arg->cmd) {
++ case OPTEE_RPC_CMD_GET_TIME:
++ handle_rpc_func_cmd_get_time(arg);
++ break;
++ case OPTEE_RPC_CMD_WAIT_QUEUE:
++ handle_rpc_func_cmd_wq(optee, arg);
++ break;
++ case OPTEE_RPC_CMD_SUSPEND:
++ handle_rpc_func_cmd_wait(arg);
++ break;
++ case OPTEE_RPC_CMD_SHM_ALLOC:
++ handle_ffa_rpc_func_cmd_shm_alloc(ctx, arg);
++ break;
++ case OPTEE_RPC_CMD_SHM_FREE:
++ handle_ffa_rpc_func_cmd_shm_free(ctx, optee, arg);
++ break;
++ case OPTEE_RPC_CMD_I2C_TRANSFER:
++ handle_rpc_func_cmd_i2c_transfer(ctx, arg);
++ break;
++ default:
++ handle_rpc_supp_cmd(ctx, optee, arg);
++ }
++}
++
++void optee_handle_ffa_rpc(struct tee_context *ctx, u32 cmd,
++ struct optee_msg_arg *arg)
++{
++ switch (cmd) {
++ case OPTEE_FFA_YIELDING_CALL_RETURN_RPC_CMD:
++ handle_ffa_rpc_func_cmd(ctx, arg);
++ break;
++ case OPTEE_FFA_YIELDING_CALL_RETURN_INTERRUPT:
++ /* Interrupt delivered by now */
++ break;
++ default:
++ pr_warn("Unknown RPC func 0x%x\n", cmd);
++ break;
++ }
++}
++#endif /*CONFIG_ARM_FFA_TRANSPORT*/
+--
+2.29.2
+
diff --git a/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc0/0021-drivers-optee-hack-for-UUID-endianess-issue.patch b/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc0/0021-drivers-optee-hack-for-UUID-endianess-issue.patch
new file mode 100644
index 0000000..8f3d397
--- /dev/null
+++ b/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.10/tc0/0021-drivers-optee-hack-for-UUID-endianess-issue.patch
@@ -0,0 +1,58 @@
+From 831d01e34ff2065c585da91c8923ea44146097cd Mon Sep 17 00:00:00 2001
+From: Arunachalam Ganapathy <arunachalam.ganapathy@arm.com>
+Date: Thu, 27 May 2021 13:40:33 +0100
+Subject: [PATCH 13/14] drivers: optee: hack for UUID endianess issue
+
+Signed-off-by: Arunachalam Ganapathy <arunachalam.ganapathy@arm.com>
+Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
+Change-Id: Id5c42e4fe491a448f746b9d132dae20c85666554
+
+Upstream-Status: Inappropriate [will not be submitted as its only a workaround]
+---
+ drivers/firmware/arm_ffa/driver.c | 19 +++++++++++++++++++
+ 1 file changed, 19 insertions(+)
+
+diff --git a/drivers/firmware/arm_ffa/driver.c b/drivers/firmware/arm_ffa/driver.c
+index 056a3fca14d1..82c84fe10be2 100644
+--- a/drivers/firmware/arm_ffa/driver.c
++++ b/drivers/firmware/arm_ffa/driver.c
+@@ -275,8 +275,18 @@ ffa_partition_probe(const uuid_t *uuid, struct ffa_partition_info **buffer)
+ struct ffa_partition_info *pbuf;
+
+ export_uuid((u8 *)uuid0_4, uuid);
++
++#if 0
+ count = __ffa_partition_info_get(uuid0_4[0], uuid0_4[1], uuid0_4[2],
+ uuid0_4[3], NULL, 0);
++#else
++ /* hack for optee UUID endianess issue */
++ count = __ffa_partition_info_get(be32_to_cpup(&uuid0_4[0]),
++ be32_to_cpup(&uuid0_4[1]),
++ be32_to_cpup(&uuid0_4[2]),
++ be32_to_cpup(&uuid0_4[3]), NULL, 0);
++#endif
++
+ if (count <= 0)
+ return count;
+
+@@ -284,8 +294,17 @@ ffa_partition_probe(const uuid_t *uuid, struct ffa_partition_info **buffer)
+ if (!pbuf)
+ return -ENOMEM;
+
++#if 0
+ count = __ffa_partition_info_get(uuid0_4[0], uuid0_4[1], uuid0_4[2],
+ uuid0_4[3], pbuf, count);
++#else
++ /* hack for optee UUID endianess issue */
++ count = __ffa_partition_info_get(be32_to_cpup(&uuid0_4[0]),
++ be32_to_cpup(&uuid0_4[1]),
++ be32_to_cpup(&uuid0_4[2]),
++ be32_to_cpup(&uuid0_4[3]),
++ pbuf, count);
++#endif
+ if (count <= 0)
+ kfree(pbuf);
+
+--
+2.29.2
+
--
2.29.2
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH 3/6] arm-bsp/tc0: Update optee to 3.14.0
2021-07-22 11:32 [PATCH 1/6] arm: update Android common kernel Arunachalam Ganapathy
2021-07-22 11:32 ` [PATCH 2/6] arm-bsp/linux: add ffa driver to TC0 Arunachalam Ganapathy
@ 2021-07-22 11:32 ` Arunachalam Ganapathy
2021-07-22 11:32 ` [PATCH 4/6] arm/hafnium: update to version 2.5 Arunachalam Ganapathy
` (2 subsequent siblings)
4 siblings, 0 replies; 6+ messages in thread
From: Arunachalam Ganapathy @ 2021-07-22 11:32 UTC (permalink / raw)
To: meta-arm; +Cc: nd, Arunachalam Ganapathy
Signed-off-by: Arunachalam Ganapathy <arunachalam.ganapathy@arm.com>
Change-Id: Ic70bcab5a3e0b7ccf6deb9a0dc3efe21112995fa
---
...void-memcpy-when-using-TEEC_TempMemo.patch | 52 --
...e-page-aligned-shared-memory-buffers.patch | 95 ---
...ore-SPMC-update-for-FF-A-version-1.0.patch | 50 --
.../tc0/0002-core-add-thread_smccc.patch | 89 ---
...e-enable-SPCI-with-SPM-Core-at-S-EL2.patch | 623 ------------------
...fixes-to-align-with-upstream-hafnium.patch | 188 ------
...e-arm-Total-Compute-platform-support.patch | 187 ------
...alcompute-Add-support-for-S-EL2-SPMC.patch | 108 ---
...e-add-optee-manifest-file-and-sp-lay.patch | 73 --
...e-define-tzdram-start-address-for-S-.patch | 36 -
...totalcompute-add-Theodul-DSU-support.patch | 93 ---
...P-declare-device-regions-in-manifest.patch | 47 --
...TEE-SP-use-CNTVCT-in-place-of-CNTVCT.patch | 173 -----
.../optee/files/optee-os/tc0/sp_layout.json | 6 +
.../optee/optee-client-tc0.inc | 11 +-
....bbappend => optee-client_3.14.0.bbappend} | 0
.../recipes-security/optee/optee-os-tc0.inc | 39 +-
...11.0.bbappend => optee-os_3.14.0.bbappend} | 0
.../recipes-security/optee/optee-test-tc0.inc | 11 -
....0.bbappend => optee-test_3.14.0.bbappend} | 0
20 files changed, 16 insertions(+), 1865 deletions(-)
delete mode 100644 meta-arm-bsp/recipes-security/optee/files/optee-client/tc0/0001-Revert-libteec-Avoid-memcpy-when-using-TEEC_TempMemo.patch
delete mode 100644 meta-arm-bsp/recipes-security/optee/files/optee-client/tc0/0002-Allocate-page-aligned-shared-memory-buffers.patch
delete mode 100644 meta-arm-bsp/recipes-security/optee/files/optee-os/tc0/0001-core-SPMC-update-for-FF-A-version-1.0.patch
delete mode 100644 meta-arm-bsp/recipes-security/optee/files/optee-os/tc0/0002-core-add-thread_smccc.patch
delete mode 100644 meta-arm-bsp/recipes-security/optee/files/optee-os/tc0/0003-core-enable-SPCI-with-SPM-Core-at-S-EL2.patch
delete mode 100644 meta-arm-bsp/recipes-security/optee/files/optee-os/tc0/0004-core-fixes-to-align-with-upstream-hafnium.patch
delete mode 100644 meta-arm-bsp/recipes-security/optee/files/optee-os/tc0/0005-core-arm-Total-Compute-platform-support.patch
delete mode 100644 meta-arm-bsp/recipes-security/optee/files/optee-os/tc0/0006-plat-totalcompute-Add-support-for-S-EL2-SPMC.patch
delete mode 100644 meta-arm-bsp/recipes-security/optee/files/optee-os/tc0/0007-plat-totalcompute-add-optee-manifest-file-and-sp-lay.patch
delete mode 100644 meta-arm-bsp/recipes-security/optee/files/optee-os/tc0/0008-plat-totalcompute-define-tzdram-start-address-for-S-.patch
delete mode 100644 meta-arm-bsp/recipes-security/optee/files/optee-os/tc0/0009-plat-totalcompute-add-Theodul-DSU-support.patch
delete mode 100644 meta-arm-bsp/recipes-security/optee/files/optee-os/tc0/0010-WIP-OP-TEE-SP-declare-device-regions-in-manifest.patch
delete mode 100644 meta-arm-bsp/recipes-security/optee/files/optee-os/tc0/0011-WIP-OP-TEE-SP-use-CNTVCT-in-place-of-CNTVCT.patch
create mode 100644 meta-arm-bsp/recipes-security/optee/files/optee-os/tc0/sp_layout.json
rename meta-arm-bsp/recipes-security/optee/{optee-client_3.11.0.bbappend => optee-client_3.14.0.bbappend} (100%)
rename meta-arm-bsp/recipes-security/optee/{optee-os_3.11.0.bbappend => optee-os_3.14.0.bbappend} (100%)
rename meta-arm-bsp/recipes-security/optee/{optee-test_3.11.0.bbappend => optee-test_3.14.0.bbappend} (100%)
diff --git a/meta-arm-bsp/recipes-security/optee/files/optee-client/tc0/0001-Revert-libteec-Avoid-memcpy-when-using-TEEC_TempMemo.patch b/meta-arm-bsp/recipes-security/optee/files/optee-client/tc0/0001-Revert-libteec-Avoid-memcpy-when-using-TEEC_TempMemo.patch
deleted file mode 100644
index 4515c1d..0000000
--- a/meta-arm-bsp/recipes-security/optee/files/optee-client/tc0/0001-Revert-libteec-Avoid-memcpy-when-using-TEEC_TempMemo.patch
+++ /dev/null
@@ -1,52 +0,0 @@
-Upstream-Status: Pending [https://github.com/jenswi-linaro/optee_client/commit/7e569bdf770f635c5de1f4e659d41039a6199a0b]
-Signed-off-by: Arunachalam Ganapathy <arunachalam.ganapathy@arm.com>
-
-From 7e569bdf770f635c5de1f4e659d41039a6199a0b Mon Sep 17 00:00:00 2001
-From: Jens Wiklander <jens.wiklander@linaro.org>
-Date: Wed, 11 Nov 2020 10:09:38 +0100
-Subject: [PATCH 1/2] Revert "libteec: Avoid memcpy() when using
- TEEC_TempMemoryReference"
-
-This reverts commit dcb13e2f457fa98e9ba49dd2a364542680671e95.
----
- libteec/src/tee_client_api.c | 14 ++++----------
- 1 file changed, 4 insertions(+), 10 deletions(-)
-
-diff --git a/libteec/src/tee_client_api.c b/libteec/src/tee_client_api.c
-index 6b81e09..b8ccdfa 100644
---- a/libteec/src/tee_client_api.c
-+++ b/libteec/src/tee_client_api.c
-@@ -217,15 +217,11 @@ static TEEC_Result teec_pre_process_tmpref(TEEC_Context *ctx,
- MEMREF_SHM_ID(param) = shm->id;
- }
- } else {
-- shm->buffer = tmpref->buffer;
-- res = TEEC_RegisterSharedMemory(ctx, shm);
-+ res = TEEC_AllocateSharedMemory(ctx, shm);
- if (res != TEEC_SUCCESS)
- return res;
-
-- if (shm->shadow_buffer)
-- memcpy(shm->shadow_buffer, tmpref->buffer,
-- tmpref->size);
--
-+ memcpy(shm->buffer, tmpref->buffer, tmpref->size);
- MEMREF_SHM_ID(param) = shm->id;
- }
-
-@@ -388,10 +384,8 @@ static void teec_post_process_tmpref(uint32_t param_type,
- TEEC_SharedMemory *shm)
- {
- if (param_type != TEEC_MEMREF_TEMP_INPUT) {
-- if (MEMREF_SIZE(param) <= tmpref->size && tmpref->buffer &&
-- shm->shadow_buffer)
-- memcpy(tmpref->buffer, shm->shadow_buffer,
-- MEMREF_SIZE(param));
-+ if (MEMREF_SIZE(param) <= tmpref->size && tmpref->buffer)
-+ memcpy(tmpref->buffer, shm->buffer, MEMREF_SIZE(param));
-
- tmpref->size = MEMREF_SIZE(param);
- }
---
-2.26.2
-
diff --git a/meta-arm-bsp/recipes-security/optee/files/optee-client/tc0/0002-Allocate-page-aligned-shared-memory-buffers.patch b/meta-arm-bsp/recipes-security/optee/files/optee-client/tc0/0002-Allocate-page-aligned-shared-memory-buffers.patch
deleted file mode 100644
index 5928bfd..0000000
--- a/meta-arm-bsp/recipes-security/optee/files/optee-client/tc0/0002-Allocate-page-aligned-shared-memory-buffers.patch
+++ /dev/null
@@ -1,95 +0,0 @@
-Upstream-Status: Pending [https://github.com/jenswi-linaro/optee_client/commit/7a67f8b7681ecf3abb5b09e5e320857d16f4a7e6]
-Signed-off-by: Arunachalam Ganapathy <arunachalam.ganapathy@arm.com>
-
-From 7a67f8b7681ecf3abb5b09e5e320857d16f4a7e6 Mon Sep 17 00:00:00 2001
-From: Jens Wiklander <jens.wiklander@linaro.org>
-Date: Mon, 16 Nov 2020 17:34:07 +0100
-Subject: [PATCH 2/2] Allocate page aligned shared memory buffers
-
-Allocate page aligned shared memory buffer guarantee that each shared
-memory buffer doesn't accidentally share a page of memory or they may
-become aliased when mapped in secure world. This is normally not a big
-problem but may make it a bit harder to track down buffer overruns in
-shared memory buffers.
-
-In a post Arm v8.4 architecture with FF-A [1] there's trouble since it's
-not permitted to share the same physical page twice.
-
-Signed-off-by: Jens Wiklander <jens.wiklander@linaro.org>
----
- libteec/src/tee_client_api.c | 14 ++++++++++++--
- tee-supplicant/src/tee_supplicant.c | 12 +++++++++++-
- 2 files changed, 23 insertions(+), 3 deletions(-)
-
-diff --git a/libteec/src/tee_client_api.c b/libteec/src/tee_client_api.c
-index b8ccdfa..676d373 100644
---- a/libteec/src/tee_client_api.c
-+++ b/libteec/src/tee_client_api.c
-@@ -74,6 +74,16 @@ static void teec_mutex_unlock(pthread_mutex_t *mu)
- pthread_mutex_unlock(mu);
- }
-
-+static void *teec_paged_aligned_alloc(size_t sz)
-+{
-+ void *p = NULL;
-+
-+ if (!posix_memalign(&p, sysconf(_SC_PAGESIZE), sz))
-+ return p;
-+
-+ return NULL;
-+}
-+
- static int teec_open_dev(const char *devname, const char *capabilities,
- uint32_t *gen_caps)
- {
-@@ -790,7 +800,7 @@ TEEC_Result TEEC_RegisterSharedMemory(TEEC_Context *ctx, TEEC_SharedMemory *shm)
- * we're not making matters worse by trying to allocate and
- * register a shadow buffer before giving up.
- */
-- shm->shadow_buffer = malloc(s);
-+ shm->shadow_buffer = teec_paged_aligned_alloc(s);
- if (!shm->shadow_buffer)
- return TEEC_ERROR_OUT_OF_MEMORY;
- fd = teec_shm_register(ctx->fd, shm->shadow_buffer, s,
-@@ -873,7 +883,7 @@ TEEC_Result TEEC_AllocateSharedMemory(TEEC_Context *ctx, TEEC_SharedMemory *shm)
- s = 8;
-
- if (ctx->reg_mem) {
-- shm->buffer = malloc(s);
-+ shm->buffer = teec_paged_aligned_alloc(s);
- if (!shm->buffer)
- return TEEC_ERROR_OUT_OF_MEMORY;
-
-diff --git a/tee-supplicant/src/tee_supplicant.c b/tee-supplicant/src/tee_supplicant.c
-index 94cf382..d590c2b 100644
---- a/tee-supplicant/src/tee_supplicant.c
-+++ b/tee-supplicant/src/tee_supplicant.c
-@@ -127,6 +127,16 @@ static size_t num_waiters_dec(struct thread_arg *arg)
- return ret;
- }
-
-+static void *paged_aligned_alloc(size_t sz)
-+{
-+ void *p = NULL;
-+
-+ if (!posix_memalign(&p, sysconf(_SC_PAGESIZE), sz))
-+ return p;
-+
-+ return NULL;
-+}
-+
- static int get_value(size_t num_params, struct tee_ioctl_param *params,
- const uint32_t idx, struct param_value **value)
- {
-@@ -336,7 +346,7 @@ static struct tee_shm *register_local_shm(int fd, size_t size)
-
- memset(&data, 0, sizeof(data));
-
-- buf = malloc(size);
-+ buf = paged_aligned_alloc(size);
- if (!buf)
- return NULL;
-
---
-2.26.2
-
diff --git a/meta-arm-bsp/recipes-security/optee/files/optee-os/tc0/0001-core-SPMC-update-for-FF-A-version-1.0.patch b/meta-arm-bsp/recipes-security/optee/files/optee-os/tc0/0001-core-SPMC-update-for-FF-A-version-1.0.patch
deleted file mode 100644
index d3b2319..0000000
--- a/meta-arm-bsp/recipes-security/optee/files/optee-os/tc0/0001-core-SPMC-update-for-FF-A-version-1.0.patch
+++ /dev/null
@@ -1,50 +0,0 @@
-Upstream-Status: Pending [https://github.com/jenswi-linaro/optee_os/commit/7c3b052b871420618a08402f626923fe85a139db]
-Signed-off-by: Arunachalam Ganapathy <arunachalam.ganapathy@arm.com>
-
-From 7c3b052b871420618a08402f626923fe85a139db Mon Sep 17 00:00:00 2001
-From: Marc Bonnici <marc.bonnici@arm.com>
-Date: Wed, 23 Sep 2020 13:55:22 +0100
-Subject: [PATCH 1/3] core: SPMC: update for FF-A version 1.0
-
-Update expected memory attributes. As per the FF-A spec (5.11.3) a
-lender of a memory region should not specify the instruction access
-permission, therefore update the expected memory attribute.
-
-Updates the version number to 1.0 replacing the previous version number
-0.9.
----
- core/arch/arm/include/optee_ffa.h | 4 ++--
- core/arch/arm/kernel/thread_spmc.c | 2 +-
- 2 files changed, 3 insertions(+), 3 deletions(-)
-
-diff --git a/core/arch/arm/include/optee_ffa.h b/core/arch/arm/include/optee_ffa.h
-index 8498fbab..9daca732 100644
---- a/core/arch/arm/include/optee_ffa.h
-+++ b/core/arch/arm/include/optee_ffa.h
-@@ -27,8 +27,8 @@
- * w3-w7: Implementation defined, free to be used below
- */
-
--#define OPTEE_FFA_VERSION_MAJOR UINT32_C(0)
--#define OPTEE_FFA_VERSION_MINOR UINT32_C(9)
-+#define OPTEE_FFA_VERSION_MAJOR UINT32_C(1)
-+#define OPTEE_FFA_VERSION_MINOR UINT32_C(0)
-
- #define OPTEE_FFA_BLOCKING_CALL(id) UINT32_C(id)
- #define OPTEE_FFA_YIELDING_CALL_BIT 31
-diff --git a/core/arch/arm/kernel/thread_spmc.c b/core/arch/arm/kernel/thread_spmc.c
-index 81edf03a..16f3bbe1 100644
---- a/core/arch/arm/kernel/thread_spmc.c
-+++ b/core/arch/arm/kernel/thread_spmc.c
-@@ -433,7 +433,7 @@ static int mem_share_init(void *buf, size_t blen, unsigned int *page_count,
- {
- struct mem_region_descr *region_descr = NULL;
- struct mem_transaction_descr *descr = NULL;
-- const uint8_t exp_mem_acc_perm = 0x6; /* Not executable, Read-write */
-+ const uint8_t exp_mem_acc_perm = 0x2; /* Read-write */
- /* Normal memory, Write-Back cacheable, Inner shareable */
- const uint8_t exp_mem_reg_attr = 0x2f;
- unsigned int num_mem_accs = 0;
---
-2.26.2
-
diff --git a/meta-arm-bsp/recipes-security/optee/files/optee-os/tc0/0002-core-add-thread_smccc.patch b/meta-arm-bsp/recipes-security/optee/files/optee-os/tc0/0002-core-add-thread_smccc.patch
deleted file mode 100644
index 32a420e..0000000
--- a/meta-arm-bsp/recipes-security/optee/files/optee-os/tc0/0002-core-add-thread_smccc.patch
+++ /dev/null
@@ -1,89 +0,0 @@
-Upstream-Status: Pending [https://github.com/jenswi-linaro/optee_os/commit/269e226eea2b2f26a6f844b7d25bc2b2a9b26315]
-Signed-off-by: Arunachalam Ganapathy <arunachalam.ganapathy@arm.com>
-
-From 269e226eea2b2f26a6f844b7d25bc2b2a9b26315 Mon Sep 17 00:00:00 2001
-From: Jens Wiklander <jens.wiklander@linaro.org>
-Date: Tue, 4 Feb 2020 17:30:55 +0100
-Subject: [PATCH 2/3] core: add thread_smccc()
-
-Adds the assembly function thread_smccc() which loads the first 8
-registers with the argument and executes an SMC or HVC instruction as
-appropriate. The result in the first 8 registers is then saved in the
-argument struct.
-
-Change-Id: Ie14154fb38de5ced3cfdebdb0bf19e48caaf2279
-Signed-off-by: Jens Wiklander <jens.wiklander@linaro.org>
----
- core/arch/arm/include/kernel/thread.h | 1 +
- core/arch/arm/kernel/thread_a32.S | 16 ++++++++++++++++
- core/arch/arm/kernel/thread_a64.S | 15 +++++++++++++++
- 3 files changed, 32 insertions(+)
-
-diff --git a/core/arch/arm/include/kernel/thread.h b/core/arch/arm/include/kernel/thread.h
-index b9c0ba4b..4f0520e9 100644
---- a/core/arch/arm/include/kernel/thread.h
-+++ b/core/arch/arm/include/kernel/thread.h
-@@ -704,6 +704,7 @@ uint32_t thread_rpc_cmd(uint32_t cmd, size_t num_params,
-
- unsigned long thread_smc(unsigned long func_id, unsigned long a1,
- unsigned long a2, unsigned long a3);
-+void thread_smccc(struct thread_smc_args *arg_res);
-
- /**
- * Allocate data for payload buffers.
-diff --git a/core/arch/arm/kernel/thread_a32.S b/core/arch/arm/kernel/thread_a32.S
-index 199e90a9..75d85c32 100644
---- a/core/arch/arm/kernel/thread_a32.S
-+++ b/core/arch/arm/kernel/thread_a32.S
-@@ -210,6 +210,22 @@ FUNC thread_smc , :
- bx lr
- END_FUNC thread_smc
-
-+/* void thread_smccc(struct thread_smc_args *arg_res) */
-+FUNC thread_smccc , :
-+ push {r4-r7}
-+ push {r0, lr}
-+ ldm r0, {r0-r7}
-+#ifdef CFG_CORE_SEL2_SPMC
-+ hvc #0
-+#else
-+ smc #0
-+#endif
-+ pop {r12, lr}
-+ stm r12, {r0-r7}
-+ pop {r4-r7}
-+ bx lr
-+END_FUNC thread_smccc
-+
- FUNC thread_init_vbar , :
- /* Set vector (VBAR) */
- write_vbar r0
-diff --git a/core/arch/arm/kernel/thread_a64.S b/core/arch/arm/kernel/thread_a64.S
-index 9ce31eb2..3e0f5115 100644
---- a/core/arch/arm/kernel/thread_a64.S
-+++ b/core/arch/arm/kernel/thread_a64.S
-@@ -65,6 +65,21 @@ FUNC thread_smc , :
- ret
- END_FUNC thread_smc
-
-+/* void thread_smccc(struct thread_smc_args *arg_res) */
-+FUNC thread_smccc , :
-+ push x0, xzr
-+ mov x8, x0
-+ load_xregs x8, 0, 0, 7
-+#ifdef CFG_CORE_SEL2_SPMC
-+ hvc #0
-+#else
-+ smc #0
-+#endif
-+ pop x8, xzr
-+ store_xregs x8, 0, 0, 7
-+ ret
-+END_FUNC thread_smccc
-+
- FUNC thread_init_vbar , :
- msr vbar_el1, x0
- ret
---
-2.26.2
-
diff --git a/meta-arm-bsp/recipes-security/optee/files/optee-os/tc0/0003-core-enable-SPCI-with-SPM-Core-at-S-EL2.patch b/meta-arm-bsp/recipes-security/optee/files/optee-os/tc0/0003-core-enable-SPCI-with-SPM-Core-at-S-EL2.patch
deleted file mode 100644
index c3967dc..0000000
--- a/meta-arm-bsp/recipes-security/optee/files/optee-os/tc0/0003-core-enable-SPCI-with-SPM-Core-at-S-EL2.patch
+++ /dev/null
@@ -1,623 +0,0 @@
-Upstream-Status: Pending [https://github.com/jenswi-linaro/optee_os/commit/80f0ec4ba2af33584e99e917fa165b77028a511f]
-Signed-off-by: Arunachalam Ganapathy <arunachalam.ganapathy@arm.com>
-
-From 80f0ec4ba2af33584e99e917fa165b77028a511f Mon Sep 17 00:00:00 2001
-From: Marc Bonnici <marc.bonnici@arm.com>
-Date: Fri, 5 Jun 2020 13:47:40 +0100
-Subject: [PATCH 3/3] core: enable SPCI with SPM Core at S-EL2
-
-This is a port of a pre-exisiting patch to support the case where
-the SPM Core is implementation at S-EL2, that is, in a secure hypervisor.
-This configuration is also know as "S-EL2 SPMC" in the FFA specification.
-
-Compile with CFG_CORE_SEL2_SPMC=y
-
-Note that this is an experimental feature, ABIs etc may have
-incompatible changes.
-
-Sqaushed in:
- core: Update cookie to uint64 in S-EL2 code
-
- As part of the update to FF-A 1.0 the globally
- unique handle to identify a shared memory object is now 64
- bits wide instead of 32. This commit updates the
- remaining usage of 32 bit values.
-
- core: Remove page count from S-EL2 code
-
- The page count field has been dropped from upstream OP-TEE to
- accommodate using a 64 bit handle in the same size message param struct,
- therefore update our implementation to support this.
-
- core: Update remaining FF-A structures to EAC
-
- Update relinquish data structures and ABI invocations to the FFA
- EAC spec
----
- core/arch/arm/arm.mk | 7 ++
- core/arch/arm/include/kernel/thread.h | 6 +
- core/arch/arm/include/mm/mobj.h | 6 +
- core/arch/arm/kernel/thread_spmc.c | 164 ++++++++++++++++++++++++-
- core/arch/arm/kernel/thread_spmc_a64.S | 3 +-
- core/arch/arm/mm/mobj_ffa.c | 104 +++++++++++-----
- core/arch/arm/plat-vexpress/conf.mk | 5 +
- 7 files changed, 260 insertions(+), 35 deletions(-)
-
-diff --git a/core/arch/arm/arm.mk b/core/arch/arm/arm.mk
-index f495f3c9..7c5e8fb0 100644
---- a/core/arch/arm/arm.mk
-+++ b/core/arch/arm/arm.mk
-@@ -97,6 +97,13 @@ endif
- # changes
- ifeq ($(CFG_CORE_SEL1_SPMC),y)
- $(call force,CFG_CORE_FFA,y)
-+$(call force,CFG_CORE_SEL2_SPMC,n)
-+endif
-+# SPMC configuration "S-EL2 SPMC" where SPM Core is implemented at S-EL2,
-+# that is, the hypervisor sandboxing OP-TEE
-+ifeq ($(CFG_CORE_SEL2_SPMC),y)
-+$(call force,CFG_CORE_FFA,y)
-+$(call force,CFG_CORE_SEL1_SPMC,n)
- endif
-
- # Unmaps all kernel mode code except the code needed to take exceptions
-diff --git a/core/arch/arm/include/kernel/thread.h b/core/arch/arm/include/kernel/thread.h
-index 4f0520e9..95f48589 100644
---- a/core/arch/arm/include/kernel/thread.h
-+++ b/core/arch/arm/include/kernel/thread.h
-@@ -759,6 +759,12 @@ enum thread_shm_cache_user {
- void *thread_rpc_shm_cache_alloc(enum thread_shm_cache_user user,
- enum thread_shm_type shm_type,
- size_t size, struct mobj **mobj);
-+
-+#if defined(CFG_CORE_SEL2_SPMC)
-+struct mobj_ffa *thread_spmc_populate_mobj_from_rx(uint64_t cookie);
-+void thread_spmc_relinquish(uint64_t memory_region_handle);
-+#endif
-+
- #endif /*__ASSEMBLER__*/
-
- #endif /*KERNEL_THREAD_H*/
-diff --git a/core/arch/arm/include/mm/mobj.h b/core/arch/arm/include/mm/mobj.h
-index 2b9bd90c..3f820666 100644
---- a/core/arch/arm/include/mm/mobj.h
-+++ b/core/arch/arm/include/mm/mobj.h
-@@ -216,6 +216,12 @@ struct mobj_ffa *mobj_ffa_sel1_spmc_new(unsigned int num_pages);
- void mobj_ffa_sel1_spmc_delete(struct mobj_ffa *mobj);
- TEE_Result mobj_ffa_sel1_spmc_reclaim(uint64_t cookie);
- #endif
-+#ifdef CFG_CORE_SEL2_SPMC
-+struct mobj_ffa *mobj_ffa_sel2_spmc_new(uint64_t cookie,
-+ unsigned int num_pages);
-+void mobj_ffa_sel2_spmc_delete(struct mobj_ffa *mobj);
-+#endif
-+
- uint64_t mobj_ffa_get_cookie(struct mobj_ffa *mobj);
- TEE_Result mobj_ffa_add_pages_at(struct mobj_ffa *mobj, unsigned int *idx,
- paddr_t pa, unsigned int num_pages);
-diff --git a/core/arch/arm/kernel/thread_spmc.c b/core/arch/arm/kernel/thread_spmc.c
-index 16f3bbe1..3d7dc035 100644
---- a/core/arch/arm/kernel/thread_spmc.c
-+++ b/core/arch/arm/kernel/thread_spmc.c
-@@ -7,6 +7,7 @@
- #include <assert.h>
- #include <ffa.h>
- #include <io.h>
-+#include <initcall.h>
- #include <kernel/interrupt.h>
- #include <kernel/panic.h>
- #include <kernel/spinlock.h>
-@@ -88,6 +89,18 @@ struct mem_frag_state {
-
- static uint16_t my_sp_id = 0x8001;
-
-+
-+/* Table 149: FFA_MEM_RELINQUISH. */
-+struct ffa_relinquish_descriptor {
-+ uint64_t handle;
-+ uint32_t flags;
-+ uint32_t endpoint_count;
-+ uint16_t endpoint_id_array[];
-+};
-+
-+/* Our VM ID is 0x8001, non-secure VM ID 0x0001 */
-+const uint32_t thread_spmc_target_info = 0x80010001;
-+
- /*
- * If @rxtx_size is 0 RX/TX buffers are not mapped or initialized.
- *
-@@ -101,8 +114,16 @@ static uint16_t my_sp_id = 0x8001;
- * these buffers so we must always be careful when reading. while we hold
- * the lock.
- */
-+
-+#ifdef CFG_CORE_SEL2_SPMC
-+static uint8_t rx_buf[SMALL_PAGE_SIZE] __aligned(SMALL_PAGE_SIZE);
-+static uint8_t tx_buf[SMALL_PAGE_SIZE] __aligned(SMALL_PAGE_SIZE);
-+#else
- static void *rx_buf;
- static void *tx_buf;
-+#endif
-+
-+
- static unsigned int rxtx_size;
- static unsigned int rxtx_spinlock;
- static bool tx_buf_is_mine;
-@@ -127,6 +148,28 @@ static void set_args(struct thread_smc_args *args, uint32_t fid,
- .a5 = w5, };
- }
-
-+static int __maybe_unused
-+set_pages(struct constituent_address_range *regions, unsigned int num_regions,
-+ unsigned int num_pages, struct mobj_ffa *mf)
-+{
-+ unsigned int n = 0;
-+ unsigned int idx = 0;
-+
-+ for (n = 0; n < num_regions; n++) {
-+ unsigned int page_count = READ_ONCE(regions[n].page_count);
-+ uint64_t addr = READ_ONCE(regions[n].address);
-+
-+ if (mobj_ffa_add_pages_at(mf, &idx, addr, page_count))
-+ return FFA_INVALID_PARAMETERS;
-+ }
-+
-+ if (idx != num_pages)
-+ return FFA_INVALID_PARAMETERS;
-+
-+ return 0;
-+}
-+
-+
- static void handle_version(struct thread_smc_args *args)
- {
- /*
-@@ -188,6 +231,7 @@ static void handle_features(struct thread_smc_args *args)
- FFA_PARAM_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ);
- }
-
-+#ifdef CFG_CORE_SEL1_SPMC
- static int map_buf(paddr_t pa, unsigned int sz, void **va_ret)
- {
- tee_mm_entry_t *mm = NULL;
-@@ -293,6 +337,7 @@ out:
- set_args(args, ret_fid, FFA_PARAM_MBZ, rc,
- FFA_PARAM_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ);
- }
-+#endif
-
- static void handle_rx_release(struct thread_smc_args *args)
- {
-@@ -408,6 +453,7 @@ static void handle_blocking_call(struct thread_smc_args *args)
- }
- }
-
-+#if CFG_CORE_SEL1_SPMC
- static int get_acc_perms(struct mem_accsess_descr *mem_acc,
- unsigned int num_mem_accs, uint8_t *acc_perms,
- unsigned int *region_offs)
-@@ -531,7 +577,11 @@ static int add_mem_share_frag(struct mem_frag_state *s, void *buf, size_t flen)
-
- SLIST_REMOVE(&frag_state_head, s, mem_frag_state, link);
- if (rc < 0)
-+#ifdef CFG_CORE_SEL2_SPMC
-+ mobj_ffa_sel2_spmc_delete(s->share.mf);
-+#else
- mobj_ffa_sel1_spmc_delete(s->share.mf);
-+#endif
- else
- mobj_ffa_push_to_inactive(s->share.mf);
- free(s);
-@@ -559,8 +609,8 @@ static int add_mem_share(tee_mm_entry_t *mm, void *buf, size_t blen,
- sizeof(struct constituent_address_range), &n) ||
- ADD_OVERFLOW(n, addr_range_offs, &n) || n > blen)
- return FFA_INVALID_PARAMETERS;
--
- share.mf = mobj_ffa_sel1_spmc_new(share.page_count);
-+
- if (!share.mf)
- return FFA_NO_MEMORY;
-
-@@ -601,6 +651,7 @@ static int add_mem_share(tee_mm_entry_t *mm, void *buf, size_t blen,
- return 0;
- err:
- mobj_ffa_sel1_spmc_delete(share.mf);
-+
- return rc;
- }
-
-@@ -809,6 +860,7 @@ static void handle_mem_reclaim(struct thread_smc_args *args)
- out:
- set_args(args, ret_fid, ret_val, 0, 0, 0, 0);
- }
-+#endif
-
- /* Only called from assembly */
- void thread_spmc_msg_recv(struct thread_smc_args *args);
-@@ -822,6 +874,7 @@ void thread_spmc_msg_recv(struct thread_smc_args *args)
- case FFA_FEATURES:
- handle_features(args);
- break;
-+#if CFG_CORE_SEL1_SPMC
- #ifdef ARM64
- case FFA_RXTX_MAP_64:
- #endif
-@@ -831,6 +884,7 @@ void thread_spmc_msg_recv(struct thread_smc_args *args)
- case FFA_RXTX_UNMAP:
- handle_rxtx_unmap(args);
- break;
-+#endif
- case FFA_RX_RELEASE:
- handle_rx_release(args);
- break;
-@@ -847,6 +901,7 @@ void thread_spmc_msg_recv(struct thread_smc_args *args)
- else
- handle_blocking_call(args);
- break;
-+#if CFG_CORE_SEL1_SPMC
- #ifdef ARM64
- case FFA_MEM_SHARE_64:
- #endif
-@@ -859,6 +914,7 @@ void thread_spmc_msg_recv(struct thread_smc_args *args)
- case FFA_MEM_FRAG_TX:
- handle_mem_frag_tx(args);
- break;
-+#endif
- default:
- EMSG("Unhandled FFA function ID %#"PRIx32, (uint32_t)args->a0);
- set_args(args, FFA_ERROR, FFA_PARAM_MBZ, FFA_NOT_SUPPORTED,
-@@ -1185,3 +1241,109 @@ void thread_rpc_free_global_payload(struct mobj *mobj __unused)
-
- assert(!cant_happen);
- }
-+
-+#ifdef CFG_CORE_SEL2_SPMC
-+static void spmc_rxtx_map(void)
-+{
-+ struct thread_smc_args args = {
-+ .a0 = FFA_RXTX_MAP_64,
-+ .a1 = (vaddr_t)tx_buf,
-+ .a2 = (vaddr_t)rx_buf,
-+ .a3 = 1,
-+ };
-+
-+ thread_smccc(&args);
-+ if (args.a0 == FFA_ERROR) {
-+ EMSG("ERROR rxtx map failed with error %ld\n", args.a2);
-+ panic();
-+ }
-+}
-+
-+static struct mem_transaction_descr *spmc_retrieve_req(uint64_t cookie)
-+{
-+ struct mem_transaction_descr *retrieve_region = (void *)tx_buf;
-+
-+ struct thread_smc_args args = {
-+ .a0 = FFA_MEM_RETRIEVE_REQ_64,
-+ .a1 = sizeof(*retrieve_region), // Total Length
-+ .a2 = sizeof(*retrieve_region), // Frag Length == Total length
-+ .a3 = 0, // Address, Using TX -> MBZ
-+ .a4 = 0 // Using TX -> MBZ
-+ };
-+
-+ /* TODO pass all the information required by the spec */
-+ memset(retrieve_region, 0, sizeof(*retrieve_region));
-+ retrieve_region->global_handle = cookie;
-+
-+ thread_smccc(&args);
-+ if (args.a0 == FFA_ERROR /*TODO != FFA_MEM_RETRIEVE_RESP_64 */) {
-+ EMSG("Failed to fetch cookie %#"PRIx64, cookie);
-+ return NULL;
-+ }
-+
-+ return (void *)rx_buf;
-+}
-+
-+void thread_spmc_relinquish(uint64_t cookie)
-+{
-+ struct ffa_relinquish_descriptor *relinquish_desc = (void *)tx_buf;
-+
-+ struct thread_smc_args args = {
-+ .a0 = FFA_MEM_RELINQUISH,
-+ };
-+
-+ memset(relinquish_desc, 0, sizeof(*relinquish_desc));
-+ relinquish_desc->handle = cookie;
-+ relinquish_desc->flags = 0;
-+ /* TODO: Add endpoint details. */
-+ thread_smccc(&args);
-+ if (args.a0 != FFA_SUCCESS_32)
-+ EMSG("Failed to relinquish cookie %#"PRIx64, cookie);
-+}
-+
-+struct mobj_ffa *thread_spmc_populate_mobj_from_rx(uint64_t cookie)
-+{
-+ struct mem_transaction_descr *retrieve_desc;
-+ struct mem_region_descr *descr;
-+ struct mobj_ffa *mf;
-+ uint32_t num_pages;
-+
-+
-+ /* XXX Support single mem_region. */
-+ retrieve_desc = spmc_retrieve_req(cookie);
-+
-+ if (!retrieve_desc) {
-+ EMSG("Failed to retrieve cookie from rx buffer %#"PRIx64, cookie);
-+ return NULL;
-+ }
-+
-+ descr = (struct mem_region_descr *)
-+ ((uint8_t *)retrieve_desc +
-+ retrieve_desc->mem_accsess_descr_array[0].mem_region_offs);
-+
-+ num_pages = descr->total_page_count;
-+ mf = mobj_ffa_sel2_spmc_new(cookie, num_pages);
-+
-+ if (!mf)
-+ return NULL;
-+
-+ if (set_pages(descr->address_range_array,
-+ descr->address_range_count,
-+ num_pages, mf)) {
-+ mobj_ffa_sel2_spmc_delete(mf);
-+ return NULL;
-+
-+ }
-+
-+ return mf;
-+}
-+
-+static TEE_Result spmc_init(void)
-+{
-+ spmc_rxtx_map();
-+
-+ return TEE_SUCCESS;
-+}
-+service_init(spmc_init);
-+
-+#endif /*CFG_CORE_SEL2_SPMC*/
-diff --git a/core/arch/arm/kernel/thread_spmc_a64.S b/core/arch/arm/kernel/thread_spmc_a64.S
-index 3d57da4d..66f9d0b4 100644
---- a/core/arch/arm/kernel/thread_spmc_a64.S
-+++ b/core/arch/arm/kernel/thread_spmc_a64.S
-@@ -17,7 +17,8 @@
-
- FUNC thread_ffa_msg_wait , :
- mov_imm x0, FFA_MSG_WAIT /* FID */
-- mov x1, #FFA_TARGET_INFO_MBZ /* Target info MBZ */
-+ adr x1, thread_spmc_target_info
-+ ldr w1, [x1]
- mov x2, #FFA_PARAM_MBZ /* Param MBZ */
- mov x3, #FFA_PARAM_MBZ /* Param MBZ */
- mov x4, #FFA_PARAM_MBZ /* Param MBZ */
-diff --git a/core/arch/arm/mm/mobj_ffa.c b/core/arch/arm/mm/mobj_ffa.c
-index fd5e66ea..e2c585a2 100644
---- a/core/arch/arm/mm/mobj_ffa.c
-+++ b/core/arch/arm/mm/mobj_ffa.c
-@@ -19,8 +19,10 @@ struct mobj_ffa {
- tee_mm_entry_t *mm;
- struct refcount mapcount;
- uint16_t page_offset;
-+#ifdef CFG_CORE_SEL1_SPMC
- bool registered_by_cookie;
- bool unregistered_by_cookie;
-+#endif
- paddr_t pages[];
- };
-
-@@ -186,6 +188,24 @@ void mobj_ffa_sel1_spmc_delete(struct mobj_ffa *mf)
- }
- #endif /*CFG_CORE_SEL1_SPMC*/
-
-+#ifdef CFG_CORE_SEL2_SPMC
-+struct mobj_ffa *mobj_ffa_sel2_spmc_new(uint64_t cookie,
-+ unsigned int num_pages)
-+{
-+ struct mobj_ffa *mf = NULL;
-+
-+ mf = ffa_new(num_pages);
-+ if (mf)
-+ mf->cookie = cookie;
-+ return mf;
-+}
-+
-+void mobj_ffa_sel2_spmc_delete(struct mobj_ffa *mf)
-+{
-+ free(mf);
-+}
-+#endif /*CFG_CORE_SEL2_SPMC*/
-+
- TEE_Result mobj_ffa_add_pages_at(struct mobj_ffa *mf, unsigned int *idx,
- paddr_t pa, unsigned int num_pages)
- {
-@@ -234,7 +254,9 @@ static void unmap_helper(struct mobj_ffa *mf)
- }
- }
-
--TEE_Result mobj_ffa_unregister_by_cookie(uint64_t cookie)
-+
-+#ifdef CFG_CORE_SEL1_SPMC
-+TEE_Result mobj_ffa_sel1_spmc_reclaim(uint64_t cookie)
- {
- TEE_Result res = TEE_SUCCESS;
- struct mobj_ffa *mf = NULL;
-@@ -244,7 +266,7 @@ TEE_Result mobj_ffa_unregister_by_cookie(uint64_t cookie)
- mf = find_in_list(&shm_head, cmp_cookie, cookie);
- /*
- * If the mobj is found here it's still active and cannot be
-- * unregistered.
-+ * reclaimed.
- */
- if (mf) {
- DMSG("cookie %#"PRIx64" busy refc %u",
-@@ -252,24 +274,34 @@ TEE_Result mobj_ffa_unregister_by_cookie(uint64_t cookie)
- res = TEE_ERROR_BUSY;
- goto out;
- }
-+
- mf = find_in_list(&shm_inactive_head, cmp_cookie, cookie);
-+ if (!mf) {
-+ res = TEE_ERROR_ITEM_NOT_FOUND;
-+ goto out;
-+ }
- /*
-- * If the mobj isn't found or if it already has been unregistered.
-+ * If the mobj has been registered via mobj_ffa_get_by_cookie()
-+ * but not unregistered yet with mobj_ffa_unregister_by_cookie().
- */
-- if (!mf || mf->unregistered_by_cookie) {
-- res = TEE_ERROR_ITEM_NOT_FOUND;
-+ if (mf->registered_by_cookie && !mf->unregistered_by_cookie) {
-+ DMSG("cookie %#"PRIx64" busy", cookie);
-+ res = TEE_ERROR_BUSY;
- goto out;
- }
-- mf->unregistered_by_cookie = true;
-- res = TEE_SUCCESS;
-
-+ if (!pop_from_list(&shm_inactive_head, cmp_ptr, (vaddr_t)mf))
-+ panic();
-+ res = TEE_SUCCESS;
- out:
- cpu_spin_unlock_xrestore(&shm_lock, exceptions);
-+ if (!res)
-+ mobj_ffa_sel1_spmc_delete(mf);
- return res;
- }
-+#endif /*CFG_CORE_SEL1_SPMC*/
-
--#ifdef CFG_CORE_SEL1_SPMC
--TEE_Result mobj_ffa_sel1_spmc_reclaim(uint64_t cookie)
-+TEE_Result mobj_ffa_unregister_by_cookie(uint64_t cookie)
- {
- TEE_Result res = TEE_SUCCESS;
- struct mobj_ffa *mf = NULL;
-@@ -279,7 +311,7 @@ TEE_Result mobj_ffa_sel1_spmc_reclaim(uint64_t cookie)
- mf = find_in_list(&shm_head, cmp_cookie, cookie);
- /*
- * If the mobj is found here it's still active and cannot be
-- * reclaimed.
-+ * unregistered.
- */
- if (mf) {
- DMSG("cookie %#"PRIx64" busy refc %u",
-@@ -287,43 +319,42 @@ TEE_Result mobj_ffa_sel1_spmc_reclaim(uint64_t cookie)
- res = TEE_ERROR_BUSY;
- goto out;
- }
--
- mf = find_in_list(&shm_inactive_head, cmp_cookie, cookie);
-- if (!mf) {
-- res = TEE_ERROR_ITEM_NOT_FOUND;
-- goto out;
-- }
- /*
-- * If the mobj has been registered via mobj_ffa_get_by_cookie()
-- * but not unregistered yet with mobj_ffa_unregister_by_cookie().
-+ * If the mobj isn't found or if it already has been unregistered.
- */
-- if (mf->registered_by_cookie && !mf->unregistered_by_cookie) {
-- DMSG("cookie %#"PRIx64" busy", cookie);
-- res = TEE_ERROR_BUSY;
-+#ifdef CFG_CORE_SEL2_SPMC
-+ if (!mf) {
-+#else
-+ if (!mf || mf->unregistered_by_cookie) {
-+#endif
-+ res = TEE_ERROR_ITEM_NOT_FOUND;
- goto out;
- }
-
-- if (!pop_from_list(&shm_inactive_head, cmp_ptr, (vaddr_t)mf))
-- panic();
-+
-+#ifdef CFG_CORE_SEL2_SPMC
-+ mf = pop_from_list(&shm_inactive_head, cmp_cookie, cookie);
-+ mobj_ffa_sel2_spmc_delete(mf);
-+ thread_spmc_relinquish(cookie);
-+#else
-+ mf->unregistered_by_cookie = true;
-+#endif
- res = TEE_SUCCESS;
-+
- out:
- cpu_spin_unlock_xrestore(&shm_lock, exceptions);
-- if (!res)
-- mobj_ffa_sel1_spmc_delete(mf);
- return res;
- }
--#endif /*CFG_CORE_SEL1_SPMC*/
-
--struct mobj *mobj_ffa_get_by_cookie(uint64_t cookie, unsigned int internal_offs)
-+struct mobj *mobj_ffa_get_by_cookie(uint64_t cookie,
-+ unsigned int internal_offs)
- {
- struct mobj_ffa *mf = NULL;
- uint32_t exceptions = 0;
--
- if (internal_offs >= SMALL_PAGE_SIZE)
- return NULL;
--
- exceptions = cpu_spin_lock_xsave(&shm_lock);
--
- mf = find_in_list(&shm_head, cmp_cookie, cookie);
- if (mf) {
- if (mf->page_offset == internal_offs) {
-@@ -345,9 +376,19 @@ struct mobj *mobj_ffa_get_by_cookie(uint64_t cookie, unsigned int internal_offs)
- }
- } else {
- mf = pop_from_list(&shm_inactive_head, cmp_cookie, cookie);
-+#if defined(CFG_CORE_SEL2_SPMC)
-+ /* Try to retrieve it from the SPM at S-EL2 */
-+ if (mf)
-+ DMSG("cookie %#"PRIx64" resurrecting", cookie);
-+ if (!mf)
-+ EMSG("Populating mobj from rx buffer\n");
-+ mf = thread_spmc_populate_mobj_from_rx(cookie);
-+#endif
- if (mf) {
-+#if defined(CFG_CORE_SEL1_SPMC)
- mf->unregistered_by_cookie = false;
- mf->registered_by_cookie = true;
-+#endif
- assert(refcount_val(&mf->mobj.refc) == 0);
- refcount_set(&mf->mobj.refc, 1);
- refcount_set(&mf->mapcount, 0);
-@@ -358,15 +399,12 @@ struct mobj *mobj_ffa_get_by_cookie(uint64_t cookie, unsigned int internal_offs)
- SLIST_INSERT_HEAD(&shm_head, mf, link);
- }
- }
--
- cpu_spin_unlock_xrestore(&shm_lock, exceptions);
--
- if (!mf) {
- EMSG("Failed to get cookie %#"PRIx64" internal_offs %#x",
-- cookie, internal_offs);
-+ cookie, internal_offs);
- return NULL;
- }
--
- return &mf->mobj;
- }
-
-diff --git a/core/arch/arm/plat-vexpress/conf.mk b/core/arch/arm/plat-vexpress/conf.mk
-index 26b9f51e..dd6530a6 100644
---- a/core/arch/arm/plat-vexpress/conf.mk
-+++ b/core/arch/arm/plat-vexpress/conf.mk
-@@ -58,8 +58,13 @@ CFG_WITH_STATS ?= y
-
- ifeq ($(PLATFORM_FLAVOR),fvp)
- CFG_TEE_CORE_NB_CORE = 8
-+ifeq ($(CFG_CORE_SEL2_SPMC),y)
-+CFG_TZDRAM_START ?= 0x06280000
-+CFG_TZDRAM_SIZE ?= 0x01D80000
-+else
- CFG_TZDRAM_START ?= 0x06000000
- CFG_TZDRAM_SIZE ?= 0x02000000
-+endif
- CFG_SHMEM_START ?= 0x83000000
- CFG_SHMEM_SIZE ?= 0x00200000
- # DRAM1 is defined above 4G
---
-2.26.2
-
diff --git a/meta-arm-bsp/recipes-security/optee/files/optee-os/tc0/0004-core-fixes-to-align-with-upstream-hafnium.patch b/meta-arm-bsp/recipes-security/optee/files/optee-os/tc0/0004-core-fixes-to-align-with-upstream-hafnium.patch
deleted file mode 100644
index a36a510..0000000
--- a/meta-arm-bsp/recipes-security/optee/files/optee-os/tc0/0004-core-fixes-to-align-with-upstream-hafnium.patch
+++ /dev/null
@@ -1,188 +0,0 @@
-Upstream-Status: Pending [Not submitted to upstream yet]
-Signed-off-by: Arunachalam Ganapathy <arunachalam.ganapathy@arm.com>
-
-From 5ca96d9ff7fa5481282fb8f59a54d3cc91a1ae36 Mon Sep 17 00:00:00 2001
-From: Olivier Deprez <olivier.deprez@arm.com>
-Date: Thu, 1 Oct 2020 07:59:54 +0200
-Subject: [PATCH 1/5] core: fixes to align with upstream hafnium
-
-FF-A: fix call to thread_spmc_populate_mobj_from_rx
-
-FF-A: fix typos in thread_spmc.c
-
-FF-A: fix mem retrieve request
-
-FF-A. fix mem relinquish
-
-FF-A: call rx release from thread_spmc_populate_mobj_from_rx
-
-Change-Id: I38794b34bf17428d62218e30bdd0180f75498ed4
-Signed-off-by: Olivier Deprez <olivier.deprez@arm.com>
-Signed-off-by: Arunachalam Ganapathy <arunachalam.ganapathy@arm.com>
----
- core/arch/arm/kernel/thread_spmc.c | 52 +++++++++++++++++++++---------
- core/arch/arm/mm/mobj_ffa.c | 3 +-
- 2 files changed, 39 insertions(+), 16 deletions(-)
-
-diff --git a/core/arch/arm/kernel/thread_spmc.c b/core/arch/arm/kernel/thread_spmc.c
-index 3d7dc035..872221d6 100644
---- a/core/arch/arm/kernel/thread_spmc.c
-+++ b/core/arch/arm/kernel/thread_spmc.c
-@@ -48,7 +48,7 @@ struct mem_access_perm_descr {
- };
-
- /* Table 41: Endpoint memory access descriptor */
--struct mem_accsess_descr {
-+struct mem_access_descr {
- struct mem_access_perm_descr mem_access_perm_descr;
- uint32_t mem_region_offs;
- uint64_t reserved;
-@@ -64,7 +64,7 @@ struct mem_transaction_descr {
- uint64_t tag;
- uint32_t reserved1;
- uint32_t mem_access_descr_count;
-- struct mem_accsess_descr mem_accsess_descr_array[];
-+ struct mem_access_descr mem_access_descr_array[];
- };
-
- struct ffa_partition_info {
-@@ -453,8 +453,8 @@ static void handle_blocking_call(struct thread_smc_args *args)
- }
- }
-
--#if CFG_CORE_SEL1_SPMC
--static int get_acc_perms(struct mem_accsess_descr *mem_acc,
-+#ifdef CFG_CORE_SEL1_SPMC
-+static int get_acc_perms(struct mem_access_descr *mem_acc,
- unsigned int num_mem_accs, uint8_t *acc_perms,
- unsigned int *region_offs)
- {
-@@ -495,7 +495,7 @@ static int mem_share_init(void *buf, size_t blen, unsigned int *page_count,
-
- /* Check that the endpoint memory access descriptor array fits */
- num_mem_accs = READ_ONCE(descr->mem_access_descr_count);
-- if (MUL_OVERFLOW(sizeof(struct mem_accsess_descr), num_mem_accs, &n) ||
-+ if (MUL_OVERFLOW(sizeof(struct mem_access_descr), num_mem_accs, &n) ||
- ADD_OVERFLOW(sizeof(*descr), n, &n) || n > blen)
- return FFA_INVALID_PARAMETERS;
-
-@@ -503,7 +503,7 @@ static int mem_share_init(void *buf, size_t blen, unsigned int *page_count,
- return FFA_INVALID_PARAMETERS;
-
- /* Check that the access permissions matches what's expected */
-- if (get_acc_perms(descr->mem_accsess_descr_array,
-+ if (get_acc_perms(descr->mem_access_descr_array,
- num_mem_accs, &mem_acc_perm, ®ion_descr_offs) ||
- mem_acc_perm != exp_mem_acc_perm)
- return FFA_INVALID_PARAMETERS;
-@@ -1263,17 +1263,29 @@ static struct mem_transaction_descr *spmc_retrieve_req(uint64_t cookie)
- {
- struct mem_transaction_descr *retrieve_region = (void *)tx_buf;
-
-+ uint64_t size = sizeof(*retrieve_region) +
-+ 1 * sizeof(struct mem_access_descr);
- struct thread_smc_args args = {
- .a0 = FFA_MEM_RETRIEVE_REQ_64,
-- .a1 = sizeof(*retrieve_region), // Total Length
-- .a2 = sizeof(*retrieve_region), // Frag Length == Total length
-+ .a1 = size, // Total Length
-+ .a2 = size, // Frag Length == Total length
- .a3 = 0, // Address, Using TX -> MBZ
- .a4 = 0 // Using TX -> MBZ
- };
-
- /* TODO pass all the information required by the spec */
-- memset(retrieve_region, 0, sizeof(*retrieve_region));
-+ memset(retrieve_region, 0, size);
- retrieve_region->global_handle = cookie;
-+ retrieve_region->flags = 1;
-+ retrieve_region->mem_access_descr_count = 1;
-+ retrieve_region->mem_access_descr_array[0].mem_region_offs = 0;
-+ retrieve_region->mem_access_descr_array[0].reserved = 0;
-+ retrieve_region->mem_access_descr_array[0].mem_access_perm_descr =
-+ (struct mem_access_perm_descr) {
-+ .endpoint_id = my_sp_id,
-+ .access_perm = 0,
-+ .flags = 0
-+ };
-
- thread_smccc(&args);
- if (args.a0 == FFA_ERROR /*TODO != FFA_MEM_RETRIEVE_RESP_64 */) {
-@@ -1296,6 +1308,8 @@ void thread_spmc_relinquish(uint64_t cookie)
- relinquish_desc->handle = cookie;
- relinquish_desc->flags = 0;
- /* TODO: Add endpoint details. */
-+ relinquish_desc->endpoint_count = 1;
-+ relinquish_desc->endpoint_id_array[0] = my_sp_id;
- thread_smccc(&args);
- if (args.a0 != FFA_SUCCESS_32)
- EMSG("Failed to relinquish cookie %#"PRIx64, cookie);
-@@ -1303,11 +1317,14 @@ void thread_spmc_relinquish(uint64_t cookie)
-
- struct mobj_ffa *thread_spmc_populate_mobj_from_rx(uint64_t cookie)
- {
-+ struct mobj_ffa *ret = NULL;
- struct mem_transaction_descr *retrieve_desc;
- struct mem_region_descr *descr;
- struct mobj_ffa *mf;
- uint32_t num_pages;
--
-+ struct thread_smc_args ffa_rx_release_args = {
-+ .a0 = FFA_RX_RELEASE
-+ };
-
- /* XXX Support single mem_region. */
- retrieve_desc = spmc_retrieve_req(cookie);
-@@ -1319,23 +1336,28 @@ struct mobj_ffa *thread_spmc_populate_mobj_from_rx(uint64_t cookie)
-
- descr = (struct mem_region_descr *)
- ((uint8_t *)retrieve_desc +
-- retrieve_desc->mem_accsess_descr_array[0].mem_region_offs);
-+ retrieve_desc->mem_access_descr_array[0].mem_region_offs);
-
- num_pages = descr->total_page_count;
- mf = mobj_ffa_sel2_spmc_new(cookie, num_pages);
-
- if (!mf)
-- return NULL;
-+ goto out;
-
- if (set_pages(descr->address_range_array,
- descr->address_range_count,
- num_pages, mf)) {
- mobj_ffa_sel2_spmc_delete(mf);
-- return NULL;
--
-+ goto out;
- }
-
-- return mf;
-+ ret = mf;
-+
-+out:
-+ /* Release RX buffer after the mem retrieve request. */
-+ thread_smccc(&ffa_rx_release_args);
-+
-+ return ret;
- }
-
- static TEE_Result spmc_init(void)
-diff --git a/core/arch/arm/mm/mobj_ffa.c b/core/arch/arm/mm/mobj_ffa.c
-index e2c585a2..8e334f04 100644
---- a/core/arch/arm/mm/mobj_ffa.c
-+++ b/core/arch/arm/mm/mobj_ffa.c
-@@ -380,9 +380,10 @@ struct mobj *mobj_ffa_get_by_cookie(uint64_t cookie,
- /* Try to retrieve it from the SPM at S-EL2 */
- if (mf)
- DMSG("cookie %#"PRIx64" resurrecting", cookie);
-- if (!mf)
-+ if (!mf) {
- EMSG("Populating mobj from rx buffer\n");
- mf = thread_spmc_populate_mobj_from_rx(cookie);
-+ }
- #endif
- if (mf) {
- #if defined(CFG_CORE_SEL1_SPMC)
---
-2.26.2
-
diff --git a/meta-arm-bsp/recipes-security/optee/files/optee-os/tc0/0005-core-arm-Total-Compute-platform-support.patch b/meta-arm-bsp/recipes-security/optee/files/optee-os/tc0/0005-core-arm-Total-Compute-platform-support.patch
deleted file mode 100644
index 52270ec..0000000
--- a/meta-arm-bsp/recipes-security/optee/files/optee-os/tc0/0005-core-arm-Total-Compute-platform-support.patch
+++ /dev/null
@@ -1,187 +0,0 @@
-Upstream-Status: Pending [Not submitted to upstream yet]
-Signed-off-by: Arunachalam Ganapathy <arunachalam.ganapathy@arm.com>
-
-From 0c427d7f164a46862f6267b616d4ade28865b57a Mon Sep 17 00:00:00 2001
-From: Arunachalam Ganapathy <arunachalam.ganapathy@arm.com>
-Date: Wed, 15 Jul 2020 12:51:04 +0100
-Subject: [PATCH 2/5] core: arm: Total Compute platform support
-
-Initial support for Total Compute platform[1]
- - defines tc0 platform configuration
- - enables CFG_ARM64_core by default
- - defines TZCDRAM_BASE
-
-Link: [1] https://community.arm.com/developer/tools-software/oss-platforms/w/docs/606/total-compute
-
-Change-Id: Icddafbdfac40bb6ff3c367910acf632688343721
-Signed-off-by: Arunachalam Ganapathy <arunachalam.ganapathy@arm.com>
----
- core/arch/arm/plat-totalcompute/conf.mk | 32 +++++++++++
- core/arch/arm/plat-totalcompute/main.c | 55 +++++++++++++++++++
- .../arm/plat-totalcompute/platform_config.h | 43 +++++++++++++++
- core/arch/arm/plat-totalcompute/sub.mk | 2 +
- 4 files changed, 132 insertions(+)
- create mode 100644 core/arch/arm/plat-totalcompute/conf.mk
- create mode 100644 core/arch/arm/plat-totalcompute/main.c
- create mode 100644 core/arch/arm/plat-totalcompute/platform_config.h
- create mode 100644 core/arch/arm/plat-totalcompute/sub.mk
-
-diff --git a/core/arch/arm/plat-totalcompute/conf.mk b/core/arch/arm/plat-totalcompute/conf.mk
-new file mode 100644
-index 00000000..4fe894c7
---- /dev/null
-+++ b/core/arch/arm/plat-totalcompute/conf.mk
-@@ -0,0 +1,32 @@
-+PLATFORM_FLAVOR ?= tc0
-+
-+ifeq ($(PLATFORM_FLAVOR),tc0)
-+include core/arch/arm/cpu/cortex-armv8-0.mk
-+platform-debugger-arm := 1
-+endif
-+
-+$(call force,CFG_WITH_ARM_TRUSTED_FW,y)
-+$(call force,CFG_GENERIC_BOOT,y)
-+$(call force,CFG_GIC,y)
-+$(call force,CFG_ARM_GICV3,y)
-+$(call force,CFG_PL011,y)
-+$(call force,CFG_PM_STUBS,y)
-+$(call force,CFG_SECURE_TIME_SOURCE_CNTPCT,y)
-+$(call force,CFG_ARM64_core,y)
-+$(call force,CFG_WITH_LPAE,y)
-+
-+ifeq ($(platform-debugger-arm),1)
-+# ARM debugger needs this
-+platform-cflags-debug-info = -gdwarf-2
-+platform-aflags-debug-info = -gdwarf-2
-+endif
-+
-+ifeq ($(PLATFORM_FLAVOR),tc0)
-+CFG_TEE_CORE_NB_CORE = 4
-+
-+CFG_TZDRAM_START ?= 0xff000000
-+CFG_TZDRAM_SIZE ?= 0x01000000
-+
-+CFG_SHMEM_START ?= 0xfce00000
-+CFG_SHMEM_SIZE ?= 0x00200000
-+endif
-diff --git a/core/arch/arm/plat-totalcompute/main.c b/core/arch/arm/plat-totalcompute/main.c
-new file mode 100644
-index 00000000..e775abfc
---- /dev/null
-+++ b/core/arch/arm/plat-totalcompute/main.c
-@@ -0,0 +1,55 @@
-+/*
-+ * Copyright (c) 2020, Arm Limited. All rights reserved.
-+ *
-+ * SPDX-License-Identifier: BSD-3-Clause
-+ */
-+
-+#include <arm.h>
-+#include <console.h>
-+#include <drivers/gic.h>
-+#include <drivers/pl011.h>
-+#include <initcall.h>
-+#include <kernel/boot.h>
-+#include <kernel/interrupt.h>
-+#include <kernel/misc.h>
-+#include <kernel/panic.h>
-+
-+#include <mm/core_mmu.h>
-+#include <platform_config.h>
-+
-+static struct gic_data gic_data __nex_bss;
-+static struct pl011_data console_data __nex_bss;
-+
-+register_phys_mem_pgdir(MEM_AREA_IO_SEC, CONSOLE_UART_BASE, PL011_REG_SIZE);
-+register_phys_mem_pgdir(MEM_AREA_IO_SEC, GICD_BASE, GIC_DIST_REG_SIZE);
-+
-+register_ddr(DRAM0_BASE, DRAM0_SIZE);
-+
-+void main_init_gic(void)
-+{
-+ vaddr_t gicc_base;
-+
-+ gicc_base = (vaddr_t)phys_to_virt(GIC_BASE + GICC_OFFSET,
-+ MEM_AREA_IO_SEC);
-+ if (!gicc_base)
-+ panic();
-+
-+ /*
-+ * On ARMv8, GIC configuration is initialized in ARM-TF
-+ * gicd base address is same as gicc_base.
-+ */
-+ gic_init_base_addr(&gic_data, gicc_base, gicc_base);
-+ itr_init(&gic_data.chip);
-+}
-+
-+void itr_core_handler(void)
-+{
-+ gic_it_handle(&gic_data);
-+}
-+
-+void console_init(void)
-+{
-+ pl011_init(&console_data, CONSOLE_UART_BASE, CONSOLE_UART_CLK_IN_HZ,
-+ CONSOLE_UART_BAUDRATE);
-+ register_serial_console(&console_data.chip);
-+}
-diff --git a/core/arch/arm/plat-totalcompute/platform_config.h b/core/arch/arm/plat-totalcompute/platform_config.h
-new file mode 100644
-index 00000000..dfc58857
---- /dev/null
-+++ b/core/arch/arm/plat-totalcompute/platform_config.h
-@@ -0,0 +1,43 @@
-+/*
-+ * Copyright (c) 2020, Arm Limited. All rights reserved.
-+ *
-+ * SPDX-License-Identifier: BSD-3-Clause
-+ */
-+
-+#ifndef PLATFORM_CONFIG_H
-+#define PLATFORM_CONFIG_H
-+
-+#include <mm/generic_ram_layout.h>
-+
-+/* Make stacks aligned to data cache line length */
-+#define STACK_ALIGNMENT 64
-+
-+#if defined(PLATFORM_FLAVOR_tc0)
-+#define GIC_BASE 0x30000000
-+#define GICD_OFFSET 0x0
-+#define GICC_OFFSET 0x0
-+
-+#define UART0_BASE 0x7FF70000
-+#define UART1_BASE 0x7FF80000
-+
-+#define CONSOLE_UART_BASE UART0_BASE
-+
-+#define DRAM0_BASE 0x80000000
-+#define DRAM0_SIZE 0x7d000000
-+
-+#define TZCDRAM_BASE 0xff000000
-+#define TZCDRAM_SIZE 0x01000000
-+
-+#else
-+#error "Unknown platform flavor"
-+#endif
-+
-+#ifdef GIC_BASE
-+#define GICD_BASE (GIC_BASE + GICD_OFFSET)
-+#define GICC_BASE (GIC_BASE + GICC_OFFSET)
-+#endif
-+
-+#define CONSOLE_UART_BAUDRATE 115200
-+#define CONSOLE_UART_CLK_IN_HZ 7372800
-+
-+#endif /* PLATFORM_CONFIG_H */
-diff --git a/core/arch/arm/plat-totalcompute/sub.mk b/core/arch/arm/plat-totalcompute/sub.mk
-new file mode 100644
-index 00000000..8ddc2fd4
---- /dev/null
-+++ b/core/arch/arm/plat-totalcompute/sub.mk
-@@ -0,0 +1,2 @@
-+global-incdirs-y += .
-+srcs-y += main.c
---
-2.26.2
-
diff --git a/meta-arm-bsp/recipes-security/optee/files/optee-os/tc0/0006-plat-totalcompute-Add-support-for-S-EL2-SPMC.patch b/meta-arm-bsp/recipes-security/optee/files/optee-os/tc0/0006-plat-totalcompute-Add-support-for-S-EL2-SPMC.patch
deleted file mode 100644
index 3070d5f..0000000
--- a/meta-arm-bsp/recipes-security/optee/files/optee-os/tc0/0006-plat-totalcompute-Add-support-for-S-EL2-SPMC.patch
+++ /dev/null
@@ -1,108 +0,0 @@
-Upstream-Status: Pending [Not submitted to upstream yet]
-Signed-off-by: Arunachalam Ganapathy <arunachalam.ganapathy@arm.com>
-
-From 8c21a8c7ac92839f36f83ebff9a208f24302c780 Mon Sep 17 00:00:00 2001
-From: Arunachalam Ganapathy <arunachalam.ganapathy@arm.com>
-Date: Mon, 16 Nov 2020 17:29:09 +0000
-Subject: [PATCH 3/5] plat-totalcompute: Add support for S-EL2 SPMC
-
-This patch adds CFG_CORE_SEL2_SPMC support. Defines CFG_TZDRAM_START
-address with memory region reserved for SPMC. Adds secondary cpu boot
-request handler.
-
-Change-Id: I3f274c7bb6b7df2706ea81aee0f2a8f8f39c1d80
-Signed-off-by: Arunachalam Ganapathy <arunachalam.ganapathy@arm.com>
----
- core/arch/arm/plat-totalcompute/conf.mk | 5 ++
- core/arch/arm/plat-totalcompute/sub.mk | 3 ++
- core/arch/arm/plat-totalcompute/tc0_spmc_pm.c | 50 +++++++++++++++++++
- 3 files changed, 58 insertions(+)
- create mode 100644 core/arch/arm/plat-totalcompute/tc0_spmc_pm.c
-
-diff --git a/core/arch/arm/plat-totalcompute/conf.mk b/core/arch/arm/plat-totalcompute/conf.mk
-index 4fe894c7..34095acf 100644
---- a/core/arch/arm/plat-totalcompute/conf.mk
-+++ b/core/arch/arm/plat-totalcompute/conf.mk
-@@ -24,8 +24,13 @@ endif
- ifeq ($(PLATFORM_FLAVOR),tc0)
- CFG_TEE_CORE_NB_CORE = 4
-
-+ifeq ($(CFG_CORE_SEL2_SPMC),y)
-+CFG_TZDRAM_START ?= 0xfd281000
-+CFG_TZDRAM_SIZE ?= 0x01d7f000
-+else
- CFG_TZDRAM_START ?= 0xff000000
- CFG_TZDRAM_SIZE ?= 0x01000000
-+endif
-
- CFG_SHMEM_START ?= 0xfce00000
- CFG_SHMEM_SIZE ?= 0x00200000
-diff --git a/core/arch/arm/plat-totalcompute/sub.mk b/core/arch/arm/plat-totalcompute/sub.mk
-index 8ddc2fd4..ffd76ee9 100644
---- a/core/arch/arm/plat-totalcompute/sub.mk
-+++ b/core/arch/arm/plat-totalcompute/sub.mk
-@@ -1,2 +1,5 @@
- global-incdirs-y += .
- srcs-y += main.c
-+ifeq ($(CFG_CORE_FFA),y)
-+srcs-y += tc0_spmc_pm.c
-+endif
-diff --git a/core/arch/arm/plat-totalcompute/tc0_spmc_pm.c b/core/arch/arm/plat-totalcompute/tc0_spmc_pm.c
-new file mode 100644
-index 00000000..8e59a8cc
---- /dev/null
-+++ b/core/arch/arm/plat-totalcompute/tc0_spmc_pm.c
-@@ -0,0 +1,50 @@
-+// SPDX-License-Identifier: BSD-2-Clause
-+/*
-+ * Copyright (c) 2020, Arm Limited
-+ */
-+
-+#include <arm.h>
-+#include <kernel/boot.h>
-+#include <ffa.h>
-+#include <sm/psci.h>
-+
-+/*
-+ * Lookup table of core and cluster affinities on the TC0. In the absence of a
-+ * DT that provides the same information, this table is used to initialise
-+ * OP-TEE on secondary cores.
-+ */
-+static const uint64_t core_clus_aff_array[] = {
-+ 0x0000, /* Cluster 0 Cpu 0 */
-+ 0x0001, /* Cluster 0 Cpu 1 */
-+ 0x0002, /* Cluster 0 Cpu 2 */
-+ 0x0003 /* Cluster 0 Cpu 3 */
-+};
-+
-+void ffa_secondary_cpu_boot_req(vaddr_t secondary_ep, uint64_t cookie)
-+{
-+ unsigned long mpidr = read_mpidr();
-+ unsigned int aff_shift = 0;
-+ unsigned long a1 = 0;
-+ unsigned int cnt = 0;
-+ int32_t ret = 0;
-+
-+ if (mpidr & MPIDR_MT_MASK)
-+ aff_shift = MPIDR_CLUSTER_SHIFT;
-+
-+ for (cnt = 0; cnt < ARRAY_SIZE(core_clus_aff_array); cnt++) {
-+ /* Clear out the affinity fields until level 2 */
-+ a1 = mpidr & ~(unsigned long)MPIDR_AARCH32_AFF_MASK;
-+
-+ /* Create an mpidr from core_clus_aff_array */
-+ a1 |= core_clus_aff_array[cnt] << aff_shift;
-+
-+ /* Invoke the PSCI_CPU_ON_SMC64 function */
-+ ret = thread_smc(PSCI_CPU_ON_SMC64, a1, secondary_ep, cookie);
-+
-+ if (ret != PSCI_RET_SUCCESS)
-+ EMSG("PSCI_CPU_ON op on mpidr 0x%lx failed %"PRId32,
-+ a1, ret);
-+ else
-+ DMSG("PSCI_CPU_ON op on mpidr 0x%lx done", a1);
-+ }
-+}
---
-2.26.2
-
diff --git a/meta-arm-bsp/recipes-security/optee/files/optee-os/tc0/0007-plat-totalcompute-add-optee-manifest-file-and-sp-lay.patch b/meta-arm-bsp/recipes-security/optee/files/optee-os/tc0/0007-plat-totalcompute-add-optee-manifest-file-and-sp-lay.patch
deleted file mode 100644
index 6535496..0000000
--- a/meta-arm-bsp/recipes-security/optee/files/optee-os/tc0/0007-plat-totalcompute-add-optee-manifest-file-and-sp-lay.patch
+++ /dev/null
@@ -1,73 +0,0 @@
-Upstream-Status: Pending [Not submitted to upstream yet]
-Signed-off-by: Arunachalam Ganapathy <arunachalam.ganapathy@arm.com>
-
-From 582bf63102ec37dadff2147dcebcb62783dcf377 Mon Sep 17 00:00:00 2001
-From: Arunachalam Ganapathy <arunachalam.ganapathy@arm.com>
-Date: Mon, 16 Nov 2020 18:03:21 +0000
-Subject: [PATCH 4/5] plat-totalcompute: add optee manifest file and sp layout
-
-For S-EL2 SPMC, add optee manifest file and sp layout file
-
-Change-Id: Ic3179987decf4e017cd4a0ad91b3beeea2bd6ca1
-Signed-off-by: Arunachalam Ganapathy <arunachalam.ganapathy@arm.com>
----
- .../arm/plat-totalcompute/optee_manifest.dts | 33 +++++++++++++++++++
- .../arch/arm/plat-totalcompute/sp_layout.json | 6 ++++
- 2 files changed, 39 insertions(+)
- create mode 100644 core/arch/arm/plat-totalcompute/optee_manifest.dts
- create mode 100644 core/arch/arm/plat-totalcompute/sp_layout.json
-
-diff --git a/core/arch/arm/plat-totalcompute/optee_manifest.dts b/core/arch/arm/plat-totalcompute/optee_manifest.dts
-new file mode 100644
-index 00000000..4e60cbe1
---- /dev/null
-+++ b/core/arch/arm/plat-totalcompute/optee_manifest.dts
-@@ -0,0 +1,33 @@
-+/*
-+ * Copyright (c) 2020, Arm Limited. All rights reserved.
-+ *
-+ * SPDX-License-Identifier: BSD-3-Clause
-+ *
-+ * This file is a Partition Manifest (PM) for a minimal Secure Partition (SP)
-+ * that has additional optional properties defined.
-+ *
-+ */
-+
-+/dts-v1/;
-+
-+/ {
-+ compatible = "arm,ffa-manifest-1.0";
-+
-+ /* Properties */
-+ description = "op-tee";
-+ ffa-version = <0x00010000>; /* 31:16 - Major, 15:0 - Minor */
-+ uuid = <0x486178e0 0xe7f811e3 0xbc5e0002 0xa5d5c51b>;
-+ id = <1>;
-+ execution-ctx-count = <4>;
-+ exception-level = <2>; /* S-EL1 */
-+ execution-state = <0>; /* AARCH64 */
-+ load-address = <0xfd280000>;
-+ entrypoint-offset = <0x1000>;
-+ xlat-granule = <0>; /* 4KiB */
-+ boot-order = <0>;
-+ messaging-method = <0>; /* Direct messaging only */
-+ run-time-model = <1>; /* Run to completion */
-+
-+ /* Boot protocol */
-+ gp-register-num = <0x0>;
-+};
-diff --git a/core/arch/arm/plat-totalcompute/sp_layout.json b/core/arch/arm/plat-totalcompute/sp_layout.json
-new file mode 100644
-index 00000000..05bc7851
---- /dev/null
-+++ b/core/arch/arm/plat-totalcompute/sp_layout.json
-@@ -0,0 +1,6 @@
-+{
-+ "op-tee" : {
-+ "image": "tee-pager_v2.bin",
-+ "pm": "optee_manifest.dts"
-+ }
-+}
---
-2.26.2
-
diff --git a/meta-arm-bsp/recipes-security/optee/files/optee-os/tc0/0008-plat-totalcompute-define-tzdram-start-address-for-S-.patch b/meta-arm-bsp/recipes-security/optee/files/optee-os/tc0/0008-plat-totalcompute-define-tzdram-start-address-for-S-.patch
deleted file mode 100644
index 015bdc9..0000000
--- a/meta-arm-bsp/recipes-security/optee/files/optee-os/tc0/0008-plat-totalcompute-define-tzdram-start-address-for-S-.patch
+++ /dev/null
@@ -1,36 +0,0 @@
-Upstream-Status: Pending [Not submitted to upstream yet]
-Signed-off-by: Arunachalam Ganapathy <arunachalam.ganapathy@arm.com>
-
-From 1827607c6381339d051a36a84d749c3a50e3463d Mon Sep 17 00:00:00 2001
-From: Arunachalam Ganapathy <arunachalam.ganapathy@arm.com>
-Date: Mon, 16 Nov 2020 17:38:07 +0000
-Subject: [PATCH 5/5] plat-totalcompute: define tzdram start address for S-EL1
- SPMC config
-
-Define TZDRAM_START for CFG_CORE_SEL1_SPMC config
-
-Change-Id: I71aaa92a0ecdb791802336ca31ab52e97ee52955
-Signed-off-by: Arunachalam Ganapathy <arunachalam.ganapathy@arm.com>
----
- core/arch/arm/plat-totalcompute/conf.mk | 5 ++++-
- 1 file changed, 4 insertions(+), 1 deletion(-)
-
-diff --git a/core/arch/arm/plat-totalcompute/conf.mk b/core/arch/arm/plat-totalcompute/conf.mk
-index 34095acf..d330eb92 100644
---- a/core/arch/arm/plat-totalcompute/conf.mk
-+++ b/core/arch/arm/plat-totalcompute/conf.mk
-@@ -24,7 +24,10 @@ endif
- ifeq ($(PLATFORM_FLAVOR),tc0)
- CFG_TEE_CORE_NB_CORE = 4
-
--ifeq ($(CFG_CORE_SEL2_SPMC),y)
-+ifeq ($(CFG_CORE_SEL1_SPMC),y)
-+CFG_TZDRAM_START ?= 0xfd000000
-+CFG_TZDRAM_SIZE ?= 0x02000000
-+else ifeq ($(CFG_CORE_SEL2_SPMC),y)
- CFG_TZDRAM_START ?= 0xfd281000
- CFG_TZDRAM_SIZE ?= 0x01d7f000
- else
---
-2.26.2
-
diff --git a/meta-arm-bsp/recipes-security/optee/files/optee-os/tc0/0009-plat-totalcompute-add-Theodul-DSU-support.patch b/meta-arm-bsp/recipes-security/optee/files/optee-os/tc0/0009-plat-totalcompute-add-Theodul-DSU-support.patch
deleted file mode 100644
index e52a9d0..0000000
--- a/meta-arm-bsp/recipes-security/optee/files/optee-os/tc0/0009-plat-totalcompute-add-Theodul-DSU-support.patch
+++ /dev/null
@@ -1,93 +0,0 @@
-Upstream-Status: Pending [Not submitted to upstream yet]
-Signed-off-by: Arunachalam Ganapathy <arunachalam.ganapathy@arm.com>
-
-From 3563e39d66404ff2415d29c4018757a85cd0ad97 Mon Sep 17 00:00:00 2001
-From: Arunachalam Ganapathy <arunachalam.ganapathy@arm.com>
-Date: Wed, 13 Jan 2021 13:49:54 +0000
-Subject: [PATCH 1/3] plat-totalcompute: add Theodul DSU support
-
-- Change CPU count from 4 to 8
-- Set heap size to 128K
-- In debug print, change EMSG to DMSG
-
-Change-Id: Ic426f5e08ac4e7ce1be37333486c75a3228e3415
-Signed-off-by: Arunachalam Ganapathy <arunachalam.ganapathy@arm.com>
----
- core/arch/arm/mm/mobj_ffa.c | 2 +-
- core/arch/arm/plat-totalcompute/conf.mk | 4 +++-
- core/arch/arm/plat-totalcompute/optee_manifest.dts | 2 +-
- core/arch/arm/plat-totalcompute/tc0_spmc_pm.c | 10 +++++++++-
- 4 files changed, 14 insertions(+), 4 deletions(-)
-
-diff --git a/core/arch/arm/mm/mobj_ffa.c b/core/arch/arm/mm/mobj_ffa.c
-index 8e334f04..500404c3 100644
---- a/core/arch/arm/mm/mobj_ffa.c
-+++ b/core/arch/arm/mm/mobj_ffa.c
-@@ -381,7 +381,7 @@ struct mobj *mobj_ffa_get_by_cookie(uint64_t cookie,
- if (mf)
- DMSG("cookie %#"PRIx64" resurrecting", cookie);
- if (!mf) {
-- EMSG("Populating mobj from rx buffer\n");
-+ DMSG("Populating mobj from rx: %#"PRIx64"", cookie);
- mf = thread_spmc_populate_mobj_from_rx(cookie);
- }
- #endif
-diff --git a/core/arch/arm/plat-totalcompute/conf.mk b/core/arch/arm/plat-totalcompute/conf.mk
-index d330eb92..c35437aa 100644
---- a/core/arch/arm/plat-totalcompute/conf.mk
-+++ b/core/arch/arm/plat-totalcompute/conf.mk
-@@ -22,7 +22,9 @@ platform-aflags-debug-info = -gdwarf-2
- endif
-
- ifeq ($(PLATFORM_FLAVOR),tc0)
--CFG_TEE_CORE_NB_CORE = 4
-+CFG_TEE_CORE_NB_CORE = 8
-+
-+CFG_CORE_HEAP_SIZE ?= 131072
-
- ifeq ($(CFG_CORE_SEL1_SPMC),y)
- CFG_TZDRAM_START ?= 0xfd000000
-diff --git a/core/arch/arm/plat-totalcompute/optee_manifest.dts b/core/arch/arm/plat-totalcompute/optee_manifest.dts
-index 4e60cbe1..60cb5957 100644
---- a/core/arch/arm/plat-totalcompute/optee_manifest.dts
-+++ b/core/arch/arm/plat-totalcompute/optee_manifest.dts
-@@ -18,7 +18,7 @@
- ffa-version = <0x00010000>; /* 31:16 - Major, 15:0 - Minor */
- uuid = <0x486178e0 0xe7f811e3 0xbc5e0002 0xa5d5c51b>;
- id = <1>;
-- execution-ctx-count = <4>;
-+ execution-ctx-count = <8>;
- exception-level = <2>; /* S-EL1 */
- execution-state = <0>; /* AARCH64 */
- load-address = <0xfd280000>;
-diff --git a/core/arch/arm/plat-totalcompute/tc0_spmc_pm.c b/core/arch/arm/plat-totalcompute/tc0_spmc_pm.c
-index 8e59a8cc..3fb32823 100644
---- a/core/arch/arm/plat-totalcompute/tc0_spmc_pm.c
-+++ b/core/arch/arm/plat-totalcompute/tc0_spmc_pm.c
-@@ -17,7 +17,11 @@ static const uint64_t core_clus_aff_array[] = {
- 0x0000, /* Cluster 0 Cpu 0 */
- 0x0001, /* Cluster 0 Cpu 1 */
- 0x0002, /* Cluster 0 Cpu 2 */
-- 0x0003 /* Cluster 0 Cpu 3 */
-+ 0x0003, /* Cluster 0 Cpu 3 */
-+ 0x0004, /* Cluster 0 Cpu 4 */
-+ 0x0005, /* Cluster 0 Cpu 5 */
-+ 0x0006, /* Cluster 0 Cpu 6 */
-+ 0x0007 /* Cluster 0 Cpu 7 */
- };
-
- void ffa_secondary_cpu_boot_req(vaddr_t secondary_ep, uint64_t cookie)
-@@ -38,6 +42,10 @@ void ffa_secondary_cpu_boot_req(vaddr_t secondary_ep, uint64_t cookie)
- /* Create an mpidr from core_clus_aff_array */
- a1 |= core_clus_aff_array[cnt] << aff_shift;
-
-+ /* Ignore current cpu */
-+ if (a1 == mpidr)
-+ continue;
-+
- /* Invoke the PSCI_CPU_ON_SMC64 function */
- ret = thread_smc(PSCI_CPU_ON_SMC64, a1, secondary_ep, cookie);
-
---
-2.29.2
-
diff --git a/meta-arm-bsp/recipes-security/optee/files/optee-os/tc0/0010-WIP-OP-TEE-SP-declare-device-regions-in-manifest.patch b/meta-arm-bsp/recipes-security/optee/files/optee-os/tc0/0010-WIP-OP-TEE-SP-declare-device-regions-in-manifest.patch
deleted file mode 100644
index fbc5161..0000000
--- a/meta-arm-bsp/recipes-security/optee/files/optee-os/tc0/0010-WIP-OP-TEE-SP-declare-device-regions-in-manifest.patch
+++ /dev/null
@@ -1,47 +0,0 @@
-Upstream-Status: Pending [Not submitted to upstream yet]
-Signed-off-by: Arunachalam Ganapathy <arunachalam.ganapathy@arm.com>
-
-From fd325f731da694057a2738411faa2ccbeea71778 Mon Sep 17 00:00:00 2001
-From: Olivier Deprez <olivier.deprez@arm.com>
-Date: Thu, 3 Dec 2020 22:29:37 +0100
-Subject: [PATCH 2/3] WIP OP-TEE SP declare device regions in manifest
-
-Secure Partitions must declare peripherals they access such
-that the SPMC maps IO regions in SP's Stage-2 translation
-regime. OP-TEE currently directly accesses the GIC Distributor
-and the UART0 peripheral hence declare those device regions in
-OP-TEE's manifest.
-
-Change-Id: I1fda46e5cf17153dfaf499042dceff325729d041
-Signed-off-by: Olivier Deprez <olivier.deprez@arm.com>
----
- .../arch/arm/plat-totalcompute/optee_manifest.dts | 15 +++++++++++++++
- 1 file changed, 15 insertions(+)
-
-diff --git a/core/arch/arm/plat-totalcompute/optee_manifest.dts b/core/arch/arm/plat-totalcompute/optee_manifest.dts
-index 60cb5957..cdc28d98 100644
---- a/core/arch/arm/plat-totalcompute/optee_manifest.dts
-+++ b/core/arch/arm/plat-totalcompute/optee_manifest.dts
-@@ -30,4 +30,19 @@
-
- /* Boot protocol */
- gp-register-num = <0x0>;
-+
-+ device-regions {
-+ compatible = "arm,ffa-manifest-device-regions";
-+ uart0 {
-+ base-address = <0x00000000 0x7ff70000>;
-+ pages-count = <1>;
-+ attributes = <0x3>; /* read-write */
-+ };
-+
-+ gicd {
-+ base-address = <0x00000000 0x30000000>;
-+ pages-count = <16>;
-+ attributes = <0x3>; /* read-write */
-+ };
-+ };
- };
---
-2.29.2
-
diff --git a/meta-arm-bsp/recipes-security/optee/files/optee-os/tc0/0011-WIP-OP-TEE-SP-use-CNTVCT-in-place-of-CNTVCT.patch b/meta-arm-bsp/recipes-security/optee/files/optee-os/tc0/0011-WIP-OP-TEE-SP-use-CNTVCT-in-place-of-CNTVCT.patch
deleted file mode 100644
index 323ace7..0000000
--- a/meta-arm-bsp/recipes-security/optee/files/optee-os/tc0/0011-WIP-OP-TEE-SP-use-CNTVCT-in-place-of-CNTVCT.patch
+++ /dev/null
@@ -1,173 +0,0 @@
-Upstream-Status: Pending [Not submitted to upstream yet]
-Signed-off-by: Arunachalam Ganapathy <arunachalam.ganapathy@arm.com>
-
-From 85110aaf32b6d3b19fdca301f7a07a4683825802 Mon Sep 17 00:00:00 2001
-From: Olivier Deprez <olivier.deprez@arm.com>
-Date: Thu, 3 Dec 2020 17:33:09 +0100
-Subject: [PATCH 3/3] WIP OP-TEE SP use CNTVCT in place of CNTVCT
-
-The SPMC forbids access to the physical counter and Secure Partitions
-shall rather access the virtual counter (for which virtual offset is
-set to 0). More information at [1].
-
-[1] https://lists.trustedfirmware.org/pipermail/hafnium/2020-December/000092.html
-
-Change-Id: Ifab083921fa12154cafc31bd80ce91fa8da0db82
-Signed-off-by: Olivier Deprez <olivier.deprez@arm.com>
----
- core/arch/arm/include/arm64.h | 2 +-
- core/arch/arm/include/kernel/delay.h | 4 ++--
- core/arch/arm/kernel/arm32_sysreg.txt | 2 +-
- core/arch/arm/kernel/tee_time_arm_cntpct.c | 4 ++--
- core/kernel/tee_ta_manager.c | 4 ++--
- lib/libutee/arch/arm/arm32_user_sysreg.txt | 2 +-
- lib/libutee/include/arm64_user_sysreg.h | 2 +-
- lib/libutils/ext/ftrace/ftrace.c | 6 +++---
- 8 files changed, 13 insertions(+), 13 deletions(-)
-
-diff --git a/core/arch/arm/include/arm64.h b/core/arch/arm/include/arm64.h
-index 40a6b113..46c5431f 100644
---- a/core/arch/arm/include/arm64.h
-+++ b/core/arch/arm/include/arm64.h
-@@ -322,7 +322,7 @@ DEFINE_U32_REG_READ_FUNC(sctlr_el1)
-
- /* ARM Generic timer functions */
- DEFINE_REG_READ_FUNC_(cntfrq, uint32_t, cntfrq_el0)
--DEFINE_REG_READ_FUNC_(cntpct, uint64_t, cntpct_el0)
-+DEFINE_REG_READ_FUNC_(cntvct, uint64_t, cntvct_el0)
- DEFINE_REG_READ_FUNC_(cntkctl, uint32_t, cntkctl_el1)
- DEFINE_REG_WRITE_FUNC_(cntkctl, uint32_t, cntkctl_el1)
- DEFINE_REG_READ_FUNC_(cntps_ctl, uint32_t, cntps_ctl_el1)
-diff --git a/core/arch/arm/include/kernel/delay.h b/core/arch/arm/include/kernel/delay.h
-index 00510059..34629ba2 100644
---- a/core/arch/arm/include/kernel/delay.h
-+++ b/core/arch/arm/include/kernel/delay.h
-@@ -44,12 +44,12 @@ static inline uint64_t arm_cnt_us2cnt(uint32_t us)
-
- static inline uint64_t timeout_init_us(uint32_t us)
- {
-- return read_cntpct() + arm_cnt_us2cnt(us);
-+ return read_cntvct() + arm_cnt_us2cnt(us);
- }
-
- static inline bool timeout_elapsed(uint64_t expire)
- {
-- return read_cntpct() > expire;
-+ return read_cntvct() > expire;
- }
-
- #endif
-diff --git a/core/arch/arm/kernel/arm32_sysreg.txt b/core/arch/arm/kernel/arm32_sysreg.txt
-index b69ebcb4..155773f8 100644
---- a/core/arch/arm/kernel/arm32_sysreg.txt
-+++ b/core/arch/arm/kernel/arm32_sysreg.txt
-@@ -117,7 +117,7 @@ VBAR c12 0 c0 0 RW Vector Base Address Register
-
- @ B8.2 Generic Timer registers summary
- CNTFRQ c14 0 c0 0 RW Counter Frequency register
--CNTPCT - 0 c14 - RO Physical Count register
-+CNTVCT - 1 c14 - RO Physical Count register
- CNTKCTL c14 0 c1 0 RW Timer PL1 Control register
- CNTP_TVAL c14 0 c2 0 RW PL1 Physical TimerValue register
- CNTP_CTL c14 0 c2 1 RW PL1 Physical Timer Control register
-diff --git a/core/arch/arm/kernel/tee_time_arm_cntpct.c b/core/arch/arm/kernel/tee_time_arm_cntpct.c
-index 3c41e4c2..04e673d9 100644
---- a/core/arch/arm/kernel/tee_time_arm_cntpct.c
-+++ b/core/arch/arm/kernel/tee_time_arm_cntpct.c
-@@ -16,7 +16,7 @@
-
- static TEE_Result arm_cntpct_get_sys_time(TEE_Time *time)
- {
-- uint64_t cntpct = read_cntpct();
-+ uint64_t cntpct = read_cntvct();
- uint32_t cntfrq = read_cntfrq();
-
- time->seconds = cntpct / cntfrq;
-@@ -49,7 +49,7 @@ REGISTER_TIME_SOURCE(arm_cntpct_time_source)
-
- void plat_prng_add_jitter_entropy(enum crypto_rng_src sid, unsigned int *pnum)
- {
-- uint64_t tsc = read_cntpct();
-+ uint64_t tsc = read_cntvct();
- int bytes = 0, n;
- static uint8_t first, bits;
- static uint16_t acc;
-diff --git a/core/kernel/tee_ta_manager.c b/core/kernel/tee_ta_manager.c
-index 46632ce7..4153fbd8 100644
---- a/core/kernel/tee_ta_manager.c
-+++ b/core/kernel/tee_ta_manager.c
-@@ -923,7 +923,7 @@ static void gprof_update_session_utime(bool suspend, struct ts_session *s,
- static void tee_ta_update_session_utime(bool suspend)
- {
- struct ts_session *s = ts_get_current_session();
-- uint64_t now = read_cntpct();
-+ uint64_t now = read_cntvct();
-
- gprof_update_session_utime(suspend, s, now);
- }
-@@ -947,7 +947,7 @@ static void ftrace_update_times(bool suspend)
- uint64_t now = 0;
- uint32_t i = 0;
-
-- now = read_cntpct();
-+ now = read_cntvct();
-
- fbuf = s->fbuf;
- if (!fbuf)
-diff --git a/lib/libutee/arch/arm/arm32_user_sysreg.txt b/lib/libutee/arch/arm/arm32_user_sysreg.txt
-index 8baefd10..13e28f20 100644
---- a/lib/libutee/arch/arm/arm32_user_sysreg.txt
-+++ b/lib/libutee/arch/arm/arm32_user_sysreg.txt
-@@ -10,4 +10,4 @@
-
- @ B8.2 Generic Timer registers summary
- CNTFRQ c14 0 c0 0 RW Counter Frequency register
--CNTPCT - 0 c14 - RO Physical Count register
-+CNTVCT - 1 c14 - RO Physical Count register
-diff --git a/lib/libutee/include/arm64_user_sysreg.h b/lib/libutee/include/arm64_user_sysreg.h
-index db4ee188..722a08c9 100644
---- a/lib/libutee/include/arm64_user_sysreg.h
-+++ b/lib/libutee/include/arm64_user_sysreg.h
-@@ -31,7 +31,7 @@ static inline __noprof void write_##reg(type val) \
-
- /* ARM Generic timer functions */
- DEFINE_REG_READ_FUNC_(cntfrq, uint32_t, cntfrq_el0)
--DEFINE_REG_READ_FUNC_(cntpct, uint64_t, cntpct_el0)
-+DEFINE_REG_READ_FUNC_(cntvct, uint64_t, cntvct_el0)
- DEFINE_REG_READ_FUNC_(tpidr_el0, uint64_t, tpidr_el0)
- DEFINE_REG_WRITE_FUNC_(tpidr_el0, uint64_t, tpidr_el0)
-
-diff --git a/lib/libutils/ext/ftrace/ftrace.c b/lib/libutils/ext/ftrace/ftrace.c
-index 101aa594..637cbd19 100644
---- a/lib/libutils/ext/ftrace/ftrace.c
-+++ b/lib/libutils/ext/ftrace/ftrace.c
-@@ -165,7 +165,7 @@ void __noprof ftrace_enter(unsigned long pc, unsigned long *lr)
-
- if (fbuf->ret_idx < FTRACE_RETFUNC_DEPTH) {
- fbuf->ret_stack[fbuf->ret_idx] = *lr;
-- fbuf->begin_time[fbuf->ret_idx] = read_cntpct();
-+ fbuf->begin_time[fbuf->ret_idx] = read_cntvct();
- fbuf->ret_idx++;
- } else {
- /*
-@@ -269,7 +269,7 @@ unsigned long __noprof ftrace_return(void)
- dur_loc = curr_buf - (fbuf->ret_idx +
- (2 * sizeof(unsigned long)) + 11);
- ftrace_duration(dur_loc, fbuf->begin_time[fbuf->ret_idx],
-- read_cntpct());
-+ read_cntvct());
- } else {
- bool full = false;
-
-@@ -297,7 +297,7 @@ unsigned long __noprof ftrace_return(void)
- dur_loc = curr_buf - fbuf->ret_idx - 6;
- ftrace_duration(dur_loc,
- fbuf->begin_time[fbuf->ret_idx],
-- read_cntpct());
-+ read_cntvct());
- }
- }
-
---
-2.29.2
-
diff --git a/meta-arm-bsp/recipes-security/optee/files/optee-os/tc0/sp_layout.json b/meta-arm-bsp/recipes-security/optee/files/optee-os/tc0/sp_layout.json
new file mode 100644
index 0000000..d37d902
--- /dev/null
+++ b/meta-arm-bsp/recipes-security/optee/files/optee-os/tc0/sp_layout.json
@@ -0,0 +1,6 @@
+{
+ "op-tee" : {
+ "image": "tee-pager_v2.bin",
+ "pm": "optee_sp_manifest.dts"
+ }
+}
diff --git a/meta-arm-bsp/recipes-security/optee/optee-client-tc0.inc b/meta-arm-bsp/recipes-security/optee/optee-client-tc0.inc
index ad9c475..d460b50 100644
--- a/meta-arm-bsp/recipes-security/optee/optee-client-tc0.inc
+++ b/meta-arm-bsp/recipes-security/optee/optee-client-tc0.inc
@@ -1,12 +1,3 @@
# TC0 specific configuration
-# Intermediate SHA with 3.11 baseline version
-SRCREV = "3f44b870299514ad8c6b7dee776eb2994d9c1cd4"
-PV = "3.11.0+git${SRCPV}"
-
-FILESEXTRAPATHS_prepend_tc0 := "${THISDIR}/files/optee-client/tc0:"
-
-SRC_URI_append = " \
- file://0001-Revert-libteec-Avoid-memcpy-when-using-TEEC_TempMemo.patch \
- file://0002-Allocate-page-aligned-shared-memory-buffers.patch \
- "
+# Change in SHA, extra patches specific to TC0 are added in this file.
diff --git a/meta-arm-bsp/recipes-security/optee/optee-client_3.11.0.bbappend b/meta-arm-bsp/recipes-security/optee/optee-client_3.14.0.bbappend
similarity index 100%
rename from meta-arm-bsp/recipes-security/optee/optee-client_3.11.0.bbappend
rename to meta-arm-bsp/recipes-security/optee/optee-client_3.14.0.bbappend
diff --git a/meta-arm-bsp/recipes-security/optee/optee-os-tc0.inc b/meta-arm-bsp/recipes-security/optee/optee-os-tc0.inc
index 1b03a35..7afc112 100644
--- a/meta-arm-bsp/recipes-security/optee/optee-os-tc0.inc
+++ b/meta-arm-bsp/recipes-security/optee/optee-os-tc0.inc
@@ -1,31 +1,12 @@
# TC0 specific configuration
-# Intermediate SHA with 3.11 baseline version
-SRCREV = "3284d935bc7e7bf7abfb5b19394a387d975d6dd4"
-PV = "3.11.0+git${SRCPV}"
-
-# This is incorporated into the SRCREV above
-SRC_URI_remove = " \
- file://0001-libutils-provide-empty-__getauxval-implementation.patch \
- file://0002-link.mk-implement-support-for-libnames-after-libgcc-.patch \
- file://0003-ta_dev_kit.mk-make-sure-that-libutils-is-linked-seco.patch \
- "
+# Intermediate SHA with 3.14 baseline version
+# This has TC0 platform support
+SRCREV = "49dbb9ef65643c4322cf3f848910fa880d1c02f6"
+PV = "3.14.0+git${SRCPV}"
FILESEXTRAPATHS_prepend_tc0 := "${THISDIR}/files/optee-os/tc0:"
-
-SRC_URI_append = " \
- file://0001-core-SPMC-update-for-FF-A-version-1.0.patch \
- file://0002-core-add-thread_smccc.patch \
- file://0003-core-enable-SPCI-with-SPM-Core-at-S-EL2.patch \
- file://0004-core-fixes-to-align-with-upstream-hafnium.patch \
- file://0005-core-arm-Total-Compute-platform-support.patch \
- file://0006-plat-totalcompute-Add-support-for-S-EL2-SPMC.patch \
- file://0007-plat-totalcompute-add-optee-manifest-file-and-sp-lay.patch \
- file://0008-plat-totalcompute-define-tzdram-start-address-for-S-.patch \
- file://0009-plat-totalcompute-add-Theodul-DSU-support.patch \
- file://0010-WIP-OP-TEE-SP-declare-device-regions-in-manifest.patch \
- file://0011-WIP-OP-TEE-SP-use-CNTVCT-in-place-of-CNTVCT.patch \
- "
+SRC_URI_append = "file://sp_layout.json"
COMPATIBLE_MACHINE = "tc0"
@@ -42,13 +23,11 @@ EXTRA_OEMAKE += " CFG_WITH_STATS=y"
EXTRA_OEMAKE += " CFG_CORE_SEL2_SPMC=y"
-# Copy optee manifest file and sp_layout
-# This function will be modified or removed once upstream optee-os adds support
-# for SEL2 SPMC config
+# Copy optee manifest file
do_install_append() {
install -d ${D}${nonarch_base_libdir}/firmware/
- install -m 644 ${S}/core/arch/arm/plat-totalcompute/sp_layout.json \
- ${D}${nonarch_base_libdir}/firmware/
- install -m 644 ${S}/core/arch/arm/plat-totalcompute/optee_manifest.dts \
+ install -m 644 ${WORKDIR}/sp_layout.json ${D}${nonarch_base_libdir}/firmware/
+ install -m 644 \
+ ${S}/core/arch/arm/plat-totalcompute/fdts/optee_sp_manifest.dts \
${D}${nonarch_base_libdir}/firmware/
}
diff --git a/meta-arm-bsp/recipes-security/optee/optee-os_3.11.0.bbappend b/meta-arm-bsp/recipes-security/optee/optee-os_3.14.0.bbappend
similarity index 100%
rename from meta-arm-bsp/recipes-security/optee/optee-os_3.11.0.bbappend
rename to meta-arm-bsp/recipes-security/optee/optee-os_3.14.0.bbappend
diff --git a/meta-arm-bsp/recipes-security/optee/optee-test-tc0.inc b/meta-arm-bsp/recipes-security/optee/optee-test-tc0.inc
index cca5076..832fea1 100644
--- a/meta-arm-bsp/recipes-security/optee/optee-test-tc0.inc
+++ b/meta-arm-bsp/recipes-security/optee/optee-test-tc0.inc
@@ -1,14 +1,3 @@
# TC0 specific configuration
-# Intermediate SHA with 3.11 baseline version
-SRCREV = "b35df64954ef96e09c0d5573014f4d1432dbc92f"
-PV = "3.11.0+git${SRCPV}"
-
-# This is incorporated into the SRCREV above
-SRC_URI_remove = " \
- file://0001-host-xtest-Adjust-order-of-including-compiler.h.patch \
- file://0002-make-remove-Wno-unsafe-loop-for-clang.patch \
- file://0003-make-remove-Wmissing-noreturn-for-clang.patch \
-"
-
COMPATIBLE_MACHINE = "tc0"
diff --git a/meta-arm-bsp/recipes-security/optee/optee-test_3.11.0.bbappend b/meta-arm-bsp/recipes-security/optee/optee-test_3.14.0.bbappend
similarity index 100%
rename from meta-arm-bsp/recipes-security/optee/optee-test_3.11.0.bbappend
rename to meta-arm-bsp/recipes-security/optee/optee-test_3.14.0.bbappend
--
2.29.2
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH 4/6] arm/hafnium: update to version 2.5
2021-07-22 11:32 [PATCH 1/6] arm: update Android common kernel Arunachalam Ganapathy
2021-07-22 11:32 ` [PATCH 2/6] arm-bsp/linux: add ffa driver to TC0 Arunachalam Ganapathy
2021-07-22 11:32 ` [PATCH 3/6] arm-bsp/tc0: Update optee to 3.14.0 Arunachalam Ganapathy
@ 2021-07-22 11:32 ` Arunachalam Ganapathy
2021-07-22 11:32 ` [PATCH 5/6] arm-bsp/tc0: update Hafnium to 2.5 Arunachalam Ganapathy
2021-07-22 11:32 ` [PATCH 6/6] arm-bsp/scp-firmware: update SHA for tc0 Arunachalam Ganapathy
4 siblings, 0 replies; 6+ messages in thread
From: Arunachalam Ganapathy @ 2021-07-22 11:32 UTC (permalink / raw)
To: meta-arm; +Cc: nd, Arunachalam Ganapathy
Signed-off-by: Arunachalam Ganapathy <arunachalam.ganapathy@arm.com>
Change-Id: I1405bd4df424e70af1286ccc675001bd79726b48
---
meta-arm/recipes-bsp/hafnium/{hafnium_2.4.bb => hafnium_2.5.bb} | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
rename meta-arm/recipes-bsp/hafnium/{hafnium_2.4.bb => hafnium_2.5.bb} (97%)
diff --git a/meta-arm/recipes-bsp/hafnium/hafnium_2.4.bb b/meta-arm/recipes-bsp/hafnium/hafnium_2.5.bb
similarity index 97%
rename from meta-arm/recipes-bsp/hafnium/hafnium_2.4.bb
rename to meta-arm/recipes-bsp/hafnium/hafnium_2.5.bb
index 361d6db..97e31e8 100644
--- a/meta-arm/recipes-bsp/hafnium/hafnium_2.4.bb
+++ b/meta-arm/recipes-bsp/hafnium/hafnium_2.5.bb
@@ -8,7 +8,7 @@ PACKAGE_ARCH = "${MACHINE_ARCH}"
inherit deploy python3native
SRC_URI = "gitsm://git.trustedfirmware.org/hafnium/hafnium.git;protocol=https"
-SRCREV = "410a3acaf669c12d41fb4c57fcaf3ecee6fdba61"
+SRCREV = "3a149eb219467c0d9336467ea1fb9d3fb65da94b"
S = "${WORKDIR}/git"
COMPATIBLE_MACHINE ?= "invalid"
--
2.29.2
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH 5/6] arm-bsp/tc0: update Hafnium to 2.5
2021-07-22 11:32 [PATCH 1/6] arm: update Android common kernel Arunachalam Ganapathy
` (2 preceding siblings ...)
2021-07-22 11:32 ` [PATCH 4/6] arm/hafnium: update to version 2.5 Arunachalam Ganapathy
@ 2021-07-22 11:32 ` Arunachalam Ganapathy
2021-07-22 11:32 ` [PATCH 6/6] arm-bsp/scp-firmware: update SHA for tc0 Arunachalam Ganapathy
4 siblings, 0 replies; 6+ messages in thread
From: Arunachalam Ganapathy @ 2021-07-22 11:32 UTC (permalink / raw)
To: meta-arm; +Cc: nd, Arunachalam Ganapathy
Signed-off-by: Arunachalam Ganapathy <arunachalam.ganapathy@arm.com>
Change-Id: I2da38cff515cb543a31c7d8e2c50b51ff94ca8d3
---
...condary-core-entry-point-at-SPMC-ini.patch | 276 ------------------
...A-Cold-boot-and-wake-up-from-suspend.patch | 95 ------
...-A-Respond-to-PSCI_CPU_OFF-from-SPMD.patch | 115 --------
.../0004-tc0-Add-Theodul-DSU-support.patch | 30 --
.../recipes-bsp/hafnium/hafnium-tc0.inc | 13 -
...nium_2.4.bbappend => hafnium_2.5.bbappend} | 0
6 files changed, 529 deletions(-)
delete mode 100644 meta-arm-bsp/recipes-bsp/hafnium/files/tc0/0001-FF-A-Register-secondary-core-entry-point-at-SPMC-ini.patch
delete mode 100644 meta-arm-bsp/recipes-bsp/hafnium/files/tc0/0002-FF-A-Cold-boot-and-wake-up-from-suspend.patch
delete mode 100644 meta-arm-bsp/recipes-bsp/hafnium/files/tc0/0003-FF-A-Respond-to-PSCI_CPU_OFF-from-SPMD.patch
delete mode 100644 meta-arm-bsp/recipes-bsp/hafnium/files/tc0/0004-tc0-Add-Theodul-DSU-support.patch
rename meta-arm-bsp/recipes-bsp/hafnium/{hafnium_2.4.bbappend => hafnium_2.5.bbappend} (100%)
diff --git a/meta-arm-bsp/recipes-bsp/hafnium/files/tc0/0001-FF-A-Register-secondary-core-entry-point-at-SPMC-ini.patch b/meta-arm-bsp/recipes-bsp/hafnium/files/tc0/0001-FF-A-Register-secondary-core-entry-point-at-SPMC-ini.patch
deleted file mode 100644
index f2219d0..0000000
--- a/meta-arm-bsp/recipes-bsp/hafnium/files/tc0/0001-FF-A-Register-secondary-core-entry-point-at-SPMC-ini.patch
+++ /dev/null
@@ -1,276 +0,0 @@
-Upstream-Status: Pending [https://review.trustedfirmware.org/c/hafnium/hafnium/+/6009/27]
-Signed-off-by: Arunachalam Ganapathy <arunachalam.ganapathy@arm.com>
-
-From 06e7602ddb383e0f88c19feaa216c24cf032a136 Mon Sep 17 00:00:00 2001
-From: Max Shvetsov <maksims.svecovs@arm.com>
-Date: Thu, 27 Aug 2020 12:37:57 +0100
-Subject: [PATCH 2/5] FF-A: Register secondary core entry point at SPMC init.
-
-When the primary physical core boots the SPMC registers its secondary
-physical core entry points to the SPMD. All Secure Partition are then
-initialized on their primary Execution Contexts. A Secure Partition
-calls PSCI_CPU_ON from its first EC (trapped to the SPMC) passing
-entry point addresses of secondary ECs. ECs are turned "on" in their
-SPMC internal states, although they do not run yet (the service call
-does not reach the EL3 PSCI layer). Later, when the NWd (Hypervisor
-or OS Kernel) boots, it calls PSCI_CPU_ON for waking up physical cores
-down to EL3. The PSCI layer calls into SPMD PM hooks, then the SPMD
-calls into the SPMC by an exception return to the registered secondary
-entry point. The target secondary core then reaches Hafnium vcpu_main.
-
-Change-Id: I2bd42ea54e1a7feebff20e878345ec196ff352e9
-Signed-off-by: Max Shvetsov <maksims.svecovs@arm.com>
-Signed-off-by: Olivier Deprez <olivier.deprez@arm.com>
----
- inc/hf/arch/init.h | 7 ++++
- inc/hf/arch/other_world.h | 2 ++
- src/arch/aarch64/hypervisor/other_world.c | 29 +++++++++++++++
- src/arch/aarch64/hypervisor/psci_handler.c | 40 +++++++++++++++++++++
- src/arch/aarch64/inc/hf/arch/spmd_helpers.h | 15 ++++++++
- src/cpu.c | 2 +-
- src/init.c | 2 ++
- src/load.c | 3 ++
- src/main.c | 12 ++++---
- 9 files changed, 106 insertions(+), 6 deletions(-)
- create mode 100644 src/arch/aarch64/inc/hf/arch/spmd_helpers.h
-
-diff --git a/inc/hf/arch/init.h b/inc/hf/arch/init.h
-index 5205e4e..ef0e48f 100644
---- a/inc/hf/arch/init.h
-+++ b/inc/hf/arch/init.h
-@@ -8,6 +8,8 @@
-
- #pragma once
-
-+#include "hf/boot_params.h"
-+
- /**
- * Performs arch specific boot time initialization.
- *
-@@ -15,3 +17,8 @@
- * possible.
- */
- void arch_one_time_init(void);
-+
-+/**
-+ * Sets up secondary cores.
-+ */
-+void arch_psci_secondary_core_init(const struct boot_params *params);
-diff --git a/inc/hf/arch/other_world.h b/inc/hf/arch/other_world.h
-index 68c0b45..860a142 100644
---- a/inc/hf/arch/other_world.h
-+++ b/inc/hf/arch/other_world.h
-@@ -20,3 +20,5 @@ bool arch_other_world_is_direct_request_valid(struct vcpu *current,
- bool arch_other_world_is_direct_response_valid(struct vcpu *current,
- ffa_vm_id_t sender_vm_id,
- ffa_vm_id_t receiver_vm_id);
-+void arch_other_world_init_ffa_id(void);
-+ffa_vm_id_t arch_other_world_get_ffa_id(void);
-diff --git a/src/arch/aarch64/hypervisor/other_world.c b/src/arch/aarch64/hypervisor/other_world.c
-index 74a2bb1..6b5bb16 100644
---- a/src/arch/aarch64/hypervisor/other_world.c
-+++ b/src/arch/aarch64/hypervisor/other_world.c
-@@ -23,6 +23,10 @@
- alignas(PAGE_SIZE) static uint8_t other_world_send_buffer[HF_MAILBOX_SIZE];
- alignas(PAGE_SIZE) static uint8_t other_world_recv_buffer[HF_MAILBOX_SIZE];
-
-+#else
-+
-+static ffa_vm_id_t physical_ffa_id;
-+
- #endif
-
- void arch_other_world_init(void)
-@@ -181,3 +185,28 @@ struct ffa_value arch_other_world_call(struct ffa_value args)
- {
- return smc_ffa_call(args);
- }
-+
-+#if SECURE_WORLD == 1
-+
-+ffa_vm_id_t arch_other_world_get_ffa_id(void)
-+{
-+ return physical_ffa_id;
-+}
-+
-+void arch_other_world_init_ffa_id(void)
-+{
-+ struct ffa_value res =
-+ smc_ffa_call((struct ffa_value){.func = FFA_ID_GET_32});
-+
-+ if (res.func != FFA_SUCCESS_32) {
-+ dlog_error("%s Failed to get SPMC's FFA-ID from SPMD.\n",
-+ __func__);
-+ physical_ffa_id = HF_INVALID_VM_ID;
-+ return;
-+ }
-+ physical_ffa_id = res.arg2 & 0xFFFF;
-+
-+ CHECK(physical_ffa_id == HF_TEE_VM_ID);
-+}
-+
-+#endif
-diff --git a/src/arch/aarch64/hypervisor/psci_handler.c b/src/arch/aarch64/hypervisor/psci_handler.c
-index f89a00b..b323faa 100644
---- a/src/arch/aarch64/hypervisor/psci_handler.c
-+++ b/src/arch/aarch64/hypervisor/psci_handler.c
-@@ -10,10 +10,13 @@
-
- #include <stdint.h>
-
-+#include "hf/arch/other_world.h"
- #include "hf/arch/plat/psci.h"
-+#include "hf/arch/spmd_helpers.h"
- #include "hf/arch/types.h"
-
- #include "hf/api.h"
-+#include "hf/boot_params.h"
- #include "hf/cpu.h"
- #include "hf/dlog.h"
- #include "hf/ffa.h"
-@@ -53,6 +56,41 @@ void arch_one_time_init(void)
- }
- #else
- el3_psci_version = PSCI_VERSION_1_1;
-+
-+ arch_other_world_init_ffa_id();
-+#endif
-+}
-+
-+/**
-+ * Register secondary physical core entry points to the SPMD.
-+ */
-+void arch_psci_secondary_core_init(const struct boot_params *params)
-+{
-+#if SECURE_WORLD == 1
-+ struct ffa_value res;
-+
-+ for (uint32_t count = 0; count < params->cpu_count; count++) {
-+ uint32_t id = params->cpu_ids[count];
-+ struct cpu *cpu = cpu_find(id);
-+ const ffa_vm_id_t ffa_id = arch_other_world_get_ffa_id();
-+
-+ res = smc_ffa_call((struct ffa_value){
-+ .func = FFA_MSG_SEND_DIRECT_REQ_32,
-+ .arg1 = ((uint64_t)ffa_id << 16) | SPMD_ID,
-+ .arg3 = SPMD_DIRECT_MSG_SET_ENTRY_POINT,
-+ .arg4 = params->cpu_ids[count],
-+ .arg5 = (uintreg_t)&cpu_entry,
-+ .arg6 = (uintreg_t)cpu});
-+
-+ if (res.func != FFA_SUCCESS_32) {
-+ dlog_warning(
-+ "%s Failed to initialize secondary core ID: "
-+ "%u\n",
-+ __func__, id);
-+ }
-+
-+ dlog_verbose("SPMD EP register returned %#x\n", res.func);
-+ }
- #endif
- }
-
-@@ -353,11 +391,13 @@ bool psci_secondary_vm_handler(struct vcpu *vcpu, uint32_t func, uintreg_t arg0,
-
- if (vcpu_secondary_reset_and_start(
- target_vcpu, entry_point_address, context_id)) {
-+#if SECURE_WORLD == 0
- /*
- * Tell the scheduler that it can start running the new
- * vCPU now.
- */
- *next = api_wake_up(vcpu, target_vcpu);
-+#endif
- *ret = PSCI_RETURN_SUCCESS;
- } else {
- *ret = PSCI_ERROR_ALREADY_ON;
-diff --git a/src/arch/aarch64/inc/hf/arch/spmd_helpers.h b/src/arch/aarch64/inc/hf/arch/spmd_helpers.h
-new file mode 100644
-index 0000000..6e11c36
---- /dev/null
-+++ b/src/arch/aarch64/inc/hf/arch/spmd_helpers.h
-@@ -0,0 +1,15 @@
-+/*
-+ * Copyright 2020 The Hafnium Authors.
-+ *
-+ * Use of this source code is governed by a BSD-style
-+ * license that can be found in the LICENSE file or at
-+ * https://opensource.org/licenses/BSD-3-Clause.
-+ */
-+
-+#define SPMD_ID 0xFFFF
-+#define SPMD_DIRECT_MSG_SET_ENTRY_POINT 1
-+
-+/**
-+ * Get SPMC ID stored in the manifest.
-+ */
-+ffa_vm_id_t get_ffa_id(void);
-diff --git a/src/cpu.c b/src/cpu.c
-index 0a3fc6f..0e0ee9a 100644
---- a/src/cpu.c
-+++ b/src/cpu.c
-@@ -138,7 +138,7 @@ bool cpu_on(struct cpu *c, ipaddr_t entry, uintreg_t arg)
- c->is_on = true;
- sl_unlock(&c->lock);
-
-- if (!prev) {
-+ if (!prev && vm_id_is_current_world(HF_PRIMARY_VM_ID)) {
- struct vm *vm = vm_find(HF_PRIMARY_VM_ID);
- struct vcpu *vcpu = vm_get_vcpu(vm, cpu_index(c));
- struct vcpu_locked vcpu_locked;
-diff --git a/src/init.c b/src/init.c
-index a5b48ab..0121213 100644
---- a/src/init.c
-+++ b/src/init.c
-@@ -146,6 +146,8 @@ void one_time_init(void)
-
- cpu_module_init(params.cpu_ids, params.cpu_count);
-
-+ arch_psci_secondary_core_init(¶ms);
-+
- /* Load all VMs. */
- update.reserved_ranges_count = 0;
- if (!load_vms(mm_stage1_locked, &manifest, &cpio, ¶ms, &update,
-diff --git a/src/load.c b/src/load.c
-index 660d77c..7accc65 100644
---- a/src/load.c
-+++ b/src/load.c
-@@ -286,6 +286,9 @@ static bool load_primary(struct mm_stage1_locked stage1_locked,
- dlog_info("Loaded primary VM with %u vCPUs, entry at %#x.\n",
- vm->vcpu_count, pa_addr(primary_begin));
-
-+ /* Mark the primary to be the first booted VM */
-+ vm_update_boot(vm);
-+
- vcpu_locked = vcpu_lock(vm_get_vcpu(vm, 0));
- vcpu_on(vcpu_locked, primary_entry, params->kernel_arg);
- vcpu_unlock(&vcpu_locked);
-diff --git a/src/main.c b/src/main.c
-index 5f30aac..3cc932e 100644
---- a/src/main.c
-+++ b/src/main.c
-@@ -15,14 +15,16 @@
- */
- struct vcpu *cpu_main(struct cpu *c)
- {
-+ struct vm *first_boot;
- struct vcpu *vcpu;
--#if SECURE_WORLD == 1
-- struct vm *first_boot = vm_get_first_boot();
-+
-+ /*
-+ * This returns the PVM in the normal worls and the first
-+ * booted Secure Partition in the secure world.
-+ */
-+ first_boot = vm_get_first_boot();
-
- vcpu = vm_get_vcpu(first_boot, cpu_index(c));
--#else
-- vcpu = vm_get_vcpu(vm_find(HF_PRIMARY_VM_ID), cpu_index(c));
--#endif
-
- vcpu->cpu = c;
-
---
-2.29.2
-
diff --git a/meta-arm-bsp/recipes-bsp/hafnium/files/tc0/0002-FF-A-Cold-boot-and-wake-up-from-suspend.patch b/meta-arm-bsp/recipes-bsp/hafnium/files/tc0/0002-FF-A-Cold-boot-and-wake-up-from-suspend.patch
deleted file mode 100644
index 6cce9ad..0000000
--- a/meta-arm-bsp/recipes-bsp/hafnium/files/tc0/0002-FF-A-Cold-boot-and-wake-up-from-suspend.patch
+++ /dev/null
@@ -1,95 +0,0 @@
-Upstream-Status: Pending [https://review.trustedfirmware.org/c/hafnium/hafnium/+/6010/29]
-Signed-off-by: Arunachalam Ganapathy <arunachalam.ganapathy@arm.com>
-
-From ebd568637627fa895e6e7f479675c650414cc240 Mon Sep 17 00:00:00 2001
-From: Max Shvetsov <maksims.svecovs@arm.com>
-Date: Thu, 27 Aug 2020 12:39:50 +0100
-Subject: [PATCH 3/5] FF-A: Cold boot and wake up from suspend.
-
-WIP: Currently there is zero entry-point passed with no arguments, This
-will be reworked once a proper way to pass this information will be
-defined.
-
-Change-Id: Ic6050af16d4081ca31729744995fbb999b170e11
-Signed-off-by: Max Shvetsov <maksims.svecovs@arm.com>
-Signed-off-by: Olivier Deprez <olivier.deprez@arm.com>
----
- inc/hf/vcpu.h | 2 ++
- src/arch/aarch64/hypervisor/psci_handler.c | 2 ++
- src/main.c | 20 ++++++++++++++++++++
- 3 files changed, 24 insertions(+)
-
-diff --git a/inc/hf/vcpu.h b/inc/hf/vcpu.h
-index 5439719..98f3a50 100644
---- a/inc/hf/vcpu.h
-+++ b/inc/hf/vcpu.h
-@@ -86,6 +86,8 @@ struct vcpu {
- * a result of a prior FFA_MSG_SEND_DIRECT_REQ invocation.
- */
- ffa_vm_id_t direct_request_origin_vm_id;
-+
-+ ipaddr_t psci_handler[1];
- };
-
- /** Encapsulates a vCPU whose lock is held. */
-diff --git a/src/arch/aarch64/hypervisor/psci_handler.c b/src/arch/aarch64/hypervisor/psci_handler.c
-index b323faa..c892385 100644
---- a/src/arch/aarch64/hypervisor/psci_handler.c
-+++ b/src/arch/aarch64/hypervisor/psci_handler.c
-@@ -389,6 +389,8 @@ bool psci_secondary_vm_handler(struct vcpu *vcpu, uint32_t func, uintreg_t arg0,
-
- target_vcpu = vm_get_vcpu(vm, target_vcpu_index);
-
-+ target_vcpu->psci_handler[0] = entry_point_address;
-+
- if (vcpu_secondary_reset_and_start(
- target_vcpu, entry_point_address, context_id)) {
- #if SECURE_WORLD == 0
-diff --git a/src/main.c b/src/main.c
-index 3cc932e..2c3d1a5 100644
---- a/src/main.c
-+++ b/src/main.c
-@@ -7,6 +7,7 @@
- */
-
- #include "hf/cpu.h"
-+#include "hf/dlog.h"
- #include "hf/vm.h"
-
- /**
-@@ -18,6 +19,18 @@ struct vcpu *cpu_main(struct cpu *c)
- struct vm *first_boot;
- struct vcpu *vcpu;
-
-+#if SECURE_WORLD == 1
-+ if (c->is_on == false) {
-+ /*
-+ * This is the PSCI warm reset path (svc_cpu_on_finish
-+ * handler relayed by SPMD). Notice currenty the "first_boot"
-+ * VM is resumed on any CPU on event.
-+ */
-+ (void)cpu_on(c, ipa_init(0UL), 0UL);
-+ dlog_verbose("%s: cpu mpidr 0x%x on\n", __func__, c->id);
-+ }
-+#endif
-+
- /*
- * This returns the PVM in the normal worls and the first
- * booted Secure Partition in the secure world.
-@@ -26,6 +39,13 @@ struct vcpu *cpu_main(struct cpu *c)
-
- vcpu = vm_get_vcpu(first_boot, cpu_index(c));
-
-+ if (vcpu->psci_handler[0].ipa) {
-+ struct vcpu_locked vcpu_locked = vcpu_lock(vcpu);
-+
-+ vcpu_on(vcpu_locked, vcpu->psci_handler[0], 0);
-+ vcpu_unlock(&vcpu_locked);
-+ }
-+
- vcpu->cpu = c;
-
- arch_cpu_init();
---
-2.29.2
-
diff --git a/meta-arm-bsp/recipes-bsp/hafnium/files/tc0/0003-FF-A-Respond-to-PSCI_CPU_OFF-from-SPMD.patch b/meta-arm-bsp/recipes-bsp/hafnium/files/tc0/0003-FF-A-Respond-to-PSCI_CPU_OFF-from-SPMD.patch
deleted file mode 100644
index 87f2a43..0000000
--- a/meta-arm-bsp/recipes-bsp/hafnium/files/tc0/0003-FF-A-Respond-to-PSCI_CPU_OFF-from-SPMD.patch
+++ /dev/null
@@ -1,115 +0,0 @@
-Upstream-Status: Pending [https://review.trustedfirmware.org/c/hafnium/hafnium/+/6011/29]
-Signed-off-by: Arunachalam Ganapathy <arunachalam.ganapathy@arm.com>
-
-From 6a836b380265876a12b2edfb7f013523af89e754 Mon Sep 17 00:00:00 2001
-From: Max Shvetsov <maksims.svecovs@arm.com>
-Date: Fri, 18 Sep 2020 13:52:20 +0100
-Subject: [PATCH 4/5] FF-A: Respond to PSCI_CPU_OFF from SPMD.
-
-At run-time when a PSCI call is made from NWd, the corresponding SPMD PM
-hooks gets called and is eventually routed to the SPMC. This change
-implements a generic "SPMD handler" processing PM events that may be
-conveyed from SPMD to SPMC such as core suspend, core off.
-
-Change-Id: Id288e26d9fbb8328acc71f5cf68c39e095a0e3da
-Signed-off-by: Max Shvetsov <maksims.svecovs@arm.com>
-Signed-off-by: Olivier Deprez <olivier.deprez@arm.com>
----
- src/arch/aarch64/hypervisor/handler.c | 49 +++++++++++++++++++++++++--
- 1 file changed, 47 insertions(+), 2 deletions(-)
-
-diff --git a/src/arch/aarch64/hypervisor/handler.c b/src/arch/aarch64/hypervisor/handler.c
-index b33298c..43a1404 100644
---- a/src/arch/aarch64/hypervisor/handler.c
-+++ b/src/arch/aarch64/hypervisor/handler.c
-@@ -13,6 +13,7 @@
- #include "hf/arch/mmu.h"
- #include "hf/arch/other_world.h"
- #include "hf/arch/plat/smc.h"
-+#include "hf/arch/spmd_helpers.h"
-
- #include "hf/api.h"
- #include "hf/check.h"
-@@ -261,6 +262,7 @@ static void set_virtual_interrupt_current(bool enable)
- }
-
- #if SECURE_WORLD == 1
-+
- static bool sp_boot_next(struct vcpu *current, struct vcpu **next,
- struct ffa_value *ffa_ret)
- {
-@@ -303,6 +305,41 @@ out:
- vm_unlock(¤t_vm_locked);
- return ret;
- }
-+
-+/**
-+ * Handle special direct messages from SPMD to SPMC. For now related to power
-+ * management only.
-+ */
-+static bool spmd_handler(struct ffa_value *args, struct vcpu *current)
-+{
-+ ffa_vm_id_t spmc_ffa_id = arch_other_world_get_ffa_id();
-+ ffa_vm_id_t sender = ffa_msg_send_sender(*args);
-+ ffa_vm_id_t receiver = ffa_msg_send_receiver(*args);
-+ ffa_vm_id_t current_vm_id = current->vm->id;
-+
-+ if (!((sender == SPMD_ID) && (receiver == spmc_ffa_id) &&
-+ (current_vm_id == HF_OTHER_WORLD_ID))) {
-+ return false;
-+ }
-+
-+ switch (args->arg3) {
-+ case PSCI_CPU_OFF:
-+ dlog_verbose("%s cpu off notification\n", __func__);
-+ args->func = FFA_MSG_SEND_DIRECT_RESP_32;
-+ args->arg1 = ((uint64_t)spmc_ffa_id << 16) | SPMD_ID;
-+ args->arg2 = 0U;
-+
-+ cpu_off(current->cpu);
-+ break;
-+ default:
-+ dlog_verbose("%s message not handled %#x\n", __func__,
-+ args->arg3);
-+ return false;
-+ }
-+
-+ return true;
-+}
-+
- #endif
-
- /**
-@@ -461,11 +498,17 @@ static bool ffa_handler(struct ffa_value *args, struct vcpu *current,
- (args->arg4 >> 16) & 0xffff,
- current);
- return true;
-- case FFA_MSG_SEND_DIRECT_REQ_32:
-+ case FFA_MSG_SEND_DIRECT_REQ_32: {
-+#if SECURE_WORLD == 1
-+ if (spmd_handler(args, current)) {
-+ return true;
-+ }
-+#endif
- *args = api_ffa_msg_send_direct_req(
- ffa_msg_send_sender(*args),
- ffa_msg_send_receiver(*args), *args, current, next);
- return true;
-+ }
- case FFA_MSG_SEND_DIRECT_RESP_32:
- *args = api_ffa_msg_send_direct_resp(
- ffa_msg_send_sender(*args),
-@@ -510,7 +553,9 @@ static void other_world_switch_loop(struct vcpu *other_world_vcpu,
- * the result of the call back to EL3 unless the API handler
- * sets *next to something different.
- */
-- if (!ffa_handler(&other_world_args, other_world_vcpu, next)) {
-+
-+ if (!spmd_handler(&other_world_args, other_world_vcpu) &&
-+ !ffa_handler(&other_world_args, other_world_vcpu, next)) {
- other_world_args.func = SMCCC_ERROR_UNKNOWN;
- }
- }
---
-2.29.2
-
diff --git a/meta-arm-bsp/recipes-bsp/hafnium/files/tc0/0004-tc0-Add-Theodul-DSU-support.patch b/meta-arm-bsp/recipes-bsp/hafnium/files/tc0/0004-tc0-Add-Theodul-DSU-support.patch
deleted file mode 100644
index 4c0b5dd..0000000
--- a/meta-arm-bsp/recipes-bsp/hafnium/files/tc0/0004-tc0-Add-Theodul-DSU-support.patch
+++ /dev/null
@@ -1,30 +0,0 @@
-From e8042fda56aa470cdda723757a957a81cd95dde8 Mon Sep 17 00:00:00 2001
-From: Arunachalam Ganapathy <arunachalam.ganapathy@arm.com>
-Date: Tue, 2 Feb 2021 12:12:32 +0000
-Subject: [PATCH] tc0: Add Theodul DSU support
-
-Signed-off-by: Arunachalam Ganapathy <arunachalam.ganapathy@arm.com>
-Upstream-Status: Pending [Not submitted to upstream yet]
-Change-Id: I4a9b7e4350410fdacccd8c12ff03a61b7e64e98b
----
- project/reference/BUILD.gn | 4 ++--
- 1 file changed, 2 insertions(+), 2 deletions(-)
-
-diff --git a/project/reference/BUILD.gn b/project/reference/BUILD.gn
-index 5596009..ffcaab7 100644
---- a/project/reference/BUILD.gn
-+++ b/project/reference/BUILD.gn
-@@ -159,8 +159,8 @@ aarch64_toolchains("secure_tc0") {
- gic_version = 3
- gicd_base_address = "0x30000000"
- gicr_base_address = "0x30140000"
-- heap_pages = 60
-- max_cpus = 4
-+ heap_pages = 80
-+ max_cpus = 8
- max_vms = 16
- toolchain_args = {
- secure_world = "1"
---
-2.29.2
-
diff --git a/meta-arm-bsp/recipes-bsp/hafnium/hafnium-tc0.inc b/meta-arm-bsp/recipes-bsp/hafnium/hafnium-tc0.inc
index 9f14f73..f387cb5 100644
--- a/meta-arm-bsp/recipes-bsp/hafnium/hafnium-tc0.inc
+++ b/meta-arm-bsp/recipes-bsp/hafnium/hafnium-tc0.inc
@@ -1,18 +1,5 @@
# TC0 specific configuration
-# Intermediate SHA with 2.4 baseline version, required for OP-TEE SEL1 support
-SRCREV = "fe7f737ec20add15d49c587ebeb55f7ea0118226"
-PV = "2.4+git${SRCPV}"
-
-FILESEXTRAPATHS_prepend_tc0 := "${THISDIR}/files/tc0:"
-
-SRC_URI_append = " \
- file://0001-FF-A-Register-secondary-core-entry-point-at-SPMC-ini.patch \
- file://0002-FF-A-Cold-boot-and-wake-up-from-suspend.patch \
- file://0003-FF-A-Respond-to-PSCI_CPU_OFF-from-SPMD.patch \
- file://0004-tc0-Add-Theodul-DSU-support.patch \
- "
-
COMPATIBLE_MACHINE = "tc0"
HAFNIUM_PROJECT = "reference"
diff --git a/meta-arm-bsp/recipes-bsp/hafnium/hafnium_2.4.bbappend b/meta-arm-bsp/recipes-bsp/hafnium/hafnium_2.5.bbappend
similarity index 100%
rename from meta-arm-bsp/recipes-bsp/hafnium/hafnium_2.4.bbappend
rename to meta-arm-bsp/recipes-bsp/hafnium/hafnium_2.5.bbappend
--
2.29.2
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH 6/6] arm-bsp/scp-firmware: update SHA for tc0
2021-07-22 11:32 [PATCH 1/6] arm: update Android common kernel Arunachalam Ganapathy
` (3 preceding siblings ...)
2021-07-22 11:32 ` [PATCH 5/6] arm-bsp/tc0: update Hafnium to 2.5 Arunachalam Ganapathy
@ 2021-07-22 11:32 ` Arunachalam Ganapathy
4 siblings, 0 replies; 6+ messages in thread
From: Arunachalam Ganapathy @ 2021-07-22 11:32 UTC (permalink / raw)
To: meta-arm; +Cc: nd, Arunachalam Ganapathy
This SHA contains fix for IRQn type conversion issues
Signed-off-by: Arunachalam Ganapathy <arunachalam.ganapathy@arm.com>
Change-Id: I10cc4729df3e12c549413f40d390c24f318c4577
---
.../recipes-bsp/scp-firmware/scp-firmware-tc0.inc | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/meta-arm-bsp/recipes-bsp/scp-firmware/scp-firmware-tc0.inc b/meta-arm-bsp/recipes-bsp/scp-firmware/scp-firmware-tc0.inc
index cacdca8..62a0e25 100644
--- a/meta-arm-bsp/recipes-bsp/scp-firmware/scp-firmware-tc0.inc
+++ b/meta-arm-bsp/recipes-bsp/scp-firmware/scp-firmware-tc0.inc
@@ -1,5 +1,14 @@
# TC0 specific SCP configuration
+# Intermediate SHA with 2.8 baseline version
+SRCREV = "67a3612716ad3b839da4209a173404692607c5a1"
+PV = "2.8+git${SRCPV}"
+
+# This is incorporated into the SRCREV above
+SRC_URI_remove = " \
+ file://0001-smt-Make-status-and-length-volatile-for-mod_smt_memo.patch \
+ "
+
COMPATIBLE_MACHINE = "tc0"
SCP_PLATFORM = "tc0"
--
2.29.2
^ permalink raw reply related [flat|nested] 6+ messages in thread
end of thread, other threads:[~2021-07-22 11:40 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-07-22 11:32 [PATCH 1/6] arm: update Android common kernel Arunachalam Ganapathy
2021-07-22 11:32 ` [PATCH 2/6] arm-bsp/linux: add ffa driver to TC0 Arunachalam Ganapathy
2021-07-22 11:32 ` [PATCH 3/6] arm-bsp/tc0: Update optee to 3.14.0 Arunachalam Ganapathy
2021-07-22 11:32 ` [PATCH 4/6] arm/hafnium: update to version 2.5 Arunachalam Ganapathy
2021-07-22 11:32 ` [PATCH 5/6] arm-bsp/tc0: update Hafnium to 2.5 Arunachalam Ganapathy
2021-07-22 11:32 ` [PATCH 6/6] arm-bsp/scp-firmware: update SHA for tc0 Arunachalam Ganapathy
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).