/** @file
  This file contains routines for GPIO and chipset specific purpose
  used by Reference Code only.

@copyright
 Copyright (c) 2016 - 2019 Intel Corporation. All rights reserved
 This software and associated documentation (if any) is furnished
 under a license and may only be used or copied in accordance
 with the terms of the license. Except as permitted by the
 license, no part of this software or documentation may be
 reproduced, stored in a retrieval system, or transmitted in any
 form or by any means without the express written consent of
 Intel Corporation.
 This file contains an 'Intel Peripheral Driver' and is uniquely
 identified as "Intel Reference Module" and is licensed for Intel
 CPUs and chipsets under the terms of your license agreement with
 Intel or your vendor. This file may be modified by the user, subject
 to additional terms of the license agreement.

@par Specification Reference:
**/

#include <Base.h>
#include <Uefi/UefiBaseType.h>
#include <Library/IoLib.h>

#include <Library/BaseMemoryLib.h> 
#include <Library/DebugLib.h>
#include <Library/GpioLib.h>
#include <Library/SteppingLib.h>
#include <Private/Library/GpioPrivateLib.h>

BXT_GPIO_PAD_INIT  CNViGpio[] =
{
  /*                  Group Pin#:  pad_name,    PMode,GPIO_Config,HostSw,GPO_STATE,INT_Trigger,  Wake_Enabled ,Term_H_L,Inverted, GPI_ROUT, IOSstae, IOSTerm,MMIO_Offset,Community */
          BXT_GPIO_PAD_CONF(L"CNV_BRI_DT"        , M1    , NA      , NA    , NA          , NA      , NA            , P_NONE        , No_invert , NA            , IOS_Masked, SAME    , GPIO_PADBAR+0x100  , SCC       ), //Function 1: CNVi
          BXT_GPIO_PAD_CONF(L"CNV_BRI_RSP"       , M1    , NA      , NA    , NA          , NA      , NA            , P_20K_H       , No_invert , NA            , IOS_Masked, EnPu    , GPIO_PADBAR+0x110  , SCC       ), //Function 1: CNVi
          BXT_GPIO_PAD_CONF(L"CNV_RGI_DT"        , M1    , NA      , NA    , NA          , NA      , NA            , P_NONE        , No_invert , NA            , IOS_Masked, SAME    , GPIO_PADBAR+0x120  , SCC       ), //Function 1: CNVi
          BXT_GPIO_PAD_CONF(L"CNV_RGI_RSP"       , M1    , NA      , NA    , NA          , NA      , NA            , P_20K_H       , No_invert , NA            , IOS_Masked, EnPu    , GPIO_PADBAR+0x130  , SCC       ), //Function 1: CNVi
          BXT_GPIO_PAD_CONF(L"CNV_RF_RESET_B"    , M1    , NA      , NA    , NA          , NA      , NA            , P_NONE        , No_invert , NA            , IOS_Masked, SAME    , GPIO_PADBAR+0x140  , SCC       ), //Function 1: CNVi
          BXT_GPIO_PAD_CONF(L"XTAL_CLKREQ"       , M1    , NA      , NA    , NA          , NA      , NA            , P_NONE        , No_invert , NA            , IOS_Masked, SAME    , GPIO_PADBAR+0x150  , SCC       ), //Function 1: CNVi
};

BXT_GPIO_PAD_INIT  CNViGpio_Crf_GnssAndBtOnUart[] =
{
  /*                  Group Pin#:  pad_name,    PMode,GPIO_Config,HostSw,GPO_STATE,INT_Trigger,  Wake_Enabled ,Term_H_L,Inverted, GPI_ROUT, IOSstae, IOSTerm,MMIO_Offset,Community */
          BXT_GPIO_PAD_CONF(L"GPIO_21"           , M2    , NA      , NA    , NA          , NA      , NA            , P_20K_H       , No_invert , NA            , Last_Value, SAME    , GPIO_PADBAR+0x150 , NORTHWEST ), //Function 2: CNV_MFUART2_RXD
          BXT_GPIO_PAD_CONF(L"GPIO_22"           , M2    , NA      , NA    , NA          , NA      , NA            , P_20K_H       , No_invert , NA            , TxDRxE    , SAME    , GPIO_PADBAR+0x160 , NORTHWEST ), //Function 2: CNV_MFUART2_TXD
          BXT_GPIO_PAD_CONF(L"GPIO_23"           , M2    , NA      , NA    , NA          , NA      , NA            , P_20K_H       , No_invert , NA            , Last_Value, SAME    , GPIO_PADBAR+0x170 , NORTHWEST ), //Functio 2: CNV_GNSS_PABLANKIt /Function 5: PMIC_STDBY
};


