soc/amd/cezanne: Move SSDT code into DSDT

Now that the ACP device is always present in DSDT move the
MSG0 method and helper functions into DSDT. This allows to clean
the common ACP code and reduces differences in the runtime code
pathes. The newly introduced DSDT is also verified at compile time.

Change-Id: Ifc55278aa66abcb54691017738cc843e3088d8e8
Signed-off-by: Patrick Rudolph <patrick.rudolph@9elements.com>
Reviewed-on: https://review.coreboot.org/c/coreboot/+/91159
Reviewed-by: Felix Held <felix-coreboot@felixheld.de>
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
This commit is contained in:
Patrick Rudolph 2026-02-11 11:57:07 +01:00 committed by Matt DeVillier
commit 4e61dd36e4
6 changed files with 79 additions and 235 deletions

View file

@ -26,7 +26,6 @@ config SOC_AMD_CEZANNE_BASE
select RTC
select SOC_AMD_COMMON
select SOC_AMD_COMMON_BLOCK_ACP_GEN1
select SOC_AMD_COMMON_BLOCK_ACP_SOC_SPECIFIC_SSDT_ENTRY
select SOC_AMD_COMMON_BLOCK_ACPI
select SOC_AMD_COMMON_BLOCK_ACPIMMIO
select SOC_AMD_COMMON_BLOCK_ACPIMMIO_PM_IO_ACCESS

View file

