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>
This commit is contained in:
parent
64fe343c03
commit
42ba8f747b
|
@ -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
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
*/
|
*/
|
||||||
|
@ -16,13 +16,6 @@
|
||||||
#define RPI3_IO_BASE ULL(0x3F000000)
|
#define RPI3_IO_BASE ULL(0x3F000000)
|
||||||
#define RPI3_IO_SIZE ULL(0x01000000)
|
#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.
|
* Power management, reset controller, watchdog.
|
||||||
*/
|
*/
|
||||||
|
@ -30,11 +23,26 @@
|
||||||
#define RPI3_PM_BASE (RPI3_IO_BASE + RPI3_IO_PM_OFFSET)
|
#define RPI3_PM_BASE (RPI3_IO_BASE + RPI3_IO_PM_OFFSET)
|
||||||
/* Registers on top of RPI3_PM_BASE. */
|
/* Registers on top of RPI3_PM_BASE. */
|
||||||
#define RPI3_PM_RSTC_OFFSET ULL(0x0000001C)
|
#define RPI3_PM_RSTC_OFFSET ULL(0x0000001C)
|
||||||
|
#define RPI3_PM_RSTS_OFFSET ULL(0x00000020)
|
||||||
#define RPI3_PM_WDOG_OFFSET ULL(0x00000024)
|
#define RPI3_PM_WDOG_OFFSET ULL(0x00000024)
|
||||||
/* Watchdog constants */
|
/* Watchdog constants */
|
||||||
#define RPI3_PM_PASSWORD ULL(0x5A000000)
|
#define RPI3_PM_PASSWORD U(0x5A000000)
|
||||||
#define RPI3_PM_RSTC_WRCFG_MASK ULL(0x00000030)
|
#define RPI3_PM_RSTC_WRCFG_MASK U(0x00000030)
|
||||||
#define RPI3_PM_RSTC_WRCFG_FULL_RESET ULL(0x00000020)
|
#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
|
* Local interrupt controller
|
||||||
|
|
|
@ -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
|
* 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)
|
/* 10 ticks (Watchdog timer = Timer clock / 16) */
|
||||||
|
#define RESET_TIMEOUT U(10)
|
||||||
|
|
||||||
|
static void __dead2 rpi3_watchdog_reset(void)
|
||||||
{
|
{
|
||||||
/* Setup watchdog for reset */
|
|
||||||
|
|
||||||
static const uintptr_t base = RPI3_PM_BASE;
|
|
||||||
uint32_t rstc;
|
uint32_t rstc;
|
||||||
|
|
||||||
INFO("rpi3: PSCI System Reset: invoking watchdog reset\n");
|
|
||||||
|
|
||||||
console_flush();
|
console_flush();
|
||||||
|
|
||||||
rstc = mmio_read_32(base + RPI3_PM_RSTC_OFFSET);
|
dsbsy();
|
||||||
rstc &= ~RPI3_PM_RSTC_WRCFG_MASK;
|
isb();
|
||||||
rstc |= RPI3_PM_RSTC_WRCFG_FULL_RESET;
|
|
||||||
|
|
||||||
dmbst();
|
mmio_write_32(RPI3_PM_BASE + RPI3_PM_WDOG_OFFSET,
|
||||||
|
|
||||||
/*
|
|
||||||
* Watchdog timer = Timer clock / 16
|
|
||||||
* Password (31:16) | Value (11:0)
|
|
||||||
*/
|
|
||||||
mmio_write_32(base + RPI3_PM_WDOG_OFFSET,
|
|
||||||
RPI3_PM_PASSWORD | RESET_TIMEOUT);
|
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 (;;) {
|
for (;;) {
|
||||||
wfi();
|
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.
|
* 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,
|
.cpu_standby = rpi3_cpu_standby,
|
||||||
.pwr_domain_on = rpi3_pwr_domain_on,
|
.pwr_domain_on = rpi3_pwr_domain_on,
|
||||||
.pwr_domain_on_finish = rpi3_pwr_domain_on_finish,
|
.pwr_domain_on_finish = rpi3_pwr_domain_on_finish,
|
||||||
|
.system_off = rpi3_system_off,
|
||||||
.system_reset = rpi3_system_reset,
|
.system_reset = rpi3_system_reset,
|
||||||
.validate_power_state = rpi3_validate_power_state,
|
.validate_power_state = rpi3_validate_power_state,
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue