public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
From: "Nhi Pham via groups.io" <nhi=os.amperecomputing.com@groups.io>
To: devel@edk2.groups.io
Cc: quic_llindhol@quicinc.com, chuong@os.amperecomputing.com,
	rebecca@os.amperecomputing.com, nhi@os.amperecomputing.com
Subject: [edk2-devel] [edk2-platforms][PATCH v2 1/5] AmpereAltraPkg/DwI2cLib: Add support for SMBUS+PEC operation
Date: Wed,  7 Aug 2024 13:47:27 +0700	[thread overview]
Message-ID: <20240807064731.4049764-2-nhi@os.amperecomputing.com> (raw)
In-Reply-To: <20240807064731.4049764-1-nhi@os.amperecomputing.com>

This introduces two input parameters to the I2cProbe() and updates the
InternalI2cRead() for the support of the SMBUS operation with optional
PEC check, which will be used by the IPMI SSIF driver.

Signed-off-by: Nhi Pham <nhi@os.amperecomputing.com>
---
 Silicon/Ampere/AmpereAltraPkg/Include/Library/I2cLib.h              |  11 +-
 Platform/Ampere/JadePkg/Library/PCF85063RealTimeClockLib/PCF85063.c |   6 +-
 Silicon/Ampere/AmpereAltraPkg/Library/DwI2cLib/DwI2cLib.c           | 129 ++++++++++++++++++--
 3 files changed, 131 insertions(+), 15 deletions(-)

