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