diff options
Diffstat (limited to 'drivers/i2c/busses/i2c-tegra-bpmp.c')
-rw-r--r-- | drivers/i2c/busses/i2c-tegra-bpmp.c | 79 |
1 files changed, 38 insertions, 41 deletions
diff --git a/drivers/i2c/busses/i2c-tegra-bpmp.c b/drivers/i2c/busses/i2c-tegra-bpmp.c index c0c7d01473f2..3680d608698b 100644 --- a/drivers/i2c/busses/i2c-tegra-bpmp.c +++ b/drivers/i2c/busses/i2c-tegra-bpmp.c @@ -38,49 +38,31 @@ struct tegra_bpmp_i2c { * firmware I2C driver to avoid any issues in future if Linux I2C flags are * changed. */ -static int tegra_bpmp_xlate_flags(u16 flags, u16 *out) +static void tegra_bpmp_xlate_flags(u16 flags, u16 *out) { - if (flags & I2C_M_TEN) { + if (flags & I2C_M_TEN) *out |= SERIALI2C_TEN; - flags &= ~I2C_M_TEN; - } - if (flags & I2C_M_RD) { + if (flags & I2C_M_RD) *out |= SERIALI2C_RD; - flags &= ~I2C_M_RD; - } - if (flags & I2C_M_STOP) { + if (flags & I2C_M_STOP) *out |= SERIALI2C_STOP; - flags &= ~I2C_M_STOP; - } - if (flags & I2C_M_NOSTART) { + if (flags & I2C_M_NOSTART) *out |= SERIALI2C_NOSTART; - flags &= ~I2C_M_NOSTART; - } - if (flags & I2C_M_REV_DIR_ADDR) { + if (flags & I2C_M_REV_DIR_ADDR) *out |= SERIALI2C_REV_DIR_ADDR; - flags &= ~I2C_M_REV_DIR_ADDR; - } - if (flags & I2C_M_IGNORE_NAK) { + if (flags & I2C_M_IGNORE_NAK) *out |= SERIALI2C_IGNORE_NAK; - flags &= ~I2C_M_IGNORE_NAK; - } - if (flags & I2C_M_NO_RD_ACK) { + if (flags & I2C_M_NO_RD_ACK) *out |= SERIALI2C_NO_RD_ACK; - flags &= ~I2C_M_NO_RD_ACK; - } - if (flags & I2C_M_RECV_LEN) { + if (flags & I2C_M_RECV_LEN) *out |= SERIALI2C_RECV_LEN; - flags &= ~I2C_M_RECV_LEN; - } - - return 0; } /** @@ -97,22 +79,19 @@ static int tegra_bpmp_xlate_flags(u16 flags, u16 *out) * * See deserialize_i2c documentation for the data format in the other direction. */ -static int tegra_bpmp_serialize_i2c_msg(struct tegra_bpmp_i2c *i2c, +static void tegra_bpmp_serialize_i2c_msg(struct tegra_bpmp_i2c *i2c, struct mrq_i2c_request *request, struct i2c_msg *msgs, unsigned int num) { char *buf = request->xfer.data_buf; unsigned int i, j, pos = 0; - int err; for (i = 0; i < num; i++) { struct i2c_msg *msg = &msgs[i]; u16 flags = 0; - err = tegra_bpmp_xlate_flags(msg->flags, &flags); - if (err < 0) - return err; + tegra_bpmp_xlate_flags(msg->flags, &flags); buf[pos++] = msg->addr & 0xff; buf[pos++] = (msg->addr & 0xff00) >> 8; @@ -128,8 +107,6 @@ static int tegra_bpmp_serialize_i2c_msg(struct tegra_bpmp_i2c *i2c, } request->xfer.data_size = pos; - - return 0; } /** @@ -217,7 +194,32 @@ static int tegra_bpmp_i2c_msg_xfer(struct tegra_bpmp_i2c *i2c, else err = tegra_bpmp_transfer(i2c->bpmp, &msg); - return err; + if (err < 0) { + dev_err(i2c->dev, "failed to transfer message: %d\n", err); + return err; + } + + if (msg.rx.ret != 0) { + if (msg.rx.ret == -BPMP_EAGAIN) { + dev_dbg(i2c->dev, "arbitration lost\n"); + return -EAGAIN; + } + + if (msg.rx.ret == -BPMP_ETIMEDOUT) { + dev_dbg(i2c->dev, "timeout\n"); + return -ETIMEDOUT; + } + + if (msg.rx.ret == -BPMP_ENXIO) { + dev_dbg(i2c->dev, "NAK\n"); + return -ENXIO; + } + + dev_err(i2c->dev, "transaction failed: %d\n", msg.rx.ret); + return -EIO; + } + + return 0; } static int tegra_bpmp_i2c_xfer_common(struct i2c_adapter *adapter, @@ -238,12 +240,7 @@ static int tegra_bpmp_i2c_xfer_common(struct i2c_adapter *adapter, memset(&request, 0, sizeof(request)); memset(&response, 0, sizeof(response)); - err = tegra_bpmp_serialize_i2c_msg(i2c, &request, msgs, num); - if (err < 0) { - dev_err(i2c->dev, "failed to serialize message: %d\n", err); - return err; - } - + tegra_bpmp_serialize_i2c_msg(i2c, &request, msgs, num); err = tegra_bpmp_i2c_msg_xfer(i2c, &request, &response, atomic); if (err < 0) { dev_err(i2c->dev, "failed to transfer message: %d\n", err); |