rpi3: Implement PSCI_SYSTEM_OFF
This implementation doesn't actually turn the system off, it simply
reboots it and prevents it from booting while keeping it in a low power
mode.
Change-Id: I7f72c9f43f25ba0341db052bc2be4774c88a7ea3
Signed-off-by: Antonio Nino Diaz <antonio.ninodiaz@arm.com>
diff --git a/plat/rpi3/rpi3_pm.c b/plat/rpi3/rpi3_pm.c
index 1d067fb..9694858 100644
--- a/plat/rpi3/rpi3_pm.c
+++ b/plat/rpi3/rpi3_pm.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -150,41 +150,61 @@
}
/*******************************************************************************
- * Platform handler to reboot the system
+ * Platform handlers for system reset and system off.
******************************************************************************/
-#define RESET_TIMEOUT 10
-static void __dead2 rpi3_system_reset(void)
-{
- /* Setup watchdog for reset */
+/* 10 ticks (Watchdog timer = Timer clock / 16) */
+#define RESET_TIMEOUT U(10)
- static const uintptr_t base = RPI3_PM_BASE;
+static void __dead2 rpi3_watchdog_reset(void)
+{
uint32_t rstc;
- INFO("rpi3: PSCI System Reset: invoking watchdog reset\n");
-
console_flush();
- rstc = mmio_read_32(base + RPI3_PM_RSTC_OFFSET);
- rstc &= ~RPI3_PM_RSTC_WRCFG_MASK;
- rstc |= RPI3_PM_RSTC_WRCFG_FULL_RESET;
-
- dmbst();
+ dsbsy();
+ isb();
- /*
- * Watchdog timer = Timer clock / 16
- * Password (31:16) | Value (11:0)
- */
- mmio_write_32(base + RPI3_PM_WDOG_OFFSET,
+ mmio_write_32(RPI3_PM_BASE + RPI3_PM_WDOG_OFFSET,
RPI3_PM_PASSWORD | RESET_TIMEOUT);
- mmio_write_32(base + RPI3_PM_RSTC_OFFSET,
- RPI3_PM_PASSWORD | rstc);
+
+ rstc = mmio_read_32(RPI3_PM_BASE + RPI3_PM_RSTC_OFFSET);
+ rstc &= ~RPI3_PM_RSTC_WRCFG_MASK;
+ rstc |= RPI3_PM_PASSWORD | RPI3_PM_RSTC_WRCFG_FULL_RESET;
+ mmio_write_32(RPI3_PM_BASE + RPI3_PM_RSTC_OFFSET, rstc);
for (;;) {
wfi();
}
}
+static void __dead2 rpi3_system_reset(void)
+{
+ INFO("rpi3: PSCI_SYSTEM_RESET: Invoking watchdog reset\n");
+
+ rpi3_watchdog_reset();
+}
+
+static void __dead2 rpi3_system_off(void)
+{
+ uint32_t rsts;
+
+ INFO("rpi3: PSCI_SYSTEM_OFF: Invoking watchdog reset\n");
+
+ /*
+ * This function doesn't actually make the Raspberry Pi turn itself off,
+ * the hardware doesn't allow it. It simply reboots it and the RSTS
+ * value tells the bootcode.bin firmware not to continue the regular
+ * bootflow and to stay in a low power mode.
+ */
+
+ rsts = mmio_read_32(RPI3_PM_BASE + RPI3_PM_RSTS_OFFSET);
+ rsts |= RPI3_PM_PASSWORD | RPI3_PM_RSTS_WRCFG_HALT;
+ mmio_write_32(RPI3_PM_BASE + RPI3_PM_RSTS_OFFSET, rsts);
+
+ rpi3_watchdog_reset();
+}
+
/*******************************************************************************
* Platform handlers and setup function.
******************************************************************************/
@@ -192,6 +212,7 @@
.cpu_standby = rpi3_cpu_standby,
.pwr_domain_on = rpi3_pwr_domain_on,
.pwr_domain_on_finish = rpi3_pwr_domain_on_finish,
+ .system_off = rpi3_system_off,
.system_reset = rpi3_system_reset,
.validate_power_state = rpi3_validate_power_state,
};