510 lines
15 KiB
C
510 lines
15 KiB
C
|
/*
|
||
|
* This file is part of the coreboot project.
|
||
|
*
|
||
|
* Copyright (C) 2014 - 2017 Intel Corporation.
|
||
|
*
|
||
|
* This program is free software; you can redistribute it and/or modify
|
||
|
* it under the terms of the GNU General Public License as published by
|
||
|
* the Free Software Foundation; version 2 of the License.
|
||
|
*
|
||
|
* This program is distributed in the hope that it will be useful,
|
||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
|
* GNU General Public License for more details.
|
||
|
*
|
||
|
*/
|
||
|
|
||
|
#include <stdint.h>
|
||
|
#include <string.h>
|
||
|
#include <arch/io.h>
|
||
|
#include <console/console.h>
|
||
|
#include <device/device.h>
|
||
|
#include <device/pci.h>
|
||
|
|
||
|
#include <soc/iomap.h>
|
||
|
#include <soc/pcr.h>
|
||
|
#include <soc/soc_util.h>
|
||
|
#include <soc/gpio.h>
|
||
|
|
||
|
// Community PadOwnOffset HostOwnOffset
|
||
|
// GpiIsOffset
|
||
|
// GpiIeOffset GpiGpeStsOffset GpiGpeEnOffset
|
||
|
// SmiStsOffset
|
||
|
// SmiEnOffset NmiStsOffset NmiEnOffset
|
||
|
// PadCfgLockOffset
|
||
|
// PadCfgLockTxOffset PadCfgOffset PadPerGroup
|
||
|
static const struct GPIO_GROUP_INFO mGpioGroupInfo[] = {
|
||
|
{PID_GPIOCOM0, R_PCH_PCR_GPIO_NC_PAD_OWN, R_PCH_PCR_GPIO_NC_HOSTSW_OWN,
|
||
|
R_PCH_PCR_GPIO_NC_GPI_IS, R_PCH_PCR_GPIO_NC_GPI_IE,
|
||
|
R_PCH_PCR_GPIO_NC_GPI_GPE_STS, R_PCH_PCR_GPIO_NC_GPI_GPE_EN,
|
||
|
R_PCH_PCR_GPIO_NC_SMI_STS, R_PCH_PCR_GPIO_NC_SMI_EN,
|
||
|
R_PCH_PCR_GPIO_NC_NMI_STS, R_PCH_PCR_GPIO_NC_NMI_EN,
|
||
|
R_PCH_PCR_GPIO_NC_PADCFGLOCK, R_PCH_PCR_GPIO_NC_PADCFGLOCKTX,
|
||
|
R_PCH_PCR_GPIO_NC_PADCFG_OFFSET,
|
||
|
V_PCH_GPIO_NC_PAD_MAX}, // DNV NORTH_ALL
|
||
|
{PID_GPIOCOM1, R_PCH_PCR_GPIO_SC_DFX_PAD_OWN,
|
||
|
R_PCH_PCR_GPIO_SC_DFX_HOSTSW_OWN, R_PCH_PCR_GPIO_SC_DFX_GPI_IS,
|
||
|
R_PCH_PCR_GPIO_SC_DFX_GPI_IE, R_PCH_PCR_GPIO_SC_DFX_GPI_GPE_STS,
|
||
|
R_PCH_PCR_GPIO_SC_DFX_GPI_GPE_EN, NO_REGISTER_FOR_PROPERTY,
|
||
|
NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY,
|
||
|
NO_REGISTER_FOR_PROPERTY, R_PCH_PCR_GPIO_SC_DFX_PADCFGLOCK,
|
||
|
R_PCH_PCR_GPIO_SC_DFX_PADCFGLOCKTX,
|
||
|
R_PCH_PCR_GPIO_SC_DFX_PADCFG_OFFSET,
|
||
|
V_PCH_GPIO_SC_DFX_PAD_MAX}, // DNV SOUTH_DFX
|
||
|
{PID_GPIOCOM1, R_PCH_PCR_GPIO_SC0_PAD_OWN,
|
||
|
R_PCH_PCR_GPIO_SC0_HOSTSW_OWN, R_PCH_PCR_GPIO_SC0_GPI_IS,
|
||
|
R_PCH_PCR_GPIO_SC0_GPI_IE, R_PCH_PCR_GPIO_SC0_GPI_GPE_STS,
|
||
|
R_PCH_PCR_GPIO_SC0_GPI_GPE_EN, R_PCH_PCR_GPIO_SC0_SMI_STS,
|
||
|
R_PCH_PCR_GPIO_SC0_SMI_EN, R_PCH_PCR_GPIO_SC0_NMI_STS,
|
||
|
R_PCH_PCR_GPIO_SC0_NMI_EN, R_PCH_PCR_GPIO_SC0_PADCFGLOCK,
|
||
|
R_PCH_PCR_GPIO_SC0_PADCFGLOCKTX, R_PCH_PCR_GPIO_SC0_PADCFG_OFFSET,
|
||
|
V_PCH_GPIO_SC0_PAD_MAX}, // DNV South Community 0
|
||
|
{PID_GPIOCOM1, R_PCH_PCR_GPIO_SC1_PAD_OWN,
|
||
|
R_PCH_PCR_GPIO_SC1_HOSTSW_OWN, R_PCH_PCR_GPIO_SC1_GPI_IS,
|
||
|
R_PCH_PCR_GPIO_SC1_GPI_IE, R_PCH_PCR_GPIO_SC1_GPI_GPE_STS,
|
||
|
R_PCH_PCR_GPIO_SC1_GPI_GPE_EN, R_PCH_PCR_GPIO_SC1_SMI_STS,
|
||
|
R_PCH_PCR_GPIO_SC1_SMI_EN, R_PCH_PCR_GPIO_SC1_NMI_STS,
|
||
|
R_PCH_PCR_GPIO_SC1_NMI_EN, R_PCH_PCR_GPIO_SC1_PADCFGLOCK,
|
||
|
R_PCH_PCR_GPIO_SC1_PADCFGLOCKTX, R_PCH_PCR_GPIO_SC1_PADCFG_OFFSET,
|
||
|
V_PCH_GPIO_SC1_PAD_MAX}, // DNV South Community 1
|
||
|
};
|
||
|
|
||
|
/* Retrieve address and length of GPIO info table */
|
||
|
static struct GPIO_GROUP_INFO *
|
||
|
GpioGetGroupInfoTable(uint32_t *GpioGroupInfoTableLength)
|
||
|
{
|
||
|
*GpioGroupInfoTableLength =
|
||
|
sizeof(mGpioGroupInfo) / sizeof(struct GPIO_GROUP_INFO);
|
||
|
return (struct GPIO_GROUP_INFO *)mGpioGroupInfo;
|
||
|
}
|
||
|
|
||
|
/* Get Gpio Pad Ownership */
|
||
|
static void GpioGetPadOwnership(GPIO_PAD GpioPad, GPIO_PAD_OWN *PadOwnVal)
|
||
|
{
|
||
|
uint32_t Mask;
|
||
|
uint32_t RegOffset;
|
||
|
uint32_t GroupIndex;
|
||
|
uint32_t PadNumber;
|
||
|
struct GPIO_GROUP_INFO *GpioGroupInfo;
|
||
|
uint32_t GpioGroupInfoLength;
|
||
|
uint32_t PadOwnRegValue;
|
||
|
|
||
|
GroupIndex = GPIO_GET_GROUP_INDEX_FROM_PAD(GpioPad);
|
||
|
PadNumber = GPIO_GET_PAD_NUMBER(GpioPad);
|
||
|
|
||
|
GpioGroupInfo = GpioGetGroupInfoTable(&GpioGroupInfoLength);
|
||
|
|
||
|
//
|
||
|
// Check if group argument exceeds GPIO GROUP INFO array
|
||
|
//
|
||
|
if ((uint32_t)GroupIndex >= GpioGroupInfoLength) {
|
||
|
printk(BIOS_ERR, "GPIO ERROR: Group argument (%d) exceeds GPIO "
|
||
|
"group range\n",
|
||
|
GroupIndex);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Check if legal pin number
|
||
|
//
|
||
|
if (PadNumber >= GpioGroupInfo[GroupIndex].PadPerGroup) {
|
||
|
printk(BIOS_ERR, "GPIO ERROR: Pin number (%d) exceeds possible "
|
||
|
"range for this group\n",
|
||
|
PadNumber);
|
||
|
return;
|
||
|
}
|
||
|
//
|
||
|
// Calculate RegOffset using Pad Ownership offset and GPIO Pad number.
|
||
|
// One DWord register contains information for 8 pads.
|
||
|
//
|
||
|
RegOffset =
|
||
|
GpioGroupInfo[GroupIndex].PadOwnOffset + (PadNumber >> 3) * 0x4;
|
||
|
|
||
|
//
|
||
|
// Calculate pad bit position within DWord register
|
||
|
//
|
||
|
PadNumber %= 8;
|
||
|
Mask = ((1 << 1) | (1 << 0)) << (PadNumber * 4);
|
||
|
|
||
|
PadOwnRegValue = read32((void *)PCH_PCR_ADDRESS(
|
||
|
GpioGroupInfo[GroupIndex].Community, RegOffset));
|
||
|
|
||
|
*PadOwnVal = (GPIO_PAD_OWN)((PadOwnRegValue & Mask) >> (PadNumber * 4));
|
||
|
}
|
||
|
|
||
|
void gpio_configure_pads(const struct pad_config *gpio, size_t num)
|
||
|
{
|
||
|
/* Return if gpio not valid */
|
||
|
if ((gpio == NULL) || (num == 0))
|
||
|
return;
|
||
|
|
||
|
uint32_t Index;
|
||
|
uint32_t Dw0Reg;
|
||
|
uint32_t Dw0RegMask;
|
||
|
uint32_t Dw1Reg;
|
||
|
uint32_t Dw1RegMask;
|
||
|
uint32_t PadCfgReg;
|
||
|
uint64_t HostSoftOwnReg[V_PCH_GPIO_GROUP_MAX];
|
||
|
uint64_t HostSoftOwnRegMask[V_PCH_GPIO_GROUP_MAX];
|
||
|
uint64_t GpiGpeEnReg[V_PCH_GPIO_GROUP_MAX];
|
||
|
uint64_t GpiGpeEnRegMask[V_PCH_GPIO_GROUP_MAX];
|
||
|
struct GPIO_GROUP_INFO *GpioGroupInfo;
|
||
|
uint32_t GpioGroupInfoLength;
|
||
|
GPIO_PAD GpioGroupOffset;
|
||
|
uint32_t NumberOfGroups;
|
||
|
GPIO_PAD_OWN PadOwnVal;
|
||
|
struct pad_config *GpioData;
|
||
|
GPIO_PAD Group;
|
||
|
uint32_t GroupIndex;
|
||
|
uint32_t PadNumber;
|
||
|
uint32_t FinalValue;
|
||
|
uint32_t Data32;
|
||
|
uint32_t PadMode1, PadMode2;
|
||
|
|
||
|
PadOwnVal = GpioPadOwnHost;
|
||
|
|
||
|
memset(HostSoftOwnReg, 0, sizeof(HostSoftOwnReg));
|
||
|
memset(HostSoftOwnRegMask, 0, sizeof(HostSoftOwnRegMask));
|
||
|
memset(GpiGpeEnReg, 0, sizeof(GpiGpeEnReg));
|
||
|
memset(GpiGpeEnRegMask, 0, sizeof(GpiGpeEnRegMask));
|
||
|
|
||
|
GpioGroupInfo = GpioGetGroupInfoTable(&GpioGroupInfoLength);
|
||
|
|
||
|
GpioGroupOffset = GPIO_DNV_GROUP_MIN;
|
||
|
NumberOfGroups = V_PCH_GPIO_GROUP_MAX;
|
||
|
|
||
|
for (Index = 0; Index < (uint32_t)num; Index++) {
|
||
|
|
||
|
Dw0RegMask = 0;
|
||
|
Dw0Reg = 0;
|
||
|
Dw1RegMask = 0;
|
||
|
Dw1Reg = 0;
|
||
|
|
||
|
GpioData = (struct pad_config *)&(gpio[Index]);
|
||
|
|
||
|
Group = GPIO_GET_GROUP_FROM_PAD(GpioData->GpioPad);
|
||
|
GroupIndex = GPIO_GET_GROUP_INDEX_FROM_PAD(GpioData->GpioPad);
|
||
|
PadNumber = GPIO_GET_PAD_NUMBER(GpioData->GpioPad);
|
||
|
|
||
|
//
|
||
|
// Check if group index argument exceeds GPIO group index range
|
||
|
//
|
||
|
if (GroupIndex >= V_PCH_GPIO_GROUP_MAX) {
|
||
|
printk(BIOS_ERR, "GPIO ERROR: Invalid Group Index "
|
||
|
"(GroupIndex=%d, Pad=%d)!\n",
|
||
|
GroupIndex, PadNumber);
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Check if group argument exceeds GPIO group range
|
||
|
//
|
||
|
if ((Group < GpioGroupOffset) ||
|
||
|
(Group >= NumberOfGroups + GpioGroupOffset)) {
|
||
|
printk(BIOS_ERR,
|
||
|
"GPIO ERROR: Invalid Group (Group=%d)!\n",
|
||
|
Group);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Check if legal pin number
|
||
|
//
|
||
|
if (PadNumber >= GpioGroupInfo[GroupIndex].PadPerGroup) {
|
||
|
printk(BIOS_ERR, "GPIO ERROR: Invalid PadNumber "
|
||
|
"(PadNumber=%d)!\n",
|
||
|
PadNumber);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Check if selected GPIO Pad is not owned by CSME/ISH
|
||
|
//
|
||
|
GpioGetPadOwnership(GpioData->GpioPad, &PadOwnVal);
|
||
|
|
||
|
if (PadOwnVal != GpioPadOwnHost) {
|
||
|
printk(BIOS_ERR, "GPIO WARNING: Accessing pad not "
|
||
|
"owned by host (Group=%d, Pad=%d)!",
|
||
|
GroupIndex, PadNumber);
|
||
|
if (PadOwnVal == GpioPadOwnCsme)
|
||
|
printk(BIOS_ERR, "The owner is CSME\n");
|
||
|
else if (PadOwnVal == GpioPadOwnIsh)
|
||
|
printk(BIOS_ERR, "The owner is ISH\n");
|
||
|
printk(BIOS_ERR, "** Please make sure the GPIO usage "
|
||
|
"in sync between CSME/ISH and Host IA "
|
||
|
"FW configuration.\n");
|
||
|
printk(BIOS_ERR, "** All the GPIO occupied by CSME/ISH "
|
||
|
"should not do any configuration by "
|
||
|
"Host IA FW.\n");
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Configure Reset Type (PadRstCfg)
|
||
|
//
|
||
|
Dw0RegMask |=
|
||
|
((((GpioData->GpioConfig.PowerConfig &
|
||
|
GPIO_CONF_RESET_MASK) >>
|
||
|
GPIO_CONF_RESET_BIT_POS) == GpioHardwareDefault)
|
||
|
? 0x0
|
||
|
: B_PCH_GPIO_RST_CONF);
|
||
|
Dw0Reg |= (((GpioData->GpioConfig.PowerConfig &
|
||
|
GPIO_CONF_RESET_MASK) >>
|
||
|
(GPIO_CONF_RESET_BIT_POS + 1))
|
||
|
<< N_PCH_GPIO_RST_CONF);
|
||
|
|
||
|
//
|
||
|
// Configure how interrupt is triggered (RxEvCfg)
|
||
|
//
|
||
|
Dw0RegMask |=
|
||
|
((((GpioData->GpioConfig.InterruptConfig &
|
||
|
GPIO_CONF_INT_TRIG_MASK) >>
|
||
|
GPIO_CONF_INT_TRIG_BIT_POS) == GpioHardwareDefault)
|
||
|
? 0x0
|
||
|
: B_PCH_GPIO_RX_LVL_EDG);
|
||
|
Dw0Reg |= (((GpioData->GpioConfig.InterruptConfig &
|
||
|
GPIO_CONF_INT_TRIG_MASK) >>
|
||
|
(GPIO_CONF_INT_TRIG_BIT_POS + 1))
|
||
|
<< N_PCH_GPIO_RX_LVL_EDG);
|
||
|
|
||
|
//
|
||
|
// Configure interrupt generation (GPIRoutIOxAPIC/SCI/SMI/NMI)
|
||
|
//
|
||
|
Dw0RegMask |=
|
||
|
((((GpioData->GpioConfig.InterruptConfig &
|
||
|
GPIO_CONF_INT_ROUTE_MASK) >>
|
||
|
GPIO_CONF_INT_ROUTE_BIT_POS) == GpioHardwareDefault)
|
||
|
? 0x0
|
||
|
: (B_PCH_GPIO_RX_NMI_ROUTE |
|
||
|
B_PCH_GPIO_RX_SCI_ROUTE |
|
||
|
B_PCH_GPIO_RX_SMI_ROUTE |
|
||
|
B_PCH_GPIO_RX_APIC_ROUTE));
|
||
|
Dw0Reg |= (((GpioData->GpioConfig.InterruptConfig &
|
||
|
GPIO_CONF_INT_ROUTE_MASK) >>
|
||
|
(GPIO_CONF_INT_ROUTE_BIT_POS + 1))
|
||
|
<< N_PCH_GPIO_RX_NMI_ROUTE);
|
||
|
|
||
|
// If CFIO is not Working as GPIO mode, Don't move TxDisabe and
|
||
|
// RxDisable
|
||
|
if (GpioData->GpioConfig.PadMode == GpioPadModeGpio) {
|
||
|
//
|
||
|
// Configure GPIO direction (GPIORxDis and GPIOTxDis)
|
||
|
//
|
||
|
Dw0RegMask |= ((((GpioData->GpioConfig.Direction &
|
||
|
GPIO_CONF_DIR_MASK) >>
|
||
|
GPIO_CONF_DIR_BIT_POS) ==
|
||
|
GpioHardwareDefault)
|
||
|
? 0x0
|
||
|
: (B_PCH_GPIO_RXDIS |
|
||
|
B_PCH_GPIO_TXDIS));
|
||
|
Dw0Reg |= (((GpioData->GpioConfig.Direction &
|
||
|
GPIO_CONF_DIR_MASK) >>
|
||
|
(GPIO_CONF_DIR_BIT_POS + 1))
|
||
|
<< N_PCH_GPIO_TXDIS);
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Configure GPIO input inversion (RXINV)
|
||
|
//
|
||
|
Dw0RegMask |= ((((GpioData->GpioConfig.Direction &
|
||
|
GPIO_CONF_INV_MASK) >>
|
||
|
GPIO_CONF_INV_BIT_POS) == GpioHardwareDefault)
|
||
|
? 0x0
|
||
|
: B_PCH_GPIO_RXINV);
|
||
|
Dw0Reg |= (((GpioData->GpioConfig.Direction &
|
||
|
GPIO_CONF_INV_MASK) >>
|
||
|
(GPIO_CONF_INV_BIT_POS + 1))
|
||
|
<< N_PCH_GPIO_RXINV);
|
||
|
|
||
|
//
|
||
|
// Configure GPIO output state (GPIOTxState)
|
||
|
//
|
||
|
Dw0RegMask |=
|
||
|
((((GpioData->GpioConfig.OutputState &
|
||
|
GPIO_CONF_OUTPUT_MASK) >>
|
||
|
GPIO_CONF_OUTPUT_BIT_POS) == GpioHardwareDefault)
|
||
|
? 0x0
|
||
|
: B_PCH_GPIO_TX_STATE);
|
||
|
Dw0Reg |= (((GpioData->GpioConfig.OutputState &
|
||
|
GPIO_CONF_OUTPUT_MASK) >>
|
||
|
(GPIO_CONF_OUTPUT_BIT_POS + 1))
|
||
|
<< N_PCH_GPIO_TX_STATE);
|
||
|
|
||
|
//
|
||
|
// Configure GPIO RX raw override to '1' (RXRAW1)
|
||
|
//
|
||
|
Dw0RegMask |=
|
||
|
((((GpioData->GpioConfig.OtherSettings &
|
||
|
GPIO_CONF_RXRAW_MASK) >>
|
||
|
GPIO_CONF_RXRAW_BIT_POS) == GpioHardwareDefault)
|
||
|
? 0x0
|
||
|
: B_PCH_GPIO_RX_RAW1);
|
||
|
Dw0Reg |= (((GpioData->GpioConfig.OtherSettings &
|
||
|
GPIO_CONF_RXRAW_MASK) >>
|
||
|
(GPIO_CONF_RXRAW_BIT_POS + 1))
|
||
|
<< N_PCH_GPIO_RX_RAW1);
|
||
|
|
||
|
//
|
||
|
// Configure GPIO Pad Mode (PMode)
|
||
|
//
|
||
|
Dw0RegMask |=
|
||
|
((((GpioData->GpioConfig.PadMode &
|
||
|
GPIO_CONF_PAD_MODE_MASK) >>
|
||
|
GPIO_CONF_PAD_MODE_BIT_POS) == GpioHardwareDefault)
|
||
|
? 0x0
|
||
|
: B_PCH_GPIO_PAD_MODE);
|
||
|
Dw0Reg |= (((GpioData->GpioConfig.PadMode &
|
||
|
GPIO_CONF_PAD_MODE_MASK) >>
|
||
|
(GPIO_CONF_PAD_MODE_BIT_POS + 1))
|
||
|
<< N_PCH_GPIO_PAD_MODE);
|
||
|
|
||
|
//
|
||
|
// Configure GPIO termination (Term)
|
||
|
//
|
||
|
Dw1RegMask |= ((((GpioData->GpioConfig.ElectricalConfig &
|
||
|
GPIO_CONF_TERM_MASK) >>
|
||
|
GPIO_CONF_TERM_BIT_POS) == GpioHardwareDefault)
|
||
|
? 0x0
|
||
|
: B_PCH_GPIO_TERM);
|
||
|
Dw1Reg |= (((GpioData->GpioConfig.ElectricalConfig &
|
||
|
GPIO_CONF_TERM_MASK) >>
|
||
|
(GPIO_CONF_TERM_BIT_POS + 1))
|
||
|
<< N_PCH_GPIO_TERM);
|
||
|
|
||
|
//
|
||
|
// Configure GPIO pad tolerance (padtol)
|
||
|
//
|
||
|
Dw1RegMask |=
|
||
|
((((GpioData->GpioConfig.ElectricalConfig &
|
||
|
GPIO_CONF_PADTOL_MASK) >>
|
||
|
GPIO_CONF_PADTOL_BIT_POS) == GpioHardwareDefault)
|
||
|
? 0x0
|
||
|
: B_PCH_GPIO_PADTOL);
|
||
|
Dw1Reg |= (((GpioData->GpioConfig.ElectricalConfig &
|
||
|
GPIO_CONF_PADTOL_MASK) >>
|
||
|
(GPIO_CONF_PADTOL_BIT_POS + 1))
|
||
|
<< N_PCH_GPIO_PADTOL);
|
||
|
|
||
|
//
|
||
|
// Check for additional requirements on setting PADCFG register
|
||
|
//
|
||
|
|
||
|
//
|
||
|
// Create PADCFG register offset using group and pad number
|
||
|
//
|
||
|
PadCfgReg = 0x8 * PadNumber +
|
||
|
GpioGroupInfo[GroupIndex].PadCfgOffset;
|
||
|
Data32 = read32((void *)PCH_PCR_ADDRESS(
|
||
|
GpioGroupInfo[GroupIndex].Community, PadCfgReg));
|
||
|
|
||
|
FinalValue = ((Data32 & (~Dw0RegMask)) | Dw0Reg);
|
||
|
|
||
|
PadMode1 =
|
||
|
(Data32 & B_PCH_GPIO_PAD_MODE) >> N_PCH_GPIO_PAD_MODE;
|
||
|
PadMode2 =
|
||
|
(Dw0Reg & B_PCH_GPIO_PAD_MODE) >> N_PCH_GPIO_PAD_MODE;
|
||
|
|
||
|
if (((Data32 & B_PCH_GPIO_PAD_MODE) !=
|
||
|
(FinalValue & B_PCH_GPIO_PAD_MODE)) ||
|
||
|
(PadMode2 == 0)) {
|
||
|
printk(BIOS_DEBUG, "Changing GpioPad PID: %x Offset: "
|
||
|
"0x%x PadModeP1: %d P2: %d ",
|
||
|
GpioGroupInfo[GroupIndex].Community, PadCfgReg,
|
||
|
PadMode1, PadMode2);
|
||
|
printk(BIOS_DEBUG, "R: 0x%08x Fx%08x !\n", Data32,
|
||
|
FinalValue);
|
||
|
//
|
||
|
// Write PADCFG DW0 register``
|
||
|
//
|
||
|
mmio_andthenor32(
|
||
|
(void *)(uint32_t)PCH_PCR_ADDRESS(
|
||
|
GpioGroupInfo[GroupIndex].Community,
|
||
|
PadCfgReg),
|
||
|
~(uint32_t)Dw0RegMask, (uint32_t)Dw0Reg);
|
||
|
}
|
||
|
|
||
|
Data32 = read32((void *)PCH_PCR_ADDRESS(
|
||
|
GpioGroupInfo[GroupIndex].Community, PadCfgReg + 0x4));
|
||
|
FinalValue = ((Data32 & (~Dw1RegMask)) | Dw1Reg);
|
||
|
if (Data32 != FinalValue) {
|
||
|
//
|
||
|
// Write PADCFG DW1 register
|
||
|
//
|
||
|
mmio_andthenor32(
|
||
|
(void *)(uint32_t)PCH_PCR_ADDRESS(
|
||
|
GpioGroupInfo[GroupIndex].Community,
|
||
|
PadCfgReg + 0x4),
|
||
|
~(uint32_t)Dw1RegMask, (uint32_t)Dw1Reg);
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Update value to be programmed in HOSTSW_OWN register
|
||
|
//
|
||
|
HostSoftOwnRegMask[GroupIndex] |= LShiftU64(
|
||
|
(uint64_t)GpioData->GpioConfig.HostSoftPadOwn & 0x1,
|
||
|
PadNumber);
|
||
|
HostSoftOwnReg[GroupIndex] |= LShiftU64(
|
||
|
(uint64_t)GpioData->GpioConfig.HostSoftPadOwn >> 0x1,
|
||
|
PadNumber);
|
||
|
|
||
|
//
|
||
|
// Update value to be programmed in GPI_GPE_EN register
|
||
|
//
|
||
|
GpiGpeEnRegMask[GroupIndex] |= LShiftU64(
|
||
|
(uint64_t)(GpioData->GpioConfig.InterruptConfig & 0x1),
|
||
|
PadNumber);
|
||
|
GpiGpeEnReg[GroupIndex] |= LShiftU64(
|
||
|
(uint64_t)(GpioData->GpioConfig.InterruptConfig &
|
||
|
GpioIntSci) >>
|
||
|
3,
|
||
|
PadNumber);
|
||
|
}
|
||
|
|
||
|
for (Index = 0; Index < NumberOfGroups; Index++) {
|
||
|
//
|
||
|
// Write HOSTSW_OWN registers
|
||
|
//
|
||
|
if (GpioGroupInfo[Index].HostOwnOffset !=
|
||
|
NO_REGISTER_FOR_PROPERTY) {
|
||
|
mmio_andthenor32(
|
||
|
(void *)PCH_PCR_ADDRESS(
|
||
|
GpioGroupInfo[Index].Community,
|
||
|
GpioGroupInfo[Index].HostOwnOffset),
|
||
|
~(uint32_t)(HostSoftOwnRegMask[Index] &
|
||
|
0xFFFFFFFF),
|
||
|
(uint32_t)(HostSoftOwnReg[Index] & 0xFFFFFFFF));
|
||
|
mmio_andthenor32(
|
||
|
(void *)PCH_PCR_ADDRESS(
|
||
|
GpioGroupInfo[Index].Community,
|
||
|
GpioGroupInfo[Index].HostOwnOffset +
|
||
|
0x4),
|
||
|
~(uint32_t)(RShiftU64(HostSoftOwnRegMask[Index],
|
||
|
32)),
|
||
|
(uint32_t)(
|
||
|
RShiftU64(HostSoftOwnReg[Index], 32)));
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Write GPI_GPE_EN registers
|
||
|
//
|
||
|
if (GpioGroupInfo[Index].GpiGpeEnOffset !=
|
||
|
NO_REGISTER_FOR_PROPERTY) {
|
||
|
mmio_andthenor32(
|
||
|
(void *)PCH_PCR_ADDRESS(
|
||
|
GpioGroupInfo[Index].Community,
|
||
|
GpioGroupInfo[Index].GpiGpeEnOffset),
|
||
|
~(uint32_t)(GpiGpeEnRegMask[Index] &
|
||
|
0xFFFFFFFF),
|
||
|
(uint32_t)(GpiGpeEnReg[Index] & 0xFFFFFFFF));
|
||
|
mmio_andthenor32(
|
||
|
(void *)PCH_PCR_ADDRESS(
|
||
|
GpioGroupInfo[Index].Community,
|
||
|
GpioGroupInfo[Index].GpiGpeEnOffset +
|
||
|
0x4),
|
||
|
~(uint32_t)(
|
||
|
RShiftU64(GpiGpeEnRegMask[Index], 32)),
|
||
|
(uint32_t)(RShiftU64(GpiGpeEnReg[Index], 32)));
|
||
|
}
|
||
|
}
|
||
|
}
|