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