soc/intel/cmn/blk/cnvi: Add _PRR method for Bluetooth CNVi Reset
The change introduces new Advanced Configuration and Power Interface
(ACPI) methods to handle Bluetooth device states, including status
checks and device reset procedures. Specifically, it adds a Power
Resource for Reset (_PRR) method and the associated power resources to
enable Operating System (OS)-level resets for Connectivity Integrated
(CNVi) Bluetooth devices as specified in Intel document
number 559910. This allows the OS to perform Bluetooth hardware recovery
in case of errors, ensuring compliance with Intel's standards. The Power
Resource ACPI code was adapted from Panther Lake (PTL) Firmware Support
Package (FSP) revision 3144.01.
The new ACPI Bluetooth code introduces the CNMT mutex, similar to the
USB Bluetooth ACPI code, to avoid simultaneous CNVi resets when
executing Wi-Fi and Bluetooth power resource _RST methods.
TEST=The following two use cases were verified using acpidbg on a Fatcat
device.
1. Test CNVi Bluetooth _RST() completion.
acpidbg -b 'evaluate \_SB.PCI0.CNVB.PRRS' # 0x0
acpidbg -b 'evaluate \_SB.PCI0.CNVB.RSTT' # 0x0
acpidbg -b 'set N \_SB.PCI0.CNVB.RSTT 1' # 0x1
acpidbg -b 'evaluate \_SB.PCI0.CNVB.CNVP._RST'
acpidbg -b 'evaluate \_SB.PCI0.CNVB.PRRS' # 0x2
2. Test that CNVi Wi-Fi _RST calls CNVi Bluetooth CFLR method.
acpidbg -b 'evaluate \_SB.PCI0.CNVB.PRRS' # 0x0
acpidbg -b 'evaluate \_SB.PCI0.CNVW.RSTT' # 0x0
acpidbg -b 'set N \_SB.PCI0.CNVW.RSTT 1' # 0x0
acpidbg -b 'evaluate \_SB.PCI0.CNVW.CNVP._RST'
acpidbg -b 'evaluate \_SB.PCI0.CNVB.PRRS' # 0x1
Change-Id: I2389901faf4fad131bb7226e356b47f4b1a4ddac
Signed-off-by: Jeremy Compostella <jeremy.compostella@intel.com>
Reviewed-on: https://review.coreboot.org/c/coreboot/+/88111
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Bora Guvendik <bora.guvendik@intel.corp-partner.google.com>
Reviewed-by: Paul Menzel <paulepanter@mailbox.org>
This commit is contained in:
parent
23f5df6eae
commit
782ae11bc7
2 changed files with 315 additions and 2 deletions
|
|
@ -285,6 +285,12 @@ static void cnvw_fill_ssdt(const struct device *dev)
|
|||
}
|
||||
acpigen_pop_len();
|
||||
|
||||
acpigen_write_if_cond_ref_of("\\_SB.PCI0.CNVB");
|
||||
{
|
||||
acpigen_emit_namestring("\\_SB.PCI0.CNVB.CFLR");
|
||||
}
|
||||
acpigen_pop_len();
|
||||
|
||||
acpigen_emit_namestring("\\_SB.PCI0.PCRO");
|
||||
acpigen_write_integer(PID_CNVI);
|
||||
acpigen_write_integer(CNVI_ABORT_PLDR);
|
||||
|
|
@ -501,6 +507,311 @@ static const char *cnvi_bt_acpi_name(const struct device *dev)
|
|||
return "CNVB";
|
||||
}
|
||||
|
||||
static void cnvb_fill_ssdt(const struct device *dev)
|
||||
{
|
||||
const char *scope = acpi_device_path(dev);
|
||||
|
||||
/*
|
||||
* Mutex (CNMT, 0)
|
||||
*/
|
||||
acpigen_write_scope("\\_SB.PCI0");
|
||||
acpigen_write_mutex("CNMT", 0);
|
||||
acpigen_write_scope_end();
|
||||
|
||||
acpi_device_write_pci_dev(dev);
|
||||
|
||||
acpigen_write_scope(scope);
|
||||
|
||||
/*
|
||||
* OperationRegion (CBTR, SystemMemory, \_SB_.PCI0.BASE(_ADR), 0x100)
|
||||
* Field (CBTR, WordAcc, NoLock, Preserve) {
|
||||
* VDID, 32, // 0x00, VID DID
|
||||
* Offset(R_CNVI_CFG_GIO_DEV_CAP),
|
||||
* , 28,
|
||||
* BFLR, 1, // Function Level Reset Capable
|
||||
* Offset(R_CNVI_CFG_GIO_DEV),
|
||||
* , 15,
|
||||
* BIFR, 1, // Init Function Level Reset
|
||||
* Offset (R_CNVI_CFG_GIO_DEV_CAP_2),
|
||||
* , 11,
|
||||
* BLTS, 1, // LTR Mechanism Supported
|
||||
* Offset (R_CNVI_CFG_GIO_DEV_2),
|
||||
* , 10,
|
||||
* BLTE, 1, // LTR Mechanism Enable
|
||||
* }
|
||||
*/
|
||||
|
||||
/* RegionOffset stored in Local0 */
|
||||
/* Local0 = \_SB_.PCI0.BASE(_ADR) */
|
||||
acpigen_write_store();
|
||||
acpigen_emit_namestring("BASE");
|
||||
acpigen_emit_namestring("_ADR");
|
||||
acpigen_emit_byte(LOCAL0_OP);
|
||||
|
||||
acpigen_emit_ext_op(OPREGION_OP);
|
||||
acpigen_emit_namestring("CBTR");
|
||||
acpigen_emit_byte(SYSTEMMEMORY);
|
||||
acpigen_emit_byte(LOCAL0_OP);
|
||||
acpigen_write_integer(0x100);
|
||||
|
||||
struct fieldlist fields[] = {
|
||||
FIELDLIST_OFFSET(0),
|
||||
FIELDLIST_NAMESTR("VDID", 32),
|
||||
FIELDLIST_OFFSET(CNVI_DEV_CAP),
|
||||
FIELDLIST_RESERVED(28),
|
||||
FIELDLIST_NAMESTR("BFLR", 1),
|
||||
FIELDLIST_OFFSET(CNVI_DEV_CONTROL),
|
||||
FIELDLIST_RESERVED(15),
|
||||
FIELDLIST_NAMESTR("BIFR", 1),
|
||||
FIELDLIST_OFFSET(CNVI_DEV_CAP_2),
|
||||
FIELDLIST_RESERVED(11),
|
||||
FIELDLIST_NAMESTR("BLTS", 1),
|
||||
FIELDLIST_OFFSET(CNVI_DEV_CONTROL_2),
|
||||
FIELDLIST_RESERVED(10),
|
||||
FIELDLIST_NAMESTR("BLTE", 1),
|
||||
};
|
||||
acpigen_write_field("CBTR", fields, ARRAY_SIZE(fields),
|
||||
FIELD_WORDACC | FIELD_NOLOCK | FIELD_PRESERVE);
|
||||
|
||||
/*
|
||||
* Name (_S0W, 3)
|
||||
*/
|
||||
acpigen_write_name_integer("_S0W", ACPI_DEVICE_SLEEP_D3_HOT);
|
||||
|
||||
/*
|
||||
* Name (PRRS, Zero)
|
||||
* Last _PRR Status
|
||||
* 0: Non-Platform-Level Device Reset (PLDR) executed [Default]
|
||||
* 1: Core PLDR Completed successfully
|
||||
* 2: Product PLDR Completed successfully
|
||||
* 3: Previous PLDR Not Completed
|
||||
* 4: Product PLDR timeout
|
||||
*/
|
||||
acpigen_write_name_integer("PRRS", 0);
|
||||
|
||||
/*
|
||||
* Name (RSTT, Zero)
|
||||
* Reset Type
|
||||
* 0: Core Reset
|
||||
* 1: Product Reset
|
||||
*/
|
||||
acpigen_write_name_integer("RSTT", 0);
|
||||
|
||||
/*
|
||||
* Bluetooth PLDR request delay (default 50 ms)
|
||||
*/
|
||||
acpigen_write_name_integer("BTDL", 50);
|
||||
|
||||
/*
|
||||
* PowerResource (CNVP, 0x05, 0x0000)
|
||||
* {
|
||||
* Method (_STA, 0, NotSerialized) // _STA: Status
|
||||
* {
|
||||
* Return (One)
|
||||
* }
|
||||
*
|
||||
* Method (_ON, 0, NotSerialized) // _ON_: Power On
|
||||
* {
|
||||
* }
|
||||
*
|
||||
* Method (_OFF, 0, NotSerialized) // _OFF: Power Off
|
||||
* {
|
||||
* }
|
||||
*
|
||||
* Method (_RST, 0, NotSerialized) // _RST: Device Reset
|
||||
* {
|
||||
* Local0 = Acquire (\_SB.PCI0.CNMT, 0x03E8)
|
||||
* If ((Local0 == Zero))
|
||||
* {
|
||||
* CFLR ()
|
||||
* If ((RSTT == One))
|
||||
* {
|
||||
* Local0 = \_SB.PCI0.PCRR(PID_CNVI, CNVI_ABORT_PLDR)
|
||||
* Local0 &= CNVI_ABORT_REQUEST
|
||||
* If ((Local0 == Zero))
|
||||
* {
|
||||
* \_SB.PCI0.PCRO (PID_CNVI, CNVI_ABORT_PLDR, 0x03)
|
||||
* Sleep (BTDL)
|
||||
* Local0 = \_SB.PCI0.PCRR(PID_CNVI, CNVI_ABORT_PLDR)
|
||||
* Local1 = (Local0 & CNVI_ABORT_REQUEST)
|
||||
* Local3 = (Local0 & CNVI_READY)
|
||||
* If ((Local1 == Zero))
|
||||
* {
|
||||
* If ((Local3 == CNVI_READY))
|
||||
* {
|
||||
* PRRS = CNVI_PLDR_COMPLETE
|
||||
* }
|
||||
* }
|
||||
* Else
|
||||
* {
|
||||
* PRRS = CNVI_PLDR_TIMEOUT
|
||||
* }
|
||||
* }
|
||||
* Else
|
||||
* {
|
||||
* PRRS = CNVI_PLDR_NOT_COMPLETE
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* If ((BLTS == One))
|
||||
* {
|
||||
* If ((BLTE == Zero))
|
||||
* {
|
||||
* BLTE = One
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* Release (\_SB.PCI0.CNMT)
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
*/
|
||||
acpigen_write_power_res("CNVP", 5, 0, NULL, 0);
|
||||
{
|
||||
acpigen_write_method("_STA", 0);
|
||||
{
|
||||
acpigen_write_return_integer(1);
|
||||
}
|
||||
acpigen_pop_len();
|
||||
|
||||
acpigen_write_method("_ON", 0);
|
||||
{
|
||||
// Empty method body
|
||||
}
|
||||
acpigen_pop_len();
|
||||
|
||||
acpigen_write_method("_OFF", 0);
|
||||
{
|
||||
// Empty method body
|
||||
}
|
||||
acpigen_pop_len();
|
||||
|
||||
acpigen_write_method("_RST", 0);
|
||||
{
|
||||
acpigen_write_store();
|
||||
acpigen_write_acquire("\\_SB.PCI0.CNMT", 1000);
|
||||
acpigen_emit_byte(LOCAL0_OP);
|
||||
|
||||
acpigen_write_if_lequal_op_int(LOCAL0_OP, 0);
|
||||
{
|
||||
acpigen_emit_namestring("CFLR");
|
||||
|
||||
acpigen_write_if_lequal_namestr_int("RSTT", 1);
|
||||
{
|
||||
acpigen_write_store();
|
||||
acpigen_emit_namestring("\\_SB.PCI0.PCRR");
|
||||
acpigen_write_integer(PID_CNVI);
|
||||
acpigen_write_integer(CNVI_ABORT_PLDR);
|
||||
acpigen_emit_byte(LOCAL0_OP);
|
||||
|
||||
acpigen_emit_byte(AND_OP);
|
||||
acpigen_emit_byte(LOCAL0_OP);
|
||||
acpigen_write_integer(CNVI_ABORT_REQUEST);
|
||||
acpigen_emit_byte(LOCAL0_OP);
|
||||
|
||||
acpigen_write_if_lequal_op_int(LOCAL0_OP, 0);
|
||||
{
|
||||
acpigen_emit_namestring("\\_SB.PCI0.PCRO");
|
||||
acpigen_write_integer(PID_CNVI);
|
||||
acpigen_write_integer(CNVI_ABORT_PLDR);
|
||||
acpigen_write_integer(CNVI_ABORT_REQUEST | CNVI_ABORT_ENABLE);
|
||||
|
||||
acpigen_emit_ext_op(SLEEP_OP);
|
||||
acpigen_emit_namestring("BTDL");
|
||||
|
||||
acpigen_write_store();
|
||||
acpigen_emit_namestring("\\_SB.PCI0.PCRR");
|
||||
acpigen_write_integer(PID_CNVI);
|
||||
acpigen_write_integer(CNVI_ABORT_PLDR);
|
||||
acpigen_emit_byte(LOCAL0_OP);
|
||||
|
||||
acpigen_emit_byte(AND_OP);
|
||||
acpigen_emit_byte(LOCAL0_OP);
|
||||
acpigen_write_integer(CNVI_ABORT_REQUEST);
|
||||
acpigen_emit_byte(LOCAL1_OP);
|
||||
|
||||
acpigen_emit_byte(AND_OP);
|
||||
acpigen_emit_byte(LOCAL0_OP);
|
||||
acpigen_write_integer(CNVI_READY);
|
||||
acpigen_emit_byte(LOCAL3_OP);
|
||||
|
||||
acpigen_write_if_lequal_op_int(LOCAL1_OP, 0);
|
||||
{
|
||||
acpigen_write_if_lequal_op_int(LOCAL3_OP, CNVI_READY);
|
||||
{
|
||||
acpigen_write_store_int_to_namestr(CNVI_PLDR_COMPLETE, "PRRS");
|
||||
}
|
||||
acpigen_pop_len();
|
||||
}
|
||||
acpigen_write_else();
|
||||
{
|
||||
acpigen_write_store_int_to_namestr(CNVI_PLDR_TIMEOUT, "PRRS");
|
||||
}
|
||||
acpigen_pop_len();
|
||||
}
|
||||
acpigen_write_else();
|
||||
{
|
||||
acpigen_write_store_int_to_namestr(CNVI_PLDR_NOT_COMPLETE, "PRRS");
|
||||
}
|
||||
acpigen_pop_len();
|
||||
}
|
||||
acpigen_pop_len();
|
||||
|
||||
acpigen_write_if_lequal_namestr_int("BLTS", 1);
|
||||
{
|
||||
acpigen_write_if_lequal_namestr_int("BLTE", 0);
|
||||
{
|
||||
acpigen_write_store_int_to_namestr(1, "BLTE");
|
||||
}
|
||||
acpigen_pop_len();
|
||||
}
|
||||
acpigen_pop_len();
|
||||
|
||||
acpigen_write_release("\\_SB.PCI0.CNMT");
|
||||
}
|
||||
acpigen_pop_len();
|
||||
}
|
||||
acpigen_pop_len();
|
||||
}
|
||||
acpigen_write_power_res_end();
|
||||
|
||||
/*
|
||||
* Name (_PRR, Package (0x01) // _PRR: Power Resource for Reset
|
||||
* {
|
||||
* CNVP
|
||||
* })
|
||||
*/
|
||||
acpigen_write_name("_PRR");
|
||||
{
|
||||
acpigen_write_package(1);
|
||||
acpigen_emit_namestring("CNVP");
|
||||
}
|
||||
acpigen_pop_len();
|
||||
|
||||
/*
|
||||
* Method (CFLR, 0, NotSerialized)
|
||||
* {
|
||||
* If ((BFLR == One))
|
||||
* {
|
||||
* BIFR = One
|
||||
* PRRS = One
|
||||
* }
|
||||
* }
|
||||
*/
|
||||
acpigen_write_method("CFLR", 0);
|
||||
{
|
||||
acpigen_write_if_lequal_namestr_int("BFLR", 1);
|
||||
{
|
||||
acpigen_write_store_int_to_namestr(1, "BIFR");
|
||||
acpigen_write_store_int_to_namestr(1, "PRRS");
|
||||
}
|
||||
acpigen_pop_len();
|
||||
}
|
||||
acpigen_pop_len();
|
||||
|
||||
acpigen_write_scope_end();
|
||||
}
|
||||
|
||||
static struct device_operations cnvi_bt_ops = {
|
||||
.read_resources = pci_dev_read_resources,
|
||||
.set_resources = pci_dev_set_resources,
|
||||
|
|
@ -508,7 +819,7 @@ static struct device_operations cnvi_bt_ops = {
|
|||
.ops_pci = &pci_dev_ops_pci,
|
||||
.scan_bus = scan_static_bus,
|
||||
.acpi_name = cnvi_bt_acpi_name,
|
||||
.acpi_fill_ssdt = acpi_device_write_pci_dev,
|
||||
.acpi_fill_ssdt = cnvb_fill_ssdt,
|
||||
};
|
||||
|
||||
static const unsigned short bt_pci_device_ids[] = {
|
||||
|
|
|
|||
|
|
@ -3,10 +3,12 @@
|
|||
#ifndef _SOC_INTEL_COMMON_CNVI_H_
|
||||
#define _SOC_INTEL_COMMON_CNVI_H_
|
||||
|
||||
/* CNVi WiFi Register */
|
||||
/* CNVi PCI configuration Registers */
|
||||
#define CNVI_DEV_CAP 0x44
|
||||
#define CNVI_DEV_CONTROL 0x48
|
||||
#define CNVI_POWER_STATUS 0xcc
|
||||
#define CNVI_DEV_CAP_2 0x64
|
||||
#define CNVI_DEV_CONTROL_2 0x68
|
||||
|
||||
/* CNVi PLDR Results */
|
||||
#define CNVI_PLDR_COMPLETE 0x02
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue