PlatformHelperLib.c 12 KB

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