Signed-off-by: Nhi Pham <n...@os.amperecomputing.com>
---
Silicon/Ampere/AmpereAltraPkg/Include/Library/I2cLib.h | 31 +++++
Silicon/Ampere/AmpereAltraPkg/Library/DwI2cLib/DwI2cLib.c | 137
+++++++++++++++++++-
2 files changed, 163 insertions(+), 5 deletions(-)
diff --git a/Silicon/Ampere/AmpereAltraPkg/Include/Library/I2cLib.h
b/Silicon/Ampere/AmpereAltraPkg/Include/Library/I2cLib.h
index f13794171029..d460f49efccb 100644
--- a/Silicon/Ampere/AmpereAltraPkg/Include/Library/I2cLib.h
+++ b/Silicon/Ampere/AmpereAltraPkg/Include/Library/I2cLib.h
@@ -65,6 +65,37 @@ I2cRead (
IN OUT UINT32 *ReadLength
);
+/**
+ SMBUS block read.
+
+ @param[in] Bus I2C bus Id.
+ @param[in] SlaveAddr The address of slave device on the bus.
+ @param[in] BufCmd Buffer where to send the command.
+ @param[in] CmdLength Length of BufCmd.
+ @param[in,out] Buf Buffer where to put the read data to.
+ @param[in,out] ReadLength Pointer to length of buffer.
+ @param[in] PecCheck If Packet Error Code (PEC) checking is required
for this operation.
+
+ @retval EFI_SUCCESS Read successfully.
+ @retval EFI_INVALID_PARAMETER A parameter is invalid.
+ @retval EFI_UNSUPPORTED The bus is not supported.
+ @retval EFI_NOT_READY The device/bus is not ready.
+ @retval EFI_TIMEOUT Timeout when transferring data.
+ @retval EFI_CRC_ERROR There are errors on receiving data.
+
+**/
+EFI_STATUS
+EFIAPI
+SmbusRead (
+ IN UINT32 Bus,
+ IN UINT32 SlaveAddr,
+ IN UINT8 *BufCmd,
+ IN UINT32 CmdLength,
+ IN OUT UINT8 *Buf,
+ IN OUT UINT32 *ReadLength,
+ IN BOOLEAN PecCheck
+ );
+
/**
Setup new transaction with I2C slave device.
diff --git a/Silicon/Ampere/AmpereAltraPkg/Library/DwI2cLib/DwI2cLib.c b/Silicon/Ampere/AmpereAltraPkg/Library/DwI2cLib/DwI2cLib.c
index 669ba2ea98a4..9e52ae69e7cd 100644
--- a/Silicon/Ampere/AmpereAltraPkg/Library/DwI2cLib/DwI2cLib.c
+++ b/Silicon/Ampere/AmpereAltraPkg/Library/DwI2cLib/DwI2cLib.c
@@ -337,6 +337,11 @@ I2cWaitTxData (
DEBUG ((DEBUG_ERROR, "%a: Timeout waiting for TX buffer available\n",
__FUNCTION__));
return EFI_TIMEOUT;
}
+
+ if ((I2cCheckErrors (Bus) & DW_IC_INTR_TX_ABRT) != 0) {
+ return EFI_ABORTED;
+ }
+
MicroSecondDelay (mI2cBusList[Bus].PollingTime);
}
@@ -542,13 +547,61 @@ InternalI2cWrite (
return Status;
}
+EFI_STATUS
+InternalSmbusReadDataLength (
+ UINT32 Bus,
+ UINT32 *Length
+ )
+{
+ EFI_STATUS Status;
+ UINTN Base;
+ UINT32 CmdSend;
+
+ Base = mI2cBusList[Bus].Base;
+
+ CmdSend = DW_IC_DATA_CMD_CMD;
+ MmioWrite32 (Base + DW_IC_DATA_CMD, CmdSend);
+ I2cSync ();
+
+ if (I2cCheckErrors (Bus) != 0) {
+ DEBUG ((DEBUG_ERROR, "%a: Sending reading command error\n", __func__));
+ return EFI_CRC_ERROR;
+ }
+
+ Status = I2cWaitRxData (Bus);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR,
+ "%a: Reading Smbus data length failed to wait data\n",
+ __func__
+ ));
+
+ if (Status != EFI_ABORTED) {
+ MmioWrite32 (Base + DW_IC_DATA_CMD, DW_IC_DATA_CMD_STOP);
+ I2cSync ();
+ }
+
+ return Status;
+ }
+
+ *Length = MmioRead32 (Base + DW_IC_DATA_CMD) & DW_IC_DATA_CMD_DAT_MASK;
+ I2cSync ();
+
+ if (I2cCheckErrors (Bus) != 0) {
+ DEBUG ((DEBUG_ERROR, "%a: Sending reading command error\n", __func__));
+ return EFI_CRC_ERROR;
+ }
+ return EFI_SUCCESS;
+}
+
EFI_STATUS
InternalI2cRead (
UINT32 Bus,
- UINT8 *BufCmd,
- UINT32 CmdLength,
- UINT8 *Buf,
- UINT32 *Length
+ UINT8 *BufCmd,
+ UINT32 CmdLength,
+ UINT8 *Buf,
+ UINT32 *Length,
+ BOOLEAN IsSmbus,