]> www.infradead.org Git - users/dwmw2/linux.git/commitdiff
LoongArch: Add ACPI standard hardware register based S3 support
authorJiaxun Yang <jiaxun.yang@flygoat.com>
Sat, 20 Jul 2024 14:41:06 +0000 (22:41 +0800)
committerHuacai Chen <chenhuacai@loongson.cn>
Sat, 20 Jul 2024 14:41:06 +0000 (22:41 +0800)
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.

Add standard S3 sleep by providing a default 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).

Signed-off-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
Signed-off-by: Huacai Chen <chenhuacai@loongson.cn>
arch/loongarch/power/platform.c
arch/loongarch/power/suspend_asm.S

index a19353f7d1b071212ab7ded9cc81edd07617b955..0909729dc2e153905bff5bd1976feb2558cb439e 100644 (file)
@@ -49,22 +49,34 @@ static int __init loongson_cpufreq_init(void)
 
 arch_initcall(loongson_cpufreq_init);
 
+static void default_suspend_addr(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;
+
+       if (!acpi_gbl_reduced_hardware)
+               acpi_write_bit_register(ACPI_BITREG_SCI_ENABLE, 1);
+
+       if (!acpi_sleep_state_supported(ACPI_STATE_S3))
                return 0;
 
-       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;
+               pr_info("ACPI S3 supported with hardware register default\n");
+               loongson_sysconf.suspend_addr = (u64)default_suspend_addr;
+       } else {
+               pr_info("ACPI S3 supported with Loongson ACPI SADR extension\n");
+               loongson_sysconf.suspend_addr = (u64)phys_to_virt(PHYSADDR(suspend_addr));
        }
-       loongson_sysconf.suspend_addr = (u64)phys_to_virt(PHYSADDR(suspend_addr));
 #endif
        return 0;
 }
index c28ad52b7bafba21fdaaae3e9aa42df36c0c0351..9fe28d5a027037cb708220763e5c39584ae4982f 100644 (file)
@@ -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.