Macros can be confusing on their own; hiding commas make things worse. This can sometimes be downright misleading. A "good" example would be the code in soc/intel/xeon_sp/spr/chip.c: CHIP_NAME("Intel SapphireRapids-SP").enable_dev = chip_enable_dev, This appears as CHIP_NAME() being some struct when in fact these are defining 2 separate members of the same struct. It was decided to remove this macro altogether, as it does not do anything special and incurs a maintenance burden. Change-Id: Iaed6dfb144bddcf5c43634b0c955c19afce388f0 Signed-off-by: Nicholas Sudsgaard <devel+coreboot@nsudsgaard.com> Reviewed-on: https://review.coreboot.org/c/coreboot/+/80239 Reviewed-by: Yidi Lin <yidilin@google.com> Reviewed-by: Felix Singer <service+coreboot-gerrit@felixsinger.de> Reviewed-by: Jakub Czapiga <czapiga@google.com> Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: Matt DeVillier <matt.devillier@amd.corp-partner.google.com>
156 lines
4.3 KiB
C
156 lines
4.3 KiB
C
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
|
|
|
#include <acpi/acpi_device.h>
|
|
#include <acpi/acpigen.h>
|
|
#include <acpi/acpigen_pci.h>
|
|
#include <assert.h>
|
|
#include <console/console.h>
|
|
#include <device/device.h>
|
|
#include <device/pci.h>
|
|
#include <device/pci_ids.h>
|
|
#include <device/pci_ops.h>
|
|
#include "chip.h"
|
|
|
|
/*
|
|
* Writes the ACPI power resources for a PCI device so it can enter D3Cold.
|
|
*
|
|
* If the device is a storage class, then the StorageD3Enable _DSD will
|
|
* also be added.
|
|
*
|
|
* e.g.,
|
|
*
|
|
* Scope (\_SB.PCI0.GP14)
|
|
* {
|
|
* Device (NVME)
|
|
* {
|
|
* Name (_PR0, Package (0x01) // _PR0: Power Resources for D0
|
|
* {
|
|
* PRIC
|
|
* })
|
|
* Name (_PR3, Package (0x01) // _PR3: Power Resources for D3hot
|
|
* {
|
|
* PRIC
|
|
* })
|
|
* PowerResource (PRIC, 0x00, 0x0000)
|
|
* {
|
|
* Method (_STA, 0, NotSerialized) // _STA: Status
|
|
* {
|
|
* ...
|
|
* }
|
|
*
|
|
* Method (_ON, 0, Serialized) // _ON_: Power On
|
|
* {
|
|
* ...
|
|
* }
|
|
*
|
|
* Method (_OFF, 0, Serialized) // _OFF: Power Off
|
|
* {
|
|
* ...
|
|
* }
|
|
* }
|
|
*
|
|
* Name (_ADR, 0x0000000000000000) // _ADR: Address
|
|
* Method (_STA, 0, NotSerialized) // _STA: Status
|
|
* {
|
|
* Return (0x0F)
|
|
* }
|
|
*
|
|
* Name (_DSD, Package (0x02) // _DSD: Device-Specific Data
|
|
* {
|
|
* ToUUID ("5025030f-842f-4ab4-a561-99a5189762d0"),
|
|
* Package (0x01)
|
|
* {
|
|
* Package (0x02)
|
|
* {
|
|
* "StorageD3Enable",
|
|
* One
|
|
* }
|
|
* }
|
|
* })
|
|
* }
|
|
* }
|
|
*/
|
|
static void pcie_rtd3_device_acpi_fill_ssdt(const struct device *dev)
|
|
{
|
|
const struct drivers_pcie_rtd3_device_config *config = config_of(dev);
|
|
/* Copy the GPIOs to avoid discards 'const' qualifier error */
|
|
struct acpi_gpio reset_gpio = config->reset_gpio;
|
|
struct acpi_gpio enable_gpio = config->enable_gpio;
|
|
const struct acpi_power_res_params power_res_params = {
|
|
.reset_gpio = &reset_gpio,
|
|
.reset_delay_ms = config->reset_delay_ms,
|
|
.reset_off_delay_ms = config->reset_off_delay_ms,
|
|
.enable_gpio = &enable_gpio,
|
|
.enable_delay_ms = config->enable_delay_ms,
|
|
.enable_off_delay_ms = config->enable_off_delay_ms,
|
|
.use_gpio_for_status = true,
|
|
};
|
|
const char *scope = acpi_device_scope(dev);
|
|
const char *name = acpi_device_name(dev);
|
|
|
|
assert(name);
|
|
assert(scope);
|
|
|
|
printk(BIOS_INFO, "%s.%s: Enable RTD3 for %s (%s)\n", scope, name, dev_path(dev),
|
|
dev->chip_ops->name);
|
|
|
|
acpigen_write_scope(scope);
|
|
acpigen_write_device(acpi_device_name(dev));
|
|
|
|
acpi_device_add_power_res(&power_res_params);
|
|
|
|
acpigen_write_ADR_pci_device(dev);
|
|
acpigen_write_STA(acpi_device_status(dev));
|
|
|
|
/* Storage devices won't enter D3 without this property */
|
|
if ((dev->class >> 16) == PCI_BASE_CLASS_STORAGE) {
|
|
acpi_device_add_storage_d3_enable(NULL);
|
|
|
|
printk(BIOS_INFO, "%s.%s: Added StorageD3Enable property\n", scope, name);
|
|
}
|
|
|
|
acpigen_write_device_end();
|
|
acpigen_write_scope_end();
|
|
|
|
/* Call the default PCI acpi_fill_ssdt */
|
|
pci_rom_ssdt(dev);
|
|
}
|
|
|
|
static const char *pcie_rtd3_device_acpi_name(const struct device *dev)
|
|
{
|
|
const struct drivers_pcie_rtd3_device_config *config = config_of(dev);
|
|
|
|
return config->name;
|
|
}
|
|
|
|
static struct device_operations pcie_rtd3_device_ops = {
|
|
.read_resources = pci_dev_read_resources,
|
|
.set_resources = pci_dev_set_resources,
|
|
.enable_resources = pci_dev_enable_resources,
|
|
.init = pci_dev_init,
|
|
.ops_pci = &pci_dev_ops_pci,
|
|
.write_acpi_tables = pci_rom_write_acpi_tables,
|
|
.acpi_fill_ssdt = pcie_rtd3_device_acpi_fill_ssdt,
|
|
.acpi_name = pcie_rtd3_device_acpi_name,
|
|
};
|
|
|
|
static void pcie_rtd3_device_enable(struct device *dev)
|
|
{
|
|
struct drivers_pcie_rtd3_device_config *config = dev ? dev->chip_info : NULL;
|
|
|
|
if (!config)
|
|
return;
|
|
|
|
if (dev->path.type != DEVICE_PATH_PCI) {
|
|
printk(BIOS_ERR, "%s: Invalid device type\n", dev_path(dev));
|
|
return;
|
|
}
|
|
|
|
dev->ops = &pcie_rtd3_device_ops;
|
|
}
|
|
|
|
struct chip_operations drivers_pcie_rtd3_device_ops = {
|
|
.name = "PCIe Device w/ Runtime D3",
|
|
.enable_dev = pcie_rtd3_device_enable
|
|
};
|