Implement FFA ABI-s for notification handling

This change implements the listed FFA ABI-s:
- FFA_NOTIFICATION_BIND
- FFA_NOTIFICATION_UNBIND
- FFA_NOTIFICATION_SET
- FFA_NOTIFICATION_GET

Change-Id: Ifc231e3d60427b1c838cf622d8338d3e112209c1
Signed-off-by: Gabor Toth <gabor.toth2@arm.com>
diff --git a/components/messaging/ffa/libsp/component.cmake b/components/messaging/ffa/libsp/component.cmake
index 8d72089..b768f09 100644
--- a/components/messaging/ffa/libsp/component.cmake
+++ b/components/messaging/ffa/libsp/component.cmake
@@ -19,6 +19,7 @@
 	"${CMAKE_CURRENT_LIST_DIR}/sp_discovery.c"
 	"${CMAKE_CURRENT_LIST_DIR}/sp_memory_management.c"
 	"${CMAKE_CURRENT_LIST_DIR}/sp_messaging.c"
+	"${CMAKE_CURRENT_LIST_DIR}/sp_notification.c"
 	"${CMAKE_CURRENT_LIST_DIR}/sp_rxtx.c"
 	)
 
@@ -34,6 +35,7 @@
 	${CMAKE_CURRENT_LIST_DIR}/include/sp_discovery.h
 	${CMAKE_CURRENT_LIST_DIR}/include/sp_memory_management.h
 	${CMAKE_CURRENT_LIST_DIR}/include/sp_messaging.h
+	${CMAKE_CURRENT_LIST_DIR}/include/sp_notification.h
 	${CMAKE_CURRENT_LIST_DIR}/include/sp_rxtx.h
 	)
 
diff --git a/components/messaging/ffa/libsp/ffa.c b/components/messaging/ffa/libsp/ffa.c
index cae246d..f648724 100644
--- a/components/messaging/ffa/libsp/ffa.c
+++ b/components/messaging/ffa/libsp/ffa.c
@@ -646,3 +646,89 @@
 	assert(result.a0 == FFA_SUCCESS_32);
 	return FFA_OK;
 }
