| // SPDX-License-Identifier: GPL-2.0-only |
| /* |
| * Copyright (C) 2024, Ventana Micro Systems Inc |
| * Author: Sunil V L <sunilvl@ventanamicro.com> |
| * |
| */ |
| |
| #include <linux/acpi.h> |
| #include <acpi/processor.h> |
| #include <linux/cpu_pm.h> |
| #include <linux/cpuidle.h> |
| #include <linux/suspend.h> |
| #include <asm/cpuidle.h> |
| #include <asm/sbi.h> |
| #include <asm/suspend.h> |
| |
| #define RISCV_FFH_LPI_TYPE_MASK GENMASK_ULL(63, 60) |
| #define RISCV_FFH_LPI_RSVD_MASK GENMASK_ULL(59, 32) |
| |
| #define RISCV_FFH_LPI_TYPE_SBI BIT_ULL(60) |
| |
| static int acpi_cpu_init_idle(unsigned int cpu) |
| { |
| int i; |
| struct acpi_lpi_state *lpi; |
| struct acpi_processor *pr = per_cpu(processors, cpu); |
| |
| if (unlikely(!pr || !pr->flags.has_lpi)) |
| return -EINVAL; |
| |
| if (!riscv_sbi_hsm_is_supported()) |
| return -ENODEV; |
| |
| if (pr->power.count <= 1) |
| return -ENODEV; |
| |
| for (i = 1; i < pr->power.count; i++) { |
| u32 state; |
| |
| lpi = &pr->power.lpi_states[i]; |
| |
| /* |
| * Validate Entry Method as per FFH spec. |
| * bits[63:60] should be 0x1 |
| * bits[59:32] should be 0x0 |
| * bits[31:0] represent a SBI power_state |
| */ |
| if (((lpi->address & RISCV_FFH_LPI_TYPE_MASK) != RISCV_FFH_LPI_TYPE_SBI) || |
| (lpi->address & RISCV_FFH_LPI_RSVD_MASK)) { |
| pr_warn("Invalid LPI entry method %#llx\n", lpi->address); |
| return -EINVAL; |
| } |
| |
| state = lpi->address; |
| if (!riscv_sbi_suspend_state_is_valid(state)) { |
| pr_warn("Invalid SBI power state %#x\n", state); |
| return -EINVAL; |
| } |
| } |
| |
| return 0; |
| } |
| |
| int acpi_processor_ffh_lpi_probe(unsigned int cpu) |
| { |
| return acpi_cpu_init_idle(cpu); |
| } |
| |
| int acpi_processor_ffh_lpi_enter(struct acpi_lpi_state *lpi) |
| { |
| u32 state = lpi->address; |
| |
| if (state & SBI_HSM_SUSP_NON_RET_BIT) |
| return CPU_PM_CPU_IDLE_ENTER_PARAM(riscv_sbi_hart_suspend, |
| lpi->index, |
| state); |
| else |
| return CPU_PM_CPU_IDLE_ENTER_RETENTION_PARAM(riscv_sbi_hart_suspend, |
| lpi->index, |
| state); |
| } |