#if (CNVI_ENABLE == 1)
/**
  This function sets CNVi Bluetooth Enable value

  @param[in] Value                CNVi BT enable value
                                  0: Disable, 1: Enable
  @retval Status
**/
EFI_STATUS
GpioSetCnviBtEnState (
  IN  UINT32  Value
  )
{
  BXT_GPIO_CONFIG Gpio_Conf_Data;
  UINT32          CommAndOffset;

  CommAndOffset                 = NW_VGPIO_0;
  
  Gpio_Conf_Data.CommAndOffset     = CommAndOffset;
  Gpio_Conf_Data.padConfg0.padCnf0 = GpioPadRead(CommAndOffset);
  Gpio_Conf_Data.padConfg1.padCnf1 = GpioPadRead(CommAndOffset + BXT_GPIO_PAD_CONF1_OFFSET);
  Gpio_Conf_Data.HostSw            = GPIO_D;
  Gpio_Conf_Data.WakeEnabled       = Wake_Disabled;

  Gpio_Conf_Data.padConfg0.r.PMode       = GPIO;
  Gpio_Conf_Data.padConfg0.r.GPIORxTxDis = GPO;
  
  if (Value == 1) {
    Gpio_Conf_Data.padConfg0.r.GPIOTxState   =  HI;
  } else {
    Gpio_Conf_Data.padConfg0.r.GPIOTxState   =  LO;
  }
  
  GpioPadConfigItem(Gpio_Conf_Data);

  return EFI_SUCCESS; 

}

/**
  This function sets CNV GNSS Enable value

  @param[in] Value                CNV GNSS enable value
                                  0: Disable, 1: Enable
  @retval Status
**/
EFI_STATUS
GpioSetCnviGnssEnState (
  IN  UINT32  Value
  )
{
  BXT_GPIO_CONFIG Gpio_Conf_Data;
  UINT32          CommAndOffset;

  CommAndOffset                 = NW_VGPIO_1;
  
  Gpio_Conf_Data.CommAndOffset     = CommAndOffset;
  Gpio_Conf_Data.padConfg0.padCnf0 = GpioPadRead(CommAndOffset);
  Gpio_Conf_Data.padConfg1.padCnf1 = GpioPadRead(CommAndOffset + BXT_GPIO_PAD_CONF1_OFFSET);
  Gpio_Conf_Data.WakeEnabled       = Wake_Disabled;

  Gpio_Conf_Data.padConfg0.r.PMode       = GPIO;
  Gpio_Conf_Data.padConfg0.r.GPIORxTxDis = GPO;
  
  if (Value == 1) {
    Gpio_Conf_Data.padConfg0.r.GPIOTxState   =  HI;
  } else {
    Gpio_Conf_Data.padConfg0.r.GPIOTxState   =  LO;
  }
  
  GpioPadConfigItem(Gpio_Conf_Data);

  return EFI_SUCCESS; 

}

/**
  This function sets CNVi WiFi mode

  @param[in] Value                CNVi WiFi Mode value
                                  GpioCnviWiFiHostaccessable: WiFi uses Host accessible registers for WiFi Power state transitions
                                  GpioCnviWiFiForcedEnabled: WiFi uses normal Flow for WiFi Power state transitions
  @retval Status
**/
EFI_STATUS
GpioSetWifiHostAccessMode (
  IN  VGPIO_CNVI_WIFI_MODE  WiFiMode
  )
{
  BXT_GPIO_CONFIG Gpio_Conf_Data;
  UINT32          CommAndOffset;

  CommAndOffset                = NW_VGPIO_2;
  
  Gpio_Conf_Data.CommAndOffset     = CommAndOffset;
  Gpio_Conf_Data.padConfg0.padCnf0 = GpioPadRead(CommAndOffset);
  Gpio_Conf_Data.padConfg1.padCnf1 = GpioPadRead(CommAndOffset + BXT_GPIO_PAD_CONF1_OFFSET);
  Gpio_Conf_Data.WakeEnabled       = Wake_Disabled;

  Gpio_Conf_Data.padConfg0.r.PMode       = GPIO;
  Gpio_Conf_Data.padConfg0.r.GPIORxTxDis = GPO;
  
  if (WiFiMode == GpioCnviWiFiForcedEnabled) {
    Gpio_Conf_Data.padConfg0.r.GPIOTxState   =  HI;
  } else {
    Gpio_Conf_Data.padConfg0.r.GPIOTxState   =  LO;
  }
  
  GpioPadConfigItem(Gpio_Conf_Data);

  return EFI_SUCCESS; 

}

/**
  This function sets CNVi Bluetooth charging mode

  @param[in] Value                CNVi BT charging mode
                                  0: Normal BT operation
                                  1: BT wireless charging special mode for dead empty battery and S3/4/5 cases
  @retval Status
**/
EFI_STATUS
GpioSetCnviBtChargingMode (
  IN  UINT32  Value
  )
{
  BXT_GPIO_CONFIG Gpio_Conf_Data;
  UINT32          CommAndOffset;

  CommAndOffset                = NW_VGPIO_3;
  
  Gpio_Conf_Data.CommAndOffset     = CommAndOffset;
  Gpio_Conf_Data.padConfg0.padCnf0 = GpioPadRead(CommAndOffset);
  Gpio_Conf_Data.padConfg1.padCnf1 = GpioPadRead(CommAndOffset + BXT_GPIO_PAD_CONF1_OFFSET);
  Gpio_Conf_Data.WakeEnabled       = Wake_Disabled;

  Gpio_Conf_Data.padConfg0.r.PMode       = GPIO;
  Gpio_Conf_Data.padConfg0.r.GPIORxTxDis = GPO;
  
  if (Value == 1) {
    Gpio_Conf_Data.padConfg0.r.GPIOTxState   =  HI;
  } else {
    Gpio_Conf_Data.padConfg0.r.GPIOTxState   =  LO;
  }
  
  GpioPadConfigItem(Gpio_Conf_Data);

  return EFI_SUCCESS; 

}

