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