xref: /linux/drivers/iio/light/veml6030.c (revision 32cfb3c48e24511ccf9f76d8a2e04a30397af438)
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * VEML6030 Ambient Light Sensor
4  *
5  * Copyright (c) 2019, Rishi Gupta <gupt21@gmail.com>
6  *
7  * Datasheet: https://www.vishay.com/docs/84366/veml6030.pdf
8  * Appnote-84367: https://www.vishay.com/docs/84367/designingveml6030.pdf
9  */
10 
11 #include <linux/module.h>
12 #include <linux/i2c.h>
13 #include <linux/err.h>
14 #include <linux/regmap.h>
15 #include <linux/interrupt.h>
16 #include <linux/pm_runtime.h>
17 #include <linux/iio/iio.h>
18 #include <linux/iio/sysfs.h>
19 #include <linux/iio/events.h>
20 
21 /* Device registers */
22 #define VEML6030_REG_ALS_CONF   0x00
23 #define VEML6030_REG_ALS_WH     0x01
24 #define VEML6030_REG_ALS_WL     0x02
25 #define VEML6030_REG_ALS_PSM    0x03
26 #define VEML6030_REG_ALS_DATA   0x04
27 #define VEML6030_REG_WH_DATA    0x05
28 #define VEML6030_REG_ALS_INT    0x06
29 
30 /* Bit masks for specific functionality */
31 #define VEML6030_ALS_IT       GENMASK(9, 6)
32 #define VEML6030_PSM          GENMASK(2, 1)
33 #define VEML6030_ALS_PERS     GENMASK(5, 4)
34 #define VEML6030_ALS_GAIN     GENMASK(12, 11)
35 #define VEML6030_PSM_EN       BIT(0)
36 #define VEML6030_INT_TH_LOW   BIT(15)
37 #define VEML6030_INT_TH_HIGH  BIT(14)
38 #define VEML6030_ALS_INT_EN   BIT(1)
39 #define VEML6030_ALS_SD       BIT(0)
40 
41 /*
42  * The resolution depends on both gain and integration time. The
43  * cur_resolution stores one of the resolution mentioned in the
44  * table during startup and gets updated whenever integration time
45  * or gain is changed.
46  *
47  * Table 'resolution and maximum detection range' in appnote 84367
48  * is visualized as a 2D array. The cur_gain stores index of gain
49  * in this table (0-3) while the cur_integration_time holds index
50  * of integration time (0-5).
51  */
52 struct veml6030_data {
53 	struct i2c_client *client;
54 	struct regmap *regmap;
55 	int cur_resolution;
56 	int cur_gain;
57 	int cur_integration_time;
58 };
59 
60 /* Integration time available in seconds */
61 static IIO_CONST_ATTR(in_illuminance_integration_time_available,
62 				"0.025 0.05 0.1 0.2 0.4 0.8");
63 
64 /*
65  * Scale is 1/gain. Value 0.125 is ALS gain x (1/8), 0.25 is
66  * ALS gain x (1/4), 1.0 = ALS gain x 1 and 2.0 is ALS gain x 2.
67  */
68 static IIO_CONST_ATTR(in_illuminance_scale_available,
69 				"0.125 0.25 1.0 2.0");
70 
71 static struct attribute *veml6030_attributes[] = {
72 	&iio_const_attr_in_illuminance_integration_time_available.dev_attr.attr,
73 	&iio_const_attr_in_illuminance_scale_available.dev_attr.attr,
74 	NULL
75 };
76 
77 static const struct attribute_group veml6030_attr_group = {
78 	.attrs = veml6030_attributes,
79 };
80 
81 /*
82  * Persistence = 1/2/4/8 x integration time
83  * Minimum time for which light readings must stay above configured
84  * threshold to assert the interrupt.
85  */
86 static const char * const period_values[] = {
87 		"0.1 0.2 0.4 0.8",
88 		"0.2 0.4 0.8 1.6",
89 		"0.4 0.8 1.6 3.2",
90 		"0.8 1.6 3.2 6.4",
91 		"0.05 0.1 0.2 0.4",
92 		"0.025 0.050 0.1 0.2"
93 };
94 
95 /*
96  * Return list of valid period values in seconds corresponding to
97  * the currently active integration time.
98  */
in_illuminance_period_available_show(struct device * dev,struct device_attribute * attr,char * buf)99 static ssize_t in_illuminance_period_available_show(struct device *dev,
100 				struct device_attribute *attr, char *buf)
101 {
102 	struct veml6030_data *data = iio_priv(dev_to_iio_dev(dev));
103 	int ret, reg, x;
104 
105 	ret = regmap_read(data->regmap, VEML6030_REG_ALS_CONF, &reg);
106 	if (ret) {
107 		dev_err(&data->client->dev,
108 				"can't read als conf register %d\n", ret);
109 		return ret;
110 	}
111 
112 	ret = ((reg >> 6) & 0xF);
113 	switch (ret) {
114 	case 0:
115 	case 1:
116 	case 2:
117 	case 3:
118 		x = ret;
119 		break;
120 	case 8:
121 		x = 4;
122 		break;
123 	case 12:
124 		x = 5;
125 		break;
126 	default:
127 		return -EINVAL;
128 	}
129 
130 	return sysfs_emit(buf, "%s\n", period_values[x]);
131 }
132 
133 static IIO_DEVICE_ATTR_RO(in_illuminance_period_available, 0);
134 
135 static struct attribute *veml6030_event_attributes[] = {
136 	&iio_dev_attr_in_illuminance_period_available.dev_attr.attr,
137 	NULL
138 };
139 
140 static const struct attribute_group veml6030_event_attr_group = {
141 	.attrs = veml6030_event_attributes,
142 };
143 
veml6030_als_pwr_on(struct veml6030_data * data)144 static int veml6030_als_pwr_on(struct veml6030_data *data)
145 {
146 	return regmap_clear_bits(data->regmap, VEML6030_REG_ALS_CONF,
147 				 VEML6030_ALS_SD);
148 }
149 
veml6030_als_shut_down(struct veml6030_data * data)150 static int veml6030_als_shut_down(struct veml6030_data *data)
151 {
152 	return regmap_update_bits(data->regmap, VEML6030_REG_ALS_CONF,
153 				 VEML6030_ALS_SD, 1);
154 }
155 
veml6030_als_shut_down_action(void * data)156 static void veml6030_als_shut_down_action(void *data)
157 {
158 	veml6030_als_shut_down(data);
159 }
160 
161 static const struct iio_event_spec veml6030_event_spec[] = {
162 	{
163 		.type = IIO_EV_TYPE_THRESH,
164 		.dir = IIO_EV_DIR_RISING,
165 		.mask_separate = BIT(IIO_EV_INFO_VALUE),
166 	}, {
167 		.type = IIO_EV_TYPE_THRESH,
168 		.dir = IIO_EV_DIR_FALLING,
169 		.mask_separate = BIT(IIO_EV_INFO_VALUE),
170 	}, {
171 		.type = IIO_EV_TYPE_THRESH,
172 		.dir = IIO_EV_DIR_EITHER,
173 		.mask_separate = BIT(IIO_EV_INFO_PERIOD) |
174 		BIT(IIO_EV_INFO_ENABLE),
175 	},
176 };
177 
178 /* Channel number */
179 enum veml6030_chan {
180 	CH_ALS,
181 	CH_WHITE,
182 };
183 
184 static const struct iio_chan_spec veml6030_channels[] = {
185 	{
186 		.type = IIO_LIGHT,
187 		.channel = CH_ALS,
188 		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
189 				BIT(IIO_CHAN_INFO_PROCESSED) |
190 				BIT(IIO_CHAN_INFO_INT_TIME) |
191 				BIT(IIO_CHAN_INFO_SCALE),
192 		.event_spec = veml6030_event_spec,
193 		.num_event_specs = ARRAY_SIZE(veml6030_event_spec),
194 	},
195 	{
196 		.type = IIO_INTENSITY,
197 		.channel = CH_WHITE,
198 		.modified = 1,
199 		.channel2 = IIO_MOD_LIGHT_BOTH,
200 		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
201 				BIT(IIO_CHAN_INFO_PROCESSED),
202 	},
203 };
204 
205 static const struct regmap_config veml6030_regmap_config = {
206 	.name = "veml6030_regmap",
207 	.reg_bits = 8,
208 	.val_bits = 16,
209 	.max_register = VEML6030_REG_ALS_INT,
210 	.val_format_endian = REGMAP_ENDIAN_LITTLE,
211 };
212 
veml6030_get_intgrn_tm(struct iio_dev * indio_dev,int * val,int * val2)213 static int veml6030_get_intgrn_tm(struct iio_dev *indio_dev,
214 						int *val, int *val2)
215 {
216 	int ret, reg;
217 	struct veml6030_data *data = iio_priv(indio_dev);
218 
219 	ret = regmap_read(data->regmap, VEML6030_REG_ALS_CONF, &reg);
220 	if (ret) {
221 		dev_err(&data->client->dev,
222 				"can't read als conf register %d\n", ret);
223 		return ret;
224 	}
225 
226 	switch ((reg >> 6) & 0xF) {
227 	case 0:
228 		*val2 = 100000;
229 		break;
230 	case 1:
231 		*val2 = 200000;
232 		break;
233 	case 2:
234 		*val2 = 400000;
235 		break;
236 	case 3:
237 		*val2 = 800000;
238 		break;
239 	case 8:
240 		*val2 = 50000;
241 		break;
242 	case 12:
243 		*val2 = 25000;
244 		break;
245 	default:
246 		return -EINVAL;
247 	}
248 
249 	*val = 0;
250 	return IIO_VAL_INT_PLUS_MICRO;
251 }
252 
veml6030_set_intgrn_tm(struct iio_dev * indio_dev,int val,int val2)253 static int veml6030_set_intgrn_tm(struct iio_dev *indio_dev,
254 						int val, int val2)
255 {
256 	int ret, new_int_time, int_idx;
257 	struct veml6030_data *data = iio_priv(indio_dev);
258 
259 	if (val)
260 		return -EINVAL;
261 
262 	switch (val2) {
263 	case 25000:
264 		new_int_time = 0x300;
265 		int_idx = 5;
266 		break;
267 	case 50000:
268 		new_int_time = 0x200;
269 		int_idx = 4;
270 		break;
271 	case 100000:
272 		new_int_time = 0x00;
273 		int_idx = 3;
274 		break;
275 	case 200000:
276 		new_int_time = 0x40;
277 		int_idx = 2;
278 		break;
279 	case 400000:
280 		new_int_time = 0x80;
281 		int_idx = 1;
282 		break;
283 	case 800000:
284 		new_int_time = 0xC0;
285 		int_idx = 0;
286 		break;
287 	default:
288 		return -EINVAL;
289 	}
290 
291 	ret = regmap_update_bits(data->regmap, VEML6030_REG_ALS_CONF,
292 					VEML6030_ALS_IT, new_int_time);
293 	if (ret) {
294 		dev_err(&data->client->dev,
295 				"can't update als integration time %d\n", ret);
296 		return ret;
297 	}
298 
299 	/*
300 	 * Cache current integration time and update resolution. For every
301 	 * increase in integration time to next level, resolution is halved
302 	 * and vice-versa.
303 	 */
304 	if (data->cur_integration_time < int_idx)
305 		data->cur_resolution <<= int_idx - data->cur_integration_time;
306 	else if (data->cur_integration_time > int_idx)
307 		data->cur_resolution >>= data->cur_integration_time - int_idx;
308 
309 	data->cur_integration_time = int_idx;
310 
311 	return ret;
312 }
313 
veml6030_read_persistence(struct iio_dev * indio_dev,int * val,int * val2)314 static int veml6030_read_persistence(struct iio_dev *indio_dev,
315 						int *val, int *val2)
316 {
317 	int ret, reg, period, x, y;
318 	struct veml6030_data *data = iio_priv(indio_dev);
319 
320 	ret = veml6030_get_intgrn_tm(indio_dev, &x, &y);
321 	if (ret < 0)
322 		return ret;
323 
324 	ret = regmap_read(data->regmap, VEML6030_REG_ALS_CONF, &reg);
325 	if (ret) {
326 		dev_err(&data->client->dev,
327 				"can't read als conf register %d\n", ret);
328 	}
329 
330 	/* integration time multiplied by 1/2/4/8 */
331 	period = y * (1 << ((reg >> 4) & 0x03));
332 
333 	*val = period / 1000000;
334 	*val2 = period % 1000000;
335 
336 	return IIO_VAL_INT_PLUS_MICRO;
337 }
338 
veml6030_write_persistence(struct iio_dev * indio_dev,int val,int val2)339 static int veml6030_write_persistence(struct iio_dev *indio_dev,
340 						int val, int val2)
341 {
342 	int ret, period, x, y;
343 	struct veml6030_data *data = iio_priv(indio_dev);
344 
345 	ret = veml6030_get_intgrn_tm(indio_dev, &x, &y);
346 	if (ret < 0)
347 		return ret;
348 
349 	if (!val) {
350 		period = val2 / y;
351 	} else {
352 		if ((val == 1) && (val2 == 600000))
353 			period = 1600000 / y;
354 		else if ((val == 3) && (val2 == 200000))
355 			period = 3200000 / y;
356 		else if ((val == 6) && (val2 == 400000))
357 			period = 6400000 / y;
358 		else
359 			period = -1;
360 	}
361 
362 	if (period <= 0 || period > 8 || hweight8(period) != 1)
363 		return -EINVAL;
364 
365 	ret = regmap_update_bits(data->regmap, VEML6030_REG_ALS_CONF,
366 				VEML6030_ALS_PERS, (ffs(period) - 1) << 4);
367 	if (ret)
368 		dev_err(&data->client->dev,
369 				"can't set persistence value %d\n", ret);
370 
371 	return ret;
372 }
373 
veml6030_set_als_gain(struct iio_dev * indio_dev,int val,int val2)374 static int veml6030_set_als_gain(struct iio_dev *indio_dev,
375 						int val, int val2)
376 {
377 	int ret, new_gain, gain_idx;
378 	struct veml6030_data *data = iio_priv(indio_dev);
379 
380 	if (val == 0 && val2 == 125000) {
381 		new_gain = 0x1000; /* 0x02 << 11 */
382 		gain_idx = 3;
383 	} else if (val == 0 && val2 == 250000) {
384 		new_gain = 0x1800;
385 		gain_idx = 2;
386 	} else if (val == 1 && val2 == 0) {
387 		new_gain = 0x00;
388 		gain_idx = 1;
389 	} else if (val == 2 && val2 == 0) {
390 		new_gain = 0x800;
391 		gain_idx = 0;
392 	} else {
393 		return -EINVAL;
394 	}
395 
396 	ret = regmap_update_bits(data->regmap, VEML6030_REG_ALS_CONF,
397 					VEML6030_ALS_GAIN, new_gain);
398 	if (ret) {
399 		dev_err(&data->client->dev,
400 				"can't set als gain %d\n", ret);
401 		return ret;
402 	}
403 
404 	/*
405 	 * Cache currently set gain & update resolution. For every
406 	 * increase in the gain to next level, resolution is halved
407 	 * and vice-versa.
408 	 */
409 	if (data->cur_gain < gain_idx)
410 		data->cur_resolution <<= gain_idx - data->cur_gain;
411 	else if (data->cur_gain > gain_idx)
412 		data->cur_resolution >>= data->cur_gain - gain_idx;
413 
414 	data->cur_gain = gain_idx;
415 
416 	return ret;
417 }
418 
veml6030_get_als_gain(struct iio_dev * indio_dev,int * val,int * val2)419 static int veml6030_get_als_gain(struct iio_dev *indio_dev,
420 						int *val, int *val2)
421 {
422 	int ret, reg;
423 	struct veml6030_data *data = iio_priv(indio_dev);
424 
425 	ret = regmap_read(data->regmap, VEML6030_REG_ALS_CONF, &reg);
426 	if (ret) {
427 		dev_err(&data->client->dev,
428 				"can't read als conf register %d\n", ret);
429 		return ret;
430 	}
431 
432 	switch ((reg >> 11) & 0x03) {
433 	case 0:
434 		*val = 1;
435 		*val2 = 0;
436 		break;
437 	case 1:
438 		*val = 2;
439 		*val2 = 0;
440 		break;
441 	case 2:
442 		*val = 0;
443 		*val2 = 125000;
444 		break;
445 	case 3:
446 		*val = 0;
447 		*val2 = 250000;
448 		break;
449 	default:
450 		return -EINVAL;
451 	}
452 
453 	return IIO_VAL_INT_PLUS_MICRO;
454 }
455 
veml6030_read_thresh(struct iio_dev * indio_dev,int * val,int * val2,int dir)456 static int veml6030_read_thresh(struct iio_dev *indio_dev,
457 						int *val, int *val2, int dir)
458 {
459 	int ret, reg;
460 	struct veml6030_data *data = iio_priv(indio_dev);
461 
462 	if (dir == IIO_EV_DIR_RISING)
463 		ret = regmap_read(data->regmap, VEML6030_REG_ALS_WH, &reg);
464 	else
465 		ret = regmap_read(data->regmap, VEML6030_REG_ALS_WL, &reg);
466 	if (ret) {
467 		dev_err(&data->client->dev,
468 				"can't read als threshold value %d\n", ret);
469 		return ret;
470 	}
471 
472 	*val = reg & 0xffff;
473 	return IIO_VAL_INT;
474 }
475 
veml6030_write_thresh(struct iio_dev * indio_dev,int val,int val2,int dir)476 static int veml6030_write_thresh(struct iio_dev *indio_dev,
477 						int val, int val2, int dir)
478 {
479 	int ret;
480 	struct veml6030_data *data = iio_priv(indio_dev);
481 
482 	if (val > 0xFFFF || val < 0 || val2)
483 		return -EINVAL;
484 
485 	if (dir == IIO_EV_DIR_RISING) {
486 		ret = regmap_write(data->regmap, VEML6030_REG_ALS_WH, val);
487 		if (ret)
488 			dev_err(&data->client->dev,
489 					"can't set high threshold %d\n", ret);
490 	} else {
491 		ret = regmap_write(data->regmap, VEML6030_REG_ALS_WL, val);
492 		if (ret)
493 			dev_err(&data->client->dev,
494 					"can't set low threshold %d\n", ret);
495 	}
496 
497 	return ret;
498 }
499 
500 /*
501  * Provide both raw as well as light reading in lux.
502  * light (in lux) = resolution * raw reading
503  */
veml6030_read_raw(struct iio_dev * indio_dev,struct iio_chan_spec const * chan,int * val,int * val2,long mask)504 static int veml6030_read_raw(struct iio_dev *indio_dev,
505 			    struct iio_chan_spec const *chan, int *val,
506 			    int *val2, long mask)
507 {
508 	int ret, reg;
509 	struct veml6030_data *data = iio_priv(indio_dev);
510 	struct regmap *regmap = data->regmap;
511 	struct device *dev = &data->client->dev;
512 
513 	switch (mask) {
514 	case IIO_CHAN_INFO_RAW:
515 	case IIO_CHAN_INFO_PROCESSED:
516 		switch (chan->type) {
517 		case IIO_LIGHT:
518 			ret = regmap_read(regmap, VEML6030_REG_ALS_DATA, &reg);
519 			if (ret < 0) {
520 				dev_err(dev, "can't read als data %d\n", ret);
521 				return ret;
522 			}
523 			if (mask == IIO_CHAN_INFO_PROCESSED) {
524 				*val = (reg * data->cur_resolution) / 10000;
525 				*val2 = (reg * data->cur_resolution) % 10000 * 100;
526 				return IIO_VAL_INT_PLUS_MICRO;
527 			}
528 			*val = reg;
529 			return IIO_VAL_INT;
530 		case IIO_INTENSITY:
531 			ret = regmap_read(regmap, VEML6030_REG_WH_DATA, &reg);
532 			if (ret < 0) {
533 				dev_err(dev, "can't read white data %d\n", ret);
534 				return ret;
535 			}
536 			if (mask == IIO_CHAN_INFO_PROCESSED) {
537 				*val = (reg * data->cur_resolution) / 10000;
538 				*val2 = (reg * data->cur_resolution) % 10000;
539 				return IIO_VAL_INT_PLUS_MICRO;
540 			}
541 			*val = reg;
542 			return IIO_VAL_INT;
543 		default:
544 			return -EINVAL;
545 		}
546 	case IIO_CHAN_INFO_INT_TIME:
547 		if (chan->type == IIO_LIGHT)
548 			return veml6030_get_intgrn_tm(indio_dev, val, val2);
549 		return -EINVAL;
550 	case IIO_CHAN_INFO_SCALE:
551 		if (chan->type == IIO_LIGHT)
552 			return veml6030_get_als_gain(indio_dev, val, val2);
553 		return -EINVAL;
554 	default:
555 		return -EINVAL;
556 	}
557 }
558 
veml6030_write_raw(struct iio_dev * indio_dev,struct iio_chan_spec const * chan,int val,int val2,long mask)559 static int veml6030_write_raw(struct iio_dev *indio_dev,
560 				struct iio_chan_spec const *chan,
561 				int val, int val2, long mask)
562 {
563 	switch (mask) {
564 	case IIO_CHAN_INFO_INT_TIME:
565 		switch (chan->type) {
566 		case IIO_LIGHT:
567 			return veml6030_set_intgrn_tm(indio_dev, val, val2);
568 		default:
569 			return -EINVAL;
570 		}
571 	case IIO_CHAN_INFO_SCALE:
572 		switch (chan->type) {
573 		case IIO_LIGHT:
574 			return veml6030_set_als_gain(indio_dev, val, val2);
575 		default:
576 			return -EINVAL;
577 		}
578 	default:
579 		return -EINVAL;
580 	}
581 }
582 
veml6030_read_event_val(struct iio_dev * indio_dev,const struct iio_chan_spec * chan,enum iio_event_type type,enum iio_event_direction dir,enum iio_event_info info,int * val,int * val2)583 static int veml6030_read_event_val(struct iio_dev *indio_dev,
584 		const struct iio_chan_spec *chan, enum iio_event_type type,
585 		enum iio_event_direction dir, enum iio_event_info info,
586 		int *val, int *val2)
587 {
588 	switch (info) {
589 	case IIO_EV_INFO_VALUE:
590 		switch (dir) {
591 		case IIO_EV_DIR_RISING:
592 		case IIO_EV_DIR_FALLING:
593 			return veml6030_read_thresh(indio_dev, val, val2, dir);
594 		default:
595 			return -EINVAL;
596 		}
597 		break;
598 	case IIO_EV_INFO_PERIOD:
599 		return veml6030_read_persistence(indio_dev, val, val2);
600 	default:
601 		return -EINVAL;
602 	}
603 }
604 
veml6030_write_event_val(struct iio_dev * indio_dev,const struct iio_chan_spec * chan,enum iio_event_type type,enum iio_event_direction dir,enum iio_event_info info,int val,int val2)605 static int veml6030_write_event_val(struct iio_dev *indio_dev,
606 		const struct iio_chan_spec *chan, enum iio_event_type type,
607 		enum iio_event_direction dir, enum iio_event_info info,
608 		int val, int val2)
609 {
610 	switch (info) {
611 	case IIO_EV_INFO_VALUE:
612 		return veml6030_write_thresh(indio_dev, val, val2, dir);
613 	case IIO_EV_INFO_PERIOD:
614 		return veml6030_write_persistence(indio_dev, val, val2);
615 	default:
616 		return -EINVAL;
617 	}
618 }
619 
veml6030_read_interrupt_config(struct iio_dev * indio_dev,const struct iio_chan_spec * chan,enum iio_event_type type,enum iio_event_direction dir)620 static int veml6030_read_interrupt_config(struct iio_dev *indio_dev,
621 		const struct iio_chan_spec *chan, enum iio_event_type type,
622 		enum iio_event_direction dir)
623 {
624 	int ret, reg;
625 	struct veml6030_data *data = iio_priv(indio_dev);
626 
627 	ret = regmap_read(data->regmap, VEML6030_REG_ALS_CONF, &reg);
628 	if (ret) {
629 		dev_err(&data->client->dev,
630 				"can't read als conf register %d\n", ret);
631 		return ret;
632 	}
633 
634 	if (reg & VEML6030_ALS_INT_EN)
635 		return 1;
636 	else
637 		return 0;
638 }
639 
640 /*
641  * Sensor should not be measuring light when interrupt is configured.
642  * Therefore correct sequence to configure interrupt functionality is:
643  * shut down -> enable/disable interrupt -> power on
644  *
645  * state = 1 enables interrupt, state = 0 disables interrupt
646  */
veml6030_write_interrupt_config(struct iio_dev * indio_dev,const struct iio_chan_spec * chan,enum iio_event_type type,enum iio_event_direction dir,int state)647 static int veml6030_write_interrupt_config(struct iio_dev *indio_dev,
648 		const struct iio_chan_spec *chan, enum iio_event_type type,
649 		enum iio_event_direction dir, int state)
650 {
651 	int ret;
652 	struct veml6030_data *data = iio_priv(indio_dev);
653 
654 	if (state < 0 || state > 1)
655 		return -EINVAL;
656 
657 	ret = veml6030_als_shut_down(data);
658 	if (ret < 0) {
659 		dev_err(&data->client->dev,
660 			"can't disable als to configure interrupt %d\n", ret);
661 		return ret;
662 	}
663 
664 	/* enable interrupt + power on */
665 	ret = regmap_update_bits(data->regmap, VEML6030_REG_ALS_CONF,
666 			VEML6030_ALS_INT_EN | VEML6030_ALS_SD, state << 1);
667 	if (ret)
668 		dev_err(&data->client->dev,
669 			"can't enable interrupt & poweron als %d\n", ret);
670 
671 	return ret;
672 }
673 
674 static const struct iio_info veml6030_info = {
675 	.read_raw  = veml6030_read_raw,
676 	.write_raw = veml6030_write_raw,
677 	.read_event_value = veml6030_read_event_val,
678 	.write_event_value	= veml6030_write_event_val,
679 	.read_event_config = veml6030_read_interrupt_config,
680 	.write_event_config	= veml6030_write_interrupt_config,
681 	.attrs = &veml6030_attr_group,
682 	.event_attrs = &veml6030_event_attr_group,
683 };
684 
685 static const struct iio_info veml6030_info_no_irq = {
686 	.read_raw  = veml6030_read_raw,
687 	.write_raw = veml6030_write_raw,
688 	.attrs = &veml6030_attr_group,
689 };
690 
veml6030_event_handler(int irq,void * private)691 static irqreturn_t veml6030_event_handler(int irq, void *private)
692 {
693 	int ret, reg, evtdir;
694 	struct iio_dev *indio_dev = private;
695 	struct veml6030_data *data = iio_priv(indio_dev);
696 
697 	ret = regmap_read(data->regmap, VEML6030_REG_ALS_INT, &reg);
698 	if (ret) {
699 		dev_err(&data->client->dev,
700 				"can't read als interrupt register %d\n", ret);
701 		return IRQ_HANDLED;
702 	}
703 
704 	/* Spurious interrupt handling */
705 	if (!(reg & (VEML6030_INT_TH_HIGH | VEML6030_INT_TH_LOW)))
706 		return IRQ_NONE;
707 
708 	if (reg & VEML6030_INT_TH_HIGH)
709 		evtdir = IIO_EV_DIR_RISING;
710 	else
711 		evtdir = IIO_EV_DIR_FALLING;
712 
713 	iio_push_event(indio_dev, IIO_UNMOD_EVENT_CODE(IIO_INTENSITY,
714 					0, IIO_EV_TYPE_THRESH, evtdir),
715 					iio_get_time_ns(indio_dev));
716 
717 	return IRQ_HANDLED;
718 }
719 
720 /*
721  * Set ALS gain to 1/8, integration time to 100 ms, PSM to mode 2,
722  * persistence to 1 x integration time and the threshold
723  * interrupt disabled by default. First shutdown the sensor,
724  * update registers and then power on the sensor.
725  */
veml6030_hw_init(struct iio_dev * indio_dev)726 static int veml6030_hw_init(struct iio_dev *indio_dev)
727 {
728 	int ret, val;
729 	struct veml6030_data *data = iio_priv(indio_dev);
730 	struct i2c_client *client = data->client;
731 
732 	ret = veml6030_als_shut_down(data);
733 	if (ret) {
734 		dev_err(&client->dev, "can't shutdown als %d\n", ret);
735 		return ret;
736 	}
737 
738 	ret = regmap_write(data->regmap, VEML6030_REG_ALS_CONF, 0x1001);
739 	if (ret) {
740 		dev_err(&client->dev, "can't setup als configs %d\n", ret);
741 		return ret;
742 	}
743 
744 	ret = regmap_update_bits(data->regmap, VEML6030_REG_ALS_PSM,
745 				 VEML6030_PSM | VEML6030_PSM_EN, 0x03);
746 	if (ret) {
747 		dev_err(&client->dev, "can't setup default PSM %d\n", ret);
748 		return ret;
749 	}
750 
751 	ret = regmap_write(data->regmap, VEML6030_REG_ALS_WH, 0xFFFF);
752 	if (ret) {
753 		dev_err(&client->dev, "can't setup high threshold %d\n", ret);
754 		return ret;
755 	}
756 
757 	ret = regmap_write(data->regmap, VEML6030_REG_ALS_WL, 0x0000);
758 	if (ret) {
759 		dev_err(&client->dev, "can't setup low threshold %d\n", ret);
760 		return ret;
761 	}
762 
763 	ret = veml6030_als_pwr_on(data);
764 	if (ret) {
765 		dev_err(&client->dev, "can't poweron als %d\n", ret);
766 		return ret;
767 	}
768 
769 	/* Wait 4 ms to let processor & oscillator start correctly */
770 	usleep_range(4000, 4002);
771 
772 	/* Clear stale interrupt status bits if any during start */
773 	ret = regmap_read(data->regmap, VEML6030_REG_ALS_INT, &val);
774 	if (ret < 0) {
775 		dev_err(&client->dev,
776 			"can't clear als interrupt status %d\n", ret);
777 		return ret;
778 	}
779 
780 	/* Cache currently active measurement parameters */
781 	data->cur_gain = 3;
782 	data->cur_resolution = 5376;
783 	data->cur_integration_time = 3;
784 
785 	return ret;
786 }
787 
veml6030_probe(struct i2c_client * client)788 static int veml6030_probe(struct i2c_client *client)
789 {
790 	int ret;
791 	struct veml6030_data *data;
792 	struct iio_dev *indio_dev;
793 	struct regmap *regmap;
794 
795 	if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
796 		dev_err(&client->dev, "i2c adapter doesn't support plain i2c\n");
797 		return -EOPNOTSUPP;
798 	}
799 
800 	regmap = devm_regmap_init_i2c(client, &veml6030_regmap_config);
801 	if (IS_ERR(regmap)) {
802 		dev_err(&client->dev, "can't setup regmap\n");
803 		return PTR_ERR(regmap);
804 	}
805 
806 	indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
807 	if (!indio_dev)
808 		return -ENOMEM;
809 
810 	data = iio_priv(indio_dev);
811 	i2c_set_clientdata(client, indio_dev);
812 	data->client = client;
813 	data->regmap = regmap;
814 
815 	indio_dev->name = "veml6030";
816 	indio_dev->channels = veml6030_channels;
817 	indio_dev->num_channels = ARRAY_SIZE(veml6030_channels);
818 	indio_dev->modes = INDIO_DIRECT_MODE;
819 
820 	if (client->irq) {
821 		ret = devm_request_threaded_irq(&client->dev, client->irq,
822 						NULL, veml6030_event_handler,
823 						IRQF_TRIGGER_LOW | IRQF_ONESHOT,
824 						"veml6030", indio_dev);
825 		if (ret < 0) {
826 			dev_err(&client->dev,
827 					"irq %d request failed\n", client->irq);
828 			return ret;
829 		}
830 		indio_dev->info = &veml6030_info;
831 	} else {
832 		indio_dev->info = &veml6030_info_no_irq;
833 	}
834 
835 	ret = veml6030_hw_init(indio_dev);
836 	if (ret < 0)
837 		return ret;
838 
839 	ret = devm_add_action_or_reset(&client->dev,
840 					veml6030_als_shut_down_action, data);
841 	if (ret < 0)
842 		return ret;
843 
844 	return devm_iio_device_register(&client->dev, indio_dev);
845 }
846 
veml6030_runtime_suspend(struct device * dev)847 static int veml6030_runtime_suspend(struct device *dev)
848 {
849 	int ret;
850 	struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
851 	struct veml6030_data *data = iio_priv(indio_dev);
852 
853 	ret = veml6030_als_shut_down(data);
854 	if (ret < 0)
855 		dev_err(&data->client->dev, "can't suspend als %d\n", ret);
856 
857 	return ret;
858 }
859 
veml6030_runtime_resume(struct device * dev)860 static int veml6030_runtime_resume(struct device *dev)
861 {
862 	int ret;
863 	struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
864 	struct veml6030_data *data = iio_priv(indio_dev);
865 
866 	ret = veml6030_als_pwr_on(data);
867 	if (ret < 0)
868 		dev_err(&data->client->dev, "can't resume als %d\n", ret);
869 
870 	return ret;
871 }
872 
873 static DEFINE_RUNTIME_DEV_PM_OPS(veml6030_pm_ops, veml6030_runtime_suspend,
874 				 veml6030_runtime_resume, NULL);
875 
876 static const struct of_device_id veml6030_of_match[] = {
877 	{ .compatible = "vishay,veml6030" },
878 	{ }
879 };
880 MODULE_DEVICE_TABLE(of, veml6030_of_match);
881 
882 static const struct i2c_device_id veml6030_id[] = {
883 	{ "veml6030" },
884 	{ }
885 };
886 MODULE_DEVICE_TABLE(i2c, veml6030_id);
887 
888 static struct i2c_driver veml6030_driver = {
889 	.driver = {
890 		.name = "veml6030",
891 		.of_match_table = veml6030_of_match,
892 		.pm = pm_ptr(&veml6030_pm_ops),
893 	},
894 	.probe = veml6030_probe,
895 	.id_table = veml6030_id,
896 };
897 module_i2c_driver(veml6030_driver);
898 
899 MODULE_AUTHOR("Rishi Gupta <gupt21@gmail.com>");
900 MODULE_DESCRIPTION("VEML6030 Ambient Light Sensor");
901 MODULE_LICENSE("GPL v2");
902