211 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * cros_ec_baro - Driver for barometer sensor behind CrosEC.4 *5 * Copyright (C) 2017 Google, Inc6 */7 8#include <linux/device.h>9#include <linux/iio/buffer.h>10#include <linux/iio/common/cros_ec_sensors_core.h>11#include <linux/iio/iio.h>12#include <linux/iio/kfifo_buf.h>13#include <linux/iio/trigger.h>14#include <linux/iio/triggered_buffer.h>15#include <linux/iio/trigger_consumer.h>16#include <linux/kernel.h>17#include <linux/mod_devicetable.h>18#include <linux/module.h>19#include <linux/slab.h>20#include <linux/platform_data/cros_ec_commands.h>21#include <linux/platform_data/cros_ec_proto.h>22#include <linux/platform_device.h>23 24/*25 * One channel for pressure, the other for timestamp.26 */27#define CROS_EC_BARO_MAX_CHANNELS (1 + 1)28 29/* State data for ec_sensors iio driver. */30struct cros_ec_baro_state {31 /* Shared by all sensors */32 struct cros_ec_sensors_core_state core;33 34 struct iio_chan_spec channels[CROS_EC_BARO_MAX_CHANNELS];35};36 37static int cros_ec_baro_read(struct iio_dev *indio_dev,38 struct iio_chan_spec const *chan,39 int *val, int *val2, long mask)40{41 struct cros_ec_baro_state *st = iio_priv(indio_dev);42 u16 data = 0;43 int ret;44 int idx = chan->scan_index;45 46 mutex_lock(&st->core.cmd_lock);47 48 switch (mask) {49 case IIO_CHAN_INFO_RAW:50 ret = cros_ec_sensors_read_cmd(indio_dev, 1 << idx,51 (s16 *)&data);52 if (ret)53 break;54 55 *val = data;56 ret = IIO_VAL_INT;57 break;58 case IIO_CHAN_INFO_SCALE:59 st->core.param.cmd = MOTIONSENSE_CMD_SENSOR_RANGE;60 st->core.param.sensor_range.data = EC_MOTION_SENSE_NO_VALUE;61 62 ret = cros_ec_motion_send_host_cmd(&st->core, 0);63 if (ret)64 break;65 66 *val = st->core.resp->sensor_range.ret;67 68 /* scale * in_pressure_raw --> kPa */69 *val2 = 10 << CROS_EC_SENSOR_BITS;70 ret = IIO_VAL_FRACTIONAL;71 break;72 default:73 ret = cros_ec_sensors_core_read(&st->core, chan, val, val2,74 mask);75 break;76 }77 78 mutex_unlock(&st->core.cmd_lock);79 80 return ret;81}82 83static int cros_ec_baro_write(struct iio_dev *indio_dev,84 struct iio_chan_spec const *chan,85 int val, int val2, long mask)86{87 struct cros_ec_baro_state *st = iio_priv(indio_dev);88 int ret = 0;89 90 mutex_lock(&st->core.cmd_lock);91 92 switch (mask) {93 case IIO_CHAN_INFO_SCALE:94 st->core.param.cmd = MOTIONSENSE_CMD_SENSOR_RANGE;95 st->core.param.sensor_range.data = val;96 97 /* Always roundup, so caller gets at least what it asks for. */98 st->core.param.sensor_range.roundup = 1;99 100 ret = cros_ec_motion_send_host_cmd(&st->core, 0);101 if (ret == 0) {102 st->core.range_updated = true;103 st->core.curr_range = val;104 }105 break;106 default:107 ret = cros_ec_sensors_core_write(&st->core, chan, val, val2,108 mask);109 break;110 }111 112 mutex_unlock(&st->core.cmd_lock);113 114 return ret;115}116 117static const struct iio_info cros_ec_baro_info = {118 .read_raw = &cros_ec_baro_read,119 .write_raw = &cros_ec_baro_write,120 .read_avail = &cros_ec_sensors_core_read_avail,121};122 123static int cros_ec_baro_probe(struct platform_device *pdev)124{125 struct device *dev = &pdev->dev;126 struct cros_ec_dev *ec_dev = dev_get_drvdata(dev->parent);127 struct iio_dev *indio_dev;128 struct cros_ec_baro_state *state;129 struct iio_chan_spec *channel;130 int ret;131 132 if (!ec_dev || !ec_dev->ec_dev) {133 dev_warn(dev, "No CROS EC device found.\n");134 return -EINVAL;135 }136 137 indio_dev = devm_iio_device_alloc(dev, sizeof(*state));138 if (!indio_dev)139 return -ENOMEM;140 141 ret = cros_ec_sensors_core_init(pdev, indio_dev, true,142 cros_ec_sensors_capture);143 if (ret)144 return ret;145 146 indio_dev->info = &cros_ec_baro_info;147 state = iio_priv(indio_dev);148 channel = state->channels;149 /* Common part */150 channel->info_mask_separate = BIT(IIO_CHAN_INFO_RAW);151 channel->info_mask_shared_by_all =152 BIT(IIO_CHAN_INFO_SCALE) |153 BIT(IIO_CHAN_INFO_SAMP_FREQ);154 channel->info_mask_shared_by_all_available =155 BIT(IIO_CHAN_INFO_SAMP_FREQ);156 channel->scan_type.realbits = CROS_EC_SENSOR_BITS;157 channel->scan_type.storagebits = CROS_EC_SENSOR_BITS;158 channel->scan_type.shift = 0;159 channel->scan_index = 0;160 channel->ext_info = cros_ec_sensors_ext_info;161 channel->scan_type.sign = 'u';162 163 /* Sensor specific */164 switch (state->core.type) {165 case MOTIONSENSE_TYPE_BARO:166 channel->type = IIO_PRESSURE;167 break;168 default:169 dev_warn(dev, "Unknown motion sensor\n");170 return -EINVAL;171 }172 173 /* Timestamp */174 channel++;175 channel->type = IIO_TIMESTAMP;176 channel->channel = -1;177 channel->scan_index = 1;178 channel->scan_type.sign = 's';179 channel->scan_type.realbits = 64;180 channel->scan_type.storagebits = 64;181 182 indio_dev->channels = state->channels;183 indio_dev->num_channels = CROS_EC_BARO_MAX_CHANNELS;184 185 state->core.read_ec_sensors_data = cros_ec_sensors_read_cmd;186 187 return cros_ec_sensors_core_register(dev, indio_dev,188 cros_ec_sensors_push_data);189}190 191static const struct platform_device_id cros_ec_baro_ids[] = {192 {193 .name = "cros-ec-baro",194 },195 { /* sentinel */ }196};197MODULE_DEVICE_TABLE(platform, cros_ec_baro_ids);198 199static struct platform_driver cros_ec_baro_platform_driver = {200 .driver = {201 .name = "cros-ec-baro",202 .pm = &cros_ec_sensors_pm_ops,203 },204 .probe = cros_ec_baro_probe,205 .id_table = cros_ec_baro_ids,206};207module_platform_driver(cros_ec_baro_platform_driver);208 209MODULE_DESCRIPTION("ChromeOS EC barometer sensor driver");210MODULE_LICENSE("GPL v2");211