/** @file
  This file contains VER2 specific GPIO information

  Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
  SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#include <Uefi/UefiBaseType.h>
#include <Library/DebugLib.h>
#include <Library/PchInfoLib.h>
#include <Library/GpioLib.h>
#include <Library/GpioNativeLib.h>
#include <Library/GpioPrivateLib.h>
#include <Library/GpioHelpersLib.h>
#include <Library/BaseMemoryLib.h>
#include <Library/CpuRegbarAccessLib.h>
#include <Register/GpioRegsVer2.h>
#include <Register/PmcRegsVer2.h>
#include <Register/PchPcrRegs.h>
#include <Pins/GpioPinsVer2Lp.h>

GLOBAL_REMOVE_IF_UNREFERENCED GPIO_GROUP_INFO mPchLpGpioGroupInfo[] = {
  {PID_GPIOCOM0, R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_B_PAD_OWN,  R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_B_HOSTSW_OWN,  R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_B_GPI_IS, R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_B_GPI_IE, R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_B_GPI_GPE_STS, R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_B_GPI_GPE_EN, R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_B_SMI_STS, R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_B_SMI_EN, R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_B_NMI_STS, R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_B_NMI_EN, R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_B_PADCFGLOCK,  R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_B_PADCFGLOCKTX,   R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_B_PADCFG_OFFSET,  GPIO_VER2_PCH_LP_GPIO_GPP_B_PAD_MAX}, //TGL PCH-LP GPP_B
  {PID_GPIOCOM0, NO_REGISTER_FOR_PROPERTY,                   NO_REGISTER_FOR_PROPERTY,                      NO_REGISTER_FOR_PROPERTY,                 NO_REGISTER_FOR_PROPERTY,                 NO_REGISTER_FOR_PROPERTY,                      NO_REGISTER_FOR_PROPERTY,                     NO_REGISTER_FOR_PROPERTY,            NO_REGISTER_FOR_PROPERTY,           NO_REGISTER_FOR_PROPERTY,            NO_REGISTER_FOR_PROPERTY,           NO_REGISTER_FOR_PROPERTY,                      NO_REGISTER_FOR_PROPERTY,                         NO_REGISTER_FOR_PROPERTY,                         0},
  {PID_GPIOCOM0, R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_A_PAD_OWN,  R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_A_HOSTSW_OWN,  R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_A_GPI_IS, R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_A_GPI_IE, R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_A_GPI_GPE_STS, R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_A_GPI_GPE_EN, NO_REGISTER_FOR_PROPERTY,            NO_REGISTER_FOR_PROPERTY,           NO_REGISTER_FOR_PROPERTY,            NO_REGISTER_FOR_PROPERTY,           R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_A_PADCFGLOCK,  R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_A_PADCFGLOCKTX,   R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_A_PADCFG_OFFSET,  GPIO_VER2_PCH_LP_GPIO_GPP_A_PAD_MAX}, //TGL PCH-LP GPP_A
  {PID_GPIOCOM5, R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_R_PAD_OWN,  R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_R_HOSTSW_OWN,  R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_R_GPI_IS, R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_R_GPI_IE, R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_R_GPI_GPE_STS, R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_R_GPI_GPE_EN, NO_REGISTER_FOR_PROPERTY,            NO_REGISTER_FOR_PROPERTY,           NO_REGISTER_FOR_PROPERTY,            NO_REGISTER_FOR_PROPERTY,           R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_R_PADCFGLOCK,  R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_R_PADCFGLOCKTX,   R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_R_PADCFG_OFFSET,  GPIO_VER2_PCH_LP_GPIO_GPP_R_PAD_MAX}, //TGL PCH-LP GPP_R
  {PID_GPIOCOM5, NO_REGISTER_FOR_PROPERTY,                   NO_REGISTER_FOR_PROPERTY,                      NO_REGISTER_FOR_PROPERTY,                 NO_REGISTER_FOR_PROPERTY,                 NO_REGISTER_FOR_PROPERTY,                      NO_REGISTER_FOR_PROPERTY,                     NO_REGISTER_FOR_PROPERTY,            NO_REGISTER_FOR_PROPERTY,           NO_REGISTER_FOR_PROPERTY,            NO_REGISTER_FOR_PROPERTY,           NO_REGISTER_FOR_PROPERTY,                      NO_REGISTER_FOR_PROPERTY,                         NO_REGISTER_FOR_PROPERTY,                         0},
  {PID_GPIOCOM2, R_GPIO_VER2_PCH_LP_GPIO_PCR_GPD_PAD_OWN,    R_GPIO_VER2_PCH_LP_GPIO_PCR_GPD_HOSTSW_OWN,    R_GPIO_VER2_PCH_LP_GPIO_PCR_GPD_GPI_IS,   R_GPIO_VER2_PCH_LP_GPIO_PCR_GPD_GPI_IE,   R_GPIO_VER2_PCH_LP_GPIO_PCR_GPD_GPI_GPE_STS,   R_GPIO_VER2_PCH_LP_GPIO_PCR_GPD_GPI_GPE_EN,   NO_REGISTER_FOR_PROPERTY,            NO_REGISTER_FOR_PROPERTY,           NO_REGISTER_FOR_PROPERTY,            NO_REGISTER_FOR_PROPERTY,           R_GPIO_VER2_PCH_LP_GPIO_PCR_GPD_PADCFGLOCK,    R_GPIO_VER2_PCH_LP_GPIO_PCR_GPD_PADCFGLOCKTX,     R_GPIO_VER2_PCH_LP_GPIO_PCR_GPD_PADCFG_OFFSET,    GPIO_VER2_PCH_LP_GPIO_GPD_PAD_MAX},   //TGL PCH-LP GPD
  {PID_GPIOCOM1, R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_S_PAD_OWN,  R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_S_HOSTSW_OWN,  R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_S_GPI_IS, R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_S_GPI_IE, R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_S_GPI_GPE_STS, R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_S_GPI_GPE_EN, NO_REGISTER_FOR_PROPERTY,            NO_REGISTER_FOR_PROPERTY,           NO_REGISTER_FOR_PROPERTY,            NO_REGISTER_FOR_PROPERTY,           R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_S_PADCFGLOCK,  R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_S_PADCFGLOCKTX,   R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_S_PADCFG_OFFSET,  GPIO_VER2_PCH_LP_GPIO_GPP_S_PAD_MAX}, //TGL PCH-LP GPP_S
  {PID_GPIOCOM1, R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_H_PAD_OWN,  R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_H_HOSTSW_OWN,  R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_H_GPI_IS, R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_H_GPI_IE, R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_H_GPI_GPE_STS, R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_H_GPI_GPE_EN, NO_REGISTER_FOR_PROPERTY,            NO_REGISTER_FOR_PROPERTY,           NO_REGISTER_FOR_PROPERTY,            NO_REGISTER_FOR_PROPERTY,           R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_H_PADCFGLOCK,  R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_H_PADCFGLOCKTX,   R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_H_PADCFG_OFFSET,  GPIO_VER2_PCH_LP_GPIO_GPP_H_PAD_MAX}, //TGL PCH-LP GPP_H
  {PID_GPIOCOM1, R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_D_PAD_OWN,  R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_D_HOSTSW_OWN,  R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_D_GPI_IS, R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_D_GPI_IE, R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_D_GPI_GPE_STS, R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_D_GPI_GPE_EN, R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_D_SMI_STS, R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_D_SMI_EN, R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_D_NMI_STS, R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_D_NMI_EN, R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_D_PADCFGLOCK,  R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_D_PADCFGLOCKTX,   R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_D_PADCFG_OFFSET,  GPIO_VER2_PCH_LP_GPIO_GPP_D_PAD_MAX}, //TGL PCH-LP GPP_D
  {PID_GPIOCOM1, NO_REGISTER_FOR_PROPERTY,                   NO_REGISTER_FOR_PROPERTY,                      NO_REGISTER_FOR_PROPERTY,                 NO_REGISTER_FOR_PROPERTY,                 NO_REGISTER_FOR_PROPERTY,                      NO_REGISTER_FOR_PROPERTY,                     NO_REGISTER_FOR_PROPERTY,            NO_REGISTER_FOR_PROPERTY,           NO_REGISTER_FOR_PROPERTY,            NO_REGISTER_FOR_PROPERTY,           NO_REGISTER_FOR_PROPERTY,                      NO_REGISTER_FOR_PROPERTY,                         NO_REGISTER_FOR_PROPERTY,                         0},
  {PID_GPIOCOM1, NO_REGISTER_FOR_PROPERTY,                   NO_REGISTER_FOR_PROPERTY,                      NO_REGISTER_FOR_PROPERTY,                 NO_REGISTER_FOR_PROPERTY,                 NO_REGISTER_FOR_PROPERTY,                      NO_REGISTER_FOR_PROPERTY,                     NO_REGISTER_FOR_PROPERTY,            NO_REGISTER_FOR_PROPERTY,           NO_REGISTER_FOR_PROPERTY,            NO_REGISTER_FOR_PROPERTY,           NO_REGISTER_FOR_PROPERTY,                      NO_REGISTER_FOR_PROPERTY,                         NO_REGISTER_FOR_PROPERTY,                         0},
  {PID_GPIOCOM4, R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_C_PAD_OWN,  R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_C_HOSTSW_OWN,  R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_C_GPI_IS, R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_C_GPI_IE, R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_C_GPI_GPE_STS, R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_C_GPI_GPE_EN, R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_C_SMI_STS, R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_C_SMI_EN, R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_C_NMI_STS, R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_C_NMI_EN, R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_C_PADCFGLOCK,  R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_C_PADCFGLOCKTX,   R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_C_PADCFG_OFFSET,  GPIO_VER2_PCH_LP_GPIO_GPP_C_PAD_MAX}, //TGL PCH-LP GPP_C
  {PID_GPIOCOM4, R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_F_PAD_OWN,  R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_F_HOSTSW_OWN,  R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_F_GPI_IS, R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_F_GPI_IE, R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_F_GPI_GPE_STS, R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_F_GPI_GPE_EN, NO_REGISTER_FOR_PROPERTY,            NO_REGISTER_FOR_PROPERTY,           NO_REGISTER_FOR_PROPERTY,            NO_REGISTER_FOR_PROPERTY,           R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_F_PADCFGLOCK,  R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_F_PADCFGLOCKTX,   R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_F_PADCFG_OFFSET,  GPIO_VER2_PCH_LP_GPIO_GPP_F_PAD_MAX}, //TGL PCH-LP GPP_F
  {PID_GPIOCOM4, NO_REGISTER_FOR_PROPERTY,                   NO_REGISTER_FOR_PROPERTY,                      NO_REGISTER_FOR_PROPERTY,                 NO_REGISTER_FOR_PROPERTY,                 NO_REGISTER_FOR_PROPERTY,                      NO_REGISTER_FOR_PROPERTY,                     NO_REGISTER_FOR_PROPERTY,            NO_REGISTER_FOR_PROPERTY,           NO_REGISTER_FOR_PROPERTY,            NO_REGISTER_FOR_PROPERTY,           NO_REGISTER_FOR_PROPERTY,                      NO_REGISTER_FOR_PROPERTY,                         NO_REGISTER_FOR_PROPERTY,                         0},
  {PID_GPIOCOM4, R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_E_PAD_OWN,  R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_E_HOSTSW_OWN,  R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_E_GPI_IS, R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_E_GPI_IE, R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_E_GPI_GPE_STS, R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_E_GPI_GPE_EN, R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_E_SMI_STS, R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_E_SMI_EN, R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_E_NMI_STS, R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_E_NMI_EN, R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_E_PADCFGLOCK,  R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_E_PADCFGLOCKTX,   R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_E_PADCFG_OFFSET,  GPIO_VER2_PCH_LP_GPIO_GPP_E_PAD_MAX}, //TGL PCH-LP GPP_E
  {PID_GPIOCOM4, NO_REGISTER_FOR_PROPERTY,                   NO_REGISTER_FOR_PROPERTY,                      NO_REGISTER_FOR_PROPERTY,                 NO_REGISTER_FOR_PROPERTY,                 NO_REGISTER_FOR_PROPERTY,                      NO_REGISTER_FOR_PROPERTY,                     NO_REGISTER_FOR_PROPERTY,            NO_REGISTER_FOR_PROPERTY,           NO_REGISTER_FOR_PROPERTY,            NO_REGISTER_FOR_PROPERTY,           NO_REGISTER_FOR_PROPERTY,                      NO_REGISTER_FOR_PROPERTY,                         NO_REGISTER_FOR_PROPERTY,                         0},
  {PID_GPIOCOM3, NO_REGISTER_FOR_PROPERTY,                   NO_REGISTER_FOR_PROPERTY,                      NO_REGISTER_FOR_PROPERTY,                 NO_REGISTER_FOR_PROPERTY,                 NO_REGISTER_FOR_PROPERTY,                      NO_REGISTER_FOR_PROPERTY,                     NO_REGISTER_FOR_PROPERTY,            NO_REGISTER_FOR_PROPERTY,           NO_REGISTER_FOR_PROPERTY,            NO_REGISTER_FOR_PROPERTY,           NO_REGISTER_FOR_PROPERTY,                      NO_REGISTER_FOR_PROPERTY,                         NO_REGISTER_FOR_PROPERTY,                         0},
  {PID_GPIOCOM3, NO_REGISTER_FOR_PROPERTY,                   NO_REGISTER_FOR_PROPERTY,                      NO_REGISTER_FOR_PROPERTY,                 NO_REGISTER_FOR_PROPERTY,                 NO_REGISTER_FOR_PROPERTY,                      NO_REGISTER_FOR_PROPERTY,                     NO_REGISTER_FOR_PROPERTY,            NO_REGISTER_FOR_PROPERTY,           NO_REGISTER_FOR_PROPERTY,            NO_REGISTER_FOR_PROPERTY,           NO_REGISTER_FOR_PROPERTY,                      NO_REGISTER_FOR_PROPERTY,                         NO_REGISTER_FOR_PROPERTY,                         0}
};

/**
  This procedure will retrieve address and length of GPIO info table

  @param[out]  GpioGroupInfoTableLength   Length of GPIO group table

  @retval Pointer to GPIO group table

**/
CONST GPIO_GROUP_INFO*
GpioGetGroupInfoTable (
  OUT UINT32              *GpioGroupInfoTableLength
  )
{
  *GpioGroupInfoTableLength = ARRAY_SIZE (mPchLpGpioGroupInfo);
  return mPchLpGpioGroupInfo;
}

