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