11#include <efi.h>
2- #include "csmwrap.h"
2+ #include <csmwrap.h>
3+ #include <io.h>
4+ #include <printf.h>
5+ #include <pci.h>
36
4- #include "io.h"
57
6- #define PCI_DEVICE_NUMBER_PCH_P2SB 31
7- #define PCI_FUNCTION_NUMBER_PCH_P2SB 1
8+ // See Silicon/ArrowlakePkg/Include/Register/PchBdfAssignment.h
9+ //
10+ // Primary to Sideband (P2SB) Bridge SOC (D31:F1)
11+ //
12+ #define PCI_DEVICE_NUMBER_PCH_P2SB 31
13+ #define PCI_FUNCTION_NUMBER_PCH_P2SB 1
814
915#define SBREG_BAR 0x10
1016#define SBREG_BARH 0x14
5561 */
5662#define B_P2SB_CFG_P2SBC_HIDE (1 << 8) ///< P2SB Hide Bit
5763
58- static int pit_8254cge_workaround (void )
64+
65+ EFI_STATUS find_p2sb_pci (struct csmwrap_priv * priv , UINT64 * pci_address )
66+ {
67+ PCI_TYPE00 pdev ;
68+
69+ for (int pciroot = 0 ; pciroot < priv -> rootbus_count ; pciroot ++ ) {
70+ UINT8 bus = priv -> rootbus_list [pciroot ];
71+ UINT64 d31f0 = EFI_PCI_ADDRESS (bus , 31 , 0 );
72+
73+ if (PciConfigRead (EfiPciIoWidthUint32 , d31f0 , sizeof (pdev .Hdr ) / 4 , & pdev .Hdr ) != EFI_SUCCESS ) {
74+ continue ; // Skip if configuration cannot be read
75+ }
76+
77+ if (pdev .Hdr .VendorId != 0x8086 || !IS_PCI_MULTI_FUNC (& pdev )) {
78+ continue ; // Not an Intel multifunc device
79+ }
80+
81+ if (!IS_CLASS2 (& pdev , PCI_CLASS_BRIDGE , PCI_CLASS_BRIDGE_ISA )) {
82+ continue ; // D31F0 is not a ISA bridge
83+ }
84+
85+ * pci_address = EFI_PCI_ADDRESS (bus , PCI_DEVICE_NUMBER_PCH_P2SB , PCI_FUNCTION_NUMBER_PCH_P2SB );
86+
87+ return EFI_SUCCESS ; // Found P2SB
88+ }
89+
90+ return EFI_NOT_FOUND ; // No P2SB found
91+ }
92+
93+ static int pit_8254cge_workaround (struct csmwrap_priv * priv )
5994{
95+ EFI_STATUS Status ;
6096 uint32_t reg ;
6197 unsigned long base ;
6298 bool p2sb_hide = false;
63- int pch_pci_bus = 0 ;
99+ UINT64 p2sb_addr ;
100+
101+ Status = find_p2sb_pci (priv , & p2sb_addr );
102+ if (EFI_ERROR (Status )) {
103+ DEBUG ((DEBUG_INFO , "P2SB Not found %d, skipping 8254CGE workaround\n" , Status ));
104+ return -1 ; // P2SB not found, skip workaround
105+ }
64106
65- reg = pciConfigReadDWord ( pch_pci_bus , PCI_DEVICE_NUMBER_PCH_P2SB ,
66- PCI_FUNCTION_NUMBER_PCH_P2SB ,
67- 0x0 );
107+ DEBUG (( DEBUG_INFO , "P2SB Address: %lx\n" , p2sb_addr ));
108+
109+ Status = PciConfigRead ( EfiPciIoWidthUint32 , p2sb_addr , 1 , & reg );
68110
69111 /* P2SB maybe hidden, try unhide it first */
70112 if ((reg & 0xFFFF ) == 0xffff ) {
71- reg = pciConfigReadDWord (pch_pci_bus , PCI_DEVICE_NUMBER_PCH_P2SB ,
72- PCI_FUNCTION_NUMBER_PCH_P2SB ,
73- R_P2SB_CFG_P2SBC );
113+ Status = PciConfigRead (EfiPciIoWidthUint32 , p2sb_addr + R_P2SB_CFG_P2SBC , 1 , & reg );
74114 reg &= ~B_P2SB_CFG_P2SBC_HIDE ;
75- pciConfigWriteDWord (pch_pci_bus , PCI_DEVICE_NUMBER_PCH_P2SB ,
76- PCI_FUNCTION_NUMBER_PCH_P2SB ,
77- R_P2SB_CFG_P2SBC , reg );
115+ Status = PciConfigWrite (EfiPciIoWidthUint32 , p2sb_addr + R_P2SB_CFG_P2SBC , 1 , & reg );
78116 p2sb_hide = true;
79117 }
80118
81- reg = pciConfigReadDWord (pch_pci_bus , PCI_DEVICE_NUMBER_PCH_P2SB ,
82- PCI_FUNCTION_NUMBER_PCH_P2SB ,
83- 0x0 );
119+ /* Read header again */
120+ Status = PciConfigRead (EfiPciIoWidthUint32 , p2sb_addr , 1 , & reg );
84121
85122 if ((reg & 0xFFFF ) != 0x8086 ) {
86- printf ( "No P2SB found, proceed to PIT test \n" );
123+ DEBUG (( DEBUG_ERROR , "Unable to unhide P2SB \n") );
87124 goto test_pit ;
88125 }
89126
90- reg = pciConfigReadDWord (pch_pci_bus , PCI_DEVICE_NUMBER_PCH_P2SB ,
91- PCI_FUNCTION_NUMBER_PCH_P2SB ,
92- SBREG_BAR );
127+ Status = PciConfigRead (EfiPciIoWidthUint32 , p2sb_addr + SBREG_BAR , 1 , & reg );
93128 base = reg & ~0x0F ;
94129
95- reg = pciConfigReadDWord (pch_pci_bus , PCI_DEVICE_NUMBER_PCH_P2SB ,
96- PCI_FUNCTION_NUMBER_PCH_P2SB ,
97- SBREG_BARH );
130+ Status = PciConfigRead (EfiPciIoWidthUint32 , p2sb_addr + SBREG_BARH , 1 , & reg );
98131#ifdef __LP64__
99132 base |= ((uint64_t )reg & 0xFFFFFFFF ) << 32 ;
100133#else
@@ -103,7 +136,6 @@ static int pit_8254cge_workaround(void)
103136 goto test_pit ;
104137 }
105138#endif
106-
107139 /* FIXME: Validate base */
108140 reg = readl (PCH_PCR_ADDRESS (base , PID_ITSS , R_PCH_PCR_ITSS_ITSSPRC ));
109141 printf ("ITSSPRC = %x, ITSSPRC.8254CGE= %x\n" , reg , !!(reg & B_PCH_PCR_ITSS_ITSSPRC_8254CGE ));
@@ -113,13 +145,9 @@ static int pit_8254cge_workaround(void)
113145
114146 /* Hide P2SB again */
115147 if (p2sb_hide ) {
116- reg = pciConfigReadDWord (pch_pci_bus , PCI_DEVICE_NUMBER_PCH_P2SB ,
117- PCI_FUNCTION_NUMBER_PCH_P2SB ,
118- R_P2SB_CFG_P2SBC );
148+ Status = PciConfigRead (EfiPciIoWidthUint32 , p2sb_addr + R_P2SB_CFG_P2SBC , 1 , & reg );
119149 reg |= B_P2SB_CFG_P2SBC_HIDE ;
120- pciConfigWriteDWord (pch_pci_bus , PCI_DEVICE_NUMBER_PCH_P2SB ,
121- PCI_FUNCTION_NUMBER_PCH_P2SB ,
122- R_P2SB_CFG_P2SBC , reg );
150+ Status = PciConfigWrite (EfiPciIoWidthUint32 , p2sb_addr + R_P2SB_CFG_P2SBC , 1 , & reg );
123151 }
124152
125153test_pit :
@@ -138,17 +166,13 @@ static int pit_8254cge_workaround(void)
138166 return 0 ;
139167}
140168
141- int apply_intel_platform_workarounds (void )
169+ int apply_intel_platform_workarounds (struct csmwrap_priv * priv )
142170{
143- uint16_t vendor_id ;
144-
145- vendor_id = pciConfigReadWord (0 , 0 , 0 , 0x0 );
146-
147- if (vendor_id != 0x8086 ) {
148- return 0 ;
171+ if (priv -> hbridge_hdr .VendorId != 0x8086 ) {
172+ return 0 ; // Not an Intel platform
149173 }
150174
151- pit_8254cge_workaround ();
175+ pit_8254cge_workaround (priv );
152176
153177 return 0 ;
154178}
0 commit comments