xref: /aosp_15_r20/external/coreboot/src/soc/intel/denverton_ns/gpio_dnv.c (revision b9411a12aaaa7e1e6a6fb7c5e057f44ee179a49c)
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 
3 #include <stdint.h>
4 #include <string.h>
5 #include <device/mmio.h>
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>
13 #include <soc/gpio_dnv.h>
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 *
GpioGetGroupInfoTable(uint32_t * GpioGroupInfoTableLength)60 GpioGetGroupInfoTable(uint32_t *GpioGroupInfoTableLength)
61 {
62 	*GpioGroupInfoTableLength = ARRAY_SIZE(mGpioGroupInfo);
63 	return (struct GPIO_GROUP_INFO *)mGpioGroupInfo;
64 }
65 
66 /* Get Gpio Pad Ownership */
GpioGetPadOwnership(GPIO_PAD GpioPad,GPIO_PAD_OWN * PadOwnVal)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 
gpio_configure_dnv_pads(const struct dnv_pad_config * gpio,size_t num)120 void gpio_configure_dnv_pads(const struct dnv_pad_config *gpio, size_t num)
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;
141 	struct dnv_pad_config *GpioData;
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++) {
162 		Dw0RegMask = 0;
163 		Dw0Reg = 0;
164 		Dw1RegMask = 0;
165 		Dw1Reg = 0;
166 
167 		GpioData = (struct dnv_pad_config *)&(gpio[Index]);
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 
271 		// If CFIO is not Working as GPIO mode, Don't move TxDisable and
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 		//
427 		HostSoftOwnRegMask[GroupIndex] |=
428 			((uint64_t)GpioData->GpioConfig.HostSoftPadOwn & 0x1) << PadNumber;
429 		HostSoftOwnReg[GroupIndex] |=
430 			((uint64_t)GpioData->GpioConfig.HostSoftPadOwn >> 0x1) << PadNumber;
431 
432 		//
433 		// Update value to be programmed in GPI_GPE_EN register
434 		//
435 		GpiGpeEnRegMask[GroupIndex] |=
436 			((uint64_t)GpioData->GpioConfig.InterruptConfig & 0x1) << PadNumber;
437 		GpiGpeEnReg[GroupIndex] |=
438 			(((uint64_t)GpioData->GpioConfig.InterruptConfig & GpioIntSci) >> 3)
439 			<< PadNumber;
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),
460 				~(uint32_t)(HostSoftOwnRegMask[Index] >> 32),
461 				(uint32_t)(HostSoftOwnReg[Index] >> 32));
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),
481 				~(uint32_t)(GpiGpeEnRegMask[Index] >> 32),
482 				(uint32_t)(GpiGpeEnReg[Index] >> 32));
483 		}
484 	}
485 }
486