1 /** @file 2 Gpio setting for multiplatform.. 3 4 Copyright (c) 2013 - 2014, Intel Corporation. All rights reserved.<BR> 5 6 This program and the accompanying materials are licensed and made available under 8 the terms and conditions of the BSD License that accompanies this distribution. 10 The full text of the license may be found at 12 http://opensource.org/licenses/bsd-license.php. 14 16 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 18 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 20 22 24 **/ 25 26 #include <BoardGpios.h> 27 #include <Guid/SetupVariable.h> 28 29 // 30 //AlpineValley platform ocde begin 31 // 32 #define AV_SC_REG_GPIOS_MUXES_SEL0 0x48 33 #define AV_SC_REG_GPIOS_MUXES_SEL1 0x4C 34 #define AV_SC_REG_GPIOS_MUXES_SEL2 0x50 35 #define AV_SC_REG_GPIOS_MUXES_EN0 0x54 36 #define AV_SC_REG_GPIOS_MUXES_EN1 0x58 37 #define AV_SC_REG_GPIOS_MUXES_EN2 0x5C 38 // 39 //AlpineValley platform code end 40 // 41 42 EFI_GUID gPeiSmbusPpiGuid = EFI_PEI_SMBUS_PPI_GUID; 43 44 /** 45 @param None 46 47 @retval EFI_SUCCESS The function completed successfully. 48 49 **/ 50 EFI_STATUS 51 ConfigurePlatformSysCtrlGpio ( 52 IN EFI_PEI_SERVICES **PeiServices, 53 IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor, 54 IN VOID *SmbusPpi 55 ) 56 { 57 // 58 //AlpineValley platform code begin 59 // 60 // Initialize GPIO Settings: 61 // 62 UINT32 Status; 63 EFI_PLATFORM_INFO_HOB *PlatformInfoHob; 64 65 DEBUG ((EFI_D_INFO, "ConfigurePlatformSysCtrlGpio()...\n")); 66 67 // 68 // Obtain Platform Info from HOB. 69 // 70 Status = GetPlatformInfoHob ((const EFI_PEI_SERVICES **)PeiServices, &PlatformInfoHob); 71 ASSERT_EFI_ERROR (Status); 72 73 // 74 // The GPIO settings are dependent upon the platform. Obtain the Board ID through 75 // the EC to determine the current platform. 76 // 77 DEBUG ((EFI_D_INFO, "Platform Flavor | Board ID = 0x%X | 0x%X\n", PlatformInfoHob->PlatformFlavor, PlatformInfoHob->BoardId)); 78 79 80 81 Status = (**PeiServices).LocatePpi ( 82 (const EFI_PEI_SERVICES **)PeiServices, 83 &gPeiSmbusPpiGuid, 84 0, 85 NULL, 86 (void **)&SmbusPpi 87 ); 88 ASSERT_EFI_ERROR (Status); 89 90 // 91 // Select/modify the GPIO initialization data based on the Board ID. 92 // 93 switch (PlatformInfoHob->BoardId) 94 { 95 default: 96 Status = EFI_SUCCESS; 97 98 // 99 // Do nothing for other RVP boards. 100 // 101 break; 102 } 103 return Status; 104 } 105 106 static EFI_PEI_NOTIFY_DESCRIPTOR mNotifyList[] = { 107 { 108 EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK| EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST, 109 &gEfiPeiSmbusPpiGuid, 110 ConfigurePlatformSysCtrlGpio 111 } 112 }; 113 114 EFI_STATUS 115 InstallPlatformSysCtrlGPIONotify ( 116 IN CONST EFI_PEI_SERVICES **PeiServices 117 ) 118 { 119 EFI_STATUS Status; 120 121 DEBUG ((EFI_D_INFO, "InstallPlatformSysCtrlGPIONotify()...\n")); 122 123 Status = (*PeiServices)->NotifyPpi(PeiServices, &mNotifyList[0]); 124 ASSERT_EFI_ERROR (Status); 125 return EFI_SUCCESS; 126 127 } 128 129 #define V_PCH_ILB_IRQE_UARTIRQEN_IRQ3 BIT3 // UART IRQ3 Enable 130 131 /** 132 Returns the Correct GPIO table for Mobile/Desktop respectively. 133 Before call it, make sure PlatformInfoHob->BoardId&PlatformFlavor is get correctly. 134 135 @param PeiServices General purpose services available to every PEIM. 136 @param PlatformInfoHob PlatformInfoHob pointer with PlatformFlavor specified. 137 @param BoardId BoardId ID as determined through the EC. 138 139 @retval EFI_SUCCESS The function completed successfully. 140 @retval EFI_DEVICE_ERROR KSC fails to respond. 141 142 **/ 143 EFI_STATUS 144 MultiPlatformGpioTableInit ( 145 IN CONST EFI_PEI_SERVICES **PeiServices, 146 IN EFI_PLATFORM_INFO_HOB *PlatformInfoHob 147 ) 148 { 149 EFI_STATUS Status; 150 EFI_PEI_READ_ONLY_VARIABLE2_PPI *PeiReadOnlyVarPpi; 151 UINTN VarSize; 152 SYSTEM_CONFIGURATION SystemConfiguration; 153 154 DEBUG ((EFI_D_INFO, "MultiPlatformGpioTableInit()...\n")); 155 156 // 157 // Select/modify the GPIO initialization data based on the Board ID. 158 // 159 switch (PlatformInfoHob->BoardId) { 160 161 case BOARD_ID_MINNOW2: // Minnow2 162 case BOARD_ID_MINNOW2_TURBOT: 163 Status = (**PeiServices).LocatePpi ( 164 PeiServices, 165 &gEfiPeiReadOnlyVariable2PpiGuid, 166 0, 167 NULL, 168 (void **)&PeiReadOnlyVarPpi 169 ); 170 ASSERT_EFI_ERROR (Status); 171 172 VarSize = sizeof (SYSTEM_CONFIGURATION); 173 Status = PeiReadOnlyVarPpi->GetVariable ( 174 PeiReadOnlyVarPpi, 175 PLATFORM_SETUP_VARIABLE_NAME, 176 &gEfiSetupVariableGuid, 177 NULL, 178 &VarSize, 179 &SystemConfiguration 180 ); 181 182 if (SystemConfiguration.GpioWakeCapability == 1) { 183 PlatformInfoHob->PlatformCfioData = (EFI_PHYSICAL_ADDRESS)(UINTN) &mMinnow2CfioInitData2; 184 } 185 else { 186 PlatformInfoHob->PlatformCfioData = (EFI_PHYSICAL_ADDRESS)(UINTN) &mMinnow2CfioInitData; 187 } 188 189 PlatformInfoHob->PlatformGpioData_NC = (EFI_PHYSICAL_ADDRESS)(UINTN) &mMinnow2_GpioInitData_NC[0]; 190 PlatformInfoHob->PlatformGpioData_SC = (EFI_PHYSICAL_ADDRESS)(UINTN) &mMinnow2_GpioInitData_SC[0]; 191 PlatformInfoHob->PlatformGpioData_SUS = (EFI_PHYSICAL_ADDRESS)(UINTN) &mMinnow2_GpioInitData_SUS[0]; 192 break; 193 194 } 195 196 return EFI_SUCCESS; 197 } 198 199 UINT32 200 GPIORead32 ( 201 IN UINT32 mmio_conf 202 ) 203 { 204 UINT32 conf_val; 205 UINT32 i; 206 conf_val = MmioRead32(mmio_conf); 207 for(i=0;i<5;i++){ 208 if(conf_val == 0xffffffff) 209 conf_val = MmioRead32(mmio_conf); 210 else 211 break; 212 } 213 214 return conf_val; 215 } 216 217 /** 218 219 Set GPIO CONF0 and PAD_VAL registers for NC/SC/SUS GPIO clusters 220 221 @param Gpio_Mmio_Offset GPIO_SCORE_OFFSET or GPIO_NCORE_OFFSET or GPIO_SSUS_OFFSET. 222 @param Gpio_Pin_Num Pin numbers to config for each GPIO clusters. 223 @param Gpio_Conf_Data GPIO_CONF_PAD_INIT data array for each GPIO clusters. 224 225 **/ 226 VOID 227 InternalGpioConfig ( 228 IN UINT32 Gpio_Mmio_Offset, 229 IN UINT32 Gpio_Pin_Num, 230 GPIO_CONF_PAD_INIT* Gpio_Conf_Data 231 ) 232 { 233 UINT32 index; 234 UINT32 mmio_conf0; 235 UINT32 mmio_padval; 236 PAD_CONF0 conf0_val; 237 PAD_VAL pad_val; 238 239 // 240 // GPIO WELL -- Memory base registers 241 // 242 243 // A0 BIOS Spec doesn't mention it although X0 does. comment out now. 244 // GPIO write 0x01001002 to IOBASE + Gpio_Mmio_Offset + 0x0900 245 // 246 for(index=0; index < Gpio_Pin_Num; index++) 247 { 248 // 249 // Calculate the MMIO Address for specific GPIO pin CONF0 register pointed by index. 250 // 251 mmio_conf0 = IO_BASE_ADDRESS + Gpio_Mmio_Offset + R_PCH_CFIO_PAD_CONF0 + Gpio_Conf_Data[index].offset * 16; 252 mmio_padval= IO_BASE_ADDRESS + Gpio_Mmio_Offset + R_PCH_CFIO_PAD_VAL + Gpio_Conf_Data[index].offset * 16; 253 254 #ifdef EFI_DEBUG 255 DEBUG ((EFI_D_INFO, "%s, ", Gpio_Conf_Data[index].pad_name)); 256 257 #endif 258 DEBUG ((EFI_D_INFO, "Usage = %d, Func# = %d, IntType = %d, Pull Up/Down = %d, MMIO Base = 0x%08x, ", 259 Gpio_Conf_Data[index].usage, 260 Gpio_Conf_Data[index].func, 261 Gpio_Conf_Data[index].int_type, 262 Gpio_Conf_Data[index].pull, 263 mmio_conf0)); 264 265 // 266 // Step 1: PadVal Programming. 267 // 268 pad_val.dw = GPIORead32(mmio_padval); 269 270 // 271 // Config PAD_VAL only for GPIO (Non-Native) Pin 272 // 273 if(Native != Gpio_Conf_Data[index].usage) 274 { 275 pad_val.dw &= ~0x6; // Clear bits 1:2 276 pad_val.dw |= (Gpio_Conf_Data[index].usage & 0x6); // Set bits 1:2 according to PadVal 277 278 // 279 // set GPO default value 280 // 281 if(Gpio_Conf_Data[index].usage == GPO && Gpio_Conf_Data[index].gpod4 != NA) 282 { 283 pad_val.r.pad_val = Gpio_Conf_Data[index].gpod4; 284 } 285 } 286 287 288 DEBUG ((EFI_D_INFO, "Set PAD_VAL = 0x%08x, ", pad_val.dw)); 289 290 MmioWrite32(mmio_padval, pad_val.dw); 291 292 // 293 // Step 2: CONF0 Programming 294 // Read GPIO default CONF0 value, which is assumed to be default value after reset. 295 // 296 conf0_val.dw = GPIORead32(mmio_conf0); 297 298 // 299 // Set Function # 300 // 301 conf0_val.r.Func_Pin_Mux = Gpio_Conf_Data[index].func; 302 303 if(GPO == Gpio_Conf_Data[index].usage) 304 { 305 // 306 // If used as GPO, then internal pull need to be disabled. 307 // 308 conf0_val.r.Pull_assign = 0; // Non-pull 309 } 310 else 311 { 312 // 313 // Set PullUp / PullDown 314 // 315 if(P_20K_H == Gpio_Conf_Data[index].pull) 316 { 317 conf0_val.r.Pull_assign = 0x1; // PullUp 318 conf0_val.r.Pull_strength = 0x2;// 20K 319 } 320 else if(P_20K_L == Gpio_Conf_Data[index].pull) 321 { 322 conf0_val.r.Pull_assign = 0x2; // PullDown 323 conf0_val.r.Pull_strength = 0x2;// 20K 324 } 325 else if(P_10K_H == Gpio_Conf_Data[index].pull) 326 { 327 conf0_val.r.Pull_assign = 0x1; // PullUp 328 conf0_val.r.Pull_strength = 0x1;// 10K 329 } 330 else if(P_10K_L == Gpio_Conf_Data[index].pull) 331 { 332 conf0_val.r.Pull_assign = 0x2; // PullDown 333 conf0_val.r.Pull_strength = 0x1;// 10K 334 } 335 else if(P_2K_H == Gpio_Conf_Data[index].pull) 336 { 337 conf0_val.r.Pull_assign = 0x1; // PullUp 338 conf0_val.r.Pull_strength = 0x0;// 2K 339 } 340 else if(P_2K_L == Gpio_Conf_Data[index].pull) 341 { 342 conf0_val.r.Pull_assign = 0x2; // PullDown 343 conf0_val.r.Pull_strength = 0x0;// 2K 344 } 345 else if(P_NONE == Gpio_Conf_Data[index].pull) 346 { 347 conf0_val.r.Pull_assign = 0; // Non-pull 348 } 349 else 350 { 351 ASSERT(FALSE); // Invalid value 352 } 353 } 354 355 356 // 357 // Set INT Trigger Type 358 // 359 conf0_val.dw &= ~0x0f000000; // Clear bits 27:24 360 361 // 362 // Set INT Trigger Type 363 // 364 if(TRIG_ == Gpio_Conf_Data[index].int_type) 365 { 366 // 367 // Interrupt not capable, clear bits 27:24 368 // 369 } 370 else 371 { 372 conf0_val.dw |= (Gpio_Conf_Data[index].int_type & 0x0f)<<24; 373 } 374 375 DEBUG ((EFI_D_INFO, "Set CONF0 = 0x%08x\n", conf0_val.dw)); 376 377 // 378 // Write back the targeted GPIO config value according to platform (board) GPIO setting. 379 // 380 MmioWrite32 (mmio_conf0, conf0_val.dw); 381 } 382 383 // 384 // A0 BIOS Spec doesn't mention it although X0 does. comment out now. 385 // GPIO SCORE write 0x01001002 to IOBASE + 0x0900 386 // 387 } 388 389 /** 390 Returns the Correct GPIO table for Mobile/Desktop respectively. 391 Before call it, make sure PlatformInfoHob->BoardId&PlatformFlavor is get correctly. 392 393 @param PeiServices General purpose services available to every PEIM. 394 @param PlatformInfoHob PlatformInfoHob pointer with PlatformFlavor specified. 395 @param BoardId BoardId ID as determined through the EC. 396 397 @retval EFI_SUCCESS The function completed successfully. 398 @retval EFI_DEVICE_ERROR KSC fails to respond. 399 400 **/ 401 EFI_STATUS 402 MultiPlatformGpioProgram ( 403 IN CONST EFI_PEI_SERVICES **PeiServices, 404 IN EFI_PLATFORM_INFO_HOB *PlatformInfoHob 405 ) 406 { 407 #if !_SIMIC_ 408 CFIO_INIT_STRUCT* PlatformCfioDataPtr; 409 410 PlatformCfioDataPtr = (CFIO_INIT_STRUCT *) (UINTN) PlatformInfoHob->PlatformCfioData; 411 DEBUG ((EFI_D_INFO, "MultiPlatformGpioProgram()...\n")); 412 413 // 414 // SCORE GPIO WELL -- IO base registers 415 // 416 417 // 418 // GPIO_USE_SEL Register -> 1 = GPIO 0 = Native 419 // 420 IoWrite32 (GPIO_BASE_ADDRESS + R_PCH_GPIO_SC_USE_SEL, PlatformCfioDataPtr->Use_Sel_SC0); 421 422 // 423 // Set GP_LVL Register 424 // 425 IoWrite32 (GPIO_BASE_ADDRESS + R_PCH_GPIO_SC_LVL , PlatformCfioDataPtr->GP_Lvl_SC0); 426 427 // 428 // GP_IO_SEL Register -> 1 = Input 0 = Output. If Native Mode don't care 429 // 430 IoWrite32 (GPIO_BASE_ADDRESS + R_PCH_GPIO_SC_IO_SEL, PlatformCfioDataPtr->Io_Sel_SC0); 431 432 // 433 // GPIO Triger Positive Edge Enable Register 434 // 435 IoWrite32 (GPIO_BASE_ADDRESS + R_PCH_GPIO_SC_TPE, PlatformCfioDataPtr->TPE_SC0); 436 437 // 438 // GPIO Trigger Negative Edge Enable Register 439 // 440 IoWrite32 (GPIO_BASE_ADDRESS + R_PCH_GPIO_SC_TNE, PlatformCfioDataPtr->TNE_SC0); 441 442 // 443 // GPIO Trigger Status 444 // 445 IoWrite32 (GPIO_BASE_ADDRESS + R_PCH_GPIO_SC_TS, PlatformCfioDataPtr->TS_SC0); 446 447 // 448 // GPIO_USE_SEL2 Register -> 1 = GPIO 0 = Native 449 // 450 IoWrite32 (GPIO_BASE_ADDRESS + R_PCH_GPIO_SC_USE_SEL2, PlatformCfioDataPtr->Use_Sel_SC1); 451 452 // 453 // Set GP_LVL2 Register 454 // 455 IoWrite32 (GPIO_BASE_ADDRESS + R_PCH_GPIO_SC_LVL2, PlatformCfioDataPtr->GP_Lvl_SC1); 456 457 // 458 // GP_IO_SEL2 Register -> 1 = Input 0 = Output. If Native Mode don't care 459 // 460 IoWrite32 (GPIO_BASE_ADDRESS + R_PCH_GPIO_SC_IO_SEL2, PlatformCfioDataPtr->Io_Sel_SC1); 461 462 // 463 // GPIO_USE_SEL3 Register -> 1 = GPIO 0 = Native 464 // 465 IoWrite32 (GPIO_BASE_ADDRESS + R_PCH_GPIO_SC_USE_SEL3, PlatformCfioDataPtr->Use_Sel_SC2); 466 467 // 468 // Set GP_LVL3 Register 469 // 470 IoWrite32 (GPIO_BASE_ADDRESS + R_PCH_GPIO_SC_LVL3, PlatformCfioDataPtr->GP_Lvl_SC2); 471 472 // 473 // GP_IO_SEL3 Register -> 1 = Input 0 = Output if Native Mode don't care 474 // 475 IoWrite32 (GPIO_BASE_ADDRESS + R_PCH_GPIO_SC_IO_SEL3, PlatformCfioDataPtr->Io_Sel_SC2); 476 477 // 478 // SUS GPIO WELL -- IO base registers 479 // 480 481 // 482 // GPIO_USE_SEL Register -> 1 = GPIO 0 = Native 483 // 484 IoWrite32 (GPIO_BASE_ADDRESS + R_PCH_GPIO_SUS_USE_SEL, PlatformCfioDataPtr->Use_Sel_SS); 485 486 // 487 // Set GP_LVL Register 488 // 489 IoWrite32 (GPIO_BASE_ADDRESS + R_PCH_GPIO_SUS_LVL , PlatformCfioDataPtr->GP_Lvl_SS); 490 491 // 492 // GP_IO_SEL Register -> 1 = Input 0 = Output. If Native Mode don't care. 493 // 494 IoWrite32 (GPIO_BASE_ADDRESS + R_PCH_GPIO_SUS_IO_SEL, PlatformCfioDataPtr->Io_Sel_SS); 495 496 // 497 // GPIO Triger Positive Edge Enable Register. 498 // 499 IoWrite32 (GPIO_BASE_ADDRESS + R_PCH_GPIO_SUS_TPE, PlatformCfioDataPtr->TPE_SS); 500 501 // 502 // GPIO Trigger Negative Edge Enable Register. 503 // 504 IoWrite32 (GPIO_BASE_ADDRESS + R_PCH_GPIO_SUS_TNE, PlatformCfioDataPtr->TNE_SS); 505 506 // 507 // GPIO Trigger Status. 508 // 509 IoWrite32 (GPIO_BASE_ADDRESS + R_PCH_GPIO_SUS_TS, PlatformCfioDataPtr->TS_SS); 510 511 // 512 // GPIO Wake Enable. 513 // 514 IoWrite32 (GPIO_BASE_ADDRESS + R_PCH_GPIO_SUS_WAKE_EN, PlatformCfioDataPtr->WE_SS); 515 516 // 517 // Config SC/NC/SUS GPIO Pins 518 // 519 switch (PlatformInfoHob->BoardId) { 520 case BOARD_ID_MINNOW2: 521 case BOARD_ID_MINNOW2_TURBOT: 522 DEBUG ((EFI_D_INFO, "Start to config Minnow2 GPIO pins\n")); 523 InternalGpioConfig(GPIO_SCORE_OFFSET, sizeof(mMinnow2_GpioInitData_SC)/sizeof(mMinnow2_GpioInitData_SC[0]), (GPIO_CONF_PAD_INIT *) (UINTN) PlatformInfoHob->PlatformGpioData_SC); 524 InternalGpioConfig(GPIO_NCORE_OFFSET, sizeof(mMinnow2_GpioInitData_NC)/sizeof(mMinnow2_GpioInitData_NC[0]), (GPIO_CONF_PAD_INIT *) (UINTN) PlatformInfoHob->PlatformGpioData_NC); 525 InternalGpioConfig(GPIO_SSUS_OFFSET, sizeof(mMinnow2_GpioInitData_SUS)/sizeof(mMinnow2_GpioInitData_SUS[0]), (GPIO_CONF_PAD_INIT *) (UINTN) PlatformInfoHob->PlatformGpioData_SUS); 526 break; 527 default: 528 529 break; 530 } 531 532 // 533 // configure the CFIO Pnp settings 534 // 535 if (PlatformInfoHob->CfioEnabled) { 536 if (PlatformInfoHob->BoardId == BOARD_ID_MINNOW2 || PlatformInfoHob->BoardId == BOARD_ID_MINNOW2_TURBOT){ 537 InternalGpioConfig(GPIO_SCORE_OFFSET, sizeof(mNB_BB_FAB3_GpioInitData_SC_TRI)/sizeof(mNB_BB_FAB3_GpioInitData_SC_TRI[0]), (GPIO_CONF_PAD_INIT *) (UINTN)PlatformInfoHob->PlatformGpioData_SC_TRI); 538 } 539 } 540 #else 541 DEBUG ((EFI_D_INFO, "Skip MultiPlatformGpioProgram()...for SIMICS or HYB model\n")); 542 #endif 543 return EFI_SUCCESS; 544 } 545 546