diff options
author | Eran Mitrani <mitrani@google.com> | 2022-11-29 17:46:38 -0800 |
---|---|---|
committer | Martin Roth <martin.roth@amd.corp-partner.google.com> | 2022-12-15 16:53:51 +0000 |
commit | 4c9440c673a7343ed98c6a4902d718abc7ac5ab7 (patch) | |
tree | da31825c8faa275d67d2a88a7f7f55df05203d6c /src/soc | |
parent | d27cd2a3284470a177cb0d637e37ca29583c06a5 (diff) |
soc/intel/{adl, common}: provide a list of D-states to enter LPM
This was done previously for ADL. moving the code to common so
it can be leveraged for other platforms (e.g. MTL)
TEST=Built and tested on anahera by verifying SSDT contents
Change-Id: I45eded3868a4987cb5eb0676c50378ac52ec3752
Signed-off-by: Eran Mitrani <mitrani@google.com>
Reviewed-on: https://review.coreboot.org/c/coreboot/+/70166
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Subrata Banik <subratabanik@google.com>
Reviewed-by: Kapil Porwal <kapilporwal@google.com>
Diffstat (limited to 'src/soc')
-rw-r--r-- | src/soc/intel/alderlake/acpi.c | 221 | ||||
-rw-r--r-- | src/soc/intel/common/block/acpi/acpi.c | 2 | ||||
-rw-r--r-- | src/soc/intel/common/block/acpi/pep.c | 122 | ||||
-rw-r--r-- | src/soc/intel/common/block/include/intelblocks/acpi.h | 27 |
4 files changed, 205 insertions, 167 deletions
diff --git a/src/soc/intel/alderlake/acpi.c b/src/soc/intel/alderlake/acpi.c index 9420b005e2..1d92a61ad6 100644 --- a/src/soc/intel/alderlake/acpi.c +++ b/src/soc/intel/alderlake/acpi.c @@ -22,13 +22,6 @@ #include <cpu/cpu.h> #include <types.h> - -#define DEFAULT_CPU_D_STATE D0 -#define LPI_STATES_ALL 0xff -#define LPI_REVISION 0 -#define LPI_ENABLED 1 - - /* * List of supported C-states in this processor. */ @@ -119,14 +112,6 @@ static int cstate_set_s0ix[] = { C_STATE_C10 }; -enum dev_sleep_states { - D0, /* 0 */ - D1, /* 1 */ - D2, /* 2 */ - D3, /* 3 */ - NONE -}; - const acpi_cstate_t *soc_get_cstate_map(size_t *entries) { static acpi_cstate_t map[MAX(ARRAY_SIZE(cstate_set_s0ix), @@ -181,156 +166,68 @@ void soc_fill_fadt(acpi_fadt_t *fadt) fadt->flags |= ACPI_FADT_LOW_PWR_IDLE_S0; } -static const struct { - uint8_t pci_dev; - enum dev_sleep_states min_sleep_state; -} min_pci_sleep_states[] = { - { SA_DEVFN_ROOT, D3 }, - { SA_DEVFN_CPU_PCIE1_0, D3 }, - { SA_DEVFN_IGD, D3 }, - { SA_DEVFN_DPTF, D3 }, - { SA_DEVFN_IPU, D3 }, - { SA_DEVFN_CPU_PCIE6_0, D3 }, - { SA_DEVFN_CPU_PCIE6_2, D3 }, - { SA_DEVFN_TBT0, D3 }, - { SA_DEVFN_TBT1, D3 }, - { SA_DEVFN_TBT2, D3 }, - { SA_DEVFN_TBT3, D3 }, - { SA_DEVFN_GNA, D3 }, - { SA_DEVFN_TCSS_XHCI, D3 }, - { SA_DEVFN_TCSS_XDCI, D3 }, - { SA_DEVFN_TCSS_DMA0, D3 }, - { SA_DEVFN_TCSS_DMA1, D3 }, - { SA_DEVFN_VMD, D3 }, - { PCH_DEVFN_I2C6, D3 }, - { PCH_DEVFN_I2C7, D3 }, - { PCH_DEVFN_THC0, D3 }, - { PCH_DEVFN_THC1, D3 }, - { PCH_DEVFN_XHCI, D3 }, - { PCH_DEVFN_USBOTG, D3 }, - { PCH_DEVFN_SRAM, D3 }, - { PCH_DEVFN_CNVI_WIFI, D3 }, - { PCH_DEVFN_I2C0, D3 }, - { PCH_DEVFN_I2C1, D3 }, - { PCH_DEVFN_I2C2, D3 }, - { PCH_DEVFN_I2C3, D3 }, - { PCH_DEVFN_CSE, D0 }, - { PCH_DEVFN_SATA, D3 }, - { PCH_DEVFN_I2C4, D3 }, - { PCH_DEVFN_I2C5, D3 }, - { PCH_DEVFN_UART2, D3 }, - { PCH_DEVFN_PCIE1, D0 }, - { PCH_DEVFN_PCIE2, D0 }, - { PCH_DEVFN_PCIE3, D0 }, - { PCH_DEVFN_PCIE4, D0 }, - { PCH_DEVFN_PCIE5, D0 }, - { PCH_DEVFN_PCIE6, D0 }, - { PCH_DEVFN_PCIE7, D0 }, - { PCH_DEVFN_PCIE8, D0 }, - { PCH_DEVFN_PCIE9, D0 }, - { PCH_DEVFN_PCIE10, D0 }, - { PCH_DEVFN_PCIE11, D0 }, - { PCH_DEVFN_PCIE12, D0 }, - { PCH_DEVFN_UART0, D3 }, - { PCH_DEVFN_UART1, D3 }, - { PCH_DEVFN_GSPI0, D3 }, - { PCH_DEVFN_GSPI1, D3 }, - { PCH_DEVFN_ESPI, D0 }, - { PCH_DEVFN_PMC, D0 }, - { PCH_DEVFN_HDA, D0 }, - { PCH_DEVFN_SPI, D3 }, - { PCH_DEVFN_GBE, D3 }, +static struct min_sleep_state min_pci_sleep_states[] = { + { SA_DEVFN_ROOT, ACPI_DEVICE_SLEEP_D3 }, + { SA_DEVFN_CPU_PCIE1_0, ACPI_DEVICE_SLEEP_D3 }, + { SA_DEVFN_IGD, ACPI_DEVICE_SLEEP_D3 }, + { SA_DEVFN_DPTF, ACPI_DEVICE_SLEEP_D3 }, + { SA_DEVFN_IPU, ACPI_DEVICE_SLEEP_D3 }, + { SA_DEVFN_CPU_PCIE6_0, ACPI_DEVICE_SLEEP_D3 }, + { SA_DEVFN_CPU_PCIE6_2, ACPI_DEVICE_SLEEP_D3 }, + { SA_DEVFN_TBT0, ACPI_DEVICE_SLEEP_D3 }, + { SA_DEVFN_TBT1, ACPI_DEVICE_SLEEP_D3 }, + { SA_DEVFN_TBT2, ACPI_DEVICE_SLEEP_D3 }, + { SA_DEVFN_TBT3, ACPI_DEVICE_SLEEP_D3 }, + { SA_DEVFN_GNA, ACPI_DEVICE_SLEEP_D3 }, + { SA_DEVFN_TCSS_XHCI, ACPI_DEVICE_SLEEP_D3 }, + { SA_DEVFN_TCSS_XDCI, ACPI_DEVICE_SLEEP_D3 }, + { SA_DEVFN_TCSS_DMA0, ACPI_DEVICE_SLEEP_D3 }, + { SA_DEVFN_TCSS_DMA1, ACPI_DEVICE_SLEEP_D3 }, + { SA_DEVFN_VMD, ACPI_DEVICE_SLEEP_D3 }, + { PCH_DEVFN_I2C6, ACPI_DEVICE_SLEEP_D3 }, + { PCH_DEVFN_I2C7, ACPI_DEVICE_SLEEP_D3 }, + { PCH_DEVFN_THC0, ACPI_DEVICE_SLEEP_D3 }, + { PCH_DEVFN_THC1, ACPI_DEVICE_SLEEP_D3 }, + { PCH_DEVFN_XHCI, ACPI_DEVICE_SLEEP_D3 }, + { PCH_DEVFN_USBOTG, ACPI_DEVICE_SLEEP_D3 }, + { PCH_DEVFN_SRAM, ACPI_DEVICE_SLEEP_D3 }, + { PCH_DEVFN_CNVI_WIFI, ACPI_DEVICE_SLEEP_D3 }, + { PCH_DEVFN_I2C0, ACPI_DEVICE_SLEEP_D3 }, + { PCH_DEVFN_I2C1, ACPI_DEVICE_SLEEP_D3 }, + { PCH_DEVFN_I2C2, ACPI_DEVICE_SLEEP_D3 }, + { PCH_DEVFN_I2C3, ACPI_DEVICE_SLEEP_D3 }, + { PCH_DEVFN_CSE, ACPI_DEVICE_SLEEP_D0 }, + { PCH_DEVFN_SATA, ACPI_DEVICE_SLEEP_D3 }, + { PCH_DEVFN_I2C4, ACPI_DEVICE_SLEEP_D3 }, + { PCH_DEVFN_I2C5, ACPI_DEVICE_SLEEP_D3 }, + { PCH_DEVFN_UART2, ACPI_DEVICE_SLEEP_D3 }, + { PCH_DEVFN_PCIE1, ACPI_DEVICE_SLEEP_D0 }, + { PCH_DEVFN_PCIE2, ACPI_DEVICE_SLEEP_D0 }, + { PCH_DEVFN_PCIE3, ACPI_DEVICE_SLEEP_D0 }, + { PCH_DEVFN_PCIE4, ACPI_DEVICE_SLEEP_D0 }, + { PCH_DEVFN_PCIE5, ACPI_DEVICE_SLEEP_D0 }, + { PCH_DEVFN_PCIE6, ACPI_DEVICE_SLEEP_D0 }, + { PCH_DEVFN_PCIE7, ACPI_DEVICE_SLEEP_D0 }, + { PCH_DEVFN_PCIE8, ACPI_DEVICE_SLEEP_D0 }, + { PCH_DEVFN_PCIE9, ACPI_DEVICE_SLEEP_D0 }, + { PCH_DEVFN_PCIE10, ACPI_DEVICE_SLEEP_D0 }, + { PCH_DEVFN_PCIE11, ACPI_DEVICE_SLEEP_D0 }, + { PCH_DEVFN_PCIE12, ACPI_DEVICE_SLEEP_D0 }, + { PCH_DEVFN_UART0, ACPI_DEVICE_SLEEP_D3 }, + { PCH_DEVFN_UART1, ACPI_DEVICE_SLEEP_D3 }, + { PCH_DEVFN_GSPI0, ACPI_DEVICE_SLEEP_D3 }, + { PCH_DEVFN_GSPI1, ACPI_DEVICE_SLEEP_D3 }, + { PCH_DEVFN_ESPI, ACPI_DEVICE_SLEEP_D0 }, + { PCH_DEVFN_PMC, ACPI_DEVICE_SLEEP_D0 }, + { PCH_DEVFN_HDA, ACPI_DEVICE_SLEEP_D0 }, + { PCH_DEVFN_SPI, ACPI_DEVICE_SLEEP_D3 }, + { PCH_DEVFN_GBE, ACPI_DEVICE_SLEEP_D3 }, }; -static enum dev_sleep_states get_min_sleep_state(const struct device *dev) +struct min_sleep_state *soc_get_min_sleep_state_array(size_t *size) { - if (!is_dev_enabled(dev)) - return NONE; - - switch (dev->path.type) { - case DEVICE_PATH_APIC: - return DEFAULT_CPU_D_STATE; - - case DEVICE_PATH_PCI: - /* skip external buses*/ - if (dev->bus->secondary != 0) - return NONE; - for (size_t i = 0; i < ARRAY_SIZE(min_pci_sleep_states); i++) - if (min_pci_sleep_states[i].pci_dev == dev->path.pci.devfn) - return min_pci_sleep_states[i].min_sleep_state; - printk(BIOS_WARNING, "Unknown min d_state for %x\n", dev->path.pci.devfn); - return NONE; - - default: - return NONE; - } -} - -/* Generate the LPI constraint table and return the number of devices included */ -void soc_lpi_get_constraints(void *unused) -{ - unsigned int num_entries; - const struct device *dev; - enum dev_sleep_states min_sleep_state; - - num_entries = 0; - - for (dev = all_devices; dev; dev = dev->next) { - if (get_min_sleep_state(dev) != NONE) - num_entries++; - } - - acpigen_emit_byte(RETURN_OP); - acpigen_write_package(num_entries); - - size_t cpu_index = 0; - for (dev = all_devices; dev; dev = dev->next) { - min_sleep_state = get_min_sleep_state(dev); - if (min_sleep_state == NONE) - continue; - - acpigen_write_package(3); - { - char path[32] = { 0 }; - /* Emit the device path */ - switch (dev->path.type) { - case DEVICE_PATH_PCI: - acpigen_emit_namestring(acpi_device_path(dev)); - break; - - case DEVICE_PATH_APIC: - snprintf(path, sizeof(path), CONFIG_ACPI_CPU_STRING, - cpu_index++); - acpigen_emit_namestring(path); - break; - - default: - /* Unhandled */ - printk(BIOS_WARNING, - "Unhandled device path type %d\n", dev->path.type); - acpigen_emit_namestring(NULL); - break; - } - - acpigen_write_integer(LPI_ENABLED); - acpigen_write_package(2); - { - acpigen_write_integer(LPI_REVISION); - acpigen_write_package(2); /* no optional device info */ - { - /* Assume constraints apply to all entries */ - acpigen_write_integer(LPI_STATES_ALL); - acpigen_write_integer(min_sleep_state); /* min D-state */ - } - acpigen_write_package_end(); - } - acpigen_write_package_end(); - } - acpigen_write_package_end(); - } - - acpigen_write_package_end(); - printk(BIOS_INFO, "Returning SoC specific constraint package for %d devices\n", num_entries); + *size = ARRAY_SIZE(min_pci_sleep_states); + return min_pci_sleep_states; } uint32_t soc_read_sci_irq_select(void) diff --git a/src/soc/intel/common/block/acpi/acpi.c b/src/soc/intel/common/block/acpi/acpi.c index 010f23d287..4b3cb8a50b 100644 --- a/src/soc/intel/common/block/acpi/acpi.c +++ b/src/soc/intel/common/block/acpi/acpi.c @@ -1,5 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-or-later */ +#include <acpi/acpi.h> #include <acpi/acpi_pm.h> #include <acpi/acpigen.h> #include <arch/ioapic.h> @@ -69,7 +70,6 @@ static unsigned long acpi_madt_irq_overrides(unsigned long current) current += acpi_create_madt_irqoverride((void *)current, 0, sci, sci, flags); - return current; } diff --git a/src/soc/intel/common/block/acpi/pep.c b/src/soc/intel/common/block/acpi/pep.c index 2ba9f94573..2dd094908e 100644 --- a/src/soc/intel/common/block/acpi/pep.c +++ b/src/soc/intel/common/block/acpi/pep.c @@ -23,10 +23,20 @@ #define RESTORE_PM_BITS_HOOK "\\_SB.PCI0.RGPM" #define THUNDERBOLT_DEVICE "\\_SB.PCI0.TXHC" #define THUNDERBOLT_IOM_DPOF "\\_SB.PCI0.DPOF" -#define LPI_STATES_ALL 0xff -#define MIN_DEVICE_STATE ACPI_DEVICE_SLEEP_D0 #define PEPD_SCOPE "\\_SB.PCI0" +#define MIN_DEVICE_STATE ACPI_DEVICE_SLEEP_D0 +#define LPI_STATES_ALL 0xff + +enum { + LPI_REVISION_0 = 0, +}; + +enum { + LPI_DISABLED = 0, + LPI_ENABLED = 1, +}; + struct reg_info { uint8_t *addr; size_t buffer_size; @@ -81,7 +91,7 @@ static void read_pmc_lpm_requirements(const struct soc_pmc_lpm *lpm, * device, one that is known to exist, i.e. ACPI_CPU_STRING. expects at least * one device and crashes without it with a bluescreen. */ -__weak void soc_lpi_get_constraints(void *unused) +static void acpi_gen_default_lpi_constraints(void) { char path[16]; printk(BIOS_INFO, "Returning default LPI constraint package\n"); @@ -117,6 +127,110 @@ __weak void soc_lpi_get_constraints(void *unused) acpigen_write_package_end(); } +__weak struct min_sleep_state *soc_get_min_sleep_state_array(size_t *size) +{ + printk(BIOS_DEBUG, "Empty min sleep state array returned\n"); + *size = 0; + return NULL; +} + +static enum acpi_device_sleep_states get_min_sleep_state( + const struct device *dev, struct min_sleep_state *states_arr, size_t size) +{ + if (!is_dev_enabled(dev)) + return ACPI_DEVICE_SLEEP_NONE; + switch (dev->path.type) { + case DEVICE_PATH_APIC: + return MIN_DEVICE_STATE; + + case DEVICE_PATH_PCI: + /* skip external buses*/ + if ((dev->bus->secondary != 0) || (!states_arr)) + return ACPI_DEVICE_SLEEP_NONE; + for (size_t i = 0; i < size; i++) + if (states_arr[i].pci_dev == dev->path.pci.devfn) + return states_arr[i].min_sleep_state; + printk(BIOS_WARNING, "Unknown min d_state for %x\n", dev->path.pci.devfn); + return ACPI_DEVICE_SLEEP_NONE; + + default: + return ACPI_DEVICE_SLEEP_NONE; + } +} + +/* Generate the LPI constraint table */ +static void acpi_lpi_get_constraints(void *unused) +{ + unsigned int num_entries = 0; + const struct device *dev; + enum acpi_device_sleep_states min_sleep_state; + size_t size; + struct min_sleep_state *states_arr = soc_get_min_sleep_state_array(&size); + + if (size && states_arr) { + for (dev = all_devices; dev; dev = dev->next) { + if (get_min_sleep_state(dev, states_arr, size) + != ACPI_DEVICE_SLEEP_NONE) + num_entries++; + } + } + if (!num_entries) { + acpi_gen_default_lpi_constraints(); + } else { + acpigen_emit_byte(RETURN_OP); + acpigen_write_package(num_entries); + + size_t cpu_index = 0; + for (dev = all_devices; dev; dev = dev->next) { + min_sleep_state = get_min_sleep_state(dev, states_arr, size); + if (min_sleep_state == ACPI_DEVICE_SLEEP_NONE) + continue; + + acpigen_write_package(3); + { + char path[32] = { 0 }; + /* Emit the device path */ + switch (dev->path.type) { + case DEVICE_PATH_PCI: + acpigen_emit_namestring(acpi_device_path(dev)); + break; + + case DEVICE_PATH_APIC: + snprintf(path, sizeof(path), CONFIG_ACPI_CPU_STRING, + cpu_index++); + acpigen_emit_namestring(path); + break; + + default: + /* Unhandled */ + printk(BIOS_WARNING, + "Unhandled device path type %d\n", + dev->path.type); + acpigen_emit_namestring(NULL); + break; + } + + acpigen_write_integer(LPI_ENABLED); + acpigen_write_package(2); + { + acpigen_write_integer(LPI_REVISION_0); + acpigen_write_package(2); /* no optional device info */ + { + /* Assume constraints apply to all entries */ + acpigen_write_integer(LPI_STATES_ALL); + /* min D-state */ + acpigen_write_integer(min_sleep_state); + } + acpigen_write_package_end(); + } + acpigen_write_package_end(); + } + acpigen_write_package_end(); + } + acpigen_write_package_end(); + } +} + static void lpi_s0ix_entry(void *unused) { /* Inform the EC */ @@ -200,7 +314,7 @@ static void lpi_display_off(void *unused) static void (*lpi_s0_helpers[])(void *) = { NULL, /* enumerate functions (autogenerated) */ - soc_lpi_get_constraints,/* get device constraints */ + acpi_lpi_get_constraints,/* get device constraints */ NULL, /* get crash dump device */ lpi_display_off, /* display off notify */ lpi_display_on, /* display on notify */ diff --git a/src/soc/intel/common/block/include/intelblocks/acpi.h b/src/soc/intel/common/block/include/intelblocks/acpi.h index b03f6ccb2b..c149c6939e 100644 --- a/src/soc/intel/common/block/include/intelblocks/acpi.h +++ b/src/soc/intel/common/block/include/intelblocks/acpi.h @@ -127,4 +127,31 @@ enum core_type get_soc_cpu_type(void); /* Check if CPU supports Nominal frequency or not */ bool soc_is_nominal_freq_supported(void); + +/* Min sleep state per device*/ +struct min_sleep_state { + uint8_t pci_dev; + enum acpi_device_sleep_states min_sleep_state; +}; + +/* + * This SOC callback returns an array that maps devices to their min sleep state. + * Example: + * + * static struct min_sleep_state min_pci_sleep_states[] = { + * { SA_DEVFN_ROOT, ACPI_DEVICE_SLEEP_D3 }, + * { SA_DEVFN_CPU_PCIE1_0, ACPI_DEVICE_SLEEP_D3 }, + * { SA_DEVFN_IGD, ACPI_DEVICE_SLEEP_D3 }, + * ... + * }; + * + * const struct pad_config *variant_early_gpio_table(size_t *num) + * { + * *num = ARRAY_SIZE(early_gpio_table); + * return early_gpio_table; + * } + * + */ +struct min_sleep_state *soc_get_min_sleep_state_array(size_t *size); + #endif /* _SOC_INTEL_COMMON_BLOCK_ACPI_H_ */ |