+
+/* Notification interfaces */
+ffa_result ffa_notification_bind(uint16_t sender, uint16_t receiver, uint32_t flags,
+				 uint64_t notification_bitmap)
+{
+	struct ffa_params result = {0};
+	uint32_t notification_bitmap_hi = 0;
+	uint32_t notification_bitmap_lo = 0;
+
+	reg_pair_from_64(notification_bitmap, &notification_bitmap_hi, &notification_bitmap_lo);
+
+	ffa_svc(FFA_NOTIFICATION_BIND, SHIFT_U32(sender, FFA_NOTIF_SOURCE_ID_SHIFT) | receiver,
+		flags, notification_bitmap_lo, notification_bitmap_hi, FFA_PARAM_MBZ, FFA_PARAM_MBZ,
+		FFA_PARAM_MBZ, &result);
+
+	if (result.a0 == FFA_ERROR)
+		return ffa_get_errorcode(&result);
+
+	assert(result.a0 == FFA_SUCCESS_32);
+	return FFA_OK;
+}
+
+ffa_result ffa_notification_unbind(uint16_t sender, uint16_t receiver, uint64_t notification_bitmap)
+{
+	struct ffa_params result = {0};
+	uint32_t notification_bitmap_hi = 0;
+	uint32_t notification_bitmap_lo = 0;
+
+	reg_pair_from_64(notification_bitmap, &notification_bitmap_hi, &notification_bitmap_lo);
+
+	ffa_svc(FFA_NOTIFICATION_UNBIND, SHIFT_U32(sender, FFA_NOTIF_SOURCE_ID_SHIFT) | receiver,
+		FFA_PARAM_MBZ, notification_bitmap_lo, notification_bitmap_hi, FFA_PARAM_MBZ,
+		FFA_PARAM_MBZ, FFA_PARAM_MBZ, &result);
+
+	if (result.a0 == FFA_ERROR)
+		return ffa_get_errorcode(&result);
+
+	assert(result.a0 == FFA_SUCCESS_32);
+	return FFA_OK;
+}
+
+ffa_result ffa_notification_set(uint16_t sender, uint16_t receiver, uint32_t flags,
+				uint64_t notification_bitmap)
+{
+	struct ffa_params result = {0};
+	uint32_t notification_bitmap_hi = 0;
+	uint32_t notification_bitmap_lo = 0;
+
+	if (!(flags & FFA_NOTIF_SET_FLAGS_PER_VCPU_NOTIFICATIONS) &&
+	    (flags && FFA_NOTIF_SET_FLAGS_RECEIVER_VCPU_MASK))
+		return FFA_INVALID_PARAMETERS;
+
+	reg_pair_from_64(notification_bitmap, &notification_bitmap_hi, &notification_bitmap_lo);
+
+	ffa_svc(FFA_NOTIFICATION_SET, SHIFT_U32(sender, FFA_NOTIF_SOURCE_ID_SHIFT) | receiver,
+		flags, notification_bitmap_lo, notification_bitmap_hi, FFA_PARAM_MBZ, FFA_PARAM_MBZ,
+		FFA_PARAM_MBZ, &result);
+
+	if (result.a0 == FFA_ERROR)
+		return ffa_get_errorcode(&result);
+
+	assert(result.a0 == FFA_SUCCESS_32);
+	return FFA_OK;
+}
+
+ffa_result ffa_notification_get(uint16_t sender, uint16_t receiver, uint32_t flags,
+				uint64_t *sp_notification_bitmap, uint64_t *vm_notification_bitmap,
+				uint64_t *framework_notification_bitmap)
+{
+	struct ffa_params result = {0};
+
+	ffa_svc(FFA_NOTIFICATION_GET, SHIFT_U32(sender, FFA_NOTIF_SOURCE_ID_SHIFT) | receiver,
+		flags, FFA_PARAM_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ,
+		&result);
+
+	if (result.a0 == FFA_ERROR)
+		return ffa_get_errorcode(&result);
+
+	assert(result.a0 == FFA_SUCCESS_32);
+
+	*sp_notification_bitmap = reg_pair_to_64(result.a3, result.a2);
+	*vm_notification_bitmap = reg_pair_to_64(result.a5, result.a4);
+	*framework_notification_bitmap = reg_pair_to_64(result.a7, result.a6);
+
+	return FFA_OK;
+}
diff --git a/components/messaging/ffa/libsp/include/ffa_api.h b/components/messaging/ffa/libsp/include/ffa_api.h
index bec9009..6366fca 100644
--- a/components/messaging/ffa/libsp/include/ffa_api.h
+++ b/components/messaging/ffa/libsp/include/ffa_api.h
@@ -414,6 +414,63 @@
 ffa_result ffa_console_log_64(const char *message, size_t length);
 
 /**
+ * @brief 	Requests the partition manager to bind notifications specified
+ * 		in the Notification bitmap parameter to the Sender endpoint.
+ *
+ * @param[in]  sender              Sender endpoint ID
+ * @param[in]  receiver            Receiver endpoint ID
+ * @param[in]  flags               Notification flags
+ * @param[in]  notification_bitmap Bitmap to identify the notifications which the
+ *                                 Sender endpoint is allowed to signal.
+ * @return                         The FF-A error status code
+ */
+ffa_result ffa_notification_bind(uint16_t sender, uint16_t receiver, uint32_t flags,
+				 uint64_t notification_bitmap);
+
+/**
+ * @brief 	Requests the partition manager to unbind notifications specified
+ *              in the Notification bitmap parameter to the Sender endpoint.
+ *
+ * @param[in]  sender              Sender endpoint ID
+ * @param[in]  receiver            Receiver endpoint ID
+ * @param[in]  notification_bitmap Bitmap to identify the notifications which the
+ *                                 sender endpoint is allowed to signal.
+ * @return                         The FF-A error status code
+ */
+ffa_result ffa_notification_unbind(uint16_t sender, uint16_t receiver,
+				   uint64_t notification_bitmap);
+
+/**
+ * @brief 	Requests the partition manager to signal notifications specified
+ *              in the Notification bitmap parameter to the Sender endpoint.
+ *
+ * @param[in]  sender              Sender endpoint ID
+ * @param[in]  receiver            Receiver endpoint ID
+ * @param[in]  flags               Notification flags
+ * @param[in]  notification_bitmap Bitmap to identify the notifications which the
+ *                                 sender endpoint is allowed to signal.
+ * @return                         The FF-A error status code
+ */
+ffa_result ffa_notification_set(uint16_t sender, uint16_t receiver, uint32_t flags,
+				uint64_t notification_bitmap);
+
+/**
+ * @brief 	Requests the partition manager to request notifications specified
+ *              in the Notification bitmap parameter to the Sender endpoint.
+ *
+ * @param[in]  sender                        Sender endpoint ID
+ * @param[in]  receiver                      Receiver endpoint ID
+ * @param[in]  flags                         Notification flags
+ * @param[out] sp_notification_bitmap        Pending notifications received from SPs.
+ * @param[out] vm_notification_bitmap        Pending notifications received from VMs.
+ * @param[out] framework_notification_bitmap Pending notifications received from the framework.
+ * @return                                   The FF-A error status code
+ */
+ffa_result ffa_notification_get(uint16_t sender, uint16_t receiver, uint32_t flags,
+				uint64_t *sp_notification_bitmap, uint64_t *vm_notification_bitmap,
+				uint64_t *framework_notification_bitmap);
+
+/**
  * @brief      Interrupt handler prototype. Must be implemented by another
  *             component.
  *
diff --git a/components/messaging/ffa/libsp/include/ffa_api_defines.h b/components/messaging/ffa/libsp/include/ffa_api_defines.h
index 39cd0e8..488665f 100644
--- a/components/messaging/ffa/libsp/include/ffa_api_defines.h
+++ b/components/messaging/ffa/libsp/include/ffa_api_defines.h
@@ -68,6 +68,10 @@
 #define FFA_MEM_PERM_SET		UINT32_C(0x84000089)
 #define FFA_CONSOLE_LOG_32		UINT32_C(0x8400008A)
 #define FFA_CONSOLE_LOG_64		UINT32_C(0xC400008A)
+#define FFA_NOTIFICATION_BIND		UINT32_C(0x8400007F)
+#define FFA_NOTIFICATION_UNBIND		UINT32_C(0x84000080)
+#define FFA_NOTIFICATION_SET		UINT32_C(0x84000081)
+#define FFA_NOTIFICATION_GET		UINT32_C(0x84000082)
 
 /* Utility macros */
 #define FFA_TO_32_BIT_FUNC(x)		((x) & (~UINT32_C(0x40000000)))
