blob: aec0c8394c2e5b708e1fdcd6d09b9d4ef2d4d486 [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
11#include <common.h>
12#include <acpi_s3.h>
13#include <dt-structs.h>
14#include <dm.h>
15#include <spl.h>
16#include <asm/io.h>
17#include <asm/pci.h>
18#include <power/acpi_pmc.h>
19
20#define GPIO_GPE_CFG 0x1050
21
22/* Memory mapped IO registers behind PMC_BASE_ADDRESS */
23#define PRSTS 0x1000
24#define GEN_PMCON1 0x1020
25#define COLD_BOOT_STS BIT(27)
26#define COLD_RESET_STS BIT(26)
27#define WARM_RESET_STS BIT(25)
28#define GLOBAL_RESET_STS BIT(24)
29#define SRS BIT(20)
30#define MS4V BIT(18)
31#define RPS BIT(2)
32#define GEN_PMCON1_CLR1_BITS (COLD_BOOT_STS | COLD_RESET_STS | \
33 WARM_RESET_STS | GLOBAL_RESET_STS | \
34 SRS | MS4V)
35#define GEN_PMCON2 0x1024
36#define GEN_PMCON3 0x1028
37
38/* Offset of TCO registers from ACPI base I/O address */
39#define TCO_REG_OFFSET 0x60
40#define TCO1_STS 0x64
41#define DMISCI_STS BIT(9)
42#define BOOT_STS BIT(18)
43#define TCO2_STS 0x66
44#define TCO1_CNT 0x68
45#define TCO_LOCK BIT(12)
46#define TCO2_CNT 0x6a
47
48enum {
49 ETR = 0x1048,
50 CF9_LOCK = 1UL << 31,
51 CF9_GLB_RST = 1 << 20,
52};
53
54struct apl_pmc_platdata {
55#if CONFIG_IS_ENABLED(OF_PLATDATA)
56 struct dtd_intel_apl_pmc dtplat;
57#endif
58 pci_dev_t bdf;
59};
60
61static int apl_pmc_fill_power_state(struct udevice *dev)
62{
63 struct acpi_pmc_upriv *upriv = dev_get_uclass_priv(dev);
64
65 upriv->tco1_sts = inw(upriv->acpi_base + TCO1_STS);
66 upriv->tco2_sts = inw(upriv->acpi_base + TCO2_STS);
67
68 upriv->prsts = readl(upriv->pmc_bar0 + PRSTS);
69 upriv->gen_pmcon1 = readl(upriv->pmc_bar0 + GEN_PMCON1);
70 upriv->gen_pmcon2 = readl(upriv->pmc_bar0 + GEN_PMCON2);
71 upriv->gen_pmcon3 = readl(upriv->pmc_bar0 + GEN_PMCON3);
72
73 return 0;
74}
75
76static int apl_prev_sleep_state(struct udevice *dev, int prev_sleep_state)
77{
78 struct acpi_pmc_upriv *upriv = dev_get_uclass_priv(dev);
79
80 /* WAK_STS bit will not be set when waking from G3 state */
81 if (!(upriv->pm1_sts & WAK_STS) &&
82 (upriv->gen_pmcon1 & COLD_BOOT_STS))
83 prev_sleep_state = ACPI_S5;
84
85 return prev_sleep_state;
86}
87
88static int apl_disable_tco(struct udevice *dev)
89{
90 struct acpi_pmc_upriv *upriv = dev_get_uclass_priv(dev);
91
92 pmc_disable_tco_base(upriv->acpi_base + TCO_REG_OFFSET);
93
94 return 0;
95}
96
97static int apl_global_reset_set_enable(struct udevice *dev, bool enable)
98{
99 struct acpi_pmc_upriv *upriv = dev_get_uclass_priv(dev);
100
101 if (enable)
102 setbits_le32(upriv->pmc_bar0 + ETR, CF9_GLB_RST);
103 else
104 clrbits_le32(upriv->pmc_bar0 + ETR, CF9_GLB_RST);
105
106 return 0;
107}
108
109int apl_pmc_ofdata_to_uc_platdata(struct udevice *dev)
110{
111 struct acpi_pmc_upriv *upriv = dev_get_uclass_priv(dev);
112 struct apl_pmc_platdata *plat = dev_get_platdata(dev);
113
114#if !CONFIG_IS_ENABLED(OF_PLATDATA)
115 u32 base[6];
116 int size;
117 int ret;
118
119 ret = dev_read_u32_array(dev, "early-regs", base, ARRAY_SIZE(base));
120 if (ret)
121 return log_msg_ret("Missing/short early-regs", ret);
Simon Glassbaf7bd42019-12-29 21:19:13 -0700122 if (spl_phase() == PHASE_TPL) {
123 upriv->pmc_bar0 = (void *)base[0];
124 upriv->pmc_bar2 = (void *)base[2];
125
126 /* Since PCI is not enabled, we must get the BDF manually */
127 plat->bdf = pci_get_devfn(dev);
128 if (plat->bdf < 0)
129 return log_msg_ret("Cannot get PMC PCI address",
130 plat->bdf);
131 }
Simon Glasse63ca972019-12-06 21:42:57 -0700132 upriv->acpi_base = base[4];
133
134 /* Since PCI is not enabled, we must get the BDF manually */
135 plat->bdf = pci_get_devfn(dev);
136 if (plat->bdf < 0)
137 return log_msg_ret("Cannot get PMC PCI address", plat->bdf);
138
139 /* Get the dwX values for pmc gpe settings */
140 size = dev_read_size(dev, "gpe0-dw");
141 if (size < 0)
142 return log_msg_ret("Cannot read gpe0-dm", size);
143 upriv->gpe0_count = size / sizeof(u32);
144 ret = dev_read_u32_array(dev, "gpe0-dw", upriv->gpe0_dw,
145 upriv->gpe0_count);
146 if (ret)
147 return log_msg_ret("Bad gpe0-dw", ret);
148
149 return pmc_ofdata_to_uc_platdata(dev);
150#else
151 struct dtd_intel_apl_pmc *dtplat = &plat->dtplat;
152
153 plat->bdf = pci_ofplat_get_devfn(dtplat->reg[0]);
154 upriv->pmc_bar0 = (void *)dtplat->early_regs[0];
155 upriv->pmc_bar2 = (void *)dtplat->early_regs[2];
156 upriv->acpi_base = dtplat->early_regs[4];
157 upriv->gpe0_dwx_mask = dtplat->gpe0_dwx_mask;
158 upriv->gpe0_dwx_shift_base = dtplat->gpe0_dwx_shift_base;
159 upriv->gpe0_sts_reg = dtplat->gpe0_sts;
160 upriv->gpe0_sts_reg += upriv->acpi_base;
161 upriv->gpe0_en_reg = dtplat->gpe0_en;
162 upriv->gpe0_en_reg += upriv->acpi_base;
163 upriv->gpe0_count = min((int)ARRAY_SIZE(dtplat->gpe0_dw), GPE0_REG_MAX);
164 memcpy(upriv->gpe0_dw, dtplat->gpe0_dw, sizeof(dtplat->gpe0_dw));
165#endif
166 upriv->gpe_cfg = (u32 *)(upriv->pmc_bar0 + GPIO_GPE_CFG);
167
168 return 0;
169}
170
171static int enable_pmcbar(struct udevice *dev)
172{
173 struct acpi_pmc_upriv *upriv = dev_get_uclass_priv(dev);
174 struct apl_pmc_platdata *priv = dev_get_platdata(dev);
175 pci_dev_t pmc = priv->bdf;
176
177 /*
178 * Set PMC base addresses and enable decoding. BARs 1 and 3 are 64-bit
179 * BARs.
180 */
181 pci_x86_write_config(pmc, PCI_BASE_ADDRESS_0, (ulong)upriv->pmc_bar0,
182 PCI_SIZE_32);
183 pci_x86_write_config(pmc, PCI_BASE_ADDRESS_1, 0, PCI_SIZE_32);
184 pci_x86_write_config(pmc, PCI_BASE_ADDRESS_2, (ulong)upriv->pmc_bar2,
185 PCI_SIZE_32);
186 pci_x86_write_config(pmc, PCI_BASE_ADDRESS_3, 0, PCI_SIZE_32);
187 pci_x86_write_config(pmc, PCI_BASE_ADDRESS_4, upriv->acpi_base,
188 PCI_SIZE_16);
189 pci_x86_write_config(pmc, PCI_COMMAND, PCI_COMMAND_IO |
190 PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER,
191 PCI_SIZE_16);
192
193 return 0;
194}
195
196static int apl_pmc_probe(struct udevice *dev)
197{
Simon Glassbaf7bd42019-12-29 21:19:13 -0700198 if (spl_phase() == PHASE_TPL) {
Simon Glasse63ca972019-12-06 21:42:57 -0700199 return enable_pmcbar(dev);
Simon Glassbaf7bd42019-12-29 21:19:13 -0700200 } else {
201 struct acpi_pmc_upriv *upriv = dev_get_uclass_priv(dev);
202
203 upriv->pmc_bar0 = (void *)dm_pci_read_bar32(dev, 0);
204 upriv->pmc_bar2 = (void *)dm_pci_read_bar32(dev, 2);
205 }
Simon Glasse63ca972019-12-06 21:42:57 -0700206
207 return 0;
208}
209
210static struct acpi_pmc_ops apl_pmc_ops = {
211 .init = apl_pmc_fill_power_state,
212 .prev_sleep_state = apl_prev_sleep_state,
213 .disable_tco = apl_disable_tco,
214 .global_reset_set_enable = apl_global_reset_set_enable,
215};
216
217static const struct udevice_id apl_pmc_ids[] = {
218 { .compatible = "intel,apl-pmc" },
219 { }
220};
221
222U_BOOT_DRIVER(apl_pmc) = {
223 .name = "intel_apl_pmc",
224 .id = UCLASS_ACPI_PMC,
225 .of_match = apl_pmc_ids,
226 .ofdata_to_platdata = apl_pmc_ofdata_to_uc_platdata,
227 .probe = apl_pmc_probe,
228 .ops = &apl_pmc_ops,
229 .platdata_auto_alloc_size = sizeof(struct apl_pmc_platdata),
230};