/** @file Gpio setting for multiplatform.. Copyright (c) 2013 - 2014, Intel Corporation. All rights reserved.<BR> This program and the accompanying materials are licensed and made available under the terms and conditions of the BSD License that accompanies this distribution. The full text of the license may be found at http://opensource.org/licenses/bsd-license.php. THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. **/ #include <BoardGpios.h> #include <Guid/SetupVariable.h> // //AlpineValley platform ocde begin // #define AV_SC_REG_GPIOS_MUXES_SEL0 0x48 #define AV_SC_REG_GPIOS_MUXES_SEL1 0x4C #define AV_SC_REG_GPIOS_MUXES_SEL2 0x50 #define AV_SC_REG_GPIOS_MUXES_EN0 0x54 #define AV_SC_REG_GPIOS_MUXES_EN1 0x58 #define AV_SC_REG_GPIOS_MUXES_EN2 0x5C // //AlpineValley platform code end // EFI_GUID gPeiSmbusPpiGuid = EFI_PEI_SMBUS_PPI_GUID; /** @param None @retval EFI_SUCCESS The function completed successfully. **/ EFI_STATUS ConfigurePlatformSysCtrlGpio ( IN EFI_PEI_SERVICES **PeiServices, IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor, IN VOID *SmbusPpi ) { // //AlpineValley platform code begin // // Initialize GPIO Settings: // UINT32 Status; EFI_PLATFORM_INFO_HOB *PlatformInfoHob; DEBUG ((EFI_D_INFO, "ConfigurePlatformSysCtrlGpio()...\n")); // // Obtain Platform Info from HOB. // Status = GetPlatformInfoHob ((const EFI_PEI_SERVICES **)PeiServices, &PlatformInfoHob); ASSERT_EFI_ERROR (Status); // // The GPIO settings are dependent upon the platform. Obtain the Board ID through // the EC to determine the current platform. // DEBUG ((EFI_D_INFO, "Platform Flavor | Board ID = 0x%X | 0x%X\n", PlatformInfoHob->PlatformFlavor, PlatformInfoHob->BoardId)); Status = (**PeiServices).LocatePpi ( (const EFI_PEI_SERVICES **)PeiServices, &gPeiSmbusPpiGuid, 0, NULL, (void **)&SmbusPpi ); ASSERT_EFI_ERROR (Status); // // Select/modify the GPIO initialization data based on the Board ID. // switch (PlatformInfoHob->BoardId) { default: Status = EFI_SUCCESS; // // Do nothing for other RVP boards. // break; } return Status; } static EFI_PEI_NOTIFY_DESCRIPTOR mNotifyList[] = { { EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK| EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST, &gEfiPeiSmbusPpiGuid, ConfigurePlatformSysCtrlGpio } }; EFI_STATUS InstallPlatformSysCtrlGPIONotify ( IN CONST EFI_PEI_SERVICES **PeiServices ) { EFI_STATUS Status; DEBUG ((EFI_D_INFO, "InstallPlatformSysCtrlGPIONotify()...\n")); Status = (*PeiServices)->NotifyPpi(PeiServices, &mNotifyList[0]); ASSERT_EFI_ERROR (Status); return EFI_SUCCESS; } #define V_PCH_ILB_IRQE_UARTIRQEN_IRQ3 BIT3 // UART IRQ3 Enable /** Returns the Correct GPIO table for Mobile/Desktop respectively. Before call it, make sure PlatformInfoHob->BoardId&PlatformFlavor is get correctly. @param PeiServices General purpose services available to every PEIM. @param PlatformInfoHob PlatformInfoHob pointer with PlatformFlavor specified. @param BoardId BoardId ID as determined through the EC. @retval EFI_SUCCESS The function completed successfully. @retval EFI_DEVICE_ERROR KSC fails to respond. **/ EFI_STATUS MultiPlatformGpioTableInit ( IN CONST EFI_PEI_SERVICES **PeiServices, IN EFI_PLATFORM_INFO_HOB *PlatformInfoHob ) { EFI_STATUS Status; EFI_PEI_READ_ONLY_VARIABLE2_PPI *PeiReadOnlyVarPpi; UINTN VarSize; SYSTEM_CONFIGURATION SystemConfiguration; DEBUG ((EFI_D_INFO, "MultiPlatformGpioTableInit()...\n")); // // Select/modify the GPIO initialization data based on the Board ID. // switch (PlatformInfoHob->BoardId) { case BOARD_ID_MINNOW2: // Minnow2 case BOARD_ID_MINNOW2_TURBOT: Status = (**PeiServices).LocatePpi ( PeiServices, &gEfiPeiReadOnlyVariable2PpiGuid, 0, NULL, (void **)&PeiReadOnlyVarPpi ); ASSERT_EFI_ERROR (Status); VarSize = sizeof (SYSTEM_CONFIGURATION); Status = PeiReadOnlyVarPpi->GetVariable ( PeiReadOnlyVarPpi, PLATFORM_SETUP_VARIABLE_NAME, &gEfiSetupVariableGuid, NULL, &VarSize, &SystemConfiguration ); if (SystemConfiguration.GpioWakeCapability == 1) { PlatformInfoHob->PlatformCfioData = (EFI_PHYSICAL_ADDRESS)(UINTN) &mMinnow2CfioInitData2; } else { PlatformInfoHob->PlatformCfioData = (EFI_PHYSICAL_ADDRESS)(UINTN) &mMinnow2CfioInitData; } PlatformInfoHob->PlatformGpioData_NC = (EFI_PHYSICAL_ADDRESS)(UINTN) &mMinnow2_GpioInitData_NC[0]; PlatformInfoHob->PlatformGpioData_SC = (EFI_PHYSICAL_ADDRESS)(UINTN) &mMinnow2_GpioInitData_SC[0]; PlatformInfoHob->PlatformGpioData_SUS = (EFI_PHYSICAL_ADDRESS)(UINTN) &mMinnow2_GpioInitData_SUS[0]; break; } return EFI_SUCCESS; } UINT32 GPIORead32 ( IN UINT32 mmio_conf ) { UINT32 conf_val; UINT32 i; conf_val = MmioRead32(mmio_conf); for(i=0;i<5;i++){ if(conf_val == 0xffffffff) conf_val = MmioRead32(mmio_conf); else break; } return conf_val; } /** Set GPIO CONF0 and PAD_VAL registers for NC/SC/SUS GPIO clusters @param Gpio_Mmio_Offset GPIO_SCORE_OFFSET or GPIO_NCORE_OFFSET or GPIO_SSUS_OFFSET. @param Gpio_Pin_Num Pin numbers to config for each GPIO clusters. @param Gpio_Conf_Data GPIO_CONF_PAD_INIT data array for each GPIO clusters. **/ VOID InternalGpioConfig ( IN UINT32 Gpio_Mmio_Offset, IN UINT32 Gpio_Pin_Num, GPIO_CONF_PAD_INIT* Gpio_Conf_Data ) { UINT32 index; UINT32 mmio_conf0; UINT32 mmio_padval; PAD_CONF0 conf0_val; PAD_VAL pad_val; // // GPIO WELL -- Memory base registers // // A0 BIOS Spec doesn't mention it although X0 does. comment out now. // GPIO write 0x01001002 to IOBASE + Gpio_Mmio_Offset + 0x0900 // for(index=0; index < Gpio_Pin_Num; index++) { // // Calculate the MMIO Address for specific GPIO pin CONF0 register pointed by index. // mmio_conf0 = IO_BASE_ADDRESS + Gpio_Mmio_Offset + R_PCH_CFIO_PAD_CONF0 + Gpio_Conf_Data[index].offset * 16; mmio_padval= IO_BASE_ADDRESS + Gpio_Mmio_Offset + R_PCH_CFIO_PAD_VAL + Gpio_Conf_Data[index].offset * 16; #ifdef EFI_DEBUG DEBUG ((EFI_D_INFO, "%s, ", Gpio_Conf_Data[index].pad_name)); #endif DEBUG ((EFI_D_INFO, "Usage = %d, Func# = %d, IntType = %d, Pull Up/Down = %d, MMIO Base = 0x%08x, ", Gpio_Conf_Data[index].usage, Gpio_Conf_Data[index].func, Gpio_Conf_Data[index].int_type, Gpio_Conf_Data[index].pull, mmio_conf0)); // // Step 1: PadVal Programming. // pad_val.dw = GPIORead32(mmio_padval); // // Config PAD_VAL only for GPIO (Non-Native) Pin // if(Native != Gpio_Conf_Data[index].usage) { pad_val.dw &= ~0x6; // Clear bits 1:2 pad_val.dw |= (Gpio_Conf_Data[index].usage & 0x6); // Set bits 1:2 according to PadVal // // set GPO default value // if(Gpio_Conf_Data[index].usage == GPO && Gpio_Conf_Data[index].gpod4 != NA) { pad_val.r.pad_val = Gpio_Conf_Data[index].gpod4; } } DEBUG ((EFI_D_INFO, "Set PAD_VAL = 0x%08x, ", pad_val.dw)); MmioWrite32(mmio_padval, pad_val.dw); // // Step 2: CONF0 Programming // Read GPIO default CONF0 value, which is assumed to be default value after reset. // conf0_val.dw = GPIORead32(mmio_conf0); // // Set Function # // conf0_val.r.Func_Pin_Mux = Gpio_Conf_Data[index].func; if(GPO == Gpio_Conf_Data[index].usage) { // // If used as GPO, then internal pull need to be disabled. // conf0_val.r.Pull_assign = 0; // Non-pull } else { // // Set PullUp / PullDown // if(P_20K_H == Gpio_Conf_Data[index].pull) { conf0_val.r.Pull_assign = 0x1; // PullUp conf0_val.r.Pull_strength = 0x2;// 20K } else if(P_20K_L == Gpio_Conf_Data[index].pull) { conf0_val.r.Pull_assign = 0x2; // PullDown conf0_val.r.Pull_strength = 0x2;// 20K } else if(P_10K_H == Gpio_Conf_Data[index].pull) { conf0_val.r.Pull_assign = 0x1; // PullUp conf0_val.r.Pull_strength = 0x1;// 10K } else if(P_10K_L == Gpio_Conf_Data[index].pull) { conf0_val.r.Pull_assign = 0x2; // PullDown conf0_val.r.Pull_strength = 0x1;// 10K } else if(P_2K_H == Gpio_Conf_Data[index].pull) { conf0_val.r.Pull_assign = 0x1; // PullUp conf0_val.r.Pull_strength = 0x0;// 2K } else if(P_2K_L == Gpio_Conf_Data[index].pull) { conf0_val.r.Pull_assign = 0x2; // PullDown conf0_val.r.Pull_strength = 0x0;// 2K } else if(P_NONE == Gpio_Conf_Data[index].pull) { conf0_val.r.Pull_assign = 0; // Non-pull } else { ASSERT(FALSE); // Invalid value } } // // Set INT Trigger Type // conf0_val.dw &= ~0x0f000000; // Clear bits 27:24 // // Set INT Trigger Type // if(TRIG_ == Gpio_Conf_Data[index].int_type) { // // Interrupt not capable, clear bits 27:24 // } else { conf0_val.dw |= (Gpio_Conf_Data[index].int_type & 0x0f)<<24; } DEBUG ((EFI_D_INFO, "Set CONF0 = 0x%08x\n", conf0_val.dw)); // // Write back the targeted GPIO config value according to platform (board) GPIO setting. // MmioWrite32 (mmio_conf0, conf0_val.dw); } // // A0 BIOS Spec doesn't mention it although X0 does. comment out now. // GPIO SCORE write 0x01001002 to IOBASE + 0x0900 // } /** Returns the Correct GPIO table for Mobile/Desktop respectively. Before call it, make sure PlatformInfoHob->BoardId&PlatformFlavor is get correctly. @param PeiServices General purpose services available to every PEIM. @param PlatformInfoHob PlatformInfoHob pointer with PlatformFlavor specified. @param BoardId BoardId ID as determined through the EC. @retval EFI_SUCCESS The function completed successfully. @retval EFI_DEVICE_ERROR KSC fails to respond. **/ EFI_STATUS MultiPlatformGpioProgram ( IN CONST EFI_PEI_SERVICES **PeiServices, IN EFI_PLATFORM_INFO_HOB *PlatformInfoHob ) { #if !_SIMIC_ CFIO_INIT_STRUCT* PlatformCfioDataPtr; PlatformCfioDataPtr = (CFIO_INIT_STRUCT *) (UINTN) PlatformInfoHob->PlatformCfioData; DEBUG ((EFI_D_INFO, "MultiPlatformGpioProgram()...\n")); // // SCORE GPIO WELL -- IO base registers // // // GPIO_USE_SEL Register -> 1 = GPIO 0 = Native // IoWrite32 (GPIO_BASE_ADDRESS + R_PCH_GPIO_SC_USE_SEL, PlatformCfioDataPtr->Use_Sel_SC0); // // Set GP_LVL Register // IoWrite32 (GPIO_BASE_ADDRESS + R_PCH_GPIO_SC_LVL , PlatformCfioDataPtr->GP_Lvl_SC0); // // GP_IO_SEL Register -> 1 = Input 0 = Output. If Native Mode don't care // IoWrite32 (GPIO_BASE_ADDRESS + R_PCH_GPIO_SC_IO_SEL, PlatformCfioDataPtr->Io_Sel_SC0); // // GPIO Triger Positive Edge Enable Register // IoWrite32 (GPIO_BASE_ADDRESS + R_PCH_GPIO_SC_TPE, PlatformCfioDataPtr->TPE_SC0); // // GPIO Trigger Negative Edge Enable Register // IoWrite32 (GPIO_BASE_ADDRESS + R_PCH_GPIO_SC_TNE, PlatformCfioDataPtr->TNE_SC0); // // GPIO Trigger Status // IoWrite32 (GPIO_BASE_ADDRESS + R_PCH_GPIO_SC_TS, PlatformCfioDataPtr->TS_SC0); // // GPIO_USE_SEL2 Register -> 1 = GPIO 0 = Native // IoWrite32 (GPIO_BASE_ADDRESS + R_PCH_GPIO_SC_USE_SEL2, PlatformCfioDataPtr->Use_Sel_SC1); // // Set GP_LVL2 Register // IoWrite32 (GPIO_BASE_ADDRESS + R_PCH_GPIO_SC_LVL2, PlatformCfioDataPtr->GP_Lvl_SC1); // // GP_IO_SEL2 Register -> 1 = Input 0 = Output. If Native Mode don't care // IoWrite32 (GPIO_BASE_ADDRESS + R_PCH_GPIO_SC_IO_SEL2, PlatformCfioDataPtr->Io_Sel_SC1); // // GPIO_USE_SEL3 Register -> 1 = GPIO 0 = Native // IoWrite32 (GPIO_BASE_ADDRESS + R_PCH_GPIO_SC_USE_SEL3, PlatformCfioDataPtr->Use_Sel_SC2); // // Set GP_LVL3 Register // IoWrite32 (GPIO_BASE_ADDRESS + R_PCH_GPIO_SC_LVL3, PlatformCfioDataPtr->GP_Lvl_SC2); // // GP_IO_SEL3 Register -> 1 = Input 0 = Output if Native Mode don't care // IoWrite32 (GPIO_BASE_ADDRESS + R_PCH_GPIO_SC_IO_SEL3, PlatformCfioDataPtr->Io_Sel_SC2); // // SUS GPIO WELL -- IO base registers // // // GPIO_USE_SEL Register -> 1 = GPIO 0 = Native // IoWrite32 (GPIO_BASE_ADDRESS + R_PCH_GPIO_SUS_USE_SEL, PlatformCfioDataPtr->Use_Sel_SS); // // Set GP_LVL Register // IoWrite32 (GPIO_BASE_ADDRESS + R_PCH_GPIO_SUS_LVL , PlatformCfioDataPtr->GP_Lvl_SS); // // GP_IO_SEL Register -> 1 = Input 0 = Output. If Native Mode don't care. // IoWrite32 (GPIO_BASE_ADDRESS + R_PCH_GPIO_SUS_IO_SEL, PlatformCfioDataPtr->Io_Sel_SS); // // GPIO Triger Positive Edge Enable Register. // IoWrite32 (GPIO_BASE_ADDRESS + R_PCH_GPIO_SUS_TPE, PlatformCfioDataPtr->TPE_SS); // // GPIO Trigger Negative Edge Enable Register. // IoWrite32 (GPIO_BASE_ADDRESS + R_PCH_GPIO_SUS_TNE, PlatformCfioDataPtr->TNE_SS); // // GPIO Trigger Status. // IoWrite32 (GPIO_BASE_ADDRESS + R_PCH_GPIO_SUS_TS, PlatformCfioDataPtr->TS_SS); // // GPIO Wake Enable. // IoWrite32 (GPIO_BASE_ADDRESS + R_PCH_GPIO_SUS_WAKE_EN, PlatformCfioDataPtr->WE_SS); // // Config SC/NC/SUS GPIO Pins // switch (PlatformInfoHob->BoardId) { case BOARD_ID_MINNOW2: case BOARD_ID_MINNOW2_TURBOT: DEBUG ((EFI_D_INFO, "Start to config Minnow2 GPIO pins\n")); InternalGpioConfig(GPIO_SCORE_OFFSET, sizeof(mMinnow2_GpioInitData_SC)/sizeof(mMinnow2_GpioInitData_SC[0]), (GPIO_CONF_PAD_INIT *) (UINTN) PlatformInfoHob->PlatformGpioData_SC); InternalGpioConfig(GPIO_NCORE_OFFSET, sizeof(mMinnow2_GpioInitData_NC)/sizeof(mMinnow2_GpioInitData_NC[0]), (GPIO_CONF_PAD_INIT *) (UINTN) PlatformInfoHob->PlatformGpioData_NC); InternalGpioConfig(GPIO_SSUS_OFFSET, sizeof(mMinnow2_GpioInitData_SUS)/sizeof(mMinnow2_GpioInitData_SUS[0]), (GPIO_CONF_PAD_INIT *) (UINTN) PlatformInfoHob->PlatformGpioData_SUS); break; default: break; } // // configure the CFIO Pnp settings // if (PlatformInfoHob->CfioEnabled) { if (PlatformInfoHob->BoardId == BOARD_ID_MINNOW2 || PlatformInfoHob->BoardId == BOARD_ID_MINNOW2_TURBOT){ 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); } } #else DEBUG ((EFI_D_INFO, "Skip MultiPlatformGpioProgram()...for SIMICS or HYB model\n")); #endif return EFI_SUCCESS; }