@ -92,226 +92,3 @@ const acpi_cstate_t *get_cstate_config_data(size_t *size)
*size = ARRAY_SIZE(cstate_cfg_table);
return cstate_cfg_table;
}
static void acp_soc_write_smn_access_methods(void)
{
acpigen_write_method_serialized("SMNR", 1);
acpigen_write_store_op_to_namestr(ARG0_OP, "\\_SB.PCI0.GNB.SMNA");
acpigen_write_return_namestr("\\_SB.PCI0.GNB.SMND");
acpigen_write_method_end();
acpigen_write_method_serialized("SMNW", 2);
acpigen_write_store_op_to_namestr(ARG0_OP, "\\_SB.PCI0.GNB.SMNA");
acpigen_write_store_op_to_namestr(ARG1_OP, "\\_SB.PCI0.GNB.SMND");
acpigen_write_method_end();
}
/* write value of ACPI variable into SMN register */
static void acp_soc_write_smn_register_write(uint8_t op, uint32_t smn_address)
{
acpigen_emit_namestring("^SMNW");
acpigen_write_integer(smn_address);
acpigen_emit_byte(op);
}
/* read SMN register and store value into ACPI variable */
static void acp_soc_write_smn_register_read(uint32_t smn_address, uint8_t op)
{
acpigen_write_store();
acpigen_emit_namestring("^SMNR");
acpigen_write_integer(smn_address);
acpigen_emit_byte(op);
}
static void acp_soc_write_mailbox_access(void)
{
acp_soc_write_smn_register_write(ARG0_OP, 0x00058A74);
acp_soc_write_smn_register_write(ARG1_OP, 0x00058A54);
acp_soc_write_smn_register_write(ARG2_OP, 0x00058A14);
acp_soc_write_smn_register_read(0x00058A74, LOCAL0_OP);
/* While (LEqual (Local0, 0)) */
acpigen_emit_byte(WHILE_OP);
acpigen_write_len_f();
acpigen_emit_byte(LEQUAL_OP);
acpigen_emit_byte(LOCAL0_OP);
acpigen_emit_byte(ZERO_OP);
acp_soc_write_smn_register_read(0x00058A74, LOCAL0_OP);
acpigen_pop_len(); /* While */
acp_soc_write_smn_register_read(0x00058A54, LOCAL1_OP);
acpigen_write_return_op(LOCAL1_OP);
}
static void acp_soc_write_psp_mbox_buffer_field(void)
{
acpigen_write_name("MBOX");
acpigen_write_byte_buffer(NULL, 4);
acpigen_write_create_buffer_word_field("MBOX", 0, "STAT");
acpigen_write_create_buffer_byte_field("MBOX", 2, "CMDI");
acpigen_write_create_buffer_bit_field("MBOX", 31, "REDY");
}
static void acp_soc_write_psp_read_mbox_from_hw(void)
{
acp_soc_write_smn_register_read(0x03810570, LOCAL0_OP);
acpigen_write_store_op_to_namestr(LOCAL0_OP, "MBOX");
}
static void acp_soc_write_psp_write_mbox_to_hw(void)
{
acpigen_write_store_namestr_to_op("MBOX", LOCAL0_OP);
acp_soc_write_smn_register_write(LOCAL0_OP, 0x03810570);
}
static void acp_soc_write_psp_mailbox_access(void)
{
acp_soc_write_psp_mbox_buffer_field();
acp_soc_write_psp_read_mbox_from_hw();
/* While (LOr (LNotEqual (REDY, 0x1), LNotEqual (CMDI, 0x00))) */
acpigen_emit_byte(WHILE_OP);
acpigen_write_len_f();
acpigen_emit_byte(LOR_OP);
acpigen_emit_byte(LNOT_OP);
acpigen_emit_byte(LEQUAL_OP);
acpigen_emit_namestring("REDY");
acpigen_write_integer(1);
acpigen_emit_byte(LNOT_OP);
acpigen_emit_byte(LEQUAL_OP);
acpigen_emit_namestring("CMDI");
acpigen_write_integer(0);
acp_soc_write_psp_read_mbox_from_hw();
acpigen_pop_len(); /* While */
acpigen_write_store_int_to_op(0, LOCAL0_OP);
acpigen_write_store_op_to_namestr(LOCAL0_OP, "MBOX");
acpigen_write_store_int_to_namestr(0x33, "CMDI");
acp_soc_write_psp_write_mbox_to_hw();
acpigen_write_sleep(1);
acp_soc_write_psp_read_mbox_from_hw();
/* While (LNotEqual (CMDI, 0x00)) */
acpigen_emit_byte(WHILE_OP);
acpigen_write_len_f();
acpigen_emit_byte(LNOT_OP);
acpigen_emit_byte(LEQUAL_OP);
acpigen_emit_namestring("CMDI");
acpigen_write_integer(0);
acp_soc_write_psp_read_mbox_from_hw();
acpigen_pop_len(); /* While */
acpigen_write_return_op(LOCAL0_OP);
}
static void acp_soc_write_msg0_method(void)
{
acpigen_write_method_serialized("MSG0", 3);
/* If (ARG2 != 0x9) */
acpigen_write_if_lnotequal_op_int(ARG2_OP, 0x9);
acp_soc_write_mailbox_access();
acpigen_write_else();
acp_soc_write_psp_mailbox_access();
acpigen_write_if_end();
acpigen_write_method_end(); /* MSG0 */
}
void acp_soc_write_ssdt_entry(const struct device *dev)
{
/*
* SMN and mailbox interface using the SMN OperationRegion on the host bridge
*
* Provide both SMN read/write methods for direct SMN register access and the MSG0
* method which is used by some ACP drivers to access two different mailbox interfaces
* in the hardware. One mailbox interface is used to configure the ACP's clock source,
* the other one is used to notify the PSP that the DSP firmware has been loaded, so
* that the PSP can validate the firmware and set the qualifier bit to enable running
* it.
*
* Scope (\_SB.PCI0.GP41.ACPD)
* {
* Method (SMNR, 1, Serialized)
* {
* Store (Arg0, \_SB.PCI0.GNB.SMNA)
* Return (\_SB.PCI0.GNB.SMND)
* }
*
* Method (SMNW, 2, Serialized)
* {
* Store (Arg0, \_SB.PCI0.GNB.SMNA)
* Store (Arg1, \_SB.PCI0.GNB.SMND)
* }
*
* Method (MSG0, 3, Serialized)
* {
* If (LNotEqual (Arg2, 0x09))
* {
* ^SMNW (0x00058A74, Arg0)
* ^SMNW (0x00058A54, Arg1)
* ^SMNW (0x00058A14, Arg2)
* Store (^SMNR (0x00058A74), Local0)
* While (LEqual (Local0, Zero))
* {
* Store (^SMNR (0x00058A74), Local0)
* }
* Store (^SMNR (0x00058A54), Local1)
* Return (Local1)
* }
* Else
* {
* Name (MBOX, Buffer (0x04){})
* CreateWordField (MBOX, Zero, STAT)
* CreateByteField (MBOX, 0x02, CMDI)
* CreateBitField (MBOX, 0x1F, REDY)
* Store (^SMNR (0x03810570), Local0)
* Store (Local0, MBOX)
* While (LOr (LNotEqual (REDY, One), LNotEqual (CMDI, Zero)))
* {
* Store (^SMNR (0x03810570), Local0)
* Store (Local0, MBOX)
* }
* Store (Zero, Local0)
* Store (Local0, MBOX)
* Store (0x33, CMDI)
* Store (MBOX, Local0)
* ^SMNW (0x03810570, Local0)
* Sleep (One)
* Store (^SMNR (0x03810570), Local0)
* Store (Local0, MBOX)
* While (LNotEqual (CMDI, Zero))
* {
* Store (^SMNR (0x03810570), Local0)
* Store (Local0, MBOX)
* }
* Return (Local0)
* }
* }
* }
*/
acpigen_write_scope(acpi_device_path(dev));
acp_soc_write_smn_access_methods();
acp_soc_write_msg0_method();
acpigen_write_scope_end();
}

