Skip to content

Commit 4dc4af9

Browse files
jones-drewpalmer-dabbelt
authored andcommitted
riscv: sbi: Introduce system suspend support
When the SUSP SBI extension is present it implies that the standard "suspend to RAM" type is available. Wire it up to the generic platform suspend support, also applying the already present support for non-retentive CPU suspend. When the kernel is built with CONFIG_SUSPEND, one can do 'echo mem > /sys/power/state' to suspend. Resumption will occur when a platform-specific wake-up event arrives. Signed-off-by: Andrew Jones <[email protected]> Tested-by: Samuel Holland <[email protected]> Reviewed-by: Conor Dooley <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Palmer Dabbelt <[email protected]>
1 parent 3a58275 commit 4dc4af9

File tree

3 files changed

+54
-1
lines changed

3 files changed

+54
-1
lines changed

arch/riscv/Kconfig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ config RISCV
6666
select CLINT_TIMER if !MMU
6767
select CLONE_BACKWARDS
6868
select COMMON_CLK
69-
select CPU_PM if CPU_IDLE || HIBERNATION
69+
select CPU_PM if CPU_IDLE || HIBERNATION || SUSPEND
7070
select EDAC_SUPPORT
7171
select FRAME_POINTER if PERF_EVENTS || (FUNCTION_TRACER && !DYNAMIC_FTRACE)
7272
select GENERIC_ARCH_TOPOLOGY

arch/riscv/include/asm/sbi.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ enum sbi_ext_id {
2929
SBI_EXT_RFENCE = 0x52464E43,
3030
SBI_EXT_HSM = 0x48534D,
3131
SBI_EXT_SRST = 0x53525354,
32+
SBI_EXT_SUSP = 0x53555350,
3233
SBI_EXT_PMU = 0x504D55,
3334
SBI_EXT_DBCN = 0x4442434E,
3435

@@ -114,6 +115,14 @@ enum sbi_srst_reset_reason {
114115
SBI_SRST_RESET_REASON_SYS_FAILURE,
115116
};
116117

118+
enum sbi_ext_susp_fid {
119+
SBI_EXT_SUSP_SYSTEM_SUSPEND = 0,
120+
};
121+
122+
enum sbi_ext_susp_sleep_type {
123+
SBI_SUSP_SLEEP_TYPE_SUSPEND_TO_RAM = 0,
124+
};
125+
117126
enum sbi_ext_pmu_fid {
118127
SBI_EXT_PMU_NUM_COUNTERS = 0,
119128
SBI_EXT_PMU_COUNTER_GET_INFO,

arch/riscv/kernel/suspend.c

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,12 @@
44
* Copyright (c) 2022 Ventana Micro Systems Inc.
55
*/
66

7+
#define pr_fmt(fmt) "suspend: " fmt
8+
79
#include <linux/ftrace.h>
10+
#include <linux/suspend.h>
811
#include <asm/csr.h>
12+
#include <asm/sbi.h>
913
#include <asm/suspend.h>
1014

1115
void suspend_save_csrs(struct suspend_context *context)
@@ -85,3 +89,43 @@ int cpu_suspend(unsigned long arg,
8589

8690
return rc;
8791
}
92+
93+
#ifdef CONFIG_RISCV_SBI
94+
static int sbi_system_suspend(unsigned long sleep_type,
95+
unsigned long resume_addr,
96+
unsigned long opaque)
97+
{
98+
struct sbiret ret;
99+
100+
ret = sbi_ecall(SBI_EXT_SUSP, SBI_EXT_SUSP_SYSTEM_SUSPEND,
101+
sleep_type, resume_addr, opaque, 0, 0, 0);
102+
if (ret.error)
103+
return sbi_err_map_linux_errno(ret.error);
104+
105+
return ret.value;
106+
}
107+
108+
static int sbi_system_suspend_enter(suspend_state_t state)
109+
{
110+
return cpu_suspend(SBI_SUSP_SLEEP_TYPE_SUSPEND_TO_RAM, sbi_system_suspend);
111+
}
112+
113+
static const struct platform_suspend_ops sbi_system_suspend_ops = {
114+
.valid = suspend_valid_only_mem,
115+
.enter = sbi_system_suspend_enter,
116+
};
117+
118+
static int __init sbi_system_suspend_init(void)
119+
{
120+
if (sbi_spec_version >= sbi_mk_version(2, 0) &&
121+
sbi_probe_extension(SBI_EXT_SUSP) > 0) {
122+
pr_info("SBI SUSP extension detected\n");
123+
if (IS_ENABLED(CONFIG_SUSPEND))
124+
suspend_set_ops(&sbi_system_suspend_ops);
125+
}
126+
127+
return 0;
128+
}
129+
130+
arch_initcall(sbi_system_suspend_init);
131+
#endif /* CONFIG_RISCV_SBI */

0 commit comments

Comments
 (0)