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