summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/soc/intel/xeon_sp/Makefile.inc1
-rw-r--r--src/soc/intel/xeon_sp/include/soc/gpe.h11
-rw-r--r--src/soc/intel/xeon_sp/include/soc/iomap.h5
-rw-r--r--src/soc/intel/xeon_sp/include/soc/pm.h100
-rw-r--r--src/soc/intel/xeon_sp/include/soc/pmc.h12
-rw-r--r--src/soc/intel/xeon_sp/pmc.c195
-rw-r--r--src/soc/intel/xeon_sp/skx/chip.h1
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;