diff --git a/Silicon/Ampere/AmpereAltraPkg/Include/Library/I2cLib.h b/Silicon/Ampere/AmpereAltraPkg/Include/Library/I2cLib.h
index f13794171029..3a312f7b6aed 100644
--- a/Silicon/Ampere/AmpereAltraPkg/Include/Library/I2cLib.h
+++ b/Silicon/Ampere/AmpereAltraPkg/Include/Library/I2cLib.h
@@ -1,7 +1,7 @@
 /** @file
   Library implementation for the Designware I2C controller.
 
-  Copyright (c) 2020 - 2021, Ampere Computing LLC. All rights reserved.<BR>
+  Copyright (c) 2020 - 2024, Ampere Computing LLC. All rights reserved.<BR>
 
   SPDX-License-Identifier: BSD-2-Clause-Patent
 
@@ -70,6 +70,9 @@ I2cRead (
 
   @param[in] Bus      I2C bus Id.
   @param[in] BusSpeed I2C bus speed in Hz.
+  @param[in] IsSmbus  Flag to indicate if the bus is used to execute an SMBus operation.
+  @param[in] PecCheck If Packet Error Code (PEC) checking is required for the SMBUS operation
+                      and is ignored when present in other operations.
 
   @retval EFI_SUCCESS           Success.
   @retval EFI_INVALID_PARAMETER A parameter is invalid.
@@ -78,8 +81,10 @@ I2cRead (
 EFI_STATUS
 EFIAPI
 I2cProbe (
-  IN UINT32 Bus,
-  IN UINTN  BusSpeed
+  IN UINT32   Bus,
+  IN UINTN    BusSpeed,
+  IN BOOLEAN  IsSmbus,
+  IN BOOLEAN  PecCheck
   );
 
 /**
diff --git a/Platform/Ampere/JadePkg/Library/PCF85063RealTimeClockLib/PCF85063.c b/Platform/Ampere/JadePkg/Library/PCF85063RealTimeClockLib/PCF85063.c
index bc886b530f3c..a9e7328381e6 100644
--- a/Platform/Ampere/JadePkg/Library/PCF85063RealTimeClockLib/PCF85063.c
+++ b/Platform/Ampere/JadePkg/Library/PCF85063RealTimeClockLib/PCF85063.c
@@ -1,6 +1,6 @@
 /** @file
 
-  Copyright (c) 2020 - 2021, Ampere Computing LLC. All rights reserved.<BR>
+  Copyright (c) 2020 - 2024, Ampere Computing LLC. All rights reserved.<BR>
 
   SPDX-License-Identifier: BSD-2-Clause-Patent
 
@@ -104,7 +104,7 @@ RtcI2cRead (
     return EFI_DEVICE_ERROR;
   }
 
-  Status = I2cProbe (I2C_RTC_BUS_ADDRESS, I2C_RTC_BUS_SPEED);
+  Status = I2cProbe (I2C_RTC_BUS_ADDRESS, I2C_RTC_BUS_SPEED, FALSE, FALSE);
   if (EFI_ERROR (Status)) {
     return EFI_DEVICE_ERROR;
   }
@@ -148,7 +148,7 @@ RtcI2cWrite (
     return EFI_INVALID_PARAMETER;
   }
 
-  Status = I2cProbe (I2C_RTC_BUS_ADDRESS, I2C_RTC_BUS_SPEED);
+  Status = I2cProbe (I2C_RTC_BUS_ADDRESS, I2C_RTC_BUS_SPEED, FALSE, FALSE);
   if (EFI_ERROR (Status)) {
     return EFI_DEVICE_ERROR;
   }
diff --git a/Silicon/Ampere/AmpereAltraPkg/Library/DwI2cLib/DwI2cLib.c b/Silicon/Ampere/AmpereAltraPkg/Library/DwI2cLib/DwI2cLib.c
index 669ba2ea98a4..a6631ea17d69 100644
--- a/Silicon/Ampere/AmpereAltraPkg/Library/DwI2cLib/DwI2cLib.c
+++ b/Silicon/Ampere/AmpereAltraPkg/Library/DwI2cLib/DwI2cLib.c
@@ -1,6 +1,6 @@
 /** @file
 
-  Copyright (c) 2020 - 2021, Ampere Computing LLC. All rights reserved.<BR>
+  Copyright (c) 2020 - 2024, Ampere Computing LLC. All rights reserved.<BR>
 
   SPDX-License-Identifier: BSD-2-Clause-Patent
 
@@ -31,12 +31,14 @@
 // Private I2C bus data
 //
 typedef struct {
-  UINTN  Base;
-  UINT32 BusSpeed;
-  UINT32 RxFifo;
-  UINT32 TxFifo;
-  UINT32 PollingTime;
-  UINT32 Enabled;
+  UINTN      Base;
+  UINT32     BusSpeed;
+  UINT32     RxFifo;
+  UINT32     TxFifo;
+  UINT32     PollingTime;
+  UINT32     Enabled;
+  BOOLEAN    IsSmbus;
+  BOOLEAN    PecCheck;
 } DW_I2C_CONTEXT_T;
 
 //
@@ -337,6 +339,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,6 +549,72 @@ InternalI2cWrite (
   return Status;
 }
 
+/**
+  This extracts the data length from the initial byte of the SMBUS transaction. This allows
+  the driver to accurately read the SMBUS response with the exact length, rather than
+  consistently reading 32-byte block of data.
+
+  @param[in]  Bus      I2C bus Id.
+  @param[out] BusSpeed Pointer to the buffer to store the read length.
+
+  @retval EFI_SUCCESS  The operation is successful.
+  @retval Others       An error occurred.
+
+**/
+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)) {
+    //
+    // If the SMBUS target is not ready to handle the request
+    // or is busy with preparing the response data, it will response
+    // NACK, and the error status TX_ABRT is triggered to indicate that
+    // the RX FIFO is not ready for reading. Thus, the following message
+    // serves more as verbose alert rather than an error.
+    //
+    DEBUG ((DEBUG_VERBOSE,
+      "%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,
@@ -559,6 +632,7 @@ InternalI2cRead (
   UINTN      Count;
   UINTN      ReadCount;
   UINTN      WriteCount;
+  UINT32     ResponseLen;
 
   Status = EFI_SUCCESS;
   Base = mI2cBusList[Bus].Base;
@@ -601,6 +675,35 @@ InternalI2cRead (
   }
 
   WriteCount = 0;
+  if (mI2cBusList[Bus].IsSmbus) {
+    //
+    // Read Smbus Data Length, first byte of the Smbus response data.
+    //
+    Status = InternalSmbusReadDataLength (Bus, &ResponseLen);
+    if (EFI_ERROR (Status)) {
+      goto Exit;
+    }
+
+    WriteCount++;
+    Buf[ReadCount++] = ResponseLen;
+
+    //
+    // Abort the transaction when the requested length is shorter than the actual response data
+    // or if there is no response data when PEC disabled.
+    //
+    if ((*Length < (ResponseLen + 2)) || (!mI2cBusList[Bus].PecCheck && ResponseLen == 0)) {
+      MmioWrite32 (Base + DW_IC_DATA_CMD, DW_IC_DATA_CMD_CMD | DW_IC_DATA_CMD_STOP);
+      I2cSync ();
+      Status = EFI_INVALID_PARAMETER;
+      goto Exit;
+    }
+
+    *Length = ResponseLen + 1; // Response Data Length + 8-bit Byte Count field
+    if (mI2cBusList[Bus].PecCheck) {
+      *Length += 1; // ++ 8-bit PEC field
+    }
+  }
+
   while ((*Length - ReadCount) != 0) {
     TxLimit = mI2cBusList[Bus].TxFifo - MmioRead32 (Base + DW_IC_TXFLR);
     RxLimit = mI2cBusList[Bus].RxFifo - MmioRead32 (Base + DW_IC_RXFLR);
@@ -750,6 +853,9 @@ I2cRead (
 
   @param[in] Bus      I2C bus Id.
   @param[in] BusSpeed I2C bus speed in Hz.
+  @param[in] IsSmbus  Flag to indicate if the bus is used to execute an SMBus operation.
+  @param[in] PecCheck If Packet Error Code (PEC) checking is required for the SMBUS operation
+                      and is ignored when present in other operations.
 
   @retval EFI_SUCCESS           Success.
   @retval EFI_INVALID_PARAMETER A parameter is invalid.
@@ -758,8 +864,10 @@ I2cRead (
 EFI_STATUS
 EFIAPI
 I2cProbe (
-  IN UINT32 Bus,
-  IN UINTN  BusSpeed
+  IN UINT32   Bus,
+  IN UINTN    BusSpeed,
+  IN BOOLEAN  IsSmbus,
+  IN BOOLEAN  PecCheck
   )
 {
   if (Bus >= AC01_I2C_MAX_BUS_NUM
@@ -768,6 +876,9 @@ I2cProbe (
     return EFI_INVALID_PARAMETER;
   }
 
+  mI2cBusList[Bus].IsSmbus  = IsSmbus;
+  mI2cBusList[Bus].PecCheck = PecCheck;
+
   return I2cInit (Bus, BusSpeed);
 }
 
-- 
2.25.1



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#120262): https://edk2.groups.io/g/devel/message/120262
Mute This Topic: https://groups.io/mt/107765353/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-



  reply	other threads:[~2024-08-07  6:50 UTC|newest]

Thread overview: 19+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-08-07  6:47 [edk2-devel] [edk2-platforms][PATCH v2 0/5] Add IPMI SSIF support Nhi Pham via groups.io
2024-08-07  6:47 ` Nhi Pham via groups.io [this message]
2024-08-07  6:47 ` [edk2-devel] [edk2-platforms][PATCH v2 2/5] AmpereSiliconPkg: Define PCDs for SMBUS and BMC Nhi Pham via groups.io
2024-08-07  6:47 ` [edk2-devel] [edk2-platforms][PATCH v2 3/5] AmpereAltraPkg: Add SmbusHc PEI and DXE drivers Nhi Pham via groups.io
2024-08-07  6:47 ` [edk2-devel] [edk2-platforms][PATCH v2 4/5] JadePkg: Add PlatformBmcReadyLib to support BMC ready check Nhi Pham via groups.io
2024-08-07  6:47 ` [edk2-devel] [edk2-platforms][PATCH v2 5/5] Ampere/Jade: Enable IPMI SSIF Nhi Pham via groups.io
2024-08-07  7:16 ` [edk2-devel] [edk2-platforms][PATCH v2 0/5] Add IPMI SSIF support Chang, Abner via groups.io
2024-08-07  7:35   ` Nhi Pham via groups.io
2024-08-09  2:44     ` Chang, Abner via groups.io
2024-08-09  3:05       ` Nhi Pham via groups.io
2024-08-09  4:34         ` Chang, Abner via groups.io
2024-08-07 10:23   ` Leif Lindholm
2024-08-07 10:45     ` Chang, Abner via groups.io
2024-08-07 10:56       ` Leif Lindholm
2024-08-07 10:59         ` Chang, Abner via groups.io
2024-08-08  3:06 ` Nhi Pham via groups.io
     [not found] ` <17E9A1ED2D454E7A.19172@groups.io>
2024-08-13  4:16   ` Nhi Pham via groups.io
2024-08-29  5:55 ` Chuong Tran
2024-08-29  7:11   ` Nhi Pham via groups.io

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-list from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20240807064731.4049764-2-nhi@os.amperecomputing.com \
    --to=devel@edk2.groups.io \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox