2 Functions for accessing I2C registers.
4 Copyright (c) 2004 - 2015, Intel Corporation. All rights reserved.<BR>
6 SPDX-License-Identifier: BSD-2-Clause-Patent
10 #include <Library/DebugLib.h>
11 #include <Library/TimerLib.h>
12 #include <PchRegs/PchRegsPcu.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>
21 #define GLOBAL_NVS_OFFSET(Field) (UINTN)((CHAR8*)&((EFI_GLOBAL_NVS_AREA*)0)->Field - (CHAR8*)0)
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) + \
32 #define PCI_D31F0_REG_BASE PCIEX_BASE_ADDRESS + (UINT32) (31 << 15)
34 typedef struct _LPSS_PCI_DEVICE_INFO
{
41 } LPSS_PCI_DEVICE_INFO
;
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}
54 #define LPSS_PCI_DEVICE_NUMBER sizeof(mLpssPciDeviceList)/sizeof(LPSS_PCI_DEVICE_INFO)
56 STATIC UINTN mI2CBaseAddress
= 0;
57 STATIC UINT16 mI2CSlaveAddress
= 0;
59 UINT16 mI2cMode
=B_IC_RESTART_EN
| B_IC_SLAVE_DISABLE
| B_MASTER_MODE
;
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
)
73 This function get I2Cx controller base address (BAR0).
75 @param I2cControllerIndex Bus Number of I2C controller.
81 IN UINT8 I2cControllerIndex
85 EFI_GLOBAL_NVS_AREA_PROTOCOL
*GlobalNvsArea
;
91 Status
= gBS
->LocateProtocol (
92 &gEfiGlobalNvsAreaProtocolGuid
,
98 // PCI mode from PEI ( Global NVS is not ready).
100 if (EFI_ERROR(Status
)) {
101 DEBUG ((EFI_D_INFO
, "GetI2cBarAddr() gEfiGlobalNvsAreaProtocolGuid:%r\n", Status
));
103 // Global NVS is not ready.
108 AcpiBaseAddr
= *(UINTN
*)((CHAR8
*)GlobalNvsArea
->Area
+ mI2cNvsBaseAddress
[I2cControllerIndex
+ 1]);
111 //PCI mode from DXE (global NVS protocal) to LPSS OnReadytoBoot(swith to ACPI).
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
,
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
));
126 if (MmioRead32 (PciMmBase
) != 0xFFFFFFFF) {
127 if((MmioRead32 (PciMmBase
+R_PCH_LPSS_I2C_STSCMD
)& B_PCH_LPSS_I2C_STSCMD_MSE
)) {
129 // Get the address allocted.
131 mLpssPciDeviceList
[I2cControllerIndex
+ 1].Bar0
=MmioRead32 (PciMmBase
+R_PCH_LPSS_I2C_BAR
);
132 mLpssPciDeviceList
[I2cControllerIndex
+ 1].Bar1
=MmioRead32 (PciMmBase
+R_PCH_LPSS_I2C_BAR1
);
135 AcpiBaseAddr
=mLpssPciDeviceList
[I2cControllerIndex
+1].Bar0
;
139 // ACPI mode from BDS: LPSS OnReadytoBoot
142 DEBUG ((EFI_D_INFO
, "GetI2cBarAddr() NVS Varialable is updated by this LIB or LPSS \n"));
145 DEBUG ((EFI_D_INFO
, "GetI2cBarAddr() I2cControllerIndex+1 0x%x AcpiBaseAddr:0x%x \n", (I2cControllerIndex
+ 1), AcpiBaseAddr
));
151 This function enables I2C controllers.
153 @param I2cControllerIndex Bus Number of I2C controllers.
155 @return Result of the I2C initialization.
159 IN UINT8 I2cControllerIndex
165 EFI_GLOBAL_NVS_AREA_PROTOCOL
*GlobalNvsArea
;
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
177 DEBUG ((EFI_D_INFO
, "ProgramPciLpssI2C() Start\n"));
180 // Set the VLV Function Disable Register to ZERO
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
;
188 DEBUG ((EFI_D_INFO
, "ProgramPciLpssI2C()------------I2cControllerIndex=%x,PMC=%x\n",I2cControllerIndex
,MmioRead32(PmcBase
+R_PCH_PMC_FUNC_DIS
)));
191 PciMmBase
= MmPciAddress (
192 mLpssPciDeviceList
[I2cControllerIndex
+1].Segment
,
193 mLpssPciDeviceList
[I2cControllerIndex
+1].BusNum
,
194 mLpssPciDeviceList
[I2cControllerIndex
+1].DeviceNum
,
195 mLpssPciDeviceList
[I2cControllerIndex
+1].FunctionNum
,
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
));
204 if (MmioRead32 (PciMmBase
) != 0xFFFFFFFF) {
205 if((MmioRead32 (PciMmBase
+R_PCH_LPSS_I2C_STSCMD
)& B_PCH_LPSS_I2C_STSCMD_MSE
)) {
207 // Get the address allocted.
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
));
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
));
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
));
227 // Bus Master Enable & Memory Space Enable
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);
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
));
241 MmioWrite32 (mLpssPciDeviceList
[I2cControllerIndex
+1].Bar0
+ R_PCH_LPSS_I2C_MEM_PCP
,0x80020003);//No use for A0
243 DEBUG ((EFI_D_INFO
, "ProgramPciLpssI2C() Programmed()\n"));
247 // BDS: already switched to ACPI mode
251 Status
= gBS
->LocateProtocol (
252 &gEfiGlobalNvsAreaProtocolGuid
,
256 if (EFI_ERROR(Status
)) {
257 DEBUG ((EFI_D_INFO
, "GetI2cBarAddr() gEfiGlobalNvsAreaProtocolGuid:%r\n", Status
));
259 // gEfiGlobalNvsAreaProtocolGuid is not ready.
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
));
268 DEBUG ((EFI_D_INFO
, "ProgramPciLpssI2C() End\n"));
278 @return Result of the I2C disabling.
288 UINT32 NumTries
= 10000;
290 MmioWrite32 ( mI2CBaseAddress
+ R_IC_ENABLE
, 0 );
291 while ( 0 != ( MmioRead32 ( mI2CBaseAddress
+ R_IC_ENABLE_STATUS
) & 1)) {
292 MicroSecondDelay (10);
295 return RETURN_NOT_READY
;
299 return RETURN_SUCCESS
;
307 @return Result of the I2C disabling.
317 UINT32 NumTries
= 10000;
319 MmioWrite32 (mI2CBaseAddress
+ R_IC_ENABLE
, 1);
321 while (0 == (MmioRead32 (mI2CBaseAddress
+ R_IC_ENABLE_STATUS
) & 1)) {
322 MicroSecondDelay (10);
325 return RETURN_NOT_READY
;
329 return RETURN_SUCCESS
;
337 @return Result of the I2C enabling.
341 IN UINTN BusClockHertz
344 DEBUG((EFI_D_INFO
,"InputFreq BusClockHertz: %d\r\n",BusClockHertz
));
347 // Set the 100 KHz clock divider according to SV result and I2C spec
349 MmioWrite32 ( mI2CBaseAddress
+ R_IC_SS_SCL_HCNT
, (UINT16
)0x214 );
350 MmioWrite32 ( mI2CBaseAddress
+ R_IC_SS_SCL_LCNT
, (UINT16
)0x272 );
353 // Set the 400 KHz clock divider according to SV result and I2C spec
355 MmioWrite32 ( mI2CBaseAddress
+ R_IC_FS_SCL_HCNT
, (UINT16
)0x50 );
356 MmioWrite32 ( mI2CBaseAddress
+ R_IC_FS_SCL_LCNT
, (UINT16
)0xAD );
358 switch ( BusClockHertz
) {
360 MmioWrite32 ( mI2CBaseAddress
+ R_IC_SDA_HOLD
, (UINT16
)0x40);//100K
361 mI2cMode
= V_SPEED_STANDARD
;
364 MmioWrite32 ( mI2CBaseAddress
+ R_IC_SDA_HOLD
, (UINT16
)0x32);//400K
365 mI2cMode
= V_SPEED_FAST
;
368 MmioWrite32 ( mI2CBaseAddress
+ R_IC_SDA_HOLD
, (UINT16
)0x09);//3.4M
369 mI2cMode
= V_SPEED_HIGH
;
373 // Select the frequency counter,
374 // Enable restart condition,
375 // Enable master FSM, disable slave FSM.
377 mI2cMode
|= B_IC_RESTART_EN
| B_IC_SLAVE_DISABLE
| B_MASTER_MODE
;
383 Initializes the host controller to execute I2C commands.
385 @param I2cControllerIndex Index of I2C controller in LPSS device. 0 represents I2C0, which is PCI function 1 of LPSS device.
387 @return EFI_SUCCESS Opcode initialization on the I2C host controller completed.
388 @return EFI_DEVICE_ERROR Device error, operation failed.
392 IN UINT8 I2cControllerIndex
,
393 IN UINT16 SlaveAddress
396 EFI_STATUS Status
=RETURN_SUCCESS
;
398 UINTN GnvsI2cBarAddr
=0;
401 // Verify the parameters
403 if ((1023 < SlaveAddress
) || (6 < I2cControllerIndex
)) {
404 Status
= RETURN_INVALID_PARAMETER
;
405 DEBUG((EFI_D_INFO
,"I2CInit Exit with RETURN_INVALID_PARAMETER\r\n"));
408 MmioWrite32 ( mI2CBaseAddress
+ R_IC_TAR
, (UINT16
)SlaveAddress
);
409 mI2CSlaveAddress
= SlaveAddress
;
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).
416 if(mI2CBaseAddress
== mLpssPciDeviceList
[I2cControllerIndex
+ 1].Bar0
) {
419 // I2CInit is already called.
421 GnvsI2cBarAddr
=GetI2cBarAddr(I2cControllerIndex
);
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
;
429 Status
=ProgramPciLpssI2C(I2cControllerIndex
);
430 if(Status
!=EFI_SUCCESS
) {
435 mI2CBaseAddress
= (UINT32
) mLpssPciDeviceList
[I2cControllerIndex
+ 1].Bar0
;
436 DEBUG ((EFI_D_ERROR
, "mI2CBaseAddress = 0x%x \n",mI2CBaseAddress
));
442 while ((1 == ( MmioRead32 ( mI2CBaseAddress
+ R_IC_STATUS
) & STAT_MST_ACTIVITY
))) {
443 MicroSecondDelay(10);
446 DEBUG((EFI_D_INFO
, "Try timeout\r\n"));
447 return RETURN_DEVICE_ERROR
;
451 Status
= I2cDisable();
452 DEBUG((EFI_D_INFO
, "I2cDisable Status = %r\r\n", Status
));
453 I2cBusFrequencySet(400 * 1000);
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();
464 DEBUG((EFI_D_INFO
, "I2cEnable Status = %r\r\n", Status
));
465 MmioRead32 ( mI2CBaseAddress
+ R_IC_CLR_TX_ABRT
);
471 Reads a Byte from I2C Device.
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
480 @return EFI_SUCCESS IF the byte value has been successfully read
481 @return EFI_DEVICE_ERROR Operation Failed, Device Error
485 IN UINT8 I2cControllerIndex
,
486 IN UINT8 SlaveAddress
,
488 OUT UINT8
*ReadBuffer
,
497 UINT8
*ReceiveDataEnd
;
498 UINT8
*ReceiveRequest
;
502 Status
= EFI_SUCCESS
;
504 ReceiveDataEnd
= &ReadBuffer
[ReadBytes
];
507 ReceiveRequest
= ReadBuffer
;
508 DEBUG((EFI_D_INFO
,"Read: ---------------%d bytes to RX\r\n",ReceiveDataEnd
- ReceiveRequest
));
510 while ((ReceiveDataEnd
> ReceiveRequest
) || (ReceiveDataEnd
> ReadBuffer
)) {
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
));
524 // Determine if another byte was received
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
));
533 if(ReceiveDataEnd
== ReceiveRequest
) {
534 MicroSecondDelay ( FIFO_WRITE_DELAY
);
535 DEBUG((EFI_D_INFO
,"ReceiveDataEnd==ReceiveRequest------------%x\r\n",I2cStatus
& STAT_RFNE
));
539 // To avoid sys hung without ul-pmc device on RVP,
540 // waiting the last request to get data and make (ReceiveDataEnd > ReadBuffer) =TRUE.
549 // Wait until a read request will fit.
551 if (0 == (I2cStatus
& STAT_TFNF
)) {
552 DEBUG((EFI_D_INFO
,"Wait until a read request will fit\r\n"));
553 MicroSecondDelay (10);
558 // Issue the next read request.
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
);
569 MicroSecondDelay (FIFO_WRITE_DELAY
);
579 Writes a Byte to I2C Device.
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
588 @return EFI_SUCCESS IF the byte value has been successfully written
589 @return EFI_DEVICE_ERROR Operation Failed, Device Error
591 EFI_STATUS
ByteWriteI2CBasic(
592 IN UINT8 I2cControllerIndex
,
593 IN UINT8 SlaveAddress
,
595 IN UINT8
*WriteBuffer
,
607 Status
= EFI_SUCCESS
;
609 Status
=I2CInit(I2cControllerIndex
, SlaveAddress
);
610 if(Status
!=EFI_SUCCESS
)
613 TransmitEnd
= &WriteBuffer
[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
));
625 if (0 == (I2cStatus
& STAT_TFNF
)) {
627 // If TX not full , will send cmd or continue to wait
629 MicroSecondDelay (FIFO_WRITE_DELAY
);
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
++));
644 // Add a small delay to work around some odd behavior being seen. Without this delay bytes get dropped.
646 MicroSecondDelay ( FIFO_WRITE_DELAY
);//wait after send cmd
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
));
658 if(0 == MmioRead16(mI2CBaseAddress
+ R_IC_TXFLR
)) break;
660 MicroSecondDelay (FIFO_WRITE_DELAY
);
664 // to avoid sys hung without ul-pmc device on RVP.
665 // Waiting the last request to get data and make (ReceiveDataEnd > ReadBuffer) =TRUE.
680 Reads a Byte from I2C Device.
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
688 @return EFI_SUCCESS IF the byte value has been successfully read
689 @return EFI_DEVICE_ERROR Operation Failed, Device Error
691 EFI_STATUS
ByteReadI2C(
692 IN UINT8 I2cControllerIndex
,
693 IN UINT8 SlaveAddress
,
696 OUT UINT8
*ReadBuffer
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
);
709 Writes a Byte to I2C Device.
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
717 @return EFI_SUCCESS IF the byte value has been successfully read
718 @return EFI_DEVICE_ERROR Operation Failed, Device Error
720 EFI_STATUS
ByteWriteI2C(
721 IN UINT8 I2cControllerIndex
,
722 IN UINT8 SlaveAddress
,
725 IN UINT8
*WriteBuffer
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
);