Home | History | Annotate | Download | only in QNCAccessLib
      1 /** @file
      2 Common Lib function for QNC internal network access.
      3 
      4 Copyright (c) 2013-2015 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 //
     17 // The package level header files this module uses
     18 //
     19 #include <Uefi.h>
     20 
     21 #include <IntelQNCRegs.h>
     22 #include <Library/QNCAccessLib.h>
     23 #include <Library/DebugLib.h>
     24 #include <IndustryStandard/Pci22.h>
     25 
     26 UINT32
     27 EFIAPI
     28 QNCPortRead(
     29   UINT8 Port,
     30   UINT32 RegAddress
     31   )
     32 {
     33   McD0PciCfg32 (QNC_ACCESS_PORT_MEA) = (RegAddress & 0xFFFFFF00);
     34   McD0PciCfg32 (QNC_ACCESS_PORT_MCR) = MESSAGE_READ_DW (Port, RegAddress);
     35   return McD0PciCfg32 (QNC_ACCESS_PORT_MDR);
     36 }
     37 
     38 VOID
     39 EFIAPI
     40 QNCPortWrite (
     41   UINT8 Port,
     42   UINT32 RegAddress,
     43   UINT32 WriteValue
     44   )
     45 {
     46   McD0PciCfg32 (QNC_ACCESS_PORT_MDR) = WriteValue;
     47   McD0PciCfg32 (QNC_ACCESS_PORT_MEA) = (RegAddress & 0xFFFFFF00);
     48   McD0PciCfg32 (QNC_ACCESS_PORT_MCR) = MESSAGE_WRITE_DW (Port, RegAddress);
     49 }
     50 
     51 UINT32
     52 EFIAPI
     53 QNCAltPortRead (
     54   UINT8 Port,
     55   UINT32 RegAddress
     56   )
     57 {
     58   McD0PciCfg32 (QNC_ACCESS_PORT_MEA) = (RegAddress & 0xFFFFFF00);
     59   McD0PciCfg32 (QNC_ACCESS_PORT_MCR) = ALT_MESSAGE_READ_DW (Port, RegAddress);
     60   return McD0PciCfg32 (QNC_ACCESS_PORT_MDR);
     61 }
     62 
     63 VOID
     64 EFIAPI
     65 QNCAltPortWrite (
     66   UINT8 Port,
     67   UINT32 RegAddress,
     68   UINT32 WriteValue
     69   )
     70 {
     71   McD0PciCfg32 (QNC_ACCESS_PORT_MDR) = WriteValue;
     72   McD0PciCfg32 (QNC_ACCESS_PORT_MEA) = (RegAddress & 0xFFFFFF00);
     73   McD0PciCfg32 (QNC_ACCESS_PORT_MCR) = ALT_MESSAGE_WRITE_DW (Port, RegAddress);
     74 }
     75 
     76 UINT32
     77 EFIAPI
     78 QNCPortIORead(
     79   UINT8 Port,
     80   UINT32 RegAddress
     81   )
     82 {
     83   McD0PciCfg32 (QNC_ACCESS_PORT_MEA) = (RegAddress & 0xFFFFFF00);
     84   McD0PciCfg32 (QNC_ACCESS_PORT_MCR) = MESSAGE_IO_READ_DW (Port, RegAddress);
     85   return McD0PciCfg32 (QNC_ACCESS_PORT_MDR);
     86 }
     87 
     88 VOID
     89 EFIAPI
     90 QNCPortIOWrite (
     91   UINT8 Port,
     92   UINT32 RegAddress,
     93   UINT32 WriteValue
     94   )
     95 {
     96   McD0PciCfg32 (QNC_ACCESS_PORT_MDR) = WriteValue;
     97   McD0PciCfg32 (QNC_ACCESS_PORT_MEA) = (RegAddress & 0xFFFFFF00);
     98   McD0PciCfg32 (QNC_ACCESS_PORT_MCR) = MESSAGE_IO_WRITE_DW (Port, RegAddress);
     99 }
    100 
    101 RETURN_STATUS
    102 EFIAPI
    103 QNCMmIoWrite (
    104   UINT32             MmIoAddress,
    105   QNC_MEM_IO_WIDTH    Width,
    106   UINT32             DataNumber,
    107   VOID               *pData
    108   )
    109 /*++
    110 
    111 Routine Description:
    112 
    113   This is for the special consideration for QNC MMIO write, as required by FWG, a reading must be performed after MMIO writing
    114 to ensure the expected write is processed and data is flushed into chipset
    115 
    116 Arguments:
    117 
    118   Row -- row number to be cleared ( start from 1 )
    119 
    120 Returns:
    121 
    122   EFI_SUCCESS
    123 
    124 --*/
    125 {
    126   RETURN_STATUS  Status;
    127   UINTN          Index;
    128 
    129   Status = RETURN_SUCCESS;
    130 
    131   for (Index =0; Index < DataNumber; Index++) {
    132     switch (Width) {
    133       case QNCMmioWidthUint8:
    134         QNCMmio8 (MmIoAddress, 0) = ((UINT8 *)pData)[Index];
    135         if (QNCMmio8 (MmIoAddress, 0) != ((UINT8*)pData)[Index]) {
    136           Status = RETURN_DEVICE_ERROR;
    137           break;
    138         }
    139         break;
    140 
    141       case QNCMmioWidthUint16:
    142         QNCMmio16 (MmIoAddress, 0) = ((UINT16 *)pData)[Index];
    143         if (QNCMmio16 (MmIoAddress, 0) != ((UINT16 *)pData)[Index]) {
    144           Status = RETURN_DEVICE_ERROR;
    145           break;
    146         }
    147         break;
    148 
    149       case QNCMmioWidthUint32:
    150         QNCMmio32 (MmIoAddress, 0) = ((UINT32 *)pData)[Index];
    151         if (QNCMmio32 (MmIoAddress, 0) != ((UINT32 *)pData)[Index]) {
    152           Status = RETURN_DEVICE_ERROR;
    153           break;
    154         }
    155         break;
    156 
    157       case QNCMmioWidthUint64:
    158         QNCMmio64 (MmIoAddress, 0) = ((UINT64 *)pData)[Index];
    159         if (QNCMmio64 (MmIoAddress, 0) != ((UINT64 *)pData)[Index]) {
    160           Status = RETURN_DEVICE_ERROR;
    161           break;
    162         }
    163         break;
    164 
    165       default:
    166         break;
    167     }
    168   }
    169 
    170   return Status;
    171 }
    172 
    173 UINT32
    174 EFIAPI
    175 QncHsmmcRead (
    176   VOID
    177   )
    178 {
    179   return QNCPortRead (QUARK_NC_HOST_BRIDGE_SB_PORT_ID, QNC_MSG_FSBIC_REG_HSMMC);
    180 }
    181 
    182 VOID
    183 EFIAPI
    184 QncHsmmcWrite (
    185   UINT32 WriteValue
    186   )
    187 {
    188   UINT16  DeviceId;
    189   UINT32  Data32;
    190 
    191   //
    192   // Check what Soc we are running on (read Host bridge DeviceId)
    193   //
    194   DeviceId = QNCMmPci16(0, MC_BUS, MC_DEV, MC_FUN, PCI_DEVICE_ID_OFFSET);
    195 
    196   if (DeviceId == QUARK2_MC_DEVICE_ID) {
    197     //
    198     // Disable HSMMC configuration
    199     //
    200     Data32 = QncHsmmcRead ();
    201     Data32 &= ~SMM_CTL_EN;
    202     QNCPortWrite (QUARK_NC_HOST_BRIDGE_SB_PORT_ID, QNC_MSG_FSBIC_REG_HSMMC, Data32);
    203 
    204     //
    205     // Validate HSMMC configuration is disabled
    206     //
    207     Data32 = QncHsmmcRead ();
    208     ASSERT((Data32 & SMM_CTL_EN) == 0);
    209 
    210     //
    211     // Enable HSMMC configuration
    212     //
    213     WriteValue |= SMM_CTL_EN;
    214   }
    215 
    216   //
    217   // Write the register value
    218   //
    219   QNCPortWrite (QUARK_NC_HOST_BRIDGE_SB_PORT_ID, QNC_MSG_FSBIC_REG_HSMMC, WriteValue);
    220 
    221   if (DeviceId == QUARK2_MC_DEVICE_ID) {
    222     //
    223     // Validate HSMMC configuration is enabled
    224     //
    225     Data32 = QncHsmmcRead ();
    226     ASSERT((Data32 & SMM_CTL_EN) != 0);
    227   }
    228 }
    229 
    230 VOID
    231 EFIAPI
    232 QncImrWrite (
    233   UINT32 ImrBaseOffset,
    234   UINT32 ImrLow,
    235   UINT32 ImrHigh,
    236   UINT32 ImrReadMask,
    237   UINT32 ImrWriteMask
    238   )
    239 {
    240   UINT16  DeviceId;
    241   UINT32  Data32;
    242 
    243   //
    244   // Check what Soc we are running on (read Host bridge DeviceId)
    245   //
    246   DeviceId = QNCMmPci16(0, MC_BUS, MC_DEV, MC_FUN, PCI_DEVICE_ID_OFFSET);
    247 
    248   //
    249   // Disable IMR protection
    250   //
    251   if (DeviceId == QUARK2_MC_DEVICE_ID) {
    252     //
    253     // Disable IMR protection
    254     //
    255     Data32 = QNCPortRead (QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, ImrBaseOffset+QUARK_NC_MEMORY_MANAGER_IMRXL);
    256     Data32 &= ~IMR_EN;
    257     QNCPortWrite (QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, ImrBaseOffset+QUARK_NC_MEMORY_MANAGER_IMRXL, Data32);
    258 
    259     //
    260     // Validate IMR protection is disabled
    261     //
    262     Data32 = QNCPortRead (QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, ImrBaseOffset+QUARK_NC_MEMORY_MANAGER_IMRXL);
    263     ASSERT((Data32 & IMR_EN) == 0);
    264 
    265     //
    266     // Update the IMR (IMRXL must be last as it may enable IMR violation checking)
    267     //
    268     QNCPortWrite (QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, ImrBaseOffset+QUARK_NC_MEMORY_MANAGER_IMRXRM, ImrReadMask);
    269     QNCPortWrite (QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, ImrBaseOffset+QUARK_NC_MEMORY_MANAGER_IMRXWM, ImrWriteMask);
    270     QNCPortWrite (QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, ImrBaseOffset+QUARK_NC_MEMORY_MANAGER_IMRXH, ImrHigh);
    271     QNCPortWrite (QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, ImrBaseOffset+QUARK_NC_MEMORY_MANAGER_IMRXL, ImrLow);
    272 
    273     //
    274     // Validate IMR protection is enabled/disabled
    275     //
    276     Data32 = QNCPortRead (QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, ImrBaseOffset+QUARK_NC_MEMORY_MANAGER_IMRXL);
    277     ASSERT((Data32 & IMR_EN) == (ImrLow & IMR_EN));
    278   } else {
    279     //
    280     // Disable IMR protection (allow all access)
    281     //
    282     QNCPortWrite (QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, ImrBaseOffset+QUARK_NC_MEMORY_MANAGER_IMRXRM, (UINT32)IMRX_ALL_ACCESS);
    283     QNCPortWrite (QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, ImrBaseOffset+QUARK_NC_MEMORY_MANAGER_IMRXWM, (UINT32)IMRX_ALL_ACCESS);
    284 
    285     //
    286     // Update the IMR (IMRXRM/IMRXWM must be last as they restrict IMR access)
    287     //
    288     QNCPortWrite (QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, ImrBaseOffset+QUARK_NC_MEMORY_MANAGER_IMRXL, (ImrLow & ~IMR_EN));
    289     QNCPortWrite (QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, ImrBaseOffset+QUARK_NC_MEMORY_MANAGER_IMRXH, ImrHigh);
    290     QNCPortWrite (QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, ImrBaseOffset+QUARK_NC_MEMORY_MANAGER_IMRXRM, ImrReadMask);
    291     QNCPortWrite (QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, ImrBaseOffset+QUARK_NC_MEMORY_MANAGER_IMRXWM, ImrWriteMask);
    292   }
    293 }
    294 
    295 VOID
    296 EFIAPI
    297 QncIClkAndThenOr (
    298   UINT32 RegAddress,
    299   UINT32 AndValue,
    300   UINT32 OrValue
    301   )
    302 {
    303   UINT32 RegValue;
    304   //
    305   // Whenever an iCLK SB register (Endpoint 32h) is being programmed the access
    306   // should always consist of a READ from the address followed by 2 identical
    307   // WRITEs to that address.
    308   //
    309   RegValue = QNCAltPortRead (QUARK_ICLK_SB_PORT_ID, RegAddress);
    310   RegValue &= AndValue;
    311   RegValue |= OrValue;
    312   QNCAltPortWrite (QUARK_ICLK_SB_PORT_ID, RegAddress, RegValue);
    313   QNCAltPortWrite (QUARK_ICLK_SB_PORT_ID, RegAddress, RegValue);
    314 }
    315 
    316 VOID
    317 EFIAPI
    318 QncIClkOr (
    319   UINT32 RegAddress,
    320   UINT32 OrValue
    321   )
    322 {
    323   UINT32 RegValue;
    324   //
    325   // Whenever an iCLK SB register (Endpoint 32h) is being programmed the access
    326   // should always consist of a READ from the address followed by 2 identical
    327   // WRITEs to that address.
    328   //
    329   RegValue = QNCAltPortRead (QUARK_ICLK_SB_PORT_ID, RegAddress);
    330   RegValue |= OrValue;
    331   QNCAltPortWrite (QUARK_ICLK_SB_PORT_ID, RegAddress, RegValue);
    332   QNCAltPortWrite (QUARK_ICLK_SB_PORT_ID, RegAddress, RegValue);
    333 }
    334