]> git.proxmox.com Git - mirror_edk2.git/blame - QuarkPlatformPkg/Library/PlatformHelperLib/PlatformHelperLib.c
QuarkPlatformPkg: Replace BSD License with BSD+Patent License
[mirror_edk2.git] / QuarkPlatformPkg / Library / PlatformHelperLib / PlatformHelperLib.c
CommitLineData
b303605e
MK
1/** @file\r
2Helper routines with common PEI / DXE implementation.\r
3\r
b1169100 4Copyright (c) 2013-2016 Intel Corporation.\r
b303605e 5\r
0eb3de2e 6SPDX-License-Identifier: BSD-2-Clause-Patent\r
b303605e
MK
7\r
8**/\r
9\r
10#include "CommonHeader.h"\r
b1169100 11#include <Library/I2cLib.h>\r
b303605e
MK
12\r
13CHAR16 *mPlatTypeNameTable[] = { EFI_PLATFORM_TYPE_NAME_TABLE_DEFINITION };\r
14UINTN mPlatTypeNameTableLen = ((sizeof(mPlatTypeNameTable)) / sizeof (CHAR16 *));\r
15\r
16//\r
17// Routines defined in other source modules of this component.\r
18//\r
19\r
20//\r
21// Routines local to this source module.\r
22//\r
23\r
24//\r
25// Routines shared with other souce modules in this component.\r
26//\r
27\r
28EFI_STATUS\r
29WriteFirstFreeSpiProtect (\r
30 IN CONST UINT32 PchRootComplexBar,\r
31 IN CONST UINT32 DirectValue,\r
32 IN CONST UINT32 BaseAddress,\r
33 IN CONST UINT32 Length,\r
34 OUT UINT32 *OffsetPtr\r
35 )\r
36{\r
37 UINT32 RegVal;\r
38 UINT32 Offset;\r
39 UINT32 StepLen;\r
40\r
41 ASSERT (PchRootComplexBar > 0);\r
42\r
43 Offset = 0;\r
44 if (OffsetPtr != NULL) {\r
45 *OffsetPtr = Offset;\r
46 }\r
47 if (MmioRead32 (PchRootComplexBar + R_QNC_RCRB_SPIPBR0) == 0) {\r
48 Offset = R_QNC_RCRB_SPIPBR0;\r
49 } else {\r
50 if (MmioRead32 (PchRootComplexBar + R_QNC_RCRB_SPIPBR1) == 0) {\r
51 Offset = R_QNC_RCRB_SPIPBR1;\r
52 } else {\r
53 if (MmioRead32 (PchRootComplexBar + R_QNC_RCRB_SPIPBR2) == 0) {\r
54 Offset = R_QNC_RCRB_SPIPBR2;\r
55 }\r
56 }\r
57 }\r
58 if (Offset != 0) {\r
59 if (DirectValue == 0) {\r
60 StepLen = ALIGN_VALUE (Length,SIZE_4KB); // Bring up to 4K boundary.\r
61 RegVal = BaseAddress + StepLen - 1;\r
62 RegVal &= 0x00FFF000; // Set EDS Protected Range Limit (PRL).\r
63 RegVal |= ((BaseAddress >> 12) & 0xfff); // or in EDS Protected Range Base (PRB).\r
64 } else {\r
65 RegVal = DirectValue;\r
66 }\r
67 //\r
68 // Enable protection.\r
69 //\r
70 RegVal |= B_QNC_RCRB_SPIPBRn_WPE;\r
71 MmioWrite32 (PchRootComplexBar + Offset, RegVal);\r
72 if (RegVal == MmioRead32 (PchRootComplexBar + Offset)) {\r
73 if (OffsetPtr != NULL) {\r
74 *OffsetPtr = Offset;\r
75 }\r
76 return EFI_SUCCESS;\r
77 }\r
78 return EFI_DEVICE_ERROR;\r
79 }\r
80 return EFI_NOT_FOUND;\r
81}\r
82\r
83//\r
84// Routines exported by this component.\r
85//\r
86\r
b303605e
MK
87/**\r
88 Clear SPI Protect registers.\r
89\r
90 @retval EFI_SUCCESS SPI protect registers cleared.\r
91 @retval EFI_ACCESS_DENIED Unable to clear SPI protect registers.\r
92**/\r
93\r
94EFI_STATUS\r
95EFIAPI\r
96PlatformClearSpiProtect (\r
97 VOID\r
98 )\r
99{\r
100 UINT32 PchRootComplexBar;\r
101\r
102 PchRootComplexBar = QNC_RCRB_BASE;\r
103 //\r
104 // Check if the SPI interface has been locked-down.\r
105 //\r
106 if ((MmioRead16 (PchRootComplexBar + R_QNC_RCRB_SPIS) & B_QNC_RCRB_SPIS_SCL) != 0) {\r
107 return EFI_ACCESS_DENIED;\r
108 }\r
109 MmioWrite32 (PchRootComplexBar + R_QNC_RCRB_SPIPBR0, 0);\r
110 if (MmioRead32 (PchRootComplexBar + R_QNC_RCRB_SPIPBR0) != 0) {\r
111 return EFI_ACCESS_DENIED;\r
112 }\r
113 MmioWrite32 (PchRootComplexBar + R_QNC_RCRB_SPIPBR1, 0);\r
114 if (MmioRead32 (PchRootComplexBar + R_QNC_RCRB_SPIPBR0) != 0) {\r
115 return EFI_ACCESS_DENIED;\r
116 }\r
117 MmioWrite32 (PchRootComplexBar + R_QNC_RCRB_SPIPBR2, 0);\r
118 if (MmioRead32 (PchRootComplexBar + R_QNC_RCRB_SPIPBR0) != 0) {\r
119 return EFI_ACCESS_DENIED;\r
120 }\r
121 return EFI_SUCCESS;\r
122}\r
123\r
124/**\r
125 Determine if an SPI address range is protected.\r
126\r
127 @param SpiBaseAddress Base of SPI range.\r
128 @param Length Length of SPI range.\r
129\r
130 @retval TRUE Range is protected.\r
131 @retval FALSE Range is not protected.\r
132**/\r
133BOOLEAN\r
134EFIAPI\r
135PlatformIsSpiRangeProtected (\r
136 IN CONST UINT32 SpiBaseAddress,\r
137 IN CONST UINT32 Length\r
138 )\r
139{\r
140 UINT32 RegVal;\r
141 UINT32 Offset;\r
142 UINT32 Limit;\r
143 UINT32 ProtectedBase;\r
144 UINT32 ProtectedLimit;\r
145 UINT32 PchRootComplexBar;\r
146\r
147 PchRootComplexBar = QNC_RCRB_BASE;\r
148\r
149 if (Length > 0) {\r
150 Offset = R_QNC_RCRB_SPIPBR0;\r
151 Limit = SpiBaseAddress + (Length - 1);\r
152 do {\r
153 RegVal = MmioRead32 (PchRootComplexBar + Offset);\r
154 if ((RegVal & B_QNC_RCRB_SPIPBRn_WPE) != 0) {\r
155 ProtectedBase = (RegVal & 0xfff) << 12;\r
156 ProtectedLimit = (RegVal & 0x00fff000) + 0xfff;\r
157 if (SpiBaseAddress >= ProtectedBase && Limit <= ProtectedLimit) {\r
158 return TRUE;\r
159 }\r
160 }\r
161 if (Offset == R_QNC_RCRB_SPIPBR0) {\r
162 Offset = R_QNC_RCRB_SPIPBR1;\r
163 } else if (Offset == R_QNC_RCRB_SPIPBR1) {\r
164 Offset = R_QNC_RCRB_SPIPBR2;\r
165 } else {\r
166 break;\r
167 }\r
168 } while (TRUE);\r
169 }\r
170 return FALSE;\r
171}\r
172\r
173/**\r
174 Set Legacy GPIO Level\r
175\r
176 @param LevelRegOffset GPIO level register Offset from GPIO Base Address.\r
177 @param GpioNum GPIO bit to change.\r
178 @param HighLevel If TRUE set GPIO High else Set GPIO low.\r
179\r
180**/\r
181VOID\r
182EFIAPI\r
183PlatformLegacyGpioSetLevel (\r
184 IN CONST UINT32 LevelRegOffset,\r
185 IN CONST UINT32 GpioNum,\r
186 IN CONST BOOLEAN HighLevel\r
187 )\r
188{\r
189 UINT32 RegValue;\r
190 UINT32 GpioBaseAddress;\r
191 UINT32 GpioNumMask;\r
192\r
193 GpioBaseAddress = LpcPciCfg32 (R_QNC_LPC_GBA_BASE) & B_QNC_LPC_GPA_BASE_MASK;\r
194 ASSERT (GpioBaseAddress > 0);\r
195\r
196 RegValue = IoRead32 (GpioBaseAddress + LevelRegOffset);\r
197 GpioNumMask = (1 << GpioNum);\r
198 if (HighLevel) {\r
199 RegValue |= (GpioNumMask);\r
200 } else {\r
201 RegValue &= ~(GpioNumMask);\r
202 }\r
203 IoWrite32 (GpioBaseAddress + LevelRegOffset, RegValue);\r
204}\r
205\r
206/**\r
207 Get Legacy GPIO Level\r
208\r
209 @param LevelRegOffset GPIO level register Offset from GPIO Base Address.\r
210 @param GpioNum GPIO bit to check.\r
211\r
212 @retval TRUE If bit is SET.\r
213 @retval FALSE If bit is CLEAR.\r
214\r
215**/\r
216BOOLEAN\r
217EFIAPI\r
218PlatformLegacyGpioGetLevel (\r
219 IN CONST UINT32 LevelRegOffset,\r
220 IN CONST UINT32 GpioNum\r
221 )\r
222{\r
223 UINT32 RegValue;\r
224 UINT32 GpioBaseAddress;\r
225 UINT32 GpioNumMask;\r
226\r
227 GpioBaseAddress = LpcPciCfg32 (R_QNC_LPC_GBA_BASE) & B_QNC_LPC_GPA_BASE_MASK;\r
228 RegValue = IoRead32 (GpioBaseAddress + LevelRegOffset);\r
229 GpioNumMask = (1 << GpioNum);\r
230 return ((RegValue & GpioNumMask) != 0);\r
231}\r
b1169100
MK
232\r
233\r
234BOOLEAN\r
235Pcal9555GetPortRegBit (\r
236 IN CONST UINT32 Pcal9555SlaveAddr,\r
237 IN CONST UINT32 GpioNum,\r
238 IN CONST UINT8 RegBase\r
239 )\r
240{\r
241 EFI_STATUS Status;\r
242 UINTN ReadLength;\r
243 UINTN WriteLength;\r
244 UINT8 Data[2];\r
245 EFI_I2C_DEVICE_ADDRESS I2cDeviceAddr;\r
246 EFI_I2C_ADDR_MODE I2cAddrMode;\r
247 UINT8 *RegValuePtr;\r
248 UINT8 GpioNumMask;\r
249 UINT8 SubAddr;\r
250\r
251 I2cDeviceAddr.I2CDeviceAddress = (UINTN)Pcal9555SlaveAddr;\r
252 I2cAddrMode = EfiI2CSevenBitAddrMode;\r
253\r
254 if (GpioNum < 8) {\r
255 SubAddr = RegBase;\r
256 GpioNumMask = (UINT8)(1 << GpioNum);\r
257 } else {\r
258 SubAddr = RegBase + 1;\r
259 GpioNumMask = (UINT8)(1 << (GpioNum - 8));\r
260 }\r
261\r
262 //\r
263 // Output port value always at 2nd byte in Data variable.\r
264 //\r
265 RegValuePtr = &Data[1];\r
266\r
267 //\r
268 // On read entry sub address at 2nd byte, on read exit output\r
269 // port value in 2nd byte.\r
270 //\r
271 Data[1] = SubAddr;\r
272 WriteLength = 1;\r
273 ReadLength = 1;\r
274 Status = I2cReadMultipleByte (\r
275 I2cDeviceAddr,\r
276 I2cAddrMode,\r
277 &WriteLength,\r
278 &ReadLength,\r
279 &Data[1]\r
280 );\r
281 ASSERT_EFI_ERROR (Status);\r
282\r
283 //\r
284 // Adjust output port bit given callers request.\r
285 //\r
286 return ((*RegValuePtr & GpioNumMask) != 0);\r
287}\r
288\r
289VOID\r
290Pcal9555SetPortRegBit (\r
291 IN CONST UINT32 Pcal9555SlaveAddr,\r
292 IN CONST UINT32 GpioNum,\r
293 IN CONST UINT8 RegBase,\r
294 IN CONST BOOLEAN LogicOne\r
295 )\r
296{\r
297 EFI_STATUS Status;\r
298 UINTN ReadLength;\r
299 UINTN WriteLength;\r
300 UINT8 Data[2];\r
301 EFI_I2C_DEVICE_ADDRESS I2cDeviceAddr;\r
302 EFI_I2C_ADDR_MODE I2cAddrMode;\r
303 UINT8 *RegValuePtr;\r
304 UINT8 GpioNumMask;\r
305 UINT8 SubAddr;\r
306\r
307 I2cDeviceAddr.I2CDeviceAddress = (UINTN)Pcal9555SlaveAddr;\r
308 I2cAddrMode = EfiI2CSevenBitAddrMode;\r
309\r
310 if (GpioNum < 8) {\r
311 SubAddr = RegBase;\r
312 GpioNumMask = (UINT8)(1 << GpioNum);\r
313 } else {\r
314 SubAddr = RegBase + 1;\r
315 GpioNumMask = (UINT8)(1 << (GpioNum - 8));\r
316 }\r
317\r
318 //\r
319 // Output port value always at 2nd byte in Data variable.\r
320 //\r
321 RegValuePtr = &Data[1];\r
322\r
323 //\r
324 // On read entry sub address at 2nd byte, on read exit output\r
325 // port value in 2nd byte.\r
326 //\r
327 Data[1] = SubAddr;\r
328 WriteLength = 1;\r
329 ReadLength = 1;\r
330 Status = I2cReadMultipleByte (\r
331 I2cDeviceAddr,\r
332 I2cAddrMode,\r
333 &WriteLength,\r
334 &ReadLength,\r
335 &Data[1]\r
336 );\r
337 ASSERT_EFI_ERROR (Status);\r
338\r
339 //\r
340 // Adjust output port bit given callers request.\r
341 //\r
342 if (LogicOne) {\r
343 *RegValuePtr = *RegValuePtr | GpioNumMask;\r
344 } else {\r
345 *RegValuePtr = *RegValuePtr & ~(GpioNumMask);\r
346 }\r
347\r
348 //\r
349 // Update register. Sub address at 1st byte, value at 2nd byte.\r
350 //\r
351 WriteLength = 2;\r
352 Data[0] = SubAddr;\r
353 Status = I2cWriteMultipleByte (\r
354 I2cDeviceAddr,\r
355 I2cAddrMode,\r
356 &WriteLength,\r
357 Data\r
358 );\r
359 ASSERT_EFI_ERROR (Status);\r
360}\r
361\r
362/**\r
363Set the direction of Pcal9555 IO Expander GPIO pin.\r
364\r
365@param Pcal9555SlaveAddr I2c Slave address of Pcal9555 Io Expander.\r
366@param GpioNum Gpio direction to configure - values 0-7 for Port0\r
367and 8-15 for Port1.\r
368@param CfgAsInput If TRUE set pin direction as input else set as output.\r
369\r
370**/\r
371VOID\r
372EFIAPI\r
373PlatformPcal9555GpioSetDir (\r
374 IN CONST UINT32 Pcal9555SlaveAddr,\r
375 IN CONST UINT32 GpioNum,\r
376 IN CONST BOOLEAN CfgAsInput\r
377 )\r
378{\r
379 Pcal9555SetPortRegBit (\r
380 Pcal9555SlaveAddr,\r
381 GpioNum,\r
382 PCAL9555_REG_CFG_PORT0,\r
383 CfgAsInput\r
384 );\r
385}\r
386\r
387/**\r
388Set the level of Pcal9555 IO Expander GPIO high or low.\r
389\r
390@param Pcal9555SlaveAddr I2c Slave address of Pcal9555 Io Expander.\r
391@param GpioNum Gpio to change values 0-7 for Port0 and 8-15\r
392for Port1.\r
393@param HighLevel If TRUE set pin high else set pin low.\r
394\r
395**/\r
396VOID\r
397EFIAPI\r
398PlatformPcal9555GpioSetLevel (\r
399 IN CONST UINT32 Pcal9555SlaveAddr,\r
400 IN CONST UINT32 GpioNum,\r
401 IN CONST BOOLEAN HighLevel\r
402 )\r
403{\r
404 Pcal9555SetPortRegBit (\r
405 Pcal9555SlaveAddr,\r
406 GpioNum,\r
407 PCAL9555_REG_OUT_PORT0,\r
408 HighLevel\r
409 );\r
410}\r
411\r
412/**\r
413\r
414Enable pull-up/pull-down resistors of Pcal9555 GPIOs.\r
415\r
416@param Pcal9555SlaveAddr I2c Slave address of Pcal9555 Io Expander.\r
417@param GpioNum Gpio to change values 0-7 for Port0 and 8-15\r
418for Port1.\r
419\r
420**/\r
421VOID\r
422EFIAPI\r
423PlatformPcal9555GpioEnablePull (\r
424 IN CONST UINT32 Pcal9555SlaveAddr,\r
425 IN CONST UINT32 GpioNum\r
426 )\r
427{\r
428 Pcal9555SetPortRegBit (\r
429 Pcal9555SlaveAddr,\r
430 GpioNum,\r
431 PCAL9555_REG_PULL_EN_PORT0,\r
432 TRUE\r
433 );\r
434}\r
435\r
436/**\r
437\r
438Disable pull-up/pull-down resistors of Pcal9555 GPIOs.\r
439\r
440@param Pcal9555SlaveAddr I2c Slave address of Pcal9555 Io Expander.\r
441@param GpioNum Gpio to change values 0-7 for Port0 and 8-15\r
442for Port1.\r
443\r
444**/\r
445VOID\r
446EFIAPI\r
447PlatformPcal9555GpioDisablePull (\r
448 IN CONST UINT32 Pcal9555SlaveAddr,\r
449 IN CONST UINT32 GpioNum\r
450 )\r
451{\r
452 Pcal9555SetPortRegBit (\r
453 Pcal9555SlaveAddr,\r
454 GpioNum,\r
455 PCAL9555_REG_PULL_EN_PORT0,\r
456 FALSE\r
457 );\r
458}\r
459\r
460/**\r
461\r
462Get state of Pcal9555 GPIOs.\r
463\r
464@param Pcal9555SlaveAddr I2c Slave address of Pcal9555 Io Expander.\r
465@param GpioNum Gpio to change values 0-7 for Port0 and 8-15\r
466for Port1.\r
467\r
468@retval TRUE GPIO pin is high\r
469@retval FALSE GPIO pin is low\r
470**/\r
471BOOLEAN\r
472EFIAPI\r
473PlatformPcal9555GpioGetState (\r
474 IN CONST UINT32 Pcal9555SlaveAddr,\r
475 IN CONST UINT32 GpioNum\r
476 )\r
477{\r
478 return Pcal9555GetPortRegBit (Pcal9555SlaveAddr, GpioNum, PCAL9555_REG_IN_PORT0);\r
479}\r
480\r
481\r