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 This program and the accompanying materials
9 are licensed and made available under the terms and conditions of the BSD License
10 which accompanies this distribution. The full text of the license may be found at
11 http://opensource.org/licenses/bsd-license.php
13 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
14 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
19 // Include common header file for this module.
21 #include "CommonHeader.h"
23 #include "QNCSmmHelpers.h"
26 // Help handle porting bit shifts to IA-64.
28 #define BIT_ZERO 0x00000001
32 QNCSmmPublishDispatchProtocols(
40 // Install protocol interfaces.
42 for (Index
= 0; Index
< NUM_PROTOCOLS
; Index
++) {
43 Status
= gSmst
->SmmInstallProtocolInterface (
44 &mPrivateData
.InstallMultProtHandle
,
45 mPrivateData
.Protocols
[Index
].Guid
,
47 &mPrivateData
.Protocols
[Index
].Protocols
.Generic
50 ASSERT_EFI_ERROR (Status
);
62 Initialize bits that aren't necessarily related to an SMI source.
66 gSmst - SMM System Table; contains an entry for SMM CPU IO
70 EFI_SUCCESS. Asserts, otherwise.
81 Status
= QNCSmmEnableGlobalSmiBit ();
82 ASSERT_EFI_ERROR (Status
);
85 // Be *really* sure to clear all SMIs
93 QNCSmmEnableGlobalSmiBit (
100 Enables the QNC to generate SMIs. Note that no SMIs will be generated
101 if no SMI sources are enabled. Conversely, no enabled SMI source will
102 generate SMIs if SMIs are not globally enabled. This is the main
103 switchbox for SMI generation.
119 // Enable SMI globally
121 NewValue
= QNCPortRead (QUARK_NC_HOST_BRIDGE_SB_PORT_ID
, QNC_MSG_FSBIC_REG_HMISC
);
123 QNCPortWrite (QUARK_NC_HOST_BRIDGE_SB_PORT_ID
, QNC_MSG_FSBIC_REG_HMISC
, NewValue
);
136 Clears the SMI after all SMI source have been processed.
137 Note that this function will not work correctly (as it is
138 written) unless all SMI sources have been processed.
139 A revision of this function could manually clear all SMI
140 status bits to guarantee success.
158 // Determine whether an ACPI OS is present (via the SCI_EN bit)
160 Pm1Cnt
= IoRead32(PcdGet16 (PcdPm1blkIoBaseAddress
) + R_QNC_PM1BLK_PM1C
);
161 SciEn
= (BOOLEAN
)((Pm1Cnt
& B_QNC_PM1BLK_PM1C_SCIEN
) == B_QNC_PM1BLK_PM1C_SCIEN
);
163 if (SciEn
== FALSE
) {
166 // Clear any SMIs that double as SCIs (when SCI_EN==0)
168 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
);
170 Gpe0Sts
= B_QNC_GPE0BLK_GPE0S_ALL
;
172 IoOr16((PcdGet16 (PcdPm1blkIoBaseAddress
) + R_QNC_PM1BLK_PM1S
), Pm1Sts
);
173 IoOr32(((UINT16
)(LpcPciCfg32 (R_QNC_LPC_GPE0BLK
) & 0xFFFF) + R_QNC_GPE0BLK_GPE0S
), Gpe0Sts
);
177 // Clear all SMIs that are unaffected by SCI_EN
179 SmiSts
= IoRead32((UINT16
)(LpcPciCfg32 (R_QNC_LPC_GPE0BLK
) & 0xFFFF) + R_QNC_GPE0BLK_SMIS
);
180 SmiSts
|= B_QNC_GPE0BLK_SMIS_ALL
;
181 IoWrite32(((UINT16
)(LpcPciCfg32 (R_QNC_LPC_GPE0BLK
) & 0xFFFF) + R_QNC_GPE0BLK_SMIS
), SmiSts
);
184 // Try to clear the EOS bit. ASSERT on an error
186 EosSet
= QNCSmmSetAndCheckEos();
193 QNCSmmSetAndCheckEos(
198 // Reset the QNC to generate subsequent SMIs
200 IoOr32(((UINT16
)(LpcPciCfg32 (R_QNC_LPC_GPE0BLK
) & 0xFFFF) + R_QNC_GPE0BLK_SMIS
), B_QNC_GPE0BLK_SMIS_EOS
);
212 // Determine whether an ACPI OS is present (via the SCI_EN bit)
214 Pm1Cnt
= IoRead32(PcdGet16 (PcdPm1blkIoBaseAddress
) + R_QNC_PM1BLK_PM1C
);
216 SciEn
= (BOOLEAN
)((Pm1Cnt
& B_QNC_PM1BLK_PM1C_SCIEN
) == B_QNC_PM1BLK_PM1C_SCIEN
);
222 // These may or may not need to change w/ the QNC version; they're highly IA-32 dependent, though.
227 CONST QNC_SMM_BIT_DESC
*BitDesc
237 ASSERT (BitDesc
!= NULL
);
238 ASSERT (!IS_BIT_DESC_NULL( *BitDesc
) );
243 switch (BitDesc
->Reg
.Type
) {
247 // Double check that we correctly read in the acpi base address
249 ASSERT ((PcdGet16 (PcdPm1blkIoBaseAddress
) != 0x0) && ((PcdGet16 (PcdPm1blkIoBaseAddress
) & 0x1) != 0x1) );
251 switch (BitDesc
->SizeInBytes
) {
255 // Chances are that this field didn't get initialized.
256 // Check your assignments to bit descriptions.
262 Register
= (UINT64
) IoRead8 (PcdGet16 (PcdPm1blkIoBaseAddress
) + BitDesc
->Reg
.Data
.acpi
);
266 Register
= (UINT64
) IoRead16 (PcdGet16 (PcdPm1blkIoBaseAddress
) + BitDesc
->Reg
.Data
.acpi
);
270 Register
= (UINT64
) IoRead32 (PcdGet16 (PcdPm1blkIoBaseAddress
) + BitDesc
->Reg
.Data
.acpi
);
275 // Unsupported or invalid register size
281 if ((Register
& LShiftU64 (BIT_ZERO
, BitDesc
->Bit
)) != 0) {
290 // Double check that we correctly read in the gpe base address
292 ASSERT (((UINT16
)(LpcPciCfg32 (R_QNC_LPC_GPE0BLK
) & 0xFFFF) != 0x0) && (((UINT16
)(LpcPciCfg32 (R_QNC_LPC_GPE0BLK
) & 0xFFFF) & 0x1) != 0x1) );
294 switch (BitDesc
->SizeInBytes
) {
298 // Chances are that this field didn't get initialized.
299 // Check your assignments to bit descriptions.
305 Register
= (UINT64
) IoRead8 ((UINT16
)(LpcPciCfg32 (R_QNC_LPC_GPE0BLK
) & 0xFFFF) + BitDesc
->Reg
.Data
.gpe
);
309 Register
= (UINT64
) IoRead16 ((UINT16
)(LpcPciCfg32 (R_QNC_LPC_GPE0BLK
) & 0xFFFF) + BitDesc
->Reg
.Data
.gpe
);
313 Register
= (UINT64
) IoRead32 ((UINT16
)(LpcPciCfg32 (R_QNC_LPC_GPE0BLK
) & 0xFFFF) + BitDesc
->Reg
.Data
.gpe
);
318 // Unsupported or invalid register size
324 if ((Register
& LShiftU64 (BIT_ZERO
, BitDesc
->Bit
)) != 0) {
331 case MEMORY_MAPPED_IO_ADDRESS_TYPE
:
333 // Read the register, and it with the bit to read
337 // This code does not support reads greater then 64 bits
339 ASSERT (BitDesc
->SizeInBytes
<= 8);
340 CopyMem (&Register
, BitDesc
->Reg
.Data
.Mmio
, BitDesc
->SizeInBytes
);
341 Register
&= LShiftU64 (BIT0
, BitDesc
->Bit
);
350 PciBus
= BitDesc
->Reg
.Data
.pci
.Fields
.Bus
;
351 PciDev
= BitDesc
->Reg
.Data
.pci
.Fields
.Dev
;
352 PciFun
= BitDesc
->Reg
.Data
.pci
.Fields
.Fnc
;
353 PciReg
= BitDesc
->Reg
.Data
.pci
.Fields
.Reg
;
354 switch (BitDesc
->SizeInBytes
) {
358 // Chances are that this field didn't get initialized.
359 // Check your assignments to bit descriptions.
364 Register
= (UINT64
) PciRead8 (PCI_LIB_ADDRESS (PciBus
, PciDev
, PciFun
, PciReg
));
368 Register
= (UINT64
) PciRead16 (PCI_LIB_ADDRESS (PciBus
, PciDev
, PciFun
, PciReg
));
372 Register
= (UINT64
) PciRead32 (PCI_LIB_ADDRESS (PciBus
, PciDev
, PciFun
, PciReg
));
377 // Unsupported or invalid register size
383 if ((Register
& LShiftU64 (BIT_ZERO
, BitDesc
->Bit
)) != 0) {
392 // This address type is not yet implemented
403 CONST QNC_SMM_BIT_DESC
*BitDesc
,
404 CONST BOOLEAN ValueToWrite
415 ASSERT (BitDesc
!= NULL
);
416 ASSERT (!IS_BIT_DESC_NULL(*BitDesc
));
418 AndVal
= ~(BIT_ZERO
<< (BitDesc
->Bit
));
419 OrVal
= ((UINT32
)ValueToWrite
) << (BitDesc
->Bit
);
421 switch (BitDesc
->Reg
.Type
) {
425 // Double check that we correctly read in the acpi base address
427 ASSERT ((PcdGet16 (PcdPm1blkIoBaseAddress
) != 0x0) && ((PcdGet16 (PcdPm1blkIoBaseAddress
) & 0x1) != 0x1));
429 switch (BitDesc
->SizeInBytes
) {
433 // Chances are that this field didn't get initialized.
434 // Check your assignments to bit descriptions.
440 IoAndThenOr8 (PcdGet16 (PcdPm1blkIoBaseAddress
) + BitDesc
->Reg
.Data
.acpi
, (UINT8
)AndVal
, (UINT8
)OrVal
);
444 IoAndThenOr16 (PcdGet16 (PcdPm1blkIoBaseAddress
) + BitDesc
->Reg
.Data
.acpi
, (UINT16
)AndVal
, (UINT16
)OrVal
);
448 IoAndThenOr32 (PcdGet16 (PcdPm1blkIoBaseAddress
) + BitDesc
->Reg
.Data
.acpi
, (UINT32
)AndVal
, (UINT32
)OrVal
);
453 // Unsupported or invalid register size
462 // Double check that we correctly read in the gpe base address
464 ASSERT (((UINT16
)(LpcPciCfg32 (R_QNC_LPC_GPE0BLK
) & 0xFFFF) != 0x0) && (((UINT16
)(LpcPciCfg32 (R_QNC_LPC_GPE0BLK
) & 0xFFFF) & 0x1) != 0x1));
466 switch (BitDesc
->SizeInBytes
) {
470 // Chances are that this field didn't get initialized.
471 // Check your assignments to bit descriptions.
477 IoAndThenOr8 ((UINT16
)(LpcPciCfg32 (R_QNC_LPC_GPE0BLK
) & 0xFFFF) + BitDesc
->Reg
.Data
.gpe
, (UINT8
)AndVal
, (UINT8
)OrVal
);
481 IoAndThenOr16 ((UINT16
)(LpcPciCfg32 (R_QNC_LPC_GPE0BLK
) & 0xFFFF) + BitDesc
->Reg
.Data
.gpe
, (UINT16
)AndVal
, (UINT16
)OrVal
);
485 IoAndThenOr32 ((UINT16
)(LpcPciCfg32 (R_QNC_LPC_GPE0BLK
) & 0xFFFF) + BitDesc
->Reg
.Data
.gpe
, (UINT32
)AndVal
, (UINT32
)OrVal
);
490 // Unsupported or invalid register size
497 case MEMORY_MAPPED_IO_ADDRESS_TYPE
:
499 // Read the register, or it with the bit to set, then write it back.
503 // This code does not support writes greater then 64 bits
505 ASSERT (BitDesc
->SizeInBytes
<= 8);
506 CopyMem (&Register
, BitDesc
->Reg
.Data
.Mmio
, BitDesc
->SizeInBytes
);
509 CopyMem (BitDesc
->Reg
.Data
.Mmio
, &Register
, BitDesc
->SizeInBytes
);
513 PciBus
= BitDesc
->Reg
.Data
.pci
.Fields
.Bus
;
514 PciDev
= BitDesc
->Reg
.Data
.pci
.Fields
.Dev
;
515 PciFun
= BitDesc
->Reg
.Data
.pci
.Fields
.Fnc
;
516 PciReg
= BitDesc
->Reg
.Data
.pci
.Fields
.Reg
;
517 switch (BitDesc
->SizeInBytes
) {
521 // Chances are that this field didn't get initialized -- check your assignments
522 // to bit descriptions.
528 PciAndThenOr8 (PCI_LIB_ADDRESS (PciBus
, PciDev
, PciFun
, PciReg
), (UINT8
) AndVal
, (UINT8
) OrVal
);
532 PciAndThenOr16 (PCI_LIB_ADDRESS (PciBus
, PciDev
, PciFun
, PciReg
), (UINT16
) AndVal
, (UINT16
) OrVal
);
536 PciAndThenOr32 (PCI_LIB_ADDRESS (PciBus
, PciDev
, PciFun
, PciReg
), (UINT32
) AndVal
, (UINT32
) OrVal
);
541 // Unsupported or invalid register size
550 // This address type is not yet implemented