blob: 9a082577d1c2e11e3aa41c362b06093cf60a03b4 [file] [log] [blame]
Angel Ponsf5627e82020-04-05 15:46:52 +02001/* SPDX-License-Identifier: GPL-2.0-only */
2/* This file is part of the coreboot project. */
Lijian Zhaoac87a982017-08-28 17:46:55 -07003
Subrata Banik0baad612017-11-23 13:58:34 +05304#include <bootstate.h>
Lijian Zhaoac87a982017-08-28 17:46:55 -07005#include <console/console.h>
Kyösti Mälkki13f66502019-03-03 08:01:05 +02006#include <device/mmio.h>
Lijian Zhaoac87a982017-08-28 17:46:55 -07007#include <device/device.h>
Subrata Banik0baad612017-11-23 13:58:34 +05308#include <intelblocks/pmc.h>
Lijian Zhaoac87a982017-08-28 17:46:55 -07009#include <intelblocks/pmclib.h>
10#include <intelblocks/rtc.h>
Lijian Zhaoac87a982017-08-28 17:46:55 -070011#include <soc/pci_devs.h>
12#include <soc/pm.h>
Lijian Zhaoac87a982017-08-28 17:46:55 -070013
Elyes HAOUASc3385072019-03-21 15:38:06 +010014#include "chip.h"
15
Subrata Banik33cd28e2017-12-19 12:33:59 +053016/*
17 * Set which power state system will be after reapplying
18 * the power (from G3 State)
19 */
Nico Huber733c28f2019-08-05 19:33:09 +020020void pmc_soc_set_afterg3_en(const bool on)
Subrata Banik33cd28e2017-12-19 12:33:59 +053021{
22 uint8_t reg8;
Nico Huber733c28f2019-08-05 19:33:09 +020023 uint8_t *const pmcbase = pmc_mmio_regs();
Subrata Banik33cd28e2017-12-19 12:33:59 +053024
Lijian Zhaoc3e75b42019-01-15 17:37:50 -080025 reg8 = read8(pmcbase + GEN_PMCON_A);
Nico Huber733c28f2019-08-05 19:33:09 +020026 if (on)
27 reg8 &= ~SLEEP_AFTER_POWER_FAIL;
28 else
29 reg8 |= SLEEP_AFTER_POWER_FAIL;
Lijian Zhaoc3e75b42019-01-15 17:37:50 -080030 write8(pmcbase + GEN_PMCON_A, reg8);
Subrata Banik33cd28e2017-12-19 12:33:59 +053031}
32
Krzysztof Sywula42a66fb2019-03-13 16:48:56 -070033static void pm1_enable_pwrbtn_smi(void *unused)
34{
35 /*
36 * Enable power button SMI only before jumping to payload. This ensures
37 * that:
38 * 1. Power button SMI is enabled only after coreboot is done.
39 * 2. On resume path, power button SMI is not enabled and thus avoids
40 * any shutdowns because of power button presses due to power button
41 * press in resume path.
42 */
43 pmc_update_pm1_enable(PWRBTN_EN);
44}
45
46BOOT_STATE_INIT_ENTRY(BS_PAYLOAD_LOAD, BS_ON_EXIT, pm1_enable_pwrbtn_smi, NULL);
47
Lijian Zhaoac87a982017-08-28 17:46:55 -070048static void config_deep_sX(uint32_t offset, uint32_t mask, int sx, int enable)
49{
50 uint32_t reg;
51 uint8_t *pmcbase = pmc_mmio_regs();
52
53 printk(BIOS_DEBUG, "%sabling Deep S%c\n",
54 enable ? "En" : "Dis", sx + '0');
55 reg = read32(pmcbase + offset);
56 if (enable)
57 reg |= mask;
58 else
59 reg &= ~mask;
60 write32(pmcbase + offset, reg);
61}
62
63static void config_deep_s5(int on_ac, int on_dc)
64{
65 /* Treat S4 the same as S5. */
66 config_deep_sX(S4_PWRGATE_POL, S4AC_GATE_SUS, 4, on_ac);
67 config_deep_sX(S4_PWRGATE_POL, S4DC_GATE_SUS, 4, on_dc);
68 config_deep_sX(S5_PWRGATE_POL, S5AC_GATE_SUS, 5, on_ac);
69 config_deep_sX(S5_PWRGATE_POL, S5DC_GATE_SUS, 5, on_dc);
70}
71
72static void config_deep_s3(int on_ac, int on_dc)
73{
74 config_deep_sX(S3_PWRGATE_POL, S3AC_GATE_SUS, 3, on_ac);
75 config_deep_sX(S3_PWRGATE_POL, S3DC_GATE_SUS, 3, on_dc);
76}
77
78static void config_deep_sx(uint32_t deepsx_config)
79{
80 uint32_t reg;
81 uint8_t *pmcbase = pmc_mmio_regs();
82
83 reg = read32(pmcbase + DSX_CFG);
84 reg &= ~DSX_CFG_MASK;
85 reg |= deepsx_config;
86 write32(pmcbase + DSX_CFG, reg);
87}
88
Subrata Banik0baad612017-11-23 13:58:34 +053089static void pmc_init(void *unused)
Lijian Zhaoac87a982017-08-28 17:46:55 -070090{
Kyösti Mälkkid5f645c2019-09-28 00:20:27 +030091 const config_t *config = config_of_soc();
Lijian Zhaoac87a982017-08-28 17:46:55 -070092
93 rtc_init();
94
Nico Huber733c28f2019-08-05 19:33:09 +020095 pmc_set_power_failure_state(true);
96 pmc_gpe_init();
Lijian Zhaoac87a982017-08-28 17:46:55 -070097
Lijian Zhaoac87a982017-08-28 17:46:55 -070098 config_deep_s3(config->deep_s3_enable_ac, config->deep_s3_enable_dc);
99 config_deep_s5(config->deep_s5_enable_ac, config->deep_s5_enable_dc);
100 config_deep_sx(config->deep_sx_config);
101}
102
Subrata Banik0baad612017-11-23 13:58:34 +0530103/*
104* Initialize PMC controller.
105*
106* PMC controller gets hidden from PCI bus during FSP-Silicon init call.
107* Hence PCI enumeration can't be used to initialize bus device and
108* allocate resources.
109*/
110BOOT_STATE_INIT_ENTRY(BS_DEV_INIT_CHIPS, BS_ON_EXIT, pmc_init, NULL);
Furquan Shaikhac8c60e2019-02-25 16:01:25 -0800111
Furquan Shaikh67a489f2019-02-27 00:59:06 -0800112static void soc_acpi_mode_init(void *unused)
Furquan Shaikhac8c60e2019-02-25 16:01:25 -0800113{
114 /*
115 * PMC initialization happens earlier for this SoC because FSP-Silicon
116 * init hides PMC from PCI bus. However, pmc_set_acpi_mode, which
117 * disables ACPI mode doesn't need to happen that early and can be
Furquan Shaikh67a489f2019-02-27 00:59:06 -0800118 * delayed till typical BS_DEV_INIT. This ensures that ACPI mode
119 * disabling happens the same way for all SoCs and hence the ordering of
120 * events is the same.
Furquan Shaikhac8c60e2019-02-25 16:01:25 -0800121 *
122 * This is important to ensure that the ordering does not break the
123 * assumptions of any other drivers (e.g. ChromeEC) which could be
124 * taking different actions based on disabling of ACPI (e.g. flushing of
125 * all EC hostevent bits).
Furquan Shaikh67a489f2019-02-27 00:59:06 -0800126 *
127 * P.S.: This cannot be done as part of pmc_soc_init as PMC device is
128 * hidden and hence the PMC driver never gets enumerated and so init is
129 * not called for it.
Furquan Shaikhac8c60e2019-02-25 16:01:25 -0800130 */
131 pmc_set_acpi_mode();
132}
Furquan Shaikh67a489f2019-02-27 00:59:06 -0800133
134BOOT_STATE_INIT_ENTRY(BS_DEV_INIT, BS_ON_EXIT, soc_acpi_mode_init, NULL);