2 Functions for accessing I2C registers.
4 Copyright (c) 2004 - 2015, Intel Corporation. All rights reserved.<BR>
6 This program and the accompanying materials are licensed and made available under
7 the terms and conditions of the BSD License that accompanies this distribution.
8 The full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php.
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
16 #include <Library/DebugLib.h>
17 #include <Library/TimerLib.h>
18 #include <PchRegs/PchRegsPcu.h>
20 #include <PlatformBaseAddresses.h>
21 #include <PchRegs/PchRegsLpss.h>
22 #include <Library/I2CLib.h>
23 #include <Protocol/GlobalNvsArea.h>
24 #include <Library/UefiBootServicesTableLib.h>
27 #define GLOBAL_NVS_OFFSET(Field) (UINTN)((CHAR8*)&((EFI_GLOBAL_NVS_AREA*)0)->Field - (CHAR8*)0)
29 #define PCIEX_BASE_ADDRESS 0xE0000000
30 #define PCI_EXPRESS_BASE_ADDRESS ((VOID *) (UINTN) PCIEX_BASE_ADDRESS)
31 #define MmPciAddress( Segment, Bus, Device, Function, Register ) \
32 ((UINTN)PCI_EXPRESS_BASE_ADDRESS + \
33 (UINTN)(Bus << 20) + \
34 (UINTN)(Device << 15) + \
35 (UINTN)(Function << 12) + \
38 #define PCI_D31F0_REG_BASE PCIEX_BASE_ADDRESS + (UINT32) (31 << 15)
40 typedef struct _LPSS_PCI_DEVICE_INFO
{
47 } LPSS_PCI_DEVICE_INFO
;
49 LPSS_PCI_DEVICE_INFO mLpssPciDeviceList
[] = {
50 {0, DEFAULT_PCI_BUS_NUMBER_PCH
, PCI_DEVICE_NUMBER_PCH_LPSS_DMAC1
, PCI_FUNCTION_NUMBER_PCH_LPSS_DMAC
, 0xFE900000, 0xFE908000},
51 {0, DEFAULT_PCI_BUS_NUMBER_PCH
, PCI_DEVICE_NUMBER_PCH_LPSS_I2C
, PCI_FUNCTION_NUMBER_PCH_LPSS_I2C0
, 0xFE910000, 0xFE918000},
52 {0, DEFAULT_PCI_BUS_NUMBER_PCH
, PCI_DEVICE_NUMBER_PCH_LPSS_I2C
, PCI_FUNCTION_NUMBER_PCH_LPSS_I2C1
, 0xFE920000, 0xFE928000},
53 {0, DEFAULT_PCI_BUS_NUMBER_PCH
, PCI_DEVICE_NUMBER_PCH_LPSS_I2C
, PCI_FUNCTION_NUMBER_PCH_LPSS_I2C2
, 0xFE930000, 0xFE938000},
54 {0, DEFAULT_PCI_BUS_NUMBER_PCH
, PCI_DEVICE_NUMBER_PCH_LPSS_I2C
, PCI_FUNCTION_NUMBER_PCH_LPSS_I2C3
, 0xFE940000, 0xFE948000},
55 {0, DEFAULT_PCI_BUS_NUMBER_PCH
, PCI_DEVICE_NUMBER_PCH_LPSS_I2C
, PCI_FUNCTION_NUMBER_PCH_LPSS_I2C4
, 0xFE950000, 0xFE958000},
56 {0, DEFAULT_PCI_BUS_NUMBER_PCH
, PCI_DEVICE_NUMBER_PCH_LPSS_I2C
, PCI_FUNCTION_NUMBER_PCH_LPSS_I2C5
, 0xFE960000, 0xFE968000},
57 {0, DEFAULT_PCI_BUS_NUMBER_PCH
, PCI_DEVICE_NUMBER_PCH_LPSS_I2C
, PCI_FUNCTION_NUMBER_PCH_LPSS_I2C6
, 0xFE970000, 0xFE978000}
60 #define LPSS_PCI_DEVICE_NUMBER sizeof(mLpssPciDeviceList)/sizeof(LPSS_PCI_DEVICE_INFO)
62 STATIC UINTN mI2CBaseAddress
= 0;
63 STATIC UINT16 mI2CSlaveAddress
= 0;
65 UINT16 mI2cMode
=B_IC_RESTART_EN
| B_IC_SLAVE_DISABLE
| B_MASTER_MODE
;
67 UINTN mI2cNvsBaseAddress
[] = {
68 GLOBAL_NVS_OFFSET(LDMA2Addr
),
69 GLOBAL_NVS_OFFSET(I2C1Addr
),
70 GLOBAL_NVS_OFFSET(I2C2Addr
),
71 GLOBAL_NVS_OFFSET(I2C3Addr
),
72 GLOBAL_NVS_OFFSET(I2C4Addr
),
73 GLOBAL_NVS_OFFSET(I2C5Addr
),
74 GLOBAL_NVS_OFFSET(I2C6Addr
),
75 GLOBAL_NVS_OFFSET(I2C7Addr
)
79 This function get I2Cx controller base address (BAR0).
81 @param I2cControllerIndex Bus Number of I2C controller.
87 IN UINT8 I2cControllerIndex
91 EFI_GLOBAL_NVS_AREA_PROTOCOL
*GlobalNvsArea
;
97 Status
= gBS
->LocateProtocol (
98 &gEfiGlobalNvsAreaProtocolGuid
,
104 // PCI mode from PEI ( Global NVS is not ready).
106 if (EFI_ERROR(Status
)) {
107 DEBUG ((EFI_D_INFO
, "GetI2cBarAddr() gEfiGlobalNvsAreaProtocolGuid:%r\n", Status
));
109 // Global NVS is not ready.
114 AcpiBaseAddr
= *(UINTN
*)((CHAR8
*)GlobalNvsArea
->Area
+ mI2cNvsBaseAddress
[I2cControllerIndex
+ 1]);
117 //PCI mode from DXE (global NVS protocal) to LPSS OnReadytoBoot(swith to ACPI).
119 if(AcpiBaseAddr
==0) {
120 PciMmBase
= MmPciAddress (
121 mLpssPciDeviceList
[I2cControllerIndex
+ 1].Segment
,
122 mLpssPciDeviceList
[I2cControllerIndex
+ 1].BusNum
,
123 mLpssPciDeviceList
[I2cControllerIndex
+ 1].DeviceNum
,
124 mLpssPciDeviceList
[I2cControllerIndex
+ 1].FunctionNum
,
127 DEBUG((EFI_D_ERROR
, "\nGetI2cBarAddr() I2C Device %x %x %x PciMmBase:%x\n", \
128 mLpssPciDeviceList
[I2cControllerIndex
+ 1].BusNum
, \
129 mLpssPciDeviceList
[I2cControllerIndex
+ 1].DeviceNum
, \
130 mLpssPciDeviceList
[I2cControllerIndex
+ 1].FunctionNum
, PciMmBase
));
132 if (MmioRead32 (PciMmBase
) != 0xFFFFFFFF) {
133 if((MmioRead32 (PciMmBase
+R_PCH_LPSS_I2C_STSCMD
)& B_PCH_LPSS_I2C_STSCMD_MSE
)) {
135 // Get the address allocted.
137 mLpssPciDeviceList
[I2cControllerIndex
+ 1].Bar0
=MmioRead32 (PciMmBase
+R_PCH_LPSS_I2C_BAR
);
138 mLpssPciDeviceList
[I2cControllerIndex
+ 1].Bar1
=MmioRead32 (PciMmBase
+R_PCH_LPSS_I2C_BAR1
);
141 AcpiBaseAddr
=mLpssPciDeviceList
[I2cControllerIndex
+1].Bar0
;
145 // ACPI mode from BDS: LPSS OnReadytoBoot
148 DEBUG ((EFI_D_INFO
, "GetI2cBarAddr() NVS Varialable is updated by this LIB or LPSS \n"));
151 DEBUG ((EFI_D_INFO
, "GetI2cBarAddr() I2cControllerIndex+1 0x%x AcpiBaseAddr:0x%x \n", (I2cControllerIndex
+ 1), AcpiBaseAddr
));
157 This function enables I2C controllers.
159 @param I2cControllerIndex Bus Number of I2C controllers.
161 @return Result of the I2C initialization.
165 IN UINT8 I2cControllerIndex
171 EFI_GLOBAL_NVS_AREA_PROTOCOL
*GlobalNvsArea
;
173 UINT32 PmcFunctionDsiable
[]= {
174 B_PCH_PMC_FUNC_DIS_LPSS2_FUNC1
,
175 B_PCH_PMC_FUNC_DIS_LPSS2_FUNC2
,
176 B_PCH_PMC_FUNC_DIS_LPSS2_FUNC3
,
177 B_PCH_PMC_FUNC_DIS_LPSS2_FUNC4
,
178 B_PCH_PMC_FUNC_DIS_LPSS2_FUNC5
,
179 B_PCH_PMC_FUNC_DIS_LPSS2_FUNC6
,
180 B_PCH_PMC_FUNC_DIS_LPSS2_FUNC7
183 DEBUG ((EFI_D_INFO
, "ProgramPciLpssI2C() Start\n"));
186 // Set the VLV Function Disable Register to ZERO
188 PmcBase
= MmioRead32 (PCI_D31F0_REG_BASE
+ R_PCH_LPC_PMC_BASE
) & B_PCH_LPC_PMC_BASE_BAR
;
189 if(MmioRead32(PmcBase
+R_PCH_PMC_FUNC_DIS
)&PmcFunctionDsiable
[I2cControllerIndex
]) {
190 DEBUG ((EFI_D_INFO
, "ProgramPciLpssI2C() End:I2C[%x] is disabled\n",I2cControllerIndex
));
191 return EFI_NOT_READY
;
194 DEBUG ((EFI_D_INFO
, "ProgramPciLpssI2C()------------I2cControllerIndex=%x,PMC=%x\n",I2cControllerIndex
,MmioRead32(PmcBase
+R_PCH_PMC_FUNC_DIS
)));
197 PciMmBase
= MmPciAddress (
198 mLpssPciDeviceList
[I2cControllerIndex
+1].Segment
,
199 mLpssPciDeviceList
[I2cControllerIndex
+1].BusNum
,
200 mLpssPciDeviceList
[I2cControllerIndex
+1].DeviceNum
,
201 mLpssPciDeviceList
[I2cControllerIndex
+1].FunctionNum
,
205 DEBUG((EFI_D_ERROR
, "Program Pci Lpss I2C Device %x %x %x PciMmBase:%x\n", \
206 mLpssPciDeviceList
[I2cControllerIndex
+1].BusNum
, \
207 mLpssPciDeviceList
[I2cControllerIndex
+1].DeviceNum
, \
208 mLpssPciDeviceList
[I2cControllerIndex
+1].FunctionNum
, PciMmBase
));
210 if (MmioRead32 (PciMmBase
) != 0xFFFFFFFF) {
211 if((MmioRead32 (PciMmBase
+R_PCH_LPSS_I2C_STSCMD
)& B_PCH_LPSS_I2C_STSCMD_MSE
)) {
213 // Get the address allocted.
215 mLpssPciDeviceList
[I2cControllerIndex
+1].Bar0
=MmioRead32 (PciMmBase
+R_PCH_LPSS_I2C_BAR
);
216 mLpssPciDeviceList
[I2cControllerIndex
+1].Bar1
=MmioRead32 (PciMmBase
+R_PCH_LPSS_I2C_BAR1
);
217 DEBUG((EFI_D_ERROR
, "ProgramPciLpssI2C() bar0:0x%x bar1:0x%x\n",mLpssPciDeviceList
[I2cControllerIndex
+1].Bar0
, mLpssPciDeviceList
[I2cControllerIndex
+1].Bar1
));
223 ASSERT (((mLpssPciDeviceList
[I2cControllerIndex
+1].Bar0
& B_PCH_LPSS_I2C_BAR_BA
) == mLpssPciDeviceList
[I2cControllerIndex
+1].Bar0
) && (mLpssPciDeviceList
[I2cControllerIndex
+1].Bar0
!= 0));
224 MmioWrite32 ((UINTN
) (PciMmBase
+ R_PCH_LPSS_I2C_BAR
), (UINT32
) (mLpssPciDeviceList
[I2cControllerIndex
+1].Bar0
& B_PCH_LPSS_I2C_BAR_BA
));
229 ASSERT (((mLpssPciDeviceList
[I2cControllerIndex
+1].Bar1
& B_PCH_LPSS_I2C_BAR1_BA
) == mLpssPciDeviceList
[I2cControllerIndex
+1].Bar1
) && (mLpssPciDeviceList
[I2cControllerIndex
+1].Bar1
!= 0));
230 MmioWrite32 ((UINTN
) (PciMmBase
+ R_PCH_LPSS_I2C_BAR1
), (UINT32
) (mLpssPciDeviceList
[I2cControllerIndex
+1].Bar1
& B_PCH_LPSS_I2C_BAR1_BA
));
233 // Bus Master Enable & Memory Space Enable
235 MmioOr32 ((UINTN
) (PciMmBase
+ R_PCH_LPSS_I2C_STSCMD
), (UINT32
) (B_PCH_LPSS_I2C_STSCMD_BME
| B_PCH_LPSS_I2C_STSCMD_MSE
));
236 ASSERT (MmioRead32 (mLpssPciDeviceList
[I2cControllerIndex
+1].Bar0
) != 0xFFFFFFFF);
242 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
));
247 MmioWrite32 (mLpssPciDeviceList
[I2cControllerIndex
+1].Bar0
+ R_PCH_LPSS_I2C_MEM_PCP
,0x80020003);//No use for A0
249 DEBUG ((EFI_D_INFO
, "ProgramPciLpssI2C() Programmed()\n"));
253 // BDS: already switched to ACPI mode
257 Status
= gBS
->LocateProtocol (
258 &gEfiGlobalNvsAreaProtocolGuid
,
262 if (EFI_ERROR(Status
)) {
263 DEBUG ((EFI_D_INFO
, "GetI2cBarAddr() gEfiGlobalNvsAreaProtocolGuid:%r\n", Status
));
265 // gEfiGlobalNvsAreaProtocolGuid is not ready.
269 mLpssPciDeviceList
[I2cControllerIndex
+ 1].Bar0
= *(UINTN
*)((CHAR8
*)GlobalNvsArea
->Area
+ mI2cNvsBaseAddress
[I2cControllerIndex
+ 1]);
270 DEBUG ((EFI_D_INFO
, "ProgramPciLpssI2C(): is switched to ACPI 0x:%x \n",mLpssPciDeviceList
[I2cControllerIndex
+ 1].Bar0
));
274 DEBUG ((EFI_D_INFO
, "ProgramPciLpssI2C() End\n"));
284 @return Result of the I2C disabling.
294 UINT32 NumTries
= 10000;
296 MmioWrite32 ( mI2CBaseAddress
+ R_IC_ENABLE
, 0 );
297 while ( 0 != ( MmioRead32 ( mI2CBaseAddress
+ R_IC_ENABLE_STATUS
) & 1)) {
298 MicroSecondDelay (10);
301 return RETURN_NOT_READY
;
305 return RETURN_SUCCESS
;
313 @return Result of the I2C disabling.
323 UINT32 NumTries
= 10000;
325 MmioWrite32 (mI2CBaseAddress
+ R_IC_ENABLE
, 1);
327 while (0 == (MmioRead32 (mI2CBaseAddress
+ R_IC_ENABLE_STATUS
) & 1)) {
328 MicroSecondDelay (10);
331 return RETURN_NOT_READY
;
335 return RETURN_SUCCESS
;
343 @return Result of the I2C enabling.
347 IN UINTN BusClockHertz
350 DEBUG((EFI_D_INFO
,"InputFreq BusClockHertz: %d\r\n",BusClockHertz
));
353 // Set the 100 KHz clock divider according to SV result and I2C spec
355 MmioWrite32 ( mI2CBaseAddress
+ R_IC_SS_SCL_HCNT
, (UINT16
)0x214 );
356 MmioWrite32 ( mI2CBaseAddress
+ R_IC_SS_SCL_LCNT
, (UINT16
)0x272 );
359 // Set the 400 KHz clock divider according to SV result and I2C spec
361 MmioWrite32 ( mI2CBaseAddress
+ R_IC_FS_SCL_HCNT
, (UINT16
)0x50 );
362 MmioWrite32 ( mI2CBaseAddress
+ R_IC_FS_SCL_LCNT
, (UINT16
)0xAD );
364 switch ( BusClockHertz
) {
366 MmioWrite32 ( mI2CBaseAddress
+ R_IC_SDA_HOLD
, (UINT16
)0x40);//100K
367 mI2cMode
= V_SPEED_STANDARD
;
370 MmioWrite32 ( mI2CBaseAddress
+ R_IC_SDA_HOLD
, (UINT16
)0x32);//400K
371 mI2cMode
= V_SPEED_FAST
;
374 MmioWrite32 ( mI2CBaseAddress
+ R_IC_SDA_HOLD
, (UINT16
)0x09);//3.4M
375 mI2cMode
= V_SPEED_HIGH
;
379 // Select the frequency counter,
380 // Enable restart condition,
381 // Enable master FSM, disable slave FSM.
383 mI2cMode
|= B_IC_RESTART_EN
| B_IC_SLAVE_DISABLE
| B_MASTER_MODE
;
389 Initializes the host controller to execute I2C commands.
391 @param I2cControllerIndex Index of I2C controller in LPSS device. 0 represents I2C0, which is PCI function 1 of LPSS device.
393 @return EFI_SUCCESS Opcode initialization on the I2C host controller completed.
394 @return EFI_DEVICE_ERROR Device error, operation failed.
398 IN UINT8 I2cControllerIndex
,
399 IN UINT16 SlaveAddress
402 EFI_STATUS Status
=RETURN_SUCCESS
;
404 UINTN GnvsI2cBarAddr
=0;
407 // Verify the parameters
409 if ((1023 < SlaveAddress
) || (6 < I2cControllerIndex
)) {
410 Status
= RETURN_INVALID_PARAMETER
;
411 DEBUG((EFI_D_INFO
,"I2CInit Exit with RETURN_INVALID_PARAMETER\r\n"));
414 MmioWrite32 ( mI2CBaseAddress
+ R_IC_TAR
, (UINT16
)SlaveAddress
);
415 mI2CSlaveAddress
= SlaveAddress
;
418 // 1.PEI: program and init ( before pci enumeration).
419 // 2.DXE:update address and re-init ( after pci enumeration).
420 // 3.BDS:update ACPI address and re-init ( after acpi mode is enabled).
422 if(mI2CBaseAddress
== mLpssPciDeviceList
[I2cControllerIndex
+ 1].Bar0
) {
425 // I2CInit is already called.
427 GnvsI2cBarAddr
=GetI2cBarAddr(I2cControllerIndex
);
429 if((GnvsI2cBarAddr
== 0)||(GnvsI2cBarAddr
== mI2CBaseAddress
)) {
430 DEBUG((EFI_D_INFO
,"I2CInit Exit with mI2CBaseAddress:%x == [%x].Bar0\r\n",mI2CBaseAddress
,I2cControllerIndex
+1));
431 return RETURN_SUCCESS
;
435 Status
=ProgramPciLpssI2C(I2cControllerIndex
);
436 if(Status
!=EFI_SUCCESS
) {
441 mI2CBaseAddress
= (UINT32
) mLpssPciDeviceList
[I2cControllerIndex
+ 1].Bar0
;
442 DEBUG ((EFI_D_ERROR
, "mI2CBaseAddress = 0x%x \n",mI2CBaseAddress
));
448 while ((1 == ( MmioRead32 ( mI2CBaseAddress
+ R_IC_STATUS
) & STAT_MST_ACTIVITY
))) {
449 MicroSecondDelay(10);
452 DEBUG((EFI_D_INFO
, "Try timeout\r\n"));
453 return RETURN_DEVICE_ERROR
;
457 Status
= I2cDisable();
458 DEBUG((EFI_D_INFO
, "I2cDisable Status = %r\r\n", Status
));
459 I2cBusFrequencySet(400 * 1000);
461 MmioWrite32(mI2CBaseAddress
+ R_IC_INTR_MASK
, 0x0);
462 if (0x7f < SlaveAddress
)
463 SlaveAddress
= ( SlaveAddress
& 0x3ff ) | IC_TAR_10BITADDR_MASTER
;
464 MmioWrite32 ( mI2CBaseAddress
+ R_IC_TAR
, (UINT16
)SlaveAddress
);
465 MmioWrite32 ( mI2CBaseAddress
+ R_IC_RX_TL
, 0);
466 MmioWrite32 ( mI2CBaseAddress
+ R_IC_TX_TL
, 0 );
467 MmioWrite32 ( mI2CBaseAddress
+ R_IC_CON
, mI2cMode
);
468 Status
= I2cEnable();
470 DEBUG((EFI_D_INFO
, "I2cEnable Status = %r\r\n", Status
));
471 MmioRead32 ( mI2CBaseAddress
+ R_IC_CLR_TX_ABRT
);
477 Reads a Byte from I2C Device.
479 @param I2cControllerIndex I2C Bus no to which the I2C device has been connected
480 @param SlaveAddress Device Address from which the byte value has to be read
481 @param Offset Offset from which the data has to be read
482 @param *Byte Address to which the value read has to be stored
483 @param Start Whether a RESTART is issued before the byte is sent or received
484 @param End Whether STOP is generated after a data byte is sent or received
486 @return EFI_SUCCESS IF the byte value has been successfully read
487 @return EFI_DEVICE_ERROR Operation Failed, Device Error
491 IN UINT8 I2cControllerIndex
,
492 IN UINT8 SlaveAddress
,
494 OUT UINT8
*ReadBuffer
,
503 UINT8
*ReceiveDataEnd
;
504 UINT8
*ReceiveRequest
;
508 Status
= EFI_SUCCESS
;
510 ReceiveDataEnd
= &ReadBuffer
[ReadBytes
];
513 ReceiveRequest
= ReadBuffer
;
514 DEBUG((EFI_D_INFO
,"Read: ---------------%d bytes to RX\r\n",ReceiveDataEnd
- ReceiveRequest
));
516 while ((ReceiveDataEnd
> ReceiveRequest
) || (ReceiveDataEnd
> ReadBuffer
)) {
521 RawIntrStat
= (UINT16
)MmioRead32 (mI2CBaseAddress
+ R_IC_RawIntrStat
);
522 if ( 0 != ( RawIntrStat
& I2C_INTR_TX_ABRT
)) {
523 MmioRead32 ( mI2CBaseAddress
+ R_IC_CLR_TX_ABRT
);
524 Status
= RETURN_DEVICE_ERROR
;
525 DEBUG((EFI_D_INFO
,"TX ABRT ,%d bytes hasn't been transferred\r\n",ReceiveDataEnd
- ReceiveRequest
));
530 // Determine if another byte was received
532 I2cStatus
= (UINT16
)MmioRead32 (mI2CBaseAddress
+ R_IC_STATUS
);
533 if (0 != ( I2cStatus
& STAT_RFNE
)) {
534 ReceiveData
= (UINT16
)MmioRead32 ( mI2CBaseAddress
+ R_IC_DATA_CMD
);
535 *ReadBuffer
++ = (UINT8
)ReceiveData
;
536 DEBUG((EFI_D_INFO
,"MmioRead32 ,1 byte 0x:%x is received\r\n",ReceiveData
));
539 if(ReceiveDataEnd
== ReceiveRequest
) {
540 MicroSecondDelay ( FIFO_WRITE_DELAY
);
541 DEBUG((EFI_D_INFO
,"ReceiveDataEnd==ReceiveRequest------------%x\r\n",I2cStatus
& STAT_RFNE
));
545 // To avoid sys hung without ul-pmc device on RVP,
546 // waiting the last request to get data and make (ReceiveDataEnd > ReadBuffer) =TRUE.
555 // Wait until a read request will fit.
557 if (0 == (I2cStatus
& STAT_TFNF
)) {
558 DEBUG((EFI_D_INFO
,"Wait until a read request will fit\r\n"));
559 MicroSecondDelay (10);
564 // Issue the next read request.
567 MmioWrite32 ( mI2CBaseAddress
+ R_IC_DATA_CMD
, B_READ_CMD
|B_CMD_RESTART
|B_CMD_STOP
);
568 } else if (!End
&& Start
) {
569 MmioWrite32 ( mI2CBaseAddress
+ R_IC_DATA_CMD
, B_READ_CMD
|B_CMD_RESTART
);
570 } else if (End
&& !Start
) {
571 MmioWrite32 ( mI2CBaseAddress
+ R_IC_DATA_CMD
, B_READ_CMD
|B_CMD_STOP
);
572 } else if (!End
&& !Start
) {
573 MmioWrite32 ( mI2CBaseAddress
+ R_IC_DATA_CMD
, B_READ_CMD
);
575 MicroSecondDelay (FIFO_WRITE_DELAY
);
585 Writes a Byte to I2C Device.
587 @param I2cControllerIndex I2C Bus no to which the I2C device has been connected
588 @param SlaveAddress Device Address from which the byte value has to be written
589 @param Offset Offset from which the data has to be read
590 @param *Byte Address to which the value written is stored
591 @param Start Whether a RESTART is issued before the byte is sent or received
592 @param End Whether STOP is generated after a data byte is sent or received
594 @return EFI_SUCCESS IF the byte value has been successfully written
595 @return EFI_DEVICE_ERROR Operation Failed, Device Error
597 EFI_STATUS
ByteWriteI2CBasic(
598 IN UINT8 I2cControllerIndex
,
599 IN UINT8 SlaveAddress
,
601 IN UINT8
*WriteBuffer
,
613 Status
= EFI_SUCCESS
;
615 Status
=I2CInit(I2cControllerIndex
, SlaveAddress
);
616 if(Status
!=EFI_SUCCESS
)
619 TransmitEnd
= &WriteBuffer
[WriteBytes
];
621 DEBUG((EFI_D_INFO
,"Write: --------------%d bytes to TX\r\n",TransmitEnd
- WriteBuffer
));
622 while (TransmitEnd
> WriteBuffer
) {
623 I2cStatus
= MmioRead32 (mI2CBaseAddress
+ R_IC_STATUS
);
624 RawIntrStat
= (UINT16
)MmioRead32 (mI2CBaseAddress
+ R_IC_RawIntrStat
);
625 if (0 != ( RawIntrStat
& I2C_INTR_TX_ABRT
)) {
626 MmioRead32 ( mI2CBaseAddress
+ R_IC_CLR_TX_ABRT
);
627 Status
= RETURN_DEVICE_ERROR
;
628 DEBUG((EFI_D_ERROR
,"TX ABRT TransmitEnd:0x%x WriteBuffer:0x%x\r\n", TransmitEnd
, WriteBuffer
));
631 if (0 == (I2cStatus
& STAT_TFNF
)) {
633 // If TX not full , will send cmd or continue to wait
635 MicroSecondDelay (FIFO_WRITE_DELAY
);
640 MmioWrite32 (mI2CBaseAddress
+ R_IC_DATA_CMD
, (*WriteBuffer
++)|B_CMD_RESTART
|B_CMD_STOP
);
641 } else if (!End
&& Start
) {
642 MmioWrite32 (mI2CBaseAddress
+ R_IC_DATA_CMD
, (*WriteBuffer
++)|B_CMD_RESTART
);
643 } else if (End
&& !Start
) {
644 MmioWrite32 (mI2CBaseAddress
+ R_IC_DATA_CMD
, (*WriteBuffer
++)|B_CMD_STOP
);
645 } else if (!End
&& !Start
) {
646 MmioWrite32 (mI2CBaseAddress
+ R_IC_DATA_CMD
, (*WriteBuffer
++));
650 // Add a small delay to work around some odd behavior being seen. Without this delay bytes get dropped.
652 MicroSecondDelay ( FIFO_WRITE_DELAY
);//wait after send cmd
658 RawIntrStat
= MmioRead16 ( mI2CBaseAddress
+ R_IC_RawIntrStat
);
659 if (0 != ( RawIntrStat
& I2C_INTR_TX_ABRT
)) {
660 MmioRead16 (mI2CBaseAddress
+ R_IC_CLR_TX_ABRT
);
661 Status
= RETURN_DEVICE_ERROR
;
662 DEBUG((EFI_D_ERROR
,"TX ABRT TransmitEnd:0x%x WriteBuffer:0x%x\r\n", TransmitEnd
, WriteBuffer
));
664 if(0 == MmioRead16(mI2CBaseAddress
+ R_IC_TXFLR
)) break;
666 MicroSecondDelay (FIFO_WRITE_DELAY
);
670 // to avoid sys hung without ul-pmc device on RVP.
671 // Waiting the last request to get data and make (ReceiveDataEnd > ReadBuffer) =TRUE.
686 Reads a Byte from I2C Device.
688 @param I2cControllerIndex I2C Bus no to which the I2C device has been connected
689 @param SlaveAddress Device Address from which the byte value has to be read
690 @param Offset Offset from which the data has to be read
691 @param ReadBytes Number of bytes to be read
692 @param *ReadBuffer Address to which the value read has to be stored
694 @return EFI_SUCCESS IF the byte value has been successfully read
695 @return EFI_DEVICE_ERROR Operation Failed, Device Error
697 EFI_STATUS
ByteReadI2C(
698 IN UINT8 I2cControllerIndex
,
699 IN UINT8 SlaveAddress
,
702 OUT UINT8
*ReadBuffer
707 DEBUG ((EFI_D_INFO
, "ByteReadI2C:---offset:0x%x\n",Offset
));
708 Status
= ByteWriteI2CBasic(I2cControllerIndex
, SlaveAddress
,1,&Offset
,TRUE
,FALSE
);
709 Status
= ByteReadI2CBasic(I2cControllerIndex
, SlaveAddress
,ReadBytes
,ReadBuffer
,TRUE
,TRUE
);
715 Writes a Byte to I2C Device.
717 @param I2cControllerIndex I2C Bus no to which the I2C device has been connected
718 @param SlaveAddress Device Address from which the byte value has to be written
719 @param Offset Offset from which the data has to be written
720 @param WriteBytes Number of bytes to be written
721 @param *Byte Address to which the value written is stored
723 @return EFI_SUCCESS IF the byte value has been successfully read
724 @return EFI_DEVICE_ERROR Operation Failed, Device Error
726 EFI_STATUS
ByteWriteI2C(
727 IN UINT8 I2cControllerIndex
,
728 IN UINT8 SlaveAddress
,
731 IN UINT8
*WriteBuffer
736 DEBUG ((EFI_D_INFO
, "ByteWriteI2C:---offset/bytes/buf:0x%x,0x%x,0x%x,0x%x\n",Offset
,WriteBytes
,WriteBuffer
,*WriteBuffer
));
737 Status
= ByteWriteI2CBasic(I2cControllerIndex
, SlaveAddress
,1,&Offset
,TRUE
,FALSE
);
738 Status
= ByteWriteI2CBasic(I2cControllerIndex
, SlaveAddress
,WriteBytes
,WriteBuffer
,FALSE
,TRUE
);