root/drivers/platform/chrome/cros_ec_i2c.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. to_ec_dev
  2. cros_ec_pkt_xfer_i2c
  3. cros_ec_cmd_xfer_i2c
  4. cros_ec_i2c_probe
  5. cros_ec_i2c_remove
  6. cros_ec_i2c_suspend
  7. cros_ec_i2c_resume

   1 // SPDX-License-Identifier: GPL-2.0
   2 // I2C interface for ChromeOS Embedded Controller
   3 //
   4 // Copyright (C) 2012 Google, Inc
   5 
   6 #include <linux/acpi.h>
   7 #include <linux/delay.h>
   8 #include <linux/kernel.h>
   9 #include <linux/module.h>
  10 #include <linux/i2c.h>
  11 #include <linux/interrupt.h>
  12 #include <linux/platform_data/cros_ec_commands.h>
  13 #include <linux/platform_data/cros_ec_proto.h>
  14 #include <linux/platform_device.h>
  15 #include <linux/slab.h>
  16 
  17 /**
  18  * Request format for protocol v3
  19  * byte 0       0xda (EC_COMMAND_PROTOCOL_3)
  20  * byte 1-8     struct ec_host_request
  21  * byte 10-     response data
  22  */
  23 struct ec_host_request_i2c {
  24         /* Always 0xda to backward compatible with v2 struct */
  25         uint8_t  command_protocol;
  26         struct ec_host_request ec_request;
  27 } __packed;
  28 
  29 
  30 /*
  31  * Response format for protocol v3
  32  * byte 0       result code
  33  * byte 1       packet_length
  34  * byte 2-9     struct ec_host_response
  35  * byte 10-     response data
  36  */
  37 struct ec_host_response_i2c {
  38         uint8_t result;
  39         uint8_t packet_length;
  40         struct ec_host_response ec_response;
  41 } __packed;
  42 
  43 static inline struct cros_ec_device *to_ec_dev(struct device *dev)
  44 {
  45         struct i2c_client *client = to_i2c_client(dev);
  46 
  47         return i2c_get_clientdata(client);
  48 }
  49 
  50 static int cros_ec_pkt_xfer_i2c(struct cros_ec_device *ec_dev,
  51                                 struct cros_ec_command *msg)
  52 {
  53         struct i2c_client *client = ec_dev->priv;
  54         int ret = -ENOMEM;
  55         int i;
  56         int packet_len;
  57         u8 *out_buf = NULL;
  58         u8 *in_buf = NULL;
  59         u8 sum;
  60         struct i2c_msg i2c_msg[2];
  61         struct ec_host_response *ec_response;
  62         struct ec_host_request_i2c *ec_request_i2c;
  63         struct ec_host_response_i2c *ec_response_i2c;
  64         int request_header_size = sizeof(struct ec_host_request_i2c);
  65         int response_header_size = sizeof(struct ec_host_response_i2c);
  66 
  67         i2c_msg[0].addr = client->addr;
  68         i2c_msg[0].flags = 0;
  69         i2c_msg[1].addr = client->addr;
  70         i2c_msg[1].flags = I2C_M_RD;
  71 
  72         packet_len = msg->insize + response_header_size;
  73         BUG_ON(packet_len > ec_dev->din_size);
  74         in_buf = ec_dev->din;
  75         i2c_msg[1].len = packet_len;
  76         i2c_msg[1].buf = (char *) in_buf;
  77 
  78         packet_len = msg->outsize + request_header_size;
  79         BUG_ON(packet_len > ec_dev->dout_size);
  80         out_buf = ec_dev->dout;
  81         i2c_msg[0].len = packet_len;
  82         i2c_msg[0].buf = (char *) out_buf;
  83 
  84         /* create request data */
  85         ec_request_i2c = (struct ec_host_request_i2c *) out_buf;
  86         ec_request_i2c->command_protocol = EC_COMMAND_PROTOCOL_3;
  87 
  88         ec_dev->dout++;
  89         ret = cros_ec_prepare_tx(ec_dev, msg);
  90         ec_dev->dout--;
  91 
  92         /* send command to EC and read answer */
  93         ret = i2c_transfer(client->adapter, i2c_msg, 2);
  94         if (ret < 0) {
  95                 dev_dbg(ec_dev->dev, "i2c transfer failed: %d\n", ret);
  96                 goto done;
  97         } else if (ret != 2) {
  98                 dev_err(ec_dev->dev, "failed to get response: %d\n", ret);
  99                 ret = -EIO;
 100                 goto done;
 101         }
 102 
 103         ec_response_i2c = (struct ec_host_response_i2c *) in_buf;
 104         msg->result = ec_response_i2c->result;
 105         ec_response = &ec_response_i2c->ec_response;
 106 
 107         switch (msg->result) {
 108         case EC_RES_SUCCESS:
 109                 break;
 110         case EC_RES_IN_PROGRESS:
 111                 ret = -EAGAIN;
 112                 dev_dbg(ec_dev->dev, "command 0x%02x in progress\n",
 113                         msg->command);
 114                 goto done;
 115 
 116         default:
 117                 dev_dbg(ec_dev->dev, "command 0x%02x returned %d\n",
 118                         msg->command, msg->result);
 119                 /*
 120                  * When we send v3 request to v2 ec, ec won't recognize the
 121                  * 0xda (EC_COMMAND_PROTOCOL_3) and will return with status
 122                  * EC_RES_INVALID_COMMAND with zero data length.
 123                  *
 124                  * In case of invalid command for v3 protocol the data length
 125                  * will be at least sizeof(struct ec_host_response)
 126                  */
 127                 if (ec_response_i2c->result == EC_RES_INVALID_COMMAND &&
 128                     ec_response_i2c->packet_length == 0) {
 129                         ret = -EPROTONOSUPPORT;
 130                         goto done;
 131                 }
 132         }
 133 
 134         if (ec_response_i2c->packet_length < sizeof(struct ec_host_response)) {
 135                 dev_err(ec_dev->dev,
 136                         "response of %u bytes too short; not a full header\n",
 137                         ec_response_i2c->packet_length);
 138                 ret = -EBADMSG;
 139                 goto done;
 140         }
 141 
 142         if (msg->insize < ec_response->data_len) {
 143                 dev_err(ec_dev->dev,
 144                         "response data size is too large: expected %u, got %u\n",
 145                         msg->insize,
 146                         ec_response->data_len);
 147                 ret = -EMSGSIZE;
 148                 goto done;
 149         }
 150 
 151         /* copy response packet payload and compute checksum */
 152         sum = 0;
 153         for (i = 0; i < sizeof(struct ec_host_response); i++)
 154                 sum += ((u8 *)ec_response)[i];
 155 
 156         memcpy(msg->data,
 157                in_buf + response_header_size,
 158                ec_response->data_len);
 159         for (i = 0; i < ec_response->data_len; i++)
 160                 sum += msg->data[i];
 161 
 162         /* All bytes should sum to zero */
 163         if (sum) {
 164                 dev_err(ec_dev->dev, "bad packet checksum\n");
 165                 ret = -EBADMSG;
 166                 goto done;
 167         }
 168 
 169         ret = ec_response->data_len;
 170 
 171 done:
 172         if (msg->command == EC_CMD_REBOOT_EC)
 173                 msleep(EC_REBOOT_DELAY_MS);
 174 
 175         return ret;
 176 }
 177 
 178 static int cros_ec_cmd_xfer_i2c(struct cros_ec_device *ec_dev,
 179                                 struct cros_ec_command *msg)
 180 {
 181         struct i2c_client *client = ec_dev->priv;
 182         int ret = -ENOMEM;
 183         int i;
 184         int len;
 185         int packet_len;
 186         u8 *out_buf = NULL;
 187         u8 *in_buf = NULL;
 188         u8 sum;
 189         struct i2c_msg i2c_msg[2];
 190 
 191         i2c_msg[0].addr = client->addr;
 192         i2c_msg[0].flags = 0;
 193         i2c_msg[1].addr = client->addr;
 194         i2c_msg[1].flags = I2C_M_RD;
 195 
 196         /*
 197          * allocate larger packet (one byte for checksum, one byte for
 198          * length, and one for result code)
 199          */
 200         packet_len = msg->insize + 3;
 201         in_buf = kzalloc(packet_len, GFP_KERNEL);
 202         if (!in_buf)
 203                 goto done;
 204         i2c_msg[1].len = packet_len;
 205         i2c_msg[1].buf = (char *)in_buf;
 206 
 207         /*
 208          * allocate larger packet (one byte for checksum, one for
 209          * command code, one for length, and one for command version)
 210          */
 211         packet_len = msg->outsize + 4;
 212         out_buf = kzalloc(packet_len, GFP_KERNEL);
 213         if (!out_buf)
 214                 goto done;
 215         i2c_msg[0].len = packet_len;
 216         i2c_msg[0].buf = (char *)out_buf;
 217 
 218         out_buf[0] = EC_CMD_VERSION0 + msg->version;
 219         out_buf[1] = msg->command;
 220         out_buf[2] = msg->outsize;
 221 
 222         /* copy message payload and compute checksum */
 223         sum = out_buf[0] + out_buf[1] + out_buf[2];
 224         for (i = 0; i < msg->outsize; i++) {
 225                 out_buf[3 + i] = msg->data[i];
 226                 sum += out_buf[3 + i];
 227         }
 228         out_buf[3 + msg->outsize] = sum;
 229 
 230         /* send command to EC and read answer */
 231         ret = i2c_transfer(client->adapter, i2c_msg, 2);
 232         if (ret < 0) {
 233                 dev_err(ec_dev->dev, "i2c transfer failed: %d\n", ret);
 234                 goto done;
 235         } else if (ret != 2) {
 236                 dev_err(ec_dev->dev, "failed to get response: %d\n", ret);
 237                 ret = -EIO;
 238                 goto done;
 239         }
 240 
 241         /* check response error code */
 242         msg->result = i2c_msg[1].buf[0];
 243         ret = cros_ec_check_result(ec_dev, msg);
 244         if (ret)
 245                 goto done;
 246 
 247         len = in_buf[1];
 248         if (len > msg->insize) {
 249                 dev_err(ec_dev->dev, "packet too long (%d bytes, expected %d)",
 250                         len, msg->insize);
 251                 ret = -ENOSPC;
 252                 goto done;
 253         }
 254 
 255         /* copy response packet payload and compute checksum */
 256         sum = in_buf[0] + in_buf[1];
 257         for (i = 0; i < len; i++) {
 258                 msg->data[i] = in_buf[2 + i];
 259                 sum += in_buf[2 + i];
 260         }
 261         dev_dbg(ec_dev->dev, "packet: %*ph, sum = %02x\n",
 262                 i2c_msg[1].len, in_buf, sum);
 263         if (sum != in_buf[2 + len]) {
 264                 dev_err(ec_dev->dev, "bad packet checksum\n");
 265                 ret = -EBADMSG;
 266                 goto done;
 267         }
 268 
 269         ret = len;
 270 done:
 271         kfree(in_buf);
 272         kfree(out_buf);
 273         if (msg->command == EC_CMD_REBOOT_EC)
 274                 msleep(EC_REBOOT_DELAY_MS);
 275 
 276         return ret;
 277 }
 278 
 279 static int cros_ec_i2c_probe(struct i2c_client *client,
 280                              const struct i2c_device_id *dev_id)
 281 {
 282         struct device *dev = &client->dev;
 283         struct cros_ec_device *ec_dev = NULL;
 284         int err;
 285 
 286         ec_dev = devm_kzalloc(dev, sizeof(*ec_dev), GFP_KERNEL);
 287         if (!ec_dev)
 288                 return -ENOMEM;
 289 
 290         i2c_set_clientdata(client, ec_dev);
 291         ec_dev->dev = dev;
 292         ec_dev->priv = client;
 293         ec_dev->irq = client->irq;
 294         ec_dev->cmd_xfer = cros_ec_cmd_xfer_i2c;
 295         ec_dev->pkt_xfer = cros_ec_pkt_xfer_i2c;
 296         ec_dev->phys_name = client->adapter->name;
 297         ec_dev->din_size = sizeof(struct ec_host_response_i2c) +
 298                            sizeof(struct ec_response_get_protocol_info);
 299         ec_dev->dout_size = sizeof(struct ec_host_request_i2c);
 300 
 301         err = cros_ec_register(ec_dev);
 302         if (err) {
 303                 dev_err(dev, "cannot register EC\n");
 304                 return err;
 305         }
 306 
 307         return 0;
 308 }
 309 
 310 static int cros_ec_i2c_remove(struct i2c_client *client)
 311 {
 312         struct cros_ec_device *ec_dev = i2c_get_clientdata(client);
 313 
 314         return cros_ec_unregister(ec_dev);
 315 }
 316 
 317 #ifdef CONFIG_PM_SLEEP
 318 static int cros_ec_i2c_suspend(struct device *dev)
 319 {
 320         struct cros_ec_device *ec_dev = to_ec_dev(dev);
 321 
 322         return cros_ec_suspend(ec_dev);
 323 }
 324 
 325 static int cros_ec_i2c_resume(struct device *dev)
 326 {
 327         struct cros_ec_device *ec_dev = to_ec_dev(dev);
 328 
 329         return cros_ec_resume(ec_dev);
 330 }
 331 #endif
 332 
 333 static const struct dev_pm_ops cros_ec_i2c_pm_ops = {
 334         SET_LATE_SYSTEM_SLEEP_PM_OPS(cros_ec_i2c_suspend, cros_ec_i2c_resume)
 335 };
 336 
 337 #ifdef CONFIG_OF
 338 static const struct of_device_id cros_ec_i2c_of_match[] = {
 339         { .compatible = "google,cros-ec-i2c", },
 340         { /* sentinel */ },
 341 };
 342 MODULE_DEVICE_TABLE(of, cros_ec_i2c_of_match);
 343 #endif
 344 
 345 static const struct i2c_device_id cros_ec_i2c_id[] = {
 346         { "cros-ec-i2c", 0 },
 347         { }
 348 };
 349 MODULE_DEVICE_TABLE(i2c, cros_ec_i2c_id);
 350 
 351 #ifdef CONFIG_ACPI
 352 static const struct acpi_device_id cros_ec_i2c_acpi_id[] = {
 353         { "GOOG0008", 0 },
 354         { /* sentinel */ }
 355 };
 356 MODULE_DEVICE_TABLE(acpi, cros_ec_i2c_acpi_id);
 357 #endif
 358 
 359 static struct i2c_driver cros_ec_driver = {
 360         .driver = {
 361                 .name   = "cros-ec-i2c",
 362                 .acpi_match_table = ACPI_PTR(cros_ec_i2c_acpi_id),
 363                 .of_match_table = of_match_ptr(cros_ec_i2c_of_match),
 364                 .pm     = &cros_ec_i2c_pm_ops,
 365         },
 366         .probe          = cros_ec_i2c_probe,
 367         .remove         = cros_ec_i2c_remove,
 368         .id_table       = cros_ec_i2c_id,
 369 };
 370 
 371 module_i2c_driver(cros_ec_driver);
 372 
 373 MODULE_LICENSE("GPL v2");
 374 MODULE_DESCRIPTION("I2C interface for ChromeOS Embedded Controller");

/* [<][>][^][v][top][bottom][index][help] */