root/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c

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

DEFINITIONS

This source file includes following definitions.
  1. cros_ec_get_host_cmd_version_mask
  2. get_default_min_max_freq
  3. cros_ec_sensors_core_init
  4. cros_ec_motion_send_host_cmd
  5. cros_ec_sensors_calibrate
  6. cros_ec_sensors_id
  7. cros_ec_sensors_loc
  8. cros_ec_sensors_idx_to_reg
  9. cros_ec_sensors_cmd_read_u8
  10. cros_ec_sensors_cmd_read_u16
  11. cros_ec_sensors_read_until_not_busy
  12. cros_ec_sensors_read_data_unsafe
  13. cros_ec_sensors_read_lpc
  14. cros_ec_sensors_read_cmd
  15. cros_ec_sensors_capture
  16. cros_ec_sensors_core_read
  17. cros_ec_sensors_core_read_avail
  18. cros_ec_sensors_core_write
  19. cros_ec_sensors_prepare
  20. cros_ec_sensors_complete

   1 // SPDX-License-Identifier: GPL-2.0
   2 /*
   3  * cros_ec_sensors_core - Common function for Chrome OS EC sensor driver.
   4  *
   5  * Copyright (C) 2016 Google, Inc
   6  */
   7 
   8 #include <linux/delay.h>
   9 #include <linux/device.h>
  10 #include <linux/iio/buffer.h>
  11 #include <linux/iio/common/cros_ec_sensors_core.h>
  12 #include <linux/iio/iio.h>
  13 #include <linux/iio/kfifo_buf.h>
  14 #include <linux/iio/trigger_consumer.h>
  15 #include <linux/kernel.h>
  16 #include <linux/mfd/cros_ec.h>
  17 #include <linux/module.h>
  18 #include <linux/slab.h>
  19 #include <linux/platform_data/cros_ec_commands.h>
  20 #include <linux/platform_data/cros_ec_proto.h>
  21 #include <linux/platform_device.h>
  22 
  23 static char *cros_ec_loc[] = {
  24         [MOTIONSENSE_LOC_BASE] = "base",
  25         [MOTIONSENSE_LOC_LID] = "lid",
  26         [MOTIONSENSE_LOC_MAX] = "unknown",
  27 };
  28 
  29 static int cros_ec_get_host_cmd_version_mask(struct cros_ec_device *ec_dev,
  30                                              u16 cmd_offset, u16 cmd, u32 *mask)
  31 {
  32         int ret;
  33         struct {
  34                 struct cros_ec_command msg;
  35                 union {
  36                         struct ec_params_get_cmd_versions params;
  37                         struct ec_response_get_cmd_versions resp;
  38                 };
  39         } __packed buf = {
  40                 .msg = {
  41                         .command = EC_CMD_GET_CMD_VERSIONS + cmd_offset,
  42                         .insize = sizeof(struct ec_response_get_cmd_versions),
  43                         .outsize = sizeof(struct ec_params_get_cmd_versions)
  44                         },
  45                 .params = {.cmd = cmd}
  46         };
  47 
  48         ret = cros_ec_cmd_xfer_status(ec_dev, &buf.msg);
  49         if (ret >= 0)
  50                 *mask = buf.resp.version_mask;
  51         return ret;
  52 }
  53 
  54 static void get_default_min_max_freq(enum motionsensor_type type,
  55                                      u32 *min_freq,
  56                                      u32 *max_freq)
  57 {
  58         switch (type) {
  59         case MOTIONSENSE_TYPE_ACCEL:
  60         case MOTIONSENSE_TYPE_GYRO:
  61                 *min_freq = 12500;
  62                 *max_freq = 100000;
  63                 break;
  64         case MOTIONSENSE_TYPE_MAG:
  65                 *min_freq = 5000;
  66                 *max_freq = 25000;
  67                 break;
  68         case MOTIONSENSE_TYPE_PROX:
  69         case MOTIONSENSE_TYPE_LIGHT:
  70                 *min_freq = 100;
  71                 *max_freq = 50000;
  72                 break;
  73         case MOTIONSENSE_TYPE_BARO:
  74                 *min_freq = 250;
  75                 *max_freq = 20000;
  76                 break;
  77         case MOTIONSENSE_TYPE_ACTIVITY:
  78         default:
  79                 *min_freq = 0;
  80                 *max_freq = 0;
  81                 break;
  82         }
  83 }
  84 
  85 int cros_ec_sensors_core_init(struct platform_device *pdev,
  86                               struct iio_dev *indio_dev,
  87                               bool physical_device)
  88 {
  89         struct device *dev = &pdev->dev;
  90         struct cros_ec_sensors_core_state *state = iio_priv(indio_dev);
  91         struct cros_ec_dev *ec = dev_get_drvdata(pdev->dev.parent);
  92         struct cros_ec_sensor_platform *sensor_platform = dev_get_platdata(dev);
  93         u32 ver_mask;
  94         int ret, i;
  95 
  96         platform_set_drvdata(pdev, indio_dev);
  97 
  98         state->ec = ec->ec_dev;
  99         state->msg = devm_kzalloc(&pdev->dev,
 100                                 max((u16)sizeof(struct ec_params_motion_sense),
 101                                 state->ec->max_response), GFP_KERNEL);
 102         if (!state->msg)
 103                 return -ENOMEM;
 104 
 105         state->resp = (struct ec_response_motion_sense *)state->msg->data;
 106 
 107         mutex_init(&state->cmd_lock);
 108 
 109         ret = cros_ec_get_host_cmd_version_mask(state->ec,
 110                                                 ec->cmd_offset,
 111                                                 EC_CMD_MOTION_SENSE_CMD,
 112                                                 &ver_mask);
 113         if (ret < 0)
 114                 return ret;
 115 
 116         /* Set up the host command structure. */
 117         state->msg->version = fls(ver_mask) - 1;
 118         state->msg->command = EC_CMD_MOTION_SENSE_CMD + ec->cmd_offset;
 119         state->msg->outsize = sizeof(struct ec_params_motion_sense);
 120 
 121         indio_dev->dev.parent = &pdev->dev;
 122         indio_dev->name = pdev->name;
 123 
 124         if (physical_device) {
 125                 indio_dev->modes = INDIO_DIRECT_MODE;
 126 
 127                 state->param.cmd = MOTIONSENSE_CMD_INFO;
 128                 state->param.info.sensor_num = sensor_platform->sensor_num;
 129                 ret = cros_ec_motion_send_host_cmd(state, 0);
 130                 if (ret) {
 131                         dev_warn(dev, "Can not access sensor info\n");
 132                         return ret;
 133                 }
 134                 state->type = state->resp->info.type;
 135                 state->loc = state->resp->info.location;
 136 
 137                 /* Set sign vector, only used for backward compatibility. */
 138                 memset(state->sign, 1, CROS_EC_SENSOR_MAX_AXIS);
 139 
 140                 for (i = CROS_EC_SENSOR_X; i < CROS_EC_SENSOR_MAX_AXIS; i++)
 141                         state->calib[i].scale = MOTION_SENSE_DEFAULT_SCALE;
 142 
 143                 /* 0 is a correct value used to stop the device */
 144                 state->frequencies[0] = 0;
 145                 if (state->msg->version < 3) {
 146                         get_default_min_max_freq(state->resp->info.type,
 147                                                  &state->frequencies[1],
 148                                                  &state->frequencies[2]);
 149                 } else {
 150                         state->frequencies[1] =
 151                             state->resp->info_3.min_frequency;
 152                         state->frequencies[2] =
 153                             state->resp->info_3.max_frequency;
 154                 }
 155         }
 156 
 157         return 0;
 158 }
 159 EXPORT_SYMBOL_GPL(cros_ec_sensors_core_init);
 160 
 161 int cros_ec_motion_send_host_cmd(struct cros_ec_sensors_core_state *state,
 162                                  u16 opt_length)
 163 {
 164         int ret;
 165 
 166         if (opt_length)
 167                 state->msg->insize = min(opt_length, state->ec->max_response);
 168         else
 169                 state->msg->insize = state->ec->max_response;
 170 
 171         memcpy(state->msg->data, &state->param, sizeof(state->param));
 172 
 173         ret = cros_ec_cmd_xfer_status(state->ec, state->msg);
 174         if (ret < 0)
 175                 return ret;
 176 
 177         if (ret &&
 178             state->resp != (struct ec_response_motion_sense *)state->msg->data)
 179                 memcpy(state->resp, state->msg->data, ret);
 180 
 181         return 0;
 182 }
 183 EXPORT_SYMBOL_GPL(cros_ec_motion_send_host_cmd);
 184 
 185 static ssize_t cros_ec_sensors_calibrate(struct iio_dev *indio_dev,
 186                 uintptr_t private, const struct iio_chan_spec *chan,
 187                 const char *buf, size_t len)
 188 {
 189         struct cros_ec_sensors_core_state *st = iio_priv(indio_dev);
 190         int ret, i;
 191         bool calibrate;
 192 
 193         ret = strtobool(buf, &calibrate);
 194         if (ret < 0)
 195                 return ret;
 196         if (!calibrate)
 197                 return -EINVAL;
 198 
 199         mutex_lock(&st->cmd_lock);
 200         st->param.cmd = MOTIONSENSE_CMD_PERFORM_CALIB;
 201         ret = cros_ec_motion_send_host_cmd(st, 0);
 202         if (ret != 0) {
 203                 dev_warn(&indio_dev->dev, "Unable to calibrate sensor\n");
 204         } else {
 205                 /* Save values */
 206                 for (i = CROS_EC_SENSOR_X; i < CROS_EC_SENSOR_MAX_AXIS; i++)
 207                         st->calib[i].offset = st->resp->perform_calib.offset[i];
 208         }
 209         mutex_unlock(&st->cmd_lock);
 210 
 211         return ret ? ret : len;
 212 }
 213 
 214 static ssize_t cros_ec_sensors_id(struct iio_dev *indio_dev,
 215                                   uintptr_t private,
 216                                   const struct iio_chan_spec *chan, char *buf)
 217 {
 218         struct cros_ec_sensors_core_state *st = iio_priv(indio_dev);
 219 
 220         return snprintf(buf, PAGE_SIZE, "%d\n", st->param.info.sensor_num);
 221 }
 222 
 223 static ssize_t cros_ec_sensors_loc(struct iio_dev *indio_dev,
 224                 uintptr_t private, const struct iio_chan_spec *chan,
 225                 char *buf)
 226 {
 227         struct cros_ec_sensors_core_state *st = iio_priv(indio_dev);
 228 
 229         return snprintf(buf, PAGE_SIZE, "%s\n", cros_ec_loc[st->loc]);
 230 }
 231 
 232 const struct iio_chan_spec_ext_info cros_ec_sensors_ext_info[] = {
 233         {
 234                 .name = "calibrate",
 235                 .shared = IIO_SHARED_BY_ALL,
 236                 .write = cros_ec_sensors_calibrate
 237         },
 238         {
 239                 .name = "id",
 240                 .shared = IIO_SHARED_BY_ALL,
 241                 .read = cros_ec_sensors_id
 242         },
 243         {
 244                 .name = "location",
 245                 .shared = IIO_SHARED_BY_ALL,
 246                 .read = cros_ec_sensors_loc
 247         },
 248         { },
 249 };
 250 EXPORT_SYMBOL_GPL(cros_ec_sensors_ext_info);
 251 
 252 /**
 253  * cros_ec_sensors_idx_to_reg - convert index into offset in shared memory
 254  * @st:         pointer to state information for device
 255  * @idx:        sensor index (should be element of enum sensor_index)
 256  *
 257  * Return:      address to read at
 258  */
 259 static unsigned int cros_ec_sensors_idx_to_reg(
 260                                         struct cros_ec_sensors_core_state *st,
 261                                         unsigned int idx)
 262 {
 263         /*
 264          * When using LPC interface, only space for 2 Accel and one Gyro.
 265          * First halfword of MOTIONSENSE_TYPE_ACCEL is used by angle.
 266          */
 267         if (st->type == MOTIONSENSE_TYPE_ACCEL)
 268                 return EC_MEMMAP_ACC_DATA + sizeof(u16) *
 269                         (1 + idx + st->param.info.sensor_num *
 270                          CROS_EC_SENSOR_MAX_AXIS);
 271 
 272         return EC_MEMMAP_GYRO_DATA + sizeof(u16) * idx;
 273 }
 274 
 275 static int cros_ec_sensors_cmd_read_u8(struct cros_ec_device *ec,
 276                                        unsigned int offset, u8 *dest)
 277 {
 278         return ec->cmd_readmem(ec, offset, 1, dest);
 279 }
 280 
 281 static int cros_ec_sensors_cmd_read_u16(struct cros_ec_device *ec,
 282                                          unsigned int offset, u16 *dest)
 283 {
 284         __le16 tmp;
 285         int ret = ec->cmd_readmem(ec, offset, 2, &tmp);
 286 
 287         if (ret >= 0)
 288                 *dest = le16_to_cpu(tmp);
 289 
 290         return ret;
 291 }
 292 
 293 /**
 294  * cros_ec_sensors_read_until_not_busy() - read until is not busy
 295  *
 296  * @st: pointer to state information for device
 297  *
 298  * Read from EC status byte until it reads not busy.
 299  * Return: 8-bit status if ok, -errno on failure.
 300  */
 301 static int cros_ec_sensors_read_until_not_busy(
 302                                         struct cros_ec_sensors_core_state *st)
 303 {
 304         struct cros_ec_device *ec = st->ec;
 305         u8 status;
 306         int ret, attempts = 0;
 307 
 308         ret = cros_ec_sensors_cmd_read_u8(ec, EC_MEMMAP_ACC_STATUS, &status);
 309         if (ret < 0)
 310                 return ret;
 311 
 312         while (status & EC_MEMMAP_ACC_STATUS_BUSY_BIT) {
 313                 /* Give up after enough attempts, return error. */
 314                 if (attempts++ >= 50)
 315                         return -EIO;
 316 
 317                 /* Small delay every so often. */
 318                 if (attempts % 5 == 0)
 319                         msleep(25);
 320 
 321                 ret = cros_ec_sensors_cmd_read_u8(ec, EC_MEMMAP_ACC_STATUS,
 322                                                   &status);
 323                 if (ret < 0)
 324                         return ret;
 325         }
 326 
 327         return status;
 328 }
 329 
 330 /**
 331  * read_ec_sensors_data_unsafe() - read acceleration data from EC shared memory
 332  * @indio_dev:  pointer to IIO device
 333  * @scan_mask:  bitmap of the sensor indices to scan
 334  * @data:       location to store data
 335  *
 336  * This is the unsafe function for reading the EC data. It does not guarantee
 337  * that the EC will not modify the data as it is being read in.
 338  *
 339  * Return: 0 on success, -errno on failure.
 340  */
 341 static int cros_ec_sensors_read_data_unsafe(struct iio_dev *indio_dev,
 342                          unsigned long scan_mask, s16 *data)
 343 {
 344         struct cros_ec_sensors_core_state *st = iio_priv(indio_dev);
 345         struct cros_ec_device *ec = st->ec;
 346         unsigned int i;
 347         int ret;
 348 
 349         /* Read all sensors enabled in scan_mask. Each value is 2 bytes. */
 350         for_each_set_bit(i, &scan_mask, indio_dev->masklength) {
 351                 ret = cros_ec_sensors_cmd_read_u16(ec,
 352                                              cros_ec_sensors_idx_to_reg(st, i),
 353                                              data);
 354                 if (ret < 0)
 355                         return ret;
 356 
 357                 *data *= st->sign[i];
 358                 data++;
 359         }
 360 
 361         return 0;
 362 }
 363 
 364 /**
 365  * cros_ec_sensors_read_lpc() - read acceleration data from EC shared memory.
 366  * @indio_dev: pointer to IIO device.
 367  * @scan_mask: bitmap of the sensor indices to scan.
 368  * @data: location to store data.
 369  *
 370  * Note: this is the safe function for reading the EC data. It guarantees
 371  * that the data sampled was not modified by the EC while being read.
 372  *
 373  * Return: 0 on success, -errno on failure.
 374  */
 375 int cros_ec_sensors_read_lpc(struct iio_dev *indio_dev,
 376                              unsigned long scan_mask, s16 *data)
 377 {
 378         struct cros_ec_sensors_core_state *st = iio_priv(indio_dev);
 379         struct cros_ec_device *ec = st->ec;
 380         u8 samp_id = 0xff, status = 0;
 381         int ret, attempts = 0;
 382 
 383         /*
 384          * Continually read all data from EC until the status byte after
 385          * all reads reflects that the EC is not busy and the sample id
 386          * matches the sample id from before all reads. This guarantees
 387          * that data read in was not modified by the EC while reading.
 388          */
 389         while ((status & (EC_MEMMAP_ACC_STATUS_BUSY_BIT |
 390                           EC_MEMMAP_ACC_STATUS_SAMPLE_ID_MASK)) != samp_id) {
 391                 /* If we have tried to read too many times, return error. */
 392                 if (attempts++ >= 5)
 393                         return -EIO;
 394 
 395                 /* Read status byte until EC is not busy. */
 396                 ret = cros_ec_sensors_read_until_not_busy(st);
 397                 if (ret < 0)
 398                         return ret;
 399 
 400                 /*
 401                  * Store the current sample id so that we can compare to the
 402                  * sample id after reading the data.
 403                  */
 404                 samp_id = ret & EC_MEMMAP_ACC_STATUS_SAMPLE_ID_MASK;
 405 
 406                 /* Read all EC data, format it, and store it into data. */
 407                 ret = cros_ec_sensors_read_data_unsafe(indio_dev, scan_mask,
 408                                                        data);
 409                 if (ret < 0)
 410                         return ret;
 411 
 412                 /* Read status byte. */
 413                 ret = cros_ec_sensors_cmd_read_u8(ec, EC_MEMMAP_ACC_STATUS,
 414                                                   &status);
 415                 if (ret < 0)
 416                         return ret;
 417         }
 418 
 419         return 0;
 420 }
 421 EXPORT_SYMBOL_GPL(cros_ec_sensors_read_lpc);
 422 
 423 int cros_ec_sensors_read_cmd(struct iio_dev *indio_dev,
 424                              unsigned long scan_mask, s16 *data)
 425 {
 426         struct cros_ec_sensors_core_state *st = iio_priv(indio_dev);
 427         int ret;
 428         unsigned int i;
 429 
 430         /* Read all sensor data through a command. */
 431         st->param.cmd = MOTIONSENSE_CMD_DATA;
 432         ret = cros_ec_motion_send_host_cmd(st, sizeof(st->resp->data));
 433         if (ret != 0) {
 434                 dev_warn(&indio_dev->dev, "Unable to read sensor data\n");
 435                 return ret;
 436         }
 437 
 438         for_each_set_bit(i, &scan_mask, indio_dev->masklength) {
 439                 *data = st->resp->data.data[i];
 440                 data++;
 441         }
 442 
 443         return 0;
 444 }
 445 EXPORT_SYMBOL_GPL(cros_ec_sensors_read_cmd);
 446 
 447 irqreturn_t cros_ec_sensors_capture(int irq, void *p)
 448 {
 449         struct iio_poll_func *pf = p;
 450         struct iio_dev *indio_dev = pf->indio_dev;
 451         struct cros_ec_sensors_core_state *st = iio_priv(indio_dev);
 452         int ret;
 453 
 454         mutex_lock(&st->cmd_lock);
 455 
 456         /* Clear capture data. */
 457         memset(st->samples, 0, indio_dev->scan_bytes);
 458 
 459         /* Read data based on which channels are enabled in scan mask. */
 460         ret = st->read_ec_sensors_data(indio_dev,
 461                                        *(indio_dev->active_scan_mask),
 462                                        (s16 *)st->samples);
 463         if (ret < 0)
 464                 goto done;
 465 
 466         iio_push_to_buffers_with_timestamp(indio_dev, st->samples,
 467                                            iio_get_time_ns(indio_dev));
 468 
 469 done:
 470         /*
 471          * Tell the core we are done with this trigger and ready for the
 472          * next one.
 473          */
 474         iio_trigger_notify_done(indio_dev->trig);
 475 
 476         mutex_unlock(&st->cmd_lock);
 477 
 478         return IRQ_HANDLED;
 479 }
 480 EXPORT_SYMBOL_GPL(cros_ec_sensors_capture);
 481 
 482 int cros_ec_sensors_core_read(struct cros_ec_sensors_core_state *st,
 483                           struct iio_chan_spec const *chan,
 484                           int *val, int *val2, long mask)
 485 {
 486         int ret;
 487 
 488         switch (mask) {
 489         case IIO_CHAN_INFO_SAMP_FREQ:
 490                 st->param.cmd = MOTIONSENSE_CMD_EC_RATE;
 491                 st->param.ec_rate.data =
 492                         EC_MOTION_SENSE_NO_VALUE;
 493 
 494                 ret = cros_ec_motion_send_host_cmd(st, 0);
 495                 if (ret)
 496                         break;
 497 
 498                 *val = st->resp->ec_rate.ret;
 499                 ret = IIO_VAL_INT;
 500                 break;
 501         case IIO_CHAN_INFO_FREQUENCY:
 502                 st->param.cmd = MOTIONSENSE_CMD_SENSOR_ODR;
 503                 st->param.sensor_odr.data =
 504                         EC_MOTION_SENSE_NO_VALUE;
 505 
 506                 ret = cros_ec_motion_send_host_cmd(st, 0);
 507                 if (ret)
 508                         break;
 509 
 510                 *val = st->resp->sensor_odr.ret;
 511                 ret = IIO_VAL_INT;
 512                 break;
 513         default:
 514                 ret = -EINVAL;
 515                 break;
 516         }
 517 
 518         return ret;
 519 }
 520 EXPORT_SYMBOL_GPL(cros_ec_sensors_core_read);
 521 
 522 int cros_ec_sensors_core_read_avail(struct iio_dev *indio_dev,
 523                                     struct iio_chan_spec const *chan,
 524                                     const int **vals,
 525                                     int *type,
 526                                     int *length,
 527                                     long mask)
 528 {
 529         struct cros_ec_sensors_core_state *state = iio_priv(indio_dev);
 530 
 531         switch (mask) {
 532         case IIO_CHAN_INFO_SAMP_FREQ:
 533                 *length = ARRAY_SIZE(state->frequencies);
 534                 *vals = (const int *)&state->frequencies;
 535                 *type = IIO_VAL_INT;
 536                 return IIO_AVAIL_LIST;
 537         }
 538 
 539         return -EINVAL;
 540 }
 541 EXPORT_SYMBOL_GPL(cros_ec_sensors_core_read_avail);
 542 
 543 int cros_ec_sensors_core_write(struct cros_ec_sensors_core_state *st,
 544                                struct iio_chan_spec const *chan,
 545                                int val, int val2, long mask)
 546 {
 547         int ret;
 548 
 549         switch (mask) {
 550         case IIO_CHAN_INFO_FREQUENCY:
 551                 st->param.cmd = MOTIONSENSE_CMD_SENSOR_ODR;
 552                 st->param.sensor_odr.data = val;
 553 
 554                 /* Always roundup, so caller gets at least what it asks for. */
 555                 st->param.sensor_odr.roundup = 1;
 556 
 557                 ret = cros_ec_motion_send_host_cmd(st, 0);
 558                 break;
 559         case IIO_CHAN_INFO_SAMP_FREQ:
 560                 st->param.cmd = MOTIONSENSE_CMD_EC_RATE;
 561                 st->param.ec_rate.data = val;
 562 
 563                 ret = cros_ec_motion_send_host_cmd(st, 0);
 564                 if (ret)
 565                         break;
 566                 st->curr_sampl_freq = val;
 567                 break;
 568         default:
 569                 ret = -EINVAL;
 570                 break;
 571         }
 572         return ret;
 573 }
 574 EXPORT_SYMBOL_GPL(cros_ec_sensors_core_write);
 575 
 576 static int __maybe_unused cros_ec_sensors_prepare(struct device *dev)
 577 {
 578         struct iio_dev *indio_dev = dev_get_drvdata(dev);
 579         struct cros_ec_sensors_core_state *st = iio_priv(indio_dev);
 580 
 581         if (st->curr_sampl_freq == 0)
 582                 return 0;
 583 
 584         /*
 585          * If the sensors are sampled at high frequency, we will not be able to
 586          * sleep. Set sampling to a long period if necessary.
 587          */
 588         if (st->curr_sampl_freq < CROS_EC_MIN_SUSPEND_SAMPLING_FREQUENCY) {
 589                 mutex_lock(&st->cmd_lock);
 590                 st->param.cmd = MOTIONSENSE_CMD_EC_RATE;
 591                 st->param.ec_rate.data = CROS_EC_MIN_SUSPEND_SAMPLING_FREQUENCY;
 592                 cros_ec_motion_send_host_cmd(st, 0);
 593                 mutex_unlock(&st->cmd_lock);
 594         }
 595         return 0;
 596 }
 597 
 598 static void __maybe_unused cros_ec_sensors_complete(struct device *dev)
 599 {
 600         struct iio_dev *indio_dev = dev_get_drvdata(dev);
 601         struct cros_ec_sensors_core_state *st = iio_priv(indio_dev);
 602 
 603         if (st->curr_sampl_freq == 0)
 604                 return;
 605 
 606         if (st->curr_sampl_freq < CROS_EC_MIN_SUSPEND_SAMPLING_FREQUENCY) {
 607                 mutex_lock(&st->cmd_lock);
 608                 st->param.cmd = MOTIONSENSE_CMD_EC_RATE;
 609                 st->param.ec_rate.data = st->curr_sampl_freq;
 610                 cros_ec_motion_send_host_cmd(st, 0);
 611                 mutex_unlock(&st->cmd_lock);
 612         }
 613 }
 614 
 615 const struct dev_pm_ops cros_ec_sensors_pm_ops = {
 616 #ifdef CONFIG_PM_SLEEP
 617         .prepare = cros_ec_sensors_prepare,
 618         .complete = cros_ec_sensors_complete
 619 #endif
 620 };
 621 EXPORT_SYMBOL_GPL(cros_ec_sensors_pm_ops);
 622 
 623 MODULE_DESCRIPTION("ChromeOS EC sensor hub core functions");
 624 MODULE_LICENSE("GPL v2");

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