Skip to content

Commit 782ae11

Browse files
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>
1 parent 23f5df6 commit 782ae11

File tree

2 files changed

+315
-2
lines changed
  • src/soc/intel/common/block

2 files changed

+315
-2
lines changed

src/soc/intel/common/block/cnvi/cnvi.c

Lines changed: 312 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -285,6 +285,12 @@ static void cnvw_fill_ssdt(const struct device *dev)
285285
}
286286
acpigen_pop_len();
287287

288+
acpigen_write_if_cond_ref_of("\\_SB.PCI0.CNVB");
289+
{
290+
acpigen_emit_namestring("\\_SB.PCI0.CNVB.CFLR");
291+
}
292+
acpigen_pop_len();
293+
288294
acpigen_emit_namestring("\\_SB.PCI0.PCRO");
289295
acpigen_write_integer(PID_CNVI);
290296
acpigen_write_integer(CNVI_ABORT_PLDR);
@@ -501,14 +507,319 @@ static const char *cnvi_bt_acpi_name(const struct device *dev)
501507
return "CNVB";
502508
}
503509

510+
static void cnvb_fill_ssdt(const struct device *dev)
511+
{
512+
const char *scope = acpi_device_path(dev);
513+
514+
/*
515+
* Mutex (CNMT, 0)
516+
*/
517+
acpigen_write_scope("\\_SB.PCI0");
518+
acpigen_write_mutex("CNMT", 0);
519+
acpigen_write_scope_end();
520+
521+
acpi_device_write_pci_dev(dev);
522+
523+
acpigen_write_scope(scope);
524+
525+
/*
526+
* OperationRegion (CBTR, SystemMemory, \_SB_.PCI0.BASE(_ADR), 0x100)
527+
* Field (CBTR, WordAcc, NoLock, Preserve) {
528+
* VDID, 32, // 0x00, VID DID
529+
* Offset(R_CNVI_CFG_GIO_DEV_CAP),
530+
* , 28,
531+
* BFLR, 1, // Function Level Reset Capable
532+
* Offset(R_CNVI_CFG_GIO_DEV),
533+
* , 15,
534+
* BIFR, 1, // Init Function Level Reset
535+
* Offset (R_CNVI_CFG_GIO_DEV_CAP_2),
536+
* , 11,
537+
* BLTS, 1, // LTR Mechanism Supported
538+
* Offset (R_CNVI_CFG_GIO_DEV_2),
539+
* , 10,
540+
* BLTE, 1, // LTR Mechanism Enable
541+
* }
542+
*/
543+
544+
/* RegionOffset stored in Local0 */
545+
/* Local0 = \_SB_.PCI0.BASE(_ADR) */
546+
acpigen_write_store();
547+
acpigen_emit_namestring("BASE");
548+
acpigen_emit_namestring("_ADR");
549+
acpigen_emit_byte(LOCAL0_OP);
550+
551+
acpigen_emit_ext_op(OPREGION_OP);
552+
acpigen_emit_namestring("CBTR");
553+
acpigen_emit_byte(SYSTEMMEMORY);
554+
acpigen_emit_byte(LOCAL0_OP);
555+
acpigen_write_integer(0x100);
556+
557+
struct fieldlist fields[] = {
558+
FIELDLIST_OFFSET(0),
559+
FIELDLIST_NAMESTR("VDID", 32),
560+
FIELDLIST_OFFSET(CNVI_DEV_CAP),
561+
FIELDLIST_RESERVED(28),
562+
FIELDLIST_NAMESTR("BFLR", 1),
563+
FIELDLIST_OFFSET(CNVI_DEV_CONTROL),
564+
FIELDLIST_RESERVED(15),
565+
FIELDLIST_NAMESTR("BIFR", 1),
566+
FIELDLIST_OFFSET(CNVI_DEV_CAP_2),
567+
FIELDLIST_RESERVED(11),
568+
FIELDLIST_NAMESTR("BLTS", 1),
569+
FIELDLIST_OFFSET(CNVI_DEV_CONTROL_2),
570+
FIELDLIST_RESERVED(10),
571+
FIELDLIST_NAMESTR("BLTE", 1),
572+
};
573+
acpigen_write_field("CBTR", fields, ARRAY_SIZE(fields),
574+
FIELD_WORDACC | FIELD_NOLOCK | FIELD_PRESERVE);
575+
576+
/*
577+
* Name (_S0W, 3)
578+
*/
579+
acpigen_write_name_integer("_S0W", ACPI_DEVICE_SLEEP_D3_HOT);
580+
581+
/*
582+
* Name (PRRS, Zero)
583+
* Last _PRR Status
584+
* 0: Non-Platform-Level Device Reset (PLDR) executed [Default]
585+
* 1: Core PLDR Completed successfully
586+
* 2: Product PLDR Completed successfully
587+
* 3: Previous PLDR Not Completed
588+
* 4: Product PLDR timeout
589+
*/
590+
acpigen_write_name_integer("PRRS", 0);
591+
592+
/*
593+
* Name (RSTT, Zero)
594+
* Reset Type
595+
* 0: Core Reset
596+
* 1: Product Reset
597+
*/
598+
acpigen_write_name_integer("RSTT", 0);
599+
600+
/*
601+
* Bluetooth PLDR request delay (default 50 ms)
602+
*/
603+
acpigen_write_name_integer("BTDL", 50);
604+
605+
/*
606+
* PowerResource (CNVP, 0x05, 0x0000)
607+
* {
608+
* Method (_STA, 0, NotSerialized) // _STA: Status
609+
* {
610+
* Return (One)
611+
* }
612+
*
613+
* Method (_ON, 0, NotSerialized) // _ON_: Power On
614+
* {
615+
* }
616+
*
617+
* Method (_OFF, 0, NotSerialized) // _OFF: Power Off
618+
* {
619+
* }
620+
*
621+
* Method (_RST, 0, NotSerialized) // _RST: Device Reset
622+
* {
623+
* Local0 = Acquire (\_SB.PCI0.CNMT, 0x03E8)
624+
* If ((Local0 == Zero))
625+
* {
626+
* CFLR ()
627+
* If ((RSTT == One))
628+
* {
629+
* Local0 = \_SB.PCI0.PCRR(PID_CNVI, CNVI_ABORT_PLDR)
630+
* Local0 &= CNVI_ABORT_REQUEST
631+
* If ((Local0 == Zero))
632+
* {
633+
* \_SB.PCI0.PCRO (PID_CNVI, CNVI_ABORT_PLDR, 0x03)
634+
* Sleep (BTDL)
635+
* Local0 = \_SB.PCI0.PCRR(PID_CNVI, CNVI_ABORT_PLDR)
636+
* Local1 = (Local0 & CNVI_ABORT_REQUEST)
637+
* Local3 = (Local0 & CNVI_READY)
638+
* If ((Local1 == Zero))
639+
* {
640+
* If ((Local3 == CNVI_READY))
641+
* {
642+
* PRRS = CNVI_PLDR_COMPLETE
643+
* }
644+
* }
645+
* Else
646+
* {
647+
* PRRS = CNVI_PLDR_TIMEOUT
648+
* }
649+
* }
650+
* Else
651+
* {
652+
* PRRS = CNVI_PLDR_NOT_COMPLETE
653+
* }
654+
* }
655+
*
656+
* If ((BLTS == One))
657+
* {
658+
* If ((BLTE == Zero))
659+
* {
660+
* BLTE = One
661+
* }
662+
* }
663+
*
664+
* Release (\_SB.PCI0.CNMT)
665+
* }
666+
* }
667+
* }
668+
*/
669+
acpigen_write_power_res("CNVP", 5, 0, NULL, 0);
670+
{
671+
acpigen_write_method("_STA", 0);
672+
{
673+
acpigen_write_return_integer(1);
674+
}
675+
acpigen_pop_len();
676+
677+
acpigen_write_method("_ON", 0);
678+
{
679+
// Empty method body
680+
}
681+
acpigen_pop_len();
682+
683+
acpigen_write_method("_OFF", 0);
684+
{
685+
// Empty method body
686+
}
687+
acpigen_pop_len();
688+
689+
acpigen_write_method("_RST", 0);
690+
{
691+
acpigen_write_store();
692+
acpigen_write_acquire("\\_SB.PCI0.CNMT", 1000);
693+
acpigen_emit_byte(LOCAL0_OP);
694+
695+
acpigen_write_if_lequal_op_int(LOCAL0_OP, 0);
696+
{
697+
acpigen_emit_namestring("CFLR");
698+
699+
acpigen_write_if_lequal_namestr_int("RSTT", 1);
700+
{
701+
acpigen_write_store();
702+
acpigen_emit_namestring("\\_SB.PCI0.PCRR");
703+
acpigen_write_integer(PID_CNVI);
704+
acpigen_write_integer(CNVI_ABORT_PLDR);
705+
acpigen_emit_byte(LOCAL0_OP);
706+
707+
acpigen_emit_byte(AND_OP);
708+
acpigen_emit_byte(LOCAL0_OP);
709+
acpigen_write_integer(CNVI_ABORT_REQUEST);
710+
acpigen_emit_byte(LOCAL0_OP);
711+
712+
acpigen_write_if_lequal_op_int(LOCAL0_OP, 0);
713+
{
714+
acpigen_emit_namestring("\\_SB.PCI0.PCRO");
715+
acpigen_write_integer(PID_CNVI);
716+
acpigen_write_integer(CNVI_ABORT_PLDR);
717+
acpigen_write_integer(CNVI_ABORT_REQUEST | CNVI_ABORT_ENABLE);
718+
719+
acpigen_emit_ext_op(SLEEP_OP);
720+
acpigen_emit_namestring("BTDL");
721+
722+
acpigen_write_store();
723+
acpigen_emit_namestring("\\_SB.PCI0.PCRR");
724+
acpigen_write_integer(PID_CNVI);
725+
acpigen_write_integer(CNVI_ABORT_PLDR);
726+
acpigen_emit_byte(LOCAL0_OP);
727+
728+
acpigen_emit_byte(AND_OP);
729+
acpigen_emit_byte(LOCAL0_OP);
730+
acpigen_write_integer(CNVI_ABORT_REQUEST);
731+
acpigen_emit_byte(LOCAL1_OP);
732+
733+
acpigen_emit_byte(AND_OP);
734+
acpigen_emit_byte(LOCAL0_OP);
735+
acpigen_write_integer(CNVI_READY);
736+
acpigen_emit_byte(LOCAL3_OP);
737+
738+
acpigen_write_if_lequal_op_int(LOCAL1_OP, 0);
739+
{
740+
acpigen_write_if_lequal_op_int(LOCAL3_OP, CNVI_READY);
741+
{
742+
acpigen_write_store_int_to_namestr(CNVI_PLDR_COMPLETE, "PRRS");
743+
}
744+
acpigen_pop_len();
745+
}
746+
acpigen_write_else();
747+
{
748+
acpigen_write_store_int_to_namestr(CNVI_PLDR_TIMEOUT, "PRRS");
749+
}
750+
acpigen_pop_len();
751+
}
752+
acpigen_write_else();
753+
{
754+
acpigen_write_store_int_to_namestr(CNVI_PLDR_NOT_COMPLETE, "PRRS");
755+
}
756+
acpigen_pop_len();
757+
}
758+
acpigen_pop_len();
759+
760+
acpigen_write_if_lequal_namestr_int("BLTS", 1);
761+
{
762+
acpigen_write_if_lequal_namestr_int("BLTE", 0);
763+
{
764+
acpigen_write_store_int_to_namestr(1, "BLTE");
765+
}
766+
acpigen_pop_len();
767+
}
768+
acpigen_pop_len();
769+
770+
acpigen_write_release("\\_SB.PCI0.CNMT");
771+
}
772+
acpigen_pop_len();
773+
}
774+
acpigen_pop_len();
775+
}
776+
acpigen_write_power_res_end();
777+
778+
/*
779+
* Name (_PRR, Package (0x01) // _PRR: Power Resource for Reset
780+
* {
781+
* CNVP
782+
* })
783+
*/
784+
acpigen_write_name("_PRR");
785+
{
786+
acpigen_write_package(1);
787+
acpigen_emit_namestring("CNVP");
788+
}
789+
acpigen_pop_len();
790+
791+
/*
792+
* Method (CFLR, 0, NotSerialized)
793+
* {
794+
* If ((BFLR == One))
795+
* {
796+
* BIFR = One
797+
* PRRS = One
798+
* }
799+
* }
800+
*/
801+
acpigen_write_method("CFLR", 0);
802+
{
803+
acpigen_write_if_lequal_namestr_int("BFLR", 1);
804+
{
805+
acpigen_write_store_int_to_namestr(1, "BIFR");
806+
acpigen_write_store_int_to_namestr(1, "PRRS");
807+
}
808+
acpigen_pop_len();
809+
}
810+
acpigen_pop_len();
811+
812+
acpigen_write_scope_end();
813+
}
814+
504815
static struct device_operations cnvi_bt_ops = {
505816
.read_resources = pci_dev_read_resources,
506817
.set_resources = pci_dev_set_resources,
507818
.enable_resources = pci_dev_enable_resources,
508819
.ops_pci = &pci_dev_ops_pci,
509820
.scan_bus = scan_static_bus,
510821
.acpi_name = cnvi_bt_acpi_name,
511-
.acpi_fill_ssdt = acpi_device_write_pci_dev,
822+
.acpi_fill_ssdt = cnvb_fill_ssdt,
512823
};
513824

514825
static const unsigned short bt_pci_device_ids[] = {

src/soc/intel/common/block/include/intelblocks/cnvi.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,12 @@
33
#ifndef _SOC_INTEL_COMMON_CNVI_H_
44
#define _SOC_INTEL_COMMON_CNVI_H_
55

6-
/* CNVi WiFi Register */
6+
/* CNVi PCI configuration Registers */
77
#define CNVI_DEV_CAP 0x44
88
#define CNVI_DEV_CONTROL 0x48
99
#define CNVI_POWER_STATUS 0xcc
10+
#define CNVI_DEV_CAP_2 0x64
11+
#define CNVI_DEV_CONTROL_2 0x68
1012

1113
/* CNVi PLDR Results */
1214
#define CNVI_PLDR_COMPLETE 0x02

0 commit comments

Comments
 (0)