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

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

DEFINITIONS

This source file includes following definitions.
  1. cros_ec_sensors_read_lid_angle
  2. cros_ec_lid_angle_read
  3. cros_ec_lid_angle_probe

   1 // SPDX-License-Identifier: GPL-2.0
   2 
   3 /*
   4  * cros_ec_lid_angle - Driver for CrOS EC lid angle sensor.
   5  *
   6  * Copyright 2018 Google, Inc
   7  *
   8  * This driver uses the cros-ec interface to communicate with the Chrome OS
   9  * EC about counter sensors. Counters are presented through
  10  * iio sysfs.
  11  */
  12 
  13 #include <linux/delay.h>
  14 #include <linux/device.h>
  15 #include <linux/iio/buffer.h>
  16 #include <linux/iio/common/cros_ec_sensors_core.h>
  17 #include <linux/iio/iio.h>
  18 #include <linux/iio/kfifo_buf.h>
  19 #include <linux/iio/trigger.h>
  20 #include <linux/iio/triggered_buffer.h>
  21 #include <linux/iio/trigger_consumer.h>
  22 #include <linux/kernel.h>
  23 #include <linux/module.h>
  24 #include <linux/platform_data/cros_ec_commands.h>
  25 #include <linux/platform_device.h>
  26 #include <linux/slab.h>
  27 
  28 #define DRV_NAME "cros-ec-lid-angle"
  29 
  30 /*
  31  * One channel for the lid angle, the other for timestamp.
  32  */
  33 static const struct iio_chan_spec cros_ec_lid_angle_channels[] = {
  34         {
  35                 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
  36                 .scan_type.realbits = CROS_EC_SENSOR_BITS,
  37                 .scan_type.storagebits = CROS_EC_SENSOR_BITS,
  38                 .scan_type.sign = 'u',
  39                 .type = IIO_ANGL
  40         },
  41         IIO_CHAN_SOFT_TIMESTAMP(1)
  42 };
  43 
  44 /* State data for ec_sensors iio driver. */
  45 struct cros_ec_lid_angle_state {
  46         /* Shared by all sensors */
  47         struct cros_ec_sensors_core_state core;
  48 };
  49 
  50 static int cros_ec_sensors_read_lid_angle(struct iio_dev *indio_dev,
  51                                           unsigned long scan_mask, s16 *data)
  52 {
  53         struct cros_ec_sensors_core_state *st = iio_priv(indio_dev);
  54         int ret;
  55 
  56         st->param.cmd = MOTIONSENSE_CMD_LID_ANGLE;
  57         ret = cros_ec_motion_send_host_cmd(st, sizeof(st->resp->lid_angle));
  58         if (ret) {
  59                 dev_warn(&indio_dev->dev, "Unable to read lid angle\n");
  60                 return ret;
  61         }
  62 
  63         *data = st->resp->lid_angle.value;
  64         return 0;
  65 }
  66 
  67 static int cros_ec_lid_angle_read(struct iio_dev *indio_dev,
  68                                     struct iio_chan_spec const *chan,
  69                                     int *val, int *val2, long mask)
  70 {
  71         struct cros_ec_lid_angle_state *st = iio_priv(indio_dev);
  72         s16 data;
  73         int ret;
  74 
  75         mutex_lock(&st->core.cmd_lock);
  76         ret = cros_ec_sensors_read_lid_angle(indio_dev, 1, &data);
  77         if (ret == 0) {
  78                 *val = data;
  79                 ret = IIO_VAL_INT;
  80         }
  81         mutex_unlock(&st->core.cmd_lock);
  82         return ret;
  83 }
  84 
  85 static const struct iio_info cros_ec_lid_angle_info = {
  86         .read_raw = &cros_ec_lid_angle_read,
  87 };
  88 
  89 static int cros_ec_lid_angle_probe(struct platform_device *pdev)
  90 {
  91         struct device *dev = &pdev->dev;
  92         struct iio_dev *indio_dev;
  93         struct cros_ec_lid_angle_state *state;
  94         int ret;
  95 
  96         indio_dev = devm_iio_device_alloc(dev, sizeof(*state));
  97         if (!indio_dev)
  98                 return -ENOMEM;
  99 
 100         ret = cros_ec_sensors_core_init(pdev, indio_dev, false);
 101         if (ret)
 102                 return ret;
 103 
 104         indio_dev->info = &cros_ec_lid_angle_info;
 105         state = iio_priv(indio_dev);
 106         indio_dev->channels = cros_ec_lid_angle_channels;
 107         indio_dev->num_channels = ARRAY_SIZE(cros_ec_lid_angle_channels);
 108 
 109         state->core.read_ec_sensors_data = cros_ec_sensors_read_lid_angle;
 110 
 111         ret = devm_iio_triggered_buffer_setup(dev, indio_dev, NULL,
 112                         cros_ec_sensors_capture, NULL);
 113         if (ret)
 114                 return ret;
 115 
 116         return devm_iio_device_register(dev, indio_dev);
 117 }
 118 
 119 static const struct platform_device_id cros_ec_lid_angle_ids[] = {
 120         {
 121                 .name = DRV_NAME,
 122         },
 123         { /* sentinel */ }
 124 };
 125 MODULE_DEVICE_TABLE(platform, cros_ec_lid_angle_ids);
 126 
 127 static struct platform_driver cros_ec_lid_angle_platform_driver = {
 128         .driver = {
 129                 .name   = DRV_NAME,
 130                 .pm     = &cros_ec_sensors_pm_ops,
 131         },
 132         .probe          = cros_ec_lid_angle_probe,
 133         .id_table       = cros_ec_lid_angle_ids,
 134 };
 135 module_platform_driver(cros_ec_lid_angle_platform_driver);
 136 
 137 MODULE_DESCRIPTION("ChromeOS EC driver for reporting convertible lid angle.");
 138 MODULE_LICENSE("GPL v2");

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