3 This driver is responsible for the registration of child drivers
4 and the abstraction of the QNC SMI sources.
6 Copyright (c) 2013-2015 Intel Corporation.
8 SPDX-License-Identifier: BSD-2-Clause-Patent
13 // Include common header file for this module.
15 #include "CommonHeader.h"
17 #include "QNCSmmHelpers.h"
20 // Help handle porting bit shifts to IA-64.
22 #define BIT_ZERO 0x00000001
26 QNCSmmPublishDispatchProtocols(
34 // Install protocol interfaces.
36 for (Index
= 0; Index
< NUM_PROTOCOLS
; Index
++) {
37 Status
= gSmst
->SmmInstallProtocolInterface (
38 &mPrivateData
.InstallMultProtHandle
,
39 mPrivateData
.Protocols
[Index
].Guid
,
41 &mPrivateData
.Protocols
[Index
].Protocols
.Generic
44 ASSERT_EFI_ERROR (Status
);
56 Initialize bits that aren't necessarily related to an SMI source.
60 gSmst - SMM System Table; contains an entry for SMM CPU IO
64 EFI_SUCCESS. Asserts, otherwise.
75 Status
= QNCSmmEnableGlobalSmiBit ();
76 ASSERT_EFI_ERROR (Status
);
79 // Be *really* sure to clear all SMIs
87 QNCSmmEnableGlobalSmiBit (
94 Enables the QNC to generate SMIs. Note that no SMIs will be generated
95 if no SMI sources are enabled. Conversely, no enabled SMI source will
96 generate SMIs if SMIs are not globally enabled. This is the main
97 switchbox for SMI generation.
113 // Enable SMI globally
115 NewValue
= QNCPortRead (QUARK_NC_HOST_BRIDGE_SB_PORT_ID
, QNC_MSG_FSBIC_REG_HMISC
);
117 QNCPortWrite (QUARK_NC_HOST_BRIDGE_SB_PORT_ID
, QNC_MSG_FSBIC_REG_HMISC
, NewValue
);
130 Clears the SMI after all SMI source have been processed.
131 Note that this function will not work correctly (as it is
132 written) unless all SMI sources have been processed.
133 A revision of this function could manually clear all SMI
134 status bits to guarantee success.
152 // Determine whether an ACPI OS is present (via the SCI_EN bit)
154 Pm1Cnt
= IoRead32(PcdGet16 (PcdPm1blkIoBaseAddress
) + R_QNC_PM1BLK_PM1C
);
155 SciEn
= (BOOLEAN
)((Pm1Cnt
& B_QNC_PM1BLK_PM1C_SCIEN
) == B_QNC_PM1BLK_PM1C_SCIEN
);
157 if (SciEn
== FALSE
) {
160 // Clear any SMIs that double as SCIs (when SCI_EN==0)
162 Pm1Sts
= (B_QNC_PM1BLK_PM1S_WAKE
| B_QNC_PM1BLK_PM1S_PCIEWSTS
| B_QNC_PM1BLK_PM1S_RTC
| B_QNC_PM1BLK_PM1S_GLOB
| B_QNC_PM1BLK_PM1S_TO
);
164 Gpe0Sts
= B_QNC_GPE0BLK_GPE0S_ALL
;
166 IoOr16((PcdGet16 (PcdPm1blkIoBaseAddress
) + R_QNC_PM1BLK_PM1S
), Pm1Sts
);
167 IoOr32(((UINT16
)(LpcPciCfg32 (R_QNC_LPC_GPE0BLK
) & 0xFFFF) + R_QNC_GPE0BLK_GPE0S
), Gpe0Sts
);
171 // Clear all SMIs that are unaffected by SCI_EN
173 SmiSts
= IoRead32((UINT16
)(LpcPciCfg32 (R_QNC_LPC_GPE0BLK
) & 0xFFFF) + R_QNC_GPE0BLK_SMIS
);
174 SmiSts
|= B_QNC_GPE0BLK_SMIS_ALL
;
175 IoWrite32(((UINT16
)(LpcPciCfg32 (R_QNC_LPC_GPE0BLK
) & 0xFFFF) + R_QNC_GPE0BLK_SMIS
), SmiSts
);
178 // Try to clear the EOS bit. ASSERT on an error
180 EosSet
= QNCSmmSetAndCheckEos();
187 QNCSmmSetAndCheckEos(
192 // Reset the QNC to generate subsequent SMIs
194 IoOr32(((UINT16
)(LpcPciCfg32 (R_QNC_LPC_GPE0BLK
) & 0xFFFF) + R_QNC_GPE0BLK_SMIS
), B_QNC_GPE0BLK_SMIS_EOS
);
206 // Determine whether an ACPI OS is present (via the SCI_EN bit)
208 Pm1Cnt
= IoRead32(PcdGet16 (PcdPm1blkIoBaseAddress
) + R_QNC_PM1BLK_PM1C
);
210 SciEn
= (BOOLEAN
)((Pm1Cnt
& B_QNC_PM1BLK_PM1C_SCIEN
) == B_QNC_PM1BLK_PM1C_SCIEN
);
216 // These may or may not need to change w/ the QNC version; they're highly IA-32 dependent, though.
221 CONST QNC_SMM_BIT_DESC
*BitDesc
231 ASSERT (BitDesc
!= NULL
);
232 ASSERT (!IS_BIT_DESC_NULL( *BitDesc
) );
237 switch (BitDesc
->Reg
.Type
) {
241 // Double check that we correctly read in the acpi base address
243 ASSERT ((PcdGet16 (PcdPm1blkIoBaseAddress
) != 0x0) && ((PcdGet16 (PcdPm1blkIoBaseAddress
) & 0x1) != 0x1) );
245 switch (BitDesc
->SizeInBytes
) {
249 // Chances are that this field didn't get initialized.
250 // Check your assignments to bit descriptions.
256 Register
= (UINT64
) IoRead8 (PcdGet16 (PcdPm1blkIoBaseAddress
) + BitDesc
->Reg
.Data
.acpi
);
260 Register
= (UINT64
) IoRead16 (PcdGet16 (PcdPm1blkIoBaseAddress
) + BitDesc
->Reg
.Data
.acpi
);
264 Register
= (UINT64
) IoRead32 (PcdGet16 (PcdPm1blkIoBaseAddress
) + BitDesc
->Reg
.Data
.acpi
);
269 // Unsupported or invalid register size
275 if ((Register
& LShiftU64 (BIT_ZERO
, BitDesc
->Bit
)) != 0) {
284 // Double check that we correctly read in the gpe base address
286 ASSERT (((UINT16
)(LpcPciCfg32 (R_QNC_LPC_GPE0BLK
) & 0xFFFF) != 0x0) && (((UINT16
)(LpcPciCfg32 (R_QNC_LPC_GPE0BLK
) & 0xFFFF) & 0x1) != 0x1) );
288 switch (BitDesc
->SizeInBytes
) {
292 // Chances are that this field didn't get initialized.
293 // Check your assignments to bit descriptions.
299 Register
= (UINT64
) IoRead8 ((UINT16
)(LpcPciCfg32 (R_QNC_LPC_GPE0BLK
) & 0xFFFF) + BitDesc
->Reg
.Data
.gpe
);
303 Register
= (UINT64
) IoRead16 ((UINT16
)(LpcPciCfg32 (R_QNC_LPC_GPE0BLK
) & 0xFFFF) + BitDesc
->Reg
.Data
.gpe
);
307 Register
= (UINT64
) IoRead32 ((UINT16
)(LpcPciCfg32 (R_QNC_LPC_GPE0BLK
) & 0xFFFF) + BitDesc
->Reg
.Data
.gpe
);
312 // Unsupported or invalid register size
318 if ((Register
& LShiftU64 (BIT_ZERO
, BitDesc
->Bit
)) != 0) {
325 case MEMORY_MAPPED_IO_ADDRESS_TYPE
:
327 // Read the register, and it with the bit to read
331 // This code does not support reads greater then 64 bits
333 ASSERT (BitDesc
->SizeInBytes
<= 8);
334 CopyMem (&Register
, BitDesc
->Reg
.Data
.Mmio
, BitDesc
->SizeInBytes
);
335 Register
&= LShiftU64 (BIT0
, BitDesc
->Bit
);
344 PciBus
= BitDesc
->Reg
.Data
.pci
.Fields
.Bus
;
345 PciDev
= BitDesc
->Reg
.Data
.pci
.Fields
.Dev
;
346 PciFun
= BitDesc
->Reg
.Data
.pci
.Fields
.Fnc
;
347 PciReg
= BitDesc
->Reg
.Data
.pci
.Fields
.Reg
;
348 switch (BitDesc
->SizeInBytes
) {
352 // Chances are that this field didn't get initialized.
353 // Check your assignments to bit descriptions.
358 Register
= (UINT64
) PciRead8 (PCI_LIB_ADDRESS (PciBus
, PciDev
, PciFun
, PciReg
));
362 Register
= (UINT64
) PciRead16 (PCI_LIB_ADDRESS (PciBus
, PciDev
, PciFun
, PciReg
));
366 Register
= (UINT64
) PciRead32 (PCI_LIB_ADDRESS (PciBus
, PciDev
, PciFun
, PciReg
));
371 // Unsupported or invalid register size
377 if ((Register
& LShiftU64 (BIT_ZERO
, BitDesc
->Bit
)) != 0) {
386 // This address type is not yet implemented
397 CONST QNC_SMM_BIT_DESC
*BitDesc
,
398 CONST BOOLEAN ValueToWrite
409 ASSERT (BitDesc
!= NULL
);
410 ASSERT (!IS_BIT_DESC_NULL(*BitDesc
));
412 AndVal
= ~(BIT_ZERO
<< (BitDesc
->Bit
));
413 OrVal
= ((UINT32
)ValueToWrite
) << (BitDesc
->Bit
);
415 switch (BitDesc
->Reg
.Type
) {
419 // Double check that we correctly read in the acpi base address
421 ASSERT ((PcdGet16 (PcdPm1blkIoBaseAddress
) != 0x0) && ((PcdGet16 (PcdPm1blkIoBaseAddress
) & 0x1) != 0x1));
423 switch (BitDesc
->SizeInBytes
) {
427 // Chances are that this field didn't get initialized.
428 // Check your assignments to bit descriptions.
434 IoAndThenOr8 (PcdGet16 (PcdPm1blkIoBaseAddress
) + BitDesc
->Reg
.Data
.acpi
, (UINT8
)AndVal
, (UINT8
)OrVal
);
438 IoAndThenOr16 (PcdGet16 (PcdPm1blkIoBaseAddress
) + BitDesc
->Reg
.Data
.acpi
, (UINT16
)AndVal
, (UINT16
)OrVal
);
442 IoAndThenOr32 (PcdGet16 (PcdPm1blkIoBaseAddress
) + BitDesc
->Reg
.Data
.acpi
, (UINT32
)AndVal
, (UINT32
)OrVal
);
447 // Unsupported or invalid register size
456 // Double check that we correctly read in the gpe base address
458 ASSERT (((UINT16
)(LpcPciCfg32 (R_QNC_LPC_GPE0BLK
) & 0xFFFF) != 0x0) && (((UINT16
)(LpcPciCfg32 (R_QNC_LPC_GPE0BLK
) & 0xFFFF) & 0x1) != 0x1));
460 switch (BitDesc
->SizeInBytes
) {
464 // Chances are that this field didn't get initialized.
465 // Check your assignments to bit descriptions.
471 IoAndThenOr8 ((UINT16
)(LpcPciCfg32 (R_QNC_LPC_GPE0BLK
) & 0xFFFF) + BitDesc
->Reg
.Data
.gpe
, (UINT8
)AndVal
, (UINT8
)OrVal
);
475 IoAndThenOr16 ((UINT16
)(LpcPciCfg32 (R_QNC_LPC_GPE0BLK
) & 0xFFFF) + BitDesc
->Reg
.Data
.gpe
, (UINT16
)AndVal
, (UINT16
)OrVal
);
479 IoAndThenOr32 ((UINT16
)(LpcPciCfg32 (R_QNC_LPC_GPE0BLK
) & 0xFFFF) + BitDesc
->Reg
.Data
.gpe
, (UINT32
)AndVal
, (UINT32
)OrVal
);
484 // Unsupported or invalid register size
491 case MEMORY_MAPPED_IO_ADDRESS_TYPE
:
493 // Read the register, or it with the bit to set, then write it back.
497 // This code does not support writes greater then 64 bits
499 ASSERT (BitDesc
->SizeInBytes
<= 8);
500 CopyMem (&Register
, BitDesc
->Reg
.Data
.Mmio
, BitDesc
->SizeInBytes
);
503 CopyMem (BitDesc
->Reg
.Data
.Mmio
, &Register
, BitDesc
->SizeInBytes
);
507 PciBus
= BitDesc
->Reg
.Data
.pci
.Fields
.Bus
;
508 PciDev
= BitDesc
->Reg
.Data
.pci
.Fields
.Dev
;
509 PciFun
= BitDesc
->Reg
.Data
.pci
.Fields
.Fnc
;
510 PciReg
= BitDesc
->Reg
.Data
.pci
.Fields
.Reg
;
511 switch (BitDesc
->SizeInBytes
) {
515 // Chances are that this field didn't get initialized -- check your assignments
516 // to bit descriptions.
522 PciAndThenOr8 (PCI_LIB_ADDRESS (PciBus
, PciDev
, PciFun
, PciReg
), (UINT8
) AndVal
, (UINT8
) OrVal
);
526 PciAndThenOr16 (PCI_LIB_ADDRESS (PciBus
, PciDev
, PciFun
, PciReg
), (UINT16
) AndVal
, (UINT16
) OrVal
);
530 PciAndThenOr32 (PCI_LIB_ADDRESS (PciBus
, PciDev
, PciFun
, PciReg
), (UINT32
) AndVal
, (UINT32
) OrVal
);
535 // Unsupported or invalid register size
544 // This address type is not yet implemented