summaryrefslogtreecommitdiff
path: root/src/soc/intel/tigerlake/pmc.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/soc/intel/tigerlake/pmc.c')
-rw-r--r--src/soc/intel/tigerlake/pmc.c114
1 files changed, 114 insertions, 0 deletions
diff --git a/src/soc/intel/tigerlake/pmc.c b/src/soc/intel/tigerlake/pmc.c
new file mode 100644
index 0000000000..65284ec57c
--- /dev/null
+++ b/src/soc/intel/tigerlake/pmc.c
@@ -0,0 +1,114 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2019 Intel Corp.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+/*
+ * This file is created based on Intel Tiger Lake Processor PCH Datasheet
+ * Document number: 575857
+ * Chapter number: 4
+ */
+
+#include <bootstate.h>
+#include <console/console.h>
+#include <device/mmio.h>
+#include <device/device.h>
+#include <intelblocks/pmc.h>
+#include <intelblocks/pmclib.h>
+#include <intelblocks/rtc.h>
+#include <soc/pci_devs.h>
+#include <soc/pm.h>
+#include <soc/soc_chip.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;
+ uint8_t *const pmcbase = pmc_mmio_regs();
+
+ reg8 = read8(pmcbase + GEN_PMCON_A);
+ if (on)
+ reg8 &= ~SLEEP_AFTER_POWER_FAIL;
+ else
+ reg8 |= SLEEP_AFTER_POWER_FAIL;
+ write8(pmcbase + GEN_PMCON_A, reg8);
+}
+
+static void config_deep_sX(uint32_t offset, uint32_t mask, int sx, int enable)
+{
+ uint32_t reg;
+ uint8_t *pmcbase = pmc_mmio_regs();
+
+ printk(BIOS_DEBUG, "%sabling Deep S%c\n",
+ enable ? "En" : "Dis", sx + '0');
+ reg = read32(pmcbase + offset);
+ if (enable)
+ reg |= mask;
+ else
+ reg &= ~mask;
+ write32(pmcbase + offset, reg);
+}
+
+static void config_deep_s5(int on_ac, int on_dc)
+{
+ /* Treat S4 the same as S5. */
+ config_deep_sX(S4_PWRGATE_POL, S4AC_GATE_SUS, 4, on_ac);
+ config_deep_sX(S4_PWRGATE_POL, S4DC_GATE_SUS, 4, on_dc);
+ config_deep_sX(S5_PWRGATE_POL, S5AC_GATE_SUS, 5, on_ac);
+ config_deep_sX(S5_PWRGATE_POL, S5DC_GATE_SUS, 5, on_dc);
+}
+
+static void config_deep_s3(int on_ac, int on_dc)
+{
+ config_deep_sX(S3_PWRGATE_POL, S3AC_GATE_SUS, 3, on_ac);
+ config_deep_sX(S3_PWRGATE_POL, S3DC_GATE_SUS, 3, on_dc);
+}
+
+static void config_deep_sx(uint32_t deepsx_config)
+{
+ uint32_t reg;
+ uint8_t *pmcbase = pmc_mmio_regs();
+
+ reg = read32(pmcbase + DSX_CFG);
+ reg &= ~DSX_CFG_MASK;
+ reg |= deepsx_config;
+ write32(pmcbase + DSX_CFG, reg);
+}
+
+static void pmc_init(void *unused)
+{
+ const config_t *config = config_of_soc();
+
+ rtc_init();
+
+ pmc_set_power_failure_state(true);
+ pmc_gpe_init();
+
+ pmc_set_acpi_mode();
+
+ config_deep_s3(config->deep_s3_enable_ac, config->deep_s3_enable_dc);
+ config_deep_s5(config->deep_s5_enable_ac, config->deep_s5_enable_dc);
+ config_deep_sx(config->deep_sx_config);
+}
+
+/*
+* Initialize PMC controller.
+*
+* PMC controller gets hidden from PCI bus during FSP-Silicon init call.
+* Hence PCI enumeration can't be used to initialize bus device and
+* allocate resources.
+*/
+BOOT_STATE_INIT_ENTRY(BS_DEV_INIT_CHIPS, BS_ON_EXIT, pmc_init, NULL);