Lines Matching +full:bpmp +full:- +full:bus +full:- +full:id
1 // SPDX-License-Identifier: GPL-2.0-only
3 * drivers/i2c/busses/i2c-tegra-bpmp.c
19 #include <soc/tegra/bpmp-abi.h>
20 #include <soc/tegra/bpmp.h>
32 struct tegra_bpmp *bpmp; member
33 unsigned int bus; member
37 * Linux flags are translated to BPMP defined I2C flags that are used in BPMP
70 * [addr little-endian][flags little-endian][len little-endian][data if write]
71 * [addr little-endian][flags little-endian][len little-endian][data if write]
87 char *buf = request->xfer.data_buf; in tegra_bpmp_serialize_i2c_msg()
94 tegra_bpmp_xlate_flags(msg->flags, &flags); in tegra_bpmp_serialize_i2c_msg()
96 buf[pos++] = msg->addr & 0xff; in tegra_bpmp_serialize_i2c_msg()
97 buf[pos++] = (msg->addr & 0xff00) >> 8; in tegra_bpmp_serialize_i2c_msg()
100 buf[pos++] = msg->len & 0xff; in tegra_bpmp_serialize_i2c_msg()
101 buf[pos++] = (msg->len & 0xff00) >> 8; in tegra_bpmp_serialize_i2c_msg()
104 for (j = 0; j < msg->len; j++) in tegra_bpmp_serialize_i2c_msg()
105 buf[pos++] = msg->buf[j]; in tegra_bpmp_serialize_i2c_msg()
109 request->xfer.data_size = pos; in tegra_bpmp_serialize_i2c_msg()
113 * The data in the BPMP -> CPU direction is composed of sequential blocks for
116 * - !I2C_M_RD, len == 5, data == a0 01 02 03 04
117 * - !I2C_M_RD, len == 1, data == a0
118 * - I2C_M_RD, len == 2, data == [uninitialized buffer 1]
119 * - !I2C_M_RD, len == 1, data == a2
120 * - I2C_M_RD, len == 2, data == [uninitialized buffer 2]
122 * ...then the data in the BPMP -> CPU direction would be 4 bytes total, and
131 size_t size = response->xfer.data_size, len = 0, pos = 0; in tegra_bpmp_i2c_deserialize()
132 char *buf = response->xfer.data_buf; in tegra_bpmp_i2c_deserialize()
140 return -EINVAL; in tegra_bpmp_i2c_deserialize()
162 return -EINVAL; in tegra_bpmp_i2c_msg_len_check()
169 return -EINVAL; in tegra_bpmp_i2c_msg_len_check()
182 request->cmd = CMD_I2C_XFER; in tegra_bpmp_i2c_msg_xfer()
183 request->xfer.bus_id = i2c->bus; in tegra_bpmp_i2c_msg_xfer()
193 err = tegra_bpmp_transfer_atomic(i2c->bpmp, &msg); in tegra_bpmp_i2c_msg_xfer()
195 err = tegra_bpmp_transfer(i2c->bpmp, &msg); in tegra_bpmp_i2c_msg_xfer()
198 dev_err(i2c->dev, "failed to transfer message: %d\n", err); in tegra_bpmp_i2c_msg_xfer()
203 if (msg.rx.ret == -BPMP_EAGAIN) { in tegra_bpmp_i2c_msg_xfer()
204 dev_dbg(i2c->dev, "arbitration lost\n"); in tegra_bpmp_i2c_msg_xfer()
205 return -EAGAIN; in tegra_bpmp_i2c_msg_xfer()
208 if (msg.rx.ret == -BPMP_ETIMEDOUT) { in tegra_bpmp_i2c_msg_xfer()
209 dev_dbg(i2c->dev, "timeout\n"); in tegra_bpmp_i2c_msg_xfer()
210 return -ETIMEDOUT; in tegra_bpmp_i2c_msg_xfer()
213 if (msg.rx.ret == -BPMP_ENXIO) { in tegra_bpmp_i2c_msg_xfer()
214 dev_dbg(i2c->dev, "NAK\n"); in tegra_bpmp_i2c_msg_xfer()
215 return -ENXIO; in tegra_bpmp_i2c_msg_xfer()
218 dev_err(i2c->dev, "transaction failed: %d\n", msg.rx.ret); in tegra_bpmp_i2c_msg_xfer()
219 return -EIO; in tegra_bpmp_i2c_msg_xfer()
236 dev_err(i2c->dev, "unsupported message length\n"); in tegra_bpmp_i2c_xfer_common()
246 dev_err(i2c->dev, "failed to transfer message: %d\n", err); in tegra_bpmp_i2c_xfer_common()
252 dev_err(i2c->dev, "failed to deserialize message: %d\n", err); in tegra_bpmp_i2c_xfer_common()
289 i2c = devm_kzalloc(&pdev->dev, sizeof(*i2c), GFP_KERNEL); in tegra_bpmp_i2c_probe()
291 return -ENOMEM; in tegra_bpmp_i2c_probe()
293 i2c->dev = &pdev->dev; in tegra_bpmp_i2c_probe()
295 i2c->bpmp = dev_get_drvdata(pdev->dev.parent); in tegra_bpmp_i2c_probe()
296 if (!i2c->bpmp) in tegra_bpmp_i2c_probe()
297 return -ENODEV; in tegra_bpmp_i2c_probe()
299 err = of_property_read_u32(pdev->dev.of_node, "nvidia,bpmp-bus-id", in tegra_bpmp_i2c_probe()
304 i2c->bus = value; in tegra_bpmp_i2c_probe()
306 i2c_set_adapdata(&i2c->adapter, i2c); in tegra_bpmp_i2c_probe()
307 i2c->adapter.owner = THIS_MODULE; in tegra_bpmp_i2c_probe()
308 strscpy(i2c->adapter.name, "Tegra BPMP I2C adapter", in tegra_bpmp_i2c_probe()
309 sizeof(i2c->adapter.name)); in tegra_bpmp_i2c_probe()
310 i2c->adapter.algo = &tegra_bpmp_i2c_algo; in tegra_bpmp_i2c_probe()
311 i2c->adapter.dev.parent = &pdev->dev; in tegra_bpmp_i2c_probe()
312 i2c->adapter.dev.of_node = pdev->dev.of_node; in tegra_bpmp_i2c_probe()
316 return i2c_add_adapter(&i2c->adapter); in tegra_bpmp_i2c_probe()
323 i2c_del_adapter(&i2c->adapter); in tegra_bpmp_i2c_remove()
327 { .compatible = "nvidia,tegra186-bpmp-i2c", },
334 .name = "tegra-bpmp-i2c",
342 MODULE_DESCRIPTION("NVIDIA Tegra BPMP I2C bus controller driver");
344 MODULE_AUTHOR("Juha-Matti Tilli");