diff options
author | Antonio Nino Diaz <antonio.ninodiaz@arm.com> | 2018-07-14 02:15:51 +0100 |
---|---|---|
committer | Antonio Nino Diaz <antonio.ninodiaz@arm.com> | 2018-07-14 02:15:51 +0100 |
commit | 42ba8f747b154fbc349bfbccd47b5fdd6b4f6d81 (patch) | |
tree | 08c436a97471275a185e24a8307589c5443543b2 | |
parent | 64fe343c03dd1b86c342efde97c3cd94f56d84f6 (diff) | |
download | platform_external_arm-trusted-firmware-42ba8f747b154fbc349bfbccd47b5fdd6b4f6d81.tar.gz platform_external_arm-trusted-firmware-42ba8f747b154fbc349bfbccd47b5fdd6b4f6d81.tar.bz2 platform_external_arm-trusted-firmware-42ba8f747b154fbc349bfbccd47b5fdd6b4f6d81.zip |
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>
-rw-r--r-- | plat/rpi3/rpi3_hw.h | 30 | ||||
-rw-r--r-- | plat/rpi3/rpi3_pm.c | 63 |
2 files changed, 61 insertions, 32 deletions
diff --git a/plat/rpi3/rpi3_hw.h b/plat/rpi3/rpi3_hw.h index 70272e003..f411acbca 100644 --- a/plat/rpi3/rpi3_hw.h +++ b/plat/rpi3/rpi3_hw.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2017, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -17,24 +17,32 @@ #define RPI3_IO_SIZE ULL(0x01000000) /* - * Serial port (called 'Mini UART' in the BCM docucmentation). - */ -#define RPI3_IO_MINI_UART_OFFSET ULL(0x00215040) -#define RPI3_MINI_UART_BASE (RPI3_IO_BASE + RPI3_IO_MINI_UART_OFFSET) -#define RPI3_MINI_UART_CLK_IN_HZ ULL(500000000) - -/* * Power management, reset controller, watchdog. */ #define RPI3_IO_PM_OFFSET ULL(0x00100000) #define RPI3_PM_BASE (RPI3_IO_BASE + RPI3_IO_PM_OFFSET) /* Registers on top of RPI3_PM_BASE. */ #define RPI3_PM_RSTC_OFFSET ULL(0x0000001C) +#define RPI3_PM_RSTS_OFFSET ULL(0x00000020) #define RPI3_PM_WDOG_OFFSET ULL(0x00000024) /* Watchdog constants */ -#define RPI3_PM_PASSWORD ULL(0x5A000000) -#define RPI3_PM_RSTC_WRCFG_MASK ULL(0x00000030) -#define RPI3_PM_RSTC_WRCFG_FULL_RESET ULL(0x00000020) +#define RPI3_PM_PASSWORD U(0x5A000000) +#define RPI3_PM_RSTC_WRCFG_MASK U(0x00000030) +#define RPI3_PM_RSTC_WRCFG_FULL_RESET U(0x00000020) +/* + * The RSTS register is used by the VideoCore firmware when booting the + * Raspberry Pi to know which partition to boot from. The partition value is + * formed by bits 0, 2, 4, 6, 8 and 10. Partition 63 is used by said firmware + * to indicate halt. + */ +#define RPI3_PM_RSTS_WRCFG_HALT U(0x00000555) + +/* + * Serial port (called 'Mini UART' in the BCM docucmentation). + */ +#define RPI3_IO_MINI_UART_OFFSET ULL(0x00215040) +#define RPI3_MINI_UART_BASE (RPI3_IO_BASE + RPI3_IO_MINI_UART_OFFSET) +#define RPI3_MINI_UART_CLK_IN_HZ ULL(500000000) /* * Local interrupt controller diff --git a/plat/rpi3/rpi3_pm.c b/plat/rpi3/rpi3_pm.c index 1d067fb13..96948580e 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 @@ void rpi3_pwr_domain_on_finish(const psci_power_state_t *target_state) } /******************************************************************************* - * 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 @@ static const plat_psci_ops_t plat_rpi3_psci_pm_ops = { .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, }; |