/**
  Get GPIO Chipset ID specific to PCH generation and series
**/
UINT32
GpioGetThisChipsetId (
  VOID
  )
{
  return GPIO_VER2_LP_CHIPSET_ID;
}

/**
  This internal procedure will check if group is within DeepSleepWell.

  @param[in]  Group               GPIO Group

  @retval GroupWell               TRUE:  This is DSW Group
                                  FALSE: This is not DSW Group
**/
BOOLEAN
GpioIsDswGroup (
  IN  GPIO_GROUP         Group
  )
{
  if (Group == GPIO_VER2_LP_GROUP_GPD) {
    return TRUE;
  } else {
    return FALSE;
  }
}

GLOBAL_REMOVE_IF_UNREFERENCED GPIO_GROUP_TO_GPE_MAPPING mPchLpGpioGroupToGpeMapping[] = {
    {GPIO_VER2_LP_GROUP_GPP_B,   0, V_TGL_PCH_LP_PMC_PWRM_GPIO_CFG_GPP_B},
    {GPIO_VER2_LP_GROUP_GPP_A,   0, V_TGL_PCH_LP_PMC_PWRM_GPIO_CFG_GPP_A},
    {GPIO_VER2_LP_GROUP_GPP_R,   0, V_TGL_PCH_LP_PMC_PWRM_GPIO_CFG_GPP_R},
    {GPIO_VER2_LP_GROUP_GPD,     0, V_TGL_PCH_LP_PMC_PWRM_GPIO_CFG_GPD  },
    {GPIO_VER2_LP_GROUP_GPP_S,   0, V_TGL_PCH_LP_PMC_PWRM_GPIO_CFG_GPP_S},
    {GPIO_VER2_LP_GROUP_GPP_H,   0, V_TGL_PCH_LP_PMC_PWRM_GPIO_CFG_GPP_H},
    {GPIO_VER2_LP_GROUP_GPP_D,   0, V_TGL_PCH_LP_PMC_PWRM_GPIO_CFG_GPP_D},
    {GPIO_VER2_LP_GROUP_GPP_C,   0, V_TGL_PCH_LP_PMC_PWRM_GPIO_CFG_GPP_C},
    {GPIO_VER2_LP_GROUP_GPP_F,   0, V_TGL_PCH_LP_PMC_PWRM_GPIO_CFG_GPP_F},
    {GPIO_VER2_LP_GROUP_GPP_E,   0, V_TGL_PCH_LP_PMC_PWRM_GPIO_CFG_GPP_E}
};

/**
  Get information for GPIO Group required to program GPIO and PMC for desired 1-Tier GPE mapping

  @param[out] GpioGroupToGpeMapping        Table with GPIO Group to GPE mapping
  @param[out] GpioGroupToGpeMappingLength  GPIO Group to GPE mapping table length
**/
VOID
GpioGetGroupToGpeMapping (
  OUT GPIO_GROUP_TO_GPE_MAPPING  **GpioGroupToGpeMapping,
  OUT UINT32                     *GpioGroupToGpeMappingLength
  )
{
  *GpioGroupToGpeMapping = mPchLpGpioGroupToGpeMapping;
  *GpioGroupToGpeMappingLength = ARRAY_SIZE (mPchLpGpioGroupToGpeMapping);
}

/**
  Check if 0x13 opcode supported for writing to GPIO lock unlock register

  @retval TRUE                It's supported
  @retval FALSE               It's not supported
**/
BOOLEAN
IsGpioLockOpcodeSupported (
  VOID
  )
{
  return TRUE;
}
