Skip to content

Commit c422d09

Browse files
committed
lib: acpi: Enable poweroff feature
Enable system poweroff feature using ACPI. Signed-off-by: Anisetti Avinash Krishna <anisetti.avinash.krishna@intel.com>
1 parent 3c7e43f commit c422d09

File tree

4 files changed

+75
-0
lines changed

4 files changed

+75
-0
lines changed

include/zephyr/acpi/acpi.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -299,4 +299,13 @@ ACPI_MADT_LOCAL_APIC *acpi_local_apic_get(int cpu_num);
299299
*/
300300
int acpi_invoke_method(char *path, ACPI_OBJECT_LIST *arg_list, ACPI_OBJECT *ret_obj);
301301

302+
#if defined(CONFIG_ACPI_POWEROFF)
303+
/**
304+
* @brief system level poweroff by setting it to soft off.
305+
*
306+
* @return return EINVAL of the pm1_cnt address is not available.
307+
*/
308+
int acpi_poweroff(void);
309+
#endif
310+
302311
#endif

lib/acpi/Kconfig

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,11 @@ config ACPI_SHELL
3434
help
3535
Enable commands for debugging ACPI using the built-in shell.
3636

37+
config ACPI_POWEROFF
38+
bool "Power off functionality by setting system to S5 power state"
39+
help
40+
Enable support for system power off through ACPI.
41+
3742
config ACPI_DEV_MAX
3843
int "maximum child devices"
3944
default 1000

lib/acpi/acpi.c

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,23 @@
1414
#include <zephyr/logging/log.h>
1515
LOG_MODULE_REGISTER(ACPI, CONFIG_ACPI_LOG_LEVEL);
1616

17+
#if defined(CONFIG_ACPI_POWEROFF)
18+
19+
/* PM1_CNT register */
20+
#if (defined(CONFIG_BOARD_QEMU_X86_64) || defined(CONFIG_BOARD_QEMU_X86))
21+
#define PM1_CNT_SLP_TYP_S5 0x00 /* S5 SLP_TYP is 0 in QEMU */
22+
#elif defined(CONFIG_ACRN_COMMON)
23+
#define PM1_CNT_SLP_TYP_S5 0x05 /* S5 SLP_TYP is 5 in ACRN */
24+
#else
25+
#define PM1_CNT_SLP_TYP_S5 0x07 /* S5 SLP_TYP is 7 in other platforms*/
26+
#endif
27+
28+
#define PM1_CNT_SLP_TYP_SHFT 0x0A /* Shift to SLP_TYP bits(10-12) in PM1_CNT */
29+
30+
#define PM1_CNT_SLP_EN BIT(13) /* Sets SLP_EN bit13 */
31+
32+
#endif
33+
1734
static struct {
1835
struct acpi_dev child_dev[CONFIG_ACPI_DEV_MAX];
1936
int num_dev;
@@ -974,3 +991,34 @@ static int acpi_init(void)
974991
exit:
975992
return status;
976993
}
994+
995+
#if defined(CONFIG_ACPI_POWEROFF)
996+
997+
int acpi_poweroff(void)
998+
{
999+
ACPI_STATUS status;
1000+
uintptr_t pm1_cnt_addr;
1001+
uint32_t pm1_cnt;
1002+
1003+
if (!acpi.early_init) {
1004+
status = acpi_early_init();
1005+
if (status) {
1006+
LOG_ERR("ACPI early init failed");
1007+
return -ENODEV;
1008+
}
1009+
}
1010+
1011+
if (!AcpiGbl_FADT.Pm1aControlBlock) {
1012+
return -EINVAL;
1013+
}
1014+
1015+
pm1_cnt_addr = AcpiGbl_FADT.Pm1aControlBlock;
1016+
1017+
pm1_cnt = sys_in16(pm1_cnt_addr);
1018+
pm1_cnt |= ((PM1_CNT_SLP_TYP_S5 << PM1_CNT_SLP_TYP_SHFT) | PM1_CNT_SLP_EN);
1019+
sys_out16(pm1_cnt, pm1_cnt_addr);
1020+
1021+
return 0;
1022+
}
1023+
1024+
#endif

lib/acpi/acpi_shell.c

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -346,6 +346,16 @@ static int read_table(const struct shell *sh, size_t argc, char **argv)
346346
return 0;
347347
}
348348

349+
#if defined(CONFIG_ACPI_POWEROFF)
350+
351+
static void cmd_acpi_poweroff(const struct shell *sh)
352+
{
353+
if (acpi_poweroff()) {
354+
shell_print(sh, "ACPI poweroff failed due to invalid PM1_CNT address");
355+
}
356+
}
357+
#endif
358+
349359
SHELL_STATIC_SUBCMD_SET_CREATE(
350360
sub_acpi,
351361
SHELL_CMD(crs, NULL,
@@ -366,6 +376,9 @@ SHELL_STATIC_SUBCMD_SET_CREATE(
366376
get_acpi_dev_resource),
367377
SHELL_CMD(rd_table, NULL, "read ACPI table (eg: acpi read_table APIC)",
368378
read_table),
379+
#if defined(CONFIG_ACPI_POWEROFF)
380+
SHELL_CMD(poweroff, NULL, "poweroff the platform", cmd_acpi_poweroff),
381+
#endif
369382
SHELL_SUBCMD_SET_END /* Array terminated. */
370383
);
371384

0 commit comments

Comments
 (0)