Home | History | Annotate | Download | only in PlatformHelperLib
      1 /** @file
      2 Helper routines with common PEI / DXE implementation.
      3 
      4 Copyright (c) 2013-2016 Intel Corporation.
      5 
      6 This program and the accompanying materials
      7 are licensed and made available under the terms and conditions of the BSD License
      8 which accompanies this distribution.  The full text of the license may be found at
      9 http://opensource.org/licenses/bsd-license.php
     10 
     11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     13 
     14 **/
     15 
     16 #include "CommonHeader.h"
     17 #include <Library/I2cLib.h>
     18 
     19 CHAR16 *mPlatTypeNameTable[]  = { EFI_PLATFORM_TYPE_NAME_TABLE_DEFINITION };
     20 UINTN mPlatTypeNameTableLen  = ((sizeof(mPlatTypeNameTable)) / sizeof (CHAR16 *));
     21 
     22 //
     23 // Routines defined in other source modules of this component.
     24 //
     25 
     26 //
     27 // Routines local to this source module.
     28 //
     29 
     30 //
     31 // Routines shared with other souce modules in this component.
     32 //
     33 
     34 EFI_STATUS
     35 WriteFirstFreeSpiProtect (
     36   IN CONST UINT32                         PchRootComplexBar,
     37   IN CONST UINT32                         DirectValue,
     38   IN CONST UINT32                         BaseAddress,
     39   IN CONST UINT32                         Length,
     40   OUT UINT32                              *OffsetPtr
     41   )
     42 {
     43   UINT32                            RegVal;
     44   UINT32                            Offset;
     45   UINT32                            StepLen;
     46 
     47   ASSERT (PchRootComplexBar > 0);
     48 
     49   Offset = 0;
     50   if (OffsetPtr != NULL) {
     51     *OffsetPtr = Offset;
     52   }
     53   if (MmioRead32 (PchRootComplexBar + R_QNC_RCRB_SPIPBR0) == 0) {
     54     Offset = R_QNC_RCRB_SPIPBR0;
     55   } else {
     56     if (MmioRead32 (PchRootComplexBar + R_QNC_RCRB_SPIPBR1) == 0) {
     57       Offset = R_QNC_RCRB_SPIPBR1;
     58     } else {
     59       if (MmioRead32 (PchRootComplexBar + R_QNC_RCRB_SPIPBR2) == 0) {
     60         Offset = R_QNC_RCRB_SPIPBR2;
     61       }
     62     }
     63   }
     64   if (Offset != 0) {
     65     if (DirectValue == 0) {
     66       StepLen = ALIGN_VALUE (Length,SIZE_4KB);   // Bring up to 4K boundary.
     67       RegVal = BaseAddress + StepLen - 1;
     68       RegVal &= 0x00FFF000;                     // Set EDS Protected Range Limit (PRL).
     69       RegVal |= ((BaseAddress >> 12) & 0xfff);  // or in EDS Protected Range Base (PRB).
     70     } else {
     71       RegVal = DirectValue;
     72     }
     73     //
     74     // Enable protection.
     75     //
     76     RegVal |= B_QNC_RCRB_SPIPBRn_WPE;
     77     MmioWrite32 (PchRootComplexBar + Offset, RegVal);
     78     if (RegVal == MmioRead32 (PchRootComplexBar + Offset)) {
     79       if (OffsetPtr != NULL) {
     80         *OffsetPtr = Offset;
     81       }
     82       return EFI_SUCCESS;
     83     }
     84     return EFI_DEVICE_ERROR;
     85   }
     86   return EFI_NOT_FOUND;
     87 }
     88 
     89 //
     90 // Routines exported by this component.
     91 //
     92 
     93 /**
     94   Read 8bit character from debug stream.
     95 
     96   Block until character is read.
     97 
     98   @return 8bit character read from debug stream.
     99 
    100 **/
    101 CHAR8
    102 EFIAPI
    103 PlatformDebugPortGetChar8 (
    104   VOID
    105   )
    106 {
    107   CHAR8                             Got;
    108 
    109   do {
    110     if (SerialPortPoll ()) {
    111       if (SerialPortRead ((UINT8 *) &Got, 1) == 1) {
    112         break;
    113       }
    114     }
    115   } while (TRUE);
    116 
    117   return Got;
    118 }
    119 
    120 /**
    121   Clear SPI Protect registers.
    122 
    123   @retval EFI_SUCCESS        SPI protect registers cleared.
    124   @retval EFI_ACCESS_DENIED  Unable to clear SPI protect registers.
    125 **/
    126 
    127 EFI_STATUS
    128 EFIAPI
    129 PlatformClearSpiProtect (
    130   VOID
    131   )
    132 {
    133   UINT32                            PchRootComplexBar;
    134 
    135   PchRootComplexBar = QNC_RCRB_BASE;
    136   //
    137   // Check if the SPI interface has been locked-down.
    138   //
    139   if ((MmioRead16 (PchRootComplexBar + R_QNC_RCRB_SPIS) & B_QNC_RCRB_SPIS_SCL) != 0) {
    140     return EFI_ACCESS_DENIED;
    141   }
    142   MmioWrite32 (PchRootComplexBar + R_QNC_RCRB_SPIPBR0, 0);
    143   if (MmioRead32 (PchRootComplexBar + R_QNC_RCRB_SPIPBR0) != 0) {
    144     return EFI_ACCESS_DENIED;
    145   }
    146   MmioWrite32 (PchRootComplexBar + R_QNC_RCRB_SPIPBR1, 0);
    147   if (MmioRead32 (PchRootComplexBar + R_QNC_RCRB_SPIPBR0) != 0) {
    148     return EFI_ACCESS_DENIED;
    149   }
    150   MmioWrite32 (PchRootComplexBar + R_QNC_RCRB_SPIPBR2, 0);
    151   if (MmioRead32 (PchRootComplexBar + R_QNC_RCRB_SPIPBR0) != 0) {
    152     return EFI_ACCESS_DENIED;
    153   }
    154   return EFI_SUCCESS;
    155 }
    156 
    157 /**
    158   Determine if an SPI address range is protected.
    159 
    160   @param  SpiBaseAddress  Base of SPI range.
    161   @param  Length          Length of SPI range.
    162 
    163   @retval TRUE       Range is protected.
    164   @retval FALSE      Range is not protected.
    165 **/
    166 BOOLEAN
    167 EFIAPI
    168 PlatformIsSpiRangeProtected (
    169   IN CONST UINT32                         SpiBaseAddress,
    170   IN CONST UINT32                         Length
    171   )
    172 {
    173   UINT32                            RegVal;
    174   UINT32                            Offset;
    175   UINT32                            Limit;
    176   UINT32                            ProtectedBase;
    177   UINT32                            ProtectedLimit;
    178   UINT32                            PchRootComplexBar;
    179 
    180   PchRootComplexBar = QNC_RCRB_BASE;
    181 
    182   if (Length > 0) {
    183     Offset = R_QNC_RCRB_SPIPBR0;
    184     Limit = SpiBaseAddress + (Length - 1);
    185     do {
    186       RegVal = MmioRead32 (PchRootComplexBar + Offset);
    187       if ((RegVal & B_QNC_RCRB_SPIPBRn_WPE) != 0) {
    188         ProtectedBase = (RegVal & 0xfff) << 12;
    189         ProtectedLimit = (RegVal & 0x00fff000) + 0xfff;
    190         if (SpiBaseAddress >= ProtectedBase && Limit <= ProtectedLimit) {
    191           return TRUE;
    192         }
    193       }
    194       if (Offset == R_QNC_RCRB_SPIPBR0) {
    195         Offset = R_QNC_RCRB_SPIPBR1;
    196       } else if (Offset == R_QNC_RCRB_SPIPBR1) {
    197         Offset = R_QNC_RCRB_SPIPBR2;
    198       } else {
    199         break;
    200       }
    201     } while (TRUE);
    202   }
    203   return FALSE;
    204 }
    205 
    206 /**
    207   Set Legacy GPIO Level
    208 
    209   @param  LevelRegOffset      GPIO level register Offset from GPIO Base Address.
    210   @param  GpioNum             GPIO bit to change.
    211   @param  HighLevel           If TRUE set GPIO High else Set GPIO low.
    212 
    213 **/
    214 VOID
    215 EFIAPI
    216 PlatformLegacyGpioSetLevel (
    217   IN CONST UINT32       LevelRegOffset,
    218   IN CONST UINT32       GpioNum,
    219   IN CONST BOOLEAN      HighLevel
    220   )
    221 {
    222   UINT32  RegValue;
    223   UINT32  GpioBaseAddress;
    224   UINT32  GpioNumMask;
    225 
    226   GpioBaseAddress =  LpcPciCfg32 (R_QNC_LPC_GBA_BASE) & B_QNC_LPC_GPA_BASE_MASK;
    227   ASSERT (GpioBaseAddress > 0);
    228 
    229   RegValue = IoRead32 (GpioBaseAddress + LevelRegOffset);
    230   GpioNumMask = (1 << GpioNum);
    231   if (HighLevel) {
    232     RegValue |= (GpioNumMask);
    233   } else {
    234     RegValue &= ~(GpioNumMask);
    235   }
    236   IoWrite32 (GpioBaseAddress + LevelRegOffset, RegValue);
    237 }
    238 
    239 /**
    240   Get Legacy GPIO Level
    241 
    242   @param  LevelRegOffset      GPIO level register Offset from GPIO Base Address.
    243   @param  GpioNum             GPIO bit to check.
    244 
    245   @retval TRUE       If bit is SET.
    246   @retval FALSE      If bit is CLEAR.
    247 
    248 **/
    249 BOOLEAN
    250 EFIAPI
    251 PlatformLegacyGpioGetLevel (
    252   IN CONST UINT32       LevelRegOffset,
    253   IN CONST UINT32       GpioNum
    254   )
    255 {
    256   UINT32  RegValue;
    257   UINT32  GpioBaseAddress;
    258   UINT32  GpioNumMask;
    259 
    260   GpioBaseAddress =  LpcPciCfg32 (R_QNC_LPC_GBA_BASE) & B_QNC_LPC_GPA_BASE_MASK;
    261   RegValue = IoRead32 (GpioBaseAddress + LevelRegOffset);
    262   GpioNumMask = (1 << GpioNum);
    263   return ((RegValue & GpioNumMask) != 0);
    264 }
    265 
    266 
    267 BOOLEAN
    268 Pcal9555GetPortRegBit (
    269   IN CONST UINT32                         Pcal9555SlaveAddr,
    270   IN CONST UINT32                         GpioNum,
    271   IN CONST UINT8                          RegBase
    272   )
    273 {
    274   EFI_STATUS                        Status;
    275   UINTN                             ReadLength;
    276   UINTN                             WriteLength;
    277   UINT8                             Data[2];
    278   EFI_I2C_DEVICE_ADDRESS            I2cDeviceAddr;
    279   EFI_I2C_ADDR_MODE                 I2cAddrMode;
    280   UINT8                             *RegValuePtr;
    281   UINT8                             GpioNumMask;
    282   UINT8                             SubAddr;
    283 
    284   I2cDeviceAddr.I2CDeviceAddress = (UINTN)Pcal9555SlaveAddr;
    285   I2cAddrMode = EfiI2CSevenBitAddrMode;
    286 
    287   if (GpioNum < 8) {
    288     SubAddr = RegBase;
    289     GpioNumMask = (UINT8)(1 << GpioNum);
    290   } else {
    291     SubAddr = RegBase + 1;
    292     GpioNumMask = (UINT8)(1 << (GpioNum - 8));
    293   }
    294 
    295   //
    296   // Output port value always at 2nd byte in Data variable.
    297   //
    298   RegValuePtr = &Data[1];
    299 
    300   //
    301   // On read entry sub address at 2nd byte, on read exit output
    302   // port value in 2nd byte.
    303   //
    304   Data[1] = SubAddr;
    305   WriteLength = 1;
    306   ReadLength = 1;
    307   Status = I2cReadMultipleByte (
    308     I2cDeviceAddr,
    309     I2cAddrMode,
    310     &WriteLength,
    311     &ReadLength,
    312     &Data[1]
    313     );
    314   ASSERT_EFI_ERROR (Status);
    315 
    316   //
    317   // Adjust output port bit given callers request.
    318   //
    319   return ((*RegValuePtr & GpioNumMask) != 0);
    320 }
    321 
    322 VOID
    323 Pcal9555SetPortRegBit (
    324   IN CONST UINT32                         Pcal9555SlaveAddr,
    325   IN CONST UINT32                         GpioNum,
    326   IN CONST UINT8                          RegBase,
    327   IN CONST BOOLEAN                        LogicOne
    328   )
    329 {
    330   EFI_STATUS                        Status;
    331   UINTN                             ReadLength;
    332   UINTN                             WriteLength;
    333   UINT8                             Data[2];
    334   EFI_I2C_DEVICE_ADDRESS            I2cDeviceAddr;
    335   EFI_I2C_ADDR_MODE                 I2cAddrMode;
    336   UINT8                             *RegValuePtr;
    337   UINT8                             GpioNumMask;
    338   UINT8                             SubAddr;
    339 
    340   I2cDeviceAddr.I2CDeviceAddress = (UINTN)Pcal9555SlaveAddr;
    341   I2cAddrMode = EfiI2CSevenBitAddrMode;
    342 
    343   if (GpioNum < 8) {
    344     SubAddr = RegBase;
    345     GpioNumMask = (UINT8)(1 << GpioNum);
    346   } else {
    347     SubAddr = RegBase + 1;
    348     GpioNumMask = (UINT8)(1 << (GpioNum - 8));
    349   }
    350 
    351   //
    352   // Output port value always at 2nd byte in Data variable.
    353   //
    354   RegValuePtr = &Data[1];
    355 
    356   //
    357   // On read entry sub address at 2nd byte, on read exit output
    358   // port value in 2nd byte.
    359   //
    360   Data[1] = SubAddr;
    361   WriteLength = 1;
    362   ReadLength = 1;
    363   Status = I2cReadMultipleByte (
    364     I2cDeviceAddr,
    365     I2cAddrMode,
    366     &WriteLength,
    367     &ReadLength,
    368     &Data[1]
    369     );
    370   ASSERT_EFI_ERROR (Status);
    371 
    372   //
    373   // Adjust output port bit given callers request.
    374   //
    375   if (LogicOne) {
    376     *RegValuePtr = *RegValuePtr | GpioNumMask;
    377   } else {
    378     *RegValuePtr = *RegValuePtr & ~(GpioNumMask);
    379   }
    380 
    381   //
    382   // Update register. Sub address at 1st byte, value at 2nd byte.
    383   //
    384   WriteLength = 2;
    385   Data[0] = SubAddr;
    386   Status = I2cWriteMultipleByte (
    387     I2cDeviceAddr,
    388     I2cAddrMode,
    389     &WriteLength,
    390     Data
    391     );
    392   ASSERT_EFI_ERROR (Status);
    393 }
    394 
    395 /**
    396 Set the direction of Pcal9555 IO Expander GPIO pin.
    397 
    398 @param  Pcal9555SlaveAddr  I2c Slave address of Pcal9555 Io Expander.
    399 @param  GpioNum            Gpio direction to configure - values 0-7 for Port0
    400 and 8-15 for Port1.
    401 @param  CfgAsInput         If TRUE set pin direction as input else set as output.
    402 
    403 **/
    404 VOID
    405 EFIAPI
    406 PlatformPcal9555GpioSetDir (
    407   IN CONST UINT32                         Pcal9555SlaveAddr,
    408   IN CONST UINT32                         GpioNum,
    409   IN CONST BOOLEAN                        CfgAsInput
    410   )
    411 {
    412   Pcal9555SetPortRegBit (
    413     Pcal9555SlaveAddr,
    414     GpioNum,
    415     PCAL9555_REG_CFG_PORT0,
    416     CfgAsInput
    417     );
    418 }
    419 
    420 /**
    421 Set the level of Pcal9555 IO Expander GPIO high or low.
    422 
    423 @param  Pcal9555SlaveAddr  I2c Slave address of Pcal9555 Io Expander.
    424 @param  GpioNum            Gpio to change values 0-7 for Port0 and 8-15
    425 for Port1.
    426 @param  HighLevel          If TRUE set pin high else set pin low.
    427 
    428 **/
    429 VOID
    430 EFIAPI
    431 PlatformPcal9555GpioSetLevel (
    432   IN CONST UINT32                         Pcal9555SlaveAddr,
    433   IN CONST UINT32                         GpioNum,
    434   IN CONST BOOLEAN                        HighLevel
    435   )
    436 {
    437   Pcal9555SetPortRegBit (
    438     Pcal9555SlaveAddr,
    439     GpioNum,
    440     PCAL9555_REG_OUT_PORT0,
    441     HighLevel
    442     );
    443 }
    444 
    445 /**
    446 
    447 Enable pull-up/pull-down resistors of Pcal9555 GPIOs.
    448 
    449 @param  Pcal9555SlaveAddr  I2c Slave address of Pcal9555 Io Expander.
    450 @param  GpioNum            Gpio to change values 0-7 for Port0 and 8-15
    451 for Port1.
    452 
    453 **/
    454 VOID
    455 EFIAPI
    456 PlatformPcal9555GpioEnablePull (
    457   IN CONST UINT32                         Pcal9555SlaveAddr,
    458   IN CONST UINT32                         GpioNum
    459   )
    460 {
    461   Pcal9555SetPortRegBit (
    462     Pcal9555SlaveAddr,
    463     GpioNum,
    464     PCAL9555_REG_PULL_EN_PORT0,
    465     TRUE
    466     );
    467 }
    468 
    469 /**
    470 
    471 Disable pull-up/pull-down resistors of Pcal9555 GPIOs.
    472 
    473 @param  Pcal9555SlaveAddr  I2c Slave address of Pcal9555 Io Expander.
    474 @param  GpioNum            Gpio to change values 0-7 for Port0 and 8-15
    475 for Port1.
    476 
    477 **/
    478 VOID
    479 EFIAPI
    480 PlatformPcal9555GpioDisablePull (
    481   IN CONST UINT32                         Pcal9555SlaveAddr,
    482   IN CONST UINT32                         GpioNum
    483   )
    484 {
    485   Pcal9555SetPortRegBit (
    486     Pcal9555SlaveAddr,
    487     GpioNum,
    488     PCAL9555_REG_PULL_EN_PORT0,
    489     FALSE
    490     );
    491 }
    492 
    493 /**
    494 
    495 Get state of Pcal9555 GPIOs.
    496 
    497 @param  Pcal9555SlaveAddr  I2c Slave address of Pcal9555 Io Expander.
    498 @param  GpioNum            Gpio to change values 0-7 for Port0 and 8-15
    499 for Port1.
    500 
    501 @retval TRUE               GPIO pin is high
    502 @retval FALSE              GPIO pin is low
    503 **/
    504 BOOLEAN
    505 EFIAPI
    506 PlatformPcal9555GpioGetState (
    507   IN CONST UINT32                         Pcal9555SlaveAddr,
    508   IN CONST UINT32                         GpioNum
    509   )
    510 {
    511   return Pcal9555GetPortRegBit (Pcal9555SlaveAddr, GpioNum, PCAL9555_REG_IN_PORT0);
    512 }
    513 
    514 
    515