/**
  This function enables and configures CNVi Bluetooth Host wake-up interrupt

  @param[in] None

  @retval Status
**/
EFI_STATUS
GpioConfigureCnviBtHostWakeInt (
  VOID
  )
{
  BXT_GPIO_CONFIG Gpio_Conf_Data;
  UINT32          CommAndOffset;

  CommAndOffset                = NW_VGPIO_4;
  
  Gpio_Conf_Data.CommAndOffset     = CommAndOffset;
  Gpio_Conf_Data.padConfg0.padCnf0 = GpioPadRead(CommAndOffset);
  Gpio_Conf_Data.padConfg1.padCnf1 = GpioPadRead(CommAndOffset + BXT_GPIO_PAD_CONF1_OFFSET);
  Gpio_Conf_Data.HostSw            = ACPI_D;
  Gpio_Conf_Data.WakeEnabled       = Wake_Enabled;

  Gpio_Conf_Data.padConfg0.r.GPIRout     = SCI;

  Gpio_Conf_Data.padConfg0.r.PMode       = GPIO;
  Gpio_Conf_Data.padConfg0.r.GPIORxTxDis = GPI;
  Gpio_Conf_Data.padConfg0.r.RxEvCfg     = Level;
  Gpio_Conf_Data.padConfg0.r.PadRstCfg   = Deep_Gpio_Reset;

  GpioPadConfigItem(Gpio_Conf_Data);

  return EFI_SUCCESS; 

}

/**
  This function sets CNVi Bluetooth main host interface

  @param[in] BtInterface          CNVi BT Interface Select value
                                  GpioCnviBtIfUart: UART, GpioCnviBtIfUsb: USB
  @retval Status
**/
EFI_STATUS
GpioSetCnviBtInterface (
  IN  VGPIO_CNVI_BT_INTERFACE  BtInterface
  )
{
  BXT_GPIO_CONFIG Gpio_Conf_Data;
  UINT32          CommAndOffset;

  CommAndOffset                = NW_VGPIO_5;
  
  Gpio_Conf_Data.CommAndOffset     = CommAndOffset;
  Gpio_Conf_Data.padConfg0.padCnf0 = GpioPadRead(CommAndOffset);
  Gpio_Conf_Data.padConfg1.padCnf1 = GpioPadRead(CommAndOffset + BXT_GPIO_PAD_CONF1_OFFSET);
  Gpio_Conf_Data.WakeEnabled       = Wake_Disabled;

  Gpio_Conf_Data.padConfg0.r.PMode       = GPIO;
  Gpio_Conf_Data.padConfg0.r.GPIORxTxDis = GPO;
  
  if (BtInterface == GpioCnviBtIfUsb) {
    Gpio_Conf_Data.padConfg0.r.GPIOTxState   =  HI;
  } else {
    Gpio_Conf_Data.padConfg0.r.GPIOTxState   =  LO;
  }
  
  GpioPadConfigItem(Gpio_Conf_Data);

  return EFI_SUCCESS; 

}

/**
  This function sets ISH I2C controller pins into native mode

  @param[in]  IshI2cControllerNumber   I2C controller

  @retval Status
**/
/**
EFI_STATUS
GpioSetIshI2cPinsIntoNativeMode (
  IN  UINT32            IshI2cControllerNumber
  )
{
  EFI_STATUS               Status;
  UINTN                    Index;
  GPIO_PAD_NATIVE_FUNCTION (*I2cGpio) [PCH_ISH_PINS_PER_I2C_CONTROLLER];

  Status = EFI_SUCCESS;

  if (IsPchLp ()) {
    I2cGpio = mPchLpIshI2cGpio;
  } else {
    I2cGpio = mPchHIshI2cGpio;
  }

  ASSERT (IshI2cControllerNumber < PCH_ISH_MAX_I2C_CONTROLLERS);

  for (Index = 0; Index < PCH_ISH_PINS_PER_I2C_CONTROLLER; Index++) {
    Status = SetGpioPadMode (I2cGpio[IshI2cControllerNumber][Index].Pad, I2cGpio[IshI2cControllerNumber][Index].Mode);
    if (EFI_ERROR (Status)) {
      return EFI_UNSUPPORTED;
    }
  }
  return Status;
}
**/
/**
  This function sets ISH UART controller pins into native mode

  @param[in]  IshUartControllerNumber   UART controller

  @retval Status
**/

