}
}
+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)
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));
* 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)
{
}
-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)
request->status = I2C_CHANNEL_OPERATION_ENGINE_BUSY;
return;
}
+ reset_hw_engine(dce_i2c_hw);
execute_transaction(dce_i2c_hw);
#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),\
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),\
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;
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;
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;