aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/i2c/busses/i2c-mv64xxx.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/i2c/busses/i2c-mv64xxx.c')
-rw-r--r--drivers/i2c/busses/i2c-mv64xxx.c31
1 files changed, 17 insertions, 14 deletions
diff --git a/drivers/i2c/busses/i2c-mv64xxx.c b/drivers/i2c/busses/i2c-mv64xxx.c
index 251154ae5d97..bb7bf68a7fb6 100644
--- a/drivers/i2c/busses/i2c-mv64xxx.c
+++ b/drivers/i2c/busses/i2c-mv64xxx.c
@@ -107,6 +107,21 @@ struct mv64xxx_i2c_data {
107 * 107 *
108 ***************************************************************************** 108 *****************************************************************************
109 */ 109 */
110
111/* Reset hardware and initialize FSM */
112static void
113mv64xxx_i2c_hw_init(struct mv64xxx_i2c_data *drv_data)
114{
115 writel(0, drv_data->reg_base + MV64XXX_I2C_REG_SOFT_RESET);
116 writel((((drv_data->freq_m & 0xf) << 3) | (drv_data->freq_n & 0x7)),
117 drv_data->reg_base + MV64XXX_I2C_REG_BAUD);
118 writel(0, drv_data->reg_base + MV64XXX_I2C_REG_SLAVE_ADDR);
119 writel(0, drv_data->reg_base + MV64XXX_I2C_REG_EXT_SLAVE_ADDR);
120 writel(MV64XXX_I2C_REG_CONTROL_TWSIEN | MV64XXX_I2C_REG_CONTROL_STOP,
121 drv_data->reg_base + MV64XXX_I2C_REG_CONTROL);
122 drv_data->state = MV64XXX_I2C_STATE_IDLE;
123}
124
110static void 125static void
111mv64xxx_i2c_fsm(struct mv64xxx_i2c_data *drv_data, u32 status) 126mv64xxx_i2c_fsm(struct mv64xxx_i2c_data *drv_data, u32 status)
112{ 127{
@@ -203,7 +218,7 @@ mv64xxx_i2c_fsm(struct mv64xxx_i2c_data *drv_data, u32 status)
203 drv_data->state, status, drv_data->msg->addr, 218 drv_data->state, status, drv_data->msg->addr,
204 drv_data->msg->flags); 219 drv_data->msg->flags);
205 drv_data->action = MV64XXX_I2C_ACTION_SEND_STOP; 220 drv_data->action = MV64XXX_I2C_ACTION_SEND_STOP;
206 drv_data->state = MV64XXX_I2C_STATE_IDLE; 221 mv64xxx_i2c_hw_init(drv_data);
207 drv_data->rc = -EIO; 222 drv_data->rc = -EIO;
208 } 223 }
209} 224}
@@ -367,6 +382,7 @@ mv64xxx_i2c_wait_for_completion(struct mv64xxx_i2c_data *drv_data)
367 "mv64xxx: I2C bus locked, block: %d, " 382 "mv64xxx: I2C bus locked, block: %d, "
368 "time_left: %d\n", drv_data->block, 383 "time_left: %d\n", drv_data->block,
369 (int)time_left); 384 (int)time_left);
385 mv64xxx_i2c_hw_init(drv_data);
370 } 386 }
371 } else 387 } else
372 spin_unlock_irqrestore(&drv_data->lock, flags); 388 spin_unlock_irqrestore(&drv_data->lock, flags);
@@ -443,19 +459,6 @@ static const struct i2c_algorithm mv64xxx_i2c_algo = {
443 * 459 *
444 ***************************************************************************** 460 *****************************************************************************
445 */ 461 */
446static void __devinit
447mv64xxx_i2c_hw_init(struct mv64xxx_i2c_data *drv_data)
448{
449 writel(0, drv_data->reg_base + MV64XXX_I2C_REG_SOFT_RESET);
450 writel((((drv_data->freq_m & 0xf) << 3) | (drv_data->freq_n & 0x7)),
451 drv_data->reg_base + MV64XXX_I2C_REG_BAUD);
452 writel(0, drv_data->reg_base + MV64XXX_I2C_REG_SLAVE_ADDR);
453 writel(0, drv_data->reg_base + MV64XXX_I2C_REG_EXT_SLAVE_ADDR);
454 writel(MV64XXX_I2C_REG_CONTROL_TWSIEN | MV64XXX_I2C_REG_CONTROL_STOP,
455 drv_data->reg_base + MV64XXX_I2C_REG_CONTROL);
456 drv_data->state = MV64XXX_I2C_STATE_IDLE;
457}
458
459static int __devinit 462static int __devinit
460mv64xxx_i2c_map_regs(struct platform_device *pd, 463mv64xxx_i2c_map_regs(struct platform_device *pd,
461 struct mv64xxx_i2c_data *drv_data) 464 struct mv64xxx_i2c_data *drv_data)