blob: 32fd0344861e9040dbbaa69d21b5178b50d5d4ec [file] [log] [blame]
Simon Glasse63ca972019-12-06 21:42:57 -07001// SPDX-License-Identifier: GPL-2.0
2/*
3 * Copyright (C) 2017 Intel Corporation.
4 * Copyright 2019 Google LLC
5 *
6 * Modified from coreboot pmclib.c, pmc.c and pmutil.c
7 */
8
9#define LOG_CATEGORY UCLASS_ACPI_PMC
10
Simon Glasse63ca972019-12-06 21:42:57 -070011#include <dm.h>
Simon Glasse952cf62021-03-15 17:25:45 +130012#include <dt-structs.h>
Simon Glass0f2af882020-05-10 11:40:05 -060013#include <log.h>
Simon Glasse63ca972019-12-06 21:42:57 -070014#include <spl.h>
Simon Glass50461092020-04-08 16:57:35 -060015#include <acpi/acpi_s3.h>
Simon Glasse63ca972019-12-06 21:42:57 -070016#include <asm/io.h>
17#include <asm/pci.h>
Simon Glass28c751f2020-12-19 10:39:57 -070018#include <asm/arch/pmc.h>
Simon Glass4dcacfc2020-05-10 11:40:13 -060019#include <linux/bitops.h>
Simon Glasse63ca972019-12-06 21:42:57 -070020#include <power/acpi_pmc.h>
21
22#define GPIO_GPE_CFG 0x1050
23
24/* Memory mapped IO registers behind PMC_BASE_ADDRESS */
25#define PRSTS 0x1000
26#define GEN_PMCON1 0x1020
27#define COLD_BOOT_STS BIT(27)
28#define COLD_RESET_STS BIT(26)
29#define WARM_RESET_STS BIT(25)
30#define GLOBAL_RESET_STS BIT(24)
31#define SRS BIT(20)
32#define MS4V BIT(18)
33#define RPS BIT(2)
34#define GEN_PMCON1_CLR1_BITS (COLD_BOOT_STS | COLD_RESET_STS | \
35 WARM_RESET_STS | GLOBAL_RESET_STS | \
36 SRS | MS4V)
37#define GEN_PMCON2 0x1024
38#define GEN_PMCON3 0x1028
39
40/* Offset of TCO registers from ACPI base I/O address */
41#define TCO_REG_OFFSET 0x60
42#define TCO1_STS 0x64
43#define DMISCI_STS BIT(9)
44#define BOOT_STS BIT(18)
45#define TCO2_STS 0x66
46#define TCO1_CNT 0x68
47#define TCO_LOCK BIT(12)
48#define TCO2_CNT 0x6a
49
50enum {
51 ETR = 0x1048,
52 CF9_LOCK = 1UL << 31,
53 CF9_GLB_RST = 1 << 20,
54};
55
Simon Glasse63ca972019-12-06 21:42:57 -070056static int apl_pmc_fill_power_state(struct udevice *dev)
57{
58 struct acpi_pmc_upriv *upriv = dev_get_uclass_priv(dev);
59
60 upriv->tco1_sts = inw(upriv->acpi_base + TCO1_STS);
61 upriv->tco2_sts = inw(upriv->acpi_base + TCO2_STS);
62
63 upriv->prsts = readl(upriv->pmc_bar0 + PRSTS);
64 upriv->gen_pmcon1 = readl(upriv->pmc_bar0 + GEN_PMCON1);
65 upriv->gen_pmcon2 = readl(upriv->pmc_bar0 + GEN_PMCON2);
66 upriv->gen_pmcon3 = readl(upriv->pmc_bar0 + GEN_PMCON3);
67
68 return 0;
69}
70
71static int apl_prev_sleep_state(struct udevice *dev, int prev_sleep_state)
72{
73 struct acpi_pmc_upriv *upriv = dev_get_uclass_priv(dev);
74
75 /* WAK_STS bit will not be set when waking from G3 state */
76 if (!(upriv->pm1_sts & WAK_STS) &&
77 (upriv->gen_pmcon1 & COLD_BOOT_STS))
78 prev_sleep_state = ACPI_S5;
79
80 return prev_sleep_state;
81}
82
83static int apl_disable_tco(struct udevice *dev)
84{
85 struct acpi_pmc_upriv *upriv = dev_get_uclass_priv(dev);
86
87 pmc_disable_tco_base(upriv->acpi_base + TCO_REG_OFFSET);
88
89 return 0;
90}
91
92static int apl_global_reset_set_enable(struct udevice *dev, bool enable)
93{
94 struct acpi_pmc_upriv *upriv = dev_get_uclass_priv(dev);
95
96 if (enable)
97 setbits_le32(upriv->pmc_bar0 + ETR, CF9_GLB_RST);
98 else
99 clrbits_le32(upriv->pmc_bar0 + ETR, CF9_GLB_RST);
100
101 return 0;
102}
103
Simon Glassb75b15b2020-12-03 16:55:23 -0700104int apl_pmc_ofdata_to_uc_plat(struct udevice *dev)
Simon Glasse63ca972019-12-06 21:42:57 -0700105{
106 struct acpi_pmc_upriv *upriv = dev_get_uclass_priv(dev);
Simon Glassb75b15b2020-12-03 16:55:23 -0700107 struct apl_pmc_plat *plat = dev_get_plat(dev);
Simon Glasse63ca972019-12-06 21:42:57 -0700108
Simon Glass92882652021-08-07 07:24:04 -0600109#if CONFIG_IS_ENABLED(OF_REAL)
Simon Glasse63ca972019-12-06 21:42:57 -0700110 u32 base[6];
111 int size;
112 int ret;
113
Simon Glassf77b9e22020-09-22 12:45:23 -0600114 ret = dev_read_u32_array(dev, "early-regs", base,
115 ARRAY_SIZE(base));
Simon Glasse63ca972019-12-06 21:42:57 -0700116 if (ret)
117 return log_msg_ret("Missing/short early-regs", ret);
Simon Glassbaf7bd42019-12-29 21:19:13 -0700118 if (spl_phase() == PHASE_TPL) {
119 upriv->pmc_bar0 = (void *)base[0];
120 upriv->pmc_bar2 = (void *)base[2];
121
122 /* Since PCI is not enabled, we must get the BDF manually */
123 plat->bdf = pci_get_devfn(dev);
124 if (plat->bdf < 0)
125 return log_msg_ret("Cannot get PMC PCI address",
126 plat->bdf);
127 }
Simon Glasse63ca972019-12-06 21:42:57 -0700128 upriv->acpi_base = base[4];
129
Simon Glasse63ca972019-12-06 21:42:57 -0700130 /* Get the dwX values for pmc gpe settings */
131 size = dev_read_size(dev, "gpe0-dw");
132 if (size < 0)
133 return log_msg_ret("Cannot read gpe0-dm", size);
134 upriv->gpe0_count = size / sizeof(u32);
135 ret = dev_read_u32_array(dev, "gpe0-dw", upriv->gpe0_dw,
136 upriv->gpe0_count);
137 if (ret)
138 return log_msg_ret("Bad gpe0-dw", ret);
139
Simon Glassb75b15b2020-12-03 16:55:23 -0700140 return pmc_ofdata_to_uc_plat(dev);
Simon Glasse63ca972019-12-06 21:42:57 -0700141#else
142 struct dtd_intel_apl_pmc *dtplat = &plat->dtplat;
143
144 plat->bdf = pci_ofplat_get_devfn(dtplat->reg[0]);
145 upriv->pmc_bar0 = (void *)dtplat->early_regs[0];
146 upriv->pmc_bar2 = (void *)dtplat->early_regs[2];
147 upriv->acpi_base = dtplat->early_regs[4];
148 upriv->gpe0_dwx_mask = dtplat->gpe0_dwx_mask;
149 upriv->gpe0_dwx_shift_base = dtplat->gpe0_dwx_shift_base;
150 upriv->gpe0_sts_reg = dtplat->gpe0_sts;
151 upriv->gpe0_sts_reg += upriv->acpi_base;
152 upriv->gpe0_en_reg = dtplat->gpe0_en;
153 upriv->gpe0_en_reg += upriv->acpi_base;
154 upriv->gpe0_count = min((int)ARRAY_SIZE(dtplat->gpe0_dw), GPE0_REG_MAX);
155 memcpy(upriv->gpe0_dw, dtplat->gpe0_dw, sizeof(dtplat->gpe0_dw));
156#endif
157 upriv->gpe_cfg = (u32 *)(upriv->pmc_bar0 + GPIO_GPE_CFG);
158
159 return 0;
160}
161
162static int enable_pmcbar(struct udevice *dev)
163{
164 struct acpi_pmc_upriv *upriv = dev_get_uclass_priv(dev);
Simon Glassb75b15b2020-12-03 16:55:23 -0700165 struct apl_pmc_plat *priv = dev_get_plat(dev);
Simon Glasse63ca972019-12-06 21:42:57 -0700166 pci_dev_t pmc = priv->bdf;
167
168 /*
169 * Set PMC base addresses and enable decoding. BARs 1 and 3 are 64-bit
170 * BARs.
171 */
172 pci_x86_write_config(pmc, PCI_BASE_ADDRESS_0, (ulong)upriv->pmc_bar0,
173 PCI_SIZE_32);
174 pci_x86_write_config(pmc, PCI_BASE_ADDRESS_1, 0, PCI_SIZE_32);
175 pci_x86_write_config(pmc, PCI_BASE_ADDRESS_2, (ulong)upriv->pmc_bar2,
176 PCI_SIZE_32);
177 pci_x86_write_config(pmc, PCI_BASE_ADDRESS_3, 0, PCI_SIZE_32);
178 pci_x86_write_config(pmc, PCI_BASE_ADDRESS_4, upriv->acpi_base,
179 PCI_SIZE_16);
180 pci_x86_write_config(pmc, PCI_COMMAND, PCI_COMMAND_IO |
181 PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER,
182 PCI_SIZE_16);
183
184 return 0;
185}
186
187static int apl_pmc_probe(struct udevice *dev)
188{
Simon Glassbaf7bd42019-12-29 21:19:13 -0700189 if (spl_phase() == PHASE_TPL) {
Simon Glasse63ca972019-12-06 21:42:57 -0700190 return enable_pmcbar(dev);
Simon Glassbaf7bd42019-12-29 21:19:13 -0700191 } else {
192 struct acpi_pmc_upriv *upriv = dev_get_uclass_priv(dev);
193
194 upriv->pmc_bar0 = (void *)dm_pci_read_bar32(dev, 0);
195 upriv->pmc_bar2 = (void *)dm_pci_read_bar32(dev, 2);
196 }
Simon Glasse63ca972019-12-06 21:42:57 -0700197
198 return 0;
199}
200
Simon Glass772136b2020-12-23 08:11:26 -0700201static const struct acpi_pmc_ops apl_pmc_ops = {
Simon Glasse63ca972019-12-06 21:42:57 -0700202 .init = apl_pmc_fill_power_state,
203 .prev_sleep_state = apl_prev_sleep_state,
204 .disable_tco = apl_disable_tco,
205 .global_reset_set_enable = apl_global_reset_set_enable,
206};
207
Simon Glass92882652021-08-07 07:24:04 -0600208#if CONFIG_IS_ENABLED(OF_REAL)
Simon Glasse63ca972019-12-06 21:42:57 -0700209static const struct udevice_id apl_pmc_ids[] = {
210 { .compatible = "intel,apl-pmc" },
211 { }
212};
Simon Glassec8ae8a2020-12-23 08:11:30 -0700213#endif
Simon Glasse63ca972019-12-06 21:42:57 -0700214
Simon Glassa055da82020-10-05 05:27:01 -0600215U_BOOT_DRIVER(intel_apl_pmc) = {
Simon Glasse63ca972019-12-06 21:42:57 -0700216 .name = "intel_apl_pmc",
217 .id = UCLASS_ACPI_PMC,
Simon Glassec8ae8a2020-12-23 08:11:30 -0700218 .of_match = of_match_ptr(apl_pmc_ids),
Simon Glassb75b15b2020-12-03 16:55:23 -0700219 .of_to_plat = apl_pmc_ofdata_to_uc_plat,
Simon Glasse63ca972019-12-06 21:42:57 -0700220 .probe = apl_pmc_probe,
221 .ops = &apl_pmc_ops,
Simon Glassb75b15b2020-12-03 16:55:23 -0700222 .plat_auto = sizeof(struct apl_pmc_plat),
Simon Glasse63ca972019-12-06 21:42:57 -0700223};