From: Derek Lai <derek....@amd.com>

1. Add i2c_hw_Status check to make sure when HW i2c is in use.
2. Don't reset HW engine in is_hw_busy() and instead do this in
process_transaction() because SW i2c does not check if hw i2c is in use

Signed-off-by: Derek Lai <derek....@amd.com>
Reviewed-by: Charlene Liu <charlene....@amd.com>
Acked-by: Bhawanpreet Lakha <bhawanpreet.la...@amd.com>
---
 .../gpu/drm/amd/display/dc/dce/dce_i2c_hw.c   | 65 +++++++++++--------
 .../gpu/drm/amd/display/dc/dce/dce_i2c_hw.h   |  5 ++
 2 files changed, 43 insertions(+), 27 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_i2c_hw.c 
b/drivers/gpu/drm/amd/display/dc/dce/dce_i2c_hw.c
index 526aab438374..7f2460caa2a6 100644
--- a/drivers/gpu/drm/amd/display/dc/dce/dce_i2c_hw.c
+++ b/drivers/gpu/drm/amd/display/dc/dce/dce_i2c_hw.c
@@ -149,6 +149,36 @@ static void process_channel_reply(
        }
 }
 
+static bool is_engine_available(struct dce_i2c_hw *dce_i2c_hw)
+{
+       unsigned int arbitrate;
+       unsigned int i2c_hw_status;
+
+       REG_GET(HW_STATUS, DC_I2C_DDC1_HW_STATUS, &i2c_hw_status);
+       if (i2c_hw_status == DC_I2C_STATUS__DC_I2C_STATUS_USED_BY_HW)
+               return false;
+
+       REG_GET(DC_I2C_ARBITRATION, DC_I2C_REG_RW_CNTL_STATUS, &arbitrate);
+       if (arbitrate == DC_I2C_REG_RW_CNTL_STATUS_DMCU_ONLY)
+               return false;
+
+       return true;
+}
+
+static bool is_hw_busy(struct dce_i2c_hw *dce_i2c_hw)
+{
+       uint32_t i2c_sw_status = 0;
+
+       REG_GET(DC_I2C_SW_STATUS, DC_I2C_SW_STATUS, &i2c_sw_status);
+       if (i2c_sw_status == DC_I2C_STATUS__DC_I2C_STATUS_IDLE)
+               return false;
+
+       if (is_engine_available(dce_i2c_hw))
+               return false;
+
+       return true;
+}
+
 static bool process_transaction(
        struct dce_i2c_hw *dce_i2c_hw,
        struct i2c_request_transaction_data *request)
