1 /** @file 2 3 This driver is responsible for the registration of child drivers 4 and the abstraction of the QNC SMI sources. 5 6 Copyright (c) 2013-2015 Intel Corporation. 7 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 12 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. 15 16 **/ 17 18 // 19 // Include common header file for this module. 20 // 21 #include "CommonHeader.h" 22 23 #include "QNCSmmHelpers.h" 24 25 // 26 // Help handle porting bit shifts to IA-64. 27 // 28 #define BIT_ZERO 0x00000001 29 30 31 VOID 32 QNCSmmPublishDispatchProtocols( 33 VOID 34 ) 35 { 36 UINTN Index; 37 EFI_STATUS Status; 38 39 // 40 // Install protocol interfaces. 41 // 42 for (Index = 0; Index < NUM_PROTOCOLS; Index++) { 43 Status = gSmst->SmmInstallProtocolInterface ( 44 &mPrivateData.InstallMultProtHandle, 45 mPrivateData.Protocols[Index].Guid, 46 EFI_NATIVE_INTERFACE, 47 &mPrivateData.Protocols[Index].Protocols.Generic 48 ); 49 50 ASSERT_EFI_ERROR (Status); 51 } 52 } 53 54 EFI_STATUS 55 QNCSmmInitHardware( 56 VOID 57 ) 58 /*++ 59 60 Routine Description: 61 62 Initialize bits that aren't necessarily related to an SMI source. 63 64 Dependencies: 65 66 gSmst - SMM System Table; contains an entry for SMM CPU IO 67 68 Returns: 69 70 EFI_SUCCESS. Asserts, otherwise. 71 72 --*/ 73 { 74 EFI_STATUS Status; 75 76 // 77 // Clear all SMIs 78 // 79 QNCSmmClearSmi(); 80 81 Status = QNCSmmEnableGlobalSmiBit (); 82 ASSERT_EFI_ERROR (Status); 83 84 // 85 // Be *really* sure to clear all SMIs 86 // 87 QNCSmmClearSmi (); 88 89 return EFI_SUCCESS; 90 } 91 92 EFI_STATUS 93 QNCSmmEnableGlobalSmiBit ( 94 VOID 95 ) 96 /*++ 97 98 Routine Description: 99 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. 104 105 Arguments: 106 107 None 108 109 Returns: 110 111 EFI_SUCCESS. 112 Asserts, otherwise. 113 114 --*/ 115 { 116 UINT32 NewValue; 117 118 // 119 // Enable SMI globally 120 // 121 NewValue = QNCPortRead (QUARK_NC_HOST_BRIDGE_SB_PORT_ID, QNC_MSG_FSBIC_REG_HMISC); 122 NewValue |= SMI_EN; 123 QNCPortWrite (QUARK_NC_HOST_BRIDGE_SB_PORT_ID, QNC_MSG_FSBIC_REG_HMISC, NewValue); 124 125 return EFI_SUCCESS; 126 } 127 128 EFI_STATUS 129 QNCSmmClearSmi( 130 VOID 131 ) 132 /*++ 133 134 Routine Description: 135 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. 141 142 Returns: 143 144 EFI_SUCCESS. 145 Asserts, otherwise. 146 147 --*/ 148 { 149 BOOLEAN EosSet; 150 BOOLEAN SciEn; 151 152 UINT32 Pm1Cnt = 0; 153 UINT16 Pm1Sts = 0; 154 UINT32 Gpe0Sts = 0; 155 UINT32 SmiSts = 0; 156 157 // 158 // Determine whether an ACPI OS is present (via the SCI_EN bit) 159 // 160 Pm1Cnt = IoRead32(PcdGet16 (PcdPm1blkIoBaseAddress) + R_QNC_PM1BLK_PM1C); 161 SciEn = (BOOLEAN)((Pm1Cnt & B_QNC_PM1BLK_PM1C_SCIEN) == B_QNC_PM1BLK_PM1C_SCIEN); 162 163 if (SciEn == FALSE) { 164 165 // 166 // Clear any SMIs that double as SCIs (when SCI_EN==0) 167 // 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); 169 170 Gpe0Sts = B_QNC_GPE0BLK_GPE0S_ALL; 171 172 IoOr16((PcdGet16 (PcdPm1blkIoBaseAddress) + R_QNC_PM1BLK_PM1S), Pm1Sts); 173 IoOr32(((UINT16)(LpcPciCfg32 (R_QNC_LPC_GPE0BLK) & 0xFFFF) + R_QNC_GPE0BLK_GPE0S), Gpe0Sts); 174 } 175 176 // 177 // Clear all SMIs that are unaffected by SCI_EN 178 // 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); 182 183 // 184 // Try to clear the EOS bit. ASSERT on an error 185 // 186 EosSet = QNCSmmSetAndCheckEos(); 187 ASSERT (EosSet); 188 189 return EFI_SUCCESS; 190 } 191 192 BOOLEAN 193 QNCSmmSetAndCheckEos( 194 VOID 195 ) 196 { 197 // 198 // Reset the QNC to generate subsequent SMIs 199 // 200 IoOr32(((UINT16)(LpcPciCfg32 (R_QNC_LPC_GPE0BLK) & 0xFFFF) + R_QNC_GPE0BLK_SMIS), B_QNC_GPE0BLK_SMIS_EOS); 201 return TRUE; 202 } 203 204 BOOLEAN 205 QNCSmmGetSciEn( 206 ) 207 { 208 BOOLEAN SciEn; 209 UINT32 Pm1Cnt; 210 211 // 212 // Determine whether an ACPI OS is present (via the SCI_EN bit) 213 // 214 Pm1Cnt = IoRead32(PcdGet16 (PcdPm1blkIoBaseAddress) + R_QNC_PM1BLK_PM1C); 215 216 SciEn = (BOOLEAN)((Pm1Cnt & B_QNC_PM1BLK_PM1C_SCIEN) == B_QNC_PM1BLK_PM1C_SCIEN); 217 218 return SciEn; 219 } 220 221 // 222 // These may or may not need to change w/ the QNC version; they're highly IA-32 dependent, though. 223 // 224 225 BOOLEAN 226 ReadBitDesc ( 227 CONST QNC_SMM_BIT_DESC *BitDesc 228 ) 229 { 230 UINT64 Register; 231 UINT32 PciBus; 232 UINT32 PciDev; 233 UINT32 PciFun; 234 UINT32 PciReg; 235 BOOLEAN BitWasOne; 236 237 ASSERT (BitDesc != NULL ); 238 ASSERT (!IS_BIT_DESC_NULL( *BitDesc ) ); 239 240 Register = 0; 241 BitWasOne = FALSE; 242 243 switch (BitDesc->Reg.Type) { 244 245 case ACPI_ADDR_TYPE: 246 // 247 // Double check that we correctly read in the acpi base address 248 // 249 ASSERT ((PcdGet16 (PcdPm1blkIoBaseAddress) != 0x0) && ((PcdGet16 (PcdPm1blkIoBaseAddress) & 0x1) != 0x1) ); 250 251 switch (BitDesc->SizeInBytes) { 252 253 case 0: 254 // 255 // Chances are that this field didn't get initialized. 256 // Check your assignments to bit descriptions. 257 // 258 ASSERT (FALSE ); 259 break; 260 261 case 1: 262 Register = (UINT64) IoRead8 (PcdGet16 (PcdPm1blkIoBaseAddress) + BitDesc->Reg.Data.acpi); 263 break; 264 265 case 2: 266 Register = (UINT64) IoRead16 (PcdGet16 (PcdPm1blkIoBaseAddress) + BitDesc->Reg.Data.acpi); 267 break; 268 269 case 4: 270 Register = (UINT64) IoRead32 (PcdGet16 (PcdPm1blkIoBaseAddress) + BitDesc->Reg.Data.acpi); 271 break; 272 273 default: 274 // 275 // Unsupported or invalid register size 276 // 277 ASSERT (FALSE ); 278 break; 279 }; 280 281 if ((Register & LShiftU64 (BIT_ZERO, BitDesc->Bit)) != 0) { 282 BitWasOne = TRUE; 283 } else { 284 BitWasOne = FALSE; 285 } 286 break; 287 288 case GPE_ADDR_TYPE: 289 // 290 // Double check that we correctly read in the gpe base address 291 // 292 ASSERT (((UINT16)(LpcPciCfg32 (R_QNC_LPC_GPE0BLK) & 0xFFFF) != 0x0) && (((UINT16)(LpcPciCfg32 (R_QNC_LPC_GPE0BLK) & 0xFFFF) & 0x1) != 0x1) ); 293 294 switch (BitDesc->SizeInBytes) { 295 296 case 0: 297 // 298 // Chances are that this field didn't get initialized. 299 // Check your assignments to bit descriptions. 300 // 301 ASSERT (FALSE ); 302 break; 303 304 case 1: 305 Register = (UINT64) IoRead8 ((UINT16)(LpcPciCfg32 (R_QNC_LPC_GPE0BLK) & 0xFFFF) + BitDesc->Reg.Data.gpe); 306 break; 307 308 case 2: 309 Register = (UINT64) IoRead16 ((UINT16)(LpcPciCfg32 (R_QNC_LPC_GPE0BLK) & 0xFFFF) + BitDesc->Reg.Data.gpe); 310 break; 311 312 case 4: 313 Register = (UINT64) IoRead32 ((UINT16)(LpcPciCfg32 (R_QNC_LPC_GPE0BLK) & 0xFFFF) + BitDesc->Reg.Data.gpe); 314 break; 315 316 default: 317 // 318 // Unsupported or invalid register size 319 // 320 ASSERT (FALSE ); 321 break; 322 }; 323 324 if ((Register & LShiftU64 (BIT_ZERO, BitDesc->Bit)) != 0) { 325 BitWasOne = TRUE; 326 } else { 327 BitWasOne = FALSE; 328 } 329 break; 330 331 case MEMORY_MAPPED_IO_ADDRESS_TYPE: 332 // 333 // Read the register, and it with the bit to read 334 // 335 336 // 337 // This code does not support reads greater then 64 bits 338 // 339 ASSERT (BitDesc->SizeInBytes <= 8); 340 CopyMem (&Register, BitDesc->Reg.Data.Mmio, BitDesc->SizeInBytes); 341 Register &= LShiftU64 (BIT0, BitDesc->Bit); 342 if (Register) { 343 BitWasOne = TRUE; 344 } else { 345 BitWasOne = FALSE; 346 } 347 break; 348 349 case PCI_ADDR_TYPE: 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) { 355 356 case 0: 357 // 358 // Chances are that this field didn't get initialized. 359 // Check your assignments to bit descriptions. 360 ASSERT (FALSE ); 361 break; 362 363 case 1: 364 Register = (UINT64) PciRead8 (PCI_LIB_ADDRESS (PciBus, PciDev, PciFun, PciReg)); 365 break; 366 367 case 2: 368 Register = (UINT64) PciRead16 (PCI_LIB_ADDRESS (PciBus, PciDev, PciFun, PciReg)); 369 break; 370 371 case 4: 372 Register = (UINT64) PciRead32 (PCI_LIB_ADDRESS (PciBus, PciDev, PciFun, PciReg)); 373 break; 374 375 default: 376 // 377 // Unsupported or invalid register size 378 // 379 ASSERT (FALSE ); 380 break; 381 }; 382 383 if ((Register & LShiftU64 (BIT_ZERO, BitDesc->Bit)) != 0) { 384 BitWasOne = TRUE; 385 } else { 386 BitWasOne = FALSE; 387 } 388 break; 389 390 default: 391 // 392 // This address type is not yet implemented 393 // 394 ASSERT (FALSE ); 395 break; 396 }; 397 398 return BitWasOne; 399 } 400 401 VOID 402 WriteBitDesc ( 403 CONST QNC_SMM_BIT_DESC *BitDesc, 404 CONST BOOLEAN ValueToWrite 405 ) 406 { 407 UINT64 Register; 408 UINT64 AndVal; 409 UINT64 OrVal; 410 UINT32 PciBus; 411 UINT32 PciDev; 412 UINT32 PciFun; 413 UINT32 PciReg; 414 415 ASSERT (BitDesc != NULL); 416 ASSERT (!IS_BIT_DESC_NULL(*BitDesc)); 417 418 AndVal = ~(BIT_ZERO << (BitDesc->Bit)); 419 OrVal = ((UINT32)ValueToWrite) << (BitDesc->Bit); 420 421 switch (BitDesc->Reg.Type) { 422 423 case ACPI_ADDR_TYPE: 424 // 425 // Double check that we correctly read in the acpi base address 426 // 427 ASSERT ((PcdGet16 (PcdPm1blkIoBaseAddress) != 0x0) && ((PcdGet16 (PcdPm1blkIoBaseAddress) & 0x1) != 0x1)); 428 429 switch (BitDesc->SizeInBytes) { 430 431 case 0: 432 // 433 // Chances are that this field didn't get initialized. 434 // Check your assignments to bit descriptions. 435 // 436 ASSERT (FALSE ); 437 break; 438 439 case 1: 440 IoAndThenOr8 (PcdGet16 (PcdPm1blkIoBaseAddress) + BitDesc->Reg.Data.acpi, (UINT8)AndVal, (UINT8)OrVal); 441 break; 442 443 case 2: 444 IoAndThenOr16 (PcdGet16 (PcdPm1blkIoBaseAddress) + BitDesc->Reg.Data.acpi, (UINT16)AndVal, (UINT16)OrVal); 445 break; 446 447 case 4: 448 IoAndThenOr32 (PcdGet16 (PcdPm1blkIoBaseAddress) + BitDesc->Reg.Data.acpi, (UINT32)AndVal, (UINT32)OrVal); 449 break; 450 451 default: 452 // 453 // Unsupported or invalid register size 454 // 455 ASSERT (FALSE ); 456 break; 457 }; 458 break; 459 460 case GPE_ADDR_TYPE: 461 // 462 // Double check that we correctly read in the gpe base address 463 // 464 ASSERT (((UINT16)(LpcPciCfg32 (R_QNC_LPC_GPE0BLK) & 0xFFFF) != 0x0) && (((UINT16)(LpcPciCfg32 (R_QNC_LPC_GPE0BLK) & 0xFFFF) & 0x1) != 0x1)); 465 466 switch (BitDesc->SizeInBytes) { 467 468 case 0: 469 // 470 // Chances are that this field didn't get initialized. 471 // Check your assignments to bit descriptions. 472 // 473 ASSERT (FALSE ); 474 break; 475 476 case 1: 477 IoAndThenOr8 ((UINT16)(LpcPciCfg32 (R_QNC_LPC_GPE0BLK) & 0xFFFF) + BitDesc->Reg.Data.gpe, (UINT8)AndVal, (UINT8)OrVal); 478 break; 479 480 case 2: 481 IoAndThenOr16 ((UINT16)(LpcPciCfg32 (R_QNC_LPC_GPE0BLK) & 0xFFFF) + BitDesc->Reg.Data.gpe, (UINT16)AndVal, (UINT16)OrVal); 482 break; 483 484 case 4: 485 IoAndThenOr32 ((UINT16)(LpcPciCfg32 (R_QNC_LPC_GPE0BLK) & 0xFFFF) + BitDesc->Reg.Data.gpe, (UINT32)AndVal, (UINT32)OrVal); 486 break; 487 488 default: 489 // 490 // Unsupported or invalid register size 491 // 492 ASSERT (FALSE ); 493 break; 494 }; 495 break; 496 497 case MEMORY_MAPPED_IO_ADDRESS_TYPE: 498 // 499 // Read the register, or it with the bit to set, then write it back. 500 // 501 502 // 503 // This code does not support writes greater then 64 bits 504 // 505 ASSERT (BitDesc->SizeInBytes <= 8); 506 CopyMem (&Register, BitDesc->Reg.Data.Mmio, BitDesc->SizeInBytes); 507 Register &= AndVal; 508 Register |= OrVal; 509 CopyMem (BitDesc->Reg.Data.Mmio, &Register, BitDesc->SizeInBytes); 510 break; 511 512 case PCI_ADDR_TYPE: 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) { 518 519 case 0: 520 // 521 // Chances are that this field didn't get initialized -- check your assignments 522 // to bit descriptions. 523 // 524 ASSERT (FALSE ); 525 break; 526 527 case 1: 528 PciAndThenOr8 (PCI_LIB_ADDRESS (PciBus, PciDev, PciFun, PciReg), (UINT8) AndVal, (UINT8) OrVal); 529 break; 530 531 case 2: 532 PciAndThenOr16 (PCI_LIB_ADDRESS (PciBus, PciDev, PciFun, PciReg), (UINT16) AndVal, (UINT16) OrVal); 533 break; 534 535 case 4: 536 PciAndThenOr32 (PCI_LIB_ADDRESS (PciBus, PciDev, PciFun, PciReg), (UINT32) AndVal, (UINT32) OrVal); 537 break; 538 539 default: 540 // 541 // Unsupported or invalid register size 542 // 543 ASSERT (FALSE ); 544 break; 545 }; 546 break; 547 548 default: 549 // 550 // This address type is not yet implemented 551 // 552 ASSERT (FALSE ); 553 break; 554 }; 555 } 556