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>
This commit is contained in:
		
				
					committed by
					
						
						Martin Roth
					
				
			
			
				
	
			
			
			
						parent
						
							d27cd2a328
						
					
				
				
					commit
					4c9440c673
				
			@@ -51,6 +51,7 @@ enum acpi_device_sleep_states {
 | 
				
			|||||||
	ACPI_DEVICE_SLEEP_D3		= 3,
 | 
						ACPI_DEVICE_SLEEP_D3		= 3,
 | 
				
			||||||
	ACPI_DEVICE_SLEEP_D3_HOT	= ACPI_DEVICE_SLEEP_D3,
 | 
						ACPI_DEVICE_SLEEP_D3_HOT	= ACPI_DEVICE_SLEEP_D3,
 | 
				
			||||||
	ACPI_DEVICE_SLEEP_D3_COLD	= 4,
 | 
						ACPI_DEVICE_SLEEP_D3_COLD	= 4,
 | 
				
			||||||
 | 
						ACPI_DEVICE_SLEEP_NONE		= 5,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define RSDP_SIG		"RSD PTR "  /* RSDT pointer signature */
 | 
					#define RSDP_SIG		"RSD PTR "  /* RSDT pointer signature */
 | 
				
			||||||
@@ -1283,7 +1284,6 @@ typedef struct acpi_einj {
 | 
				
			|||||||
	acpi_einj_action_table_t action_table[ACTION_COUNT];
 | 
						acpi_einj_action_table_t action_table[ACTION_COUNT];
 | 
				
			||||||
} __packed acpi_einj_t;
 | 
					} __packed acpi_einj_t;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
uintptr_t get_coreboot_rsdp(void);
 | 
					uintptr_t get_coreboot_rsdp(void);
 | 
				
			||||||
void acpi_create_einj(acpi_einj_t *einj, uintptr_t addr, u8 actions);
 | 
					void acpi_create_einj(acpi_einj_t *einj, uintptr_t addr, u8 actions);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -1298,8 +1298,6 @@ void acpi_create_ssdt_generator(acpi_header_t *ssdt, const char *oem_table_id);
 | 
				
			|||||||
void acpi_write_bert(acpi_bert_t *bert, uintptr_t region, size_t length);
 | 
					void acpi_write_bert(acpi_bert_t *bert, uintptr_t region, size_t length);
 | 
				
			||||||
void acpi_create_fadt(acpi_fadt_t *fadt, acpi_facs_t *facs, void *dsdt);
 | 
					void acpi_create_fadt(acpi_fadt_t *fadt, acpi_facs_t *facs, void *dsdt);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void soc_lpi_get_constraints(void *unused);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void acpi_fill_fadt(acpi_fadt_t *fadt);
 | 
					void acpi_fill_fadt(acpi_fadt_t *fadt);
 | 
				
			||||||
void arch_fill_fadt(acpi_fadt_t *fadt);
 | 
					void arch_fill_fadt(acpi_fadt_t *fadt);
 | 
				
			||||||
void soc_fill_fadt(acpi_fadt_t *fadt);
 | 
					void soc_fill_fadt(acpi_fadt_t *fadt);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -22,13 +22,6 @@
 | 
				
			|||||||
#include <cpu/cpu.h>
 | 
					#include <cpu/cpu.h>
 | 
				
			||||||
#include <types.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.
 | 
					 * List of supported C-states in this processor.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