@@ -159,6 +189,11 @@ static bool process_transaction(
        bool last_transaction = false;
        uint32_t value = 0;
 
+       if (is_hw_busy(dce_i2c_hw)) {
+               request->status = I2C_CHANNEL_OPERATION_ENGINE_BUSY;
+               return false;
+       }
+
        last_transaction = ((dce_i2c_hw->transaction_count == 3) ||
                        (request->action == 
DCE_I2C_TRANSACTION_ACTION_I2C_WRITE) ||
                        (request->action & 
DCE_I2C_TRANSACTION_ACTION_I2C_READ));
@@ -294,27 +329,12 @@ static bool setup_engine(
         * Enable restart of SW I2C that was interrupted by HW
         * disable queuing of software while I2C is in use by HW
         */
-       REG_UPDATE_2(DC_I2C_ARBITRATION,
-                    DC_I2C_NO_QUEUED_SW_GO, 0,
-                    DC_I2C_SW_PRIORITY, 
DC_I2C_ARBITRATION__DC_I2C_SW_PRIORITY_NORMAL);
+       REG_UPDATE(DC_I2C_ARBITRATION,
+                       DC_I2C_NO_QUEUED_SW_GO, 0);
 
        return true;
 }
 
-static bool is_hw_busy(struct dce_i2c_hw *dce_i2c_hw)
-{
-       uint32_t i2c_sw_status = 0;
-
-       REG_GET(DC_I2C_SW_STATUS, DC_I2C_SW_STATUS, &i2c_sw_status);
-       if (i2c_sw_status == DC_I2C_STATUS__DC_I2C_STATUS_IDLE)
-               return false;
-
-       reset_hw_engine(dce_i2c_hw);
-
-       REG_GET(DC_I2C_SW_STATUS, DC_I2C_SW_STATUS, &i2c_sw_status);
-       return i2c_sw_status != DC_I2C_STATUS__DC_I2C_STATUS_IDLE;
-}
-
 static void release_engine(
        struct dce_i2c_hw *dce_i2c_hw)
 {
@@ -349,16 +369,6 @@ static void release_engine(
 
 }
 
-static bool is_engine_available(struct dce_i2c_hw *dce_i2c_hw)
-{
-       unsigned int arbitrate;
-
-       REG_GET(DC_I2C_ARBITRATION, DC_I2C_REG_RW_CNTL_STATUS, &arbitrate);
-       if (arbitrate == DC_I2C_REG_RW_CNTL_STATUS_DMCU_ONLY)
-               return false;
-       return true;
-}
-
 struct dce_i2c_hw *acquire_i2c_hw_engine(
        struct resource_pool *pool,
        struct ddc *ddc)
@@ -456,6 +466,7 @@ static void submit_channel_request_hw(
                request->status = I2C_CHANNEL_OPERATION_ENGINE_BUSY;
                return;
        }
+       reset_hw_engine(dce_i2c_hw);
 
        execute_transaction(dce_i2c_hw);
 
diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_i2c_hw.h 
b/drivers/gpu/drm/amd/display/dc/dce/dce_i2c_hw.h
index f718e3d396f2..a633632f625b 100644
--- a/drivers/gpu/drm/amd/display/dc/dce/dce_i2c_hw.h
+++ b/drivers/gpu/drm/amd/display/dc/dce/dce_i2c_hw.h
@@ -84,6 +84,7 @@ enum {
 #define I2C_HW_ENGINE_COMMON_REG_LIST(id)\
        SRI(SETUP, DC_I2C_DDC, id),\
        SRI(SPEED, DC_I2C_DDC, id),\
+       SRI(HW_STATUS, DC_I2C_DDC, id),\
        SR(DC_I2C_ARBITRATION),\
        SR(DC_I2C_CONTROL),\
        SR(DC_I2C_SW_STATUS),\
@@ -105,6 +106,7 @@ enum {
        I2C_SF(DC_I2C_DDC1_SETUP, DC_I2C_DDC1_DATA_DRIVE_SEL, mask_sh),\
        I2C_SF(DC_I2C_DDC1_SETUP, DC_I2C_DDC1_INTRA_TRANSACTION_DELAY, 
mask_sh),\
        I2C_SF(DC_I2C_DDC1_SETUP, DC_I2C_DDC1_INTRA_BYTE_DELAY, mask_sh),\
+       I2C_SF(DC_I2C_DDC1_HW_STATUS, DC_I2C_DDC1_HW_STATUS, mask_sh),\
        I2C_SF(DC_I2C_ARBITRATION, DC_I2C_SW_USE_I2C_REG_REQ, mask_sh),\
        I2C_SF(DC_I2C_ARBITRATION, DC_I2C_SW_DONE_USING_I2C_REG, mask_sh),\
        I2C_SF(DC_I2C_ARBITRATION, DC_I2C_NO_QUEUED_SW_GO, mask_sh),\
@@ -146,6 +148,7 @@ struct dce_i2c_shift {
        uint8_t DC_I2C_DDC1_DATA_DRIVE_SEL;
        uint8_t DC_I2C_DDC1_INTRA_TRANSACTION_DELAY;
        uint8_t DC_I2C_DDC1_INTRA_BYTE_DELAY;
+       uint8_t DC_I2C_DDC1_HW_STATUS;
        uint8_t DC_I2C_SW_DONE_USING_I2C_REG;
        uint8_t DC_I2C_SW_USE_I2C_REG_REQ;
        uint8_t DC_I2C_NO_QUEUED_SW_GO;
@@ -185,6 +188,7 @@ struct dce_i2c_mask {
        uint32_t DC_I2C_DDC1_DATA_DRIVE_SEL;
        uint32_t DC_I2C_DDC1_INTRA_TRANSACTION_DELAY;
        uint32_t DC_I2C_DDC1_INTRA_BYTE_DELAY;
+       uint32_t DC_I2C_DDC1_HW_STATUS;
        uint32_t DC_I2C_SW_DONE_USING_I2C_REG;
        uint32_t DC_I2C_SW_USE_I2C_REG_REQ;
        uint32_t DC_I2C_NO_QUEUED_SW_GO;
@@ -219,6 +223,7 @@ struct dce_i2c_mask {
 struct dce_i2c_registers {
        uint32_t SETUP;
        uint32_t SPEED;
+       uint32_t HW_STATUS;
        uint32_t DC_I2C_ARBITRATION;
        uint32_t DC_I2C_CONTROL;
        uint32_t DC_I2C_SW_STATUS;
-- 
2.17.1

_______________________________________________
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

Reply via email to