1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Vishay VEML6075 UVA and UVB light sensor
4  *
5  * Copyright 2023 Javier Carrasco <[email protected]>
6  *
7  * 7-bit I2C slave, address 0x10
8  */
9 
10 #include <linux/bitfield.h>
11 #include <linux/delay.h>
12 #include <linux/err.h>
13 #include <linux/i2c.h>
14 #include <linux/module.h>
15 #include <linux/mutex.h>
16 #include <linux/regmap.h>
17 #include <linux/units.h>
18 
19 #include <linux/iio/iio.h>
20 
21 #define VEML6075_CMD_CONF	0x00 /* configuration register */
22 #define VEML6075_CMD_UVA	0x07 /* UVA channel */
23 #define VEML6075_CMD_UVB	0x09 /* UVB channel */
24 #define VEML6075_CMD_COMP1	0x0A /* visible light compensation */
25 #define VEML6075_CMD_COMP2	0x0B /* infrarred light compensation */
26 #define VEML6075_CMD_ID		0x0C /* device ID */
27 
28 #define VEML6075_CONF_IT	GENMASK(6, 4) /* intregration time */
29 #define VEML6075_CONF_HD	BIT(3) /* dynamic setting */
30 #define VEML6075_CONF_TRIG	BIT(2) /* trigger */
31 #define VEML6075_CONF_AF	BIT(1) /* active force enable */
32 #define VEML6075_CONF_SD	BIT(0) /* shutdown */
33 
34 #define VEML6075_IT_50_MS	0x00
35 #define VEML6075_IT_100_MS	0x01
36 #define VEML6075_IT_200_MS	0x02
37 #define VEML6075_IT_400_MS	0x03
38 #define VEML6075_IT_800_MS	0x04
39 
40 #define VEML6075_AF_DISABLE	0x00
41 #define VEML6075_AF_ENABLE	0x01
42 
43 #define VEML6075_SD_DISABLE	0x00
44 #define VEML6075_SD_ENABLE	0x01
45 
46 /* Open-air coefficients and responsivity */
47 #define VEML6075_A_COEF		2220
48 #define VEML6075_B_COEF		1330
49 #define VEML6075_C_COEF		2950
50 #define VEML6075_D_COEF		1740
51 #define VEML6075_UVA_RESP	1461
52 #define VEML6075_UVB_RESP	2591
53 
54 static const int veml6075_it_ms[] = { 50, 100, 200, 400, 800 };
55 
56 struct veml6075_data {
57 	struct i2c_client *client;
58 	struct regmap *regmap;
59 	/*
60 	 * prevent integration time modification and triggering
61 	 * measurements while a measurement is underway.
62 	 */
63 	struct mutex lock;
64 };
65 
66 /* channel number */
67 enum veml6075_chan {
68 	CH_UVA,
69 	CH_UVB,
70 };
71 
72 static const struct iio_chan_spec veml6075_channels[] = {
73 	{
74 		.type = IIO_INTENSITY,
75 		.channel = CH_UVA,
76 		.modified = 1,
77 		.channel2 = IIO_MOD_LIGHT_UVA,
78 		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
79 			BIT(IIO_CHAN_INFO_SCALE),
80 		.info_mask_shared_by_all = BIT(IIO_CHAN_INFO_INT_TIME),
81 		.info_mask_shared_by_all_available = BIT(IIO_CHAN_INFO_INT_TIME),
82 	},
83 	{
84 		.type = IIO_INTENSITY,
85 		.channel = CH_UVB,
86 		.modified = 1,
87 		.channel2 = IIO_MOD_LIGHT_UVB,
88 		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
89 			BIT(IIO_CHAN_INFO_SCALE),
90 		.info_mask_shared_by_all = BIT(IIO_CHAN_INFO_INT_TIME),
91 		.info_mask_shared_by_all_available = BIT(IIO_CHAN_INFO_INT_TIME),
92 	},
93 	{
94 		.type = IIO_UVINDEX,
95 		.info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED),
96 		.info_mask_shared_by_all = BIT(IIO_CHAN_INFO_INT_TIME),
97 		.info_mask_shared_by_all_available = BIT(IIO_CHAN_INFO_INT_TIME),
98 	},
99 };
100 
veml6075_request_measurement(struct veml6075_data * data)101 static int veml6075_request_measurement(struct veml6075_data *data)
102 {
103 	int ret, conf, int_time;
104 
105 	ret = regmap_read(data->regmap, VEML6075_CMD_CONF, &conf);
106 	if (ret < 0)
107 		return ret;
108 
109 	/* disable shutdown and trigger measurement */
110 	ret = regmap_write(data->regmap, VEML6075_CMD_CONF,
111 			   (conf | VEML6075_CONF_TRIG) & ~VEML6075_CONF_SD);
112 	if (ret < 0)
113 		return ret;
114 
115 	/*
116 	 * A measurement requires between 1.30 and 1.40 times the integration
117 	 * time for all possible configurations. Using a 1.50 factor simplifies
118 	 * operations and ensures reliability under all circumstances.
119 	 */
120 	int_time = veml6075_it_ms[FIELD_GET(VEML6075_CONF_IT, conf)];
121 	msleep(int_time + (int_time / 2));
122 
123 	/* shutdown again, data registers are still accessible */
124 	return regmap_update_bits(data->regmap, VEML6075_CMD_CONF,
125 				  VEML6075_CONF_SD, VEML6075_CONF_SD);
126 }
127 
veml6075_uva_comp(int raw_uva,int comp1,int comp2)128 static int veml6075_uva_comp(int raw_uva, int comp1, int comp2)
129 {
130 	int comp1a_c, comp2a_c, uva_comp;
131 
132 	comp1a_c = (comp1 * VEML6075_A_COEF) / 1000U;
133 	comp2a_c = (comp2 * VEML6075_B_COEF) / 1000U;
134 	uva_comp = raw_uva - comp1a_c - comp2a_c;
135 
136 	return clamp_val(uva_comp, 0, U16_MAX);
137 }
138 
veml6075_uvb_comp(int raw_uvb,int comp1,int comp2)139 static int veml6075_uvb_comp(int raw_uvb, int comp1, int comp2)
140 {
141 	int comp1b_c, comp2b_c, uvb_comp;
142 
143 	comp1b_c = (comp1 * VEML6075_C_COEF) / 1000U;
144 	comp2b_c = (comp2 * VEML6075_D_COEF) / 1000U;
145 	uvb_comp = raw_uvb - comp1b_c - comp2b_c;
146 
147 	return clamp_val(uvb_comp, 0, U16_MAX);
148 }
149 
veml6075_read_comp(struct veml6075_data * data,int * c1,int * c2)150 static int veml6075_read_comp(struct veml6075_data *data, int *c1, int *c2)
151 {
152 	int ret;
153 
154 	ret = regmap_read(data->regmap, VEML6075_CMD_COMP1, c1);
155 	if (ret < 0)
156 		return ret;
157 
158 	return regmap_read(data->regmap, VEML6075_CMD_COMP2, c2);
159 }
160 
veml6075_read_uv_direct(struct veml6075_data * data,int chan,int * val)161 static int veml6075_read_uv_direct(struct veml6075_data *data, int chan,
162 				   int *val)
163 {
164 	int c1, c2, ret;
165 
166 	guard(mutex)(&data->lock);
167 
168 	ret = veml6075_request_measurement(data);
169 	if (ret < 0)
170 		return ret;
171 
172 	ret = veml6075_read_comp(data, &c1, &c2);
173 	if (ret < 0)
174 		return ret;
175 
176 	switch (chan) {
177 	case CH_UVA:
178 		ret = regmap_read(data->regmap, VEML6075_CMD_UVA, val);
179 		if (ret < 0)
180 			return ret;
181 
182 		*val = veml6075_uva_comp(*val, c1, c2);
183 		return IIO_VAL_INT;
184 	case CH_UVB:
185 		ret = regmap_read(data->regmap, VEML6075_CMD_UVB, val);
186 		if (ret < 0)
187 			return ret;
188 
189 		*val = veml6075_uvb_comp(*val, c1, c2);
190 		return IIO_VAL_INT;
191 	default:
192 		return -EINVAL;
193 	}
194 }
195 
veml6075_read_int_time_index(struct veml6075_data * data)196 static int veml6075_read_int_time_index(struct veml6075_data *data)
197 {
198 	int ret, conf, int_index;
199 
200 	ret = regmap_read(data->regmap, VEML6075_CMD_CONF, &conf);
201 	if (ret < 0)
202 		return ret;
203 
204 	int_index = FIELD_GET(VEML6075_CONF_IT, conf);
205 	if (int_index >= ARRAY_SIZE(veml6075_it_ms))
206 		return -EINVAL;
207 
208 	return int_index;
209 }
210 
veml6075_read_int_time_ms(struct veml6075_data * data,int * val)211 static int veml6075_read_int_time_ms(struct veml6075_data *data, int *val)
212 {
213 	int int_index;
214 
215 	guard(mutex)(&data->lock);
216 	int_index = veml6075_read_int_time_index(data);
217 	if (int_index < 0)
218 		return int_index;
219 
220 	*val = veml6075_it_ms[int_index];
221 
222 	return IIO_VAL_INT;
223 }
224 
veml6075_get_uvi_micro(struct veml6075_data * data,int uva_comp,int uvb_comp)225 static int veml6075_get_uvi_micro(struct veml6075_data *data, int uva_comp,
226 				  int uvb_comp)
227 {
228 	int uvia_micro = uva_comp * VEML6075_UVA_RESP;
229 	int uvib_micro = uvb_comp * VEML6075_UVB_RESP;
230 	int int_index;
231 
232 	int_index = veml6075_read_int_time_index(data);
233 	if (int_index < 0)
234 		return int_index;
235 
236 	switch (int_index) {
237 	case VEML6075_IT_50_MS:
238 		return uvia_micro + uvib_micro;
239 	case VEML6075_IT_100_MS:
240 	case VEML6075_IT_200_MS:
241 	case VEML6075_IT_400_MS:
242 	case VEML6075_IT_800_MS:
243 		return (uvia_micro + uvib_micro) / (2 << int_index);
244 	default:
245 		return -EINVAL;
246 	}
247 }
248 
veml6075_read_uvi(struct veml6075_data * data,int * val,int * val2)249 static int veml6075_read_uvi(struct veml6075_data *data, int *val, int *val2)
250 {
251 	int ret, c1, c2, uva, uvb, uvi_micro;
252 
253 	guard(mutex)(&data->lock);
254 
255 	ret = veml6075_request_measurement(data);
256 	if (ret < 0)
257 		return ret;
258 
259 	ret = veml6075_read_comp(data, &c1, &c2);
260 	if (ret < 0)
261 		return ret;
262 
263 	ret = regmap_read(data->regmap, VEML6075_CMD_UVA, &uva);
264 	if (ret < 0)
265 		return ret;
266 
267 	ret = regmap_read(data->regmap, VEML6075_CMD_UVB, &uvb);
268 	if (ret < 0)
269 		return ret;
270 
271 	uvi_micro = veml6075_get_uvi_micro(data, veml6075_uva_comp(uva, c1, c2),
272 					   veml6075_uvb_comp(uvb, c1, c2));
273 	if (uvi_micro < 0)
274 		return uvi_micro;
275 
276 	*val = uvi_micro / MICRO;
277 	*val2 = uvi_micro % MICRO;
278 
279 	return IIO_VAL_INT_PLUS_MICRO;
280 }
281 
veml6075_read_responsivity(int chan,int * val,int * val2)282 static int veml6075_read_responsivity(int chan, int *val, int *val2)
283 {
284 	/* scale = 1 / resp */
285 	switch (chan) {
286 	case CH_UVA:
287 		/* resp = 0.93 c/uW/cm2: scale = 1.75268817 */
288 		*val = 1;
289 		*val2 = 75268817;
290 		return IIO_VAL_INT_PLUS_NANO;
291 	case CH_UVB:
292 		/* resp = 2.1 c/uW/cm2: scale = 0.476190476 */
293 		*val = 0;
294 		*val2 = 476190476;
295 		return IIO_VAL_INT_PLUS_NANO;
296 	default:
297 		return -EINVAL;
298 	}
299 }
300 
veml6075_read_avail(struct iio_dev * indio_dev,struct iio_chan_spec const * chan,const int ** vals,int * type,int * length,long mask)301 static int veml6075_read_avail(struct iio_dev *indio_dev,
302 			       struct iio_chan_spec const *chan,
303 			       const int **vals, int *type, int *length,
304 			       long mask)
305 {
306 	switch (mask) {
307 	case IIO_CHAN_INFO_INT_TIME:
308 		*length = ARRAY_SIZE(veml6075_it_ms);
309 		*vals = veml6075_it_ms;
310 		*type = IIO_VAL_INT;
311 		return IIO_AVAIL_LIST;
312 
313 	default:
314 		return -EINVAL;
315 	}
316 }
317 
veml6075_read_raw(struct iio_dev * indio_dev,struct iio_chan_spec const * chan,int * val,int * val2,long mask)318 static int veml6075_read_raw(struct iio_dev *indio_dev,
319 			     struct iio_chan_spec const *chan,
320 			     int *val, int *val2, long mask)
321 {
322 	struct veml6075_data *data = iio_priv(indio_dev);
323 
324 	switch (mask) {
325 	case IIO_CHAN_INFO_RAW:
326 		return veml6075_read_uv_direct(data, chan->channel, val);
327 	case IIO_CHAN_INFO_PROCESSED:
328 		return veml6075_read_uvi(data, val, val2);
329 	case IIO_CHAN_INFO_INT_TIME:
330 		return veml6075_read_int_time_ms(data, val);
331 	case IIO_CHAN_INFO_SCALE:
332 		return veml6075_read_responsivity(chan->channel, val, val2);
333 	default:
334 		return -EINVAL;
335 	}
336 }
337 
veml6075_write_int_time_ms(struct veml6075_data * data,int val)338 static int veml6075_write_int_time_ms(struct veml6075_data *data, int val)
339 {
340 	int i = ARRAY_SIZE(veml6075_it_ms);
341 
342 	guard(mutex)(&data->lock);
343 
344 	while (i-- > 0) {
345 		if (val == veml6075_it_ms[i])
346 			break;
347 	}
348 	if (i < 0)
349 		return -EINVAL;
350 
351 	return regmap_update_bits(data->regmap, VEML6075_CMD_CONF,
352 				  VEML6075_CONF_IT,
353 				  FIELD_PREP(VEML6075_CONF_IT, i));
354 }
355 
veml6075_write_raw(struct iio_dev * indio_dev,struct iio_chan_spec const * chan,int val,int val2,long mask)356 static int veml6075_write_raw(struct iio_dev *indio_dev,
357 			      struct iio_chan_spec const *chan,
358 			      int val, int val2, long mask)
359 {
360 	struct veml6075_data *data = iio_priv(indio_dev);
361 
362 	switch (mask) {
363 	case IIO_CHAN_INFO_INT_TIME:
364 		return veml6075_write_int_time_ms(data, val);
365 	default:
366 		return -EINVAL;
367 	}
368 }
369 
370 static const struct iio_info veml6075_info = {
371 	.read_avail = veml6075_read_avail,
372 	.read_raw = veml6075_read_raw,
373 	.write_raw = veml6075_write_raw,
374 };
375 
veml6075_readable_reg(struct device * dev,unsigned int reg)376 static bool veml6075_readable_reg(struct device *dev, unsigned int reg)
377 {
378 	switch (reg) {
379 	case VEML6075_CMD_CONF:
380 	case VEML6075_CMD_UVA:
381 	case VEML6075_CMD_UVB:
382 	case VEML6075_CMD_COMP1:
383 	case VEML6075_CMD_COMP2:
384 	case VEML6075_CMD_ID:
385 		return true;
386 	default:
387 		return false;
388 	}
389 }
390 
veml6075_writable_reg(struct device * dev,unsigned int reg)391 static bool veml6075_writable_reg(struct device *dev, unsigned int reg)
392 {
393 	switch (reg) {
394 	case VEML6075_CMD_CONF:
395 		return true;
396 	default:
397 		return false;
398 	}
399 }
400 
401 static const struct regmap_config veml6075_regmap_config = {
402 	.name = "veml6075",
403 	.reg_bits = 8,
404 	.val_bits = 16,
405 	.max_register = VEML6075_CMD_ID,
406 	.readable_reg = veml6075_readable_reg,
407 	.writeable_reg = veml6075_writable_reg,
408 	.val_format_endian = REGMAP_ENDIAN_LITTLE,
409 };
410 
veml6075_probe(struct i2c_client * client)411 static int veml6075_probe(struct i2c_client *client)
412 {
413 	struct veml6075_data *data;
414 	struct iio_dev *indio_dev;
415 	struct regmap *regmap;
416 	int config, ret;
417 
418 	indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
419 	if (!indio_dev)
420 		return -ENOMEM;
421 
422 	regmap = devm_regmap_init_i2c(client, &veml6075_regmap_config);
423 	if (IS_ERR(regmap))
424 		return PTR_ERR(regmap);
425 
426 	data = iio_priv(indio_dev);
427 	data->client = client;
428 	data->regmap = regmap;
429 
430 	mutex_init(&data->lock);
431 
432 	indio_dev->name = "veml6075";
433 	indio_dev->info = &veml6075_info;
434 	indio_dev->channels = veml6075_channels;
435 	indio_dev->num_channels = ARRAY_SIZE(veml6075_channels);
436 	indio_dev->modes = INDIO_DIRECT_MODE;
437 
438 	ret = devm_regulator_get_enable(&client->dev, "vdd");
439 	if (ret < 0)
440 		return ret;
441 
442 	/* default: 100ms integration time, active force enable, shutdown */
443 	config = FIELD_PREP(VEML6075_CONF_IT, VEML6075_IT_100_MS) |
444 		FIELD_PREP(VEML6075_CONF_AF, VEML6075_AF_ENABLE) |
445 		FIELD_PREP(VEML6075_CONF_SD, VEML6075_SD_ENABLE);
446 	ret = regmap_write(data->regmap, VEML6075_CMD_CONF, config);
447 	if (ret < 0)
448 		return ret;
449 
450 	return devm_iio_device_register(&client->dev, indio_dev);
451 }
452 
453 static const struct i2c_device_id veml6075_id[] = {
454 	{ "veml6075" },
455 	{ }
456 };
457 MODULE_DEVICE_TABLE(i2c, veml6075_id);
458 
459 static const struct of_device_id veml6075_of_match[] = {
460 	{ .compatible = "vishay,veml6075" },
461 	{}
462 };
463 MODULE_DEVICE_TABLE(of, veml6075_of_match);
464 
465 static struct i2c_driver veml6075_driver = {
466 	.driver = {
467 		.name   = "veml6075",
468 		.of_match_table = veml6075_of_match,
469 	},
470 	.probe = veml6075_probe,
471 	.id_table = veml6075_id,
472 };
473 
474 module_i2c_driver(veml6075_driver);
475 
476 MODULE_AUTHOR("Javier Carrasco <[email protected]>");
477 MODULE_DESCRIPTION("Vishay VEML6075 UVA and UVB light sensor driver");
478 MODULE_LICENSE("GPL");
479