diff options
Diffstat (limited to 'drivers/i2c/busses/i2c-bcm283x.c')
-rw-r--r-- | drivers/i2c/busses/i2c-bcm283x.c | 36 |
1 files changed, 22 insertions, 14 deletions
diff --git a/drivers/i2c/busses/i2c-bcm283x.c b/drivers/i2c/busses/i2c-bcm283x.c index 097f73d983..b40918932f 100644 --- a/drivers/i2c/busses/i2c-bcm283x.c +++ b/drivers/i2c/busses/i2c-bcm283x.c @@ -74,7 +74,7 @@ static inline struct bcm283x_i2c *to_bcm283x_i2c(struct i2c_adapter *adapter) static inline int bcm283x_i2c_init(struct bcm283x_i2c *bcm_i2c) { - struct device_d *dev = &bcm_i2c->adapter.dev; + struct device *dev = bcm_i2c->adapter.dev.parent; u32 mclk_rate, cdiv, redl, fedl; /* @@ -130,7 +130,7 @@ static int bcm283x_i2c_msg_xfer(struct bcm283x_i2c *bcm_i2c, { int ret; u32 reg_c, reg_s, reg_dlen, timeout; - struct device_d *dev = &bcm_i2c->adapter.dev; + struct device *dev = &bcm_i2c->adapter.dev; bool msg_read = (msg->flags & I2C_M_RD) > 0; bool msg_10bit = (msg->flags & I2C_M_TEN) > 0; u16 buf_pos = 0; @@ -147,7 +147,7 @@ static int bcm283x_i2c_msg_xfer(struct bcm283x_i2c *bcm_i2c, if (ret) { dev_err(dev, "timeout: 10bit read initilization\n"); - return ret; + goto out; } if (reg_s & BSC_S_ERR) goto nack; @@ -178,7 +178,7 @@ static int bcm283x_i2c_msg_xfer(struct bcm283x_i2c *bcm_i2c, if (ret) { dev_err(dev, "timeout: waiting for data in FIFO\n"); - return ret; + goto out; } if (reg_s & BSC_S_ERR) goto nack; @@ -197,7 +197,7 @@ static int bcm283x_i2c_msg_xfer(struct bcm283x_i2c *bcm_i2c, if (ret) { dev_err(dev, "timeout: waiting for space in FIFO\n"); - return ret; + goto out; } if (reg_s & BSC_S_ERR) goto nack; @@ -216,16 +216,23 @@ static int bcm283x_i2c_msg_xfer(struct bcm283x_i2c *bcm_i2c, if (ret) { dev_err(dev, "timeout: waiting for transfer to end\n"); - return ret; + goto out; } if (reg_s & BSC_S_ERR) goto nack; - writel(BSC_S_DONE | BSC_S_ERR | BSC_S_CLKT, &bcm_i2c->regs->s); - writel(BSC_C_CLEAR1 | BSC_C_I2CEN, &bcm_i2c->regs->c); - return 0; + goto out; nack: dev_dbg(dev, "device with addr %x didn't ACK\n", msg->addr); - return -EREMOTEIO; + writel(BSC_S_ERR, &bcm_i2c->regs->s); + timeout = calc_byte_timeout_us(bcm_i2c->bitrate); + // Wait for end of transfer so BSC has time to send STOP condition + readl_poll_timeout(&bcm_i2c->regs->s, reg_s, ~reg_s & BSC_S_TA, timeout); + ret = -EREMOTEIO; +out: + // Return to default state for next xfer + writel(BSC_S_DONE | BSC_S_ERR | BSC_S_CLKT, &bcm_i2c->regs->s); + writel(BSC_C_CLEAR1 | BSC_C_I2CEN, &bcm_i2c->regs->c); + return ret; } static int bcm283x_i2c_xfer(struct i2c_adapter *adapter, @@ -259,12 +266,12 @@ out: return ret; } -static int bcm283x_i2c_probe(struct device_d *dev) +static int bcm283x_i2c_probe(struct device *dev) { int ret; struct resource *iores; struct bcm283x_i2c *bcm_i2c; - struct device_node *np = dev->device_node; + struct device_node *np = dev->of_node; bcm_i2c = xzalloc(sizeof(*bcm_i2c)); @@ -301,7 +308,7 @@ static int bcm283x_i2c_probe(struct device_d *dev) bcm_i2c->adapter.master_xfer = bcm283x_i2c_xfer; bcm_i2c->adapter.nr = dev->id; bcm_i2c->adapter.dev.parent = dev; - bcm_i2c->adapter.dev.device_node = np; + bcm_i2c->adapter.dev.of_node = np; ret = bcm283x_i2c_init(bcm_i2c); if (ret) @@ -318,8 +325,9 @@ static struct of_device_id bcm283x_i2c_dt_ids[] = { { .compatible = "brcm,bcm2711-i2c", }, { /* sentinel */ } }; +MODULE_DEVICE_TABLE(of, bcm283x_i2c_dt_ids); -static struct driver_d bcm283x_i2c_driver = { +static struct driver bcm283x_i2c_driver = { .name = "i2c-bcm283x", .probe = bcm283x_i2c_probe, .of_compatible = DRV_OF_COMPAT(bcm283x_i2c_dt_ids), |