/** @file ;****************************************************************************** ;* Copyright (c) 2015 - 2016, Insyde Software Corp. All Rights Reserved. ;* ;* You may not reproduce, distribute, publish, display, perform, modify, adapt, ;* transmit, broadcast, present, recite, release, license or otherwise exploit ;* any part of this publication in any form, by any means, without the prior ;* written permission of Insyde Software Corporation. ;* ;****************************************************************************** */ #include /** This procedure will write GPIO register @param[in] RegType GPIO register type @param[in] Group GPIO group @param[in] DwNum Register number for current group (parameter applicable in accessing whole register). For group which has less then 32 pads per group DwNum must be 0. @param[in] RegAndMask Mask which will be AND'ed with register value @param[in] RegOrMask Mask which will be OR'ed with register value @retval EFI_SUCCESS The function completed successfully @retval EFI_UNSUPPORTED Feature is not supported for this group or pad **/ STATIC EFI_STATUS GpioWriteReg ( IN GPIO_REG RegType, IN GPIO_GROUP Group, IN UINT32 DwNum, IN UINT32 RegAndMask, IN UINT32 RegOrMask ) { UINT32 RegOffset; UINT32 GroupIndex; CONST GPIO_GROUP_INFO *GpioGroupInfo; UINT32 GpioGroupInfoLength; RegOffset = NO_REGISTER_FOR_PROPERTY; GroupIndex = GpioGetGroupIndexFromGroup (Group); GpioGroupInfo = GpioGetGroupInfoTable (&GpioGroupInfoLength); switch (RegType) { case GpioHostOwnershipRegister: RegOffset = GpioGroupInfo[GroupIndex].HostOwnOffset; break; case GpioGpeEnableRegister: RegOffset = GpioGroupInfo[GroupIndex].GpiGpeEnOffset; break; case GpioGpeStatusRegister: RegOffset = GpioGroupInfo[GroupIndex].GpiGpeStsOffset; break; case GpioSmiEnableRegister: RegOffset = GpioGroupInfo[GroupIndex].SmiEnOffset; break; case GpioSmiStatusRegister: RegOffset = GpioGroupInfo[GroupIndex].SmiStsOffset; break; case GpioNmiEnableRegister: RegOffset = GpioGroupInfo[GroupIndex].NmiEnOffset; break; case GpioPadConfigLockRegister: case GpioPadLockOutputRegister: ASSERT (FALSE); break; default: ASSERT (FALSE); break; } // // Check if selected register exists // if (RegOffset == NO_REGISTER_FOR_PROPERTY) { return EFI_UNSUPPORTED; } // // If there are more then 32 pads per group then certain // group information would be split into more then one DWord register. // RegOffset += DwNum * 0x4; MmioAndThenOr32 ( PCH_PCR_ADDRESS (GpioGroupInfo[GroupIndex].Community, RegOffset), RegAndMask, RegOrMask ); return EFI_SUCCESS; } /** This procedure is used to read SMI STS for a specified Pad @param[in] GpioPad GPIO pad @param[out] Data GPE STS data @retval EFI_SUCCESS The function completed successfully @retval EFI_INVALID_PARAMETER Invalid group or pad number **/ EFI_STATUS GpioGetGpiSmiSts ( IN GPIO_PAD GpioPad, OUT UINT32* Data ) { UINT32 Data32; UINT32 Mask; UINT32 GroupIndex; UINT32 PadNumber; CONST GPIO_GROUP_INFO *GpioGroupInfo; UINT32 GpioGroupInfoLength; *Data = 0xFFFFFFFF; GpioGroupInfo = GpioGetGroupInfoTable (&GpioGroupInfoLength); GroupIndex = GpioGetGroupIndexFromGpioPad (GpioPad); PadNumber = GpioGetPadNumberFromGpioPad (GpioPad); // // Check if group argument exceeds GPIO GROUP INFO array // if ((UINTN)GroupIndex >= GpioGroupInfoLength) { DEBUG ((DEBUG_ERROR, "GPIO ERROR: Group argument (%d) exceeds GPIO group range\n", GroupIndex)); ASSERT (FALSE); return EFI_INVALID_PARAMETER; } // // Check if legal pad number // if (PadNumber >= GpioGroupInfo[GroupIndex].PadPerGroup) { DEBUG ((DEBUG_ERROR, "GPIO ERROR: Pin number (%d) exceeds possible range for this group\n", PadNumber)); ASSERT (FALSE); return EFI_INVALID_PARAMETER; } // // Check if group has GPI GPE register // if (GpioGroupInfo[GroupIndex].SmiStsOffset == NO_REGISTER_FOR_PROPERTY) { return EFI_INVALID_PARAMETER; } // // Read GPI GPE Status bits // Data32 = MmioRead32( PCH_PCR_ADDRESS(GpioGroupInfo[GroupIndex].Community, GpioGroupInfo[GroupIndex].SmiStsOffset) ); Mask = (UINT32)(BIT0 << PadNumber); Data32 = (Data32 & Mask) >> PadNumber; *Data = Data32; return EFI_SUCCESS; } EFI_STATUS GpioEnableGpiSmi ( IN GPIO_PAD GpioPad, IN BOOLEAN Enable ) { GPIO_CONFIG GpioPadConfig; EFI_STATUS Status; UINT32 Data32; UINT32 PadNumber; GpioGetPadConfig (GpioPad, &GpioPadConfig); // // Set GPI_SMI_EN // Data32 = Enable ? 1 : 0; PadNumber = GpioGetPadNumberFromGpioPad (GpioPad); Status = GpioWriteReg ( GpioSmiEnableRegister, GpioGetGroupFromGpioPad (GpioPad), GPIO_GET_DW_NUM (PadNumber), ~(1 << GPIO_GET_PAD_POSITION (PadNumber)), Data32 << GPIO_GET_PAD_POSITION (PadNumber) ); ASSERT_EFI_ERROR (Status); // // Set GPIROUTSMI // Data32 = Enable ? B_GPIO_PCR_RX_SMI_ROUTE : 0; GpioWritePadCfgReg ( GpioPad, 0, (UINT32)~B_GPIO_PCR_RX_SMI_ROUTE, Data32 ); return EFI_SUCCESS; }