From 9dc35142aceecb15eea1c0211d0d325a6c0ddff6 Mon Sep 17 00:00:00 2001 From: Matt DeVillier Date: Fri, 31 Oct 2025 15:38:35 -0500 Subject: [PATCH] soc/amd/stoneyridge: Generate SATA ACPI registers at runtime Convert SATA controller ACPI OperationRegion and Field definitions from static ASL code to runtime-generated acpigen code. This allows the SATA registers (STB5, SB5, and port fields P0ER-P3PR) to be conditionally included in ACPI tables only when the SATA controller (device 00:11.0) is enabled in the devicetree. Including them unconditionally when the SATA PCI device is disabled causes Windows to BSOD (ACPI BIOS ERROR), since the OpRegion references a non-existent device. Changes: - Move SATA OperationRegion generation to sata.c using acpigen APIs - Remove static SATA fields from acpi/pci_int.asl - Add stoneyridge_sata_ops with acpi_fill_ssdt callback - Update chipset_st.cb and chipset_cz.cb to use stoneyridge_sata_ops - Remove Kconfig for SoC common SATA code, since no longer used This reduces ACPI table size when SATA is disabled and properly scopes SATA registers to the SATA device. TEST=boot Win11 on google/liara without a BSOD Change-Id: I6e7a9a60e3622368eac83c36efd384c8d92c2b05 Signed-off-by: Matt DeVillier Reviewed-on: https://review.coreboot.org/c/coreboot/+/89855 Tested-by: build bot (Jenkins) Reviewed-by: Paul Menzel Reviewed-by: Maximilian Brune --- src/soc/amd/stoneyridge/Kconfig | 1 - src/soc/amd/stoneyridge/acpi/pci_int.asl | 78 +------- src/soc/amd/stoneyridge/chipset_cz.cb | 2 +- src/soc/amd/stoneyridge/chipset_st.cb | 2 +- src/soc/amd/stoneyridge/sata.c | 220 ++++++++++++++++++++++- 5 files changed, 227 insertions(+), 76 deletions(-) diff --git a/src/soc/amd/stoneyridge/Kconfig b/src/soc/amd/stoneyridge/Kconfig index 1d236363a6..b8c04b59b6 100644 --- a/src/soc/amd/stoneyridge/Kconfig +++ b/src/soc/amd/stoneyridge/Kconfig @@ -36,7 +36,6 @@ config SOC_AMD_STONEYRIDGE select SOC_AMD_COMMON_BLOCK_PCI select SOC_AMD_COMMON_BLOCK_PM select SOC_AMD_COMMON_BLOCK_PSP_GEN1 - select SOC_AMD_COMMON_BLOCK_SATA select SOC_AMD_COMMON_BLOCK_SMBUS select SOC_AMD_COMMON_BLOCK_SMI select SOC_AMD_COMMON_BLOCK_SMM diff --git a/src/soc/amd/stoneyridge/acpi/pci_int.asl b/src/soc/amd/stoneyridge/acpi/pci_int.asl index e905c9738c..8d76c58f9e 100644 --- a/src/soc/amd/stoneyridge/acpi/pci_int.asl +++ b/src/soc/amd/stoneyridge/acpi/pci_int.asl @@ -5,8 +5,6 @@ * ((bus number + 1) * ((device number * 8) * 4096)) + register offset * The 8 comes from 8 functions per device, and 4096 bytes per function config space */ - Offset(0x00088024), /* Byte offset to SATA register 24h - Bus 0, Device 17, Function 0 */ - STB5, 32, Offset(0x00098042), /* Byte offset to OHCI0 register 42h - Bus 0, Device 19, Function 0 */ PT0D, 1, PT1D, 1, @@ -30,76 +28,12 @@ P92E, 1, /* Port92 decode enable */ } - OperationRegion(SB5, SystemMemory, STB5, 0x1000) - Field(SB5, AnyAcc, NoLock, Preserve){ - /* Port 0 */ - Offset(0x120), /* Port 0 Task file status */ - P0ER, 1, - , 2, - P0DQ, 1, - , 3, - P0BY, 1, - Offset(0x128), /* Port 0 Serial ATA status */ - P0DD, 4, - , 4, - P0IS, 4, - Offset(0x12c), /* Port 0 Serial ATA control */ - P0DI, 4, - Offset(0x130), /* Port 0 Serial ATA error */ - , 16, - P0PR, 1, - - /* Port 1 */ - offset(0x1a0), /* Port 1 Task file status */ - P1ER, 1, - , 2, - P1DQ, 1, - , 3, - P1BY, 1, - Offset(0x1a8), /* Port 1 Serial ATA status */ - P1DD, 4, - , 4, - P1IS, 4, - Offset(0x1ac), /* Port 1 Serial ATA control */ - P1DI, 4, - Offset(0x1b0), /* Port 1 Serial ATA error */ - , 16, - P1PR, 1, - - /* Port 2 */ - Offset(0x220), /* Port 2 Task file status */ - P2ER, 1, - , 2, - P2DQ, 1, - , 3, - P2BY, 1, - Offset(0x228), /* Port 2 Serial ATA status */ - P2DD, 4, - , 4, - P2IS, 4, - Offset(0x22c), /* Port 2 Serial ATA control */ - P2DI, 4, - Offset(0x230), /* Port 2 Serial ATA error */ - , 16, - P2PR, 1, - - /* Port 3 */ - Offset(0x2a0), /* Port 3 Task file status */ - P3ER, 1, - , 2, - P3DQ, 1, - , 3, - P3BY, 1, - Offset(0x2a8), /* Port 3 Serial ATA status */ - P3DD, 4, - , 4, - P3IS, 4, - Offset(0x2aC), /* Port 3 Serial ATA control */ - P3DI, 4, - Offset(0x2b0), /* Port 3 Serial ATA error */ - , 16, - P3PR, 1, - } + /* + * SATA OperationRegion (STB5, SB5) and port Fields (P0ER, P0DQ, etc.) + * are now generated at runtime via acpigen in acpi_sata.c + * This allows the SATA registers to only be included when the SATA + * controller (device 00:11.0) is enabled in the devicetree. + */ Name(IRQB, ResourceTemplate(){ IRQ(Level,ActiveLow,Shared){15} diff --git a/src/soc/amd/stoneyridge/chipset_cz.cb b/src/soc/amd/stoneyridge/chipset_cz.cb index d45c6d7d56..3101114e8f 100644 --- a/src/soc/amd/stoneyridge/chipset_cz.cb +++ b/src/soc/amd/stoneyridge/chipset_cz.cb @@ -26,7 +26,7 @@ chip soc/amd/stoneyridge device pci 09.0 alias hda_bridge off end # host audio bridge device pci 09.2 alias hda off end # main HD Audio Controller device pci 10.0 alias xhci off ops stoneyridge_usb_ops end - device pci 11.0 alias sata off ops amd_sata_ops end + device pci 11.0 alias sata off ops stoneyridge_sata_ops end device pci 12.0 alias ehci off ops stoneyridge_usb_ops end device pci 14.0 alias smbus on ops amd_smbus_ops end # primary FCH function device pci 14.3 alias lpc_bridge on ops amd_lpc_ops end diff --git a/src/soc/amd/stoneyridge/chipset_st.cb b/src/soc/amd/stoneyridge/chipset_st.cb index 0039ed97a7..e404b655de 100644 --- a/src/soc/amd/stoneyridge/chipset_st.cb +++ b/src/soc/amd/stoneyridge/chipset_st.cb @@ -20,7 +20,7 @@ chip soc/amd/stoneyridge device pci 09.0 alias hda_bridge off end # host audio bridge device pci 09.2 alias hda off end # main HD Audio Controller device pci 10.0 alias xhci off ops stoneyridge_usb_ops end - device pci 11.0 alias sata off ops amd_sata_ops end + device pci 11.0 alias sata off ops stoneyridge_sata_ops end device pci 12.0 alias ehci off ops stoneyridge_usb_ops end device pci 14.0 alias smbus on ops amd_smbus_ops end # primary FCH function device pci 14.3 alias lpc_bridge on ops amd_lpc_ops end diff --git a/src/soc/amd/stoneyridge/sata.c b/src/soc/amd/stoneyridge/sata.c index fb2f7acd91..110b23b0f1 100644 --- a/src/soc/amd/stoneyridge/sata.c +++ b/src/soc/amd/stoneyridge/sata.c @@ -1,9 +1,12 @@ /* SPDX-License-Identifier: GPL-2.0-only */ +#include +#include +#include +#include #include #include #include -#include #include void soc_enable_sata_features(struct device *dev) @@ -30,4 +33,219 @@ void soc_enable_sata_features(struct device *dev) temp = pci_read_config32(dev, SATA_MISC_CONTROL_REG); temp &= ~SATA_MISC_SUBCLASS_WREN; pci_write_config32(dev, SATA_MISC_CONTROL_REG, temp); +} + +#if CONFIG(HAVE_ACPI_TABLES) + +/* + * Generate ACPI SATA OperationRegion and Fields for port status + * This is only generated if the SATA device (00:11.0) is enabled + */ +static void sata_acpi_fill_ssdt(const struct device *dev) +{ + const char *scope; + + if (!dev->enabled) + return; + + /* First generate the standard PCI device info */ + acpi_device_write_pci_dev(dev); + + /* Get the scope for the SATA device */ + scope = acpi_device_path(dev); + if (!scope) + return; + + acpigen_write_scope(scope); + + /* + * Generate Field in PCFG OperationRegion for SATA BAR5 register + * PCFG is the PCI config space OperationRegion defined elsewhere + * + * Field(PCFG, ByteAcc, NoLock, Preserve) { + * Offset(0x00088024), + * STB5, 32, + * } + * + */ + struct fieldlist sata_pcfg_field[] = { + FIELDLIST_OFFSET(0x00088024), /* SATA device register 24h */ + FIELDLIST_NAMESTR("STB5", 32), /* SATA BAR5 (ABAR) */ + }; + acpigen_write_field("PCFG", sata_pcfg_field, ARRAY_SIZE(sata_pcfg_field), + FIELD_BYTEACC | FIELD_NOLOCK | FIELD_PRESERVE); + + /* + * Generate OperationRegion for SATA AHCI memory space + * This maps to the BAR5 (ABAR) memory region: + * + * OperationRegion(SB5, SystemMemory, STB5, 0x1000) + * + */ + acpigen_emit_ext_op(OPREGION_OP); + acpigen_emit_namestring("SB5"); + acpigen_emit_byte(SYSTEMMEMORY); + acpigen_emit_namestring("STB5"); /* Reference to the STB5 field defined above */ + acpigen_write_integer(0x1000); + + /* + * Generate Field in SB5 OperationRegion for SATA port registers + * These fields allow access to AHCI port status registers: + * + * Field(SB5, AnyAcc, NoLock, Preserve) { + * Offset(0x120), + * P0ER, 1, + * , 2, + * P0DQ, 1, + * , 3, + * P0BY, 1, + * Offset(0x128), + * P0DD, 4, + * , 4, + * P0IS, 4, + * Offset(0x12c), + * P0DI, 4, + * Offset(0x130), + * , 16, + * P0PR, 1, + * Offset(0x1a0), + * P1ER, 1, + * , 2, + * P1DQ, 1, + * , 3, + * P1BY, 1, + * Offset(0x1a8), + * P1DD, 4, + * , 4, + * P1IS, 4, + * Offset(0x1ac), + * P1DI, 4, + * Offset(0x1b0), + * , 16, + * P1PR, 1, + * Offset(0x220), + * P2ER, 1, + * , 2, + * P2DQ, 1, + * , 3, + * P2BY, 1, + * Offset(0x228), + * P2DD, 4, + * , 4, + * P2IS, 4, + * Offset(0x22c), + * P2DI, 4, + * Offset(0x230), + * , 16, + * P2PR, 1, + * Offset(0x2a0), + * P3ER, 1, + * , 2, + * P3DQ, 1, + * , 3, + * P3BY, 1, + * Offset(0x2a8), + * P3DD, 4, + * , 4, + * P3IS, 4, + * Offset(0x2ac), + * P3DI, 4, + * Offset(0x2b0), + * , 16, + * P3PR, 1, + * } + * + */ + struct fieldlist sata_port_fields[] = { + /* Port 0 - offset 0x120 */ + FIELDLIST_OFFSET(0x120), + FIELDLIST_NAMESTR("P0ER", 1), /* Error bit */ + FIELDLIST_RESERVED(2), + FIELDLIST_NAMESTR("P0DQ", 1), /* Data request */ + FIELDLIST_RESERVED(3), + FIELDLIST_NAMESTR("P0BY", 1), /* Busy */ + FIELDLIST_OFFSET(0x128), + FIELDLIST_NAMESTR("P0DD", 4), /* Device detection */ + FIELDLIST_RESERVED(4), + FIELDLIST_NAMESTR("P0IS", 4), /* Interface speed */ + FIELDLIST_OFFSET(0x12c), + FIELDLIST_NAMESTR("P0DI", 4), /* Device idle */ + FIELDLIST_OFFSET(0x130), + FIELDLIST_RESERVED(16), + FIELDLIST_NAMESTR("P0PR", 1), /* Port ready */ + + /* Port 1 - offset 0x1a0 */ + FIELDLIST_OFFSET(0x1a0), + FIELDLIST_NAMESTR("P1ER", 1), + FIELDLIST_RESERVED(2), + FIELDLIST_NAMESTR("P1DQ", 1), + FIELDLIST_RESERVED(3), + FIELDLIST_NAMESTR("P1BY", 1), + FIELDLIST_OFFSET(0x1a8), + FIELDLIST_NAMESTR("P1DD", 4), + FIELDLIST_RESERVED(4), + FIELDLIST_NAMESTR("P1IS", 4), + FIELDLIST_OFFSET(0x1ac), + FIELDLIST_NAMESTR("P1DI", 4), + FIELDLIST_OFFSET(0x1b0), + FIELDLIST_RESERVED(16), + FIELDLIST_NAMESTR("P1PR", 1), + + /* Port 2 - offset 0x220 */ + FIELDLIST_OFFSET(0x220), + FIELDLIST_NAMESTR("P2ER", 1), + FIELDLIST_RESERVED(2), + FIELDLIST_NAMESTR("P2DQ", 1), + FIELDLIST_RESERVED(3), + FIELDLIST_NAMESTR("P2BY", 1), + FIELDLIST_OFFSET(0x228), + FIELDLIST_NAMESTR("P2DD", 4), + FIELDLIST_RESERVED(4), + FIELDLIST_NAMESTR("P2IS", 4), + FIELDLIST_OFFSET(0x22c), + FIELDLIST_NAMESTR("P2DI", 4), + FIELDLIST_OFFSET(0x230), + FIELDLIST_RESERVED(16), + FIELDLIST_NAMESTR("P2PR", 1), + + /* Port 3 - offset 0x2a0 */ + FIELDLIST_OFFSET(0x2a0), + FIELDLIST_NAMESTR("P3ER", 1), + FIELDLIST_RESERVED(2), + FIELDLIST_NAMESTR("P3DQ", 1), + FIELDLIST_RESERVED(3), + FIELDLIST_NAMESTR("P3BY", 1), + FIELDLIST_OFFSET(0x2a8), + FIELDLIST_NAMESTR("P3DD", 4), + FIELDLIST_RESERVED(4), + FIELDLIST_NAMESTR("P3IS", 4), + FIELDLIST_OFFSET(0x2ac), + FIELDLIST_NAMESTR("P3DI", 4), + FIELDLIST_OFFSET(0x2b0), + FIELDLIST_RESERVED(16), + FIELDLIST_NAMESTR("P3PR", 1), + }; + acpigen_write_field("SB5", sata_port_fields, ARRAY_SIZE(sata_port_fields), + FIELD_ANYACC | FIELD_NOLOCK | FIELD_PRESERVE); + + acpigen_pop_len(); /* Scope */ +} + +static const char *sata_acpi_name(const struct device *dev) +{ + return "STCR"; +} + +#endif /* CONFIG(HAVE_ACPI_TABLES) */ + +struct device_operations stoneyridge_sata_ops = { + .read_resources = pci_dev_read_resources, + .set_resources = pci_dev_set_resources, + .enable_resources = pci_dev_enable_resources, + .init = soc_enable_sata_features, + .ops_pci = &pci_dev_ops_pci, +#if CONFIG(HAVE_ACPI_TABLES) + .acpi_name = sata_acpi_name, + .acpi_fill_ssdt = sata_acpi_fill_ssdt, +#endif };