/**
EFI_STATUS
GpioSetIshUartPinsIntoNativeMode (
  IN  UINT32            IshUartControllerNumber
  )
{
  EFI_STATUS    Status;
  UINTN         Index;
  GPIO_PAD_NATIVE_FUNCTION (*UartGpio) [PCH_ISH_PINS_PER_UART_CONTROLLER];

  Status = EFI_SUCCESS;

  if (IsPchLp ()) {
    UartGpio = mPchLpIshUartGpio;
  } else {
    UartGpio = mPchHIshUartGpio;
  }

  ASSERT (IshUartControllerNumber < PCH_ISH_MAX_UART_CONTROLLERS);

  for (Index = 0; Index < PCH_ISH_PINS_PER_UART_CONTROLLER; Index++) {
    Status = SetGpioPadMode (UartGpio[IshUartControllerNumber][Index].Pad, UartGpio[IshUartControllerNumber][Index].Mode);
    if (EFI_ERROR (Status)) {
      return EFI_UNSUPPORTED;
    }
  }
  return Status;
}
**/
/**
  This function sets ISH SPI controller pins into native mode

  @param[in]  none

  @retval Status
**/

/**
EFI_STATUS
GpioSetIshSpiPinsIntoNativeMode (
  VOID
  )
{
  EFI_STATUS    Status;
  UINTN         Index;
  GPIO_PAD_NATIVE_FUNCTION *SpiGpio;

  Status = EFI_SUCCESS;

  if (IsPchLp ()) {
    SpiGpio = mPchLpIshSpiGpio;
  } else {
    SpiGpio = mPchHIshSpiGpio;
  }

  for (Index = 0; Index < PCH_ISH_PINS_PER_SPI_CONTROLLER; Index++) {
    Status = SetGpioPadMode (SpiGpio[Index].Pad, SpiGpio[Index].Mode);
    if (EFI_ERROR (Status)) {
      return EFI_UNSUPPORTED;
    }
  }
  return Status;
}
**/
/**
  This function sets ISH GP pins into native mode

  @param[in]  IshGpPinNumber   ISH GP pin number

  @retval Status
**/

/**
EFI_STATUS
GpioSetIshGpPinsIntoNativeMode (
  IN  UINT32            IshGpPinNumber
  )
{
  EFI_STATUS               Status;
  GPIO_PAD_NATIVE_FUNCTION *IshGp;

  Status = EFI_SUCCESS;

  if (IsPchLp ()) {
    IshGp = mPchLpIshGPGpio;
  } else {
    IshGp = mPchHIshGPGpio;
  }
  ASSERT (IshGpPinNumber < PCH_ISH_MAX_GP_PINS);

  Status = SetGpioPadMode (IshGp[IshGpPinNumber].Pad, IshGp[IshGpPinNumber].Mode);
  if (EFI_ERROR (Status)) {
    return EFI_UNSUPPORTED;
  }

  return Status;
}
**/
/**
  Returns a pad for given CLKREQ# index.

  @param[in]  ClkreqIndex       CLKREQ# number

  @return CLKREQ# pad.
**/
/**
GPIO_PAD
GpioGetClkreqPad (
  IN     UINT32   ClkreqIndex
  )
{
  if (IsPchLp ()) {
    ASSERT (ClkreqIndex < PCH_LP_PCIE_MAX_CLK_REQ);
    return mPchLpPcieSrcClkReqbPinToGpioMap[ClkreqIndex].Pad;
  } else {
    ASSERT (ClkreqIndex < PCH_H_PCIE_MAX_CLK_REQ);
    return mPchHPcieSrcClkReqbPinToGpioMap[ClkreqIndex].Pad;
  }
}
**/
/**
  Enables CLKREQ# pad in native mode.

  @param[in]  ClkreqIndex       CLKREQ# number

  @return none
**/
/**
VOID
GpioEnableClkreq (
  IN     UINT32   ClkreqIndex
  )
{
  GPIO_CONFIG        PadConfig;
  GPIO_PAD           ClkreqPad;
  GPIO_PAD_MODE      PadMode;

  ZeroMem (&PadConfig, sizeof (PadConfig));

  if (IsPchLp ()) {
    ASSERT (ClkreqIndex < PCH_LP_PCIE_MAX_CLK_REQ);
    ClkreqPad = mPchLpPcieSrcClkReqbPinToGpioMap[ClkreqIndex].Pad;
    PadMode = mPchLpPcieSrcClkReqbPinToGpioMap[ClkreqIndex].Mode;
  } else {
    ASSERT (ClkreqIndex < PCH_H_PCIE_MAX_CLK_REQ);
    ClkreqPad = mPchHPcieSrcClkReqbPinToGpioMap[ClkreqIndex].Pad;
    PadMode = mPchHPcieSrcClkReqbPinToGpioMap[ClkreqIndex].Mode;
  }

  PadConfig.PadMode      = PadMode;
  PadConfig.Direction    = GpioDirNone;
  PadConfig.PowerConfig  = GpioHostDeepReset;
  DEBUG ((DEBUG_INFO, "Enabling CLKREQ%d\n", ClkreqIndex));
  GpioSetPadConfig (ClkreqPad, &PadConfig);
}
**/
/**
  This function checks if GPIO pin for PCHHOTB is in NATIVE MODE

  @param[in]  none

  @retval TRUE                    Pin is in PCHHOTB native mode
          FALSE                   Pin is in gpio mode or is not owned by HOST
**/
/**
BOOLEAN
GpioIsPchHotbPinInNativeMode (
  VOID
  )
{
  EFI_STATUS               Status;
  GPIO_PAD_NATIVE_FUNCTION PchHotbPin;
  GPIO_PAD_MODE            GpioMode;


  if (IsPchLp ()) {
    PchHotbPin = mPchLpPchHotbPin;
  } else {
    PchHotbPin = mPchHPchHotbPin;
  }

  Status =  GetGpioPadMode (PchHotbPin.Pad, &GpioMode);

  if ((EFI_ERROR (Status)) || (GpioMode != PchHotbPin.Mode)) {
    return FALSE;
  } else {
    return TRUE;
  }
}
**/
/**
  This function sets CPU GP pins into native mode

  @param[in]  CpuGpPinNum               CPU GP pin number

  @retval Status
**/
/**
EFI_STATUS
GpioSetCpuGpPinsIntoNativeMode (
  IN  UINT32                            CpuGpPinNum
  )
{
  EFI_STATUS               Status;
  GPIO_PAD_NATIVE_FUNCTION *CpuGpPins;

  if (IsPchLp ()) {
    CpuGpPins = mPchLpCpuGpPinMap;
  } else {
    CpuGpPins = mPchHCpuGpPinMap;
  }

  ASSERT (CpuGpPinNum < 4);

  Status = SetGpioPadMode (CpuGpPins[CpuGpPinNum].Pad, CpuGpPins[CpuGpPinNum].Mode);
  if (EFI_ERROR (Status)) {
    return EFI_UNSUPPORTED;
  }
  return EFI_SUCCESS;
}
**/
//#ifdef PCH_CNL


/**
  This function configures GPIO connection between CNVi and CRF
  @param: ConditionalCfg-> Parameter check to Configure CNVi RF::: for wifi, BT and GNSS or not
  @retval Status
**/

EFI_STATUS
GpioConfigureCnviCrfConnection (
  BOOLEAN ConditionalCfg
  )
{
    GpioPadConfigTable (sizeof (CNViGpio) / sizeof (CNViGpio[0]), CNViGpio);
    if (ConditionalCfg) {
      GpioPadConfigTable (sizeof (CNViGpio_Crf_GnssAndBtOnUart) / sizeof (CNViGpio_Crf_GnssAndBtOnUart[0]), CNViGpio_Crf_GnssAndBtOnUart);
    }
    return EFI_SUCCESS;
}
    
/**
  This function configures virtual GPIO connection for CNVi Bluetooth UART

  @param[in]  ConnectionType

  @retval Status
**/
/**
EFI_STATUS
GpioConfigureCnviBtUartConnection (
  IN  VGPIO_CNVI_BT_UART_CONNECTION_TYPE  ConnectionType
  )
{
  EFI_STATUS               Status;
  UINT32                   Index;
  GPIO_PAD                 *VCnviBtUartPad;
  GPIO_PAD_MODE            VCnviBtUartPadMode;
  GPIO_PAD                 *VUartForCnviBtPad;
  GPIO_PAD_MODE            VUartForCnviBtPadMode;
  GPIO_PAD_NATIVE_FUNCTION *CnviBtUartExternalPad;

  if (IsPchLp ()) {
    VCnviBtUartPad = mPchLpVCnviBtUartGpioPad;
    VUartForCnviBtPad = mPchLpVUartForCnviBtGpioPad;
    CnviBtUartExternalPad = mPchLpCnviBtUartExternalPads;
  } else {
    // No pins for PCH-H defined yet
    ASSERT (FALSE);
    return EFI_UNSUPPORTED;
  }

  switch (ConnectionType) {
    case GpioCnviBtUartToSerialIoUart0:
      VCnviBtUartPadMode = GpioPadModeNative1;
      VUartForCnviBtPadMode = GpioPadModeNative1;
      break;
    case GpioCnviBtUartToIshUart0:
      VCnviBtUartPadMode = GpioPadModeNative2;
      VUartForCnviBtPadMode = GpioPadModeNative1;
      break;
    case GpioCnviBtUartNotConnected:
    case GpioCnviBtUartToExternalPads:
      VCnviBtUartPadMode = GpioPadModeGpio;
      VUartForCnviBtPadMode = GpioPadModeGpio;
      break;
    default:
      ASSERT (FALSE);
      return EFI_INVALID_PARAMETER;
  }

  //
  // Configure CNVi Bluetooth UART for certain connection
  //
  for (Index = 0; Index < 4; Index++) {
    Status = SetGpioPadMode (VCnviBtUartPad[Index], VCnviBtUartPadMode);
    if (EFI_ERROR (Status)) {
      ASSERT_EFI_ERROR (Status);
      return EFI_UNSUPPORTED;
    }
  }

  //
  // Enable virtual connection for UART for Bluetooth
  //
  for (Index = 0; Index < 4; Index++) {
    Status = SetGpioPadMode (VUartForCnviBtPad[Index], VUartForCnviBtPadMode);
    if (EFI_ERROR (Status)) {
      ASSERT_EFI_ERROR (Status);
      return EFI_UNSUPPORTED;
    }
  }

  //
  // Enable CNVi BT UART on external pads
  //
  if (ConnectionType == GpioCnviBtUartToExternalPads) {
    for (Index = 0; Index < 4; Index++) {
      Status = SetGpioPadMode (CnviBtUartExternalPad[Index].Pad, CnviBtUartExternalPad[Index].Mode);
      if (EFI_ERROR (Status)) {
        ASSERT_EFI_ERROR (Status);
        return EFI_UNSUPPORTED;
      }
    }
  }
  return EFI_SUCCESS;
}
**/
/**
  This function configures virtual GPIO connection for CNVi Bluetooth I2S

  @param[in]  ConnectionType

  @retval Status
**/
/**
EFI_STATUS
GpioConfigureCnviBtI2sConnection (
  IN  VGPIO_CNVI_BT_I2S_CONNECTION_TYPE  ConnectionType
  )
{
  EFI_STATUS               Status;
  UINT32                   Index;
  GPIO_PAD                 *VCnviBtI2sPad;
  GPIO_PAD_MODE            VCnviBtI2sPadMode;
  GPIO_PAD                 *VSspForCnviBtPad;
  GPIO_PAD_MODE            VSspForCnviBtPadMode;
  GPIO_PAD_NATIVE_FUNCTION *CnviBtI2sExternalPad;

  if (IsPchLp ()) {
    VCnviBtI2sPad = mPchLpVCnviBtI2sGpioPad;
    VSspForCnviBtPad = mPchLpVSspForCnviBtGpioPad;
    CnviBtI2sExternalPad = mPchLpCnviBtI2sExternalPads;
  } else {
    // No pins for PCH-H defined yet
    ASSERT (FALSE);
    return EFI_UNSUPPORTED;
  }

  switch (ConnectionType) {
    case GpioCnviBtI2sToSsp0:
      VCnviBtI2sPadMode = GpioPadModeNative1;
      VSspForCnviBtPadMode = GpioPadModeNative1;
      break;
    case GpioCnviBtI2sToSsp1:
      VCnviBtI2sPadMode = GpioPadModeNative2;
      VSspForCnviBtPadMode = GpioPadModeNative1;
      break;
    case GpioCnviBtI2sToSsp2:
      VCnviBtI2sPadMode = GpioPadModeNative3;
      VSspForCnviBtPadMode = GpioPadModeNative1;
      break;
    case GpioCnviBtI2sNotConnected:
    case GpioCnviBtI2sToExternalPads:
      VCnviBtI2sPadMode = GpioPadModeGpio;
      VSspForCnviBtPadMode = GpioPadModeGpio;
      break;
    default:
      ASSERT (FALSE);
      return EFI_INVALID_PARAMETER;
  }

  //
  // Configure CNVi Bluetooth I2S for certain connection
  //
  for (Index = 0; Index < 4; Index++) {
    Status = SetGpioPadMode (VCnviBtI2sPad[Index], VCnviBtI2sPadMode);
    if (EFI_ERROR (Status)) {
      ASSERT_EFI_ERROR (Status);
      return EFI_UNSUPPORTED;
    }
  }

  //
  // Enable virtual connection for SSP for Bluetooth
  //
  for (Index = 0; Index < 4; Index++) {
    Status = SetGpioPadMode (VSspForCnviBtPad[Index], VSspForCnviBtPadMode);
    if (EFI_ERROR (Status)) {
      ASSERT_EFI_ERROR (Status);
      return EFI_UNSUPPORTED;
    }
  }

  //
  // Enable CNV BT I2S on external pads
  //
  if (ConnectionType == GpioCnviBtUartToExternalPads) {
    for (Index = 0; Index < 4; Index++) {
      Status = SetGpioPadMode (CnviBtI2sExternalPad[Index].Pad, CnviBtI2sExternalPad[Index].Mode);
      if (EFI_ERROR (Status)) {
        ASSERT_EFI_ERROR (Status);
        return EFI_UNSUPPORTED;
      }
    }
  }
  return EFI_SUCCESS;
}
**/
/**
  This function configures virtual GPIO connection for CNVi MFUART1

  @param[in]  ConnectionType

  @retval Status
**/
/**
EFI_STATUS
GpioConfigureCnviMfUart0Connection (
  IN  VGPIO_CNVI_MF_UART_CONNECTION_TYPE  ConnectionType
  )
{
  EFI_STATUS               Status;
  UINT32                   Index;
  GPIO_PAD                 *VCnviMfUart1Pad;
  GPIO_PAD_MODE            VCnviMfUart1PadMode;
  GPIO_PAD                 *VUartForCnviMfUart1Pad;
  GPIO_PAD_MODE            VUartForCnviMfUart1PadMode;
  GPIO_PAD_NATIVE_FUNCTION *CnviMfUart1ExternalPad;

  if (IsPchLp ()) {
    VCnviMfUart1Pad = mPchLpVCnviMfUart1GpioPad;
    VUartForCnviMfUart1Pad = mPchLpVUartForCnviMfUart1GpioPad;
    CnviMfUart1ExternalPad = mPchLpCnviMfUart1ExternalPads;
  } else {
    // No pins for PCH-H defined yet
    ASSERT (FALSE);
    return EFI_UNSUPPORTED;
  }

  switch (ConnectionType) {
    case GpioCnviMfUart1ToSerialIoUart2:
      VCnviMfUart1PadMode = GpioPadModeNative2;
      VUartForCnviMfUart1PadMode = GpioPadModeNative1;
      break;
    case GpioCnviMfUart1ToIshUart0:
      VCnviMfUart1PadMode = GpioPadModeNative1;
      VUartForCnviMfUart1PadMode = GpioPadModeNative1;
      break;
    case GpioCnviMfUart1NotConnected:
    case GpioCnviMfUart1ToExternalPads:
      VCnviMfUart1PadMode = GpioPadModeGpio;
      VUartForCnviMfUart1PadMode = GpioPadModeGpio;
      break;
    default:
      ASSERT (FALSE);
      return EFI_INVALID_PARAMETER;
  }

  //
  // Configure CNVi MF UART for certain connection
  //
  for (Index = 0; Index < 4; Index++) {
    Status = SetGpioPadMode (VCnviMfUart1Pad[Index], VCnviMfUart1PadMode);
    if (EFI_ERROR (Status)) {
      ASSERT_EFI_ERROR (Status);
      return EFI_UNSUPPORTED;
    }
  }

  //
  // Enable virtual connection for MF UART
  //
  for (Index = 0; Index < 4; Index++) {
    Status = SetGpioPadMode (VUartForCnviMfUart1Pad[Index], VUartForCnviMfUart1PadMode);
    if (EFI_ERROR (Status)) {
      ASSERT_EFI_ERROR (Status);
      return EFI_UNSUPPORTED;
    }
  }

  //
  // Enable CNV MF UART on external pads
  //
  if (ConnectionType == GpioCnviMfUart1ToExternalPads) {
    for (Index = 0; Index < 4; Index++) {
      Status = SetGpioPadMode (CnviMfUart1ExternalPad[Index].Pad, CnviMfUart1ExternalPad[Index].Mode);
      if (EFI_ERROR (Status)) {
        ASSERT_EFI_ERROR (Status);
        return EFI_UNSUPPORTED;
      }
    }
  }
  return EFI_SUCCESS;
}
**/
/**
  This function configures virtual GPIO connection for CNVi GNSS

  @param[in]  ConnectionType

  @retval Status
**/