@@ -332,4 +336,19 @@
 #define FFA_CONSOLE_LOG_32_MAX_LENGTH			UINT32_C(24)
 #define FFA_CONSOLE_LOG_64_MAX_LENGTH			UINT32_C(48)
 
+/* Notification interfaces */
+#define FFA_NOTIF_SOURCE_ID_SHIFT			UINT32_C(16)
+
+#define FFA_NOTIF_BIND_FLAGS_PER_VCPU_NOTIFICATIONS	BIT32(0)
+
+#define FFA_NOTIF_SET_FLAGS_PER_VCPU_NOTIFICATIONS	BIT32(0)
+#define FFA_NOTIF_SET_FLAGS_DELAY_SCHEDULE_RECEIVER 	BIT32(1)
+#define FFA_NOTIF_SET_FLAGS_RECEIVER_VCPU_MASK		GENMASK_32(31, 16)
+#define FFA_NOTIF_SET_FLAGS_RECEIVER_VCPU_SHIFT		UINT32_C(16)
+
+#define FFA_NOTIF_GET_FLAGS_PENDING_SP_NOTIF		BIT32(0)
+#define FFA_NOTIF_GET_FLAGS_PENDING_VM_NOTIF		BIT32(1)
+#define FFA_NOTIF_GET_FLAGS_PENDING_SPM_NOTIF		BIT32(2)
+#define FFA_NOTIF_GET_FLAGS_PENDING_HV_NOTIF		BIT32(3)
+
 #endif /* LIBSP_INCLUDE_FFA_API_DEFINES_H_ */
