xilinx: versal: Add client wakeup API
Implement client wakeup API for versal.
Signed-off-by: Tejas Patel <tejas.patel@xilinx.com>
Signed-off-by: Rajan Vaja <rajan.vaja@xilinx.com>
Signed-off-by: Jolly Shah <jolly.shah@xilinx.com>
Change-Id: I31b1b362fe645a82f89ce2d698ee71eb00cf15dc
diff --git a/plat/xilinx/versal/pm_service/pm_client.c b/plat/xilinx/versal/pm_service/pm_client.c
index 636b719..b234e1b 100644
--- a/plat/xilinx/versal/pm_service/pm_client.c
+++ b/plat/xilinx/versal/pm_service/pm_client.c
@@ -18,6 +18,8 @@
#include <plat/common/platform.h>
#include "pm_client.h"
+#define UNDEFINED_CPUID (~0)
+
DEFINE_BAKERY_LOCK(pm_client_secure_lock);
static const struct pm_ipi apu_ipi = {
@@ -81,6 +83,44 @@
}
/**
+ * pm_get_cpuid() - get the local cpu ID for a global node ID
+ * @nid: node id of the processor
+ *
+ * Return: the cpu ID (starting from 0) for the subsystem
+ */
+static unsigned int pm_get_cpuid(uint32_t nid)
+{
+ for (size_t i = 0; i < ARRAY_SIZE(pm_procs_all); i++) {
+ if (pm_procs_all[i].node_id == nid)
+ return i;
+ }
+ return UNDEFINED_CPUID;
+}
+
+/**
+ * pm_client_wakeup() - Client-specific wakeup actions
+ *
+ * This function should contain any PU-specific actions
+ * required for waking up another APU core
+ */
+void pm_client_wakeup(const struct pm_proc *proc)
+{
+ unsigned int cpuid = pm_get_cpuid(proc->node_id);
+
+ if (cpuid == UNDEFINED_CPUID)
+ return;
+
+ bakery_lock_get(&pm_client_secure_lock);
+
+ /* clear powerdown bit for affected cpu */
+ uint32_t val = mmio_read_32(FPD_APU_PWRCTL);
+ val &= ~(proc->pwrdn_mask);
+ mmio_write_32(FPD_APU_PWRCTL, val);
+
+ bakery_lock_release(&pm_client_secure_lock);
+}
+
+/**
* pm_get_proc() - returns pointer to the proc structure
* @cpuid: id of the cpu whose proc struct pointer should be returned
*
diff --git a/plat/xilinx/versal/pm_service/pm_client.h b/plat/xilinx/versal/pm_service/pm_client.h
index 228094e..91f135c 100644
--- a/plat/xilinx/versal/pm_service/pm_client.h
+++ b/plat/xilinx/versal/pm_service/pm_client.h
@@ -17,6 +17,7 @@
/* Functions to be implemented by each PU */
void pm_client_suspend(const struct pm_proc *proc, unsigned int state);
+void pm_client_wakeup(const struct pm_proc *proc);
void pm_client_abort_suspend(void);
/* Global variables to be set in pm_client.c */