]> git.proxmox.com Git - mirror_edk2.git/blob - Vlv2TbltDevicePkg/Library/I2CLibDxe/I2CLib.c
ArmPkg/CompilerIntrinsicsLib: Add uread, uwrite GCC assembly sources
[mirror_edk2.git] / Vlv2TbltDevicePkg / Library / I2CLibDxe / I2CLib.c
1 /** @file
2 Functions for accessing I2C registers.
3
4 Copyright (c) 2004 - 2015, Intel Corporation. All rights reserved.<BR>
5
6 SPDX-License-Identifier: BSD-2-Clause-Patent
7
8 --*/
9
10 #include <Library/DebugLib.h>
11 #include <Library/TimerLib.h>
12 #include <PchRegs/PchRegsPcu.h>
13 #include <PchRegs.h>
14 #include <PlatformBaseAddresses.h>
15 #include <PchRegs/PchRegsLpss.h>
16 #include <Library/I2CLib.h>
17 #include <Protocol/GlobalNvsArea.h>
18 #include <Library/UefiBootServicesTableLib.h>
19 #include <I2CRegs.h>
20
21 #define GLOBAL_NVS_OFFSET(Field) (UINTN)((CHAR8*)&((EFI_GLOBAL_NVS_AREA*)0)->Field - (CHAR8*)0)
22
23 #define PCIEX_BASE_ADDRESS 0xE0000000
24 #define PCI_EXPRESS_BASE_ADDRESS ((VOID *) (UINTN) PCIEX_BASE_ADDRESS)
25 #define MmPciAddress( Segment, Bus, Device, Function, Register ) \
26 ((UINTN)PCI_EXPRESS_BASE_ADDRESS + \
27 (UINTN)(Bus << 20) + \
28 (UINTN)(Device << 15) + \
29 (UINTN)(Function << 12) + \
30 (UINTN)(Register) \
31 )
32 #define PCI_D31F0_REG_BASE PCIEX_BASE_ADDRESS + (UINT32) (31 << 15)
33
34 typedef struct _LPSS_PCI_DEVICE_INFO {
35 UINTN Segment;
36 UINTN BusNum;
37 UINTN DeviceNum;
38 UINTN FunctionNum;
39 UINTN Bar0;
40 UINTN Bar1;
41 } LPSS_PCI_DEVICE_INFO;
42
43 LPSS_PCI_DEVICE_INFO mLpssPciDeviceList[] = {
44 {0, DEFAULT_PCI_BUS_NUMBER_PCH, PCI_DEVICE_NUMBER_PCH_LPSS_DMAC1, PCI_FUNCTION_NUMBER_PCH_LPSS_DMAC, 0xFE900000, 0xFE908000},
45 {0, DEFAULT_PCI_BUS_NUMBER_PCH, PCI_DEVICE_NUMBER_PCH_LPSS_I2C, PCI_FUNCTION_NUMBER_PCH_LPSS_I2C0, 0xFE910000, 0xFE918000},
46 {0, DEFAULT_PCI_BUS_NUMBER_PCH, PCI_DEVICE_NUMBER_PCH_LPSS_I2C, PCI_FUNCTION_NUMBER_PCH_LPSS_I2C1, 0xFE920000, 0xFE928000},
47 {0, DEFAULT_PCI_BUS_NUMBER_PCH, PCI_DEVICE_NUMBER_PCH_LPSS_I2C, PCI_FUNCTION_NUMBER_PCH_LPSS_I2C2, 0xFE930000, 0xFE938000},
48 {0, DEFAULT_PCI_BUS_NUMBER_PCH, PCI_DEVICE_NUMBER_PCH_LPSS_I2C, PCI_FUNCTION_NUMBER_PCH_LPSS_I2C3, 0xFE940000, 0xFE948000},
49 {0, DEFAULT_PCI_BUS_NUMBER_PCH, PCI_DEVICE_NUMBER_PCH_LPSS_I2C, PCI_FUNCTION_NUMBER_PCH_LPSS_I2C4, 0xFE950000, 0xFE958000},
50 {0, DEFAULT_PCI_BUS_NUMBER_PCH, PCI_DEVICE_NUMBER_PCH_LPSS_I2C, PCI_FUNCTION_NUMBER_PCH_LPSS_I2C5, 0xFE960000, 0xFE968000},
51 {0, DEFAULT_PCI_BUS_NUMBER_PCH, PCI_DEVICE_NUMBER_PCH_LPSS_I2C, PCI_FUNCTION_NUMBER_PCH_LPSS_I2C6, 0xFE970000, 0xFE978000}
52 };
53
54 #define LPSS_PCI_DEVICE_NUMBER sizeof(mLpssPciDeviceList)/sizeof(LPSS_PCI_DEVICE_INFO)
55
56 STATIC UINTN mI2CBaseAddress = 0;
57 STATIC UINT16 mI2CSlaveAddress = 0;
58
59 UINT16 mI2cMode=B_IC_RESTART_EN | B_IC_SLAVE_DISABLE | B_MASTER_MODE ;
60
61 UINTN mI2cNvsBaseAddress[] = {
62 GLOBAL_NVS_OFFSET(LDMA2Addr),
63 GLOBAL_NVS_OFFSET(I2C1Addr),
64 GLOBAL_NVS_OFFSET(I2C2Addr),
65 GLOBAL_NVS_OFFSET(I2C3Addr),
66 GLOBAL_NVS_OFFSET(I2C4Addr),
67 GLOBAL_NVS_OFFSET(I2C5Addr),
68 GLOBAL_NVS_OFFSET(I2C6Addr),
69 GLOBAL_NVS_OFFSET(I2C7Addr)
70 };
71
72 /**
73 This function get I2Cx controller base address (BAR0).
74
75 @param I2cControllerIndex Bus Number of I2C controller.
76
77 @return I2C BAR.
78 **/
79 UINTN
80 GetI2cBarAddr(
81 IN UINT8 I2cControllerIndex
82 )
83 {
84 EFI_STATUS Status;
85 EFI_GLOBAL_NVS_AREA_PROTOCOL *GlobalNvsArea;
86 UINTN AcpiBaseAddr;
87 UINTN PciMmBase=0;
88
89 ASSERT(gBS!=NULL);
90
91 Status = gBS->LocateProtocol (
92 &gEfiGlobalNvsAreaProtocolGuid,
93 NULL,
94 &GlobalNvsArea
95 );
96
97 //
98 // PCI mode from PEI ( Global NVS is not ready).
99 //
100 if (EFI_ERROR(Status)) {
101 DEBUG ((EFI_D_INFO, "GetI2cBarAddr() gEfiGlobalNvsAreaProtocolGuid:%r\n", Status));
102 //
103 // Global NVS is not ready.
104 //
105 return 0;
106 }
107
108 AcpiBaseAddr = *(UINTN*)((CHAR8*)GlobalNvsArea->Area + mI2cNvsBaseAddress[I2cControllerIndex + 1]);
109
110 //
111 //PCI mode from DXE (global NVS protocal) to LPSS OnReadytoBoot(swith to ACPI).
112 //
113 if(AcpiBaseAddr==0) {
114 PciMmBase = MmPciAddress (
115 mLpssPciDeviceList[I2cControllerIndex + 1].Segment,
116 mLpssPciDeviceList[I2cControllerIndex + 1].BusNum,
117 mLpssPciDeviceList[I2cControllerIndex + 1].DeviceNum,
118 mLpssPciDeviceList[I2cControllerIndex + 1].FunctionNum,
119 0
120 );
121 DEBUG((EFI_D_ERROR, "\nGetI2cBarAddr() I2C Device %x %x %x PciMmBase:%x\n", \
122 mLpssPciDeviceList[I2cControllerIndex + 1].BusNum, \
123 mLpssPciDeviceList[I2cControllerIndex + 1].DeviceNum, \
124 mLpssPciDeviceList[I2cControllerIndex + 1].FunctionNum, PciMmBase));
125
126 if (MmioRead32 (PciMmBase) != 0xFFFFFFFF) {
127 if((MmioRead32 (PciMmBase+R_PCH_LPSS_I2C_STSCMD)& B_PCH_LPSS_I2C_STSCMD_MSE)) {
128 //
129 // Get the address allocted.
130 //
131 mLpssPciDeviceList[I2cControllerIndex + 1].Bar0=MmioRead32 (PciMmBase+R_PCH_LPSS_I2C_BAR);
132 mLpssPciDeviceList[I2cControllerIndex + 1].Bar1=MmioRead32 (PciMmBase+R_PCH_LPSS_I2C_BAR1);
133 }
134 }
135 AcpiBaseAddr =mLpssPciDeviceList[I2cControllerIndex+1].Bar0;
136 }
137
138 //
139 // ACPI mode from BDS: LPSS OnReadytoBoot
140 //
141 else {
142 DEBUG ((EFI_D_INFO, "GetI2cBarAddr() NVS Varialable is updated by this LIB or LPSS \n"));
143 }
144
145 DEBUG ((EFI_D_INFO, "GetI2cBarAddr() I2cControllerIndex+1 0x%x AcpiBaseAddr:0x%x \n", (I2cControllerIndex + 1), AcpiBaseAddr));
146 return AcpiBaseAddr;
147 }
148
149
150 /**
151 This function enables I2C controllers.
152
153 @param I2cControllerIndex Bus Number of I2C controllers.
154
155 @return Result of the I2C initialization.
156 **/
157 EFI_STATUS
158 ProgramPciLpssI2C (
159 IN UINT8 I2cControllerIndex
160 )
161 {
162 UINT32 PmcBase;
163 UINTN PciMmBase=0;
164 EFI_STATUS Status;
165 EFI_GLOBAL_NVS_AREA_PROTOCOL *GlobalNvsArea;
166
167 UINT32 PmcFunctionDsiable[]= {
168 B_PCH_PMC_FUNC_DIS_LPSS2_FUNC1,
169 B_PCH_PMC_FUNC_DIS_LPSS2_FUNC2,
170 B_PCH_PMC_FUNC_DIS_LPSS2_FUNC3,
171 B_PCH_PMC_FUNC_DIS_LPSS2_FUNC4,
172 B_PCH_PMC_FUNC_DIS_LPSS2_FUNC5,
173 B_PCH_PMC_FUNC_DIS_LPSS2_FUNC6,
174 B_PCH_PMC_FUNC_DIS_LPSS2_FUNC7
175 };
176
177 DEBUG ((EFI_D_INFO, "ProgramPciLpssI2C() Start\n"));
178
179 //
180 // Set the VLV Function Disable Register to ZERO
181 //
182 PmcBase = MmioRead32 (PCI_D31F0_REG_BASE + R_PCH_LPC_PMC_BASE) & B_PCH_LPC_PMC_BASE_BAR;
183 if(MmioRead32(PmcBase+R_PCH_PMC_FUNC_DIS)&PmcFunctionDsiable[I2cControllerIndex]) {
184 DEBUG ((EFI_D_INFO, "ProgramPciLpssI2C() End:I2C[%x] is disabled\n",I2cControllerIndex));
185 return EFI_NOT_READY;
186 }
187
188 DEBUG ((EFI_D_INFO, "ProgramPciLpssI2C()------------I2cControllerIndex=%x,PMC=%x\n",I2cControllerIndex,MmioRead32(PmcBase+R_PCH_PMC_FUNC_DIS)));
189
190 {
191 PciMmBase = MmPciAddress (
192 mLpssPciDeviceList[I2cControllerIndex+1].Segment,
193 mLpssPciDeviceList[I2cControllerIndex+1].BusNum,
194 mLpssPciDeviceList[I2cControllerIndex+1].DeviceNum,
195 mLpssPciDeviceList[I2cControllerIndex+1].FunctionNum,
196 0
197 );
198
199 DEBUG((EFI_D_ERROR, "Program Pci Lpss I2C Device %x %x %x PciMmBase:%x\n", \
200 mLpssPciDeviceList[I2cControllerIndex+1].BusNum, \
201 mLpssPciDeviceList[I2cControllerIndex+1].DeviceNum, \
202 mLpssPciDeviceList[I2cControllerIndex+1].FunctionNum, PciMmBase));
203
204 if (MmioRead32 (PciMmBase) != 0xFFFFFFFF) {
205 if((MmioRead32 (PciMmBase+R_PCH_LPSS_I2C_STSCMD)& B_PCH_LPSS_I2C_STSCMD_MSE)) {
206 //
207 // Get the address allocted.
208 //
209 mLpssPciDeviceList[I2cControllerIndex+1].Bar0=MmioRead32 (PciMmBase+R_PCH_LPSS_I2C_BAR);
210 mLpssPciDeviceList[I2cControllerIndex+1].Bar1=MmioRead32 (PciMmBase+R_PCH_LPSS_I2C_BAR1);
211 DEBUG((EFI_D_ERROR, "ProgramPciLpssI2C() bar0:0x%x bar1:0x%x\n",mLpssPciDeviceList[I2cControllerIndex+1].Bar0, mLpssPciDeviceList[I2cControllerIndex+1].Bar1));
212 } else {
213
214 //
215 // Program BAR 0
216 //
217 ASSERT (((mLpssPciDeviceList[I2cControllerIndex+1].Bar0 & B_PCH_LPSS_I2C_BAR_BA) == mLpssPciDeviceList[I2cControllerIndex+1].Bar0) && (mLpssPciDeviceList[I2cControllerIndex+1].Bar0 != 0));
218 MmioWrite32 ((UINTN) (PciMmBase + R_PCH_LPSS_I2C_BAR), (UINT32) (mLpssPciDeviceList[I2cControllerIndex+1].Bar0 & B_PCH_LPSS_I2C_BAR_BA));
219
220 //
221 // Program BAR 1
222 //
223 ASSERT (((mLpssPciDeviceList[I2cControllerIndex+1].Bar1 & B_PCH_LPSS_I2C_BAR1_BA) == mLpssPciDeviceList[I2cControllerIndex+1].Bar1) && (mLpssPciDeviceList[I2cControllerIndex+1].Bar1 != 0));
224 MmioWrite32 ((UINTN) (PciMmBase + R_PCH_LPSS_I2C_BAR1), (UINT32) (mLpssPciDeviceList[I2cControllerIndex+1].Bar1 & B_PCH_LPSS_I2C_BAR1_BA));
225
226 //
227 // Bus Master Enable & Memory Space Enable
228 //
229 MmioOr32 ((UINTN) (PciMmBase + R_PCH_LPSS_I2C_STSCMD), (UINT32) (B_PCH_LPSS_I2C_STSCMD_BME | B_PCH_LPSS_I2C_STSCMD_MSE));
230 ASSERT (MmioRead32 (mLpssPciDeviceList[I2cControllerIndex+1].Bar0) != 0xFFFFFFFF);
231 }
232
233 //
234 // Release Resets
235 //
236 MmioWrite32 (mLpssPciDeviceList[I2cControllerIndex+1].Bar0 + R_PCH_LPIO_I2C_MEM_RESETS,(B_PCH_LPIO_I2C_MEM_RESETS_FUNC | B_PCH_LPIO_I2C_MEM_RESETS_APB));
237
238 //
239 // Activate Clocks
240 //
241 MmioWrite32 (mLpssPciDeviceList[I2cControllerIndex+1].Bar0 + R_PCH_LPSS_I2C_MEM_PCP,0x80020003);//No use for A0
242
243 DEBUG ((EFI_D_INFO, "ProgramPciLpssI2C() Programmed()\n"));
244 }
245
246 //
247 // BDS: already switched to ACPI mode
248 //
249 else {
250 ASSERT(gBS!=NULL);
251 Status = gBS->LocateProtocol (
252 &gEfiGlobalNvsAreaProtocolGuid,
253 NULL,
254 &GlobalNvsArea
255 );
256 if (EFI_ERROR(Status)) {
257 DEBUG ((EFI_D_INFO, "GetI2cBarAddr() gEfiGlobalNvsAreaProtocolGuid:%r\n", Status));
258 //
259 // gEfiGlobalNvsAreaProtocolGuid is not ready.
260 //
261 return 0;
262 }
263 mLpssPciDeviceList[I2cControllerIndex + 1].Bar0 = *(UINTN*)((CHAR8*)GlobalNvsArea->Area + mI2cNvsBaseAddress[I2cControllerIndex + 1]);
264 DEBUG ((EFI_D_INFO, "ProgramPciLpssI2C(): is switched to ACPI 0x:%x \n",mLpssPciDeviceList[I2cControllerIndex + 1].Bar0));
265 }
266 }
267
268 DEBUG ((EFI_D_INFO, "ProgramPciLpssI2C() End\n"));
269
270 return EFI_SUCCESS;
271 }
272
273 /**
274 Disable I2C Bus.
275
276 @param VOID.
277
278 @return Result of the I2C disabling.
279 **/
280 RETURN_STATUS
281 I2cDisable (
282 VOID
283 )
284 {
285 //
286 // 0.1 seconds
287 //
288 UINT32 NumTries = 10000;
289
290 MmioWrite32 ( mI2CBaseAddress + R_IC_ENABLE, 0 );
291 while ( 0 != ( MmioRead32 ( mI2CBaseAddress + R_IC_ENABLE_STATUS) & 1)) {
292 MicroSecondDelay (10);
293 NumTries --;
294 if(0 == NumTries) {
295 return RETURN_NOT_READY;
296 }
297 }
298
299 return RETURN_SUCCESS;
300 }
301
302 /**
303 Enable I2C Bus.
304
305 @param VOID.
306
307 @return Result of the I2C disabling.
308 **/
309 RETURN_STATUS
310 I2cEnable (
311 VOID
312 )
313 {
314 //
315 // 0.1 seconds
316 //
317 UINT32 NumTries = 10000;
318
319 MmioWrite32 (mI2CBaseAddress + R_IC_ENABLE, 1);
320
321 while (0 == (MmioRead32 (mI2CBaseAddress + R_IC_ENABLE_STATUS) & 1)) {
322 MicroSecondDelay (10);
323 NumTries --;
324 if(0 == NumTries){
325 return RETURN_NOT_READY;
326 }
327 }
328
329 return RETURN_SUCCESS;
330 }
331
332 /**
333 Enable I2C Bus.
334
335 @param VOID.
336
337 @return Result of the I2C enabling.
338 **/
339 RETURN_STATUS
340 I2cBusFrequencySet (
341 IN UINTN BusClockHertz
342 )
343 {
344 DEBUG((EFI_D_INFO,"InputFreq BusClockHertz: %d\r\n",BusClockHertz));
345
346 //
347 // Set the 100 KHz clock divider according to SV result and I2C spec
348 //
349 MmioWrite32 ( mI2CBaseAddress + R_IC_SS_SCL_HCNT, (UINT16)0x214 );
350 MmioWrite32 ( mI2CBaseAddress + R_IC_SS_SCL_LCNT, (UINT16)0x272 );
351
352 //
353 // Set the 400 KHz clock divider according to SV result and I2C spec
354 //
355 MmioWrite32 ( mI2CBaseAddress + R_IC_FS_SCL_HCNT, (UINT16)0x50 );
356 MmioWrite32 ( mI2CBaseAddress + R_IC_FS_SCL_LCNT, (UINT16)0xAD );
357
358 switch ( BusClockHertz ) {
359 case 100 * 1000:
360 MmioWrite32 ( mI2CBaseAddress + R_IC_SDA_HOLD, (UINT16)0x40);//100K
361 mI2cMode = V_SPEED_STANDARD;
362 break;
363 case 400 * 1000:
364 MmioWrite32 ( mI2CBaseAddress + R_IC_SDA_HOLD, (UINT16)0x32);//400K
365 mI2cMode = V_SPEED_FAST;
366 break;
367 default:
368 MmioWrite32 ( mI2CBaseAddress + R_IC_SDA_HOLD, (UINT16)0x09);//3.4M
369 mI2cMode = V_SPEED_HIGH;
370 }
371
372 //
373 // Select the frequency counter,
374 // Enable restart condition,
375 // Enable master FSM, disable slave FSM.
376 //
377 mI2cMode |= B_IC_RESTART_EN | B_IC_SLAVE_DISABLE | B_MASTER_MODE;
378
379 return EFI_SUCCESS;
380 }
381
382 /**
383 Initializes the host controller to execute I2C commands.
384
385 @param I2cControllerIndex Index of I2C controller in LPSS device. 0 represents I2C0, which is PCI function 1 of LPSS device.
386
387 @return EFI_SUCCESS Opcode initialization on the I2C host controller completed.
388 @return EFI_DEVICE_ERROR Device error, operation failed.
389 **/
390 EFI_STATUS
391 I2CInit (
392 IN UINT8 I2cControllerIndex,
393 IN UINT16 SlaveAddress
394 )
395 {
396 EFI_STATUS Status=RETURN_SUCCESS;
397 UINT32 NumTries = 0;
398 UINTN GnvsI2cBarAddr=0;
399
400 //
401 // Verify the parameters
402 //
403 if ((1023 < SlaveAddress) || (6 < I2cControllerIndex)) {
404 Status = RETURN_INVALID_PARAMETER;
405 DEBUG((EFI_D_INFO,"I2CInit Exit with RETURN_INVALID_PARAMETER\r\n"));
406 return Status;
407 }
408 MmioWrite32 ( mI2CBaseAddress + R_IC_TAR, (UINT16)SlaveAddress );
409 mI2CSlaveAddress = SlaveAddress;
410
411 //
412 // 1.PEI: program and init ( before pci enumeration).
413 // 2.DXE:update address and re-init ( after pci enumeration).
414 // 3.BDS:update ACPI address and re-init ( after acpi mode is enabled).
415 //
416 if(mI2CBaseAddress == mLpssPciDeviceList[I2cControllerIndex + 1].Bar0) {
417
418 //
419 // I2CInit is already called.
420 //
421 GnvsI2cBarAddr=GetI2cBarAddr(I2cControllerIndex);
422
423 if((GnvsI2cBarAddr == 0)||(GnvsI2cBarAddr == mI2CBaseAddress)) {
424 DEBUG((EFI_D_INFO,"I2CInit Exit with mI2CBaseAddress:%x == [%x].Bar0\r\n",mI2CBaseAddress,I2cControllerIndex+1));
425 return RETURN_SUCCESS;
426 }
427 }
428
429 Status=ProgramPciLpssI2C(I2cControllerIndex);
430 if(Status!=EFI_SUCCESS) {
431 return Status;
432 }
433
434
435 mI2CBaseAddress = (UINT32) mLpssPciDeviceList[I2cControllerIndex + 1].Bar0;
436 DEBUG ((EFI_D_ERROR, "mI2CBaseAddress = 0x%x \n",mI2CBaseAddress));
437
438 //
439 // 1 seconds.
440 //
441 NumTries = 10000;
442 while ((1 == ( MmioRead32 ( mI2CBaseAddress + R_IC_STATUS) & STAT_MST_ACTIVITY ))) {
443 MicroSecondDelay(10);
444 NumTries --;
445 if(0 == NumTries) {
446 DEBUG((EFI_D_INFO, "Try timeout\r\n"));
447 return RETURN_DEVICE_ERROR;
448 }
449 }
450
451 Status = I2cDisable();
452 DEBUG((EFI_D_INFO, "I2cDisable Status = %r\r\n", Status));
453 I2cBusFrequencySet(400 * 1000);
454
455 MmioWrite32(mI2CBaseAddress + R_IC_INTR_MASK, 0x0);
456 if (0x7f < SlaveAddress )
457 SlaveAddress = ( SlaveAddress & 0x3ff ) | IC_TAR_10BITADDR_MASTER;
458 MmioWrite32 ( mI2CBaseAddress + R_IC_TAR, (UINT16)SlaveAddress );
459 MmioWrite32 ( mI2CBaseAddress + R_IC_RX_TL, 0);
460 MmioWrite32 ( mI2CBaseAddress + R_IC_TX_TL, 0 );
461 MmioWrite32 ( mI2CBaseAddress + R_IC_CON, mI2cMode);
462 Status = I2cEnable();
463
464 DEBUG((EFI_D_INFO, "I2cEnable Status = %r\r\n", Status));
465 MmioRead32 ( mI2CBaseAddress + R_IC_CLR_TX_ABRT );
466
467 return EFI_SUCCESS;
468 }
469
470 /**
471 Reads a Byte from I2C Device.
472
473 @param I2cControllerIndex I2C Bus no to which the I2C device has been connected
474 @param SlaveAddress Device Address from which the byte value has to be read
475 @param Offset Offset from which the data has to be read
476 @param *Byte Address to which the value read has to be stored
477 @param Start Whether a RESTART is issued before the byte is sent or received
478 @param End Whether STOP is generated after a data byte is sent or received
479
480 @return EFI_SUCCESS IF the byte value has been successfully read
481 @return EFI_DEVICE_ERROR Operation Failed, Device Error
482 **/
483 EFI_STATUS
484 ByteReadI2CBasic(
485 IN UINT8 I2cControllerIndex,
486 IN UINT8 SlaveAddress,
487 IN UINTN ReadBytes,
488 OUT UINT8 *ReadBuffer,
489 IN UINT8 Start,
490 IN UINT8 End
491 )
492 {
493
494 EFI_STATUS Status;
495 UINT32 I2cStatus;
496 UINT16 ReceiveData;
497 UINT8 *ReceiveDataEnd;
498 UINT8 *ReceiveRequest;
499 UINT16 RawIntrStat;
500 UINT32 Count=0;
501
502 Status = EFI_SUCCESS;
503
504 ReceiveDataEnd = &ReadBuffer [ReadBytes];
505 if( ReadBytes ) {
506
507 ReceiveRequest = ReadBuffer;
508 DEBUG((EFI_D_INFO,"Read: ---------------%d bytes to RX\r\n",ReceiveDataEnd - ReceiveRequest));
509
510 while ((ReceiveDataEnd > ReceiveRequest) || (ReceiveDataEnd > ReadBuffer)) {
511
512 //
513 // Check for NACK
514 //
515 RawIntrStat = (UINT16)MmioRead32 (mI2CBaseAddress + R_IC_RawIntrStat);
516 if ( 0 != ( RawIntrStat & I2C_INTR_TX_ABRT )) {
517 MmioRead32 ( mI2CBaseAddress + R_IC_CLR_TX_ABRT );
518 Status = RETURN_DEVICE_ERROR;
519 DEBUG((EFI_D_INFO,"TX ABRT ,%d bytes hasn't been transferred\r\n",ReceiveDataEnd - ReceiveRequest));
520 break;
521 }
522
523 //
524 // Determine if another byte was received
525 //
526 I2cStatus = (UINT16)MmioRead32 (mI2CBaseAddress + R_IC_STATUS);
527 if (0 != ( I2cStatus & STAT_RFNE )) {
528 ReceiveData = (UINT16)MmioRead32 ( mI2CBaseAddress + R_IC_DATA_CMD );
529 *ReadBuffer++ = (UINT8)ReceiveData;
530 DEBUG((EFI_D_INFO,"MmioRead32 ,1 byte 0x:%x is received\r\n",ReceiveData));
531 }
532
533 if(ReceiveDataEnd == ReceiveRequest) {
534 MicroSecondDelay ( FIFO_WRITE_DELAY );
535 DEBUG((EFI_D_INFO,"ReceiveDataEnd==ReceiveRequest------------%x\r\n",I2cStatus & STAT_RFNE));
536 Count++;
537 if(Count<1024) {
538 //
539 // To avoid sys hung without ul-pmc device on RVP,
540 // waiting the last request to get data and make (ReceiveDataEnd > ReadBuffer) =TRUE.
541 //
542 continue;
543 } else {
544 break;
545 }
546 }
547
548 //
549 // Wait until a read request will fit.
550 //
551 if (0 == (I2cStatus & STAT_TFNF)) {
552 DEBUG((EFI_D_INFO,"Wait until a read request will fit\r\n"));
553 MicroSecondDelay (10);
554 continue;
555 }
556
557 //
558 // Issue the next read request.
559 //
560 if(End && Start) {
561 MmioWrite32 ( mI2CBaseAddress + R_IC_DATA_CMD, B_READ_CMD|B_CMD_RESTART|B_CMD_STOP);
562 } else if (!End && Start) {
563 MmioWrite32 ( mI2CBaseAddress + R_IC_DATA_CMD, B_READ_CMD|B_CMD_RESTART);
564 } else if (End && !Start) {
565 MmioWrite32 ( mI2CBaseAddress + R_IC_DATA_CMD, B_READ_CMD|B_CMD_STOP);
566 } else if (!End && !Start) {
567 MmioWrite32 ( mI2CBaseAddress + R_IC_DATA_CMD, B_READ_CMD);
568 }
569 MicroSecondDelay (FIFO_WRITE_DELAY);
570
571 ReceiveRequest += 1;
572 }
573 }
574
575 return Status;
576 }
577
578 /**
579 Writes a Byte to I2C Device.
580
581 @param I2cControllerIndex I2C Bus no to which the I2C device has been connected
582 @param SlaveAddress Device Address from which the byte value has to be written
583 @param Offset Offset from which the data has to be read
584 @param *Byte Address to which the value written is stored
585 @param Start Whether a RESTART is issued before the byte is sent or received
586 @param End Whether STOP is generated after a data byte is sent or received
587
588 @return EFI_SUCCESS IF the byte value has been successfully written
589 @return EFI_DEVICE_ERROR Operation Failed, Device Error
590 **/
591 EFI_STATUS ByteWriteI2CBasic(
592 IN UINT8 I2cControllerIndex,
593 IN UINT8 SlaveAddress,
594 IN UINTN WriteBytes,
595 IN UINT8 *WriteBuffer,
596 IN UINT8 Start,
597 IN UINT8 End
598 )
599 {
600
601 EFI_STATUS Status;
602 UINT32 I2cStatus;
603 UINT8 *TransmitEnd;
604 UINT16 RawIntrStat;
605 UINT32 Count=0;
606
607 Status = EFI_SUCCESS;
608
609 Status=I2CInit(I2cControllerIndex, SlaveAddress);
610 if(Status!=EFI_SUCCESS)
611 return Status;
612
613 TransmitEnd = &WriteBuffer[WriteBytes];
614 if( WriteBytes ) {
615 DEBUG((EFI_D_INFO,"Write: --------------%d bytes to TX\r\n",TransmitEnd - WriteBuffer));
616 while (TransmitEnd > WriteBuffer) {
617 I2cStatus = MmioRead32 (mI2CBaseAddress + R_IC_STATUS);
618 RawIntrStat = (UINT16)MmioRead32 (mI2CBaseAddress + R_IC_RawIntrStat);
619 if (0 != ( RawIntrStat & I2C_INTR_TX_ABRT)) {
620 MmioRead32 ( mI2CBaseAddress + R_IC_CLR_TX_ABRT);
621 Status = RETURN_DEVICE_ERROR;
622 DEBUG((EFI_D_ERROR,"TX ABRT TransmitEnd:0x%x WriteBuffer:0x%x\r\n", TransmitEnd, WriteBuffer));
623 break;
624 }
625 if (0 == (I2cStatus & STAT_TFNF)) {
626 //
627 // If TX not full , will send cmd or continue to wait
628 //
629 MicroSecondDelay (FIFO_WRITE_DELAY);
630 continue;
631 }
632
633 if(End && Start) {
634 MmioWrite32 (mI2CBaseAddress + R_IC_DATA_CMD, (*WriteBuffer++)|B_CMD_RESTART|B_CMD_STOP);
635 } else if (!End && Start) {
636 MmioWrite32 (mI2CBaseAddress + R_IC_DATA_CMD, (*WriteBuffer++)|B_CMD_RESTART);
637 } else if (End && !Start) {
638 MmioWrite32 (mI2CBaseAddress + R_IC_DATA_CMD, (*WriteBuffer++)|B_CMD_STOP);
639 } else if (!End && !Start ) {
640 MmioWrite32 (mI2CBaseAddress + R_IC_DATA_CMD, (*WriteBuffer++));
641 }
642
643 //
644 // Add a small delay to work around some odd behavior being seen. Without this delay bytes get dropped.
645 //
646 MicroSecondDelay ( FIFO_WRITE_DELAY );//wait after send cmd
647
648 //
649 // Time out
650 //
651 while(1) {
652 RawIntrStat = MmioRead16 ( mI2CBaseAddress + R_IC_RawIntrStat );
653 if (0 != ( RawIntrStat & I2C_INTR_TX_ABRT)) {
654 MmioRead16 (mI2CBaseAddress + R_IC_CLR_TX_ABRT);
655 Status = RETURN_DEVICE_ERROR;
656 DEBUG((EFI_D_ERROR,"TX ABRT TransmitEnd:0x%x WriteBuffer:0x%x\r\n", TransmitEnd, WriteBuffer));
657 }
658 if(0 == MmioRead16(mI2CBaseAddress + R_IC_TXFLR)) break;
659
660 MicroSecondDelay (FIFO_WRITE_DELAY);
661 Count++;
662 if(Count<1024) {
663 //
664 // to avoid sys hung without ul-pmc device on RVP.
665 // Waiting the last request to get data and make (ReceiveDataEnd > ReadBuffer) =TRUE.
666 //
667 continue;
668 } else {
669 break;
670 }
671 }//while( 1 )
672 }
673
674 }
675
676 return Status;
677 }
678
679 /**
680 Reads a Byte from I2C Device.
681
682 @param I2cControllerIndex I2C Bus no to which the I2C device has been connected
683 @param SlaveAddress Device Address from which the byte value has to be read
684 @param Offset Offset from which the data has to be read
685 @param ReadBytes Number of bytes to be read
686 @param *ReadBuffer Address to which the value read has to be stored
687
688 @return EFI_SUCCESS IF the byte value has been successfully read
689 @return EFI_DEVICE_ERROR Operation Failed, Device Error
690 **/
691 EFI_STATUS ByteReadI2C(
692 IN UINT8 I2cControllerIndex,
693 IN UINT8 SlaveAddress,
694 IN UINT8 Offset,
695 IN UINTN ReadBytes,
696 OUT UINT8 *ReadBuffer
697 )
698 {
699 EFI_STATUS Status;
700
701 DEBUG ((EFI_D_INFO, "ByteReadI2C:---offset:0x%x\n",Offset));
702 Status = ByteWriteI2CBasic(I2cControllerIndex, SlaveAddress,1,&Offset,TRUE,FALSE);
703 Status = ByteReadI2CBasic(I2cControllerIndex, SlaveAddress,ReadBytes,ReadBuffer,TRUE,TRUE);
704
705 return Status;
706 }
707
708 /**
709 Writes a Byte to I2C Device.
710
711 @param I2cControllerIndex I2C Bus no to which the I2C device has been connected
712 @param SlaveAddress Device Address from which the byte value has to be written
713 @param Offset Offset from which the data has to be written
714 @param WriteBytes Number of bytes to be written
715 @param *Byte Address to which the value written is stored
716
717 @return EFI_SUCCESS IF the byte value has been successfully read
718 @return EFI_DEVICE_ERROR Operation Failed, Device Error
719 **/
720 EFI_STATUS ByteWriteI2C(
721 IN UINT8 I2cControllerIndex,
722 IN UINT8 SlaveAddress,
723 IN UINT8 Offset,
724 IN UINTN WriteBytes,
725 IN UINT8 *WriteBuffer
726 )
727 {
728 EFI_STATUS Status;
729
730 DEBUG ((EFI_D_INFO, "ByteWriteI2C:---offset/bytes/buf:0x%x,0x%x,0x%x,0x%x\n",Offset,WriteBytes,WriteBuffer,*WriteBuffer));
731 Status = ByteWriteI2CBasic(I2cControllerIndex, SlaveAddress,1,&Offset,TRUE,FALSE);
732 Status = ByteWriteI2CBasic(I2cControllerIndex, SlaveAddress,WriteBytes,WriteBuffer,FALSE,TRUE);
733
734 return Status;
735 }