feat(amd): add test for IOCTL EEMI API

Add a new test case for the IOCTL EEMI API within the TF-A test
framework. The objective of this test is to verify the functionality
and behavior of the IOCTL commands.

Test cover following IOCTL IDs:
- IOCTL_GET_RPU_OPER_MODE
        - To get the RPU operating mode like split or lockstep
- IOCTL_SET_RPU_OPER_MODE
        - To set the RPU operating mode like split or lockstep

These IOCTL Ids require RPU to be enabled either as the default
subsystem or as a RPU subsytem.

Note: This initial test does not cover all IOCTL IDs, as the purpose
of the test is to validate the IOCTL EEMI API interface.

Change-Id: I9c95facaab171af862ad633f7fdcab0b18b7f9e4
Signed-off-by: Madhav Bhatt <madhav.bhatt@amd.com>
diff --git a/tftf/tests/plat/amd/common/common_files/eemi_api.c b/tftf/tests/plat/amd/common/common_files/eemi_api.c
index 29d9426..e09ca19 100644
--- a/tftf/tests/plat/amd/common/common_files/eemi_api.c
+++ b/tftf/tests/plat/amd/common/common_files/eemi_api.c
@@ -223,3 +223,17 @@
 
 	return ret;
 }
+
+int xpm_ioctl(const uint32_t node_id, const uint32_t ioctl_id, const uint32_t arg1,
+	      const uint32_t arg2, uint32_t *const response)
+{
+	uint32_t ret_payload[PAYLOAD_ARG_CNT];
+	int ret;
+
+	ret = eemi_call(PM_IOCTL, ((uint64_t)ioctl_id << 32 | node_id),
+			((uint64_t)arg2 << 32 | arg1), 0, 0, 0, 0, 0, ret_payload);
+	if (ret == PM_RET_SUCCESS)
+		*response = ret_payload[1];
+
+	return ret;
+}
diff --git a/tftf/tests/plat/amd/common/common_files/eemi_api.h b/tftf/tests/plat/amd/common/common_files/eemi_api.h
index ebed5a7..8f7eca1 100644
--- a/tftf/tests/plat/amd/common/common_files/eemi_api.h
+++ b/tftf/tests/plat/amd/common/common_files/eemi_api.h
@@ -20,6 +20,13 @@
 	struct xpm_notifier *next;	/**< Pointer to next notifier in linked list */
 } xpm_notifier;
 
+struct test_ioctl {
+	uint32_t node_id;        /**<  Node ID */
+	uint32_t ioctl_id;      /**<  Ioctl ID */
+	uint32_t ioctl_arg1;     /**<  Arg1 for Ioctl-ID if required */
+	uint32_t ioctl_arg2;     /**<  Arg2 for Ioctl-ID if required */
+};
+
 int xpm_get_api_version(uint32_t *version);
 int xpm_get_chip_id(uint32_t *id_code, uint32_t *version);
 int xpm_feature_check(const uint32_t api_id, uint32_t *const version);
@@ -30,5 +37,7 @@
 			const uint32_t qos, const uint32_t ack);
 int xpm_register_notifier(xpm_notifier * const notifier);
 int xpm_unregister_notifier(xpm_notifier * const notifier);
+int xpm_ioctl(const uint32_t node_id, const uint32_t ioctl_id, const uint32_t arg1,
+	      const uint32_t arg2, uint32_t *const response);
 
 #endif /* __EEMI_API_H__ */
diff --git a/tftf/tests/plat/amd/common/common_files/xpm_defs.h b/tftf/tests/plat/amd/common/common_files/xpm_defs.h
index 0e48418..6252dec 100644
--- a/tftf/tests/plat/amd/common/common_files/xpm_defs.h
+++ b/tftf/tests/plat/amd/common/common_files/xpm_defs.h
@@ -31,6 +31,10 @@
 #define PM_GET_CALLBACK_DATA	0xa01U
 #define TF_A_PM_REGISTER_SGI	0xa04U
 
+/* RPU operation mode */
+#define XPM_RPU_MODE_LOCKSTEP   0U
+#define XPM_RPU_MODE_SPLIT      1U
+
 /* API IDs */
 enum pm_api_id {
 	PM_API_MIN,                                     /**< 0x0 */
@@ -134,4 +138,10 @@
 	PM_NOTIFY_CB = 32U,                             /**< Notify callback */
 };
 
