blob: be412e79672d983a951fe4135411f332ffdbc9b8 [file] [log] [blame]
Duncan Laurie64bc26a2020-10-10 00:15:28 +00001/* SPDX-License-Identifier: GPL-2.0-or-later */
2
3#include <acpi/acpigen.h>
4#include <acpi/acpi_device.h>
5#include <console/console.h>
6#include <device/device.h>
7#include <device/pci_ids.h>
8#include <device/pci_ops.h>
9#include <device/pci.h>
10#include <intelblocks/pmc.h>
11#include <intelblocks/pmc_ipc.h>
12#include "chip.h"
13
14/*
15 * The "ExternalFacingPort" and "HotPlugSupportInD3" properties are defined at
16 * https://docs.microsoft.com/en-us/windows-hardware/drivers/pci/dsd-for-pcie-root-ports
17 */
18#define PCIE_EXTERNAL_PORT_UUID "EFCC06CC-73AC-4BC3-BFF0-76143807C389"
19#define PCIE_EXTERNAL_PORT_PROPERTY "ExternalFacingPort"
20
21#define PCIE_HOTPLUG_IN_D3_UUID "6211E2C0-58A3-4AF3-90E1-927A4E0C55A4"
22#define PCIE_HOTPLUG_IN_D3_PROPERTY "HotPlugSupportInD3"
23
24/*
25 * This UUID and the resulting ACPI Device Property is defined by the
26 * Power Management for Storage Hardware Devices:
27 *
28 * https://docs.microsoft.com/en-us/windows-hardware/design/component-guidelines/power-management-for-storage-hardware-devices-intro
29 */
30#define PCIE_RTD3_STORAGE_UUID "5025030F-842F-4AB4-A561-99A5189762D0"
31#define PCIE_RTD3_STORAGE_PROPERTY "StorageD3Enable"
32
33/* PCIe Root Port registers for link status and L23 control. */
34#define PCH_PCIE_CFG_LSTS 0x52 /* Link Status Register */
35#define PCH_PCIE_CFG_SPR 0xe0 /* Scratchpad */
36#define PCH_PCIE_CFG_RPPGEN 0xe2 /* Root Port Power Gating Enable */
37#define PCH_PCIE_CFG_LCAP_PN 0x4f /* Root Port Number */
38
39/* ACPI register names corresponding to PCIe root port registers. */
40#define ACPI_REG_PCI_LINK_ACTIVE "LASX" /* Link active status */
41#define ACPI_REG_PCI_L23_RDY_ENTRY "L23E" /* L23_Rdy Entry Request */
42#define ACPI_REG_PCI_L23_RDY_DETECT "L23R" /* L23_Rdy Detect Transition */
43#define ACPI_REG_PCI_L23_SAVE_STATE "NCB7" /* Scratch bit to save L23 state */
44
45/* Called from _ON to get PCIe link back to active state. */
46static void pcie_rtd3_acpi_l23_exit(void)
47{
48 /* Skip if port is not in L2/L3. */
49 acpigen_write_if_lequal_namestr_int(ACPI_REG_PCI_L23_SAVE_STATE, 1);
50
51 /* Initiate L2/L3 Ready To Detect transition. */
52 acpigen_write_store_int_to_namestr(1, ACPI_REG_PCI_L23_RDY_DETECT);
53
54 /* Wait for transition to detect. */
55 acpigen_write_delay_until_namestr_int(320, ACPI_REG_PCI_L23_RDY_DETECT, 0);
56
57 acpigen_write_store_int_to_namestr(0, ACPI_REG_PCI_L23_SAVE_STATE);
58
59 /* Once in detect, wait for link active. */
60 acpigen_write_delay_until_namestr_int(128, ACPI_REG_PCI_LINK_ACTIVE, 1);
61
62 acpigen_pop_len(); /* If */
63}
64
65/* Called from _OFF to put PCIe link into L2/L3 state. */
66static void pcie_rtd3_acpi_l23_entry(void)
67{
68 /* Initiate L2/L3 Entry request. */
69 acpigen_write_store_int_to_namestr(1, ACPI_REG_PCI_L23_RDY_ENTRY);
70
71 /* Wait for L2/L3 Entry request to clear. */
72 acpigen_write_delay_until_namestr_int(128, ACPI_REG_PCI_L23_RDY_ENTRY, 0);
73
74 acpigen_write_store_int_to_namestr(1, ACPI_REG_PCI_L23_SAVE_STATE);
75}
76
77static void
78pcie_rtd3_acpi_method_on(unsigned int pcie_rp,
79 const struct soc_intel_common_block_pcie_rtd3_config *config)
80{
81 acpigen_write_method_serialized("_ON", 0);
82
83 /* Assert enable GPIO to turn on device power. */
84 if (config->enable_gpio.pin_count) {
85 acpigen_enable_tx_gpio(&config->enable_gpio);
86 if (config->enable_delay_ms)
87 acpigen_write_sleep(config->enable_delay_ms);
88 }
89
90 /* Enable SRCCLK for root port if pin is defined. */
91 if (config->srcclk_pin >= 0)
92 pmc_ipc_acpi_set_pci_clock(pcie_rp, config->srcclk_pin, true);
93
94 /* De-assert reset GPIO to bring device out of reset. */
95 if (config->reset_gpio.pin_count) {
96 acpigen_disable_tx_gpio(&config->reset_gpio);
97 if (config->reset_delay_ms)
98 acpigen_write_sleep(config->reset_delay_ms);
99 }
100
101 /* Trigger L23 ready exit flow unless disabld by config. */
102 if (!config->disable_l23)
103 pcie_rtd3_acpi_l23_exit();
104
105 acpigen_pop_len(); /* Method */
106}
107
108static void
109pcie_rtd3_acpi_method_off(int pcie_rp,
110 const struct soc_intel_common_block_pcie_rtd3_config *config)
111{
112 acpigen_write_method_serialized("_OFF", 0);
113
114 /* Trigger L23 ready entry flow unless disabled by config. */
115 if (!config->disable_l23)
116 pcie_rtd3_acpi_l23_entry();
117
118 /* Assert reset GPIO to place device into reset. */
119 if (config->reset_gpio.pin_count) {
120 acpigen_enable_tx_gpio(&config->reset_gpio);
121 if (config->reset_off_delay_ms)
122 acpigen_write_sleep(config->reset_off_delay_ms);
123 }
124
125 /* Disable SRCCLK for this root port if pin is defined. */
126 if (config->srcclk_pin >= 0)
127 pmc_ipc_acpi_set_pci_clock(pcie_rp, config->srcclk_pin, false);
128
129 /* De-assert enable GPIO to turn off device power. */
130 if (config->enable_gpio.pin_count) {
131 acpigen_disable_tx_gpio(&config->enable_gpio);
132 if (config->enable_off_delay_ms)
133 acpigen_write_sleep(config->enable_off_delay_ms);
134 }
135
136 acpigen_pop_len(); /* Method */
137}
138
139static void
140pcie_rtd3_acpi_method_status(int pcie_rp,
141 const struct soc_intel_common_block_pcie_rtd3_config *config)
142{
143 const struct acpi_gpio *gpio;
144
145 acpigen_write_method("_STA", 0);
146
147 /* Use enable GPIO for status if provided, otherwise use reset GPIO. */
148 if (config->enable_gpio.pin_count)
149 gpio = &config->enable_gpio;
150 else
151 gpio = &config->reset_gpio;
152
153 /* Read current GPIO value into Local0. */
154 acpigen_get_tx_gpio(gpio);
155
156 /* Ensure check works for both active low and active high GPIOs. */
157 acpigen_write_store_int_to_op(gpio->active_low, LOCAL1_OP);
158
159 acpigen_write_if_lequal_op_op(LOCAL0_OP, LOCAL1_OP);
160 acpigen_write_return_op(ZERO_OP);
161 acpigen_pop_len(); /* If */
162 acpigen_write_else();
163 acpigen_write_return_op(ONE_OP);
164 acpigen_pop_len(); /* Else */
165
166 acpigen_pop_len(); /* Method */
167}
168
169static void pcie_rtd3_acpi_fill_ssdt(const struct device *dev)
170{
171 const struct soc_intel_common_block_pcie_rtd3_config *config = config_of(dev);
172 static const char *const power_res_states[] = {"_PR0"};
173 const struct device *parent = dev->bus->dev;
174 const char *scope = acpi_device_path(parent);
175 const struct opregion opregion = OPREGION("PXCS", PCI_CONFIG, 0, 0xff);
176 const struct fieldlist fieldlist[] = {
177 FIELDLIST_OFFSET(PCH_PCIE_CFG_LSTS),
178 FIELDLIST_RESERVED(13),
179 FIELDLIST_NAMESTR(ACPI_REG_PCI_LINK_ACTIVE, 1),
180 FIELDLIST_OFFSET(PCH_PCIE_CFG_SPR),
181 FIELDLIST_RESERVED(7),
182 FIELDLIST_NAMESTR(ACPI_REG_PCI_L23_SAVE_STATE, 1),
183 FIELDLIST_OFFSET(PCH_PCIE_CFG_RPPGEN),
184 FIELDLIST_RESERVED(2),
185 FIELDLIST_NAMESTR(ACPI_REG_PCI_L23_RDY_ENTRY, 1),
186 FIELDLIST_NAMESTR(ACPI_REG_PCI_L23_RDY_DETECT, 1),
187 };
188 uint8_t pcie_rp;
189 struct acpi_dp *dsd, *pkg;
190
191 if (!is_dev_enabled(parent)) {
192 printk(BIOS_ERR, "%s: root port not enabled\n", __func__);
193 return;
194 }
195 if (!scope) {
196 printk(BIOS_ERR, "%s: root port scope not found\n", __func__);
197 return;
198 }
199 if (!config->enable_gpio.pin_count && !config->reset_gpio.pin_count) {
200 printk(BIOS_ERR, "%s: Enable and/or Reset GPIO required for %s.\n",
201 __func__, scope);
202 return;
203 }
204 if (config->srcclk_pin > CONFIG_MAX_PCIE_CLOCKS) {
205 printk(BIOS_ERR, "%s: Invalid clock pin %u for %s.\n", __func__,
206 config->srcclk_pin, scope);
207 return;
208 }
209
210 /* Read port number of root port that this device is attached to. */
211 pcie_rp = pci_read_config8(parent, PCH_PCIE_CFG_LCAP_PN);
212 if (pcie_rp == 0 || pcie_rp > CONFIG_MAX_ROOT_PORTS) {
213 printk(BIOS_ERR, "%s: Invalid root port number: %u\n", __func__, pcie_rp);
214 return;
215 }
216 /* Port number is 1-based, PMC IPC method expects 0-based. */
217 pcie_rp--;
218
219 printk(BIOS_INFO, "%s: Enable RTD3 for %s (%s)\n", scope, dev_path(parent),
220 config->desc ?: dev->chip_ops->name);
221
222 /* The RTD3 power resource is added to the root port, not the device. */
223 acpigen_write_scope(scope);
224
225 if (config->desc)
226 acpigen_write_name_string("_DDN", config->desc);
227
228 acpigen_write_opregion(&opregion);
229 acpigen_write_field("PXCS", fieldlist, ARRAY_SIZE(fieldlist),
230 FIELD_ANYACC | FIELD_NOLOCK | FIELD_PRESERVE);
231
232 /* ACPI Power Resource for controlling the attached device power. */
233 acpigen_write_power_res("RTD3", 0, 0, power_res_states, ARRAY_SIZE(power_res_states));
234 pcie_rtd3_acpi_method_status(pcie_rp, config);
235 pcie_rtd3_acpi_method_on(pcie_rp, config);
236 pcie_rtd3_acpi_method_off(pcie_rp, config);
237 acpigen_pop_len(); /* PowerResource */
238
239 /* Indicate to the OS that device supports hotplug in D3. */
240 dsd = acpi_dp_new_table("_DSD");
241 pkg = acpi_dp_new_table(PCIE_HOTPLUG_IN_D3_UUID);
242 acpi_dp_add_integer(pkg, PCIE_HOTPLUG_IN_D3_PROPERTY, 1);
243 acpi_dp_add_package(dsd, pkg);
244
245 /* Indicate to the OS if the device provides an External facing port. */
246 if (config->is_external) {
247 pkg = acpi_dp_new_table(PCIE_EXTERNAL_PORT_UUID);
248 acpi_dp_add_integer(pkg, PCIE_EXTERNAL_PORT_PROPERTY, 1);
249 acpi_dp_add_package(dsd, pkg);
250 }
251 acpi_dp_write(dsd);
252
253 /*
254 * Check the sibling device on the root port to see if it is storage class and add the
255 * property for the OS to enable storage D3, or allow it to be enabled by config.
256 */
257 if (config->is_storage
258 || (dev->sibling && (dev->sibling->class >> 16) == PCI_BASE_CLASS_STORAGE)) {
259 acpigen_write_device(acpi_device_name(dev));
260 acpigen_write_ADR(0);
261 acpigen_write_STA(ACPI_STATUS_DEVICE_ALL_ON);
262 acpigen_write_name_integer("_S0W", 4);
263
264 dsd = acpi_dp_new_table("_DSD");
265 pkg = acpi_dp_new_table(PCIE_RTD3_STORAGE_UUID);
266 acpi_dp_add_integer(pkg, PCIE_RTD3_STORAGE_PROPERTY, 1);
267 acpi_dp_add_package(dsd, pkg);
268 acpi_dp_write(dsd);
269
270 acpigen_pop_len(); /* Device */
271
272 printk(BIOS_INFO, "%s: Added StorageD3Enable property\n", scope);
273 }
274
275 acpigen_pop_len(); /* Scope */
276}
277
278static const char *pcie_rtd3_acpi_name(const struct device *dev)
279{
280 /* Attached device name must be "PXSX" for the Linux Kernel to recognize it. */
281 return "PXSX";
282}
283
284static struct device_operations pcie_rtd3_ops = {
285 .read_resources = noop_read_resources,
286 .set_resources = noop_set_resources,
287 .acpi_fill_ssdt = pcie_rtd3_acpi_fill_ssdt,
288 .acpi_name = pcie_rtd3_acpi_name,
289};
290
291static void pcie_rtd3_acpi_enable(struct device *dev)
292{
293 dev->ops = &pcie_rtd3_ops;
294}
295
296struct chip_operations soc_intel_common_block_pcie_rtd3_ops = {
297 CHIP_NAME("Intel PCIe Runtime D3")
298 .enable_dev = pcie_rtd3_acpi_enable
299};