/**
EFI_STATUS
GpioConfigureCnviGnssUartConnection (
  IN  VGPIO_CNVI_GNSS_UART_CONNECTION_TYPE  ConnectionType
  )
{
  EFI_STATUS                Status;
  UINT32                    Index;
  GPIO_PAD                  *VCnviGnssUartPad;
  GPIO_PAD_MODE             VCnviGnssUartPadMode;
  GPIO_PAD                  *VUartForCnviGnssPad;
  GPIO_PAD_MODE             VUartForCnviGnssPadMode;
  GPIO_PAD_NATIVE_FUNCTION  *CnviGnssUartExternalPad;

  if (IsPchLp ()) {
    VCnviGnssUartPad = mPchLpVCnviGnssUartGpioPad;
    VUartForCnviGnssPad = mPchLpVUartForCnviGnssUartGpioPad;
    CnviGnssUartExternalPad = mPchLpCnviGnssUartExternalPads;
  } else {
    // No pins for PCH-H defined yet
    ASSERT (FALSE);
    return EFI_INVALID_PARAMETER;
  }

  switch (ConnectionType) {
    case GpioCnviGnssUartToSerialIoUart1:
      VCnviGnssUartPadMode = GpioPadModeNative2;
      VUartForCnviGnssPadMode = GpioPadModeNative1;
      break;
    case GpioCnviGnssUartToIshUart1:
      VCnviGnssUartPadMode = GpioPadModeNative1;
      VUartForCnviGnssPadMode = GpioPadModeNative1;
      break;
    case GpioCnviGnssUartNotConnected:
    case GpioCnviGnssUartToExternalPads:
      VCnviGnssUartPadMode = GpioPadModeGpio;
      VUartForCnviGnssPadMode = GpioPadModeGpio;
      break;
    default:
      ASSERT (FALSE);
      return EFI_INVALID_PARAMETER;
  }

  //
  // Configure CNVi GNSS UART for certain connection
  //
  for (Index = 0; Index < 4; Index++) {
    Status = SetGpioPadMode (VCnviGnssUartPad[Index], VCnviGnssUartPadMode);
    if (EFI_ERROR (Status)) {
      ASSERT_EFI_ERROR (Status);
      return EFI_UNSUPPORTED;
    }
  }

  //
  // Enable GNSS virtual connection for UART
  //
  for (Index = 0; Index < 4; Index++) {
    Status = SetGpioPadMode (VUartForCnviGnssPad[Index], VUartForCnviGnssPadMode);
    if (EFI_ERROR (Status)) {
      ASSERT_EFI_ERROR (Status);
      return EFI_UNSUPPORTED;
    }
  }

  //
  // Enable CNVi GNSS UART on external pads
  //
  if (ConnectionType == GpioCnviGnssUartToExternalPads) {
    for (Index = 0; Index < 4; Index++) {
      Status = SetGpioPadMode (CnviGnssUartExternalPad[Index].Pad, CnviGnssUartExternalPad[Index].Mode);
      if (EFI_ERROR (Status)) {
        ASSERT_EFI_ERROR (Status);
        return EFI_UNSUPPORTED;
      }
    }
  }
  return EFI_SUCCESS;
}


**/

