meta-arm.lists.yoctoproject.org archive mirror
 help / color / mirror / Atom feed
* [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(&param.a1, &param.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, &param, &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, &param);
-+	ret = optee_supp_thrd_req(ctx, OPTEE_RPC_CMD_SHM_ALLOC, 1, &param);
- 	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, &param);
-+	optee_supp_thrd_req(ctx, OPTEE_RPC_CMD_SHM_FREE, 1, &param);
- }
- 
- 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 +++
 .../tc0/0017-optee-sync-OP-TEE-headers.patch  |  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
+
diff --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, &param);
++	ret = optee_supp_thrd_req(ctx, OPTEE_RPC_CMD_SHM_ALLOC, 1, &param);
+ 	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, &param);
++	optee_supp_thrd_req(ctx, OPTEE_RPC_CMD_SHM_FREE, 1, &param);
+ }
+ 
+ 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(&param.a1, &param.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, &param, &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, &region_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(&params);
-+
- 	/* Load all VMs. */
- 	update.reserved_ranges_count = 0;
- 	if (!load_vms(mm_stage1_locked, &manifest, &cpio, &params, &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(&current_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).