diff --git a/components/messaging/ffa/libsp/include/sp_notification.h b/components/messaging/ffa/libsp/include/sp_notification.h
new file mode 100644
index 0000000..0b2f8bd
--- /dev/null
+++ b/components/messaging/ffa/libsp/include/sp_notification.h
@@ -0,0 +1,111 @@
+/* SPDX-License-Identifier: BSD-3-Clause */
+/*
+ * Copyright (c) 2025, Arm Limited and Contributors. All rights reserved.
+ */
+
+#ifndef SP_NOTIFICATION_H_
+#define SP_NOTIFICATION_H_
+
+#include "sp_api_defines.h"
+#include "sp_api_types.h"
+
+#include <stdbool.h>
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @brief      Notification flags of FFA_NOTIFICATION_BIND API
+ */
+struct sp_notif_bind_flags {
+	/**
+	 * true: All notifications in the bitmap are per-vCPU notifications
+	 * false: All notifications in the bitmap are global notifications
+	 */
+	bool per_cpu;
+};
+
+/**
+ * @brief      Notification flags of FFA_NOTIFICATION_SET API
+ */
+struct sp_notif_set_flags {
+	/**
+	 * true: All notifications in the bitmap are per-vCPU notifications
+	 * false: All notifications in the bitmap are global notifications
+	 */
+	bool per_cpu;
+
+	/**
+	 * Delay Schedule Receiver interrupt flag
+	 */
+	bool delay_sched_rec_intr;
+
+	/**
+	 * Receiver vCPU ID.
+	 */
+	uint16_t receiver_vcpu_id;
+};
+
+/**
+ * @brief 	Requests the partition manager to bind notifications specified
+ * 		in the Notification bitmap parameter to the Sender endpoint.
+ *
+ * @param[in]  sender              Sender endpoint ID
+ * @param[in]  receiver            Receiver endpoint ID
+ * @param[in]  flags               Notification flags
+ * @param[in]  notification_bitmap Bitmap to identify the notifications which the
+ *                                 Sender endpoint is allowed to signal.
+ * @return                         Error status code
+ */
+sp_result sp_notification_bind(uint16_t sender, uint16_t receiver,
+			       struct sp_notif_bind_flags *flags, uint64_t notification_bitmap);
+
+/**
+ * @brief 	Requests the partition manager to unbind notifications specified
+ *              in the Notification bitmap parameter to the Sender endpoint.
+ *
+ * @param[in]  sender              Sender endpoint ID
+ * @param[in]  receiver            Receiver endpoint ID
+ * @param[in]  notification_bitmap Bitmap to identify the notifications which the
+ *                                 sender endpoint is allowed to signal.
+ * @return                         Error status code
+ */
+sp_result sp_notification_unbind(uint16_t sender, uint16_t receiver, uint64_t notification_bitmap);
+
+/**
+ * @brief 	Requests the partition manager to signal notifications specified
+ *              in the Notification bitmap parameter to the Sender endpoint.
+ *
+ * @param[in]  sender              Sender endpoint ID
+ * @param[in]  receiver            Receiver endpoint ID
+ * @param[in]  flags               Notification flags
+ * @param[in]  notification_bitmap Bitmap to identify the notifications which the
+ *                                 sender endpoint is allowed to signal.
+ * @return                         Error status code
+ */
+sp_result sp_notification_set(uint16_t sender, uint16_t receiver, struct sp_notif_set_flags *flags,
+			      uint64_t notification_bitmap);
+
+/**
+ * @brief 	Requests the partition manager to request notifications specified
+ *              in the Notification bitmap parameter to the Sender endpoint.
+ *
+ * @param[in]  sender                        Sender endpoint ID
+ * @param[in]  receiver                      Receiver endpoint ID
+ * @param[out] sp_notification_bitmap        Pending notifications received from SPs.
+ * @param[out] vm_notification_bitmap        Pending notifications received from VMs.
+ * @param[out] spm_notification_bitmap       Pending notifications received from the SPM.
+ * @param[out] hv_notification_bitmap        Pending notifications received from the Hypervisor.
+ * @return                                   Error status code
+ */
+sp_result sp_notification_get(uint16_t sender, uint16_t receiver, uint64_t *sp_notification_bitmap,
+			      uint64_t *vm_notification_bitmap, uint32_t *spm_notification_bitmap,
+			      uint32_t *hv_notification_bitmap);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* SP_NOTIFICATION_H_ */
diff --git a/components/messaging/ffa/libsp/sp_notification.c b/components/messaging/ffa/libsp/sp_notification.c
new file mode 100644
index 0000000..ed25649
--- /dev/null
+++ b/components/messaging/ffa/libsp/sp_notification.c
@@ -0,0 +1,90 @@
+// SPDX-License-Identifier: BSD-3-Clause
+/*
+ * Copyright (c) 2025, Arm Limited and Contributors. All rights reserved.
+ */
+
+#include "sp_notification.h"
+#include "sp_api.h"
+#include <assert.h>
+#include <string.h>
+
+static uint32_t build_notif_bind_flags(struct sp_notif_bind_flags *flags)
+{
+	uint32_t res = 0;
+
+	if (flags->per_cpu)
+		res |= FFA_NOTIF_BIND_FLAGS_PER_VCPU_NOTIFICATIONS;
+
+	return res;
+}
+
+static uint32_t build_notif_set_flags(struct sp_notif_set_flags *flags)
+{
+	uint32_t res = 0;
+
+	if (flags->per_cpu) {
+		res |= FFA_NOTIF_SET_FLAGS_PER_VCPU_NOTIFICATIONS;
+		res |= SHIFT_U32(flags->receiver_vcpu_id, FFA_NOTIF_SET_FLAGS_RECEIVER_VCPU_SHIFT);
+	}
+
+	if (flags->delay_sched_rec_intr)
+		res |= FFA_NOTIF_SET_FLAGS_DELAY_SCHEDULE_RECEIVER;
+
+	return res;
+}
+
+sp_result sp_notification_bind(uint16_t sender, uint16_t receiver,
+			       struct sp_notif_bind_flags *flags, uint64_t notification_bitmap)
+{
+	return SP_RESULT_FFA(ffa_notification_bind(sender, receiver, build_notif_bind_flags(flags),
+						   notification_bitmap));
+}
+
+sp_result sp_notification_unbind(uint16_t sender, uint16_t receiver, uint64_t notification_bitmap)
+{
+	return SP_RESULT_FFA(ffa_notification_unbind(sender, receiver, notification_bitmap));
+}
+
+sp_result sp_notification_set(uint16_t sender, uint16_t receiver, struct sp_notif_set_flags *flags,
+			      uint64_t notification_bitmap)
+{
+	if (!flags->per_cpu && flags->receiver_vcpu_id)
+		return SP_RESULT_INVALID_PARAMETERS;
+
+	return SP_RESULT_FFA(ffa_notification_set(sender, receiver, build_notif_set_flags(flags),
+						  notification_bitmap));
+}
+
+sp_result sp_notification_get(uint16_t sender, uint16_t receiver, uint64_t *sp_notification_bitmap,
+			      uint64_t *vm_notification_bitmap, uint32_t *spm_notification_bitmap,
+			      uint32_t *hv_notification_bitmap)
+{
+	uint32_t flags = 0;
+	uint64_t buff_framework_notification_bitmap = 0;
+	uint64_t buff_sp_notification_bitmap = 0;
+	uint64_t buff_vm_notification_bitmap = 0;
+	sp_result result = 0;
+
+	if (sp_notification_bitmap)
+		flags |= FFA_NOTIF_GET_FLAGS_PENDING_SP_NOTIF;
+	if (vm_notification_bitmap)
+		flags |= FFA_NOTIF_GET_FLAGS_PENDING_VM_NOTIF;
+	if (spm_notification_bitmap)
+		flags |= FFA_NOTIF_GET_FLAGS_PENDING_SPM_NOTIF;
+	if (hv_notification_bitmap)
+		flags |= FFA_NOTIF_GET_FLAGS_PENDING_HV_NOTIF;
+
+	result = SP_RESULT_FFA(ffa_notification_get(sender, receiver, flags, &buff_sp_notification_bitmap,
+						    &buff_vm_notification_bitmap,
+						    &buff_framework_notification_bitmap));
+	if (sp_notification_bitmap)
+		*sp_notification_bitmap = buff_sp_notification_bitmap;
+	if (vm_notification_bitmap)
+		*vm_notification_bitmap = buff_vm_notification_bitmap;
+	if (spm_notification_bitmap)
+		*spm_notification_bitmap = buff_framework_notification_bitmap & 0xFFFFFFFF;
+	if (hv_notification_bitmap)
+		*hv_notification_bitmap = buff_framework_notification_bitmap >> 32 & 0xFFFFFFFF;
+
+	return result;
+}