diff options
Diffstat (limited to 'drivers/i2c/busses/i2c-designware-master.c')
-rw-r--r-- | drivers/i2c/busses/i2c-designware-master.c | 33 |
1 files changed, 27 insertions, 6 deletions
diff --git a/drivers/i2c/busses/i2c-designware-master.c b/drivers/i2c/busses/i2c-designware-master.c index 45f569155bfe..55ea91a63382 100644 --- a/drivers/i2c/busses/i2c-designware-master.c +++ b/drivers/i2c/busses/i2c-designware-master.c @@ -39,7 +39,7 @@ static void i2c_dw_configure_fifo_master(struct dw_i2c_dev *dev) static int i2c_dw_set_timings_master(struct dw_i2c_dev *dev) { - u32 comp_param1; + unsigned int comp_param1; u32 sda_falling_time, scl_falling_time; struct i2c_timings *t = &dev->timings; const char *fp_str = ""; @@ -211,7 +211,7 @@ static void i2c_dw_xfer_init(struct dw_i2c_dev *dev) { struct i2c_msg *msgs = dev->msgs; u32 ic_con = 0, ic_tar = 0; - u32 dummy; + unsigned int dummy; /* Disable the adapter */ __i2c_dw_disable(dev); @@ -287,7 +287,7 @@ static int amd_i2c_dw_xfer_quirk(struct i2c_adapter *adap, struct i2c_msg *msgs, int msg_wrt_idx, msg_itr_lmt, buf_len, data_idx; int cmd = 0, status; u8 *tx_buf; - u32 val; + unsigned int val; /* * In order to enable the interrupt for UCSI i.e. AMD NAVI GPU card, @@ -505,7 +505,8 @@ i2c_dw_read(struct dw_i2c_dev *dev) unsigned int rx_valid; for (; dev->msg_read_idx < dev->msgs_num; dev->msg_read_idx++) { - u32 len, tmp; + unsigned int tmp; + u32 len; u8 *buf; if (!(msgs[dev->msg_read_idx].flags & I2C_M_RD)) @@ -653,7 +654,7 @@ static const struct i2c_adapter_quirks i2c_dw_quirks = { static u32 i2c_dw_read_clear_intrbits(struct dw_i2c_dev *dev) { - u32 stat, dummy; + unsigned int stat, dummy; /* * The IC_INTR_STAT register just indicates "enabled" interrupts. @@ -714,7 +715,7 @@ static u32 i2c_dw_read_clear_intrbits(struct dw_i2c_dev *dev) static irqreturn_t i2c_dw_isr(int this_irq, void *dev_id) { struct dw_i2c_dev *dev = dev_id; - u32 stat, enabled; + unsigned int stat, enabled; regmap_read(dev->map, DW_IC_ENABLE, &enabled); regmap_read(dev->map, DW_IC_RAW_INTR_STAT, &stat); @@ -865,6 +866,7 @@ int i2c_dw_probe_master(struct dw_i2c_dev *dev) { struct i2c_adapter *adap = &dev->adapter; unsigned long irq_flags; + unsigned int ic_con; int ret; init_completion(&dev->cmd_complete); @@ -884,6 +886,25 @@ int i2c_dw_probe_master(struct dw_i2c_dev *dev) if (ret) return ret; + /* Lock the bus for accessing DW_IC_CON */ + ret = i2c_dw_acquire_lock(dev); + if (ret) + return ret; + + /* + * On AMD platforms BIOS advertises the bus clear feature + * and enables the SCL/SDA stuck low. SMU FW does the + * bus recovery process. Driver should not ignore this BIOS + * advertisement of bus clear feature. + */ + ret = regmap_read(dev->map, DW_IC_CON, &ic_con); + i2c_dw_release_lock(dev); + if (ret) + return ret; + + if (ic_con & DW_IC_CON_BUS_CLEAR_CTRL) + dev->master_cfg |= DW_IC_CON_BUS_CLEAR_CTRL; + ret = dev->init(dev); if (ret) return ret; |