root/drivers/platform/chrome/cros_ec_ishtp.c

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

DEFINITIONS

This source file includes following definitions.
  1. ish_evt_handler
  2. ish_send
  3. process_recv
  4. ish_event_cb
  5. cros_ish_init
  6. cros_ish_deinit
  7. prepare_cros_ec_rx
  8. cros_ec_pkt_xfer_ish
  9. cros_ec_dev_init
  10. reset_handler
  11. cros_ec_ishtp_probe
  12. cros_ec_ishtp_remove
  13. cros_ec_ishtp_reset
  14. cros_ec_ishtp_suspend
  15. cros_ec_ishtp_resume
  16. cros_ec_ishtp_mod_init
  17. cros_ec_ishtp_mod_exit

   1 // SPDX-License-Identifier: GPL-2.0
   2 // ISHTP interface for ChromeOS Embedded Controller
   3 //
   4 // Copyright (c) 2019, Intel Corporation.
   5 //
   6 // ISHTP client driver for talking to the Chrome OS EC firmware running
   7 // on Intel Integrated Sensor Hub (ISH) using the ISH Transport protocol
   8 // (ISH-TP).
   9 
  10 #include <linux/delay.h>
  11 #include <linux/module.h>
  12 #include <linux/pci.h>
  13 #include <linux/platform_data/cros_ec_commands.h>
  14 #include <linux/platform_data/cros_ec_proto.h>
  15 #include <linux/intel-ish-client-if.h>
  16 
  17 /*
  18  * ISH TX/RX ring buffer pool size
  19  *
  20  * The AP->ISH messages and corresponding ISH->AP responses are
  21  * serialized. We need 1 TX and 1 RX buffer for these.
  22  *
  23  * The MKBP ISH->AP events are serialized. We need one additional RX
  24  * buffer for them.
  25  */
  26 #define CROS_ISH_CL_TX_RING_SIZE                8
  27 #define CROS_ISH_CL_RX_RING_SIZE                8
  28 
  29 /* ISH CrOS EC Host Commands */
  30 enum cros_ec_ish_channel {
  31         CROS_EC_COMMAND = 1,                    /* AP->ISH message */
  32         CROS_MKBP_EVENT = 2,                    /* ISH->AP events */
  33 };
  34 
  35 /*
  36  * ISH firmware timeout for 1 message send failure is 1Hz, and the
  37  * firmware will retry 2 times, so 3Hz is used for timeout.
  38  */
  39 #define ISHTP_SEND_TIMEOUT                      (3 * HZ)
  40 
  41 /* ISH Transport CrOS EC ISH client unique GUID */
  42 static const guid_t cros_ish_guid =
  43         GUID_INIT(0x7b7154d0, 0x56f4, 0x4bdc,
  44                   0xb0, 0xd8, 0x9e, 0x7c, 0xda, 0xe0, 0xd6, 0xa0);
  45 
  46 struct header {
  47         u8 channel;
  48         u8 status;
  49         u8 reserved[2];
  50 } __packed;
  51 
  52 struct cros_ish_out_msg {
  53         struct header hdr;
  54         struct ec_host_request ec_request;
  55 } __packed;
  56 
  57 struct cros_ish_in_msg {
  58         struct header hdr;
  59         struct ec_host_response ec_response;
  60 } __packed;
  61 
  62 #define IN_MSG_EC_RESPONSE_PREAMBLE                                     \
  63         offsetof(struct cros_ish_in_msg, ec_response)
  64 
  65 #define OUT_MSG_EC_REQUEST_PREAMBLE                                     \
  66         offsetof(struct cros_ish_out_msg, ec_request)
  67 
  68 #define cl_data_to_dev(client_data) ishtp_device((client_data)->cl_device)
  69 
  70 /*
  71  * The Read-Write Semaphore is used to prevent message TX or RX while
  72  * the ishtp client is being initialized or undergoing reset.
  73  *
  74  * The readers are the kernel function calls responsible for IA->ISH
  75  * and ISH->AP messaging.
  76  *
  77  * The writers are .reset() and .probe() function.
  78  */
  79 DECLARE_RWSEM(init_lock);
  80 
  81 /**
  82  * struct response_info - Encapsulate firmware response related
  83  * information for passing between function ish_send() and
  84  * process_recv() callback.
  85  *
  86  * @data: Copy the data received from firmware here.
  87  * @max_size: Max size allocated for the @data buffer. If the received
  88  * data exceeds this value, we log an error.
  89  * @size: Actual size of data received from firmware.
  90  * @error: 0 for success, negative error code for a failure in process_recv().
  91  * @received: Set to true on receiving a valid firmware response to host command
  92  * @wait_queue: Wait queue for host to wait for firmware response.
  93  */
  94 struct response_info {
  95         void *data;
  96         size_t max_size;
  97         size_t size;
  98         int error;
  99         bool received;
 100         wait_queue_head_t wait_queue;
 101 };
 102 
 103 /**
 104  * struct ishtp_cl_data - Encapsulate per ISH TP Client.
 105  *
 106  * @cros_ish_cl: ISHTP firmware client instance.
 107  * @cl_device: ISHTP client device instance.
 108  * @response: Response info passing between ish_send() and process_recv().
 109  * @work_ishtp_reset: Work queue reset handling.
 110  * @work_ec_evt: Work queue for EC events.
 111  * @ec_dev: CrOS EC MFD device.
 112  *
 113  * This structure is used to store per client data.
 114  */
 115 struct ishtp_cl_data {
 116         struct ishtp_cl *cros_ish_cl;
 117         struct ishtp_cl_device *cl_device;
 118 
 119         /*
 120          * Used for passing firmware response information between
 121          * ish_send() and process_recv() callback.
 122          */
 123         struct response_info response;
 124 
 125         struct work_struct work_ishtp_reset;
 126         struct work_struct work_ec_evt;
 127         struct cros_ec_device *ec_dev;
 128 };
 129 
 130 /**
 131  * ish_evt_handler - ISH to AP event handler
 132  * @work: Work struct
 133  */
 134 static void ish_evt_handler(struct work_struct *work)
 135 {
 136         struct ishtp_cl_data *client_data =
 137                 container_of(work, struct ishtp_cl_data, work_ec_evt);
 138         struct cros_ec_device *ec_dev = client_data->ec_dev;
 139 
 140         if (cros_ec_get_next_event(ec_dev, NULL) > 0) {
 141                 blocking_notifier_call_chain(&ec_dev->event_notifier,
 142                                              0, ec_dev);
 143         }
 144 }
 145 
 146 /**
 147  * ish_send() - Send message from host to firmware
 148  *
 149  * @client_data: Client data instance
 150  * @out_msg: Message buffer to be sent to firmware
 151  * @out_size: Size of out going message
 152  * @in_msg: Message buffer where the incoming data is copied. This buffer
 153  * is allocated by calling
 154  * @in_size: Max size of incoming message
 155  *
 156  * Return: Number of bytes copied in the in_msg on success, negative
 157  * error code on failure.
 158  */
 159 static int ish_send(struct ishtp_cl_data *client_data,
 160                     u8 *out_msg, size_t out_size,
 161                     u8 *in_msg, size_t in_size)
 162 {
 163         int rv;
 164         struct header *out_hdr = (struct header *)out_msg;
 165         struct ishtp_cl *cros_ish_cl = client_data->cros_ish_cl;
 166 
 167         dev_dbg(cl_data_to_dev(client_data),
 168                 "%s: channel=%02u status=%02u\n",
 169                 __func__, out_hdr->channel, out_hdr->status);
 170 
 171         /* Setup for incoming response */
 172         client_data->response.data = in_msg;
 173         client_data->response.max_size = in_size;
 174         client_data->response.error = 0;
 175         client_data->response.received = false;
 176 
 177         rv = ishtp_cl_send(cros_ish_cl, out_msg, out_size);
 178         if (rv) {
 179                 dev_err(cl_data_to_dev(client_data),
 180                         "ishtp_cl_send error %d\n", rv);
 181                 return rv;
 182         }
 183 
 184         wait_event_interruptible_timeout(client_data->response.wait_queue,
 185                                          client_data->response.received,
 186                                          ISHTP_SEND_TIMEOUT);
 187         if (!client_data->response.received) {
 188                 dev_err(cl_data_to_dev(client_data),
 189                         "Timed out for response to host message\n");
 190                 return -ETIMEDOUT;
 191         }
 192 
 193         if (client_data->response.error < 0)
 194                 return client_data->response.error;
 195 
 196         return client_data->response.size;
 197 }
 198 
 199 /**
 200  * process_recv() - Received and parse incoming packet
 201  * @cros_ish_cl: Client instance to get stats
 202  * @rb_in_proc: Host interface message buffer
 203  *
 204  * Parse the incoming packet. If it is a response packet then it will
 205  * update per instance flags and wake up the caller waiting to for the
 206  * response. If it is an event packet then it will schedule event work.
 207  */
 208 static void process_recv(struct ishtp_cl *cros_ish_cl,
 209                          struct ishtp_cl_rb *rb_in_proc)
 210 {
 211         size_t data_len = rb_in_proc->buf_idx;
 212         struct ishtp_cl_data *client_data =
 213                 ishtp_get_client_data(cros_ish_cl);
 214         struct device *dev = cl_data_to_dev(client_data);
 215         struct cros_ish_in_msg *in_msg =
 216                 (struct cros_ish_in_msg *)rb_in_proc->buffer.data;
 217 
 218         /* Proceed only if reset or init is not in progress */
 219         if (!down_read_trylock(&init_lock)) {
 220                 /* Free the buffer */
 221                 ishtp_cl_io_rb_recycle(rb_in_proc);
 222                 dev_warn(dev,
 223                          "Host is not ready to receive incoming messages\n");
 224                 return;
 225         }
 226 
 227         /*
 228          * All firmware messages contain a header. Check the buffer size
 229          * before accessing elements inside.
 230          */
 231         if (!rb_in_proc->buffer.data) {
 232                 dev_warn(dev, "rb_in_proc->buffer.data returned null");
 233                 client_data->response.error = -EBADMSG;
 234                 goto end_error;
 235         }
 236 
 237         if (data_len < sizeof(struct header)) {
 238                 dev_err(dev, "data size %zu is less than header %zu\n",
 239                         data_len, sizeof(struct header));
 240                 client_data->response.error = -EMSGSIZE;
 241                 goto end_error;
 242         }
 243 
 244         dev_dbg(dev, "channel=%02u status=%02u\n",
 245                 in_msg->hdr.channel, in_msg->hdr.status);
 246 
 247         switch (in_msg->hdr.channel) {
 248         case CROS_EC_COMMAND:
 249                 /* Sanity check */
 250                 if (!client_data->response.data) {
 251                         dev_err(dev,
 252                                 "Receiving buffer is null. Should be allocated by calling function\n");
 253                         client_data->response.error = -EINVAL;
 254                         goto error_wake_up;
 255                 }
 256 
 257                 if (client_data->response.received) {
 258                         dev_err(dev,
 259                                 "Previous firmware message not yet processed\n");
 260                         client_data->response.error = -EINVAL;
 261                         goto error_wake_up;
 262                 }
 263 
 264                 if (data_len > client_data->response.max_size) {
 265                         dev_err(dev,
 266                                 "Received buffer size %zu is larger than allocated buffer %zu\n",
 267                                 data_len, client_data->response.max_size);
 268                         client_data->response.error = -EMSGSIZE;
 269                         goto error_wake_up;
 270                 }
 271 
 272                 if (in_msg->hdr.status) {
 273                         dev_err(dev, "firmware returned status %d\n",
 274                                 in_msg->hdr.status);
 275                         client_data->response.error = -EIO;
 276                         goto error_wake_up;
 277                 }
 278 
 279                 /* Update the actual received buffer size */
 280                 client_data->response.size = data_len;
 281 
 282                 /*
 283                  * Copy the buffer received in firmware response for the
 284                  * calling thread.
 285                  */
 286                 memcpy(client_data->response.data,
 287                        rb_in_proc->buffer.data, data_len);
 288 
 289                 /* Set flag before waking up the caller */
 290                 client_data->response.received = true;
 291 error_wake_up:
 292                 /* Wake the calling thread */
 293                 wake_up_interruptible(&client_data->response.wait_queue);
 294 
 295                 break;
 296 
 297         case CROS_MKBP_EVENT:
 298                 /* The event system doesn't send any data in buffer */
 299                 schedule_work(&client_data->work_ec_evt);
 300 
 301                 break;
 302 
 303         default:
 304                 dev_err(dev, "Invalid channel=%02d\n", in_msg->hdr.channel);
 305         }
 306 
 307 end_error:
 308         /* Free the buffer */
 309         ishtp_cl_io_rb_recycle(rb_in_proc);
 310 
 311         up_read(&init_lock);
 312 }
 313 
 314 /**
 315  * ish_event_cb() - bus driver callback for incoming message
 316  * @cl_device: ISHTP client device for which this message is targeted.
 317  *
 318  * Remove the packet from the list and process the message by calling
 319  * process_recv.
 320  */
 321 static void ish_event_cb(struct ishtp_cl_device *cl_device)
 322 {
 323         struct ishtp_cl_rb *rb_in_proc;
 324         struct ishtp_cl *cros_ish_cl = ishtp_get_drvdata(cl_device);
 325 
 326         while ((rb_in_proc = ishtp_cl_rx_get_rb(cros_ish_cl)) != NULL) {
 327                 /* Decide what to do with received data */
 328                 process_recv(cros_ish_cl, rb_in_proc);
 329         }
 330 }
 331 
 332 /**
 333  * cros_ish_init() - Init function for ISHTP client
 334  * @cros_ish_cl: ISHTP client instance
 335  *
 336  * This function complete the initializtion of the client.
 337  *
 338  * Return: 0 for success, negative error code for failure.
 339  */
 340 static int cros_ish_init(struct ishtp_cl *cros_ish_cl)
 341 {
 342         int rv;
 343         struct ishtp_device *dev;
 344         struct ishtp_fw_client *fw_client;
 345         struct ishtp_cl_data *client_data = ishtp_get_client_data(cros_ish_cl);
 346 
 347         rv = ishtp_cl_link(cros_ish_cl);
 348         if (rv) {
 349                 dev_err(cl_data_to_dev(client_data),
 350                         "ishtp_cl_link failed\n");
 351                 return rv;
 352         }
 353 
 354         dev = ishtp_get_ishtp_device(cros_ish_cl);
 355 
 356         /* Connect to firmware client */
 357         ishtp_set_tx_ring_size(cros_ish_cl, CROS_ISH_CL_TX_RING_SIZE);
 358         ishtp_set_rx_ring_size(cros_ish_cl, CROS_ISH_CL_RX_RING_SIZE);
 359 
 360         fw_client = ishtp_fw_cl_get_client(dev, &cros_ish_guid);
 361         if (!fw_client) {
 362                 dev_err(cl_data_to_dev(client_data),
 363                         "ish client uuid not found\n");
 364                 rv = -ENOENT;
 365                 goto err_cl_unlink;
 366         }
 367 
 368         ishtp_cl_set_fw_client_id(cros_ish_cl,
 369                                   ishtp_get_fw_client_id(fw_client));
 370         ishtp_set_connection_state(cros_ish_cl, ISHTP_CL_CONNECTING);
 371 
 372         rv = ishtp_cl_connect(cros_ish_cl);
 373         if (rv) {
 374                 dev_err(cl_data_to_dev(client_data),
 375                         "client connect fail\n");
 376                 goto err_cl_unlink;
 377         }
 378 
 379         ishtp_register_event_cb(client_data->cl_device, ish_event_cb);
 380         return 0;
 381 
 382 err_cl_unlink:
 383         ishtp_cl_unlink(cros_ish_cl);
 384         return rv;
 385 }
 386 
 387 /**
 388  * cros_ish_deinit() - Deinit function for ISHTP client
 389  * @cros_ish_cl: ISHTP client instance
 390  *
 391  * Unlink and free cros_ec client
 392  */
 393 static void cros_ish_deinit(struct ishtp_cl *cros_ish_cl)
 394 {
 395         ishtp_set_connection_state(cros_ish_cl, ISHTP_CL_DISCONNECTING);
 396         ishtp_cl_disconnect(cros_ish_cl);
 397         ishtp_cl_unlink(cros_ish_cl);
 398         ishtp_cl_flush_queues(cros_ish_cl);
 399 
 400         /* Disband and free all Tx and Rx client-level rings */
 401         ishtp_cl_free(cros_ish_cl);
 402 }
 403 
 404 /**
 405  * prepare_cros_ec_rx() - Check & prepare receive buffer
 406  * @ec_dev: CrOS EC MFD device.
 407  * @in_msg: Incoming message buffer
 408  * @msg: cros_ec command used to send & receive data
 409  *
 410  * Return: 0 for success, negative error code for failure.
 411  *
 412  * Check the received buffer. Convert to cros_ec_command format.
 413  */
 414 static int prepare_cros_ec_rx(struct cros_ec_device *ec_dev,
 415                               const struct cros_ish_in_msg *in_msg,
 416                               struct cros_ec_command *msg)
 417 {
 418         u8 sum = 0;
 419         int i, rv, offset;
 420 
 421         /* Check response error code */
 422         msg->result = in_msg->ec_response.result;
 423         rv = cros_ec_check_result(ec_dev, msg);
 424         if (rv < 0)
 425                 return rv;
 426 
 427         if (in_msg->ec_response.data_len > msg->insize) {
 428                 dev_err(ec_dev->dev, "Packet too long (%d bytes, expected %d)",
 429                         in_msg->ec_response.data_len, msg->insize);
 430                 return -ENOSPC;
 431         }
 432 
 433         /* Copy response packet payload and compute checksum */
 434         for (i = 0; i < sizeof(struct ec_host_response); i++)
 435                 sum += ((u8 *)in_msg)[IN_MSG_EC_RESPONSE_PREAMBLE + i];
 436 
 437         offset = sizeof(struct cros_ish_in_msg);
 438         for (i = 0; i < in_msg->ec_response.data_len; i++)
 439                 sum += msg->data[i] = ((u8 *)in_msg)[offset + i];
 440 
 441         if (sum) {
 442                 dev_dbg(ec_dev->dev, "Bad received packet checksum %d\n", sum);
 443                 return -EBADMSG;
 444         }
 445 
 446         return 0;
 447 }
 448 
 449 static int cros_ec_pkt_xfer_ish(struct cros_ec_device *ec_dev,
 450                                 struct cros_ec_command *msg)
 451 {
 452         int rv;
 453         struct ishtp_cl *cros_ish_cl = ec_dev->priv;
 454         struct ishtp_cl_data *client_data = ishtp_get_client_data(cros_ish_cl);
 455         struct device *dev = cl_data_to_dev(client_data);
 456         struct cros_ish_in_msg *in_msg = (struct cros_ish_in_msg *)ec_dev->din;
 457         struct cros_ish_out_msg *out_msg =
 458                 (struct cros_ish_out_msg *)ec_dev->dout;
 459         size_t in_size = sizeof(struct cros_ish_in_msg) + msg->insize;
 460         size_t out_size = sizeof(struct cros_ish_out_msg) + msg->outsize;
 461 
 462         /* Sanity checks */
 463         if (in_size > ec_dev->din_size) {
 464                 dev_err(dev,
 465                         "Incoming payload size %zu is too large for ec_dev->din_size %d\n",
 466                         in_size, ec_dev->din_size);
 467                 return -EMSGSIZE;
 468         }
 469 
 470         if (out_size > ec_dev->dout_size) {
 471                 dev_err(dev,
 472                         "Outgoing payload size %zu is too large for ec_dev->dout_size %d\n",
 473                         out_size, ec_dev->dout_size);
 474                 return -EMSGSIZE;
 475         }
 476 
 477         /* Proceed only if reset-init is not in progress */
 478         if (!down_read_trylock(&init_lock)) {
 479                 dev_warn(dev,
 480                          "Host is not ready to send messages to ISH. Try again\n");
 481                 return -EAGAIN;
 482         }
 483 
 484         /* Prepare the package to be sent over ISH TP */
 485         out_msg->hdr.channel = CROS_EC_COMMAND;
 486         out_msg->hdr.status = 0;
 487 
 488         ec_dev->dout += OUT_MSG_EC_REQUEST_PREAMBLE;
 489         cros_ec_prepare_tx(ec_dev, msg);
 490         ec_dev->dout -= OUT_MSG_EC_REQUEST_PREAMBLE;
 491 
 492         dev_dbg(dev,
 493                 "out_msg: struct_ver=0x%x checksum=0x%x command=0x%x command_ver=0x%x data_len=0x%x\n",
 494                 out_msg->ec_request.struct_version,
 495                 out_msg->ec_request.checksum,
 496                 out_msg->ec_request.command,
 497                 out_msg->ec_request.command_version,
 498                 out_msg->ec_request.data_len);
 499 
 500         /* Send command to ISH EC firmware and read response */
 501         rv = ish_send(client_data,
 502                       (u8 *)out_msg, out_size,
 503                       (u8 *)in_msg, in_size);
 504         if (rv < 0)
 505                 goto end_error;
 506 
 507         rv = prepare_cros_ec_rx(ec_dev, in_msg, msg);
 508         if (rv)
 509                 goto end_error;
 510 
 511         rv = in_msg->ec_response.data_len;
 512 
 513         dev_dbg(dev,
 514                 "in_msg: struct_ver=0x%x checksum=0x%x result=0x%x data_len=0x%x\n",
 515                 in_msg->ec_response.struct_version,
 516                 in_msg->ec_response.checksum,
 517                 in_msg->ec_response.result,
 518                 in_msg->ec_response.data_len);
 519 
 520 end_error:
 521         if (msg->command == EC_CMD_REBOOT_EC)
 522                 msleep(EC_REBOOT_DELAY_MS);
 523 
 524         up_read(&init_lock);
 525 
 526         return rv;
 527 }
 528 
 529 static int cros_ec_dev_init(struct ishtp_cl_data *client_data)
 530 {
 531         struct cros_ec_device *ec_dev;
 532         struct device *dev = cl_data_to_dev(client_data);
 533 
 534         ec_dev = devm_kzalloc(dev, sizeof(*ec_dev), GFP_KERNEL);
 535         if (!ec_dev)
 536                 return -ENOMEM;
 537 
 538         client_data->ec_dev = ec_dev;
 539         dev->driver_data = ec_dev;
 540 
 541         ec_dev->dev = dev;
 542         ec_dev->priv = client_data->cros_ish_cl;
 543         ec_dev->cmd_xfer = NULL;
 544         ec_dev->pkt_xfer = cros_ec_pkt_xfer_ish;
 545         ec_dev->phys_name = dev_name(dev);
 546         ec_dev->din_size = sizeof(struct cros_ish_in_msg) +
 547                            sizeof(struct ec_response_get_protocol_info);
 548         ec_dev->dout_size = sizeof(struct cros_ish_out_msg);
 549 
 550         return cros_ec_register(ec_dev);
 551 }
 552 
 553 static void reset_handler(struct work_struct *work)
 554 {
 555         int rv;
 556         struct device *dev;
 557         struct ishtp_cl *cros_ish_cl;
 558         struct ishtp_cl_device *cl_device;
 559         struct ishtp_cl_data *client_data =
 560                 container_of(work, struct ishtp_cl_data, work_ishtp_reset);
 561 
 562         /* Lock for reset to complete */
 563         down_write(&init_lock);
 564 
 565         cros_ish_cl = client_data->cros_ish_cl;
 566         cl_device = client_data->cl_device;
 567 
 568         /* Unlink, flush queues & start again */
 569         ishtp_cl_unlink(cros_ish_cl);
 570         ishtp_cl_flush_queues(cros_ish_cl);
 571         ishtp_cl_free(cros_ish_cl);
 572 
 573         cros_ish_cl = ishtp_cl_allocate(cl_device);
 574         if (!cros_ish_cl) {
 575                 up_write(&init_lock);
 576                 return;
 577         }
 578 
 579         ishtp_set_drvdata(cl_device, cros_ish_cl);
 580         ishtp_set_client_data(cros_ish_cl, client_data);
 581         client_data->cros_ish_cl = cros_ish_cl;
 582 
 583         rv = cros_ish_init(cros_ish_cl);
 584         if (rv) {
 585                 ishtp_cl_free(cros_ish_cl);
 586                 dev_err(cl_data_to_dev(client_data), "Reset Failed\n");
 587                 up_write(&init_lock);
 588                 return;
 589         }
 590 
 591         /* Refresh ec_dev device pointers */
 592         client_data->ec_dev->priv = client_data->cros_ish_cl;
 593         dev = cl_data_to_dev(client_data);
 594         dev->driver_data = client_data->ec_dev;
 595 
 596         dev_info(cl_data_to_dev(client_data), "Chrome EC ISH reset done\n");
 597 
 598         up_write(&init_lock);
 599 }
 600 
 601 /**
 602  * cros_ec_ishtp_probe() - ISHTP client driver probe callback
 603  * @cl_device: ISHTP client device instance
 604  *
 605  * Return: 0 for success, negative error code for failure.
 606  */
 607 static int cros_ec_ishtp_probe(struct ishtp_cl_device *cl_device)
 608 {
 609         int rv;
 610         struct ishtp_cl *cros_ish_cl;
 611         struct ishtp_cl_data *client_data =
 612                 devm_kzalloc(ishtp_device(cl_device),
 613                              sizeof(*client_data), GFP_KERNEL);
 614         if (!client_data)
 615                 return -ENOMEM;
 616 
 617         /* Lock for initialization to complete */
 618         down_write(&init_lock);
 619 
 620         cros_ish_cl = ishtp_cl_allocate(cl_device);
 621         if (!cros_ish_cl) {
 622                 rv = -ENOMEM;
 623                 goto end_ishtp_cl_alloc_error;
 624         }
 625 
 626         ishtp_set_drvdata(cl_device, cros_ish_cl);
 627         ishtp_set_client_data(cros_ish_cl, client_data);
 628         client_data->cros_ish_cl = cros_ish_cl;
 629         client_data->cl_device = cl_device;
 630 
 631         init_waitqueue_head(&client_data->response.wait_queue);
 632 
 633         INIT_WORK(&client_data->work_ishtp_reset,
 634                   reset_handler);
 635         INIT_WORK(&client_data->work_ec_evt,
 636                   ish_evt_handler);
 637 
 638         rv = cros_ish_init(cros_ish_cl);
 639         if (rv)
 640                 goto end_ishtp_cl_init_error;
 641 
 642         ishtp_get_device(cl_device);
 643 
 644         up_write(&init_lock);
 645 
 646         /* Register croc_ec_dev mfd */
 647         rv = cros_ec_dev_init(client_data);
 648         if (rv)
 649                 goto end_cros_ec_dev_init_error;
 650 
 651         return 0;
 652 
 653 end_cros_ec_dev_init_error:
 654         ishtp_set_connection_state(cros_ish_cl, ISHTP_CL_DISCONNECTING);
 655         ishtp_cl_disconnect(cros_ish_cl);
 656         ishtp_cl_unlink(cros_ish_cl);
 657         ishtp_cl_flush_queues(cros_ish_cl);
 658         ishtp_put_device(cl_device);
 659 end_ishtp_cl_init_error:
 660         ishtp_cl_free(cros_ish_cl);
 661 end_ishtp_cl_alloc_error:
 662         up_write(&init_lock);
 663         return rv;
 664 }
 665 
 666 /**
 667  * cros_ec_ishtp_remove() - ISHTP client driver remove callback
 668  * @cl_device: ISHTP client device instance
 669  *
 670  * Return: 0
 671  */
 672 static int cros_ec_ishtp_remove(struct ishtp_cl_device *cl_device)
 673 {
 674         struct ishtp_cl *cros_ish_cl = ishtp_get_drvdata(cl_device);
 675         struct ishtp_cl_data *client_data = ishtp_get_client_data(cros_ish_cl);
 676 
 677         cancel_work_sync(&client_data->work_ishtp_reset);
 678         cancel_work_sync(&client_data->work_ec_evt);
 679         cros_ish_deinit(cros_ish_cl);
 680         ishtp_put_device(cl_device);
 681 
 682         return 0;
 683 }
 684 
 685 /**
 686  * cros_ec_ishtp_reset() - ISHTP client driver reset callback
 687  * @cl_device: ISHTP client device instance
 688  *
 689  * Return: 0
 690  */
 691 static int cros_ec_ishtp_reset(struct ishtp_cl_device *cl_device)
 692 {
 693         struct ishtp_cl *cros_ish_cl = ishtp_get_drvdata(cl_device);
 694         struct ishtp_cl_data *client_data = ishtp_get_client_data(cros_ish_cl);
 695 
 696         schedule_work(&client_data->work_ishtp_reset);
 697 
 698         return 0;
 699 }
 700 
 701 /**
 702  * cros_ec_ishtp_suspend() - ISHTP client driver suspend callback
 703  * @device: device instance
 704  *
 705  * Return: 0 for success, negative error code for failure.
 706  */
 707 static int __maybe_unused cros_ec_ishtp_suspend(struct device *device)
 708 {
 709         struct ishtp_cl_device *cl_device = ishtp_dev_to_cl_device(device);
 710         struct ishtp_cl *cros_ish_cl = ishtp_get_drvdata(cl_device);
 711         struct ishtp_cl_data *client_data = ishtp_get_client_data(cros_ish_cl);
 712 
 713         return cros_ec_suspend(client_data->ec_dev);
 714 }
 715 
 716 /**
 717  * cros_ec_ishtp_resume() - ISHTP client driver resume callback
 718  * @device: device instance
 719  *
 720  * Return: 0 for success, negative error code for failure.
 721  */
 722 static int __maybe_unused cros_ec_ishtp_resume(struct device *device)
 723 {
 724         struct ishtp_cl_device *cl_device = ishtp_dev_to_cl_device(device);
 725         struct ishtp_cl *cros_ish_cl = ishtp_get_drvdata(cl_device);
 726         struct ishtp_cl_data *client_data = ishtp_get_client_data(cros_ish_cl);
 727 
 728         return cros_ec_resume(client_data->ec_dev);
 729 }
 730 
 731 static SIMPLE_DEV_PM_OPS(cros_ec_ishtp_pm_ops, cros_ec_ishtp_suspend,
 732                          cros_ec_ishtp_resume);
 733 
 734 static struct ishtp_cl_driver   cros_ec_ishtp_driver = {
 735         .name = "cros_ec_ishtp",
 736         .guid = &cros_ish_guid,
 737         .probe = cros_ec_ishtp_probe,
 738         .remove = cros_ec_ishtp_remove,
 739         .reset = cros_ec_ishtp_reset,
 740         .driver = {
 741                 .pm = &cros_ec_ishtp_pm_ops,
 742         },
 743 };
 744 
 745 static int __init cros_ec_ishtp_mod_init(void)
 746 {
 747         return ishtp_cl_driver_register(&cros_ec_ishtp_driver, THIS_MODULE);
 748 }
 749 
 750 static void __exit cros_ec_ishtp_mod_exit(void)
 751 {
 752         ishtp_cl_driver_unregister(&cros_ec_ishtp_driver);
 753 }
 754 
 755 module_init(cros_ec_ishtp_mod_init);
 756 module_exit(cros_ec_ishtp_mod_exit);
 757 
 758 MODULE_DESCRIPTION("ChromeOS EC ISHTP Client Driver");
 759 MODULE_AUTHOR("Rushikesh S Kadam <rushikesh.s.kadam@intel.com>");
 760 
 761 MODULE_LICENSE("GPL v2");
 762 MODULE_ALIAS("ishtp:*");

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