1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (c) 2016, NVIDIA CORPORATION.
10 #include <asm/arch-tegra/bpmp_abi.h>
12 DECLARE_GLOBAL_DATA_PTR;
14 struct tegra186_bpmp_i2c {
18 static inline void serialize_u16(uint8_t **p, uint16_t val)
25 /* These just happen to have the same values as I2C_M_* and SERIALI2C_* */
26 #define SUPPORTED_FLAGS \
31 I2C_M_REV_DIR_ADDR | \
36 static int tegra186_bpmp_i2c_xfer(struct udevice *dev, struct i2c_msg *msg,
39 struct tegra186_bpmp_i2c *priv = dev_get_priv(dev);
40 struct mrq_i2c_request req;
41 struct mrq_i2c_response resp;
45 req.cmd = CMD_I2C_XFER;
46 req.xfer.bus_id = priv->bpmp_bus_id;
47 p = &req.xfer.data_buf[0];
48 left = ARRAY_SIZE(req.xfer.data_buf);
49 for (i = 0; i < nmsgs; i++) {
51 if (!(msg[i].flags & I2C_M_RD))
53 if ((len >= BIT(16)) || (len > left))
56 if (msg[i].flags & ~SUPPORTED_FLAGS)
59 serialize_u16(&p, msg[i].addr);
60 serialize_u16(&p, msg[i].flags);
61 serialize_u16(&p, msg[i].len);
62 if (!(msg[i].flags & I2C_M_RD)) {
63 memcpy(p, msg[i].buf, msg[i].len);
67 req.xfer.data_size = p - &req.xfer.data_buf[0];
69 ret = misc_call(dev->parent, MRQ_I2C, &req, sizeof(req), &resp,
74 p = &resp.xfer.data_buf[0];
75 left = resp.xfer.data_size;
76 if (left > ARRAY_SIZE(resp.xfer.data_buf))
78 for (i = 0; i < nmsgs; i++) {
79 if (msg[i].flags & I2C_M_RD) {
80 memcpy(msg[i].buf, p, msg[i].len);
88 static int tegra186_bpmp_probe_chip(struct udevice *bus, uint chip_addr,
94 static int tegra186_bpmp_i2c_probe(struct udevice *dev)
96 struct tegra186_bpmp_i2c *priv = dev_get_priv(dev);
98 priv->bpmp_bus_id = fdtdec_get_uint(gd->fdt_blob, dev_of_offset(dev),
99 "nvidia,bpmp-bus-id", U32_MAX);
100 if (priv->bpmp_bus_id == U32_MAX) {
101 debug("%s: could not parse nvidia,bpmp-bus-id\n", __func__);
108 static const struct dm_i2c_ops tegra186_bpmp_i2c_ops = {
109 .xfer = tegra186_bpmp_i2c_xfer,
110 .probe_chip = tegra186_bpmp_probe_chip,
113 static const struct udevice_id tegra186_bpmp_i2c_ids[] = {
114 { .compatible = "nvidia,tegra186-bpmp-i2c" },
118 U_BOOT_DRIVER(i2c_gpio) = {
119 .name = "tegra186_bpmp_i2c",
121 .of_match = tegra186_bpmp_i2c_ids,
122 .probe = tegra186_bpmp_i2c_probe,
123 .priv_auto_alloc_size = sizeof(struct tegra186_bpmp_i2c),
124 .ops = &tegra186_bpmp_i2c_ops,