summaryrefslogtreecommitdiff
path: root/arch/arm64/lib/system.c
blob: 4e227f6bbcdc2cbd9e3e080feaddef01b079501c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
/* SPDX-License-Identifier: GPL-2.0+ */
/*
 * system.c - system power control, the PSCI SYSTEM_OFF and
 * SYSTEM_RESET backends. off parks the core in WFI forever, the
 * manual's low power entry (D1-2255). reset drives the PE reset
 * domain: RMR_EL2 reset request with the system reset bit, RR bit 1,
 * followed by a barrier pair so the request retires before anything
 * else observes the core.
 *
 * On real hardware a SoC also needs a watchdog or PMIC write for a
 * full board reset, that is board territory, the arch part is this.
 *
 * Copyright (C) 2026 Bradley Morgan <brads@mainlining.org>
 */

#include <debug.h>
#include <stdint.h>

void tb_system_off(void)
{
	dprintf(ALWAYS, "system off\n");

	for (;;) {
		asm volatile("wfi");
	}
}

void tb_system_reset(void)
{
	uint64_t rmr;

	dprintf(ALWAYS, "system reset\n");

	asm volatile("mrs %0, rmr_el2" : "=r" (rmr));
	rmr |= (1 << 1);	/* RR, request reset */
	asm volatile(
		"msr	rmr_el2, %0\n"
		"dsb	sy\n"
		"isb\n"
		:: "r" (rmr));

	/* if the reset domain ignores us, park */
	for (;;) {
		asm volatile("wfi");
	}
}