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