+/* IOCTL IDs */
+typedef enum {
+	IOCTL_GET_RPU_OPER_MODE = 0,                    /**< Get RPU mode */
+	IOCTL_SET_RPU_OPER_MODE = 1,                    /**< Set RPU mode */
+} pm_ioctl_id;
+
 #endif /* XPM_DEFS_H_ */
diff --git a/tftf/tests/plat/amd/common/common_files/xpm_nodeid.h b/tftf/tests/plat/amd/common/common_files/xpm_nodeid.h
index e485b67..3a41ed9 100644
--- a/tftf/tests/plat/amd/common/common_files/xpm_nodeid.h
+++ b/tftf/tests/plat/amd/common/common_files/xpm_nodeid.h
@@ -10,6 +10,7 @@
 /*
  * Device Nodes
  */
+#define PM_DEV_RPU0_0           0x18110005U
 #define PM_DEV_USB_0		0x18224018U
 
 #endif /* XPM_NODEID_H_ */
diff --git a/tftf/tests/plat/amd/common/ioctl_test/ioctl_test.c b/tftf/tests/plat/amd/common/ioctl_test/ioctl_test.c
new file mode 100644
index 0000000..e2c0170
--- /dev/null
+++ b/tftf/tests/plat/amd/common/ioctl_test/ioctl_test.c
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2025, Advanced Micro Devices, Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include "eemi_api.h"
+#include "xpm_defs.h"
+#include "xpm_nodeid.h"
+
+struct test_ioctl test_ioctl_list[] = {
+	{
+		.node_id = PM_DEV_RPU0_0,
+		.ioctl_id = IOCTL_GET_RPU_OPER_MODE,
+		.ioctl_arg1 = 0U,
+		.ioctl_arg2 = 0U,
+	},
+	{
+		.node_id = PM_DEV_RPU0_0,
+		.ioctl_id = IOCTL_SET_RPU_OPER_MODE,
+		.ioctl_arg1 = XPM_RPU_MODE_SPLIT,
+		.ioctl_arg2 = 0U,
+	},
+	{
+		.node_id = PM_DEV_RPU0_0,
+		.ioctl_id = IOCTL_GET_RPU_OPER_MODE,
+		.ioctl_arg1 = 0U,
+		.ioctl_arg2 = 0U,
+	},
+};
+
+/*
+ * This function calls IOCTL to firmware for device control and
+ * configuration.
+ */
+test_result_t test_ioctl_api(void)
+{
+	uint32_t ioctl_response = 0U;
+	int32_t status, i;
+
+	for (i = 0; i < (int32_t)ARRAY_SIZE(test_ioctl_list); i++) {
+		status = xpm_ioctl(test_ioctl_list[i].node_id,
+				   test_ioctl_list[i].ioctl_id,
+				   test_ioctl_list[i].ioctl_arg1,
+				   test_ioctl_list[i].ioctl_arg2,
+				   &ioctl_response);
+		if (status != PM_RET_SUCCESS) {
+			tftf_testcase_printf("%s ERROR Fails for IOCTL Id: %u, Status: 0x%x",
+					     __func__, test_ioctl_list[i].ioctl_id, status);
+			return TEST_RESULT_FAIL;
+		}
+
+		if (test_ioctl_list[i].ioctl_id == IOCTL_GET_RPU_OPER_MODE) {
+			tftf_testcase_printf("%s RPU_OPER_MODE: 0x%x\n", __func__,
+					     ioctl_response);
+		} else {
+			tftf_testcase_printf("%s Mode Set done successfully\n",
+					     __func__);
+		}
+	}
+
+	return TEST_RESULT_SUCCESS;
+}
diff --git a/tftf/tests/tests-versal.xml b/tftf/tests/tests-versal.xml
index ce681dd..97fa600 100644
--- a/tftf/tests/tests-versal.xml
+++ b/tftf/tests/tests-versal.xml
@@ -16,6 +16,7 @@
       <testcase name="Get Platform Chip ID" function="test_get_chip_id" />
       <testcase name="Feature Check" function="test_feature_check" />
       <testcase name="Notifier EEMI API" function="test_notifier_api" />
+      <testcase name="Ioctl EEMI API" function="test_ioctl_api" />
     </testsuite>
 
   </testsuites>