//#endif
#endif

/**
  This function indicates the SoC eSPI mode

  @param[out] eSpiMode            eSPI Flash Sharing Mode:
                                  	  1=slave attached flash sharing (SAFS);
                                  	  0=master attached flash sharing (MAFS; default)

  @retval boolean 				  TRUE: if eSPI mode is enabled, and, SoC supports eSPI mode
  	  	  	  	  	  	  	  	  FALSE: if SoC does not support eSPI mode, or, if LPC mode is default state
**/
BOOLEAN
Is_eSPI_Mode (
  OUT	UINT8	*eSpiMode
)
{
  EFI_STATUS	Status;
  UINT8			PinStrapState1 = 0,
		        PinStrapState2 = 0;

  if (GetBxtSeries() == Glk) {
	Status = GpioPadGetPinStrapState(GPIO_eSPI_MODE_EN, &PinStrapState1);
	if(EFI_ERROR(Status)){
	  DEBUG ((DEBUG_ERROR, "\tUnexpected error reading the eSPI mode set GPIO pad: 0x%x\n", GPIO_eSPI_MODE_EN));
	  DEBUG ((DEBUG_WARN, "\t Warning!!! not able to access pin strap, assuming SoC in LPC mode... \n"));
	  return FALSE;
	}

	if(PinStrapState1) {		//SoC in eSPI mode
	  Status = GpioPadGetPinStrapState(GPIO_eSPI_MODE_TYPE, &PinStrapState2);
	  if(EFI_ERROR(Status)){
		DEBUG ((DEBUG_ERROR, "\tUnexpected error reading the eSPI mode type GPIO pad: 0x%x\n", GPIO_eSPI_MODE_TYPE));
		DEBUG ((DEBUG_WARN, "\t Warning!!! not able to access pin strap, assuming SoC in LPC mode... \n"));
		return FALSE;
	  }
      if(!PinStrapState2) {	//MAF sharing mode supported in eSPI mode
		*eSpiMode = 0;
	  } else {	//SAF sharing mode supported in eSPI mode
		*eSpiMode = 1;
	  }

      return TRUE;
	} else		//SoC in regular LPC mode
      return FALSE;

  } else	//non-GLK processor supports only LPC attached SPI flash
	  return FALSE;
}

