i2c-cros-ec-tunnel.c (8041B)
1// SPDX-License-Identifier: GPL-2.0+ 2// Expose an I2C passthrough to the ChromeOS EC. 3// 4// Copyright (C) 2013 Google, Inc. 5 6#include <linux/acpi.h> 7#include <linux/module.h> 8#include <linux/i2c.h> 9#include <linux/platform_data/cros_ec_commands.h> 10#include <linux/platform_data/cros_ec_proto.h> 11#include <linux/platform_device.h> 12#include <linux/slab.h> 13 14#define I2C_MAX_RETRIES 3 15 16/** 17 * struct ec_i2c_device - Driver data for I2C tunnel 18 * 19 * @dev: Device node 20 * @adap: I2C adapter 21 * @ec: Pointer to EC device 22 * @remote_bus: The EC bus number we tunnel to on the other side. 23 * @request_buf: Buffer for transmitting data; we expect most transfers to fit. 24 * @response_buf: Buffer for receiving data; we expect most transfers to fit. 25 */ 26 27struct ec_i2c_device { 28 struct device *dev; 29 struct i2c_adapter adap; 30 struct cros_ec_device *ec; 31 32 u16 remote_bus; 33 34 u8 request_buf[256]; 35 u8 response_buf[256]; 36}; 37 38/** 39 * ec_i2c_count_message - Count bytes needed for ec_i2c_construct_message 40 * 41 * @i2c_msgs: The i2c messages to read 42 * @num: The number of i2c messages. 43 * 44 * Returns the number of bytes the messages will take up. 45 */ 46static int ec_i2c_count_message(const struct i2c_msg i2c_msgs[], int num) 47{ 48 int i; 49 int size; 50 51 size = sizeof(struct ec_params_i2c_passthru); 52 size += num * sizeof(struct ec_params_i2c_passthru_msg); 53 for (i = 0; i < num; i++) 54 if (!(i2c_msgs[i].flags & I2C_M_RD)) 55 size += i2c_msgs[i].len; 56 57 return size; 58} 59 60/** 61 * ec_i2c_construct_message - construct a message to go to the EC 62 * 63 * This function effectively stuffs the standard i2c_msg format of Linux into 64 * a format that the EC understands. 65 * 66 * @buf: The buffer to fill. We assume that the buffer is big enough. 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. 70 * 71 * Returns 0 or a negative error number. 72 */ 73static int ec_i2c_construct_message(u8 *buf, const struct i2c_msg i2c_msgs[], 74 int num, u16 bus_num) 75{ 76 struct ec_params_i2c_passthru *params; 77 u8 *out_data; 78 int i; 79 80 out_data = buf + sizeof(struct ec_params_i2c_passthru) + 81 num * sizeof(struct ec_params_i2c_passthru_msg); 82 83 params = (struct ec_params_i2c_passthru *)buf; 84 params->port = bus_num; 85 params->num_msgs = num; 86 for (i = 0; i < num; i++) { 87 const struct i2c_msg *i2c_msg = &i2c_msgs[i]; 88 struct ec_params_i2c_passthru_msg *msg = ¶ms->msg[i]; 89 90 msg->len = i2c_msg->len; 91 msg->addr_flags = i2c_msg->addr; 92 93 if (i2c_msg->flags & I2C_M_TEN) 94 return -EINVAL; 95 96 if (i2c_msg->flags & I2C_M_RD) { 97 msg->addr_flags |= EC_I2C_FLAG_READ; 98 } else { 99 memcpy(out_data, i2c_msg->buf, msg->len); 100 out_data += msg->len; 101 } 102 } 103 104 return 0; 105} 106 107/** 108 * ec_i2c_count_response - Count bytes needed for ec_i2c_parse_response 109 * 110 * @i2c_msgs: The i2c messages to fill up. 111 * @num: The number of i2c messages expected. 112 * 113 * Returns the number of response bytes expeced. 114 */ 115static int ec_i2c_count_response(struct i2c_msg i2c_msgs[], int num) 116{ 117 int size; 118 int i; 119 120 size = sizeof(struct ec_response_i2c_passthru); 121 for (i = 0; i < num; i++) 122 if (i2c_msgs[i].flags & I2C_M_RD) 123 size += i2c_msgs[i].len; 124 125 return size; 126} 127 128/** 129 * ec_i2c_parse_response - Parse a response from the EC 130 * 131 * We'll take the EC's response and copy it back into msgs. 132 * 133 * @buf: The buffer to parse. 134 * @i2c_msgs: The i2c messages to fill up. 135 * @num: The number of i2c messages; will be modified to include the actual 136 * number received. 137 * 138 * Returns 0 or a negative error number. 139 */ 140static int ec_i2c_parse_response(const u8 *buf, struct i2c_msg i2c_msgs[], 141 int *num) 142{ 143 const struct ec_response_i2c_passthru *resp; 144 const u8 *in_data; 145 int i; 146 147 in_data = buf + sizeof(struct ec_response_i2c_passthru); 148 149 resp = (const struct ec_response_i2c_passthru *)buf; 150 if (resp->i2c_status & EC_I2C_STATUS_TIMEOUT) 151 return -ETIMEDOUT; 152 else if (resp->i2c_status & EC_I2C_STATUS_NAK) 153 return -ENXIO; 154 else if (resp->i2c_status & EC_I2C_STATUS_ERROR) 155 return -EIO; 156 157 /* Other side could send us back fewer messages, but not more */ 158 if (resp->num_msgs > *num) 159 return -EPROTO; 160 *num = resp->num_msgs; 161 162 for (i = 0; i < *num; i++) { 163 struct i2c_msg *i2c_msg = &i2c_msgs[i]; 164 165 if (i2c_msgs[i].flags & I2C_M_RD) { 166 memcpy(i2c_msg->buf, in_data, i2c_msg->len); 167 in_data += i2c_msg->len; 168 } 169 } 170 171 return 0; 172} 173 174static int ec_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg i2c_msgs[], 175 int num) 176{ 177 struct ec_i2c_device *bus = adap->algo_data; 178 struct device *dev = bus->dev; 179 const u16 bus_num = bus->remote_bus; 180 int request_len; 181 int response_len; 182 int alloc_size; 183 int result; 184 struct cros_ec_command *msg; 185 186 request_len = ec_i2c_count_message(i2c_msgs, num); 187 if (request_len < 0) { 188 dev_warn(dev, "Error constructing message %d\n", request_len); 189 return request_len; 190 } 191 192 response_len = ec_i2c_count_response(i2c_msgs, num); 193 if (response_len < 0) { 194 /* Unexpected; no errors should come when NULL response */ 195 dev_warn(dev, "Error preparing response %d\n", response_len); 196 return response_len; 197 } 198 199 alloc_size = max(request_len, response_len); 200 msg = kmalloc(sizeof(*msg) + alloc_size, GFP_KERNEL); 201 if (!msg) 202 return -ENOMEM; 203 204 result = ec_i2c_construct_message(msg->data, i2c_msgs, num, bus_num); 205 if (result) { 206 dev_err(dev, "Error constructing EC i2c message %d\n", result); 207 goto exit; 208 } 209 210 msg->version = 0; 211 msg->command = EC_CMD_I2C_PASSTHRU; 212 msg->outsize = request_len; 213 msg->insize = response_len; 214 215 result = cros_ec_cmd_xfer_status(bus->ec, msg); 216 if (result < 0) { 217 dev_err(dev, "Error transferring EC i2c message %d\n", result); 218 goto exit; 219 } 220 221 result = ec_i2c_parse_response(msg->data, i2c_msgs, &num); 222 if (result < 0) 223 goto exit; 224 225 /* Indicate success by saying how many messages were sent */ 226 result = num; 227exit: 228 kfree(msg); 229 return result; 230} 231 232static u32 ec_i2c_functionality(struct i2c_adapter *adap) 233{ 234 return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; 235} 236 237static const struct i2c_algorithm ec_i2c_algorithm = { 238 .master_xfer = ec_i2c_xfer, 239 .functionality = ec_i2c_functionality, 240}; 241 242static int ec_i2c_probe(struct platform_device *pdev) 243{ 244 struct cros_ec_device *ec = dev_get_drvdata(pdev->dev.parent); 245 struct device *dev = &pdev->dev; 246 struct ec_i2c_device *bus = NULL; 247 u32 remote_bus; 248 int err; 249 250 if (!ec->cmd_xfer) { 251 dev_err(dev, "Missing sendrecv\n"); 252 return -EINVAL; 253 } 254 255 bus = devm_kzalloc(dev, sizeof(*bus), GFP_KERNEL); 256 if (bus == NULL) 257 return -ENOMEM; 258 259 err = device_property_read_u32(dev, "google,remote-bus", &remote_bus); 260 if (err) { 261 dev_err(dev, "Couldn't read remote-bus property\n"); 262 return err; 263 } 264 bus->remote_bus = remote_bus; 265 266 bus->ec = ec; 267 bus->dev = dev; 268 269 bus->adap.owner = THIS_MODULE; 270 strlcpy(bus->adap.name, "cros-ec-i2c-tunnel", sizeof(bus->adap.name)); 271 bus->adap.algo = &ec_i2c_algorithm; 272 bus->adap.algo_data = bus; 273 bus->adap.dev.parent = &pdev->dev; 274 bus->adap.dev.of_node = pdev->dev.of_node; 275 bus->adap.retries = I2C_MAX_RETRIES; 276 ACPI_COMPANION_SET(&bus->adap.dev, ACPI_COMPANION(&pdev->dev)); 277 278 err = i2c_add_adapter(&bus->adap); 279 if (err) 280 return err; 281 platform_set_drvdata(pdev, bus); 282 283 return err; 284} 285 286static int ec_i2c_remove(struct platform_device *dev) 287{ 288 struct ec_i2c_device *bus = platform_get_drvdata(dev); 289 290 i2c_del_adapter(&bus->adap); 291 292 return 0; 293} 294 295static const struct of_device_id cros_ec_i2c_of_match[] = { 296 { .compatible = "google,cros-ec-i2c-tunnel" }, 297 {}, 298}; 299MODULE_DEVICE_TABLE(of, cros_ec_i2c_of_match); 300 301static const struct acpi_device_id cros_ec_i2c_tunnel_acpi_id[] = { 302 { "GOOG0012", 0 }, 303 { } 304}; 305MODULE_DEVICE_TABLE(acpi, cros_ec_i2c_tunnel_acpi_id); 306 307static struct platform_driver ec_i2c_tunnel_driver = { 308 .probe = ec_i2c_probe, 309 .remove = ec_i2c_remove, 310 .driver = { 311 .name = "cros-ec-i2c-tunnel", 312 .acpi_match_table = ACPI_PTR(cros_ec_i2c_tunnel_acpi_id), 313 .of_match_table = of_match_ptr(cros_ec_i2c_of_match), 314 }, 315}; 316 317module_platform_driver(ec_i2c_tunnel_driver); 318 319MODULE_LICENSE("GPL"); 320MODULE_DESCRIPTION("EC I2C tunnel driver"); 321MODULE_ALIAS("platform:cros-ec-i2c-tunnel");