summaryrefslogtreecommitdiff
path: root/plat
diff options
context:
space:
mode:
authorStefan Krsmanovic <stefan.krsmanovic@aggios.com>2016-05-20 15:51:09 +0200
committerSoren Brinkmann <soren.brinkmann@xilinx.com>2016-05-24 10:18:07 -0700
commit03b8077309d9c55118737426c1e1e4bd99c7ae60 (patch)
tree481f6c854f43f6a5d688347845b86834aeaa8049 /plat
parent8212f1f0ee9e99eaf2610d263f251380996bf9f3 (diff)
zynqmp: Add bakery_lock to protect APU_PWRCTRL register access
Access to APU_PWRCTRL register is protected during suspend/wakeup pocedure in order to save valid state. If more than one CPU is accessing this register it can be left in corrupted state during read-modify-write process. Signed-off-by: Stefan Krsmanovic <stefan.krsmanovic@aggios.com> Signed-off-by: Soren Brinkmann <soren.brinkmann@xilinx.com>
Diffstat (limited to 'plat')
-rw-r--r--plat/xilinx/zynqmp/pm_service/pm_client.c15
1 files changed, 15 insertions, 0 deletions
diff --git a/plat/xilinx/zynqmp/pm_service/pm_client.c b/plat/xilinx/zynqmp/pm_service/pm_client.c
index eb986bca..d3396dfa 100644
--- a/plat/xilinx/zynqmp/pm_service/pm_client.c
+++ b/plat/xilinx/zynqmp/pm_service/pm_client.c
@@ -33,6 +33,7 @@
* for getting information about and changing state of the APU.
*/
+#include <bakery_lock.h>
#include <gicv2.h>
#include <bl_common.h>
#include <mmio.h>
@@ -47,6 +48,7 @@
#define OCM_BANK_3 (OCM_BANK_2 + 0x10000)
#define UNDEFINED_CPUID (~0)
+DEFINE_BAKERY_LOCK(pm_client_secure_lock);
/* Declaration of linker defined symbol */
extern unsigned long __BL31_END__;
@@ -162,8 +164,12 @@ const struct pm_proc *primary_proc = &pm_procs_all[0];
*/
void pm_client_suspend(const struct pm_proc *proc)
{
+ bakery_lock_get(&pm_client_secure_lock);
+
/* Set powerdown request */
mmio_write_32(APU_PWRCTL, mmio_read_32(APU_PWRCTL) | proc->pwrdn_mask);
+
+ bakery_lock_release(&pm_client_secure_lock);
}
@@ -177,9 +183,14 @@ void pm_client_abort_suspend(void)
{
/* Enable interrupts at processor level (for current cpu) */
gicv2_cpuif_enable();
+
+ bakery_lock_get(&pm_client_secure_lock);
+
/* Clear powerdown request */
mmio_write_32(APU_PWRCTL,
mmio_read_32(APU_PWRCTL) & ~primary_proc->pwrdn_mask);
+
+ bakery_lock_release(&pm_client_secure_lock);
}
/**
@@ -195,8 +206,12 @@ void pm_client_wakeup(const struct pm_proc *proc)
if (cpuid == UNDEFINED_CPUID)
return;
+ bakery_lock_get(&pm_client_secure_lock);
+
/* clear powerdown bit for affected cpu */
uint32_t val = mmio_read_32(APU_PWRCTL);
val &= ~(proc->pwrdn_mask);
mmio_write_32(APU_PWRCTL, val);
+
+ bakery_lock_release(&pm_client_secure_lock);
}