View file

@ -10,5 +10,84 @@ Scope (\_SB.PCI0.GP41) {
{
Return (STAT)
}
External (\_SB.PCI0.GNB.SMNA, FieldUnitObj)
External (\_SB.PCI0.GNB.SMND, FieldUnitObj)
/* Read SMN register and store value into ACPI variable */
Method (SMNR, 1, Serialized)
{
\_SB.PCI0.GNB.SMNA = Arg0
Return (\_SB.PCI0.GNB.SMND)
}
/* Write value of ACPI variable into SMN register */
Method (SMNW, 2, Serialized)
{
\_SB.PCI0.GNB.SMNA = Arg0
\_SB.PCI0.GNB.SMND = Arg1
}
/*
* SMN and mailbox interface using the SMN OperationRegion on the host bridge
*
* Provide both SMN read/write methods for direct SMN register access and the MSG0
* method which is used by some ACP drivers to access two different mailbox interfaces
* in the hardware. One mailbox interface is used to configure the ACP's clock source,
* the other one is used to notify the PSP that the DSP firmware has been loaded, so
* that the PSP can validate the firmware and set the qualifier bit to enable running
* it.
*/
Method (MSG0, 3, Serialized)
{
If (Arg2 != 0x09)
{
/* mailbox access */
^SMNW (0x00058A74, Arg0)
^SMNW (0x00058A54, Arg1)
^SMNW (0x00058A14, Arg2)
Local0 = ^SMNR (0x00058A74)
While (Local0 == 0)
{
Local0 = ^SMNR (0x00058A74)
}
Local1 = ^SMNR (0x00058A54)
Return (Local1)
}
Else
{
/* PSP mailbox access */
Name (MBOX, Buffer (0x04) {
0x20, 0x57, 0x91, 0x7B
})
CreateWordField (MBOX, Zero, STAT)
CreateByteField (MBOX, 0x02, CMDI)
CreateBitField (MBOX, 0x1F, REDY)
Local0 = ^SMNR (0x03810570)
MBOX = Local0
While (((REDY != 1) || (CMDI != 0)))
{
Local0 = ^SMNR (0x03810570)
MBOX = Local0
}
Local0 = Zero
MBOX = Local0
CMDI = 0x33
Local0 = MBOX
^SMNW (0x03810570, Local0)
Sleep (1)
Local0 = ^SMNR (0x03810570)
MBOX = Local0
While (CMDI != 0)
{
Local0 = ^SMNR (0x03810570)
MBOX = Local0
}
Return (Local0)
}
}
}
}

View file

@ -11,9 +11,3 @@ config SOC_AMD_COMMON_BLOCK_ACP_GEN2
help
Select this option to perform Audio Co-Processor(ACP) configuration.
Used by the ACP in AMD mendocino (family 17h) and possibly newer CPUs.
config SOC_AMD_COMMON_BLOCK_ACP_SOC_SPECIFIC_SSDT_ENTRY
bool
help
Select this option to call into the SoC code when generating the SSDT
entry for the Audio Co-Processor (ACP).

View file

@ -45,9 +45,6 @@ static void acp_fill_ssdt(const struct device *dev)
acp_fill_wov_method(dev);
acpigen_pop_len(); /* Scope */
if (CONFIG(SOC_AMD_COMMON_BLOCK_ACP_SOC_SPECIFIC_SSDT_ENTRY))
acp_soc_write_ssdt_entry(dev);
}
struct device_operations amd_acp_ops = {

View file

@ -45,6 +45,4 @@ struct acp_config {
bool dmic_present;
};
void acp_soc_write_ssdt_entry(const struct device *dev);
#endif /* AMD_COMMON_ACP_H */