diff options
| -rw-r--r-- | drivers/i2c/busses/i2c-mv64xxx.c | 31 |
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 */ | ||
| 112 | static void | ||
| 113 | mv64xxx_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 | |||
| 110 | static void | 125 | static void |
| 111 | mv64xxx_i2c_fsm(struct mv64xxx_i2c_data *drv_data, u32 status) | 126 | mv64xxx_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 | */ |
| 446 | static void __devinit | ||
| 447 | mv64xxx_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 | |||
| 459 | static int __devinit | 462 | static int __devinit |
| 460 | mv64xxx_i2c_map_regs(struct platform_device *pd, | 463 | mv64xxx_i2c_map_regs(struct platform_device *pd, |
| 461 | struct mv64xxx_i2c_data *drv_data) | 464 | struct mv64xxx_i2c_data *drv_data) |
