/** @file Gpio setting for multiplatform.. Copyright (c) 2013 - 2014, Intel Corporation. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent **/ #include #include // //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; }