summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/acpi/Kconfig8
-rw-r--r--src/acpi/acpi.c22
-rw-r--r--src/include/acpi/acpi.h94
3 files changed, 124 insertions, 0 deletions
diff --git a/src/acpi/Kconfig b/src/acpi/Kconfig
index 83d18bf62f..417ff60abb 100644
--- a/src/acpi/Kconfig
+++ b/src/acpi/Kconfig
@@ -111,3 +111,11 @@ config ACPI_PPTT_MAX_CACHES
help
This variable sets the maximum number of distinct caches per
topology level. Increasing this option also increases stack usage.
+
+config ACPI_WDAT_WDT
+ bool
+ default n
+ depends on HAVE_ACPI_TABLES
+ help
+ Selected by platforms that support and fill ACPI Watchdog Action Table
+ (WDAT).
diff --git a/src/acpi/acpi.c b/src/acpi/acpi.c
index beba5fdb3a..5e769163b7 100644
--- a/src/acpi/acpi.c
+++ b/src/acpi/acpi.c
@@ -1218,6 +1218,25 @@ static void acpi_create_iort(acpi_header_t *header, void *unused)
header->length = current - (unsigned long)iort;
}
+static void acpi_create_wdat(acpi_header_t *header, void *unused)
+{
+ if (!CONFIG(ACPI_WDAT_WDT))
+ return;
+
+ acpi_wdat_t *wdat = (acpi_wdat_t *)header;
+ unsigned long current = (unsigned long)wdat + sizeof(acpi_wdat_t);
+
+ memset((void *)wdat, 0, sizeof(acpi_wdat_t));
+
+ if (acpi_fill_header(header, "WDAT", WDAT, sizeof(acpi_wdat_t)) != CB_SUCCESS)
+ return;
+
+ current = acpi_soc_fill_wdat(wdat, current);
+
+ /* (Re)calculate length. */
+ header->length = current - (unsigned long)wdat;
+}
+
unsigned long acpi_create_lpi_desc_ncst(acpi_lpi_desc_ncst_t *lpi_desc, uint16_t uid)
{
memset(lpi_desc, 0, sizeof(acpi_lpi_desc_ncst_t));
@@ -1434,6 +1453,7 @@ unsigned long write_acpi_tables(const unsigned long start)
{ acpi_create_gtdt, NULL, sizeof(acpi_gtdt_t) },
{ acpi_create_pptt, NULL, sizeof(acpi_pptt_t) },
{ acpi_create_iort, NULL, sizeof(acpi_iort_t) },
+ { acpi_create_wdat, NULL, sizeof(acpi_wdat_t) },
};
current = start;
@@ -1787,6 +1807,8 @@ int get_acpi_table_revision(enum acpi_tables table)
return 3;
case IORT: /* IO Remapping Table E.e */
return 6;
+ case WDAT:
+ return 1;
default:
return -1;
}
diff --git a/src/include/acpi/acpi.h b/src/include/acpi/acpi.h
index 01504ce7d3..d5f4008358 100644
--- a/src/include/acpi/acpi.h
+++ b/src/include/acpi/acpi.h
@@ -102,6 +102,7 @@ enum acpi_tables {
SSDT, /* Secondary System Description Table */
TCPA, /* Trusted Computing Platform Alliance Table */
TPM2, /* Trusted Platform Module 2.0 Table */
+ WDAT, /* Watchdog Action Table */
XSDT, /* Extended System Description Table */
/* Additional proprietary tables used by coreboot */
CRAT, /* Component Resource Attribute Table */
@@ -1657,6 +1658,70 @@ struct acpi_gtdt_watchdog {
#define ACPI_GTDT_WATCHDOG_IRQ_POLARITY (1<<1)
#define ACPI_GTDT_WATCHDOG_SECURE (1<<2)
+enum acpi_wdat_actions {
+ ACPI_WDAT_RESET = 1,
+ ACPI_WDAT_GET_CURRENT_COUNTDOWN = 4,
+ ACPI_WDAT_GET_COUNTDOWN = 5,
+ ACPI_WDAT_SET_COUNTDOWN = 6,
+ ACPI_WDAT_GET_RUNNING_STATE = 8,
+ ACPI_WDAT_SET_RUNNING_STATE = 9,
+ ACPI_WDAT_GET_STOPPED_STATE = 10,
+ ACPI_WDAT_SET_STOPPED_STATE = 11,
+ ACPI_WDAT_GET_REBOOT = 16,
+ ACPI_WDAT_SET_REBOOT = 17,
+ ACPI_WDAT_GET_SHUTDOWN = 18,
+ ACPI_WDAT_SET_SHUTDOWN = 19,
+ ACPI_WDAT_GET_STATUS = 32,
+ ACPI_WDAT_SET_STATUS = 33,
+ ACPI_WDAT_ACTION_RESERVED = 34 /* 34 and greater are reserved */
+};
+
+enum acpi_wdat_instructions {
+ ACPI_WDAT_READ_VALUE = 0,
+ ACPI_WDAT_READ_COUNTDOWN = 1,
+ ACPI_WDAT_WRITE_VALUE = 2,
+ ACPI_WDAT_WRITE_COUNTDOWN = 3,
+ ACPI_WDAT_INSTRUCTION_RESERVED = 4, /* 4 and greater are reserved */
+ ACPI_WDAT_PRESERVE_REGISTER = 0x80 /* Except for this value */
+};
+
+enum acpi_wdat_flags {
+ ACPI_WDAT_FLAG_DISABLED = 0,
+ ACPI_WDAT_FLAG_ENABLED = 1
+};
+
+enum acpi_wdat_access_size {
+ ACPI_WDAT_ACCESS_SIZE_BYTE = 1,
+ ACPI_WDAT_ACCESS_SIZE_WORD = 2,
+ ACPI_WDAT_ACCESS_SIZE_DWORD = 3
+};
+
+/* ACPI WDAT */
+typedef struct acpi_wdat_entry {
+ u8 action;
+ u8 instruction;
+ u16 reserved;
+ struct acpi_gen_regaddr register_region;
+ u32 value;
+ u32 mask;
+} __packed acpi_wdat_entry_t;
+
+typedef struct acpi_table_wdat {
+ acpi_header_t header; /* Common ACPI table header */
+ u32 header_length;
+ u16 pci_segment;
+ u8 pci_bus;
+ u8 pci_device;
+ u8 pci_function;
+ u8 reserved[3];
+ u32 timer_period;
+ u32 max_count;
+ u32 min_count;
+ u8 flags;
+ u8 reserved2[3];
+ u32 entries;
+} __packed acpi_wdat_t;
+
uintptr_t get_coreboot_rsdp(void);
void acpi_create_einj(acpi_einj_t *einj, uintptr_t addr, u8 actions);
@@ -1819,6 +1884,35 @@ unsigned long acpi_gtdt_add_timer_block(unsigned long current, const uint64_t ad
unsigned long acpi_gtdt_add_watchdog(unsigned long current, uint64_t refresh_frame,
uint64_t control_frame, uint32_t gsiv, uint32_t flags);
+/*
+ * Populate primary acpi_wdat_t struct to provide basic information about watchdog and
+ * associated acpi_wdat_entry_t structures, which correspond to watchdog-related
+ * actions such as start/stop watchdog, set timeout, ping watchdog, get remaining time,
+ * etc. Each acpi_wdat_entry_t entry indicates what needs to be written to a specific
+ * address to perform a specific action or at which address the watchdog-related
+ * information is stored.
+ *
+ * The acpi_wdat_entry_t structures follow the acpi_wdat_t, so the table layout is as
+ * follows:
+ * +---------------------+
+ * | acpi_wdat_t { |
+ * | ... |
+ * | } |
+ * | acpi_wdat_entry_t { |
+ * | ... |
+ * | } |
+ * | acpi_wdat_entry_t { |
+ * | ... |
+ * | } |
+ * +---------------------+
+ *
+ * @param wdat Pointer to populate acpi_wdat_t struct
+ * @param current Position in memory after the acpi_wdat_t struct which also indicates
+ * the position where the first acpi_wdat_entry_t must be placed.
+ * @return Position after last acpi_wdat_entry_t struct
+ */
+unsigned long acpi_soc_fill_wdat(acpi_wdat_t *wdat, unsigned long current);
+
/* For ACPI S3 support. */
void __noreturn acpi_resume(void *wake_vec);
void mainboard_suspend_resume(void);