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