Lines Matching +full:i2c +full:- +full:bus
1 // SPDX-License-Identifier: GPL-2.0+
2 // Expose an I2C passthrough to the ChromeOS EC.
8 #include <linux/i2c.h>
17 * struct ec_i2c_device - Driver data for I2C tunnel
20 * @adap: I2C adapter
22 * @remote_bus: The EC bus number we tunnel to on the other side.
39 * ec_i2c_count_message - Count bytes needed for ec_i2c_construct_message
41 * @i2c_msgs: The i2c messages to read
42 * @num: The number of i2c messages.
61 * ec_i2c_construct_message - construct a message to go to the EC
67 * @i2c_msgs: The i2c messages to read.
68 * @num: The number of i2c messages.
69 * @bus_num: The remote bus number we want to talk to.
84 params->port = bus_num; in ec_i2c_construct_message()
85 params->num_msgs = num; in ec_i2c_construct_message()
88 struct ec_params_i2c_passthru_msg *msg = ¶ms->msg[i]; in ec_i2c_construct_message()
90 msg->len = i2c_msg->len; in ec_i2c_construct_message()
91 msg->addr_flags = i2c_msg->addr; in ec_i2c_construct_message()
93 if (i2c_msg->flags & I2C_M_TEN) in ec_i2c_construct_message()
94 return -EINVAL; in ec_i2c_construct_message()
96 if (i2c_msg->flags & I2C_M_RD) { in ec_i2c_construct_message()
97 msg->addr_flags |= EC_I2C_FLAG_READ; in ec_i2c_construct_message()
99 memcpy(out_data, i2c_msg->buf, msg->len); in ec_i2c_construct_message()
100 out_data += msg->len; in ec_i2c_construct_message()
108 * ec_i2c_count_response - Count bytes needed for ec_i2c_parse_response
110 * @i2c_msgs: The i2c messages to fill up.
111 * @num: The number of i2c messages expected.
129 * ec_i2c_parse_response - Parse a response from the EC
134 * @i2c_msgs: The i2c messages to fill up.
135 * @num: The number of i2c messages; will be modified to include the actual
150 if (resp->i2c_status & EC_I2C_STATUS_TIMEOUT) in ec_i2c_parse_response()
151 return -ETIMEDOUT; in ec_i2c_parse_response()
152 else if (resp->i2c_status & EC_I2C_STATUS_NAK) in ec_i2c_parse_response()
153 return -ENXIO; in ec_i2c_parse_response()
154 else if (resp->i2c_status & EC_I2C_STATUS_ERROR) in ec_i2c_parse_response()
155 return -EIO; in ec_i2c_parse_response()
158 if (resp->num_msgs > *num) in ec_i2c_parse_response()
159 return -EPROTO; in ec_i2c_parse_response()
160 *num = resp->num_msgs; in ec_i2c_parse_response()
166 memcpy(i2c_msg->buf, in_data, i2c_msg->len); in ec_i2c_parse_response()
167 in_data += i2c_msg->len; in ec_i2c_parse_response()
177 struct ec_i2c_device *bus = adap->algo_data; in ec_i2c_xfer() local
178 struct device *dev = bus->dev; in ec_i2c_xfer()
179 const u16 bus_num = bus->remote_bus; in ec_i2c_xfer()
202 return -ENOMEM; in ec_i2c_xfer()
204 result = ec_i2c_construct_message(msg->data, i2c_msgs, num, bus_num); in ec_i2c_xfer()
206 dev_err(dev, "Error constructing EC i2c message %d\n", result); in ec_i2c_xfer()
210 msg->version = 0; in ec_i2c_xfer()
211 msg->command = EC_CMD_I2C_PASSTHRU; in ec_i2c_xfer()
212 msg->outsize = request_len; in ec_i2c_xfer()
213 msg->insize = response_len; in ec_i2c_xfer()
215 result = cros_ec_cmd_xfer_status(bus->ec, msg); in ec_i2c_xfer()
217 dev_err(dev, "Error transferring EC i2c message %d\n", result); in ec_i2c_xfer()
221 result = ec_i2c_parse_response(msg->data, i2c_msgs, &num); in ec_i2c_xfer()
244 struct cros_ec_device *ec = dev_get_drvdata(pdev->dev.parent); in ec_i2c_probe()
245 struct device *dev = &pdev->dev; in ec_i2c_probe()
246 struct ec_i2c_device *bus = NULL; in ec_i2c_probe() local
250 if (!ec->cmd_xfer) { in ec_i2c_probe()
252 return -EINVAL; in ec_i2c_probe()
255 bus = devm_kzalloc(dev, sizeof(*bus), GFP_KERNEL); in ec_i2c_probe()
256 if (bus == NULL) in ec_i2c_probe()
257 return -ENOMEM; in ec_i2c_probe()
259 err = device_property_read_u32(dev, "google,remote-bus", &remote_bus); in ec_i2c_probe()
261 dev_err(dev, "Couldn't read remote-bus property\n"); in ec_i2c_probe()
264 bus->remote_bus = remote_bus; in ec_i2c_probe()
266 bus->ec = ec; in ec_i2c_probe()
267 bus->dev = dev; in ec_i2c_probe()
269 bus->adap.owner = THIS_MODULE; in ec_i2c_probe()
270 strscpy(bus->adap.name, "cros-ec-i2c-tunnel", sizeof(bus->adap.name)); in ec_i2c_probe()
271 bus->adap.algo = &ec_i2c_algorithm; in ec_i2c_probe()
272 bus->adap.algo_data = bus; in ec_i2c_probe()
273 bus->adap.dev.parent = &pdev->dev; in ec_i2c_probe()
274 bus->adap.dev.of_node = pdev->dev.of_node; in ec_i2c_probe()
275 bus->adap.retries = I2C_MAX_RETRIES; in ec_i2c_probe()
276 ACPI_COMPANION_SET(&bus->adap.dev, ACPI_COMPANION(&pdev->dev)); in ec_i2c_probe()
278 err = i2c_add_adapter(&bus->adap); in ec_i2c_probe()
281 platform_set_drvdata(pdev, bus); in ec_i2c_probe()
288 struct ec_i2c_device *bus = platform_get_drvdata(dev); in ec_i2c_remove() local
290 i2c_del_adapter(&bus->adap); in ec_i2c_remove()
294 { .compatible = "google,cros-ec-i2c-tunnel" },
309 .name = "cros-ec-i2c-tunnel",
318 MODULE_DESCRIPTION("EC I2C tunnel driver");
319 MODULE_ALIAS("platform:cros-ec-i2c-tunnel");