Linux 6.7-rc7
[linux-modified.git] / drivers / iio / common / cros_ec_sensors / cros_ec_sensors.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * cros_ec_sensors - Driver for Chrome OS Embedded Controller sensors.
4  *
5  * Copyright (C) 2016 Google, Inc
6  *
7  * This driver uses the cros-ec interface to communicate with the Chrome OS
8  * EC about sensors data. Data access is presented through iio sysfs.
9  */
10
11 #include <linux/device.h>
12 #include <linux/iio/buffer.h>
13 #include <linux/iio/common/cros_ec_sensors_core.h>
14 #include <linux/iio/iio.h>
15 #include <linux/iio/kfifo_buf.h>
16 #include <linux/iio/trigger_consumer.h>
17 #include <linux/iio/triggered_buffer.h>
18 #include <linux/kernel.h>
19 #include <linux/mod_devicetable.h>
20 #include <linux/module.h>
21 #include <linux/platform_data/cros_ec_commands.h>
22 #include <linux/platform_data/cros_ec_proto.h>
23 #include <linux/platform_device.h>
24 #include <linux/slab.h>
25
26 #define CROS_EC_SENSORS_MAX_CHANNELS 4
27
28 /* State data for ec_sensors iio driver. */
29 struct cros_ec_sensors_state {
30         /* Shared by all sensors */
31         struct cros_ec_sensors_core_state core;
32
33         struct iio_chan_spec channels[CROS_EC_SENSORS_MAX_CHANNELS];
34 };
35
36 static int cros_ec_sensors_read(struct iio_dev *indio_dev,
37                           struct iio_chan_spec const *chan,
38                           int *val, int *val2, long mask)
39 {
40         struct cros_ec_sensors_state *st = iio_priv(indio_dev);
41         s16 data = 0;
42         s64 val64;
43         int i;
44         int ret;
45         int idx = chan->scan_index;
46
47         mutex_lock(&st->core.cmd_lock);
48
49         switch (mask) {
50         case IIO_CHAN_INFO_RAW:
51                 ret = st->core.read_ec_sensors_data(indio_dev, 1 << idx, &data);
52                 if (ret < 0)
53                         break;
54                 ret = IIO_VAL_INT;
55                 *val = data;
56                 break;
57         case IIO_CHAN_INFO_CALIBBIAS:
58                 st->core.param.cmd = MOTIONSENSE_CMD_SENSOR_OFFSET;
59                 st->core.param.sensor_offset.flags = 0;
60
61                 ret = cros_ec_motion_send_host_cmd(&st->core, 0);
62                 if (ret < 0)
63                         break;
64
65                 /* Save values */
66                 for (i = CROS_EC_SENSOR_X; i < CROS_EC_SENSOR_MAX_AXIS; i++)
67                         st->core.calib[i].offset =
68                                 st->core.resp->sensor_offset.offset[i];
69                 ret = IIO_VAL_INT;
70                 *val = st->core.calib[idx].offset;
71                 break;
72         case IIO_CHAN_INFO_CALIBSCALE:
73                 st->core.param.cmd = MOTIONSENSE_CMD_SENSOR_SCALE;
74                 st->core.param.sensor_offset.flags = 0;
75
76                 ret = cros_ec_motion_send_host_cmd(&st->core, 0);
77                 if (ret == -EPROTO || ret == -EOPNOTSUPP) {
78                         /* Reading calibscale is not supported on older EC. */
79                         *val = 1;
80                         *val2 = 0;
81                         ret = IIO_VAL_INT_PLUS_MICRO;
82                         break;
83                 } else if (ret) {
84                         break;
85                 }
86
87                 /* Save values */
88                 for (i = CROS_EC_SENSOR_X; i < CROS_EC_SENSOR_MAX_AXIS; i++)
89                         st->core.calib[i].scale =
90                                 st->core.resp->sensor_scale.scale[i];
91
92                 *val = st->core.calib[idx].scale >> 15;
93                 *val2 = ((st->core.calib[idx].scale & 0x7FFF) * 1000000LL) /
94                         MOTION_SENSE_DEFAULT_SCALE;
95                 ret = IIO_VAL_INT_PLUS_MICRO;
96                 break;
97         case IIO_CHAN_INFO_SCALE:
98                 st->core.param.cmd = MOTIONSENSE_CMD_SENSOR_RANGE;
99                 st->core.param.sensor_range.data = EC_MOTION_SENSE_NO_VALUE;
100
101                 ret = cros_ec_motion_send_host_cmd(&st->core, 0);
102                 if (ret < 0)
103                         break;
104
105                 val64 = st->core.resp->sensor_range.ret;
106                 switch (st->core.type) {
107                 case MOTIONSENSE_TYPE_ACCEL:
108                         /*
109                          * EC returns data in g, iio exepects m/s^2.
110                          * Do not use IIO_G_TO_M_S_2 to avoid precision loss.
111                          */
112                         *val = div_s64(val64 * 980665, 10);
113                         *val2 = 10000 << (CROS_EC_SENSOR_BITS - 1);
114                         ret = IIO_VAL_FRACTIONAL;
115                         break;
116                 case MOTIONSENSE_TYPE_GYRO:
117                         /*
118                          * EC returns data in dps, iio expects rad/s.
119                          * Do not use IIO_DEGREE_TO_RAD to avoid precision
120                          * loss. Round to the nearest integer.
121                          */
122                         *val = 0;
123                         *val2 = div_s64(val64 * 3141592653ULL,
124                                         180 << (CROS_EC_SENSOR_BITS - 1));
125                         ret = IIO_VAL_INT_PLUS_NANO;
126                         break;
127                 case MOTIONSENSE_TYPE_MAG:
128                         /*
129                          * EC returns data in 16LSB / uT,
130                          * iio expects Gauss
131                          */
132                         *val = val64;
133                         *val2 = 100 << (CROS_EC_SENSOR_BITS - 1);
134                         ret = IIO_VAL_FRACTIONAL;
135                         break;
136                 default:
137                         ret = -EINVAL;
138                 }
139                 break;
140         default:
141                 ret = cros_ec_sensors_core_read(&st->core, chan, val, val2,
142                                                 mask);
143                 break;
144         }
145         mutex_unlock(&st->core.cmd_lock);
146
147         return ret;
148 }
149
150 static int cros_ec_sensors_write(struct iio_dev *indio_dev,
151                                struct iio_chan_spec const *chan,
152                                int val, int val2, long mask)
153 {
154         struct cros_ec_sensors_state *st = iio_priv(indio_dev);
155         int i;
156         int ret;
157         int idx = chan->scan_index;
158
159         mutex_lock(&st->core.cmd_lock);
160
161         switch (mask) {
162         case IIO_CHAN_INFO_CALIBBIAS:
163                 st->core.calib[idx].offset = val;
164
165                 /* Send to EC for each axis, even if not complete */
166                 st->core.param.cmd = MOTIONSENSE_CMD_SENSOR_OFFSET;
167                 st->core.param.sensor_offset.flags =
168                         MOTION_SENSE_SET_OFFSET;
169                 for (i = CROS_EC_SENSOR_X; i < CROS_EC_SENSOR_MAX_AXIS; i++)
170                         st->core.param.sensor_offset.offset[i] =
171                                 st->core.calib[i].offset;
172                 st->core.param.sensor_offset.temp =
173                         EC_MOTION_SENSE_INVALID_CALIB_TEMP;
174
175                 ret = cros_ec_motion_send_host_cmd(&st->core, 0);
176                 break;
177         case IIO_CHAN_INFO_CALIBSCALE:
178                 st->core.calib[idx].scale = val;
179                 /* Send to EC for each axis, even if not complete */
180
181                 st->core.param.cmd = MOTIONSENSE_CMD_SENSOR_SCALE;
182                 st->core.param.sensor_offset.flags =
183                         MOTION_SENSE_SET_OFFSET;
184                 for (i = CROS_EC_SENSOR_X; i < CROS_EC_SENSOR_MAX_AXIS; i++)
185                         st->core.param.sensor_scale.scale[i] =
186                                 st->core.calib[i].scale;
187                 st->core.param.sensor_scale.temp =
188                         EC_MOTION_SENSE_INVALID_CALIB_TEMP;
189
190                 ret = cros_ec_motion_send_host_cmd(&st->core, 0);
191                 break;
192         case IIO_CHAN_INFO_SCALE:
193                 if (st->core.type == MOTIONSENSE_TYPE_MAG) {
194                         ret = -EINVAL;
195                         break;
196                 }
197                 st->core.param.cmd = MOTIONSENSE_CMD_SENSOR_RANGE;
198                 st->core.param.sensor_range.data = val;
199
200                 /* Always roundup, so caller gets at least what it asks for. */
201                 st->core.param.sensor_range.roundup = 1;
202
203                 ret = cros_ec_motion_send_host_cmd(&st->core, 0);
204                 if (ret == 0) {
205                         st->core.range_updated = true;
206                         st->core.curr_range = val;
207                 }
208                 break;
209         default:
210                 ret = cros_ec_sensors_core_write(
211                                 &st->core, chan, val, val2, mask);
212                 break;
213         }
214
215         mutex_unlock(&st->core.cmd_lock);
216
217         return ret;
218 }
219
220 static const struct iio_info ec_sensors_info = {
221         .read_raw = &cros_ec_sensors_read,
222         .write_raw = &cros_ec_sensors_write,
223         .read_avail = &cros_ec_sensors_core_read_avail,
224 };
225
226 static int cros_ec_sensors_probe(struct platform_device *pdev)
227 {
228         struct device *dev = &pdev->dev;
229         struct iio_dev *indio_dev;
230         struct cros_ec_sensors_state *state;
231         struct iio_chan_spec *channel;
232         int ret, i;
233
234         indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*state));
235         if (!indio_dev)
236                 return -ENOMEM;
237
238         ret = cros_ec_sensors_core_init(pdev, indio_dev, true,
239                                         cros_ec_sensors_capture);
240         if (ret)
241                 return ret;
242
243         indio_dev->info = &ec_sensors_info;
244         state = iio_priv(indio_dev);
245         for (channel = state->channels, i = CROS_EC_SENSOR_X;
246              i < CROS_EC_SENSOR_MAX_AXIS; i++, channel++) {
247                 /* Common part */
248                 channel->info_mask_separate =
249                         BIT(IIO_CHAN_INFO_RAW) |
250                         BIT(IIO_CHAN_INFO_CALIBBIAS) |
251                         BIT(IIO_CHAN_INFO_CALIBSCALE);
252                 channel->info_mask_shared_by_all =
253                         BIT(IIO_CHAN_INFO_SCALE) |
254                         BIT(IIO_CHAN_INFO_SAMP_FREQ);
255                 channel->info_mask_shared_by_all_available =
256                         BIT(IIO_CHAN_INFO_SAMP_FREQ);
257                 channel->scan_type.realbits = CROS_EC_SENSOR_BITS;
258                 channel->scan_type.storagebits = CROS_EC_SENSOR_BITS;
259                 channel->scan_index = i;
260                 channel->ext_info = cros_ec_sensors_ext_info;
261                 channel->modified = 1;
262                 channel->channel2 = IIO_MOD_X + i;
263                 channel->scan_type.sign = 's';
264
265                 /* Sensor specific */
266                 switch (state->core.type) {
267                 case MOTIONSENSE_TYPE_ACCEL:
268                         channel->type = IIO_ACCEL;
269                         break;
270                 case MOTIONSENSE_TYPE_GYRO:
271                         channel->type = IIO_ANGL_VEL;
272                         break;
273                 case MOTIONSENSE_TYPE_MAG:
274                         channel->type = IIO_MAGN;
275                         break;
276                 default:
277                         dev_err(&pdev->dev, "Unknown motion sensor\n");
278                         return -EINVAL;
279                 }
280         }
281
282         /* Timestamp */
283         channel->type = IIO_TIMESTAMP;
284         channel->channel = -1;
285         channel->scan_index = CROS_EC_SENSOR_MAX_AXIS;
286         channel->scan_type.sign = 's';
287         channel->scan_type.realbits = 64;
288         channel->scan_type.storagebits = 64;
289
290         indio_dev->channels = state->channels;
291         indio_dev->num_channels = CROS_EC_SENSORS_MAX_CHANNELS;
292
293         /* There is only enough room for accel and gyro in the io space */
294         if ((state->core.ec->cmd_readmem != NULL) &&
295             (state->core.type != MOTIONSENSE_TYPE_MAG))
296                 state->core.read_ec_sensors_data = cros_ec_sensors_read_lpc;
297         else
298                 state->core.read_ec_sensors_data = cros_ec_sensors_read_cmd;
299
300         return cros_ec_sensors_core_register(dev, indio_dev,
301                         cros_ec_sensors_push_data);
302 }
303
304 static const struct platform_device_id cros_ec_sensors_ids[] = {
305         {
306                 .name = "cros-ec-accel",
307         },
308         {
309                 .name = "cros-ec-gyro",
310         },
311         {
312                 .name = "cros-ec-mag",
313         },
314         { /* sentinel */ }
315 };
316 MODULE_DEVICE_TABLE(platform, cros_ec_sensors_ids);
317
318 static struct platform_driver cros_ec_sensors_platform_driver = {
319         .driver = {
320                 .name   = "cros-ec-sensors",
321                 .pm     = &cros_ec_sensors_pm_ops,
322         },
323         .probe          = cros_ec_sensors_probe,
324         .id_table       = cros_ec_sensors_ids,
325 };
326 module_platform_driver(cros_ec_sensors_platform_driver);
327
328 MODULE_DESCRIPTION("ChromeOS EC 3-axis sensors driver");
329 MODULE_LICENSE("GPL v2");