Hi, Jiaxun, On Fri, Jun 14, 2024 at 12:41 AM Jiaxun Yang <jiaxun.yang@xxxxxxxxxxx> wrote: > > Most LoongArch 64 machines are using custom "SADR" ACPI extension > to perform ACPI S3 sleep. However the standard ACPI way to perform > sleep is to write a value to ACPI PM1/SLEEP_CTL register, and this > is never supported properly in kernel. Maybe our hardware is insane so we need "SADR", if so, this patch may break real hardware. What's your opinion, Jianmin? Huacai > > Fix standard S3 sleep by providing a fallback DoSuspend function > which calls ACPI's acpi_enter_sleep_state routine when SADR is > not provided by the firmware. > > Also fix suspend assembly code so that ra is set properly before > go into sleep routine. (Previously linked address of jirl was set > to a0, some firmware do require return address in a0 but it's > already set with la.pcrel before). > > Cc: stable@xxxxxxxxxxxxxxx > Signed-off-by: Jiaxun Yang <jiaxun.yang@xxxxxxxxxxx> > --- > arch/loongarch/power/platform.c | 24 ++++++++++++++++++------ > arch/loongarch/power/suspend_asm.S | 2 +- > 2 files changed, 19 insertions(+), 7 deletions(-) > > diff --git a/arch/loongarch/power/platform.c b/arch/loongarch/power/platform.c > index 3ea8e07aa225..2aea41f8e3ff 100644 > --- a/arch/loongarch/power/platform.c > +++ b/arch/loongarch/power/platform.c > @@ -34,22 +34,34 @@ void enable_pci_wakeup(void) > acpi_write_bit_register(ACPI_BITREG_PCIEXP_WAKE_DISABLE, 0); > } > > +static void acpi_suspend_register_fallback(void) > +{ > + acpi_enter_sleep_state(ACPI_STATE_S3); > +} > + > static int __init loongson3_acpi_suspend_init(void) > { > #ifdef CONFIG_ACPI > acpi_status status; > uint64_t suspend_addr = 0; > > - if (acpi_disabled || acpi_gbl_reduced_hardware) > + if (acpi_disabled) > return 0; > > - acpi_write_bit_register(ACPI_BITREG_SCI_ENABLE, 1); > + if (!acpi_sleep_state_supported(ACPI_STATE_S3)) > + return 0; > + > + if (!acpi_gbl_reduced_hardware) > + acpi_write_bit_register(ACPI_BITREG_SCI_ENABLE, 1); > + > status = acpi_evaluate_integer(NULL, "\\SADR", NULL, &suspend_addr); > - if (ACPI_FAILURE(status) || !suspend_addr) { > - pr_err("ACPI S3 is not support!\n"); > - return -1; > + if (!ACPI_FAILURE(status) && suspend_addr) { > + loongson_sysconf.suspend_addr = (u64)phys_to_virt(PHYSADDR(suspend_addr)); > + return 0; > } > - loongson_sysconf.suspend_addr = (u64)phys_to_virt(PHYSADDR(suspend_addr)); > + > + pr_info("ACPI S3 supported with hw register fallback\n"); > + loongson_sysconf.suspend_addr = (u64)acpi_suspend_register_fallback; > #endif > return 0; > } > diff --git a/arch/loongarch/power/suspend_asm.S b/arch/loongarch/power/suspend_asm.S > index 6fdd74eb219b..fe08dbb73c87 100644 > --- a/arch/loongarch/power/suspend_asm.S > +++ b/arch/loongarch/power/suspend_asm.S > @@ -66,7 +66,7 @@ SYM_FUNC_START(loongarch_suspend_enter) > la.pcrel a0, loongarch_wakeup_start > la.pcrel t0, loongarch_suspend_addr > ld.d t0, t0, 0 > - jirl a0, t0, 0 /* Call BIOS's STR sleep routine */ > + jirl ra, t0, 0 /* Call BIOS's STR sleep routine */ > > /* > * This is where we return upon wakeup. > > -- > 2.43.0 > >