1 // SPDX-License-Identifier: GPL-2.0-only
3 * Copyright (C) 2024, Ventana Micro Systems Inc
4 * Author: Sunil V L <sunilvl@ventanamicro.com>
8 #include <linux/acpi.h>
9 #include <acpi/processor.h>
10 #include <linux/cpu_pm.h>
11 #include <linux/cpuidle.h>
12 #include <linux/suspend.h>
13 #include <asm/cpuidle.h>
15 #include <asm/suspend.h>
17 #define RISCV_FFH_LPI_TYPE_MASK GENMASK_ULL(63, 60)
18 #define RISCV_FFH_LPI_RSVD_MASK GENMASK_ULL(59, 32)
20 #define RISCV_FFH_LPI_TYPE_SBI BIT_ULL(60)
22 static int acpi_cpu_init_idle(unsigned int cpu
)
25 struct acpi_lpi_state
*lpi
;
26 struct acpi_processor
*pr
= per_cpu(processors
, cpu
);
28 if (unlikely(!pr
|| !pr
->flags
.has_lpi
))
31 if (!riscv_sbi_hsm_is_supported())
34 if (pr
->power
.count
<= 1)
37 for (i
= 1; i
< pr
->power
.count
; i
++) {
40 lpi
= &pr
->power
.lpi_states
[i
];
43 * Validate Entry Method as per FFH spec.
44 * bits[63:60] should be 0x1
45 * bits[59:32] should be 0x0
46 * bits[31:0] represent a SBI power_state
48 if (((lpi
->address
& RISCV_FFH_LPI_TYPE_MASK
) != RISCV_FFH_LPI_TYPE_SBI
) ||
49 (lpi
->address
& RISCV_FFH_LPI_RSVD_MASK
)) {
50 pr_warn("Invalid LPI entry method %#llx\n", lpi
->address
);
55 if (!riscv_sbi_suspend_state_is_valid(state
)) {
56 pr_warn("Invalid SBI power state %#x\n", state
);
64 int acpi_processor_ffh_lpi_probe(unsigned int cpu
)
66 return acpi_cpu_init_idle(cpu
);
69 int acpi_processor_ffh_lpi_enter(struct acpi_lpi_state
*lpi
)
71 u32 state
= lpi
->address
;
73 if (state
& SBI_HSM_SUSP_NON_RET_BIT
)
74 return CPU_PM_CPU_IDLE_ENTER_PARAM(riscv_sbi_hart_suspend
,
78 return CPU_PM_CPU_IDLE_ENTER_RETENTION_PARAM(riscv_sbi_hart_suspend
,