diff options
-rw-r--r-- | src/soc/intel/xeon_sp/Makefile.inc | 1 | ||||
-rw-r--r-- | src/soc/intel/xeon_sp/include/soc/gpe.h | 11 | ||||
-rw-r--r-- | src/soc/intel/xeon_sp/include/soc/iomap.h | 5 | ||||
-rw-r--r-- | src/soc/intel/xeon_sp/include/soc/pm.h | 100 | ||||
-rw-r--r-- | src/soc/intel/xeon_sp/include/soc/pmc.h | 12 | ||||
-rw-r--r-- | src/soc/intel/xeon_sp/pmc.c | 195 | ||||
-rw-r--r-- | src/soc/intel/xeon_sp/skx/chip.h | 1 |
7 files changed, 319 insertions, 6 deletions
diff --git a/src/soc/intel/xeon_sp/Makefile.inc b/src/soc/intel/xeon_sp/Makefile.inc index 94c1764659..3bbf6b725e 100644 --- a/src/soc/intel/xeon_sp/Makefile.inc +++ b/src/soc/intel/xeon_sp/Makefile.inc @@ -8,6 +8,7 @@ subdirs-$(CONFIG_SOC_INTEL_COOPERLAKE_SP) += cpx bootblock-y += bootblock.c spi.c lpc.c gpio.c pch.c romstage-y += romstage.c reset.c util.c spi.c gpio.c pmutil.c ramstage-y += uncore.c reset.c util.c lpc.c spi.c gpio.c +ramstage-$(CONFIG_SOC_INTEL_COMMON_BLOCK_PMC) += pmc.c postcar-y += spi.c CPPFLAGS_common += -I$(src)/soc/intel/xeon_sp/include diff --git a/src/soc/intel/xeon_sp/include/soc/gpe.h b/src/soc/intel/xeon_sp/include/soc/gpe.h new file mode 100644 index 0000000000..c4acf1c1f3 --- /dev/null +++ b/src/soc/intel/xeon_sp/include/soc/gpe.h @@ -0,0 +1,11 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#ifndef _SOC_GPE_H_ +#define _SOC_GPE_H_ + +/* GPE_31_0 */ +#define GPE0_DW0_00 0 +#define GPE0_DW0_01 1 +#define GPE0_DW0_02 2 +#define GPE_MAX GPE0_DW0_02 +#endif /* _SOC_GPE_H_ */ diff --git a/src/soc/intel/xeon_sp/include/soc/iomap.h b/src/soc/intel/xeon_sp/include/soc/iomap.h index 68f6f558ae..f23f0ec9ae 100644 --- a/src/soc/intel/xeon_sp/include/soc/iomap.h +++ b/src/soc/intel/xeon_sp/include/soc/iomap.h @@ -19,7 +19,9 @@ #define SPI_BASE_ADDRESS 0xfe010000 #define SPI_BASE_SIZE 0x1000 +#define TCO_BASE_ADDRESS 0x400 #define ACPI_BASE_ADDRESS 0x500 +#define ACPI_BASE_SIZE 0x100 /* Video RAM */ #define VGA_BASE_ADDRESS 0xa0000 @@ -28,6 +30,9 @@ /* High Performance Event Timer */ #define HPET_BASE_ADDRESS 0xfed00000 +#define PCH_PWRM_BASE_ADDRESS 0xfe000000 +#define PCH_PWRM_BASE_SIZE 0x10000 + #define P2SB_BAR CONFIG_PCR_BASE_ADDRESS #endif /* _SOC_IOMAP_H_ */ diff --git a/src/soc/intel/xeon_sp/include/soc/pm.h b/src/soc/intel/xeon_sp/include/soc/pm.h index c4c1a885bc..f5a45c6106 100644 --- a/src/soc/intel/xeon_sp/include/soc/pm.h +++ b/src/soc/intel/xeon_sp/include/soc/pm.h @@ -3,15 +3,103 @@ #ifndef _SOC_PM_H_ #define _SOC_PM_H_ +#include <acpi/acpi.h> +#include <soc/gpe.h> #include <soc/iomap.h> #include <soc/pmc.h> -#define PM1_CNT 0x04 -#define PM1_STS 0x00 -#define PM1_TMR 0x08 -#define PM2_CNT 0x50 +/* ACPI_BASE_ADDRESS / PMBASE */ +#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 PM1_EN 0x02 +#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 GBL_RLS (1 << 2) +#define SCI_EN (1 << 0) +#define PM1_TMR 0x08 +#define SMI_EN 0x30 +#define ESPI_SMI_EN (1 << 28) +#define PERIODIC_EN (1 << 14) +#define TCO_SMI_EN (1 << 13) +#define APMC_EN (1 << 5) +#define SLP_SMI_EN (1 << 4) +#define BIOS_EN (1 << 2) +#define EOS (1 << 1) +#define GBL_SMI_EN (1 << 0) +#define SMI_STS 0x34 +#define SMI_STS_BITS 32 +#define GPIO_UNLOCK_SMI_STS_BIT 27 +#define PERIODIC_STS_BIT 14 +#define TCO_STS_BIT 13 +#define PM1_STS_BIT 8 +#define APM_STS_BIT 5 +#define SMI_ON_SLP_EN_STS_BIT 4 +#define BIOS_STS_BIT 2 +#define GPE_CNTL 0x42 +#define SWGPE_CTRL (1 << 1) +#define DEVACT_STS 0x44 +#define PM2_CNT 0x50 +#define GPE0_REG_MAX 4 +#define GPE0_REG_SIZE 32 +#define GPE0_STS(x) (0x80 + (x * 4)) +#define GPE0_EN(x) (0x90 + (x * 4)) +#define GPE_STD 3 /* 0x8c/0x9c = Standard GPE */ +#define GPE_STS_RSVD GPE_STD +#define GPIO_T2_STS (1 << 15) +#define PME_B0_STS (1 << 13) +#define PME_STS (1 << 11) +#define PCI_EXP_STS (1 << 9) +#define SMB_WAK_STS (1 << 7) +#define TCOSCI_STS (1 << 6) +#define GPE0_EN(x) (0x90 + (x * 4)) +#define GPIO_T2_EN (1 << 15) +#define ESPI_EN (1 << 14) +#define PME_B0_EN (1 << 13) +#define PME_EN (1 << 11) +#define PCI_EXP_EN (1 << 9) +#define TCOSCI_EN (1 << 6) -#define GPE0_REG_MAX 4 -#define GPE0_STS(x) (0x80 + (x * 4)) +#define ENABLE_SMI_PARAMS \ + (APMC_EN | GBL_SMI_EN | EOS) + +/* This is defined as ETR3 in EDS. We named it as ETR here for consistency */ +#define ETR 0xac +#define CF9_LOCK (1 << 31) +#define CF9_GLB_RST (1 << 20) + +#define PRSTS 0x10 + +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]; + uint32_t gen_pmcon_a; + uint32_t gen_pmcon_b; + uint32_t gblrst_cause[2]; + uint32_t prev_sleep_state; +} __packed; + +/* Get base address PMC memory mapped registers. */ +uint8_t *pmc_mmio_regs(void); + +/* Set the DISB after DRAM init */ +void pmc_set_disb(void); + +/* Return non-zero when RTC failure happened. */ +int rtc_failure(void); + +uint16_t get_pmbase(void); #endif diff --git a/src/soc/intel/xeon_sp/include/soc/pmc.h b/src/soc/intel/xeon_sp/include/soc/pmc.h index 49e58d366a..40b41c7d59 100644 --- a/src/soc/intel/xeon_sp/include/soc/pmc.h +++ b/src/soc/intel/xeon_sp/include/soc/pmc.h @@ -21,10 +21,22 @@ #define SCIS_IRQ23 7 #define PWRMBASE 0x48 #define GEN_PMCON_A 0xa0 +#define DISB (1 << 23) +#define GBL_RST_STS (1 << 16) #define SMI_LOCK (1 << 4) #define GEN_PMCON_B 0xa4 #define SLP_STR_POL_LOCK (1 << 18) #define ACPI_BASE_LOCK (1 << 17) #define RTC_BATTERY_DEAD (1 << 2) +#define SUS_PWR_FLR (1 << 14) +#define HOST_RST_STS (1 << 9) +#define PWR_FLR (1 << 1) +#define SLEEP_AFTER_POWER_FAIL (1 << 0) +/* Memory mapped IO registers in PMC */ +#define GPIO_GPE_CFG 0x120 +#define GPE0_DWX_MASK 0xf +#define GPE0_DW_SHIFT(x) (4 * (x)) +#define GBLRST_CAUSE0 0x124 +#define GBLRST_CAUSE1 0x128 #endif diff --git a/src/soc/intel/xeon_sp/pmc.c b/src/soc/intel/xeon_sp/pmc.c new file mode 100644 index 0000000000..a418ae5bab --- /dev/null +++ b/src/soc/intel/xeon_sp/pmc.c @@ -0,0 +1,195 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include "chip.h" +#include <console/console.h> +#include <device/device.h> +#include <device/pci_ops.h> +#include <intelblocks/pmc.h> +#include <intelblocks/pmclib.h> +#include <intelblocks/rtc.h> +#include <reg_script.h> +#include <soc/pci_devs.h> +#include <soc/pm.h> + +/* + * Set which power state system will be after reapplying + * the power (from G3 State) + */ +void pmc_soc_set_afterg3_en(const bool on) +{ + uint8_t reg8; + reg8 = pci_read_config8(PCH_DEV_PMC, GEN_PMCON_B); + if (on) + reg8 &= ~SLEEP_AFTER_POWER_FAIL; + else + reg8 |= SLEEP_AFTER_POWER_FAIL; + pci_write_config8(PCH_DEV_PMC, GEN_PMCON_B, reg8); +} + +#if ENV_RAMSTAGE +/* Fill up PMC resource structure */ +int pmc_soc_get_resources(struct pmc_resource_config *cfg) +{ + cfg->pwrmbase_offset = PWRMBASE; + cfg->pwrmbase_addr = PCH_PWRM_BASE_ADDRESS; + cfg->pwrmbase_size = PCH_PWRM_BASE_SIZE; + cfg->abase_offset = ABASE; + cfg->abase_addr = ACPI_BASE_ADDRESS; + cfg->abase_size = ACPI_BASE_SIZE; + + return 0; +} + +static const struct reg_script pch_pmc_misc_init_script[] = { + /* Enable SCI and clear SLP requests. */ + REG_IO_RMW32(ACPI_BASE_ADDRESS + PM1_CNT, ~SLP_TYP, SCI_EN), + REG_SCRIPT_END +}; + +static const struct reg_script pmc_write1_to_clear_script[] = { + REG_PCI_OR32(GEN_PMCON_A, 0), + REG_PCI_OR32(GEN_PMCON_B, 0), + REG_PCI_OR32(GEN_PMCON_B, 0), + REG_RES_OR32(PWRMBASE, GBLRST_CAUSE0, 0), + REG_RES_OR32(PWRMBASE, GBLRST_CAUSE1, 0), + REG_SCRIPT_END +}; + +void pmc_soc_init(struct device *dev) +{ + pmc_set_power_failure_state(true); + pmc_gpe_init(); + + /* Note that certain bits may be cleared from running script as + * certain bit fields are write 1 to clear. */ + reg_script_run_on_dev(dev, pch_pmc_misc_init_script); + pmc_set_acpi_mode(); + + /* Clear registers that contain write-1-to-clear bits. */ + reg_script_run_on_dev(dev, pmc_write1_to_clear_script); +} +#endif + +/* + * GPE0 + */ + +const char *const *soc_std_gpe_sts_array(size_t *gpe_arr) +{ + static const char *const gpe_sts_bits[] = { + }; + + *gpe_arr = ARRAY_SIZE(gpe_sts_bits); + return gpe_sts_bits; +} + +uint8_t *pmc_mmio_regs(void) +{ + return (void *)(uintptr_t) pci_read_config32(PCH_DEV_PMC, PWRMBASE); +} + +uintptr_t soc_read_pmc_base(void) +{ + return (uintptr_t) (pmc_mmio_regs()); +} + +uint32_t *soc_pmc_etr_addr(void) +{ + /* + * The pointer returned must not be cached, because the address depends on the + * MMCONF base address and the assigned PCI bus number, which both may change + * during the boot process! + */ + return pci_mmio_config32_addr(PCH_DEVFN_PMC << 12, ETR); +} + +void soc_get_gpi_gpe_configs(uint8_t *dw0, uint8_t *dw1, uint8_t *dw2) +{ + /* No functionality for this yet */ +} + +int rtc_failure(void) +{ + u8 reg8; + int rtc_failed; + /* PMC Controller Device 0x1F, Func 02 */ + reg8 = pci_read_config8(PCH_DEV_PMC, GEN_PMCON_B); + rtc_failed = reg8 & RTC_BATTERY_DEAD; + if (rtc_failed) { + reg8 &= ~RTC_BATTERY_DEAD; + pci_write_config8(PCH_DEV_PMC, GEN_PMCON_B, reg8); + printk(BIOS_DEBUG, "rtc_failed = 0x%x\n", rtc_failed); + } + + return !!rtc_failed; +} + +/* Return 0, 3, or 5 to indicate the previous sleep state. */ +int soc_prev_sleep_state(const struct chipset_power_state *ps, int prev_sleep_state) +{ + /* + * Check for any power failure to determine if this a wake from + * S5 because the PCH does not set the WAK_STS bit when waking + * from a true G3 state. + */ + if (!(ps->pm1_sts & WAK_STS) && + (ps->gen_pmcon_b & (PWR_FLR | SUS_PWR_FLR))) + prev_sleep_state = ACPI_S5; + + return prev_sleep_state; +} + +void soc_fill_power_state(struct chipset_power_state *ps) +{ + uint8_t *pmc; + + ps->gen_pmcon_a = pci_read_config32(PCH_DEV_PMC, GEN_PMCON_A); + ps->gen_pmcon_b = pci_read_config32(PCH_DEV_PMC, GEN_PMCON_B); + + pmc = pmc_mmio_regs(); + ps->gblrst_cause[0] = read32(pmc + GBLRST_CAUSE0); + ps->gblrst_cause[1] = read32(pmc + GBLRST_CAUSE1); + + printk(BIOS_DEBUG, "GEN_PMCON: %08x %08x\n", + ps->gen_pmcon_a, ps->gen_pmcon_b); + + printk(BIOS_DEBUG, "GBLRST_CAUSE: %08x %08x\n", + ps->gblrst_cause[0], ps->gblrst_cause[1]); +} + +/* STM Support */ +uint16_t get_pmbase(void) +{ + return ACPI_BASE_ADDRESS; +} + +const char *const *soc_smi_sts_array(size_t *smi_arr) +{ + static const char *const smi_sts_bits[] = { + [2] = "BIOS", + [3] = "LEGACY_USB", + [4] = "SLP_SMI", + [5] = "APM", + [6] = "SWSMI_TMR", + [7] = "BIOS_RLS", + [8] = "PM1", + [9] = "GPE0", + [10] = "GPI", + [11] = "MCSMI", + [12] = "DEVMON", + [13] = "TCO", + [14] = "PERIODIC", + [20] = "PCI_EXP_SMI", + [23] = "IE_SMI", + [25] = "SCC_SMI", + [26] = "SPI", + [27] = "GPIO_UNLOCK", + [28] = "ESPI_SMI", + [29] = "SERIAL_I/O", + [30] = "ME_SMI", + [31] = "XHCI", + }; + + *smi_arr = ARRAY_SIZE(smi_sts_bits); + return smi_sts_bits; +} diff --git a/src/soc/intel/xeon_sp/skx/chip.h b/src/soc/intel/xeon_sp/skx/chip.h index 440fb40f3d..bb084f3d74 100644 --- a/src/soc/intel/xeon_sp/skx/chip.h +++ b/src/soc/intel/xeon_sp/skx/chip.h @@ -37,6 +37,7 @@ struct soc_intel_xeon_sp_skx_config { * 6h = PIRQG# * 7h = PIRQH# */ + uint16_t ir00_routing; uint16_t ir01_routing; uint16_t ir02_routing; |