summaryrefslogtreecommitdiffstats
path: root/drivers/i2c/busses/i2c-bcm283x.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/i2c/busses/i2c-bcm283x.c')
-rw-r--r--drivers/i2c/busses/i2c-bcm283x.c36
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),