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