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 <matt.devillier@gmail.com>
Reviewed-on: https://review.coreboot.org/c/coreboot/+/89855
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Paul Menzel <paulepanter@mailbox.org>
Reviewed-by: Maximilian Brune <maximilian.brune@9elements.com>
This commit is contained in:
Matt DeVillier 2025-10-31 15:38:35 -05:00
commit 9dc35142ac
5 changed files with 227 additions and 76 deletions

View file

@ -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

View file

@ -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}

View file

@ -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

View file

@ -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

View file

@ -1,9 +1,12 @@
/* SPDX-License-Identifier: GPL-2.0-only */
#include <acpi/acpi_device.h>
#include <acpi/acpigen.h>
#include <amdblocks/sata.h>
#include <console/console.h>
#include <device/device.h>
#include <device/pci.h>
#include <device/pci_ops.h>
#include <amdblocks/sata.h>
#include <soc/southbridge.h>
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
};