script: build: enable building extcon-usb-fixed module
[platform/kernel/linux-rpi.git] / drivers / iio / light / zopt2201.c
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * zopt2201.c - Support for IDT ZOPT2201 ambient light and UV B sensor
4  *
5  * Copyright 2017 Peter Meerwald-Stadler <pmeerw@pmeerw.net>
6  *
7  * Datasheet: https://www.idt.com/document/dst/zopt2201-datasheet
8  * 7-bit I2C slave addresses 0x53 (default) or 0x52 (programmed)
9  *
10  * TODO: interrupt support, ALS/UVB raw mode
11  */
12
13 #include <linux/module.h>
14 #include <linux/i2c.h>
15 #include <linux/mutex.h>
16 #include <linux/err.h>
17 #include <linux/delay.h>
18
19 #include <linux/iio/iio.h>
20 #include <linux/iio/sysfs.h>
21
22 #include <asm/unaligned.h>
23
24 #define ZOPT2201_DRV_NAME "zopt2201"
25
26 /* Registers */
27 #define ZOPT2201_MAIN_CTRL              0x00
28 #define ZOPT2201_LS_MEAS_RATE           0x04
29 #define ZOPT2201_LS_GAIN                0x05
30 #define ZOPT2201_PART_ID                0x06
31 #define ZOPT2201_MAIN_STATUS            0x07
32 #define ZOPT2201_ALS_DATA               0x0d /* LSB first, 13 to 20 bits */
33 #define ZOPT2201_UVB_DATA               0x10 /* LSB first, 13 to 20 bits */
34 #define ZOPT2201_UV_COMP_DATA           0x13 /* LSB first, 13 to 20 bits */
35 #define ZOPT2201_COMP_DATA              0x16 /* LSB first, 13 to 20 bits */
36 #define ZOPT2201_INT_CFG                0x19
37 #define ZOPT2201_INT_PST                0x1a
38
39 #define ZOPT2201_MAIN_CTRL_LS_MODE      BIT(3) /* 0 .. ALS, 1 .. UV B */
40 #define ZOPT2201_MAIN_CTRL_LS_EN        BIT(1)
41
42 /* Values for ZOPT2201_LS_MEAS_RATE resolution / bit width */
43 #define ZOPT2201_MEAS_RES_20BIT         0 /* takes 400 ms */
44 #define ZOPT2201_MEAS_RES_19BIT         1 /* takes 200 ms */
45 #define ZOPT2201_MEAS_RES_18BIT         2 /* takes 100 ms, default */
46 #define ZOPT2201_MEAS_RES_17BIT         3 /* takes 50 ms */
47 #define ZOPT2201_MEAS_RES_16BIT         4 /* takes 25 ms */
48 #define ZOPT2201_MEAS_RES_13BIT         5 /* takes 3.125 ms */
49 #define ZOPT2201_MEAS_RES_SHIFT         4
50
51 /* Values for ZOPT2201_LS_MEAS_RATE measurement rate */
52 #define ZOPT2201_MEAS_FREQ_25MS         0
53 #define ZOPT2201_MEAS_FREQ_50MS         1
54 #define ZOPT2201_MEAS_FREQ_100MS        2 /* default */
55 #define ZOPT2201_MEAS_FREQ_200MS        3
56 #define ZOPT2201_MEAS_FREQ_500MS        4
57 #define ZOPT2201_MEAS_FREQ_1000MS       5
58 #define ZOPT2201_MEAS_FREQ_2000MS       6
59
60 /* Values for ZOPT2201_LS_GAIN */
61 #define ZOPT2201_LS_GAIN_1              0
62 #define ZOPT2201_LS_GAIN_3              1
63 #define ZOPT2201_LS_GAIN_6              2
64 #define ZOPT2201_LS_GAIN_9              3
65 #define ZOPT2201_LS_GAIN_18             4
66
67 /* Values for ZOPT2201_MAIN_STATUS */
68 #define ZOPT2201_MAIN_STATUS_POWERON    BIT(5)
69 #define ZOPT2201_MAIN_STATUS_INT        BIT(4)
70 #define ZOPT2201_MAIN_STATUS_DRDY       BIT(3)
71
72 #define ZOPT2201_PART_NUMBER            0xb2
73
74 struct zopt2201_data {
75         struct i2c_client *client;
76         struct mutex lock;
77         u8 gain;
78         u8 res;
79         u8 rate;
80 };
81
82 static const struct {
83         unsigned int gain; /* gain factor */
84         unsigned int scale; /* micro lux per count */
85 } zopt2201_gain_als[] = {
86         {  1, 19200000 },
87         {  3,  6400000 },
88         {  6,  3200000 },
89         {  9,  2133333 },
90         { 18,  1066666 },
91 };
92
93 static const struct {
94         unsigned int gain; /* gain factor */
95         unsigned int scale; /* micro W/m2 per count */
96 } zopt2201_gain_uvb[] = {
97         {  1, 460800 },
98         {  3, 153600 },
99         {  6,  76800 },
100         {  9,  51200 },
101         { 18,  25600 },
102 };
103
104 static const struct {
105         unsigned int bits; /* sensor resolution in bits */
106         unsigned long us; /* measurement time in micro seconds */
107 } zopt2201_resolution[] = {
108         { 20, 400000 },
109         { 19, 200000 },
110         { 18, 100000 },
111         { 17,  50000 },
112         { 16,  25000 },
113         { 13,   3125 },
114 };
115
116 static const struct {
117         unsigned int scale, uscale; /* scale factor as integer + micro */
118         u8 gain; /* gain register value */
119         u8 res; /* resolution register value */
120 } zopt2201_scale_als[] = {
121         { 19, 200000, 0, 5 },
122         {  6, 400000, 1, 5 },
123         {  3, 200000, 2, 5 },
124         {  2, 400000, 0, 4 },
125         {  2, 133333, 3, 5 },
126         {  1, 200000, 0, 3 },
127         {  1,  66666, 4, 5 },
128         {  0, 800000, 1, 4 },
129         {  0, 600000, 0, 2 },
130         {  0, 400000, 2, 4 },
131         {  0, 300000, 0, 1 },
132         {  0, 266666, 3, 4 },
133         {  0, 200000, 2, 3 },
134         {  0, 150000, 0, 0 },
135         {  0, 133333, 4, 4 },
136         {  0, 100000, 2, 2 },
137         {  0,  66666, 4, 3 },
138         {  0,  50000, 2, 1 },
139         {  0,  33333, 4, 2 },
140         {  0,  25000, 2, 0 },
141         {  0,  16666, 4, 1 },
142         {  0,   8333, 4, 0 },
143 };
144
145 static const struct {
146         unsigned int scale, uscale; /* scale factor as integer + micro */
147         u8 gain; /* gain register value */
148         u8 res; /* resolution register value */
149 } zopt2201_scale_uvb[] = {
150         { 0, 460800, 0, 5 },
151         { 0, 153600, 1, 5 },
152         { 0,  76800, 2, 5 },
153         { 0,  57600, 0, 4 },
154         { 0,  51200, 3, 5 },
155         { 0,  28800, 0, 3 },
156         { 0,  25600, 4, 5 },
157         { 0,  19200, 1, 4 },
158         { 0,  14400, 0, 2 },
159         { 0,   9600, 2, 4 },
160         { 0,   7200, 0, 1 },
161         { 0,   6400, 3, 4 },
162         { 0,   4800, 2, 3 },
163         { 0,   3600, 0, 0 },
164         { 0,   3200, 4, 4 },
165         { 0,   2400, 2, 2 },
166         { 0,   1600, 4, 3 },
167         { 0,   1200, 2, 1 },
168         { 0,    800, 4, 2 },
169         { 0,    600, 2, 0 },
170         { 0,    400, 4, 1 },
171         { 0,    200, 4, 0 },
172 };
173
174 static int zopt2201_enable_mode(struct zopt2201_data *data, bool uvb_mode)
175 {
176         u8 out = ZOPT2201_MAIN_CTRL_LS_EN;
177
178         if (uvb_mode)
179                 out |= ZOPT2201_MAIN_CTRL_LS_MODE;
180
181         return i2c_smbus_write_byte_data(data->client, ZOPT2201_MAIN_CTRL, out);
182 }
183
184 static int zopt2201_read(struct zopt2201_data *data, u8 reg)
185 {
186         struct i2c_client *client = data->client;
187         int tries = 10;
188         u8 buf[3];
189         int ret;
190
191         mutex_lock(&data->lock);
192         ret = zopt2201_enable_mode(data, reg == ZOPT2201_UVB_DATA);
193         if (ret < 0)
194                 goto fail;
195
196         while (tries--) {
197                 unsigned long t = zopt2201_resolution[data->res].us;
198
199                 if (t <= 20000)
200                         usleep_range(t, t + 1000);
201                 else
202                         msleep(t / 1000);
203                 ret = i2c_smbus_read_byte_data(client, ZOPT2201_MAIN_STATUS);
204                 if (ret < 0)
205                         goto fail;
206                 if (ret & ZOPT2201_MAIN_STATUS_DRDY)
207                         break;
208         }
209
210         if (tries < 0) {
211                 ret = -ETIMEDOUT;
212                 goto fail;
213         }
214
215         ret = i2c_smbus_read_i2c_block_data(client, reg, sizeof(buf), buf);
216         if (ret < 0)
217                 goto fail;
218
219         ret = i2c_smbus_write_byte_data(client, ZOPT2201_MAIN_CTRL, 0x00);
220         if (ret < 0)
221                 goto fail;
222         mutex_unlock(&data->lock);
223
224         return get_unaligned_le24(&buf[0]);
225
226 fail:
227         mutex_unlock(&data->lock);
228         return ret;
229 }
230
231 static const struct iio_chan_spec zopt2201_channels[] = {
232         {
233                 .type = IIO_LIGHT,
234                 .address = ZOPT2201_ALS_DATA,
235                 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
236                                       BIT(IIO_CHAN_INFO_SCALE),
237                 .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_INT_TIME),
238         },
239         {
240                 .type = IIO_INTENSITY,
241                 .modified = 1,
242                 .channel2 = IIO_MOD_LIGHT_UV,
243                 .address = ZOPT2201_UVB_DATA,
244                 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
245                                       BIT(IIO_CHAN_INFO_SCALE),
246                 .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_INT_TIME),
247         },
248         {
249                 .type = IIO_UVINDEX,
250                 .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED),
251         },
252 };
253
254 static int zopt2201_read_raw(struct iio_dev *indio_dev,
255                                 struct iio_chan_spec const *chan,
256                                 int *val, int *val2, long mask)
257 {
258         struct zopt2201_data *data = iio_priv(indio_dev);
259         u64 tmp;
260         int ret;
261
262         switch (mask) {
263         case IIO_CHAN_INFO_RAW:
264                 ret = zopt2201_read(data, chan->address);
265                 if (ret < 0)
266                         return ret;
267                 *val = ret;
268                 return IIO_VAL_INT;
269         case IIO_CHAN_INFO_PROCESSED:
270                 ret = zopt2201_read(data, ZOPT2201_UVB_DATA);
271                 if (ret < 0)
272                         return ret;
273                 *val = ret * 18 *
274                         (1 << (20 - zopt2201_resolution[data->res].bits)) /
275                         zopt2201_gain_uvb[data->gain].gain;
276                 return IIO_VAL_INT;
277         case IIO_CHAN_INFO_SCALE:
278                 switch (chan->address) {
279                 case ZOPT2201_ALS_DATA:
280                         *val = zopt2201_gain_als[data->gain].scale;
281                         break;
282                 case ZOPT2201_UVB_DATA:
283                         *val = zopt2201_gain_uvb[data->gain].scale;
284                         break;
285                 default:
286                         return -EINVAL;
287                 }
288
289                 *val2 = 1000000;
290                 *val2 *= (1 << (zopt2201_resolution[data->res].bits - 13));
291                 tmp = div_s64(*val * 1000000ULL, *val2);
292                 *val = div_s64_rem(tmp, 1000000, val2);
293
294                 return IIO_VAL_INT_PLUS_MICRO;
295         case IIO_CHAN_INFO_INT_TIME:
296                 *val = 0;
297                 *val2 = zopt2201_resolution[data->res].us;
298                 return IIO_VAL_INT_PLUS_MICRO;
299         default:
300                 return -EINVAL;
301         }
302 }
303
304 static int zopt2201_set_resolution(struct zopt2201_data *data, u8 res)
305 {
306         int ret;
307
308         ret = i2c_smbus_write_byte_data(data->client, ZOPT2201_LS_MEAS_RATE,
309                                         (res << ZOPT2201_MEAS_RES_SHIFT) |
310                                         data->rate);
311         if (ret < 0)
312                 return ret;
313
314         data->res = res;
315
316         return 0;
317 }
318
319 static int zopt2201_write_resolution(struct zopt2201_data *data,
320                                      int val, int val2)
321 {
322         int i, ret;
323
324         if (val != 0)
325                 return -EINVAL;
326
327         for (i = 0; i < ARRAY_SIZE(zopt2201_resolution); i++)
328                 if (val2 == zopt2201_resolution[i].us) {
329                         mutex_lock(&data->lock);
330                         ret = zopt2201_set_resolution(data, i);
331                         mutex_unlock(&data->lock);
332                         return ret;
333                 }
334
335         return -EINVAL;
336 }
337
338 static int zopt2201_set_gain(struct zopt2201_data *data, u8 gain)
339 {
340         int ret;
341
342         ret = i2c_smbus_write_byte_data(data->client, ZOPT2201_LS_GAIN, gain);
343         if (ret < 0)
344                 return ret;
345
346         data->gain = gain;
347
348         return 0;
349 }
350
351 static int zopt2201_write_scale_als_by_idx(struct zopt2201_data *data, int idx)
352 {
353         int ret;
354
355         mutex_lock(&data->lock);
356         ret = zopt2201_set_resolution(data, zopt2201_scale_als[idx].res);
357         if (ret < 0)
358                 goto unlock;
359
360         ret = zopt2201_set_gain(data, zopt2201_scale_als[idx].gain);
361
362 unlock:
363         mutex_unlock(&data->lock);
364         return ret;
365 }
366
367 static int zopt2201_write_scale_als(struct zopt2201_data *data,
368                                      int val, int val2)
369 {
370         int i;
371
372         for (i = 0; i < ARRAY_SIZE(zopt2201_scale_als); i++)
373                 if (val == zopt2201_scale_als[i].scale &&
374                     val2 == zopt2201_scale_als[i].uscale) {
375                         return zopt2201_write_scale_als_by_idx(data, i);
376                 }
377
378         return -EINVAL;
379 }
380
381 static int zopt2201_write_scale_uvb_by_idx(struct zopt2201_data *data, int idx)
382 {
383         int ret;
384
385         mutex_lock(&data->lock);
386         ret = zopt2201_set_resolution(data, zopt2201_scale_als[idx].res);
387         if (ret < 0)
388                 goto unlock;
389
390         ret = zopt2201_set_gain(data, zopt2201_scale_als[idx].gain);
391
392 unlock:
393         mutex_unlock(&data->lock);
394         return ret;
395 }
396
397 static int zopt2201_write_scale_uvb(struct zopt2201_data *data,
398                                      int val, int val2)
399 {
400         int i;
401
402         for (i = 0; i < ARRAY_SIZE(zopt2201_scale_uvb); i++)
403                 if (val == zopt2201_scale_uvb[i].scale &&
404                     val2 == zopt2201_scale_uvb[i].uscale)
405                         return zopt2201_write_scale_uvb_by_idx(data, i);
406
407         return -EINVAL;
408 }
409
410 static int zopt2201_write_raw(struct iio_dev *indio_dev,
411                               struct iio_chan_spec const *chan,
412                               int val, int val2, long mask)
413 {
414         struct zopt2201_data *data = iio_priv(indio_dev);
415
416         switch (mask) {
417         case IIO_CHAN_INFO_INT_TIME:
418                 return zopt2201_write_resolution(data, val, val2);
419         case IIO_CHAN_INFO_SCALE:
420                 switch (chan->address) {
421                 case ZOPT2201_ALS_DATA:
422                         return zopt2201_write_scale_als(data, val, val2);
423                 case ZOPT2201_UVB_DATA:
424                         return zopt2201_write_scale_uvb(data, val, val2);
425                 default:
426                         return -EINVAL;
427                 }
428         }
429
430         return -EINVAL;
431 }
432
433 static ssize_t zopt2201_show_int_time_available(struct device *dev,
434                                                 struct device_attribute *attr,
435                                                 char *buf)
436 {
437         size_t len = 0;
438         int i;
439
440         for (i = 0; i < ARRAY_SIZE(zopt2201_resolution); i++)
441                 len += scnprintf(buf + len, PAGE_SIZE - len, "0.%06lu ",
442                                  zopt2201_resolution[i].us);
443         buf[len - 1] = '\n';
444
445         return len;
446 }
447
448 static IIO_DEV_ATTR_INT_TIME_AVAIL(zopt2201_show_int_time_available);
449
450 static ssize_t zopt2201_show_als_scale_avail(struct device *dev,
451                                              struct device_attribute *attr,
452                                              char *buf)
453 {
454         ssize_t len = 0;
455         int i;
456
457         for (i = 0; i < ARRAY_SIZE(zopt2201_scale_als); i++)
458                 len += scnprintf(buf + len, PAGE_SIZE - len, "%d.%06u ",
459                                  zopt2201_scale_als[i].scale,
460                                  zopt2201_scale_als[i].uscale);
461         buf[len - 1] = '\n';
462
463         return len;
464 }
465
466 static ssize_t zopt2201_show_uvb_scale_avail(struct device *dev,
467                                              struct device_attribute *attr,
468                                              char *buf)
469 {
470         ssize_t len = 0;
471         int i;
472
473         for (i = 0; i < ARRAY_SIZE(zopt2201_scale_uvb); i++)
474                 len += scnprintf(buf + len, PAGE_SIZE - len, "%d.%06u ",
475                                  zopt2201_scale_uvb[i].scale,
476                                  zopt2201_scale_uvb[i].uscale);
477         buf[len - 1] = '\n';
478
479         return len;
480 }
481
482 static IIO_DEVICE_ATTR(in_illuminance_scale_available, 0444,
483                        zopt2201_show_als_scale_avail, NULL, 0);
484 static IIO_DEVICE_ATTR(in_intensity_uv_scale_available, 0444,
485                        zopt2201_show_uvb_scale_avail, NULL, 0);
486
487 static struct attribute *zopt2201_attributes[] = {
488         &iio_dev_attr_integration_time_available.dev_attr.attr,
489         &iio_dev_attr_in_illuminance_scale_available.dev_attr.attr,
490         &iio_dev_attr_in_intensity_uv_scale_available.dev_attr.attr,
491         NULL
492 };
493
494 static const struct attribute_group zopt2201_attribute_group = {
495         .attrs = zopt2201_attributes,
496 };
497
498 static const struct iio_info zopt2201_info = {
499         .read_raw = zopt2201_read_raw,
500         .write_raw = zopt2201_write_raw,
501         .attrs = &zopt2201_attribute_group,
502 };
503
504 static int zopt2201_probe(struct i2c_client *client)
505 {
506         struct zopt2201_data *data;
507         struct iio_dev *indio_dev;
508         int ret;
509
510         if (!i2c_check_functionality(client->adapter,
511                                      I2C_FUNC_SMBUS_READ_I2C_BLOCK))
512                 return -EOPNOTSUPP;
513
514         ret = i2c_smbus_read_byte_data(client, ZOPT2201_PART_ID);
515         if (ret < 0)
516                 return ret;
517         if (ret != ZOPT2201_PART_NUMBER)
518                 return -ENODEV;
519
520         indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
521         if (!indio_dev)
522                 return -ENOMEM;
523
524         data = iio_priv(indio_dev);
525         i2c_set_clientdata(client, indio_dev);
526         data->client = client;
527         mutex_init(&data->lock);
528
529         indio_dev->info = &zopt2201_info;
530         indio_dev->channels = zopt2201_channels;
531         indio_dev->num_channels = ARRAY_SIZE(zopt2201_channels);
532         indio_dev->name = ZOPT2201_DRV_NAME;
533         indio_dev->modes = INDIO_DIRECT_MODE;
534
535         data->rate = ZOPT2201_MEAS_FREQ_100MS;
536         ret = zopt2201_set_resolution(data, ZOPT2201_MEAS_RES_18BIT);
537         if (ret < 0)
538                 return ret;
539
540         ret = zopt2201_set_gain(data, ZOPT2201_LS_GAIN_3);
541         if (ret < 0)
542                 return ret;
543
544         return devm_iio_device_register(&client->dev, indio_dev);
545 }
546
547 static const struct i2c_device_id zopt2201_id[] = {
548         { "zopt2201", 0 },
549         { }
550 };
551 MODULE_DEVICE_TABLE(i2c, zopt2201_id);
552
553 static struct i2c_driver zopt2201_driver = {
554         .driver = {
555                 .name   = ZOPT2201_DRV_NAME,
556         },
557         .probe = zopt2201_probe,
558         .id_table = zopt2201_id,
559 };
560
561 module_i2c_driver(zopt2201_driver);
562
563 MODULE_AUTHOR("Peter Meerwald-Stadler <pmeerw@pmeerw.net>");
564 MODULE_DESCRIPTION("IDT ZOPT2201 ambient light and UV B sensor driver");
565 MODULE_LICENSE("GPL");