@@ -119,14 +112,6 @@ static int cstate_set_s0ix[] = {
 | 
				
			|||||||
	C_STATE_C10
 | 
						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)
 | 
					const acpi_cstate_t *soc_get_cstate_map(size_t *entries)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	static acpi_cstate_t map[MAX(ARRAY_SIZE(cstate_set_s0ix),
 | 
						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;
 | 
							fadt->flags |= ACPI_FADT_LOW_PWR_IDLE_S0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static const struct {
 | 
					static struct min_sleep_state min_pci_sleep_states[] = {
 | 
				
			||||||
	uint8_t pci_dev;
 | 
						{ SA_DEVFN_ROOT,	ACPI_DEVICE_SLEEP_D3 },
 | 
				
			||||||
	enum dev_sleep_states min_sleep_state;
 | 
						{ SA_DEVFN_CPU_PCIE1_0,	ACPI_DEVICE_SLEEP_D3 },
 | 
				
			||||||
} min_pci_sleep_states[] = {
 | 
						{ SA_DEVFN_IGD,		ACPI_DEVICE_SLEEP_D3 },
 | 
				
			||||||
	{ SA_DEVFN_ROOT,	D3 },
 | 
						{ SA_DEVFN_DPTF,	ACPI_DEVICE_SLEEP_D3 },
 | 
				
			||||||
	{ SA_DEVFN_CPU_PCIE1_0,	D3 },
 | 
						{ SA_DEVFN_IPU,		ACPI_DEVICE_SLEEP_D3 },
 | 
				
			||||||
	{ SA_DEVFN_IGD,		D3 },
 | 
						{ SA_DEVFN_CPU_PCIE6_0,	ACPI_DEVICE_SLEEP_D3 },
 | 
				
			||||||
	{ SA_DEVFN_DPTF,	D3 },
 | 
						{ SA_DEVFN_CPU_PCIE6_2,	ACPI_DEVICE_SLEEP_D3 },
 | 
				
			||||||
	{ SA_DEVFN_IPU,		D3 },
 | 
						{ SA_DEVFN_TBT0,	ACPI_DEVICE_SLEEP_D3 },
 | 
				
			||||||
	{ SA_DEVFN_CPU_PCIE6_0,	D3 },
 | 
						{ SA_DEVFN_TBT1,	ACPI_DEVICE_SLEEP_D3 },
 | 
				
			||||||
	{ SA_DEVFN_CPU_PCIE6_2,	D3 },
 | 
						{ SA_DEVFN_TBT2,	ACPI_DEVICE_SLEEP_D3 },
 | 
				
			||||||
	{ SA_DEVFN_TBT0,	D3 },
 | 
						{ SA_DEVFN_TBT3,	ACPI_DEVICE_SLEEP_D3 },
 | 
				
			||||||
	{ SA_DEVFN_TBT1,	D3 },
 | 
						{ SA_DEVFN_GNA,		ACPI_DEVICE_SLEEP_D3 },
 | 
				
			||||||
	{ SA_DEVFN_TBT2,	D3 },
 | 
						{ SA_DEVFN_TCSS_XHCI,	ACPI_DEVICE_SLEEP_D3 },
 | 
				
			||||||
	{ SA_DEVFN_TBT3,	D3 },
 | 
						{ SA_DEVFN_TCSS_XDCI,	ACPI_DEVICE_SLEEP_D3 },
 | 
				
			||||||
	{ SA_DEVFN_GNA,		D3 },
 | 
						{ SA_DEVFN_TCSS_DMA0,	ACPI_DEVICE_SLEEP_D3 },
 | 
				
			||||||
	{ SA_DEVFN_TCSS_XHCI,	D3 },
 | 
						{ SA_DEVFN_TCSS_DMA1,	ACPI_DEVICE_SLEEP_D3 },
 | 
				
			||||||
	{ SA_DEVFN_TCSS_XDCI,	D3 },
 | 
						{ SA_DEVFN_VMD,		ACPI_DEVICE_SLEEP_D3 },
 | 
				
			||||||
	{ SA_DEVFN_TCSS_DMA0,	D3 },
 | 
						{ PCH_DEVFN_I2C6,	ACPI_DEVICE_SLEEP_D3 },
 | 
				
			||||||
	{ SA_DEVFN_TCSS_DMA1,	D3 },
 | 
						{ PCH_DEVFN_I2C7,	ACPI_DEVICE_SLEEP_D3 },
 | 
				
			||||||
	{ SA_DEVFN_VMD,		D3 },
 | 
						{ PCH_DEVFN_THC0,	ACPI_DEVICE_SLEEP_D3 },
 | 
				
			||||||
	{ PCH_DEVFN_I2C6,	D3 },
 | 
						{ PCH_DEVFN_THC1,	ACPI_DEVICE_SLEEP_D3 },
 | 
				
			||||||
	{ PCH_DEVFN_I2C7,	D3 },
 | 
						{ PCH_DEVFN_XHCI,	ACPI_DEVICE_SLEEP_D3 },
 | 
				
			||||||
	{ PCH_DEVFN_THC0,	D3 },
 | 
						{ PCH_DEVFN_USBOTG,	ACPI_DEVICE_SLEEP_D3 },
 | 
				
			||||||
	{ PCH_DEVFN_THC1,	D3 },
 | 
						{ PCH_DEVFN_SRAM,	ACPI_DEVICE_SLEEP_D3 },
 | 
				
			||||||
	{ PCH_DEVFN_XHCI,	D3 },
 | 
						{ PCH_DEVFN_CNVI_WIFI,	ACPI_DEVICE_SLEEP_D3 },
 | 
				
			||||||
	{ PCH_DEVFN_USBOTG,	D3 },
 | 
						{ PCH_DEVFN_I2C0,	ACPI_DEVICE_SLEEP_D3 },
 | 
				
			||||||
	{ PCH_DEVFN_SRAM,	D3 },
 | 
						{ PCH_DEVFN_I2C1,	ACPI_DEVICE_SLEEP_D3 },
 | 
				
			||||||
	{ PCH_DEVFN_CNVI_WIFI,	D3 },
 | 
						{ PCH_DEVFN_I2C2,	ACPI_DEVICE_SLEEP_D3 },
 | 
				
			||||||
	{ PCH_DEVFN_I2C0,	D3 },
 | 
						{ PCH_DEVFN_I2C3,	ACPI_DEVICE_SLEEP_D3 },
 | 
				
			||||||
	{ PCH_DEVFN_I2C1,	D3 },
 | 
						{ PCH_DEVFN_CSE,	ACPI_DEVICE_SLEEP_D0 },
 | 
				
			||||||
	{ PCH_DEVFN_I2C2,	D3 },
 | 
						{ PCH_DEVFN_SATA,	ACPI_DEVICE_SLEEP_D3 },
 | 
				
			||||||
	{ PCH_DEVFN_I2C3,	D3 },
 | 
						{ PCH_DEVFN_I2C4,	ACPI_DEVICE_SLEEP_D3 },
 | 
				
			||||||
	{ PCH_DEVFN_CSE,	D0 },
 | 
						{ PCH_DEVFN_I2C5,	ACPI_DEVICE_SLEEP_D3 },
 | 
				
			||||||
	{ PCH_DEVFN_SATA,	D3 },
 | 
						{ PCH_DEVFN_UART2,	ACPI_DEVICE_SLEEP_D3 },
 | 
				
			||||||
	{ PCH_DEVFN_I2C4,	D3 },
 | 
						{ PCH_DEVFN_PCIE1,	ACPI_DEVICE_SLEEP_D0 },
 | 
				
			||||||
	{ PCH_DEVFN_I2C5,	D3 },
 | 
						{ PCH_DEVFN_PCIE2,	ACPI_DEVICE_SLEEP_D0 },
 | 
				
			||||||
	{ PCH_DEVFN_UART2,	D3 },
 | 
						{ PCH_DEVFN_PCIE3,	ACPI_DEVICE_SLEEP_D0 },
 | 
				
			||||||
	{ PCH_DEVFN_PCIE1,	D0 },
 | 
						{ PCH_DEVFN_PCIE4,	ACPI_DEVICE_SLEEP_D0 },
 | 
				
			||||||
	{ PCH_DEVFN_PCIE2,	D0 },
 | 
						{ PCH_DEVFN_PCIE5,	ACPI_DEVICE_SLEEP_D0 },
 | 
				
			||||||
	{ PCH_DEVFN_PCIE3,	D0 },
 | 
						{ PCH_DEVFN_PCIE6,	ACPI_DEVICE_SLEEP_D0 },
 | 
				
			||||||
	{ PCH_DEVFN_PCIE4,	D0 },
 | 
						{ PCH_DEVFN_PCIE7,	ACPI_DEVICE_SLEEP_D0 },
 | 
				
			||||||
	{ PCH_DEVFN_PCIE5,	D0 },
 | 
						{ PCH_DEVFN_PCIE8,	ACPI_DEVICE_SLEEP_D0 },
 | 
				
			||||||
	{ PCH_DEVFN_PCIE6,	D0 },
 | 
						{ PCH_DEVFN_PCIE9,	ACPI_DEVICE_SLEEP_D0 },
 | 
				
			||||||
	{ PCH_DEVFN_PCIE7,	D0 },
 | 
						{ PCH_DEVFN_PCIE10,	ACPI_DEVICE_SLEEP_D0 },
 | 
				
			||||||
	{ PCH_DEVFN_PCIE8,	D0 },
 | 
						{ PCH_DEVFN_PCIE11,	ACPI_DEVICE_SLEEP_D0 },
 | 
				
			||||||
	{ PCH_DEVFN_PCIE9,	D0 },
 | 
						{ PCH_DEVFN_PCIE12,	ACPI_DEVICE_SLEEP_D0 },
 | 
				
			||||||
	{ PCH_DEVFN_PCIE10,	D0 },
 | 
						{ PCH_DEVFN_UART0,	ACPI_DEVICE_SLEEP_D3 },
 | 
				
			||||||
	{ PCH_DEVFN_PCIE11,	D0 },
 | 
						{ PCH_DEVFN_UART1,	ACPI_DEVICE_SLEEP_D3 },
 | 
				
			||||||
	{ PCH_DEVFN_PCIE12,	D0 },
 | 
						{ PCH_DEVFN_GSPI0,	ACPI_DEVICE_SLEEP_D3 },
 | 
				
			||||||
	{ PCH_DEVFN_UART0,	D3 },
 | 
						{ PCH_DEVFN_GSPI1,	ACPI_DEVICE_SLEEP_D3 },
 | 
				
			||||||
	{ PCH_DEVFN_UART1,	D3 },
 | 
						{ PCH_DEVFN_ESPI,	ACPI_DEVICE_SLEEP_D0 },
 | 
				
			||||||
	{ PCH_DEVFN_GSPI0,	D3 },
 | 
						{ PCH_DEVFN_PMC,	ACPI_DEVICE_SLEEP_D0 },
 | 
				
			||||||
	{ PCH_DEVFN_GSPI1,	D3 },
 | 
						{ PCH_DEVFN_HDA,	ACPI_DEVICE_SLEEP_D0 },
 | 
				
			||||||
	{ PCH_DEVFN_ESPI,	D0 },
 | 
						{ PCH_DEVFN_SPI,	ACPI_DEVICE_SLEEP_D3 },
 | 
				
			||||||
	{ PCH_DEVFN_PMC,	D0 },
 | 
						{ PCH_DEVFN_GBE,	ACPI_DEVICE_SLEEP_D3 },
 | 
				
			||||||
	{ PCH_DEVFN_HDA,	D0 },
 | 
					 | 
				
			||||||
	{ PCH_DEVFN_SPI,	D3 },
 | 
					 | 
				
			||||||
	{ PCH_DEVFN_GBE,	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))
 | 
						*size = ARRAY_SIZE(min_pci_sleep_states);
 | 
				
			||||||
		return NONE;
 | 
						return min_pci_sleep_states;
 | 
				
			||||||
 | 
					 | 
				
			||||||
	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);
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
uint32_t soc_read_sci_irq_select(void)
 | 
					uint32_t soc_read_sci_irq_select(void)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,5 +1,6 @@
 | 
				
			|||||||
/* SPDX-License-Identifier: GPL-2.0-or-later */
 | 
					/* SPDX-License-Identifier: GPL-2.0-or-later */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <acpi/acpi.h>
 | 
				
			||||||
#include <acpi/acpi_pm.h>
 | 
					#include <acpi/acpi_pm.h>
 | 
				
			||||||
#include <acpi/acpigen.h>
 | 
					#include <acpi/acpigen.h>
 | 
				
			||||||
#include <arch/ioapic.h>
 | 
					#include <arch/ioapic.h>
 | 
				
			||||||
@@ -69,7 +70,6 @@ static unsigned long acpi_madt_irq_overrides(unsigned long current)
 | 
				
			|||||||
	current +=
 | 
						current +=
 | 
				
			||||||
	    acpi_create_madt_irqoverride((void *)current, 0, sci, sci, flags);
 | 
						    acpi_create_madt_irqoverride((void *)current, 0, sci, sci, flags);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
	return current;
 | 
						return current;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -23,10 +23,20 @@
 | 
				
			|||||||
#define RESTORE_PM_BITS_HOOK		"\\_SB.PCI0.RGPM"
 | 
					#define RESTORE_PM_BITS_HOOK		"\\_SB.PCI0.RGPM"
 | 
				
			||||||
#define THUNDERBOLT_DEVICE		"\\_SB.PCI0.TXHC"
 | 
					#define THUNDERBOLT_DEVICE		"\\_SB.PCI0.TXHC"
 | 
				
			||||||
#define THUNDERBOLT_IOM_DPOF		"\\_SB.PCI0.DPOF"
 | 
					#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 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 {
 | 
					struct reg_info {
 | 
				
			||||||
	uint8_t *addr;
 | 
						uint8_t *addr;
 | 
				
			||||||
	size_t buffer_size;
 | 
						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
 | 
					 * device, one that is known to exist, i.e.  ACPI_CPU_STRING.  expects at least
 | 
				
			||||||
 * one device and crashes without it with a bluescreen.
 | 
					 * 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];
 | 
						char path[16];
 | 
				
			||||||
	printk(BIOS_INFO, "Returning default LPI constraint package\n");
 | 
						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();
 | 
						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)
 | 
					static void lpi_s0ix_entry(void *unused)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	/* Inform the EC */
 | 
						/* Inform the EC */
 | 
				
			||||||
@@ -200,7 +314,7 @@ static void lpi_display_off(void *unused)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
static void (*lpi_s0_helpers[])(void *) = {
 | 
					static void (*lpi_s0_helpers[])(void *) = {
 | 
				
			||||||
	NULL,			/* enumerate functions (autogenerated) */
 | 
						NULL,			/* enumerate functions (autogenerated) */
 | 
				
			||||||
	soc_lpi_get_constraints,/* get device constraints */
 | 
						acpi_lpi_get_constraints,/* get device constraints */
 | 
				
			||||||
	NULL,			/* get crash dump device */
 | 
						NULL,			/* get crash dump device */
 | 
				
			||||||
	lpi_display_off,	/* display off notify */
 | 
						lpi_display_off,	/* display off notify */
 | 
				
			||||||
	lpi_display_on,		/* display on notify */
 | 
						lpi_display_on,		/* display on notify */
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -127,4 +127,31 @@ enum core_type get_soc_cpu_type(void);
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
/* Check if CPU supports Nominal frequency or not */
 | 
					/* Check if CPU supports Nominal frequency or not */
 | 
				
			||||||
bool soc_is_nominal_freq_supported(void);
 | 
					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_ */
 | 
					#endif				/* _SOC_INTEL_COMMON_BLOCK_ACPI_H_ */
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user