/**
  This function indicates whether the SoC supports the integrated CNV or not

  @retval boolean 				  TRUE: if CNVi is enabled,
  	  	  	  	  	  	  	  	  FALSE: if SoC does not support CNVi
**/
BOOLEAN
Is_SoC_integrated_Connectivity_Supported(
)
{
  EFI_STATUS	Status;
  UINT8			PinStrapState;

  if (GetBxtSeries() == Glk) {

	Status = GpioPadGetPinStrapState(GPIO_CNVi_PIN_STRAP, &PinStrapState);
	if(EFI_ERROR(Status)){
	  DEBUG ((DEBUG_ERROR, "\tUnexpected error reading the CNV_RGI_DT GPIO pad: 0x%x\n", GPIO_CNVi_PIN_STRAP));
	  DEBUG ((DEBUG_WARN, "\t Warning!!! not able to access pin strap, assuming SoC has CNVi fused off... \n"));
	  return FALSE;
	}
	//
	// The pin strap disable is on the RGI_DT pin which is connected to the CRF.
	//
	if(PinStrapState){		//When the pin strap is sampled high (SoC/PCH has on-die pull-up) then CNVi is disabled
	  DEBUG ((DEBUG_WARN, "\t Pin strap is disabled for CNVi...\n"));
	  return FALSE;
	} else {				//otherwise CRF pulls down RGI_DT and CNVi will be enabled
	  DEBUG ((DEBUG_INFO, "\t Pin strap is enabled for CNVi...\n"));
	  return TRUE;
	}
  } else {	//non-GLK processor does not support CNVi
	return FALSE;
  }
}
