diff --git a/src/soc/intel/common/block/cnvi/cnvi.c b/src/soc/intel/common/block/cnvi/cnvi.c index d939738e48..153643d0f9 100644 --- a/src/soc/intel/common/block/cnvi/cnvi.c +++ b/src/soc/intel/common/block/cnvi/cnvi.c @@ -255,6 +255,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(CNVI_SIDEBAND_ID); acpigen_write_integer(CNVI_ABORT_PLDR); @@ -505,6 +511,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, @@ -512,7 +823,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[] = { diff --git a/src/soc/intel/common/block/include/intelblocks/cnvi.h b/src/soc/intel/common/block/include/intelblocks/cnvi.h index fa96fdd37d..a903941b2e 100644 --- a/src/soc/intel/common/block/include/intelblocks/cnvi.h +++ b/src/soc/intel/common/block/include/intelblocks/cnvi.h @@ -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