1 /** @file
2   This file contains routines for GPIO native and chipset specific usage
3 
4 Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
6 
7 **/
8 #include "GpioLibrary.h"
9 
10 //
11 // Chipset specific data
12 //
13 //SerialIo
14 extern GPIO_PAD_NATIVE_FUNCTION mPchLpI2cGpio[PCH_LP_SERIALIO_MAX_I2C_CONTROLLERS][PCH_SERIAL_IO_PINS_PER_I2C_CONTROLLER];
15 extern GPIO_PAD_NATIVE_FUNCTION mPchHI2cGpio[PCH_H_SERIALIO_MAX_I2C_CONTROLLERS][PCH_SERIAL_IO_PINS_PER_I2C_CONTROLLER];
16 extern GPIO_PAD_NATIVE_FUNCTION mPchLpUartGpio[PCH_SERIALIO_MAX_UART_CONTROLLERS][PCH_SERIAL_IO_PINS_PER_UART_CONTROLLER];
17 extern GPIO_PAD_NATIVE_FUNCTION mPchHUartGpio[PCH_SERIALIO_MAX_UART_CONTROLLERS][PCH_SERIAL_IO_PINS_PER_UART_CONTROLLER];
18 extern GPIO_PAD_NATIVE_FUNCTION mPchLpSpiGpio[PCH_SERIALIO_MAX_SPI_CONTROLLERS][PCH_SERIAL_IO_PINS_PER_SPI_CONTROLLER];
19 extern GPIO_PAD_NATIVE_FUNCTION mPchHSpiGpio[PCH_SERIALIO_MAX_SPI_CONTROLLERS][PCH_SERIAL_IO_PINS_PER_SPI_CONTROLLER];
20 
21 //SATA
22 extern GPIO_PAD_NATIVE_FUNCTION mPchLpSataPortResetToGpioMap[PCH_LP_AHCI_MAX_PORTS];
23 extern GPIO_PAD_NATIVE_FUNCTION mPchHSataPortResetToGpioMap[PCH_H_AHCI_MAX_PORTS];
24 extern GPIO_PAD_NATIVE_FUNCTION mPchLpSataDevSlpPinToGpioMap[PCH_LP_AHCI_MAX_PORTS];
25 extern GPIO_PAD_NATIVE_FUNCTION mPchHSataDevSlpPinToGpioMap[PCH_H_AHCI_MAX_PORTS];
26 
27 //
28 // SKL specific
29 //
30 extern GPIO_GROUP_INFO mPchLpGpioGroupInfo[V_PCH_LP_GPIO_GROUP_MAX];
31 extern GPIO_GROUP_INFO mPchHGpioGroupInfo[V_PCH_H_GPIO_GROUP_MAX];
32 
33 /**
34   This procedure will set GPIO mode
35 
36   @param[in]  GpioPad             GPIO pad
37   @param[out] PadModeValue        GPIO pad mode value
38 
39   @retval EFI_SUCCESS             The function completed successfully
40   @retval EFI_INVALID_PARAMETER   Invalid group or pad number
41 **/
42 EFI_STATUS
SetGpioPadMode(IN GPIO_PAD GpioPad,IN GPIO_PAD_MODE PadModeValue)43 SetGpioPadMode (
44   IN GPIO_PAD                GpioPad,
45   IN GPIO_PAD_MODE           PadModeValue
46   )
47 {
48   UINT32               PadCfgOrMask;
49 
50   if (!GpioIsPadValid (GpioPad)) {
51     ASSERT (FALSE);
52     return EFI_INVALID_PARAMETER;
53   }
54 
55   if (!GpioIsPadHostOwned (GpioPad)) {
56     return EFI_UNSUPPORTED;
57   }
58 
59   if (PadModeValue != (GPIO_PAD_MODE)GpioHardwareDefault) {
60 
61     PadCfgOrMask = (((PadModeValue & B_GPIO_PAD_MODE_MASK) >> (N_GPIO_PAD_MODE_BIT_POS + 1)) << N_PCH_GPIO_PAD_MODE);
62 
63     GpioWritePadCfgReg (
64       GpioPad,
65       0,
66       (UINT32)~B_PCH_GPIO_PAD_MODE,
67       PadCfgOrMask
68       );
69   }
70 
71   return EFI_SUCCESS;
72 }
73 
74 /**
75   This procedure will get GPIO mode
76 
77   @param[in]  GpioPad             GPIO pad
78   @param[out] PadModeValue        GPIO pad mode value
79 
80   @retval EFI_SUCCESS             The function completed successfully
81   @retval EFI_INVALID_PARAMETER   Invalid GpioPad
82 **/
83 EFI_STATUS
GetGpioPadMode(IN GPIO_PAD GpioPad,OUT GPIO_PAD_MODE * PadModeValue)84 GetGpioPadMode (
85   IN  GPIO_PAD                 GpioPad,
86   OUT GPIO_PAD_MODE            *PadModeValue
87   )
88 {
89   UINT32        PadCfgRegValue;
90 
91   if (!GpioIsPadValid (GpioPad)) {
92     ASSERT (FALSE);
93     return EFI_INVALID_PARAMETER;
94   }
95 
96   if (!GpioIsPadHostOwned (GpioPad)) {
97     return EFI_UNSUPPORTED;
98   }
99 
100   GpioReadPadCfgReg (
101     GpioPad,
102     0,
103     &PadCfgRegValue
104     );
105 
106   *PadModeValue = (GPIO_PAD_MODE)(((PadCfgRegValue & B_PCH_GPIO_PAD_MODE) >> (N_PCH_GPIO_PAD_MODE - (N_GPIO_PAD_MODE_BIT_POS + 1))) | (0x1 << N_GPIO_PAD_MODE_BIT_POS));
107 
108   return EFI_SUCCESS;
109 }
110 
111 
112 /**
113   This procedure will retrieve address and length of GPIO info table
114 
115   @param[out]  GpioGroupInfoTableLength   Length of GPIO group table
116 
117   @retval Pointer to GPIO group table
118 
119 **/
120 GPIO_GROUP_INFO*
GpioGetGroupInfoTable(OUT UINTN * GpioGroupInfoTableLength)121 GpioGetGroupInfoTable (
122   OUT UINTN               *GpioGroupInfoTableLength
123   )
124 {
125   if (GetPchSeries () == PchLp) {
126     *GpioGroupInfoTableLength = sizeof (mPchLpGpioGroupInfo) / sizeof (GPIO_GROUP_INFO);
127     return mPchLpGpioGroupInfo;
128   } else {
129     *GpioGroupInfoTableLength = sizeof (mPchHGpioGroupInfo) / sizeof (GPIO_GROUP_INFO);
130     return mPchHGpioGroupInfo;
131   }
132 }
133 
134 
135 /**
136   This procedure is used to check if GpioPad is valid for certain chipset
137 
138   @param[in]  GpioPad             GPIO pad
139 
140   @retval TRUE                    This pin is valid on this chipset
141           FALSE                   Incorrect pin
142 **/
143 BOOLEAN
GpioIsCorrectPadForThisChipset(IN GPIO_PAD GpioPad)144 GpioIsCorrectPadForThisChipset (
145   IN  GPIO_PAD        GpioPad
146   )
147 {
148   PCH_SERIES PchSeries;
149 
150   PchSeries = GetPchSeries ();
151 
152   if ((PchSeries == PchH) && (GPIO_GET_CHIPSET_ID (GpioPad) == GPIO_SKL_H_CHIPSET_ID)) {
153     return TRUE;
154   } else if ((PchSeries == PchLp) && (GPIO_GET_CHIPSET_ID (GpioPad) == GPIO_SKL_LP_CHIPSET_ID)) {
155     return TRUE;
156   }
157 
158   return FALSE;
159 }
160 
161 
162 /**
163   This procedure will get number of pads for certain GPIO group
164 
165   @param[in] Group            GPIO group number
166 
167   @retval Value               Pad number for group
168                               If illegal group number then return 0
169 **/
170 UINT32
GpioGetPadPerGroup(IN GPIO_GROUP Group)171 GpioGetPadPerGroup (
172   IN GPIO_GROUP      Group
173   )
174 {
175   GPIO_GROUP_INFO     *GpioGroupInfo;
176   UINTN               GpioGroupInfoLength;
177   UINT32              GroupIndex;
178   //
179   // Check if group argument exceeds GPIO GROUP INFO array
180   //
181   GpioGroupInfo = GpioGetGroupInfoTable (&GpioGroupInfoLength);
182   GroupIndex = GpioGetGroupIndexFromGroup (Group);
183 
184   if ((UINTN) GroupIndex >= GpioGroupInfoLength) {
185     ASSERT (FALSE);
186     return 0;
187   } else {
188     return GpioGroupInfo[GroupIndex].PadPerGroup;
189   }
190 }
191 
192 /**
193   This procedure will get number of groups
194 
195   @param[in] none
196 
197   @retval Value               Group number
198 **/
199 UINT8
GpioGetNumberOfGroups(VOID)200 GpioGetNumberOfGroups (
201   VOID
202   )
203 {
204   if (GetPchSeries () == PchLp) {
205     return V_PCH_LP_GPIO_GROUP_MAX;
206   } else {
207     return V_PCH_H_GPIO_GROUP_MAX;
208   }
209 }
210 /**
211   This procedure will get lowest group
212 
213   @param[in] none
214 
215   @retval Value               Lowest Group
216 **/
217 GPIO_GROUP
GpioGetLowestGroup(VOID)218 GpioGetLowestGroup (
219   VOID
220   )
221 {
222   if (GetPchSeries () == PchLp) {
223     return (UINT32) GPIO_SKL_LP_GROUP_GPP_A;
224   } else {
225     return (UINT32) GPIO_SKL_H_GROUP_GPP_A;
226   }
227 }
228 /**
229   This procedure will get highest group
230 
231   @param[in] none
232 
233   @retval Value               Highest Group
234 **/
235 GPIO_GROUP
GpioGetHighestGroup(VOID)236 GpioGetHighestGroup (
237   VOID
238   )
239 {
240   if (GetPchSeries () == PchLp) {
241     return (UINT32) GPIO_SKL_LP_GROUP_GPD;
242   } else {
243     return (UINT32) GPIO_SKL_H_GROUP_GPD;
244   }
245 }
246 
247 /**
248   This procedure will get group number
249 
250   @param[in] GpioPad          Gpio Pad
251 
252   @retval Value               Group number
253 **/
254 GPIO_GROUP
GpioGetGroupFromGpioPad(IN GPIO_PAD GpioPad)255 GpioGetGroupFromGpioPad (
256   IN GPIO_PAD         GpioPad
257   )
258 {
259   return GPIO_GET_GROUP_FROM_PAD (GpioPad);
260 }
261 
262 /**
263   This procedure will get group index (0 based)
264 
265   @param[in] GpioPad          Gpio Pad
266 
267   @retval Value               Group Index
268 **/
269 UINT32
GpioGetGroupIndexFromGpioPad(IN GPIO_PAD GpioPad)270 GpioGetGroupIndexFromGpioPad (
271   IN GPIO_PAD        GpioPad
272   )
273 {
274   return (UINT32) GPIO_GET_GROUP_INDEX_FROM_PAD (GpioPad);
275 }
276 
277 /**
278   This procedure will get group index (0 based) from group
279 
280   @param[in] GpioGroup        Gpio Group
281 
282   @retval Value               Group Index
283 **/
284 UINT32
GpioGetGroupIndexFromGroup(IN GPIO_GROUP GpioGroup)285 GpioGetGroupIndexFromGroup (
286   IN GPIO_GROUP        GpioGroup
287   )
288 {
289   return (UINT32) GPIO_GET_GROUP_INDEX (GpioGroup);
290 }
291 
292 /**
293   This procedure will get pad number (0 based) from Gpio Pad
294 
295   @param[in] GpioPad          Gpio Pad
296 
297   @retval Value               Pad Number
298 **/
299 UINT32
GpioGetPadNumberFromGpioPad(IN GPIO_PAD GpioPad)300 GpioGetPadNumberFromGpioPad (
301   IN GPIO_PAD        GpioPad
302   )
303 {
304   return (UINT32) GPIO_GET_PAD_NUMBER (GpioPad);
305 }
306 /**
307   This procedure will return GpioPad from Group and PadNumber
308 
309   @param[in] Group              GPIO group
310   @param[in] PadNumber          GPIO PadNumber
311 
312   @retval GpioPad               GpioPad
313 **/
314 GPIO_PAD
GpioGetGpioPadFromGroupAndPadNumber(IN GPIO_GROUP Group,IN UINT32 PadNumber)315 GpioGetGpioPadFromGroupAndPadNumber (
316   IN GPIO_GROUP      Group,
317   IN UINT32          PadNumber
318   )
319 {
320   if (GetPchSeries () == PchLp) {
321     return GPIO_PAD_DEF (Group,PadNumber);
322   } else {
323     return GPIO_PAD_DEF (Group,PadNumber);
324   }
325 }
326 
327 /**
328   This procedure will return GpioPad from GroupIndex and PadNumber
329 
330   @param[in] GroupIndex         GPIO GroupIndex
331   @param[in] PadNumber          GPIO PadNumber
332 
333   @retval GpioPad               GpioPad
334 **/
335 GPIO_PAD
GpioGetGpioPadFromGroupIndexAndPadNumber(IN UINT32 GroupIndex,IN UINT32 PadNumber)336 GpioGetGpioPadFromGroupIndexAndPadNumber (
337   IN UINT32          GroupIndex,
338   IN UINT32          PadNumber
339   )
340 {
341   GPIO_GROUP Group;
342 
343   if (GetPchSeries () == PchLp) {
344     Group = GPIO_GROUP_DEF (GroupIndex, GPIO_SKL_LP_CHIPSET_ID);
345     return GPIO_PAD_DEF (Group,PadNumber);
346   } else {
347     Group = GPIO_GROUP_DEF (GroupIndex, GPIO_SKL_H_CHIPSET_ID);
348     return GPIO_PAD_DEF (Group,PadNumber);
349   }
350 }
351 
352 
353 /**
354   This function sets SerialIo I2C controller pins into native mode
355 
356   @param[in]  SerialIoI2cControllerNumber   I2C controller
357 
358   @retval Status
359 **/
360 EFI_STATUS
GpioSetSerialIoI2cPinsIntoNativeMode(IN UINT32 SerialIoI2cControllerNumber)361 GpioSetSerialIoI2cPinsIntoNativeMode (
362   IN  UINT32            SerialIoI2cControllerNumber
363   )
364 {
365   EFI_STATUS               Status;
366   UINTN                    Index;
367   GPIO_PAD_NATIVE_FUNCTION (*I2cGpio) [PCH_SERIAL_IO_PINS_PER_I2C_CONTROLLER];
368 
369   Status = EFI_SUCCESS;
370 
371   if (GetPchSeries () == PchLp) {
372     ASSERT (SerialIoI2cControllerNumber < PCH_LP_SERIALIO_MAX_I2C_CONTROLLERS);
373     I2cGpio = mPchLpI2cGpio;
374   } else {
375     ASSERT (SerialIoI2cControllerNumber < PCH_H_SERIALIO_MAX_I2C_CONTROLLERS);
376     I2cGpio = mPchHI2cGpio;
377   }
378 
379   for (Index = 0; Index < PCH_SERIAL_IO_PINS_PER_I2C_CONTROLLER; Index++) {
380     Status = SetGpioPadMode (I2cGpio[SerialIoI2cControllerNumber][Index].Pad, I2cGpio[SerialIoI2cControllerNumber][Index].Mode);
381     if (EFI_ERROR (Status)) {
382       return EFI_UNSUPPORTED;
383     }
384     GpioSetInputInversion (I2cGpio[SerialIoI2cControllerNumber][Index].Pad, 0);
385   }
386   return Status;
387 }
388 
389 /**
390   This function sets SerialIo I2C controller pins tolerance
391 
392   @param[in]  SerialIoI2CControllerNumber   I2C controller
393   @param[in]  Pad1v8Tolerance               TRUE:  Enable  1v8 Pad tolerance
394                                             FALSE: Disable 1v8 Pad tolerance
395 
396   @retval Status
397 **/
398 EFI_STATUS
GpioSetSerialIoI2CPinsTolerance(IN UINT32 SerialIoI2cControllerNumber,IN BOOLEAN Pad1v8Tolerance)399 GpioSetSerialIoI2CPinsTolerance (
400   IN  UINT32            SerialIoI2cControllerNumber,
401   IN  BOOLEAN           Pad1v8Tolerance
402   )
403 {
404   EFI_STATUS               Status;
405   UINTN                    Index;
406   GPIO_PAD_OWN             PadOwnership;
407   GPIO_PAD_NATIVE_FUNCTION (*I2cGpio) [PCH_SERIAL_IO_PINS_PER_I2C_CONTROLLER];
408   GPIO_CONFIG              GpioData;
409 
410   Status = EFI_SUCCESS;
411 
412   if (GetPchSeries () == PchLp) {
413     ASSERT (SerialIoI2cControllerNumber < PCH_LP_SERIALIO_MAX_I2C_CONTROLLERS);
414     I2cGpio = mPchLpI2cGpio;
415   } else {
416     ASSERT (SerialIoI2cControllerNumber < PCH_H_SERIALIO_MAX_I2C_CONTROLLERS);
417     I2cGpio = mPchHI2cGpio;
418   }
419 
420   ZeroMem (&GpioData, sizeof (GPIO_CONFIG));
421   if (Pad1v8Tolerance) {
422     GpioData.ElectricalConfig = GpioTolerance1v8;
423   } else {
424     GpioData.ElectricalConfig = GpioNoTolerance1v8;
425   }
426   for (Index = 0; Index < PCH_SERIAL_IO_PINS_PER_I2C_CONTROLLER; Index++) {
427     GpioGetPadOwnership (I2cGpio[SerialIoI2cControllerNumber][Index].Pad , &PadOwnership);
428     if (PadOwnership == GpioPadOwnHost) {
429       Status = GpioSetPadConfig (I2cGpio[SerialIoI2cControllerNumber][Index].Pad, &GpioData);
430     } else {
431       return EFI_UNSUPPORTED;
432     }
433   }
434   return Status;
435 }
436 
437 
438 /**
439   This function sets SerialIo UART controller pins into native mode
440 
441   @param[in]  SerialIoI2CControllerNumber   UART controller
442   @param[in]  HardwareFlowControl           Hardware Flow control
443 
444   @retval Status
445 **/
446 EFI_STATUS
GpioSetSerialIoUartPinsIntoNativeMode(IN UINT32 SerialIoUartControllerNumber,IN BOOLEAN HardwareFlowControl)447 GpioSetSerialIoUartPinsIntoNativeMode (
448   IN  UINT32            SerialIoUartControllerNumber,
449   IN  BOOLEAN           HardwareFlowControl
450   )
451 {
452   EFI_STATUS    Status;
453   UINTN         Index;
454   UINTN         PinsUsed;
455   GPIO_PAD_NATIVE_FUNCTION (*UartGpio) [PCH_SERIAL_IO_PINS_PER_UART_CONTROLLER];
456 
457   Status = EFI_SUCCESS;
458 
459   ASSERT (SerialIoUartControllerNumber < PCH_SERIALIO_MAX_UART_CONTROLLERS);
460 
461   if (GetPchSeries () == PchLp) {
462     UartGpio = mPchLpUartGpio;
463   } else {
464     UartGpio = mPchHUartGpio;
465   }
466 
467   if (HardwareFlowControl) {
468     PinsUsed = PCH_SERIAL_IO_PINS_PER_UART_CONTROLLER;
469   } else {
470     PinsUsed = PCH_SERIAL_IO_PINS_PER_UART_CONTROLLER_NO_FLOW_CTRL;
471   }
472 
473   for (Index = 0; Index < PinsUsed; Index++) {
474     Status = SetGpioPadMode (UartGpio[SerialIoUartControllerNumber][Index].Pad, UartGpio[SerialIoUartControllerNumber][Index].Mode);
475     if (EFI_ERROR (Status)) {
476       return EFI_UNSUPPORTED;
477     }
478     GpioSetInputInversion (UartGpio[SerialIoUartControllerNumber][Index].Pad, 0);
479   }
480   return Status;
481 }
482 
483 /**
484   This function sets SerialIo SPI controller pins into native mode
485 
486   @param[in]  SerialIoI2CControllerNumber   SPI controller
487 
488   @retval Status
489 **/
490 EFI_STATUS
GpioSetSerialIoSpiPinsIntoNativeMode(IN UINT32 SerialIoSpiControllerNumber)491 GpioSetSerialIoSpiPinsIntoNativeMode (
492   IN  UINT32            SerialIoSpiControllerNumber
493   )
494 {
495   EFI_STATUS    Status;
496   UINTN         Index;
497   GPIO_PAD_NATIVE_FUNCTION (*SpiGpio) [PCH_SERIAL_IO_PINS_PER_SPI_CONTROLLER];
498 
499   Status = EFI_SUCCESS;
500 
501   ASSERT (SerialIoSpiControllerNumber < PCH_SERIALIO_MAX_SPI_CONTROLLERS);
502 
503   if (GetPchSeries () == PchLp) {
504     SpiGpio = mPchLpSpiGpio;
505   } else {
506     SpiGpio = mPchHSpiGpio;
507   }
508 
509   for (Index = 0; Index < PCH_SERIAL_IO_PINS_PER_SPI_CONTROLLER; Index++) {
510     Status = SetGpioPadMode (SpiGpio[SerialIoSpiControllerNumber][Index].Pad, SpiGpio[SerialIoSpiControllerNumber][Index].Mode);
511     if (EFI_ERROR (Status)) {
512       return EFI_UNSUPPORTED;
513     }
514     GpioSetInputInversion (SpiGpio[SerialIoSpiControllerNumber][Index].Pad, 0);
515   }
516   return Status;
517 }
518 
519 
520 /**
521   This function checks if GPIO pin is a GSPI chip select pin
522 
523   @param[in]  GpioPad             GPIO pad
524   @param[in]  PadMode             GPIO pad mode
525 
526   @retval TRUE                    Pin is in GPIO mode
527           FALSE                   Pin is in native mode
528 **/
529 BOOLEAN
GpioIsGpioPadAGSpiCsbPin(IN GPIO_PAD GpioPad,IN GPIO_PAD_MODE PadMode)530 GpioIsGpioPadAGSpiCsbPin (
531   IN  GPIO_PAD        GpioPad,
532   IN  GPIO_PAD_MODE   PadMode
533   )
534 {
535   UINT32                   ControllerMax;
536   UINT32                   ControllerIndex;
537   GPIO_PAD_OWN             PadOwnership;
538   GPIO_PAD_NATIVE_FUNCTION (*SpiGpio) [PCH_SERIAL_IO_PINS_PER_SPI_CONTROLLER];
539 
540   if (GetPchSeries () == PchLp) {
541     SpiGpio = mPchLpSpiGpio;
542     ControllerMax = sizeof (mPchLpSpiGpio) / sizeof (GPIO_PAD_NATIVE_FUNCTION) / PCH_SERIAL_IO_PINS_PER_SPI_CONTROLLER;
543   } else {
544     SpiGpio = mPchHSpiGpio;
545     ControllerMax = sizeof (mPchHSpiGpio) / sizeof (GPIO_PAD_NATIVE_FUNCTION) / PCH_SERIAL_IO_PINS_PER_SPI_CONTROLLER;
546   }
547 
548   for (ControllerIndex = 0; ControllerIndex < ControllerMax; ControllerIndex++) {
549     if ((GpioPad == SpiGpio[ControllerIndex][0].Pad) &&
550         (PadMode == SpiGpio[ControllerIndex][0].Mode)) {
551       GpioGetPadOwnership (SpiGpio[ControllerIndex][0].Pad , &PadOwnership);
552       if (PadOwnership == GpioPadOwnHost) {
553         return TRUE;
554       } else {
555         return FALSE;
556       }
557     }
558   }
559   return FALSE;
560 }
561 
562 /**
563   This function checks if GPIO pin for SATA reset port is in GPIO MODE
564 
565   @param[in]  SataPort            SATA port number
566 
567   @retval TRUE                    Pin is in GPIO mode
568           FALSE                   Pin is in native mode
569 **/
570 BOOLEAN
GpioIsSataResetPortInGpioMode(IN UINTN SataPort)571 GpioIsSataResetPortInGpioMode (
572   IN  UINTN           SataPort
573   )
574 {
575   EFI_STATUS     Status;
576   UINT32         GpioPin;
577   GPIO_PAD_MODE  GpioMode;
578 
579 
580   if (GetPchSeries () == PchLp) {
581     ASSERT (SataPort < PCH_LP_AHCI_MAX_PORTS);
582     GpioPin = mPchLpSataPortResetToGpioMap[SataPort].Pad;
583   } else {
584     ASSERT (SataPort < PCH_H_AHCI_MAX_PORTS);
585     GpioPin = mPchHSataPortResetToGpioMap[SataPort].Pad;
586   }
587 
588   Status =  GetGpioPadMode (GpioPin, &GpioMode);
589   if ((EFI_ERROR (Status)) || (GpioMode != GpioPadModeGpio)) {
590     return FALSE;
591   } else {
592     return TRUE;
593   }
594 }
595 
596 
597 /**
598   This function checks if GPIO pin is a SataDevSlp pin
599 
600   @param[in]  GpioPad             GPIO pad
601   @param[in]  PadMode             GPIO pad mode
602 
603   @retval TRUE                    Pin is in GPIO mode
604           FALSE                   Pin is in native mode
605 **/
606 BOOLEAN
GpioIsPadASataDevSlpPin(IN GPIO_PAD GpioPad,IN GPIO_PAD_MODE PadMode)607 GpioIsPadASataDevSlpPin (
608   IN  GPIO_PAD        GpioPad,
609   IN  GPIO_PAD_MODE   PadMode
610   )
611 {
612   UINT32                    SataDevSlpPinMax;
613   UINT32                    SataDevSlpPinIndex;
614   GPIO_PAD_OWN              PadOwnership;
615   GPIO_PAD_NATIVE_FUNCTION  *SataDevSlpPinToGpioMap;
616 
617   if (GetPchSeries () == PchLp) {
618     SataDevSlpPinToGpioMap = mPchLpSataDevSlpPinToGpioMap;
619     SataDevSlpPinMax = sizeof (mPchLpSataDevSlpPinToGpioMap) /sizeof (GPIO_PAD_NATIVE_FUNCTION);
620   } else {
621     SataDevSlpPinToGpioMap = mPchHSataDevSlpPinToGpioMap;
622     SataDevSlpPinMax = sizeof (mPchHSataDevSlpPinToGpioMap) /sizeof (GPIO_PAD_NATIVE_FUNCTION);
623   }
624 
625   for (SataDevSlpPinIndex = 0; SataDevSlpPinIndex < SataDevSlpPinMax; SataDevSlpPinIndex++) {
626     if ((GpioPad == SataDevSlpPinToGpioMap[SataDevSlpPinIndex].Pad) &&
627         (PadMode == SataDevSlpPinToGpioMap[SataDevSlpPinIndex].Mode)) {
628       GpioGetPadOwnership (SataDevSlpPinToGpioMap[SataDevSlpPinIndex].Pad , &PadOwnership);
629       if (PadOwnership == GpioPadOwnHost) {
630         return TRUE;
631       } else {
632         return FALSE;
633       }
634     }
635   }
636   return FALSE;
637 }
638 
639 /**
640   This function checks if SataDevSlp pin is in native mode
641 
642   @param[in]  SataPort            SATA port
643   @param[out] DevSlpPad           DevSlpPad
644 
645   @retval TRUE                    DevSlp is in native mode
646           FALSE                   DevSlp is not in native mode
647 **/
648 BOOLEAN
GpioIsSataDevSlpPinEnabled(IN UINTN SataPort,OUT GPIO_PAD * DevSlpPad)649 GpioIsSataDevSlpPinEnabled (
650   IN  UINTN           SataPort,
651   OUT GPIO_PAD        *DevSlpPad
652   )
653 {
654   GPIO_PAD_MODE  DevSlpPadMode;
655   GPIO_PAD       DevSlpGpioPad;
656   GPIO_PAD_MODE  GpioMode;
657   EFI_STATUS     Status;
658 
659   if (GetPchSeries () == PchLp) {
660     ASSERT (SataPort < PCH_LP_AHCI_MAX_PORTS);
661     DevSlpGpioPad = mPchLpSataDevSlpPinToGpioMap[SataPort].Pad;
662     DevSlpPadMode = mPchLpSataDevSlpPinToGpioMap[SataPort].Mode;
663   } else {
664     ASSERT (SataPort < PCH_H_AHCI_MAX_PORTS);
665     DevSlpGpioPad = mPchHSataDevSlpPinToGpioMap[SataPort].Pad;
666     DevSlpPadMode = mPchHSataDevSlpPinToGpioMap[SataPort].Mode;
667   }
668 
669   Status = GetGpioPadMode (DevSlpGpioPad, &GpioMode);
670 
671   if (EFI_ERROR (Status) || (GpioMode != DevSlpPadMode)) {
672     *DevSlpPad = 0x0;
673     return FALSE;
674   } else {
675     *DevSlpPad = DevSlpGpioPad;
676     return TRUE;
677   }
678 }
679 
680