diff options
Diffstat (limited to 'arch')
| -rw-r--r-- | arch/x86/cpu/broadwell/Makefile | 1 | ||||
| -rw-r--r-- | arch/x86/cpu/broadwell/power_state.c | 90 | ||||
| -rw-r--r-- | arch/x86/include/asm/arch-broadwell/pm.h | 129 | 
3 files changed, 220 insertions, 0 deletions
| diff --git a/arch/x86/cpu/broadwell/Makefile b/arch/x86/cpu/broadwell/Makefile index a542feffc71..5a62afae59b 100644 --- a/arch/x86/cpu/broadwell/Makefile +++ b/arch/x86/cpu/broadwell/Makefile @@ -10,5 +10,6 @@ obj-y += lpc.o  obj-y += northbridge.o  obj-y += pch.o  obj-y += pinctrl_broadwell.o +obj-y += power_state.o  obj-y += refcode.o  obj-y += sata.o diff --git a/arch/x86/cpu/broadwell/power_state.c b/arch/x86/cpu/broadwell/power_state.c new file mode 100644 index 00000000000..2b9a6bf3a19 --- /dev/null +++ b/arch/x86/cpu/broadwell/power_state.c @@ -0,0 +1,90 @@ +/* + * From coreboot src/soc/intel/broadwell/romstage/power_state.c + * + * Copyright (C) 2016 Google, Inc. + * + * SPDX-License-Identifier:	GPL-2.0 + */ + +#include <common.h> +#include <pci.h> +#include <asm/io.h> +#include <asm/intel_regs.h> +#include <asm/arch/iomap.h> +#include <asm/arch/lpc.h> +#include <asm/arch/pch.h> +#include <asm/arch/pm.h> + +/* Return 0, 3, or 5 to indicate the previous sleep state. */ +static int prev_sleep_state(struct chipset_power_state *ps) +{ +	/* Default to S0. */ +	int prev_sleep_state = SLEEP_STATE_S0; + +	if (ps->pm1_sts & WAK_STS) { +		switch ((ps->pm1_cnt & SLP_TYP) >> SLP_TYP_SHIFT) { +#if CONFIG_HAVE_ACPI_RESUME +		case SLP_TYP_S3: +			prev_sleep_state = SLEEP_STATE_S3; +			break; +#endif +		case SLP_TYP_S5: +			prev_sleep_state = SLEEP_STATE_S5; +			break; +		} +		/* Clear SLP_TYP. */ +		outl(ps->pm1_cnt & ~(SLP_TYP), ACPI_BASE_ADDRESS + PM1_CNT); +	} + +	if (ps->gen_pmcon3 & (PWR_FLR | SUS_PWR_FLR)) +		prev_sleep_state = SLEEP_STATE_S5; + +	return prev_sleep_state; +} + +static void dump_power_state(struct chipset_power_state *ps) +{ +	debug("PM1_STS:   %04x\n", ps->pm1_sts); +	debug("PM1_EN:    %04x\n", ps->pm1_en); +	debug("PM1_CNT:   %08x\n", ps->pm1_cnt); +	debug("TCO_STS:   %04x %04x\n", ps->tco1_sts, ps->tco2_sts); + +	debug("GPE0_STS:  %08x %08x %08x %08x\n", +	      ps->gpe0_sts[0], ps->gpe0_sts[1], +	      ps->gpe0_sts[2], ps->gpe0_sts[3]); +	debug("GPE0_EN:   %08x %08x %08x %08x\n", +	      ps->gpe0_en[0], ps->gpe0_en[1], +	      ps->gpe0_en[2], ps->gpe0_en[3]); + +	debug("GEN_PMCON: %04x %04x %04x\n", +	      ps->gen_pmcon1, ps->gen_pmcon2, ps->gen_pmcon3); + +	debug("Previous Sleep State: S%d\n", +	      ps->prev_sleep_state); +} + +/* Fill power state structure from ACPI PM registers */ +void power_state_get(struct udevice *pch_dev, struct chipset_power_state *ps) +{ +	ps->pm1_sts = inw(ACPI_BASE_ADDRESS + PM1_STS); +	ps->pm1_en = inw(ACPI_BASE_ADDRESS + PM1_EN); +	ps->pm1_cnt = inl(ACPI_BASE_ADDRESS + PM1_CNT); +	ps->tco1_sts = inw(ACPI_BASE_ADDRESS + TCO1_STS); +	ps->tco2_sts = inw(ACPI_BASE_ADDRESS + TCO2_STS); +	ps->gpe0_sts[0] = inl(ACPI_BASE_ADDRESS + GPE0_STS(0)); +	ps->gpe0_sts[1] = inl(ACPI_BASE_ADDRESS + GPE0_STS(1)); +	ps->gpe0_sts[2] = inl(ACPI_BASE_ADDRESS + GPE0_STS(2)); +	ps->gpe0_sts[3] = inl(ACPI_BASE_ADDRESS + GPE0_STS(3)); +	ps->gpe0_en[0] = inl(ACPI_BASE_ADDRESS + GPE0_EN(0)); +	ps->gpe0_en[1] = inl(ACPI_BASE_ADDRESS + GPE0_EN(1)); +	ps->gpe0_en[2] = inl(ACPI_BASE_ADDRESS + GPE0_EN(2)); +	ps->gpe0_en[3] = inl(ACPI_BASE_ADDRESS + GPE0_EN(3)); + +	dm_pci_read_config16(pch_dev, GEN_PMCON_1, &ps->gen_pmcon1); +	dm_pci_read_config16(pch_dev, GEN_PMCON_2, &ps->gen_pmcon2); +	dm_pci_read_config16(pch_dev, GEN_PMCON_3, &ps->gen_pmcon3); + +	ps->prev_sleep_state = prev_sleep_state(ps); + +	dump_power_state(ps); +} diff --git a/arch/x86/include/asm/arch-broadwell/pm.h b/arch/x86/include/asm/arch-broadwell/pm.h new file mode 100644 index 00000000000..36ad842368e --- /dev/null +++ b/arch/x86/include/asm/arch-broadwell/pm.h @@ -0,0 +1,129 @@ +/* + * From coreboot src/soc/intel/broadwell/include/soc/pm.h + * + * Copyright (C) 2016 Google, Inc. + * + * SPDX-License-Identifier:	GPL-2.0 + */ + +#ifndef __ASM_ARCH_PM_H +#define __ASM_ARCH_PM_H + +#define PM1_STS			0x00 +#define  WAK_STS		(1 << 15) +#define  PCIEXPWAK_STS		(1 << 14) +#define  PRBTNOR_STS		(1 << 11) +#define  RTC_STS		(1 << 10) +#define  PWRBTN_STS		(1 << 8) +#define  GBL_STS		(1 << 5) +#define  BM_STS			(1 << 4) +#define  TMROF_STS		(1 << 0) +#define PM1_EN			0x02 +#define  PCIEXPWAK_DIS		(1 << 14) +#define  RTC_EN			(1 << 10) +#define  PWRBTN_EN		(1 << 8) +#define  GBL_EN			(1 << 5) +#define  TMROF_EN		(1 << 0) +#define PM1_CNT			0x04 +#define  SLP_EN			(1 << 13) +#define  SLP_TYP		(7 << 10) +#define   SLP_TYP_SHIFT         10 +#define   SLP_TYP_S0		0 +#define   SLP_TYP_S1		1 +#define   SLP_TYP_S3		5 +#define   SLP_TYP_S4		6 +#define   SLP_TYP_S5		7 +#define  GBL_RLS		(1 << 2) +#define  BM_RLD			(1 << 1) +#define  SCI_EN			(1 << 0) +#define PM1_TMR			0x08 +#define SMI_EN			0x30 +#define  XHCI_SMI_EN		(1 << 31) +#define  ME_SMI_EN		(1 << 30) +#define  GPIO_UNLOCK_SMI_EN	(1 << 27) +#define  INTEL_USB2_EN		(1 << 18) +#define  LEGACY_USB2_EN		(1 << 17) +#define  PERIODIC_EN		(1 << 14) +#define  TCO_EN			(1 << 13) +#define  MCSMI_EN		(1 << 11) +#define  BIOS_RLS		(1 <<  7) +#define  SWSMI_TMR_EN		(1 <<  6) +#define  APMC_EN		(1 <<  5) +#define  SLP_SMI_EN		(1 <<  4) +#define  LEGACY_USB_EN		(1 <<  3) +#define  BIOS_EN		(1 <<  2) +#define  EOS			(1 <<  1) +#define  GBL_SMI_EN		(1 <<  0) +#define SMI_STS			0x34 +#define UPWRC			0x3c +#define  UPWRC_WS		(1 << 8) +#define  UPWRC_WE		(1 << 1) +#define  UPWRC_SMI		(1 << 0) +#define GPE_CNTL		0x42 +#define  SWGPE_CTRL		(1 << 1) +#define DEVACT_STS		0x44 +#define PM2_CNT			0x50 +#define TCO1_CNT		0x60 +#define  TCO_TMR_HLT		(1 << 11) +#define TCO1_STS		0x64 +#define  DMISCI_STS		(1 << 9) +#define TCO2_STS		0x66 +#define  TCO2_STS_SECOND_TO	(1 << 1) + +#define GPE0_REG_MAX		4 +#define GPE0_REG_SIZE		32 +#define GPE0_STS(x)		(0x80 + (x * 4)) +#define  GPE_31_0		0	/* 0x80/0x90 = GPE[31:0] */ +#define  GPE_63_32		1	/* 0x84/0x94 = GPE[63:32] */ +#define  GPE_94_64		2	/* 0x88/0x98 = GPE[94:64] */ +#define  GPE_STD		3	/* 0x8c/0x9c = Standard GPE */ +#define   WADT_STS		(1 << 18) +#define   GP27_STS		(1 << 16) +#define   PME_B0_STS		(1 << 13) +#define   ME_SCI_STS		(1 << 12) +#define   PME_STS		(1 << 11) +#define   BATLOW_STS		(1 << 10) +#define   PCI_EXP_STS		(1 << 9) +#define   SMB_WAK_STS		(1 << 7) +#define   TCOSCI_STS		(1 << 6) +#define   SWGPE_STS		(1 << 2) +#define   HOT_PLUG_STS		(1 << 1) +#define GPE0_EN(x)		(0x90 + (x * 4)) +#define   WADT_en		(1 << 18) +#define   GP27_EN		(1 << 16) +#define   PME_B0_EN		(1 << 13) +#define   ME_SCI_EN		(1 << 12) +#define   PME_EN		(1 << 11) +#define   BATLOW_EN		(1 << 10) +#define   PCI_EXP_EN		(1 << 9) +#define   TCOSCI_EN		(1 << 6) +#define   SWGPE_EN		(1 << 2) +#define   HOT_PLUG_EN		(1 << 1) + +#define MAINBOARD_POWER_OFF	0 +#define MAINBOARD_POWER_ON	1 +#define MAINBOARD_POWER_KEEP	2 + +#define SLEEP_STATE_S0		0 +#define SLEEP_STATE_S3		3 +#define SLEEP_STATE_S5		5 + +struct chipset_power_state { +	uint16_t pm1_sts; +	uint16_t pm1_en; +	uint32_t pm1_cnt; +	uint16_t tco1_sts; +	uint16_t tco2_sts; +	uint32_t gpe0_sts[4]; +	uint32_t gpe0_en[4]; +	uint16_t gen_pmcon1; +	uint16_t gen_pmcon2; +	uint16_t gen_pmcon3; +	int prev_sleep_state; +	uint16_t hsio_version; +	uint16_t hsio_checksum; +}; + +void power_state_get(struct udevice *pch_dev, struct chipset_power_state *ps); + +#endif | 
