Angel Pons | 80d9238 | 2020-04-05 15:47:00 +0200 | [diff] [blame] | 1 | /* SPDX-License-Identifier: GPL-2.0-only */ |
Mariusz Szafranski | a404133 | 2017-08-02 17:28:17 +0200 | [diff] [blame] | 2 | |
| 3 | #include <stdint.h> |
| 4 | #include <string.h> |
Kyösti Mälkki | 13f6650 | 2019-03-03 08:01:05 +0200 | [diff] [blame] | 5 | #include <device/mmio.h> |
Mariusz Szafranski | a404133 | 2017-08-02 17:28:17 +0200 | [diff] [blame] | 6 | #include <console/console.h> |
| 7 | #include <device/device.h> |
| 8 | #include <device/pci.h> |
| 9 | |
| 10 | #include <soc/iomap.h> |
| 11 | #include <soc/pcr.h> |
| 12 | #include <soc/soc_util.h> |
Julien Viard de Galbert | 7ebb6b0 | 2018-03-01 16:03:31 +0100 | [diff] [blame] | 13 | #include <soc/gpio_dnv.h> |
Mariusz Szafranski | a404133 | 2017-08-02 17:28:17 +0200 | [diff] [blame] | 14 | |
| 15 | // Community PadOwnOffset HostOwnOffset |
| 16 | // GpiIsOffset |
| 17 | // GpiIeOffset GpiGpeStsOffset GpiGpeEnOffset |
| 18 | // SmiStsOffset |
| 19 | // SmiEnOffset NmiStsOffset NmiEnOffset |
| 20 | // PadCfgLockOffset |
| 21 | // PadCfgLockTxOffset PadCfgOffset PadPerGroup |
| 22 | static const struct GPIO_GROUP_INFO mGpioGroupInfo[] = { |
| 23 | {PID_GPIOCOM0, R_PCH_PCR_GPIO_NC_PAD_OWN, R_PCH_PCR_GPIO_NC_HOSTSW_OWN, |
| 24 | R_PCH_PCR_GPIO_NC_GPI_IS, R_PCH_PCR_GPIO_NC_GPI_IE, |
| 25 | R_PCH_PCR_GPIO_NC_GPI_GPE_STS, R_PCH_PCR_GPIO_NC_GPI_GPE_EN, |
| 26 | R_PCH_PCR_GPIO_NC_SMI_STS, R_PCH_PCR_GPIO_NC_SMI_EN, |
| 27 | R_PCH_PCR_GPIO_NC_NMI_STS, R_PCH_PCR_GPIO_NC_NMI_EN, |
| 28 | R_PCH_PCR_GPIO_NC_PADCFGLOCK, R_PCH_PCR_GPIO_NC_PADCFGLOCKTX, |
| 29 | R_PCH_PCR_GPIO_NC_PADCFG_OFFSET, |
| 30 | V_PCH_GPIO_NC_PAD_MAX}, // DNV NORTH_ALL |
| 31 | {PID_GPIOCOM1, R_PCH_PCR_GPIO_SC_DFX_PAD_OWN, |
| 32 | R_PCH_PCR_GPIO_SC_DFX_HOSTSW_OWN, R_PCH_PCR_GPIO_SC_DFX_GPI_IS, |
| 33 | R_PCH_PCR_GPIO_SC_DFX_GPI_IE, R_PCH_PCR_GPIO_SC_DFX_GPI_GPE_STS, |
| 34 | R_PCH_PCR_GPIO_SC_DFX_GPI_GPE_EN, NO_REGISTER_FOR_PROPERTY, |
| 35 | NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, |
| 36 | NO_REGISTER_FOR_PROPERTY, R_PCH_PCR_GPIO_SC_DFX_PADCFGLOCK, |
| 37 | R_PCH_PCR_GPIO_SC_DFX_PADCFGLOCKTX, |
| 38 | R_PCH_PCR_GPIO_SC_DFX_PADCFG_OFFSET, |
| 39 | V_PCH_GPIO_SC_DFX_PAD_MAX}, // DNV SOUTH_DFX |
| 40 | {PID_GPIOCOM1, R_PCH_PCR_GPIO_SC0_PAD_OWN, |
| 41 | R_PCH_PCR_GPIO_SC0_HOSTSW_OWN, R_PCH_PCR_GPIO_SC0_GPI_IS, |
| 42 | R_PCH_PCR_GPIO_SC0_GPI_IE, R_PCH_PCR_GPIO_SC0_GPI_GPE_STS, |
| 43 | R_PCH_PCR_GPIO_SC0_GPI_GPE_EN, R_PCH_PCR_GPIO_SC0_SMI_STS, |
| 44 | R_PCH_PCR_GPIO_SC0_SMI_EN, R_PCH_PCR_GPIO_SC0_NMI_STS, |
| 45 | R_PCH_PCR_GPIO_SC0_NMI_EN, R_PCH_PCR_GPIO_SC0_PADCFGLOCK, |
| 46 | R_PCH_PCR_GPIO_SC0_PADCFGLOCKTX, R_PCH_PCR_GPIO_SC0_PADCFG_OFFSET, |
| 47 | V_PCH_GPIO_SC0_PAD_MAX}, // DNV South Community 0 |
| 48 | {PID_GPIOCOM1, R_PCH_PCR_GPIO_SC1_PAD_OWN, |
| 49 | R_PCH_PCR_GPIO_SC1_HOSTSW_OWN, R_PCH_PCR_GPIO_SC1_GPI_IS, |
| 50 | R_PCH_PCR_GPIO_SC1_GPI_IE, R_PCH_PCR_GPIO_SC1_GPI_GPE_STS, |
| 51 | R_PCH_PCR_GPIO_SC1_GPI_GPE_EN, R_PCH_PCR_GPIO_SC1_SMI_STS, |
| 52 | R_PCH_PCR_GPIO_SC1_SMI_EN, R_PCH_PCR_GPIO_SC1_NMI_STS, |
| 53 | R_PCH_PCR_GPIO_SC1_NMI_EN, R_PCH_PCR_GPIO_SC1_PADCFGLOCK, |
| 54 | R_PCH_PCR_GPIO_SC1_PADCFGLOCKTX, R_PCH_PCR_GPIO_SC1_PADCFG_OFFSET, |
| 55 | V_PCH_GPIO_SC1_PAD_MAX}, // DNV South Community 1 |
| 56 | }; |
| 57 | |
| 58 | /* Retrieve address and length of GPIO info table */ |
| 59 | static struct GPIO_GROUP_INFO * |
| 60 | GpioGetGroupInfoTable(uint32_t *GpioGroupInfoTableLength) |
| 61 | { |
Patrick Georgi | 6b688f5 | 2021-02-12 13:49:11 +0100 | [diff] [blame] | 62 | *GpioGroupInfoTableLength = ARRAY_SIZE(mGpioGroupInfo); |
Mariusz Szafranski | a404133 | 2017-08-02 17:28:17 +0200 | [diff] [blame] | 63 | return (struct GPIO_GROUP_INFO *)mGpioGroupInfo; |
| 64 | } |
| 65 | |
| 66 | /* Get Gpio Pad Ownership */ |
| 67 | static void GpioGetPadOwnership(GPIO_PAD GpioPad, GPIO_PAD_OWN *PadOwnVal) |
| 68 | { |
| 69 | uint32_t Mask; |
| 70 | uint32_t RegOffset; |
| 71 | uint32_t GroupIndex; |
| 72 | uint32_t PadNumber; |
| 73 | struct GPIO_GROUP_INFO *GpioGroupInfo; |
| 74 | uint32_t GpioGroupInfoLength; |
| 75 | uint32_t PadOwnRegValue; |
| 76 | |
| 77 | GroupIndex = GPIO_GET_GROUP_INDEX_FROM_PAD(GpioPad); |
| 78 | PadNumber = GPIO_GET_PAD_NUMBER(GpioPad); |
| 79 | |
| 80 | GpioGroupInfo = GpioGetGroupInfoTable(&GpioGroupInfoLength); |
| 81 | |
| 82 | // |
| 83 | // Check if group argument exceeds GPIO GROUP INFO array |
| 84 | // |
| 85 | if ((uint32_t)GroupIndex >= GpioGroupInfoLength) { |
| 86 | printk(BIOS_ERR, "GPIO ERROR: Group argument (%d) exceeds GPIO " |
| 87 | "group range\n", |
| 88 | GroupIndex); |
| 89 | return; |
| 90 | } |
| 91 | |
| 92 | // |
| 93 | // Check if legal pin number |
| 94 | // |
| 95 | if (PadNumber >= GpioGroupInfo[GroupIndex].PadPerGroup) { |
| 96 | printk(BIOS_ERR, "GPIO ERROR: Pin number (%d) exceeds possible " |
| 97 | "range for this group\n", |
| 98 | PadNumber); |
| 99 | return; |
| 100 | } |
| 101 | // |
| 102 | // Calculate RegOffset using Pad Ownership offset and GPIO Pad number. |
| 103 | // One DWord register contains information for 8 pads. |
| 104 | // |
| 105 | RegOffset = |
| 106 | GpioGroupInfo[GroupIndex].PadOwnOffset + (PadNumber >> 3) * 0x4; |
| 107 | |
| 108 | // |
| 109 | // Calculate pad bit position within DWord register |
| 110 | // |
| 111 | PadNumber %= 8; |
| 112 | Mask = ((1 << 1) | (1 << 0)) << (PadNumber * 4); |
| 113 | |
| 114 | PadOwnRegValue = read32((void *)PCH_PCR_ADDRESS( |
| 115 | GpioGroupInfo[GroupIndex].Community, RegOffset)); |
| 116 | |
| 117 | *PadOwnVal = (GPIO_PAD_OWN)((PadOwnRegValue & Mask) >> (PadNumber * 4)); |
| 118 | } |
| 119 | |
Julien Viard de Galbert | 7ebb6b0 | 2018-03-01 16:03:31 +0100 | [diff] [blame] | 120 | void gpio_configure_dnv_pads(const struct dnv_pad_config *gpio, size_t num) |
Mariusz Szafranski | a404133 | 2017-08-02 17:28:17 +0200 | [diff] [blame] | 121 | { |
| 122 | /* Return if gpio not valid */ |
| 123 | if ((gpio == NULL) || (num == 0)) |
| 124 | return; |
| 125 | |
| 126 | uint32_t Index; |
| 127 | uint32_t Dw0Reg; |
| 128 | uint32_t Dw0RegMask; |
| 129 | uint32_t Dw1Reg; |
| 130 | uint32_t Dw1RegMask; |
| 131 | uint32_t PadCfgReg; |
| 132 | uint64_t HostSoftOwnReg[V_PCH_GPIO_GROUP_MAX]; |
| 133 | uint64_t HostSoftOwnRegMask[V_PCH_GPIO_GROUP_MAX]; |
| 134 | uint64_t GpiGpeEnReg[V_PCH_GPIO_GROUP_MAX]; |
| 135 | uint64_t GpiGpeEnRegMask[V_PCH_GPIO_GROUP_MAX]; |
| 136 | struct GPIO_GROUP_INFO *GpioGroupInfo; |
| 137 | uint32_t GpioGroupInfoLength; |
| 138 | GPIO_PAD GpioGroupOffset; |
| 139 | uint32_t NumberOfGroups; |
| 140 | GPIO_PAD_OWN PadOwnVal; |
Julien Viard de Galbert | 7ebb6b0 | 2018-03-01 16:03:31 +0100 | [diff] [blame] | 141 | struct dnv_pad_config *GpioData; |
Mariusz Szafranski | a404133 | 2017-08-02 17:28:17 +0200 | [diff] [blame] | 142 | GPIO_PAD Group; |
| 143 | uint32_t GroupIndex; |
| 144 | uint32_t PadNumber; |
| 145 | uint32_t FinalValue; |
| 146 | uint32_t Data32; |
| 147 | uint32_t PadMode1, PadMode2; |
| 148 | |
| 149 | PadOwnVal = GpioPadOwnHost; |
| 150 | |
| 151 | memset(HostSoftOwnReg, 0, sizeof(HostSoftOwnReg)); |
| 152 | memset(HostSoftOwnRegMask, 0, sizeof(HostSoftOwnRegMask)); |
| 153 | memset(GpiGpeEnReg, 0, sizeof(GpiGpeEnReg)); |
| 154 | memset(GpiGpeEnRegMask, 0, sizeof(GpiGpeEnRegMask)); |
| 155 | |
| 156 | GpioGroupInfo = GpioGetGroupInfoTable(&GpioGroupInfoLength); |
| 157 | |
| 158 | GpioGroupOffset = GPIO_DNV_GROUP_MIN; |
| 159 | NumberOfGroups = V_PCH_GPIO_GROUP_MAX; |
| 160 | |
| 161 | for (Index = 0; Index < (uint32_t)num; Index++) { |
Mariusz Szafranski | a404133 | 2017-08-02 17:28:17 +0200 | [diff] [blame] | 162 | Dw0RegMask = 0; |
| 163 | Dw0Reg = 0; |
| 164 | Dw1RegMask = 0; |
| 165 | Dw1Reg = 0; |
| 166 | |
Julien Viard de Galbert | 7ebb6b0 | 2018-03-01 16:03:31 +0100 | [diff] [blame] | 167 | GpioData = (struct dnv_pad_config *)&(gpio[Index]); |
Mariusz Szafranski | a404133 | 2017-08-02 17:28:17 +0200 | [diff] [blame] | 168 | |
| 169 | Group = GPIO_GET_GROUP_FROM_PAD(GpioData->GpioPad); |
| 170 | GroupIndex = GPIO_GET_GROUP_INDEX_FROM_PAD(GpioData->GpioPad); |
| 171 | PadNumber = GPIO_GET_PAD_NUMBER(GpioData->GpioPad); |
| 172 | |
| 173 | // |
| 174 | // Check if group index argument exceeds GPIO group index range |
| 175 | // |
| 176 | if (GroupIndex >= V_PCH_GPIO_GROUP_MAX) { |
| 177 | printk(BIOS_ERR, "GPIO ERROR: Invalid Group Index " |
| 178 | "(GroupIndex=%d, Pad=%d)!\n", |
| 179 | GroupIndex, PadNumber); |
| 180 | continue; |
| 181 | } |
| 182 | |
| 183 | // |
| 184 | // Check if group argument exceeds GPIO group range |
| 185 | // |
| 186 | if ((Group < GpioGroupOffset) || |
| 187 | (Group >= NumberOfGroups + GpioGroupOffset)) { |
| 188 | printk(BIOS_ERR, |
| 189 | "GPIO ERROR: Invalid Group (Group=%d)!\n", |
| 190 | Group); |
| 191 | return; |
| 192 | } |
| 193 | |
| 194 | // |
| 195 | // Check if legal pin number |
| 196 | // |
| 197 | if (PadNumber >= GpioGroupInfo[GroupIndex].PadPerGroup) { |
| 198 | printk(BIOS_ERR, "GPIO ERROR: Invalid PadNumber " |
| 199 | "(PadNumber=%d)!\n", |
| 200 | PadNumber); |
| 201 | return; |
| 202 | } |
| 203 | |
| 204 | // |
| 205 | // Check if selected GPIO Pad is not owned by CSME/ISH |
| 206 | // |
| 207 | GpioGetPadOwnership(GpioData->GpioPad, &PadOwnVal); |
| 208 | |
| 209 | if (PadOwnVal != GpioPadOwnHost) { |
| 210 | printk(BIOS_ERR, "GPIO WARNING: Accessing pad not " |
| 211 | "owned by host (Group=%d, Pad=%d)!", |
| 212 | GroupIndex, PadNumber); |
| 213 | if (PadOwnVal == GpioPadOwnCsme) |
| 214 | printk(BIOS_ERR, "The owner is CSME\n"); |
| 215 | else if (PadOwnVal == GpioPadOwnIsh) |
| 216 | printk(BIOS_ERR, "The owner is ISH\n"); |
| 217 | printk(BIOS_ERR, "** Please make sure the GPIO usage " |
| 218 | "in sync between CSME/ISH and Host IA " |
| 219 | "FW configuration.\n"); |
| 220 | printk(BIOS_ERR, "** All the GPIO occupied by CSME/ISH " |
| 221 | "should not do any configuration by " |
| 222 | "Host IA FW.\n"); |
| 223 | continue; |
| 224 | } |
| 225 | |
| 226 | // |
| 227 | // Configure Reset Type (PadRstCfg) |
| 228 | // |
| 229 | Dw0RegMask |= |
| 230 | ((((GpioData->GpioConfig.PowerConfig & |
| 231 | GPIO_CONF_RESET_MASK) >> |
| 232 | GPIO_CONF_RESET_BIT_POS) == GpioHardwareDefault) |
| 233 | ? 0x0 |
| 234 | : B_PCH_GPIO_RST_CONF); |
| 235 | Dw0Reg |= (((GpioData->GpioConfig.PowerConfig & |
| 236 | GPIO_CONF_RESET_MASK) >> |
| 237 | (GPIO_CONF_RESET_BIT_POS + 1)) |
| 238 | << N_PCH_GPIO_RST_CONF); |
| 239 | |
| 240 | // |
| 241 | // Configure how interrupt is triggered (RxEvCfg) |
| 242 | // |
| 243 | Dw0RegMask |= |
| 244 | ((((GpioData->GpioConfig.InterruptConfig & |
| 245 | GPIO_CONF_INT_TRIG_MASK) >> |
| 246 | GPIO_CONF_INT_TRIG_BIT_POS) == GpioHardwareDefault) |
| 247 | ? 0x0 |
| 248 | : B_PCH_GPIO_RX_LVL_EDG); |
| 249 | Dw0Reg |= (((GpioData->GpioConfig.InterruptConfig & |
| 250 | GPIO_CONF_INT_TRIG_MASK) >> |
| 251 | (GPIO_CONF_INT_TRIG_BIT_POS + 1)) |
| 252 | << N_PCH_GPIO_RX_LVL_EDG); |
| 253 | |
| 254 | // |
| 255 | // Configure interrupt generation (GPIRoutIOxAPIC/SCI/SMI/NMI) |
| 256 | // |
| 257 | Dw0RegMask |= |
| 258 | ((((GpioData->GpioConfig.InterruptConfig & |
| 259 | GPIO_CONF_INT_ROUTE_MASK) >> |
| 260 | GPIO_CONF_INT_ROUTE_BIT_POS) == GpioHardwareDefault) |
| 261 | ? 0x0 |
| 262 | : (B_PCH_GPIO_RX_NMI_ROUTE | |
| 263 | B_PCH_GPIO_RX_SCI_ROUTE | |
| 264 | B_PCH_GPIO_RX_SMI_ROUTE | |
| 265 | B_PCH_GPIO_RX_APIC_ROUTE)); |
| 266 | Dw0Reg |= (((GpioData->GpioConfig.InterruptConfig & |
| 267 | GPIO_CONF_INT_ROUTE_MASK) >> |
| 268 | (GPIO_CONF_INT_ROUTE_BIT_POS + 1)) |
| 269 | << N_PCH_GPIO_RX_NMI_ROUTE); |
| 270 | |
Jonathan Neuschäfer | 5268b76 | 2018-02-12 12:24:25 +0100 | [diff] [blame] | 271 | // If CFIO is not Working as GPIO mode, Don't move TxDisable and |
Mariusz Szafranski | a404133 | 2017-08-02 17:28:17 +0200 | [diff] [blame] | 272 | // RxDisable |
| 273 | if (GpioData->GpioConfig.PadMode == GpioPadModeGpio) { |
| 274 | // |
| 275 | // Configure GPIO direction (GPIORxDis and GPIOTxDis) |
| 276 | // |
| 277 | Dw0RegMask |= ((((GpioData->GpioConfig.Direction & |
| 278 | GPIO_CONF_DIR_MASK) >> |
| 279 | GPIO_CONF_DIR_BIT_POS) == |
| 280 | GpioHardwareDefault) |
| 281 | ? 0x0 |
| 282 | : (B_PCH_GPIO_RXDIS | |
| 283 | B_PCH_GPIO_TXDIS)); |
| 284 | Dw0Reg |= (((GpioData->GpioConfig.Direction & |
| 285 | GPIO_CONF_DIR_MASK) >> |
| 286 | (GPIO_CONF_DIR_BIT_POS + 1)) |
| 287 | << N_PCH_GPIO_TXDIS); |
| 288 | } |
| 289 | |
| 290 | // |
| 291 | // Configure GPIO input inversion (RXINV) |
| 292 | // |
| 293 | Dw0RegMask |= ((((GpioData->GpioConfig.Direction & |
| 294 | GPIO_CONF_INV_MASK) >> |
| 295 | GPIO_CONF_INV_BIT_POS) == GpioHardwareDefault) |
| 296 | ? 0x0 |
| 297 | : B_PCH_GPIO_RXINV); |
| 298 | Dw0Reg |= (((GpioData->GpioConfig.Direction & |
| 299 | GPIO_CONF_INV_MASK) >> |
| 300 | (GPIO_CONF_INV_BIT_POS + 1)) |
| 301 | << N_PCH_GPIO_RXINV); |
| 302 | |
| 303 | // |
| 304 | // Configure GPIO output state (GPIOTxState) |
| 305 | // |
| 306 | Dw0RegMask |= |
| 307 | ((((GpioData->GpioConfig.OutputState & |
| 308 | GPIO_CONF_OUTPUT_MASK) >> |
| 309 | GPIO_CONF_OUTPUT_BIT_POS) == GpioHardwareDefault) |
| 310 | ? 0x0 |
| 311 | : B_PCH_GPIO_TX_STATE); |
| 312 | Dw0Reg |= (((GpioData->GpioConfig.OutputState & |
| 313 | GPIO_CONF_OUTPUT_MASK) >> |
| 314 | (GPIO_CONF_OUTPUT_BIT_POS + 1)) |
| 315 | << N_PCH_GPIO_TX_STATE); |
| 316 | |
| 317 | // |
| 318 | // Configure GPIO RX raw override to '1' (RXRAW1) |
| 319 | // |
| 320 | Dw0RegMask |= |
| 321 | ((((GpioData->GpioConfig.OtherSettings & |
| 322 | GPIO_CONF_RXRAW_MASK) >> |
| 323 | GPIO_CONF_RXRAW_BIT_POS) == GpioHardwareDefault) |
| 324 | ? 0x0 |
| 325 | : B_PCH_GPIO_RX_RAW1); |
| 326 | Dw0Reg |= (((GpioData->GpioConfig.OtherSettings & |
| 327 | GPIO_CONF_RXRAW_MASK) >> |
| 328 | (GPIO_CONF_RXRAW_BIT_POS + 1)) |
| 329 | << N_PCH_GPIO_RX_RAW1); |
| 330 | |
| 331 | // |
| 332 | // Configure GPIO Pad Mode (PMode) |
| 333 | // |
| 334 | Dw0RegMask |= |
| 335 | ((((GpioData->GpioConfig.PadMode & |
| 336 | GPIO_CONF_PAD_MODE_MASK) >> |
| 337 | GPIO_CONF_PAD_MODE_BIT_POS) == GpioHardwareDefault) |
| 338 | ? 0x0 |
| 339 | : B_PCH_GPIO_PAD_MODE); |
| 340 | Dw0Reg |= (((GpioData->GpioConfig.PadMode & |
| 341 | GPIO_CONF_PAD_MODE_MASK) >> |
| 342 | (GPIO_CONF_PAD_MODE_BIT_POS + 1)) |
| 343 | << N_PCH_GPIO_PAD_MODE); |
| 344 | |
| 345 | // |
| 346 | // Configure GPIO termination (Term) |
| 347 | // |
| 348 | Dw1RegMask |= ((((GpioData->GpioConfig.ElectricalConfig & |
| 349 | GPIO_CONF_TERM_MASK) >> |
| 350 | GPIO_CONF_TERM_BIT_POS) == GpioHardwareDefault) |
| 351 | ? 0x0 |
| 352 | : B_PCH_GPIO_TERM); |
| 353 | Dw1Reg |= (((GpioData->GpioConfig.ElectricalConfig & |
| 354 | GPIO_CONF_TERM_MASK) >> |
| 355 | (GPIO_CONF_TERM_BIT_POS + 1)) |
| 356 | << N_PCH_GPIO_TERM); |
| 357 | |
| 358 | // |
| 359 | // Configure GPIO pad tolerance (padtol) |
| 360 | // |
| 361 | Dw1RegMask |= |
| 362 | ((((GpioData->GpioConfig.ElectricalConfig & |
| 363 | GPIO_CONF_PADTOL_MASK) >> |
| 364 | GPIO_CONF_PADTOL_BIT_POS) == GpioHardwareDefault) |
| 365 | ? 0x0 |
| 366 | : B_PCH_GPIO_PADTOL); |
| 367 | Dw1Reg |= (((GpioData->GpioConfig.ElectricalConfig & |
| 368 | GPIO_CONF_PADTOL_MASK) >> |
| 369 | (GPIO_CONF_PADTOL_BIT_POS + 1)) |
| 370 | << N_PCH_GPIO_PADTOL); |
| 371 | |
| 372 | // |
| 373 | // Check for additional requirements on setting PADCFG register |
| 374 | // |
| 375 | |
| 376 | // |
| 377 | // Create PADCFG register offset using group and pad number |
| 378 | // |
| 379 | PadCfgReg = 0x8 * PadNumber + |
| 380 | GpioGroupInfo[GroupIndex].PadCfgOffset; |
| 381 | Data32 = read32((void *)PCH_PCR_ADDRESS( |
| 382 | GpioGroupInfo[GroupIndex].Community, PadCfgReg)); |
| 383 | |
| 384 | FinalValue = ((Data32 & (~Dw0RegMask)) | Dw0Reg); |
| 385 | |
| 386 | PadMode1 = |
| 387 | (Data32 & B_PCH_GPIO_PAD_MODE) >> N_PCH_GPIO_PAD_MODE; |
| 388 | PadMode2 = |
| 389 | (Dw0Reg & B_PCH_GPIO_PAD_MODE) >> N_PCH_GPIO_PAD_MODE; |
| 390 | |
| 391 | if (((Data32 & B_PCH_GPIO_PAD_MODE) != |
| 392 | (FinalValue & B_PCH_GPIO_PAD_MODE)) || |
| 393 | (PadMode2 == 0)) { |
| 394 | printk(BIOS_DEBUG, "Changing GpioPad PID: %x Offset: " |
| 395 | "0x%x PadModeP1: %d P2: %d ", |
| 396 | GpioGroupInfo[GroupIndex].Community, PadCfgReg, |
| 397 | PadMode1, PadMode2); |
| 398 | printk(BIOS_DEBUG, "R: 0x%08x Fx%08x !\n", Data32, |
| 399 | FinalValue); |
| 400 | // |
| 401 | // Write PADCFG DW0 register`` |
| 402 | // |
| 403 | mmio_andthenor32( |
| 404 | (void *)(uint32_t)PCH_PCR_ADDRESS( |
| 405 | GpioGroupInfo[GroupIndex].Community, |
| 406 | PadCfgReg), |
| 407 | ~(uint32_t)Dw0RegMask, (uint32_t)Dw0Reg); |
| 408 | } |
| 409 | |
| 410 | Data32 = read32((void *)PCH_PCR_ADDRESS( |
| 411 | GpioGroupInfo[GroupIndex].Community, PadCfgReg + 0x4)); |
| 412 | FinalValue = ((Data32 & (~Dw1RegMask)) | Dw1Reg); |
| 413 | if (Data32 != FinalValue) { |
| 414 | // |
| 415 | // Write PADCFG DW1 register |
| 416 | // |
| 417 | mmio_andthenor32( |
| 418 | (void *)(uint32_t)PCH_PCR_ADDRESS( |
| 419 | GpioGroupInfo[GroupIndex].Community, |
| 420 | PadCfgReg + 0x4), |
| 421 | ~(uint32_t)Dw1RegMask, (uint32_t)Dw1Reg); |
| 422 | } |
| 423 | |
| 424 | // |
| 425 | // Update value to be programmed in HOSTSW_OWN register |
| 426 | // |
Patrick Rudolph | dcf30e8 | 2022-03-22 09:02:16 +0100 | [diff] [blame] | 427 | HostSoftOwnRegMask[GroupIndex] |= |
| 428 | ((uint64_t)GpioData->GpioConfig.HostSoftPadOwn & 0x1) << PadNumber; |
| 429 | HostSoftOwnReg[GroupIndex] |= |
| 430 | ((uint64_t)GpioData->GpioConfig.HostSoftPadOwn >> 0x1) << PadNumber; |
Mariusz Szafranski | a404133 | 2017-08-02 17:28:17 +0200 | [diff] [blame] | 431 | |
| 432 | // |
| 433 | // Update value to be programmed in GPI_GPE_EN register |
| 434 | // |
Patrick Rudolph | dcf30e8 | 2022-03-22 09:02:16 +0100 | [diff] [blame] | 435 | GpiGpeEnRegMask[GroupIndex] |= |
| 436 | ((uint64_t)GpioData->GpioConfig.InterruptConfig & 0x1) << PadNumber; |
| 437 | GpiGpeEnReg[GroupIndex] |= |
| 438 | (((uint64_t)GpioData->GpioConfig.InterruptConfig & GpioIntSci) >> 3) |
| 439 | << PadNumber; |
Mariusz Szafranski | a404133 | 2017-08-02 17:28:17 +0200 | [diff] [blame] | 440 | } |
| 441 | |
| 442 | for (Index = 0; Index < NumberOfGroups; Index++) { |
| 443 | // |
| 444 | // Write HOSTSW_OWN registers |
| 445 | // |
| 446 | if (GpioGroupInfo[Index].HostOwnOffset != |
| 447 | NO_REGISTER_FOR_PROPERTY) { |
| 448 | mmio_andthenor32( |
| 449 | (void *)PCH_PCR_ADDRESS( |
| 450 | GpioGroupInfo[Index].Community, |
| 451 | GpioGroupInfo[Index].HostOwnOffset), |
| 452 | ~(uint32_t)(HostSoftOwnRegMask[Index] & |
| 453 | 0xFFFFFFFF), |
| 454 | (uint32_t)(HostSoftOwnReg[Index] & 0xFFFFFFFF)); |
| 455 | mmio_andthenor32( |
| 456 | (void *)PCH_PCR_ADDRESS( |
| 457 | GpioGroupInfo[Index].Community, |
| 458 | GpioGroupInfo[Index].HostOwnOffset + |
| 459 | 0x4), |
Patrick Rudolph | dcf30e8 | 2022-03-22 09:02:16 +0100 | [diff] [blame] | 460 | ~(uint32_t)(HostSoftOwnRegMask[Index] >> 32), |
| 461 | (uint32_t)(HostSoftOwnReg[Index] >> 32)); |
Mariusz Szafranski | a404133 | 2017-08-02 17:28:17 +0200 | [diff] [blame] | 462 | } |
| 463 | |
| 464 | // |
| 465 | // Write GPI_GPE_EN registers |
| 466 | // |
| 467 | if (GpioGroupInfo[Index].GpiGpeEnOffset != |
| 468 | NO_REGISTER_FOR_PROPERTY) { |
| 469 | mmio_andthenor32( |
| 470 | (void *)PCH_PCR_ADDRESS( |
| 471 | GpioGroupInfo[Index].Community, |
| 472 | GpioGroupInfo[Index].GpiGpeEnOffset), |
| 473 | ~(uint32_t)(GpiGpeEnRegMask[Index] & |
| 474 | 0xFFFFFFFF), |
| 475 | (uint32_t)(GpiGpeEnReg[Index] & 0xFFFFFFFF)); |
| 476 | mmio_andthenor32( |
| 477 | (void *)PCH_PCR_ADDRESS( |
| 478 | GpioGroupInfo[Index].Community, |
| 479 | GpioGroupInfo[Index].GpiGpeEnOffset + |
| 480 | 0x4), |
Patrick Rudolph | dcf30e8 | 2022-03-22 09:02:16 +0100 | [diff] [blame] | 481 | ~(uint32_t)(GpiGpeEnRegMask[Index] >> 32), |
| 482 | (uint32_t)(GpiGpeEnReg[Index] >> 32)); |
Mariusz Szafranski | a404133 | 2017-08-02 17:28:17 +0200 | [diff] [blame] | 483 | } |
| 484 | } |
| 485 | } |