coreboot
coreboot is an Open Source project aimed at replacing the proprietary BIOS found in most computers.
chip.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 
3 #include <acpi/acpi_device.h>
4 #include <acpi/acpigen.h>
5 #include <acpi/acpigen_pci.h>
6 #include <assert.h>
7 #include <console/console.h>
8 #include <device/device.h>
9 #include <device/pci.h>
10 #include <device/pci_ids.h>
11 #include <device/pci_ops.h>
12 #include "chip.h"
13 
14 /*
15  * This UUID and the resulting ACPI Device Property is defined by the
16  * Power Management for Storage Hardware Devices:
17  *
18  * https://docs.microsoft.com/en-us/windows-hardware/design/component-guidelines/power-management-for-storage-hardware-devices-intro
19  */
20 #define PCIE_RTD3_STORAGE_UUID "5025030F-842F-4AB4-A561-99A5189762D0"
21 #define PCIE_RTD3_STORAGE_PROPERTY "StorageD3Enable"
22 
23 /*
24  * Writes the ACPI power resources for a PCI device so it can enter D3Cold.
25  *
26  * If the device is a storage class, then the StorageD3Enable _DSD will
27  * also be added.
28  *
29  * e.g.,
30  *
31  * Scope (\_SB.PCI0.GP14)
32  * {
33  * Device (NVME)
34  * {
35  * Name (_PR0, Package (0x01) // _PR0: Power Resources for D0
36  * {
37  * PRIC
38  * })
39  * Name (_PR3, Package (0x01) // _PR3: Power Resources for D3hot
40  * {
41  * PRIC
42  * })
43  * PowerResource (PRIC, 0x00, 0x0000)
44  * {
45  * Method (_STA, 0, NotSerialized) // _STA: Status
46  * {
47  * ...
48  * }
49  *
50  * Method (_ON, 0, Serialized) // _ON_: Power On
51  * {
52  * ...
53  * }
54  *
55  * Method (_OFF, 0, Serialized) // _OFF: Power Off
56  * {
57  * ...
58  * }
59  * }
60  *
61  * Name (_ADR, 0x0000000000000000) // _ADR: Address
62  * Method (_STA, 0, NotSerialized) // _STA: Status
63  * {
64  * Return (0x0F)
65  * }
66  *
67  * Name (_DSD, Package (0x02) // _DSD: Device-Specific Data
68  * {
69  * ToUUID ("5025030f-842f-4ab4-a561-99a5189762d0"),
70  * Package (0x01)
71  * {
72  * Package (0x02)
73  * {
74  * "StorageD3Enable",
75  * One
76  * }
77  * }
78  * })
79  * }
80  * }
81  */
82 static void pcie_rtd3_device_acpi_fill_ssdt(const struct device *dev)
83 {
84  struct acpi_dp *dsd, *pkg;
86  /* Copy the GPIOs to avoid discards 'const' qualifier error */
87  struct acpi_gpio reset_gpio = config->reset_gpio;
88  struct acpi_gpio enable_gpio = config->enable_gpio;
89  const struct acpi_power_res_params power_res_params = {
91  .reset_delay_ms = config->reset_delay_ms,
92  .reset_off_delay_ms = config->reset_off_delay_ms,
93  .enable_gpio = &enable_gpio,
94  .enable_delay_ms = config->enable_delay_ms,
95  .enable_off_delay_ms = config->enable_off_delay_ms,
96  .use_gpio_for_status = true,
97  };
98  const char *scope = acpi_device_scope(dev);
99  const char *name = acpi_device_name(dev);
100 
101  assert(name);
102  assert(scope);
103 
104  printk(BIOS_INFO, "%s.%s: Enable RTD3 for %s (%s)\n", scope, name, dev_path(dev),
105  dev->chip_ops->name);
106 
107  acpigen_write_scope(scope);
109 
110  acpi_device_add_power_res(&power_res_params);
111 
114 
115  /* Storage devices won't enter D3 without this property */
116  if ((dev->class >> 16) == PCI_BASE_CLASS_STORAGE) {
117  dsd = acpi_dp_new_table("_DSD");
120  acpi_dp_add_package(dsd, pkg);
121  acpi_dp_write(dsd);
122 
123  printk(BIOS_INFO, "%s.%s: Added StorageD3Enable property\n", scope, name);
124  }
125 
128 
129  /* Call the default PCI acpi_fill_ssdt */
130  pci_rom_ssdt(dev);
131 }
132 
133 static const char *pcie_rtd3_device_acpi_name(const struct device *dev)
134 {
135  const struct drivers_pcie_rtd3_device_config *config = config_of(dev);
136 
137  return config->name;
138 }
139 
140 static struct device_operations pcie_rtd3_device_ops = {
142  .set_resources = pci_dev_set_resources,
143  .enable_resources = pci_dev_enable_resources,
144  .init = pci_dev_init,
145  .ops_pci = &pci_dev_ops_pci,
146  .write_acpi_tables = pci_rom_write_acpi_tables,
147  .acpi_fill_ssdt = pcie_rtd3_device_acpi_fill_ssdt,
148  .acpi_name = pcie_rtd3_device_acpi_name,
149 };
150 
151 static void pcie_rtd3_device_enable(struct device *dev)
152 {
153  struct drivers_pcie_rtd3_device_config *config = dev ? dev->chip_info : NULL;
154 
155  if (!config)
156  return;
157 
158  if (dev->path.type != DEVICE_PATH_PCI) {
159  printk(BIOS_ERR, "%s: Invalid device type\n", dev_path(dev));
160  return;
161  }
162 
163  dev->ops = &pcie_rtd3_device_ops;
164 }
165 
167  CHIP_NAME("PCIe Device w/ Runtime D3")
168  .enable_dev = pcie_rtd3_device_enable
169 };
struct acpi_dp * acpi_dp_add_package(struct acpi_dp *dp, struct acpi_dp *package)
Definition: device.c:1036
void acpi_device_add_power_res(const struct acpi_power_res_params *params)
Definition: device.c:646
struct acpi_dp * acpi_dp_add_integer(struct acpi_dp *dp, const char *name, uint64_t value)
Definition: device.c:977
void acpi_dp_write(struct acpi_dp *table)
Definition: device.c:898
int acpi_device_status(const struct device *dev)
Definition: device.c:193
const char * acpi_device_name(const struct device *dev)
Definition: device.c:49
struct acpi_dp * acpi_dp_new_table(const char *name)
Definition: device.c:930
const char * acpi_device_scope(const struct device *dev)
Definition: device.c:158
void acpigen_write_scope(const char *name)
Definition: acpigen.c:326
void acpigen_write_STA(uint8_t status)
Definition: acpigen.c:783
void acpigen_write_device(const char *name)
Definition: acpigen.c:769
void acpigen_write_ADR_pci_device(const struct device *dev)
Definition: acpigen_pci.c:22
const char * name
Definition: mmu.c:92
#define assert(statement)
Definition: assert.h:74
#define printk(level,...)
Definition: stdlib.h:16
const char * dev_path(const struct device *dev)
Definition: device_util.c:149
static const char * pcie_rtd3_device_acpi_name(const struct device *dev)
Definition: chip.c:133
static void pcie_rtd3_device_acpi_fill_ssdt(const struct device *dev)
Definition: chip.c:82
static struct device_operations pcie_rtd3_device_ops
Definition: chip.c:140
static void pcie_rtd3_device_enable(struct device *dev)
Definition: chip.c:151
struct chip_operations drivers_pcie_rtd3_device_ops
Definition: chip.c:166
#define PCIE_RTD3_STORAGE_PROPERTY
Definition: chip.c:21
#define PCIE_RTD3_STORAGE_UUID
Definition: chip.c:20
void acpigen_write_device_end(void)
Definition: acpigen.h:354
void acpigen_write_scope_end(void)
Definition: acpigen.h:343
#define CHIP_NAME(X)
Definition: device.h:32
static DEVTREE_CONST void * config_of(const struct device *dev)
Definition: device.h:382
#define BIOS_INFO
BIOS_INFO - Expected events.
Definition: loglevel.h:113
#define BIOS_ERR
BIOS_ERR - System in incomplete state.
Definition: loglevel.h:72
enum board_config config
Definition: memory.c:448
@ DEVICE_PATH_PCI
Definition: path.h:9
void pci_dev_init(struct device *dev)
Default handler: only runs the relevant PCI BIOS.
Definition: pci_device.c:873
void pci_dev_enable_resources(struct device *dev)
Definition: pci_device.c:721
void pci_dev_read_resources(struct device *dev)
Definition: pci_device.c:534
struct pci_operations pci_dev_ops_pci
Default device operation for PCI devices.
Definition: pci_device.c:911
void pci_dev_set_resources(struct device *dev)
Definition: pci_device.c:691
#define PCI_BASE_CLASS_STORAGE
Definition: pci_ids.h:16
unsigned long pci_rom_write_acpi_tables(const struct device *device, unsigned long current, struct acpi_rsdp *rsdp)
void pci_rom_ssdt(const struct device *device)
#define NULL
Definition: stddef.h:19
struct acpi_gpio * enable_gpio
Definition: acpi_device.h:440
struct acpi_gpio * reset_gpio
Definition: acpi_device.h:430
const char * name
Definition: device.h:29
void(* read_resources)(struct device *dev)
Definition: device.h:39
enum device_path_type type
Definition: path.h:114
Definition: device.h:107
struct chip_operations * chip_ops
Definition: device.h:144
struct device_path path
Definition: device.h:115
struct device_operations * ops
Definition: device.h:143
unsigned int class
Definition: device.h:120
DEVTREE_CONST void * chip_info
Definition: device.h:164