blob: ed6a31dc58c77314a4423644720af67ad1f57272 [file] [log] [blame]
Angel Ponsfabfe9d2020-04-05 15:47:07 +02001/* SPDX-License-Identifier: GPL-2.0-only */
Aamir Bohradd7acaa2020-03-25 11:36:22 +05302
Aamir Bohradd7acaa2020-03-25 11:36:22 +05303#include <bootstate.h>
4#include <console/console.h>
5#include <device/mmio.h>
6#include <device/device.h>
7#include <intelblocks/pmc.h>
8#include <intelblocks/pmclib.h>
9#include <intelblocks/rtc.h>
10#include <soc/pci_devs.h>
11#include <soc/pm.h>
12#include <soc/soc_chip.h>
13
14/*
15 * Set which power state system will be after reapplying
16 * the power (from G3 State)
17 */
18void pmc_soc_set_afterg3_en(const bool on)
19{
20 uint8_t reg8;
21 uint8_t *const pmcbase = pmc_mmio_regs();
22
23 reg8 = read8(pmcbase + GEN_PMCON_A);
24 if (on)
25 reg8 &= ~SLEEP_AFTER_POWER_FAIL;
26 else
27 reg8 |= SLEEP_AFTER_POWER_FAIL;
28 write8(pmcbase + GEN_PMCON_A, reg8);
29}
30
31static void config_deep_sX(uint32_t offset, uint32_t mask, int sx, int enable)
32{
33 uint32_t reg;
34 uint8_t *pmcbase = pmc_mmio_regs();
35
36 printk(BIOS_DEBUG, "%sabling Deep S%c\n",
37 enable ? "En" : "Dis", sx + '0');
38 reg = read32(pmcbase + offset);
39 if (enable)
40 reg |= mask;
41 else
42 reg &= ~mask;
43 write32(pmcbase + offset, reg);
44}
45
46static void config_deep_s5(int on_ac, int on_dc)
47{
48 /* Treat S4 the same as S5. */
49 config_deep_sX(S4_PWRGATE_POL, S4AC_GATE_SUS, 4, on_ac);
50 config_deep_sX(S4_PWRGATE_POL, S4DC_GATE_SUS, 4, on_dc);
51 config_deep_sX(S5_PWRGATE_POL, S5AC_GATE_SUS, 5, on_ac);
52 config_deep_sX(S5_PWRGATE_POL, S5DC_GATE_SUS, 5, on_dc);
53}
54
55static void config_deep_s3(int on_ac, int on_dc)
56{
57 config_deep_sX(S3_PWRGATE_POL, S3AC_GATE_SUS, 3, on_ac);
58 config_deep_sX(S3_PWRGATE_POL, S3DC_GATE_SUS, 3, on_dc);
59}
60
61static void config_deep_sx(uint32_t deepsx_config)
62{
63 uint32_t reg;
64 uint8_t *pmcbase = pmc_mmio_regs();
65
66 reg = read32(pmcbase + DSX_CFG);
67 reg &= ~DSX_CFG_MASK;
68 reg |= deepsx_config;
69 write32(pmcbase + DSX_CFG, reg);
70}
71
Tim Wawrzynczakc47422d2020-06-01 17:03:41 -060072static void pmc_init(struct device *dev)
Aamir Bohradd7acaa2020-03-25 11:36:22 +053073{
74 const config_t *config = config_of_soc();
75
76 rtc_init();
77
78 pmc_set_power_failure_state(true);
79 pmc_gpe_init();
80
Aamir Bohradd7acaa2020-03-25 11:36:22 +053081 config_deep_s3(config->deep_s3_enable_ac, config->deep_s3_enable_dc);
82 config_deep_s5(config->deep_s5_enable_ac, config->deep_s5_enable_dc);
83 config_deep_sx(config->deep_sx_config);
84}
85
Tim Wawrzynczakc47422d2020-06-01 17:03:41 -060086static void soc_pmc_read_resources(struct device *dev)
87{
88 struct resource *res;
89
90 mmio_resource(dev, 0, PCH_PWRM_BASE_ADDRESS / KiB, PCH_PWRM_BASE_SIZE / KiB);
91
92 res = new_resource(dev, 1);
93 res->base = (resource_t)ACPI_BASE_ADDRESS;
94 res->size = (resource_t)ACPI_BASE_SIZE;
95 res->limit = res->base + res->size + 1;
96 res->flags = IORESOURCE_IO | IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
97}
98
Kane Chen00054922020-08-17 17:53:08 +080099static void soc_acpi_mode_init(struct device *dev)
100{
101 /*
102 * pmc_set_acpi_mode() should be delayed until BS_DEV_INIT in order
103 * to ensure the ordering does not break the assumptions that other
104 * drivers make about ACPI mode (e.g. Chrome EC). Since it disables
105 * ACPI mode, other drivers may take different actions based on this
106 * (e.g. Chrome EC will flush any pending hostevent bits). Because
107 * JSL has its PMC device available for device_operations, it can be
108 * done from the "ops->init" callback.
109 */
110 pmc_set_acpi_mode();
111}
112
Tim Wawrzynczakc47422d2020-06-01 17:03:41 -0600113struct device_operations pmc_ops = {
114 .read_resources = soc_pmc_read_resources,
115 .set_resources = noop_set_resources,
Kane Chen00054922020-08-17 17:53:08 +0800116 .init = soc_acpi_mode_init,
Tim Wawrzynczakc47422d2020-06-01 17:03:41 -0600117 .enable = pmc_init,
118};