Platform.c 32 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184
  1. /** @file
  2. Copyright (c) 2004 - 2019, Intel Corporation. All rights reserved.<BR>
  3. SPDX-License-Identifier: BSD-2-Clause-Patent
  4. Module Name:
  5. **/
  6. #include "CommonHeader.h"
  7. #include "Platform.h"
  8. #include <Library/PciCf8Lib.h>
  9. #include "PlatformBaseAddresses.h"
  10. #include "PchAccess.h"
  11. #include <Guid/PlatformInfo.h>
  12. #include "PchCommonDefinitions.h"
  13. #include <Ppi/MfgMemoryTest.h>
  14. #include <Guid/SetupVariable.h>
  15. #include <Guid/Vlv2Variable.h>
  16. #include <Ppi/fTPMPolicy.h>
  17. //
  18. // Start::Alpine Valley platform
  19. //
  20. enum {
  21. SMBUS_READ_BYTE,
  22. SMBUS_WRITE_BYTE,
  23. SMBUS_READ_BLOCK,
  24. SMBUS_WRITE_BLOCK
  25. };
  26. #define EC_BASE 0xE0000000
  27. //
  28. // DEVICE 0 (Memroy Controller Hub)
  29. //
  30. #define MC_BUS 0x00
  31. #define MC_DEV 0x00
  32. #define MC_FUN 0x00
  33. #define MC_DEV_FUN (MC_DEV << 3)
  34. #define MC_BUS_DEV_FUN ((MC_BUS << 8) + MC_DEV_FUN)
  35. //
  36. // SysCtl SMBus address and block size
  37. //
  38. #define AV_SC_SMBUS_ADDRESS 0x60
  39. #define AV_SC_BYTE_LEN 1
  40. #define AV_SC_BLOCK_LEN 4
  41. #define AV_SC_SMBUS_WRCMD 1
  42. #define AV_SC_SMBUS_RDCMD 0
  43. //
  44. // SysCtl registers offset
  45. //
  46. #define AV_SC_REG_PLATFORM_ID 24 // 0x18
  47. #define AV_SC_REG_BOARD_ID 28 // 0x1C
  48. #define AV_SC_REG_FAB_ID 32 // 0x20
  49. #define AV_SC_REG_ECO_ID 68 // 0x44
  50. #define AV_SC_REG_DDR_DAUGHTER_CARD_ID 144 // 0x90
  51. #define AV_SC_REG_SODIMM_CONFIG 36
  52. //
  53. // ID values
  54. //
  55. #define AV_SC_PLATFORM_ID_TABLET 0
  56. #define AV_SC_PLATFORM_ID_NETBOOK 2
  57. #define AV_SC_PLATFORM_ID_INTERPOSER 3 // Configuration TBD
  58. #define AV_SC_BOARD_ID_AV_SVP 1492
  59. #define BUS_TRIES 3 // How many times to retry on Bus Errors
  60. #define GTT_SIZE_1MB 1
  61. #define GTT_SIZE_2MB 2
  62. #define PciCfg16Read( PciExpressBase, Bus, Device, Function, Register ) \
  63. MmioRead16(PciExpressBase + \
  64. (UINTN)(Bus << 20) + \
  65. (UINTN)(Device << 15) + \
  66. (UINTN)(Function << 12) + \
  67. (UINTN)(Register))
  68. #define PciCfg16Write( PciExpressBase, Bus, Device, Function, Register, Data ) \
  69. MmioWrite16(PciExpressBase + \
  70. (UINTN)(Bus << 20) + \
  71. (UINTN)(Device << 15) + \
  72. (UINTN)(Function << 12) + \
  73. (UINTN)(Register), \
  74. (UINT16)Data)
  75. //
  76. //Memory Test Manufacturing mode
  77. //
  78. UINT32 DataPatternForMemoryTest[] = {
  79. 0x55555555, 0xAAAAAAAA, 0x55555510, 0x555555EF, 0x55555510, 0x555555EF, 0x55555510, 0x555555EF,
  80. 0x55555555, 0xAAAAAAAA, 0x55551055, 0x5555EF55, 0x55551055, 0x5555EF55, 0x55551055, 0x5555EF55,
  81. 0x55555555, 0xAAAAAAAA, 0x55105555, 0x55EF5555, 0x55105555, 0x55EF5555, 0x55105555, 0x55EF5555,
  82. 0x55555555, 0xAAAAAAAA, 0x10555555, 0xEF555555, 0x10555555, 0xEF555555, 0x10555555, 0xEF555555
  83. };
  84. #define DATA_PATTERN_ARRAY_SIZE (sizeof(DataPatternForMemoryTest) / sizeof(UINT32))
  85. //
  86. //Memory Test Manufacturing mode
  87. //
  88. //
  89. // The global indicator, the FvFileLoader callback will modify it to TRUE after loading PEIM into memory
  90. //
  91. BOOLEAN ImageInMemory = FALSE;
  92. EFI_STATUS
  93. EFIAPI
  94. Stall (
  95. IN CONST EFI_PEI_SERVICES **PeiServices,
  96. IN CONST EFI_PEI_STALL_PPI *This,
  97. IN UINTN Microseconds
  98. );
  99. EFI_STATUS
  100. EFIAPI
  101. MfgMemoryTest (
  102. IN CONST EFI_PEI_SERVICES **PeiServices,
  103. IN PEI_MFG_MEMORY_TEST_PPI *This,
  104. IN UINT32 BeginAddress,
  105. IN UINT32 MemoryLength
  106. );
  107. static EFI_PEI_STALL_PPI mStallPpi = {
  108. PEI_STALL_RESOLUTION,
  109. Stall
  110. };
  111. static PEI_MFG_MEMORY_TEST_PPI mPeiMfgMemoryTestPpi = {
  112. MfgMemoryTest
  113. };
  114. static EFI_PEI_PPI_DESCRIPTOR mInstallStallPpi[] = {
  115. {
  116. EFI_PEI_PPI_DESCRIPTOR_PPI,
  117. &gEfiPeiStallPpiGuid,
  118. &mStallPpi
  119. },
  120. {
  121. EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST,
  122. &gPeiMfgMemoryTestPpiGuid,
  123. &mPeiMfgMemoryTestPpi
  124. }
  125. };
  126. EFI_PEI_NOTIFY_DESCRIPTOR mMemoryDiscoveredNotifyList[1] = {
  127. {
  128. (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
  129. &gEfiPeiMemoryDiscoveredPpiGuid,
  130. MemoryDiscoveredPpiNotifyCallback
  131. }
  132. };
  133. EFI_STATUS
  134. EFIAPI
  135. InstallMonoStatusCode (
  136. IN EFI_FFS_FILE_HEADER *FfsHeader,
  137. IN CONST EFI_PEI_SERVICES **PeiServices
  138. );
  139. EFI_STATUS
  140. ReadPlatformIds (
  141. IN CONST EFI_PEI_SERVICES **PeiServices,
  142. IN OUT EFI_PLATFORM_INFO_HOB *PlatformInfoHob
  143. );
  144. //
  145. // Start::Alpine Valley platform
  146. //
  147. EFI_STATUS
  148. PeiSmbusExec (
  149. UINT16 SmbusBase,
  150. UINT8 SlvAddr,
  151. UINT8 Operation,
  152. UINT8 Offset,
  153. UINT8 *Length,
  154. UINT8 *Buffer
  155. );
  156. /**
  157. Detemine Turbot board
  158. @return 0: Not Turbot board
  159. 1: Turbot board
  160. **/
  161. UINT32
  162. DetermineTurbotBoard (
  163. void
  164. )
  165. {
  166. UINTN PciD31F0RegBase = 0;
  167. UINT32 GpioValue = 0;
  168. UINT32 TmpVal = 0;
  169. UINT32 MmioConf0 = 0;
  170. UINT32 MmioPadval = 0;
  171. UINT32 PConf0Offset = 0x200; //GPIO_S5_4 pad_conf0 register offset
  172. UINT32 PValueOffset = 0x208; //GPIO_S5_4 pad_value register offset
  173. UINT32 SSUSOffset = 0x2000;
  174. UINT32 IoBase = 0;
  175. DEBUG ((EFI_D_ERROR, "DetermineTurbotBoard() Entry\n"));
  176. PciD31F0RegBase = MmPciAddress (0,
  177. 0,
  178. PCI_DEVICE_NUMBER_PCH_LPC,
  179. PCI_FUNCTION_NUMBER_PCH_LPC,
  180. 0
  181. );
  182. IoBase = MmioRead32 (PciD31F0RegBase + R_PCH_LPC_IO_BASE) & B_PCH_LPC_IO_BASE_BAR;
  183. MmioConf0 = IoBase + SSUSOffset + PConf0Offset;
  184. MmioPadval = IoBase + SSUSOffset + PValueOffset;
  185. //0xFED0E200/0xFED0E208 is pad_Conf/pad_val register address of GPIO_S5_4
  186. DEBUG ((EFI_D_ERROR, "MmioConf0[0x%x], MmioPadval[0x%x]\n", MmioConf0, MmioPadval));
  187. MmioWrite32 (MmioConf0, 0x2003CC00);
  188. TmpVal = MmioRead32 (MmioPadval);
  189. TmpVal &= ~0x6; //Clear bit 1:2
  190. TmpVal |= 0x2; // Set the pin as GPI
  191. MmioWrite32 (MmioPadval, TmpVal);
  192. GpioValue = MmioRead32 (MmioPadval);
  193. DEBUG ((EFI_D_ERROR, "Gpio_S5_4 value is 0x%x\n", GpioValue));
  194. return (GpioValue & 0x1);
  195. }
  196. EFI_STATUS
  197. FtpmPolicyInit (
  198. IN CONST EFI_PEI_SERVICES **PeiServices,
  199. IN SYSTEM_CONFIGURATION *pSystemConfiguration
  200. )
  201. {
  202. EFI_STATUS Status;
  203. EFI_PEI_PPI_DESCRIPTOR *mFtpmPolicyPpiDesc;
  204. SEC_FTPM_POLICY_PPI *mFtpmPolicyPpi;
  205. DEBUG((EFI_D_INFO, "FtpmPolicyInit Entry \n"));
  206. if (NULL == PeiServices || NULL == pSystemConfiguration) {
  207. DEBUG((EFI_D_ERROR, "Input error. \n"));
  208. return EFI_INVALID_PARAMETER;
  209. }
  210. Status = (*PeiServices)->AllocatePool(
  211. PeiServices,
  212. sizeof (EFI_PEI_PPI_DESCRIPTOR),
  213. (void **)&mFtpmPolicyPpiDesc
  214. );
  215. ASSERT_EFI_ERROR (Status);
  216. Status = (*PeiServices)->AllocatePool(
  217. PeiServices,
  218. sizeof (SEC_FTPM_POLICY_PPI),
  219. (void **)&mFtpmPolicyPpi
  220. );
  221. ASSERT_EFI_ERROR (Status);
  222. //
  223. // Initialize PPI
  224. //
  225. (*PeiServices)->SetMem ((VOID *)mFtpmPolicyPpi, sizeof (SEC_FTPM_POLICY_PPI), 0);
  226. mFtpmPolicyPpiDesc->Flags = EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST;
  227. mFtpmPolicyPpiDesc->Guid = &gSeCfTPMPolicyPpiGuid;
  228. mFtpmPolicyPpiDesc->Ppi = mFtpmPolicyPpi;
  229. DEBUG((EFI_D_INFO, "pSystemConfiguration->fTPM = 0x%x \n", pSystemConfiguration->fTPM));
  230. if(pSystemConfiguration->fTPM == 1) {
  231. mFtpmPolicyPpi->fTPMEnable = TRUE;
  232. } else {
  233. mFtpmPolicyPpi->fTPMEnable = FALSE;
  234. }
  235. Status = (*PeiServices)->InstallPpi(
  236. PeiServices,
  237. mFtpmPolicyPpiDesc
  238. );
  239. ASSERT_EFI_ERROR (Status);
  240. DEBUG((EFI_D_INFO, "FtpmPolicyInit done \n"));
  241. return EFI_SUCCESS;
  242. }
  243. /**
  244. This routine attempts to acquire the SMBus
  245. @retval FAILURE as failed
  246. @retval SUCCESS as passed
  247. **/
  248. EFI_STATUS
  249. AcquireBus (
  250. UINT16 SmbusBase
  251. )
  252. {
  253. UINT8 StsReg;
  254. StsReg = 0;
  255. StsReg = (UINT8)IoRead8(SmbusBase + R_PCH_SMBUS_HSTS);
  256. if (StsReg & B_PCH_SMBUS_IUS) {
  257. return EFI_DEVICE_ERROR;
  258. } else if (StsReg & B_PCH_SMBUS_HBSY) {
  259. //
  260. // Clear Status Register and exit
  261. //
  262. // Wait for HSTS.HBSY to be clear
  263. //
  264. do { StsReg = (UINT8) IoRead8(SmbusBase+R_PCH_SMBUS_HSTS); } while ((StsReg & B_PCH_SMBUS_HBSY) != 0);
  265. //
  266. // Clear all status bits
  267. //
  268. IoWrite8(SmbusBase+R_PCH_SMBUS_HSTS, 0xFE);
  269. return EFI_SUCCESS;
  270. } else {
  271. //
  272. // Clear out any odd status information (Will Not Clear In Use)
  273. //
  274. IoWrite8(SmbusBase+R_PCH_SMBUS_HSTS, StsReg);
  275. return EFI_SUCCESS;
  276. }
  277. }
  278. //
  279. // End::Alpine Valley platform
  280. //
  281. /**
  282. This function checks the memory range in PEI.
  283. @param PeiServices Pointer to PEI Services.
  284. @param This Pei memory test PPI pointer.
  285. @param BeginAddress Beginning of the memory address to be checked.
  286. @param MemoryLength Bytes of memory range to be checked.
  287. @param Operation Type of memory check operation to be performed.
  288. @param ErrorAddress Return the address of the error memory address.
  289. @retval EFI_SUCCESS The operation completed successfully.
  290. @retval EFI_DEVICE_ERROR Memory test failed. It's not safe to use this range of memory.
  291. **/
  292. EFI_STATUS
  293. EFIAPI
  294. MfgMemoryTest (
  295. IN CONST EFI_PEI_SERVICES **PeiServices,
  296. IN PEI_MFG_MEMORY_TEST_PPI *This,
  297. IN UINT32 BeginAddress,
  298. IN UINT32 MemoryLength
  299. )
  300. {
  301. UINT32 i;
  302. UINT32 memAddr;
  303. UINT32 readData;
  304. UINT32 xorData;
  305. UINT32 TestFlag = 0;
  306. memAddr = BeginAddress;
  307. //
  308. //Output Message for MFG
  309. //
  310. DEBUG ((EFI_D_ERROR, "MFGMODE SET\n"));
  311. //
  312. //Writting the pattern in defined location.
  313. //
  314. while (memAddr < (BeginAddress+MemoryLength)) {
  315. for (i = 0; i < DATA_PATTERN_ARRAY_SIZE; i++) {
  316. if (memAddr > (BeginAddress+MemoryLength -4)) {
  317. memAddr = memAddr + 4;
  318. break;
  319. }
  320. *((volatile UINT32*) memAddr) = DataPatternForMemoryTest[i];
  321. memAddr = memAddr + 4;
  322. }
  323. }
  324. //
  325. //Verify the pattern.
  326. //
  327. memAddr = BeginAddress;
  328. while (memAddr < (BeginAddress+MemoryLength)) {
  329. for (i = 0; i < DATA_PATTERN_ARRAY_SIZE; i++) {
  330. if (memAddr > (BeginAddress+MemoryLength -4)) {
  331. memAddr = memAddr + 4;
  332. break;
  333. }
  334. readData = *((volatile UINT32*) memAddr);
  335. xorData = readData ^ DataPatternForMemoryTest[i];
  336. //
  337. // If xorData is nonzero, this particular memAddr has a failure.
  338. //
  339. if (xorData != 0x00000000) {
  340. DEBUG ((EFI_D_ERROR, "Expected value....: %x\n", DataPatternForMemoryTest[i]));
  341. DEBUG ((EFI_D_ERROR, "ReadData value....: %x\n", readData));
  342. DEBUG ((EFI_D_ERROR, "Pattern failure at....: %x\n", memAddr));
  343. TestFlag = 1;
  344. }
  345. memAddr = memAddr + 4;
  346. }
  347. }
  348. if (TestFlag) {
  349. return EFI_DEVICE_ERROR;
  350. }
  351. //
  352. //Output Message for MFG
  353. //
  354. DEBUG ((EFI_D_ERROR, "MFGMODE MEMORY TEST PASSED\n"));
  355. return EFI_SUCCESS;
  356. }
  357. BOOLEAN
  358. IsRtcUipAlwaysSet (
  359. IN CONST EFI_PEI_SERVICES **PeiServices
  360. )
  361. {
  362. EFI_PEI_STALL_PPI *StallPpi;
  363. UINTN Count;
  364. (**PeiServices).LocatePpi (PeiServices, &gEfiPeiStallPpiGuid, 0, NULL, (void **)&StallPpi);
  365. for (Count = 0; Count < 500; Count++) { // Maximum waiting approximates to 1.5 seconds (= 3 msec * 500)
  366. IoWrite8 (R_PCH_RTC_INDEX2, R_PCH_RTC_REGISTERA);
  367. if ((IoRead8 (R_PCH_RTC_TARGET2) & B_PCH_RTC_REGISTERA_UIP) == 0) {
  368. return FALSE;
  369. }
  370. StallPpi->Stall (PeiServices, StallPpi, 3000);
  371. }
  372. return TRUE;
  373. }
  374. EFI_STATUS
  375. RtcPowerFailureHandler (
  376. IN CONST EFI_PEI_SERVICES **PeiServices
  377. )
  378. {
  379. UINT16 DataUint16;
  380. UINT8 DataUint8;
  381. BOOLEAN RtcUipIsAlwaysSet;
  382. DataUint16 = MmioRead16 (PMC_BASE_ADDRESS + R_PCH_PMC_GEN_PMCON_1);
  383. RtcUipIsAlwaysSet = IsRtcUipAlwaysSet (PeiServices);
  384. if ((DataUint16 & B_PCH_PMC_GEN_PMCON_RTC_PWR_STS) || (RtcUipIsAlwaysSet)) {
  385. //
  386. // Execute the sequence below. This will ensure that the RTC state machine has been initialized.
  387. //
  388. // Step 1.
  389. // BIOS clears this bit by writing a '0' to it.
  390. //
  391. if (DataUint16 & B_PCH_PMC_GEN_PMCON_RTC_PWR_STS) {
  392. //
  393. // Set to invalid date in order to reset the time to
  394. // BIOS build time later in the boot (SBRUN.c file).
  395. //
  396. IoWrite8 (R_PCH_RTC_INDEX2, R_PCH_RTC_YEAR);
  397. IoWrite8 (R_PCH_RTC_TARGET2, 0x0FF);
  398. IoWrite8 (R_PCH_RTC_INDEX2, R_PCH_RTC_MONTH);
  399. IoWrite8 (R_PCH_RTC_TARGET2, 0x0FF);
  400. IoWrite8 (R_PCH_RTC_INDEX2, R_PCH_RTC_DAYOFMONTH);
  401. IoWrite8 (R_PCH_RTC_TARGET2, 0x0FF);
  402. IoWrite8 (R_PCH_RTC_INDEX2, R_PCH_RTC_DAYOFWEEK);
  403. IoWrite8 (R_PCH_RTC_TARGET2, 0x0FF);
  404. IoWrite8 (R_PCH_RTC_INDEX2, R_PCH_RTC_SECONDSALARM);
  405. IoWrite8 (R_PCH_RTC_TARGET2, 0x00);
  406. IoWrite8 (R_PCH_RTC_INDEX2, R_PCH_RTC_MINUTESALARM);
  407. IoWrite8 (R_PCH_RTC_TARGET2, 0x00);
  408. IoWrite8 (R_PCH_RTC_INDEX2, R_PCH_RTC_HOURSALARM);
  409. IoWrite8 (R_PCH_RTC_TARGET2, 0x00);
  410. }
  411. //
  412. // Step 2.
  413. // Set RTC Register 0Ah[6:4] to '110' or '111'.
  414. //
  415. IoWrite8 (R_PCH_RTC_INDEX2, R_PCH_RTC_REGISTERA);
  416. IoWrite8 (R_PCH_RTC_TARGET2, (V_PCH_RTC_REGISTERA_DV_DIV_RST1 | V_PCH_RTC_REGISTERA_RS_976P5US));
  417. //
  418. // Step 3.
  419. // Set RTC Register 0Bh[7].
  420. //
  421. IoWrite8 (R_PCH_RTC_INDEX2, R_PCH_RTC_REGISTERB);
  422. DataUint8 = (IoRead8 (R_PCH_RTC_TARGET2) | B_PCH_RTC_REGISTERB_SET);
  423. IoWrite8 (R_PCH_RTC_INDEX2, R_PCH_RTC_REGISTERB);
  424. IoWrite8 (R_PCH_RTC_TARGET2, DataUint8);
  425. //
  426. // Step 4.
  427. // Set RTC Register 0Ah[6:4] to '010'.
  428. //
  429. IoWrite8 (R_PCH_RTC_INDEX2, R_PCH_RTC_REGISTERA);
  430. IoWrite8 (R_PCH_RTC_TARGET2, (V_PCH_RTC_REGISTERA_DV_NORM_OP | V_PCH_RTC_REGISTERA_RS_976P5US));
  431. //
  432. // Step 5.
  433. // Clear RTC Register 0Bh[7].
  434. //
  435. IoWrite8 (R_PCH_RTC_INDEX2, R_PCH_RTC_REGISTERB);
  436. DataUint8 = (IoRead8 (R_PCH_RTC_TARGET2) & (UINT8)~B_PCH_RTC_REGISTERB_SET);
  437. IoWrite8 (R_PCH_RTC_INDEX2, R_PCH_RTC_REGISTERB);
  438. IoWrite8 (R_PCH_RTC_TARGET2, DataUint8);
  439. }
  440. return EFI_SUCCESS;
  441. }
  442. VOID
  443. PchBaseInit (
  444. VOID
  445. )
  446. {
  447. //
  448. // Program ACPI Power Management I/O Space Base Address
  449. //
  450. MmioWrite16 (
  451. MmPciAddress (0,
  452. DEFAULT_PCI_BUS_NUMBER_PCH,
  453. PCI_DEVICE_NUMBER_PCH_LPC,
  454. PCI_FUNCTION_NUMBER_PCH_LPC,
  455. R_PCH_LPC_ACPI_BASE
  456. ),
  457. (UINT16)((ACPI_BASE_ADDRESS & B_PCH_LPC_ACPI_BASE_BAR) | B_PCH_LPC_ACPI_BASE_EN)
  458. );
  459. //
  460. // Program GPIO Base Address
  461. //
  462. MmioWrite16 (
  463. MmPciAddress (0,
  464. DEFAULT_PCI_BUS_NUMBER_PCH,
  465. PCI_DEVICE_NUMBER_PCH_LPC,
  466. PCI_FUNCTION_NUMBER_PCH_LPC,
  467. R_PCH_LPC_GPIO_BASE
  468. ),
  469. (UINT16)((GPIO_BASE_ADDRESS & B_PCH_LPC_GPIO_BASE_BAR) | B_PCH_LPC_GPIO_BASE_EN)
  470. );
  471. //
  472. // Set PMC Base Address
  473. //
  474. MmioWrite32 (
  475. MmPciAddress (0,
  476. DEFAULT_PCI_BUS_NUMBER_PCH,
  477. PCI_DEVICE_NUMBER_PCH_LPC,
  478. PCI_FUNCTION_NUMBER_PCH_LPC,
  479. R_PCH_LPC_PMC_BASE
  480. ),
  481. (UINT32)((PMC_BASE_ADDRESS & B_PCH_LPC_PMC_BASE_BAR) | B_PCH_LPC_PMC_BASE_EN)
  482. );
  483. //
  484. // Set IO Base Address
  485. //
  486. MmioWrite32 (
  487. MmPciAddress (0,
  488. DEFAULT_PCI_BUS_NUMBER_PCH,
  489. PCI_DEVICE_NUMBER_PCH_LPC,
  490. PCI_FUNCTION_NUMBER_PCH_LPC,
  491. R_PCH_LPC_IO_BASE
  492. ),
  493. (UINT32)((IO_BASE_ADDRESS & B_PCH_LPC_IO_BASE_BAR) | B_PCH_LPC_IO_BASE_EN)
  494. );
  495. //
  496. // Set ILB Base Address
  497. //
  498. MmioWrite32 (
  499. MmPciAddress (0,
  500. DEFAULT_PCI_BUS_NUMBER_PCH,
  501. PCI_DEVICE_NUMBER_PCH_LPC,
  502. PCI_FUNCTION_NUMBER_PCH_LPC,
  503. R_PCH_LPC_ILB_BASE
  504. ),
  505. (UINT32)((ILB_BASE_ADDRESS & B_PCH_LPC_ILB_BASE_BAR) | B_PCH_LPC_ILB_BASE_EN)
  506. );
  507. //
  508. // Set PUnit Base Address
  509. //
  510. MmioWrite32 (
  511. MmPciAddress (0,
  512. DEFAULT_PCI_BUS_NUMBER_PCH,
  513. PCI_DEVICE_NUMBER_PCH_LPC,
  514. PCI_FUNCTION_NUMBER_PCH_LPC,
  515. R_PCH_LPC_PUNIT_BASE
  516. ),
  517. (UINT32)((PUNIT_BASE_ADDRESS & B_PCH_LPC_PUNIT_BASE_BAR) | B_PCH_LPC_PUNIT_BASE_EN)
  518. );
  519. //
  520. // Set SPI Base Address
  521. //
  522. MmioWrite32 (
  523. MmPciAddress (0,
  524. DEFAULT_PCI_BUS_NUMBER_PCH,
  525. PCI_DEVICE_NUMBER_PCH_LPC,
  526. PCI_FUNCTION_NUMBER_PCH_LPC,
  527. R_PCH_LPC_SPI_BASE
  528. ),
  529. (UINT32)((SPI_BASE_ADDRESS & B_PCH_LPC_SPI_BASE_BAR) | B_PCH_LPC_SPI_BASE_EN)
  530. );
  531. //
  532. // Set Root Complex Base Address
  533. //
  534. MmioWrite32 (
  535. MmPciAddress (0,
  536. DEFAULT_PCI_BUS_NUMBER_PCH,
  537. PCI_DEVICE_NUMBER_PCH_LPC,
  538. PCI_FUNCTION_NUMBER_PCH_LPC,
  539. R_PCH_LPC_RCBA
  540. ),
  541. (UINT32)((RCBA_BASE_ADDRESS & B_PCH_LPC_RCBA_BAR) | B_PCH_LPC_RCBA_EN)
  542. );
  543. //
  544. // Set MPHY Base Address
  545. //
  546. MmioWrite32 (
  547. MmPciAddress (0,
  548. DEFAULT_PCI_BUS_NUMBER_PCH,
  549. PCI_DEVICE_NUMBER_PCH_LPC,
  550. PCI_FUNCTION_NUMBER_PCH_LPC,
  551. R_PCH_LPC_MPHY_BASE
  552. ),
  553. (UINT32)((MPHY_BASE_ADDRESS & B_PCH_LPC_MPHY_BASE_BAR) | B_PCH_LPC_MPHY_BASE_EN)
  554. );
  555. MmioWrite16 (
  556. MmPciAddress (0,
  557. DEFAULT_PCI_BUS_NUMBER_PCH,
  558. PCI_DEVICE_NUMBER_PCH_SMBUS,
  559. PCI_FUNCTION_NUMBER_PCH_SMBUS,
  560. R_PCH_SMBUS_BASE
  561. ),
  562. (UINT16)(SMBUS_BASE_ADDRESS & B_PCH_SMBUS_BASE_BAR)
  563. );
  564. MmioOr8 (
  565. MmPciAddress (0,
  566. DEFAULT_PCI_BUS_NUMBER_PCH,
  567. PCI_DEVICE_NUMBER_PCH_SMBUS,
  568. PCI_FUNCTION_NUMBER_PCH_SMBUS,
  569. R_PCH_SMBUS_PCICMD
  570. ),
  571. B_PCH_SMBUS_PCICMD_IOSE
  572. );
  573. }
  574. /**
  575. This is the entrypoint of PEIM
  576. @param FileHandle Handle of the file being invoked.
  577. @param PeiServices Describes the list of possible PEI Services.
  578. @retval EFI_SUCCESS if it completed successfully.
  579. **/
  580. EFI_STATUS
  581. EFIAPI
  582. PeiInitPlatform (
  583. IN EFI_PEI_FILE_HANDLE FileHandle,
  584. IN CONST EFI_PEI_SERVICES **PeiServices
  585. )
  586. {
  587. UINTN SmbusRegBase;
  588. EFI_PLATFORM_INFO_HOB PlatformInfo;
  589. EFI_STATUS Status= EFI_SUCCESS;
  590. EFI_PEI_READ_ONLY_VARIABLE2_PPI *Variable = NULL;
  591. UINTN VariableSize;
  592. SYSTEM_CONFIGURATION SystemConfiguration;
  593. UINT32 GGC = 0;
  594. EFI_PEI_PPI_DESCRIPTOR *mVlvMmioPolicyPpiDesc;
  595. VLV_MMIO_POLICY_PPI *mVlvMmioPolicyPpi;
  596. ZeroMem (&PlatformInfo, sizeof(PlatformInfo));
  597. Status = InstallMonoStatusCode(FileHandle, PeiServices);
  598. ASSERT_EFI_ERROR (Status);
  599. //
  600. // Initialize Stall PPIs
  601. //
  602. Status = (*PeiServices)->InstallPpi (PeiServices, &mInstallStallPpi[0]);
  603. ASSERT_EFI_ERROR (Status);
  604. Status = (*PeiServices)->NotifyPpi (PeiServices, &mMemoryDiscoveredNotifyList[0]);
  605. ASSERT_EFI_ERROR (Status);
  606. SmbusRegBase = PchPciDeviceMmBase (
  607. DEFAULT_PCI_BUS_NUMBER_PCH,
  608. PCI_DEVICE_NUMBER_PCH_SMBUS,
  609. PCI_FUNCTION_NUMBER_PCH_SMBUS
  610. );
  611. //
  612. // Since PEI has no PCI enumerator, set the BAR & I/O space enable ourselves
  613. //
  614. MmioAndThenOr32 (SmbusRegBase + R_PCH_SMBUS_BASE, B_PCH_SMBUS_BASE_BAR, SMBUS_BASE_ADDRESS);
  615. MmioOr8 (SmbusRegBase + R_PCH_SMBUS_PCICMD, B_PCH_SMBUS_PCICMD_IOSE);
  616. PchBaseInit();
  617. //
  618. //Todo: confirm if we need program 8254
  619. //
  620. // Setting 8254
  621. // Program timer 1 as refresh timer
  622. //
  623. IoWrite8 (0x43, 0x54);
  624. IoWrite8 (0x41, 0x12);
  625. //
  626. // RTC power failure handling
  627. //
  628. RtcPowerFailureHandler (PeiServices);
  629. PchMmPci32( 0, 0, 2, 0, 0x50) = 0x210;
  630. VariableSize = sizeof (SYSTEM_CONFIGURATION);
  631. ZeroMem (&SystemConfiguration, VariableSize);
  632. //
  633. // Obtain variable services
  634. //
  635. Status = (*PeiServices)->LocatePpi(
  636. PeiServices,
  637. &gEfiPeiReadOnlyVariable2PpiGuid,
  638. 0,
  639. NULL,
  640. (void **)&Variable
  641. );
  642. ASSERT_EFI_ERROR(Status);
  643. Status = Variable->GetVariable (
  644. Variable,
  645. L"Setup",
  646. &gEfiSetupVariableGuid,
  647. NULL,
  648. &VariableSize,
  649. &SystemConfiguration
  650. );
  651. if (EFI_ERROR (Status) || VariableSize != sizeof(SYSTEM_CONFIGURATION)) {
  652. //The setup variable is corrupted
  653. VariableSize = sizeof(SYSTEM_CONFIGURATION);
  654. Status = Variable->GetVariable(
  655. Variable,
  656. L"SetupRecovery",
  657. &gEfiSetupVariableGuid,
  658. NULL,
  659. &VariableSize,
  660. &SystemConfiguration
  661. );
  662. ASSERT_EFI_ERROR (Status);
  663. }
  664. if (EFI_ERROR (Status)) {
  665. GGC = ((2 << 3) | 0x200);
  666. PciCfg16Write(EC_BASE, 0, 2, 0, 0x50, GGC);
  667. GGC = PciCfg16Read(EC_BASE, 0, 2, 0, 0x50);
  668. DEBUG((EFI_D_INFO , "GGC: 0x%08x GMSsize:0x%08x\n", GGC, (GGC & (BIT7|BIT6|BIT5|BIT4|BIT3))>>3));
  669. } else {
  670. if (SystemConfiguration.Igd == 1 && SystemConfiguration.PrimaryVideoAdaptor != 2) {
  671. GGC = (SystemConfiguration.IgdDvmt50PreAlloc << 3) |
  672. (SystemConfiguration.GTTSize == GTT_SIZE_1MB ? 0x100: 0x200);
  673. PciCfg16Write(EC_BASE, 0, 2, 0, 0x50, GGC);
  674. GGC = PciCfg16Read(EC_BASE, 0, 2, 0, 0x50);
  675. DEBUG((EFI_D_INFO , "GGC: 0x%08x GMSsize:0x%08x\n", GGC, (GGC & (BIT7|BIT6|BIT5|BIT4|BIT3))>>3));
  676. }
  677. }
  678. //
  679. // Initialize PlatformInfo HOB
  680. //
  681. Status = ReadPlatformIds(PeiServices, &PlatformInfo);
  682. ASSERT_EFI_ERROR (Status);
  683. //
  684. // 0 -> Disable , 1 -> Enable
  685. //
  686. if(SystemConfiguration.CfioPnpSettings == 1) {
  687. DEBUG((EFI_D_INFO, "CheckCfioPnpSettings: CFIO Pnp Settings Enabled\n"));
  688. PlatformInfo.CfioEnabled = 1;
  689. } else {
  690. DEBUG((EFI_D_INFO, "CheckCfioPnpSettings: CFIO Pnp Settings Disabled\n"));
  691. PlatformInfo.CfioEnabled = 0;
  692. }
  693. //
  694. // Build HOB for PlatformInfo
  695. //
  696. BuildGuidDataHob (
  697. &gEfiPlatformInfoGuid,
  698. &PlatformInfo,
  699. sizeof (EFI_PLATFORM_INFO_HOB)
  700. );
  701. //
  702. // Set the new boot mode for MRC
  703. //
  704. Status = UpdateBootMode (PeiServices);
  705. ASSERT_EFI_ERROR (Status);
  706. DEBUG((EFI_D_INFO, "Setup MMIO size ... \n\n"));
  707. //
  708. // Setup MMIO size
  709. //
  710. Status = (*PeiServices)->AllocatePool(
  711. PeiServices,
  712. sizeof (EFI_PEI_PPI_DESCRIPTOR),
  713. (void **)&mVlvMmioPolicyPpiDesc
  714. );
  715. ASSERT_EFI_ERROR (Status);
  716. Status = (*PeiServices)->AllocatePool(
  717. PeiServices,
  718. sizeof (VLV_MMIO_POLICY_PPI),
  719. (void **)&mVlvMmioPolicyPpi
  720. );
  721. ASSERT_EFI_ERROR (Status);
  722. (*PeiServices)->SetMem (
  723. (VOID *)mVlvMmioPolicyPpi,
  724. sizeof (VLV_MMIO_POLICY_PPI),
  725. 0
  726. );
  727. mVlvMmioPolicyPpiDesc->Flags = EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST;
  728. mVlvMmioPolicyPpiDesc->Guid = &gVlvMmioPolicyPpiGuid;
  729. mVlvMmioPolicyPpiDesc->Ppi = mVlvMmioPolicyPpi;
  730. switch (SystemConfiguration.MmioSize) {
  731. case 0: // 768MB
  732. mVlvMmioPolicyPpi->MmioSize = 0x300;
  733. break;
  734. case 1: // 1GB
  735. mVlvMmioPolicyPpi->MmioSize = 0x400;
  736. break;
  737. case 2: // 1.25GB
  738. mVlvMmioPolicyPpi->MmioSize = 0x500;
  739. break;
  740. case 3: // 1.5GB
  741. mVlvMmioPolicyPpi->MmioSize = 0x600;
  742. break;
  743. case 4: // 2GB
  744. mVlvMmioPolicyPpi->MmioSize = 0x800;
  745. break;
  746. default:
  747. mVlvMmioPolicyPpi->MmioSize = 0x800;
  748. break;
  749. }
  750. Status = (*PeiServices)->InstallPpi(
  751. PeiServices,
  752. mVlvMmioPolicyPpiDesc
  753. );
  754. ASSERT_EFI_ERROR (Status);
  755. return Status;
  756. }
  757. EFI_STATUS
  758. ReadPlatformIds (
  759. IN CONST EFI_PEI_SERVICES **PeiServices,
  760. IN OUT EFI_PLATFORM_INFO_HOB *PlatformInfoHob
  761. )
  762. {
  763. {
  764. EFI_STATUS Status = EFI_SUCCESS;
  765. UINT8 FabId = 0;
  766. UINTN DataSize;
  767. EFI_PLATFORM_INFO_HOB TmpHob;
  768. EFI_PEI_READ_ONLY_VARIABLE2_PPI *PeiVar;
  769. UINT32 CompatibleBoard = 0;
  770. Status = (**PeiServices).LocatePpi (
  771. PeiServices,
  772. &gEfiPeiReadOnlyVariable2PpiGuid,
  773. 0,
  774. NULL,
  775. (void **)&PeiVar
  776. );
  777. ASSERT_EFI_ERROR (Status);
  778. DataSize = sizeof (EFI_PLATFORM_INFO_HOB);
  779. Status = PeiVar->GetVariable (
  780. PeiVar,
  781. L"PlatformInfo",
  782. &gEfiVlv2VariableGuid,
  783. NULL,
  784. &DataSize,
  785. &TmpHob
  786. );
  787. if (Status == EFI_SUCCESS) {
  788. PlatformInfoHob->BoardId = TmpHob.BoardId;
  789. PlatformInfoHob->MemCfgID = TmpHob.MemCfgID;
  790. PlatformInfoHob->BoardRev = TmpHob.BoardRev;
  791. PlatformInfoHob->PlatformFlavor = TmpHob.PlatformFlavor;
  792. return Status;
  793. }
  794. CompatibleBoard = DetermineTurbotBoard();
  795. if (1 == CompatibleBoard) {
  796. PlatformInfoHob->BoardId = BOARD_ID_MINNOW2_TURBOT;
  797. DEBUG ((EFI_D_INFO, "I'm MinnowBoard Turbot!\n"));
  798. } else {
  799. PlatformInfoHob->BoardId = BOARD_ID_MINNOW2;
  800. DEBUG ((EFI_D_INFO, "I'm MinnowBoard Max!\n"));
  801. }
  802. PlatformInfoHob->MemCfgID = 0;
  803. PlatformInfoHob->BoardRev = FabId + 1; // FabId = 0 means FAB1 (BoardRev = 1), FabId = 1 means FAB2 (BoardRev = 2)...
  804. PlatformInfoHob->PlatformFlavor = FlavorMobile;
  805. }
  806. return EFI_SUCCESS;
  807. }
  808. //
  809. // Start::Alpine Valley platform
  810. //
  811. /**
  812. This routine reads SysCtl registers
  813. @param SmbusBase SMBUS Base Address
  814. @param SlvAddr Targeted Smbus Slave device address
  815. @param Operation Which SMBus protocol will be used
  816. @param Offset Offset of the register
  817. @param Length Number of bytes
  818. @param Buffer Buffer contains values read from registers
  819. @retval SUCCESS as passed
  820. @retval Others as failed
  821. **/
  822. EFI_STATUS
  823. PeiSmbusExec (
  824. UINT16 SmbusBase,
  825. UINT8 SlvAddr,
  826. UINT8 Operation,
  827. UINT8 Offset,
  828. UINT8 *Length,
  829. UINT8 *Buffer
  830. )
  831. {
  832. EFI_STATUS Status=EFI_SUCCESS;
  833. UINT8 AuxcReg;
  834. UINT8 SmbusOperation = 0;
  835. UINT8 StsReg;
  836. UINT8 SlvAddrReg;
  837. UINT8 HostCmdReg;
  838. UINT8 BlockCount = 0;
  839. BOOLEAN BufferTooSmall;
  840. UINT8 Index;
  841. UINT8 *CallBuffer;
  842. UINT8 RetryCount = BUS_TRIES;
  843. //
  844. // MrcSmbusExec supports byte and block read.
  845. // Only allow Byte or block access
  846. //
  847. if (!((*Length == AV_SC_BYTE_LEN) || (*Length == AV_SC_BLOCK_LEN))) {
  848. return EFI_INVALID_PARAMETER;
  849. }
  850. //
  851. // See if its ok to use the bus based upon INUSE_STS bit.
  852. //
  853. Status = AcquireBus (SmbusBase);
  854. ASSERT_EFI_ERROR(Status);
  855. CallBuffer = Buffer;
  856. //
  857. //SmbStatus Bits of interest
  858. //[6] = IUS (In Use Status)
  859. //[4] = FAIL
  860. //[3] = BERR (Bus Error = transaction collision)
  861. //[2] = DERR (Device Error = Illegal Command Field, Unclaimed Cycle, Host Device Timeout, CRC Error)
  862. //[1] = INTR (Successful completion of last command)
  863. //[0] = HOST BUSY
  864. //
  865. //
  866. // This is the main operation loop. If the operation results in a Smbus
  867. // collision with another master on the bus, it attempts the requested
  868. // transaction again at least BUS_TRIES attempts.
  869. //
  870. while (RetryCount--) {
  871. //
  872. // Operation Specifics (pre-execution)
  873. //
  874. Status = EFI_SUCCESS;
  875. SlvAddrReg = SlvAddr;
  876. HostCmdReg = Offset;
  877. AuxcReg = 0;
  878. switch (Operation) {
  879. case SMBUS_WRITE_BYTE:
  880. IoWrite8 (SmbusBase+R_PCH_SMBUS_HD0, CallBuffer[0]);
  881. SmbusOperation = V_PCH_SMBUS_SMB_CMD_BYTE_DATA;
  882. break;
  883. case SMBUS_READ_BYTE:
  884. SmbusOperation = V_PCH_SMBUS_SMB_CMD_BYTE_DATA;
  885. SlvAddrReg |= B_PCH_SMBUS_RW_SEL_READ;
  886. if (*Length < 1) {
  887. Status = EFI_INVALID_PARAMETER;
  888. }
  889. *Length = 1;
  890. break;
  891. case SMBUS_WRITE_BLOCK:
  892. SmbusOperation = V_PCH_SMBUS_SMB_CMD_BLOCK;
  893. IoWrite8 (SmbusBase+R_PCH_SMBUS_HD0, *(UINT8 *) Length);
  894. BlockCount = (UINT8) (*Length);
  895. if ((*Length < 1) || (*Length > 32)) {
  896. Status = EFI_INVALID_PARAMETER;
  897. break;
  898. }
  899. AuxcReg |= B_PCH_SMBUS_E32B;
  900. break;
  901. case SMBUS_READ_BLOCK:
  902. SmbusOperation = V_PCH_SMBUS_SMB_CMD_BLOCK;
  903. SlvAddrReg |= B_PCH_SMBUS_RW_SEL_READ;
  904. if ((*Length < 1) || (*Length > 32)) {
  905. Status = EFI_INVALID_PARAMETER;
  906. break;
  907. }
  908. AuxcReg |= B_PCH_SMBUS_E32B;
  909. break;
  910. default:
  911. Status = EFI_INVALID_PARAMETER;
  912. break;
  913. }
  914. //
  915. // Set Auxiliary Control register
  916. //
  917. IoWrite8 (SmbusBase+R_PCH_SMBUS_AUXC, AuxcReg);
  918. //
  919. // Reset the pointer of the internal buffer
  920. //
  921. IoRead8 (SmbusBase+R_PCH_SMBUS_HCTL);
  922. //
  923. // Now that the 32 byte buffer is turned on, we can write th block data
  924. // into it
  925. //
  926. if (Operation == SMBUS_WRITE_BLOCK) {
  927. for (Index = 0; Index < BlockCount; Index++) {
  928. //
  929. // Write next byte
  930. //
  931. IoWrite8 (SmbusBase+R_PCH_SMBUS_HBD, CallBuffer[Index]);
  932. }
  933. }
  934. //
  935. // Set SMBus slave address for the device to read
  936. //
  937. IoWrite8(SmbusBase+R_PCH_SMBUS_TSA, SlvAddrReg);
  938. //
  939. //
  940. // Set Command register for the offset to read
  941. //
  942. IoWrite8(SmbusBase+R_PCH_SMBUS_HCMD, HostCmdReg );
  943. //
  944. // Set Control Register to Set "operation command" protocol and start bit
  945. //
  946. IoWrite8(SmbusBase+R_PCH_SMBUS_HCTL, (UINT8) (SmbusOperation + B_PCH_SMBUS_START));
  947. //
  948. // Wait for IO to complete
  949. //
  950. do { StsReg = (UINT8) IoRead8(SmbusBase+0); } while ((StsReg & (BIT4|BIT3|BIT2|BIT1)) == 0);
  951. if (StsReg & B_PCH_SMBUS_DERR) {
  952. Status = EFI_DEVICE_ERROR;
  953. break;
  954. } else if (StsReg & B_PCH_SMBUS_BERR) {
  955. //
  956. // Clear the Bus Error for another try
  957. //
  958. Status = EFI_DEVICE_ERROR;
  959. IoWrite8(SmbusBase+R_PCH_SMBUS_HSTS, B_PCH_SMBUS_BERR);
  960. //
  961. // Clear Status Registers
  962. //
  963. IoWrite8(SmbusBase+R_PCH_SMBUS_HSTS, B_PCH_SMBUS_HSTS_ALL);
  964. IoWrite8(SmbusBase+R_PCH_SMBUS_AUXS, B_PCH_SMBUS_CRCE);
  965. continue;
  966. }
  967. //
  968. // successfull completion
  969. // Operation Specifics (post-execution)
  970. //
  971. switch (Operation) {
  972. case SMBUS_READ_BYTE:
  973. CallBuffer[0] = (UINT8)(IoRead8 (SmbusBase+R_PCH_SMBUS_HD0));
  974. break;
  975. case SMBUS_WRITE_BLOCK:
  976. IoWrite8(SmbusBase+R_PCH_SMBUS_HSTS, B_PCH_SMBUS_BYTE_DONE_STS);
  977. break;
  978. case SMBUS_READ_BLOCK:
  979. BufferTooSmall = FALSE;
  980. //
  981. // Find out how many bytes will be in the block
  982. //
  983. BlockCount = (UINT8)(IoRead8 (SmbusBase+R_PCH_SMBUS_HD0));
  984. if (*Length < BlockCount) {
  985. BufferTooSmall = TRUE;
  986. } else {
  987. for (Index = 0; Index < BlockCount; Index++) {
  988. //
  989. // Read the byte
  990. //
  991. CallBuffer[Index] = (UINT8)IoRead8 (SmbusBase+R_PCH_SMBUS_HBD);
  992. }
  993. }
  994. *Length = BlockCount;
  995. if (BufferTooSmall) {
  996. Status = EFI_BUFFER_TOO_SMALL;
  997. }
  998. break;
  999. default:
  1000. break;
  1001. };
  1002. if ((StsReg & B_PCH_SMBUS_BERR) && (Status == EFI_SUCCESS)) {
  1003. //
  1004. // Clear the Bus Error for another try
  1005. //
  1006. Status = EFI_DEVICE_ERROR;
  1007. IoWrite8(SmbusBase+R_PCH_SMBUS_HSTS, B_PCH_SMBUS_BERR);
  1008. continue;
  1009. } else {
  1010. break;
  1011. }
  1012. }
  1013. //
  1014. // Clear Status Registers and exit
  1015. //
  1016. IoWrite8(SmbusBase+R_PCH_SMBUS_HSTS, B_PCH_SMBUS_HSTS_ALL);
  1017. IoWrite8(SmbusBase+R_PCH_SMBUS_AUXS, B_PCH_SMBUS_CRCE);
  1018. IoWrite8(SmbusBase+R_PCH_SMBUS_AUXC, 0);
  1019. return Status;
  1020. }
  1021. //
  1022. // End::Alpine Valley platform
  1023. //