xref: /linux/drivers/iio/proximity/isl29501.c (revision d2c9a99135da931377240942d44f3dea104cedb8)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * isl29501.c: ISL29501 Time of Flight sensor driver.
4  *
5  * Copyright (C) 2018
6  * Author: Mathieu Othacehe <m.othacehe@gmail.com>
7  *
8  * 7-bit I2C slave address: 0x57
9  */
10 
11 #include <linux/kernel.h>
12 #include <linux/module.h>
13 #include <linux/i2c.h>
14 #include <linux/err.h>
15 #include <linux/iio/iio.h>
16 #include <linux/iio/sysfs.h>
17 
18 #include <linux/iio/trigger_consumer.h>
19 #include <linux/iio/buffer.h>
20 #include <linux/iio/triggered_buffer.h>
21 
22 /* Control, setting and status registers */
23 #define ISL29501_DEVICE_ID			0x00
24 #define ISL29501_ID				0x0A
25 
26 /* Sampling control registers */
27 #define ISL29501_INTEGRATION_PERIOD		0x10
28 #define ISL29501_SAMPLE_PERIOD			0x11
29 
30 /* Closed loop calibration registers */
31 #define ISL29501_CROSSTALK_I_MSB		0x24
32 #define ISL29501_CROSSTALK_I_LSB		0x25
33 #define ISL29501_CROSSTALK_I_EXPONENT		0x26
34 #define ISL29501_CROSSTALK_Q_MSB		0x27
35 #define ISL29501_CROSSTALK_Q_LSB		0x28
36 #define ISL29501_CROSSTALK_Q_EXPONENT		0x29
37 #define ISL29501_CROSSTALK_GAIN_MSB		0x2A
38 #define ISL29501_CROSSTALK_GAIN_LSB		0x2B
39 #define ISL29501_MAGNITUDE_REF_EXP		0x2C
40 #define ISL29501_MAGNITUDE_REF_MSB		0x2D
41 #define ISL29501_MAGNITUDE_REF_LSB		0x2E
42 #define ISL29501_PHASE_OFFSET_MSB		0x2F
43 #define ISL29501_PHASE_OFFSET_LSB		0x30
44 
45 /* Analog control registers */
46 #define ISL29501_DRIVER_RANGE			0x90
47 #define ISL29501_EMITTER_DAC			0x91
48 
49 #define ISL29501_COMMAND_REGISTER		0xB0
50 
51 /* Commands */
52 #define ISL29501_EMUL_SAMPLE_START_PIN		0x49
53 #define ISL29501_RESET_ALL_REGISTERS		0xD7
54 #define ISL29501_RESET_INT_SM			0xD1
55 
56 /* Ambiant light and temperature corrections */
57 #define ISL29501_TEMP_REFERENCE			0x31
58 #define ISL29501_PHASE_EXPONENT			0x33
59 #define ISL29501_TEMP_COEFF_A			0x34
60 #define ISL29501_TEMP_COEFF_B			0x39
61 #define ISL29501_AMBIANT_COEFF_A		0x36
62 #define ISL29501_AMBIANT_COEFF_B		0x3B
63 
64 /* Data output registers */
65 #define ISL29501_DISTANCE_MSB_DATA		0xD1
66 #define ISL29501_DISTANCE_LSB_DATA		0xD2
67 #define ISL29501_PRECISION_MSB			0xD3
68 #define ISL29501_PRECISION_LSB			0xD4
69 #define ISL29501_MAGNITUDE_EXPONENT		0xD5
70 #define ISL29501_MAGNITUDE_MSB			0xD6
71 #define ISL29501_MAGNITUDE_LSB			0xD7
72 #define ISL29501_PHASE_MSB			0xD8
73 #define ISL29501_PHASE_LSB			0xD9
74 #define ISL29501_I_RAW_EXPONENT			0xDA
75 #define ISL29501_I_RAW_MSB			0xDB
76 #define ISL29501_I_RAW_LSB			0xDC
77 #define ISL29501_Q_RAW_EXPONENT			0xDD
78 #define ISL29501_Q_RAW_MSB			0xDE
79 #define ISL29501_Q_RAW_LSB			0xDF
80 #define ISL29501_DIE_TEMPERATURE		0xE2
81 #define ISL29501_AMBIENT_LIGHT			0xE3
82 #define ISL29501_GAIN_MSB			0xE6
83 #define ISL29501_GAIN_LSB			0xE7
84 
85 #define ISL29501_MAX_EXP_VAL 15
86 
87 #define ISL29501_INT_TIME_AVAILABLE \
88 	"0.00007 0.00014 0.00028 0.00057 0.00114 " \
89 	"0.00228 0.00455 0.00910 0.01820 0.03640 " \
90 	"0.07281 0.14561"
91 
92 #define ISL29501_CURRENT_SCALE_AVAILABLE \
93 	"0.0039 0.0078 0.0118 0.0157 0.0196 " \
94 	"0.0235 0.0275 0.0314 0.0352 0.0392 " \
95 	"0.0431 0.0471 0.0510 0.0549 0.0588"
96 
97 enum isl29501_correction_coeff {
98 	COEFF_TEMP_A,
99 	COEFF_TEMP_B,
100 	COEFF_LIGHT_A,
101 	COEFF_LIGHT_B,
102 	COEFF_MAX,
103 };
104 
105 struct isl29501_private {
106 	struct i2c_client *client;
107 	struct mutex lock;
108 	/* Exact representation of correction coefficients. */
109 	unsigned int shadow_coeffs[COEFF_MAX];
110 };
111 
112 enum isl29501_register_name {
113 	REG_DISTANCE,
114 	REG_PHASE,
115 	REG_TEMPERATURE,
116 	REG_AMBIENT_LIGHT,
117 	REG_GAIN,
118 	REG_GAIN_BIAS,
119 	REG_PHASE_EXP,
120 	REG_CALIB_PHASE_TEMP_A,
121 	REG_CALIB_PHASE_TEMP_B,
122 	REG_CALIB_PHASE_LIGHT_A,
123 	REG_CALIB_PHASE_LIGHT_B,
124 	REG_DISTANCE_BIAS,
125 	REG_TEMPERATURE_BIAS,
126 	REG_INT_TIME,
127 	REG_SAMPLE_TIME,
128 	REG_DRIVER_RANGE,
129 	REG_EMITTER_DAC,
130 };
131 
132 struct isl29501_register_desc {
133 	u8 msb;
134 	u8 lsb;
135 };
136 
137 static const struct isl29501_register_desc isl29501_registers[] = {
138 	[REG_DISTANCE] = {
139 		.msb = ISL29501_DISTANCE_MSB_DATA,
140 		.lsb = ISL29501_DISTANCE_LSB_DATA,
141 	},
142 	[REG_PHASE] = {
143 		.msb = ISL29501_PHASE_MSB,
144 		.lsb = ISL29501_PHASE_LSB,
145 	},
146 	[REG_TEMPERATURE] = {
147 		.lsb = ISL29501_DIE_TEMPERATURE,
148 	},
149 	[REG_AMBIENT_LIGHT] = {
150 		.lsb = ISL29501_AMBIENT_LIGHT,
151 	},
152 	[REG_GAIN] = {
153 		.msb = ISL29501_GAIN_MSB,
154 		.lsb = ISL29501_GAIN_LSB,
155 	},
156 	[REG_GAIN_BIAS] = {
157 		.msb = ISL29501_CROSSTALK_GAIN_MSB,
158 		.lsb = ISL29501_CROSSTALK_GAIN_LSB,
159 	},
160 	[REG_PHASE_EXP] = {
161 		.lsb = ISL29501_PHASE_EXPONENT,
162 	},
163 	[REG_CALIB_PHASE_TEMP_A] = {
164 		.lsb = ISL29501_TEMP_COEFF_A,
165 	},
166 	[REG_CALIB_PHASE_TEMP_B] = {
167 		.lsb = ISL29501_TEMP_COEFF_B,
168 	},
169 	[REG_CALIB_PHASE_LIGHT_A] = {
170 		.lsb = ISL29501_AMBIANT_COEFF_A,
171 	},
172 	[REG_CALIB_PHASE_LIGHT_B] = {
173 		.lsb = ISL29501_AMBIANT_COEFF_B,
174 	},
175 	[REG_DISTANCE_BIAS] = {
176 		.msb = ISL29501_PHASE_OFFSET_MSB,
177 		.lsb = ISL29501_PHASE_OFFSET_LSB,
178 	},
179 	[REG_TEMPERATURE_BIAS] = {
180 		.lsb = ISL29501_TEMP_REFERENCE,
181 	},
182 	[REG_INT_TIME] = {
183 		.lsb = ISL29501_INTEGRATION_PERIOD,
184 	},
185 	[REG_SAMPLE_TIME] = {
186 		.lsb = ISL29501_SAMPLE_PERIOD,
187 	},
188 	[REG_DRIVER_RANGE] = {
189 		.lsb = ISL29501_DRIVER_RANGE,
190 	},
191 	[REG_EMITTER_DAC] = {
192 		.lsb = ISL29501_EMITTER_DAC,
193 	},
194 };
195 
isl29501_register_read(struct isl29501_private * isl29501,enum isl29501_register_name name,u32 * val)196 static int isl29501_register_read(struct isl29501_private *isl29501,
197 				  enum isl29501_register_name name,
198 				  u32 *val)
199 {
200 	const struct isl29501_register_desc *reg = &isl29501_registers[name];
201 	u8 msb = 0, lsb = 0;
202 	s32 ret;
203 
204 	mutex_lock(&isl29501->lock);
205 	if (reg->msb) {
206 		ret = i2c_smbus_read_byte_data(isl29501->client, reg->msb);
207 		if (ret < 0)
208 			goto err;
209 		msb = ret;
210 	}
211 
212 	if (reg->lsb) {
213 		ret = i2c_smbus_read_byte_data(isl29501->client, reg->lsb);
214 		if (ret < 0)
215 			goto err;
216 		lsb = ret;
217 	}
218 	mutex_unlock(&isl29501->lock);
219 
220 	*val = (msb << 8) + lsb;
221 
222 	return 0;
223 err:
224 	mutex_unlock(&isl29501->lock);
225 
226 	return ret;
227 }
228 
isl29501_register_write(struct isl29501_private * isl29501,enum isl29501_register_name name,u32 value)229 static u32 isl29501_register_write(struct isl29501_private *isl29501,
230 				   enum isl29501_register_name name,
231 				   u32 value)
232 {
233 	const struct isl29501_register_desc *reg = &isl29501_registers[name];
234 	int ret;
235 
236 	if (!reg->msb && value > U8_MAX)
237 		return -ERANGE;
238 
239 	if (value > U16_MAX)
240 		return -ERANGE;
241 
242 	mutex_lock(&isl29501->lock);
243 	if (reg->msb) {
244 		ret = i2c_smbus_write_byte_data(isl29501->client,
245 						reg->msb, value >> 8);
246 		if (ret < 0)
247 			goto err;
248 	}
249 
250 	ret = i2c_smbus_write_byte_data(isl29501->client, reg->lsb, value);
251 
252 err:
253 	mutex_unlock(&isl29501->lock);
254 	return ret;
255 }
256 
isl29501_read_ext(struct iio_dev * indio_dev,uintptr_t private,const struct iio_chan_spec * chan,char * buf)257 static ssize_t isl29501_read_ext(struct iio_dev *indio_dev,
258 				 uintptr_t private,
259 				 const struct iio_chan_spec *chan,
260 				 char *buf)
261 {
262 	struct isl29501_private *isl29501 = iio_priv(indio_dev);
263 	enum isl29501_register_name reg = private;
264 	int ret;
265 	u32 value, gain, coeff, exp;
266 
267 	switch (reg) {
268 	case REG_GAIN:
269 	case REG_GAIN_BIAS:
270 		ret = isl29501_register_read(isl29501, reg, &gain);
271 		if (ret < 0)
272 			return ret;
273 
274 		value = gain;
275 		break;
276 	case REG_CALIB_PHASE_TEMP_A:
277 	case REG_CALIB_PHASE_TEMP_B:
278 	case REG_CALIB_PHASE_LIGHT_A:
279 	case REG_CALIB_PHASE_LIGHT_B:
280 		ret = isl29501_register_read(isl29501, REG_PHASE_EXP, &exp);
281 		if (ret < 0)
282 			return ret;
283 
284 		ret = isl29501_register_read(isl29501, reg, &coeff);
285 		if (ret < 0)
286 			return ret;
287 
288 		value = coeff << exp;
289 		break;
290 	default:
291 		return -EINVAL;
292 	}
293 
294 	return sprintf(buf, "%u\n", value);
295 }
296 
isl29501_set_shadow_coeff(struct isl29501_private * isl29501,enum isl29501_register_name reg,unsigned int val)297 static int isl29501_set_shadow_coeff(struct isl29501_private *isl29501,
298 				     enum isl29501_register_name reg,
299 				     unsigned int val)
300 {
301 	enum isl29501_correction_coeff coeff;
302 
303 	switch (reg) {
304 	case REG_CALIB_PHASE_TEMP_A:
305 		coeff = COEFF_TEMP_A;
306 		break;
307 	case REG_CALIB_PHASE_TEMP_B:
308 		coeff = COEFF_TEMP_B;
309 		break;
310 	case REG_CALIB_PHASE_LIGHT_A:
311 		coeff = COEFF_LIGHT_A;
312 		break;
313 	case REG_CALIB_PHASE_LIGHT_B:
314 		coeff = COEFF_LIGHT_B;
315 		break;
316 	default:
317 		return -EINVAL;
318 	}
319 	isl29501->shadow_coeffs[coeff] = val;
320 
321 	return 0;
322 }
323 
isl29501_write_coeff(struct isl29501_private * isl29501,enum isl29501_correction_coeff coeff,int val)324 static int isl29501_write_coeff(struct isl29501_private *isl29501,
325 				enum isl29501_correction_coeff coeff,
326 				int val)
327 {
328 	enum isl29501_register_name reg;
329 
330 	switch (coeff) {
331 	case COEFF_TEMP_A:
332 		reg = REG_CALIB_PHASE_TEMP_A;
333 		break;
334 	case COEFF_TEMP_B:
335 		reg = REG_CALIB_PHASE_TEMP_B;
336 		break;
337 	case COEFF_LIGHT_A:
338 		reg = REG_CALIB_PHASE_LIGHT_A;
339 		break;
340 	case COEFF_LIGHT_B:
341 		reg = REG_CALIB_PHASE_LIGHT_B;
342 		break;
343 	default:
344 		return -EINVAL;
345 	}
346 
347 	return isl29501_register_write(isl29501, reg, val);
348 }
349 
isl29501_find_corr_exp(unsigned int val,unsigned int max_exp,unsigned int max_mantissa)350 static unsigned int isl29501_find_corr_exp(unsigned int val,
351 					   unsigned int max_exp,
352 					   unsigned int max_mantissa)
353 {
354 	unsigned int exp = 1;
355 
356 	/*
357 	 * Correction coefficients are represented under
358 	 * mantissa * 2^exponent form, where mantissa and exponent
359 	 * are stored in two separate registers of the sensor.
360 	 *
361 	 * Compute and return the lowest exponent such as:
362 	 *	     mantissa = value / 2^exponent
363 	 *
364 	 *  where mantissa < max_mantissa.
365 	 */
366 	if (val <= max_mantissa)
367 		return 0;
368 
369 	while ((val >> exp) > max_mantissa) {
370 		exp++;
371 
372 		if (exp > max_exp)
373 			return max_exp;
374 	}
375 
376 	return exp;
377 }
378 
isl29501_write_ext(struct iio_dev * indio_dev,uintptr_t private,const struct iio_chan_spec * chan,const char * buf,size_t len)379 static ssize_t isl29501_write_ext(struct iio_dev *indio_dev,
380 				  uintptr_t private,
381 				  const struct iio_chan_spec *chan,
382 				  const char *buf, size_t len)
383 {
384 	struct isl29501_private *isl29501 = iio_priv(indio_dev);
385 	enum isl29501_register_name reg = private;
386 	unsigned int val;
387 	int max_exp = 0;
388 	int ret;
389 	int i;
390 
391 	ret = kstrtouint(buf, 10, &val);
392 	if (ret)
393 		return ret;
394 
395 	switch (reg) {
396 	case REG_GAIN_BIAS:
397 		if (val > U16_MAX)
398 			return -ERANGE;
399 
400 		ret = isl29501_register_write(isl29501, reg, val);
401 		if (ret < 0)
402 			return ret;
403 
404 		break;
405 	case REG_CALIB_PHASE_TEMP_A:
406 	case REG_CALIB_PHASE_TEMP_B:
407 	case REG_CALIB_PHASE_LIGHT_A:
408 	case REG_CALIB_PHASE_LIGHT_B:
409 
410 		if (val > (U8_MAX << ISL29501_MAX_EXP_VAL))
411 			return -ERANGE;
412 
413 		/* Store the correction coefficient under its exact form. */
414 		ret = isl29501_set_shadow_coeff(isl29501, reg, val);
415 		if (ret < 0)
416 			return ret;
417 
418 		/*
419 		 * Find the highest exponent needed to represent
420 		 * correction coefficients.
421 		 */
422 		for (i = 0; i < COEFF_MAX; i++) {
423 			int corr;
424 			int corr_exp;
425 
426 			corr = isl29501->shadow_coeffs[i];
427 			corr_exp = isl29501_find_corr_exp(corr,
428 							  ISL29501_MAX_EXP_VAL,
429 							  U8_MAX / 2);
430 			dev_dbg(&isl29501->client->dev,
431 				"found exp of corr(%d) = %d\n", corr, corr_exp);
432 
433 			max_exp = max(max_exp, corr_exp);
434 		}
435 
436 		/*
437 		 * Represent every correction coefficient under
438 		 * mantissa * 2^max_exponent form and force the
439 		 * writing of those coefficients on the sensor.
440 		 */
441 		for (i = 0; i < COEFF_MAX; i++) {
442 			int corr;
443 			int mantissa;
444 
445 			corr = isl29501->shadow_coeffs[i];
446 			if (!corr)
447 				continue;
448 
449 			mantissa = corr >> max_exp;
450 
451 			ret = isl29501_write_coeff(isl29501, i, mantissa);
452 			if (ret < 0)
453 				return ret;
454 		}
455 
456 		ret = isl29501_register_write(isl29501, REG_PHASE_EXP, max_exp);
457 		if (ret < 0)
458 			return ret;
459 
460 		break;
461 	default:
462 		return -EINVAL;
463 	}
464 
465 	return len;
466 }
467 
468 #define _ISL29501_EXT_INFO(_name, _ident) { \
469 	.name = _name, \
470 	.read = isl29501_read_ext, \
471 	.write = isl29501_write_ext, \
472 	.private = _ident, \
473 	.shared = IIO_SEPARATE, \
474 }
475 
476 static const struct iio_chan_spec_ext_info isl29501_ext_info[] = {
477 	_ISL29501_EXT_INFO("agc_gain", REG_GAIN),
478 	_ISL29501_EXT_INFO("agc_gain_bias", REG_GAIN_BIAS),
479 	_ISL29501_EXT_INFO("calib_phase_temp_a", REG_CALIB_PHASE_TEMP_A),
480 	_ISL29501_EXT_INFO("calib_phase_temp_b", REG_CALIB_PHASE_TEMP_B),
481 	_ISL29501_EXT_INFO("calib_phase_light_a", REG_CALIB_PHASE_LIGHT_A),
482 	_ISL29501_EXT_INFO("calib_phase_light_b", REG_CALIB_PHASE_LIGHT_B),
483 	{ }
484 };
485 
486 #define ISL29501_DISTANCE_SCAN_INDEX 0
487 #define ISL29501_TIMESTAMP_SCAN_INDEX 1
488 
489 static const struct iio_chan_spec isl29501_channels[] = {
490 	{
491 		.type = IIO_PROXIMITY,
492 		.scan_index = ISL29501_DISTANCE_SCAN_INDEX,
493 		.info_mask_separate =
494 			BIT(IIO_CHAN_INFO_RAW)   |
495 			BIT(IIO_CHAN_INFO_SCALE) |
496 			BIT(IIO_CHAN_INFO_CALIBBIAS),
497 		.scan_type = {
498 			.sign = 'u',
499 			.realbits = 16,
500 			.storagebits = 16,
501 			.endianness = IIO_CPU,
502 		},
503 		.info_mask_shared_by_all = BIT(IIO_CHAN_INFO_INT_TIME) |
504 				BIT(IIO_CHAN_INFO_SAMP_FREQ),
505 		.ext_info = isl29501_ext_info,
506 	},
507 	{
508 		.type = IIO_PHASE,
509 		.scan_index = -1,
510 		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
511 				BIT(IIO_CHAN_INFO_SCALE),
512 	},
513 	{
514 		.type = IIO_CURRENT,
515 		.scan_index = -1,
516 		.output = 1,
517 		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
518 				BIT(IIO_CHAN_INFO_SCALE),
519 	},
520 	{
521 		.type = IIO_TEMP,
522 		.scan_index = -1,
523 		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
524 				BIT(IIO_CHAN_INFO_SCALE)     |
525 				BIT(IIO_CHAN_INFO_CALIBBIAS),
526 	},
527 	{
528 		.type = IIO_INTENSITY,
529 		.scan_index = -1,
530 		.modified = 1,
531 		.channel2 = IIO_MOD_LIGHT_CLEAR,
532 		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
533 				BIT(IIO_CHAN_INFO_SCALE),
534 	},
535 	IIO_CHAN_SOFT_TIMESTAMP(ISL29501_TIMESTAMP_SCAN_INDEX),
536 };
537 
isl29501_reset_registers(struct isl29501_private * isl29501)538 static int isl29501_reset_registers(struct isl29501_private *isl29501)
539 {
540 	int ret;
541 
542 	ret = i2c_smbus_write_byte_data(isl29501->client,
543 					ISL29501_COMMAND_REGISTER,
544 					ISL29501_RESET_ALL_REGISTERS);
545 	if (ret < 0) {
546 		dev_err(&isl29501->client->dev,
547 			"cannot reset registers %d\n", ret);
548 		return ret;
549 	}
550 
551 	ret = i2c_smbus_write_byte_data(isl29501->client,
552 					ISL29501_COMMAND_REGISTER,
553 					ISL29501_RESET_INT_SM);
554 	if (ret < 0)
555 		dev_err(&isl29501->client->dev,
556 			"cannot reset state machine %d\n", ret);
557 
558 	return ret;
559 }
560 
isl29501_begin_acquisition(struct isl29501_private * isl29501)561 static int isl29501_begin_acquisition(struct isl29501_private *isl29501)
562 {
563 	int ret;
564 
565 	ret = i2c_smbus_write_byte_data(isl29501->client,
566 					ISL29501_COMMAND_REGISTER,
567 					ISL29501_EMUL_SAMPLE_START_PIN);
568 	if (ret < 0)
569 		dev_err(&isl29501->client->dev,
570 			"cannot begin acquisition %d\n", ret);
571 
572 	return ret;
573 }
574 
575 static IIO_CONST_ATTR_INT_TIME_AVAIL(ISL29501_INT_TIME_AVAILABLE);
576 static IIO_CONST_ATTR(out_current_scale_available,
577 		      ISL29501_CURRENT_SCALE_AVAILABLE);
578 
579 static struct attribute *isl29501_attributes[] = {
580 	&iio_const_attr_integration_time_available.dev_attr.attr,
581 	&iio_const_attr_out_current_scale_available.dev_attr.attr,
582 	NULL
583 };
584 
585 static const struct attribute_group isl29501_attribute_group = {
586 	.attrs = isl29501_attributes,
587 };
588 
589 static const int isl29501_current_scale_table[][2] = {
590 	{0, 3900}, {0, 7800}, {0, 11800}, {0, 15700},
591 	{0, 19600}, {0, 23500}, {0, 27500}, {0, 31400},
592 	{0, 35200}, {0, 39200}, {0, 43100}, {0, 47100},
593 	{0, 51000}, {0, 54900}, {0, 58800},
594 };
595 
596 static const int isl29501_int_time[][2] = {
597 	{0, 70},    /* 0.07 ms */
598 	{0, 140},   /* 0.14 ms */
599 	{0, 280},   /* 0.28 ms */
600 	{0, 570},   /* 0.57 ms */
601 	{0, 1140},  /* 1.14 ms */
602 	{0, 2280},  /* 2.28 ms */
603 	{0, 4550},  /* 4.55 ms */
604 	{0, 9100},  /* 9.11 ms */
605 	{0, 18200}, /* 18.2 ms */
606 	{0, 36400}, /* 36.4 ms */
607 	{0, 72810}, /* 72.81 ms */
608 	{0, 145610} /* 145.28 ms */
609 };
610 
isl29501_get_raw(struct isl29501_private * isl29501,const struct iio_chan_spec * chan,int * raw)611 static int isl29501_get_raw(struct isl29501_private *isl29501,
612 			    const struct iio_chan_spec *chan,
613 			    int *raw)
614 {
615 	int ret;
616 
617 	switch (chan->type) {
618 	case IIO_PROXIMITY:
619 		ret = isl29501_register_read(isl29501, REG_DISTANCE, raw);
620 		if (ret < 0)
621 			return ret;
622 
623 		return IIO_VAL_INT;
624 	case IIO_INTENSITY:
625 		ret = isl29501_register_read(isl29501,
626 					     REG_AMBIENT_LIGHT,
627 					     raw);
628 		if (ret < 0)
629 			return ret;
630 
631 		return IIO_VAL_INT;
632 	case IIO_PHASE:
633 		ret = isl29501_register_read(isl29501, REG_PHASE, raw);
634 		if (ret < 0)
635 			return ret;
636 
637 		return IIO_VAL_INT;
638 	case IIO_CURRENT:
639 		ret = isl29501_register_read(isl29501, REG_EMITTER_DAC, raw);
640 		if (ret < 0)
641 			return ret;
642 
643 		return IIO_VAL_INT;
644 	case IIO_TEMP:
645 		ret = isl29501_register_read(isl29501, REG_TEMPERATURE, raw);
646 		if (ret < 0)
647 			return ret;
648 
649 		return IIO_VAL_INT;
650 	default:
651 		return -EINVAL;
652 	}
653 }
654 
isl29501_get_scale(struct isl29501_private * isl29501,const struct iio_chan_spec * chan,int * val,int * val2)655 static int isl29501_get_scale(struct isl29501_private *isl29501,
656 			      const struct iio_chan_spec *chan,
657 			      int *val, int *val2)
658 {
659 	int ret;
660 	u32 current_scale;
661 
662 	switch (chan->type) {
663 	case IIO_PROXIMITY:
664 		/* distance = raw_distance * 33.31 / 65536 (m) */
665 		*val = 3331;
666 		*val2 = 6553600;
667 
668 		return IIO_VAL_FRACTIONAL;
669 	case IIO_PHASE:
670 		/* phase = raw_phase * 2pi / 65536 (rad) */
671 		*val = 0;
672 		*val2 = 95874;
673 
674 		return IIO_VAL_INT_PLUS_NANO;
675 	case IIO_INTENSITY:
676 		/* light = raw_light * 35 / 10000 (mA) */
677 		*val = 35;
678 		*val2 = 10000;
679 
680 		return IIO_VAL_FRACTIONAL;
681 	case IIO_CURRENT:
682 		ret = isl29501_register_read(isl29501,
683 					     REG_DRIVER_RANGE,
684 					     &current_scale);
685 		if (ret < 0)
686 			return ret;
687 
688 		if (current_scale > ARRAY_SIZE(isl29501_current_scale_table))
689 			return -EINVAL;
690 
691 		if (!current_scale) {
692 			*val = 0;
693 			*val2 = 0;
694 			return IIO_VAL_INT;
695 		}
696 
697 		*val = isl29501_current_scale_table[current_scale - 1][0];
698 		*val2 = isl29501_current_scale_table[current_scale - 1][1];
699 
700 		return IIO_VAL_INT_PLUS_MICRO;
701 	case IIO_TEMP:
702 		/* temperature = raw_temperature * 125 / 100000 (milli °C) */
703 		*val = 125;
704 		*val2 = 100000;
705 
706 		return IIO_VAL_FRACTIONAL;
707 	default:
708 		return -EINVAL;
709 	}
710 }
711 
isl29501_get_calibbias(struct isl29501_private * isl29501,const struct iio_chan_spec * chan,int * bias)712 static int isl29501_get_calibbias(struct isl29501_private *isl29501,
713 				  const struct iio_chan_spec *chan,
714 				  int *bias)
715 {
716 	switch (chan->type) {
717 	case IIO_PROXIMITY:
718 		return isl29501_register_read(isl29501,
719 					      REG_DISTANCE_BIAS,
720 					      bias);
721 	case IIO_TEMP:
722 		return isl29501_register_read(isl29501,
723 					      REG_TEMPERATURE_BIAS,
724 					      bias);
725 	default:
726 		return -EINVAL;
727 	}
728 }
729 
isl29501_get_inttime(struct isl29501_private * isl29501,int * val,int * val2)730 static int isl29501_get_inttime(struct isl29501_private *isl29501,
731 				int *val, int *val2)
732 {
733 	int ret;
734 	u32 inttime;
735 
736 	ret = isl29501_register_read(isl29501, REG_INT_TIME, &inttime);
737 	if (ret < 0)
738 		return ret;
739 
740 	if (inttime >= ARRAY_SIZE(isl29501_int_time))
741 		return -EINVAL;
742 
743 	*val = isl29501_int_time[inttime][0];
744 	*val2 = isl29501_int_time[inttime][1];
745 
746 	return IIO_VAL_INT_PLUS_MICRO;
747 }
748 
isl29501_get_freq(struct isl29501_private * isl29501,int * val,int * val2)749 static int isl29501_get_freq(struct isl29501_private *isl29501,
750 			     int *val, int *val2)
751 {
752 	int ret;
753 	int sample_time;
754 	unsigned long long freq;
755 	u32 temp;
756 
757 	ret = isl29501_register_read(isl29501, REG_SAMPLE_TIME, &sample_time);
758 	if (ret < 0)
759 		return ret;
760 
761 	/* freq = 1 / (0.000450 * (sample_time + 1) * 10^-6) */
762 	freq = 1000000ULL * 1000000ULL;
763 
764 	do_div(freq, 450 * (sample_time + 1));
765 
766 	temp = do_div(freq, 1000000);
767 	*val = freq;
768 	*val2 = temp;
769 
770 	return IIO_VAL_INT_PLUS_MICRO;
771 }
772 
isl29501_read_raw(struct iio_dev * indio_dev,struct iio_chan_spec const * chan,int * val,int * val2,long mask)773 static int isl29501_read_raw(struct iio_dev *indio_dev,
774 			     struct iio_chan_spec const *chan, int *val,
775 			     int *val2, long mask)
776 {
777 	struct isl29501_private *isl29501 = iio_priv(indio_dev);
778 
779 	switch (mask) {
780 	case IIO_CHAN_INFO_RAW:
781 		return isl29501_get_raw(isl29501, chan, val);
782 	case IIO_CHAN_INFO_SCALE:
783 		return isl29501_get_scale(isl29501, chan, val, val2);
784 	case IIO_CHAN_INFO_INT_TIME:
785 		return isl29501_get_inttime(isl29501, val, val2);
786 	case IIO_CHAN_INFO_SAMP_FREQ:
787 		return isl29501_get_freq(isl29501, val, val2);
788 	case IIO_CHAN_INFO_CALIBBIAS:
789 		return isl29501_get_calibbias(isl29501, chan, val);
790 	default:
791 		return -EINVAL;
792 	}
793 }
794 
isl29501_set_raw(struct isl29501_private * isl29501,const struct iio_chan_spec * chan,int raw)795 static int isl29501_set_raw(struct isl29501_private *isl29501,
796 			    const struct iio_chan_spec *chan,
797 			    int raw)
798 {
799 	switch (chan->type) {
800 	case IIO_CURRENT:
801 		return isl29501_register_write(isl29501, REG_EMITTER_DAC, raw);
802 	default:
803 		return -EINVAL;
804 	}
805 }
806 
isl29501_set_inttime(struct isl29501_private * isl29501,int val,int val2)807 static int isl29501_set_inttime(struct isl29501_private *isl29501,
808 				int val, int val2)
809 {
810 	int i;
811 
812 	for (i = 0; i < ARRAY_SIZE(isl29501_int_time); i++) {
813 		if (isl29501_int_time[i][0] == val &&
814 		    isl29501_int_time[i][1] == val2) {
815 			return isl29501_register_write(isl29501,
816 						       REG_INT_TIME,
817 						       i);
818 		}
819 	}
820 
821 	return -EINVAL;
822 }
823 
isl29501_set_scale(struct isl29501_private * isl29501,const struct iio_chan_spec * chan,int val,int val2)824 static int isl29501_set_scale(struct isl29501_private *isl29501,
825 			      const struct iio_chan_spec *chan,
826 			      int val, int val2)
827 {
828 	int i;
829 
830 	if (chan->type != IIO_CURRENT)
831 		return -EINVAL;
832 
833 	for (i = 0; i < ARRAY_SIZE(isl29501_current_scale_table); i++) {
834 		if (isl29501_current_scale_table[i][0] == val &&
835 		    isl29501_current_scale_table[i][1] == val2) {
836 			return isl29501_register_write(isl29501,
837 						       REG_DRIVER_RANGE,
838 						       i + 1);
839 		}
840 	}
841 
842 	return -EINVAL;
843 }
844 
isl29501_set_calibbias(struct isl29501_private * isl29501,const struct iio_chan_spec * chan,int bias)845 static int isl29501_set_calibbias(struct isl29501_private *isl29501,
846 				  const struct iio_chan_spec *chan,
847 				  int bias)
848 {
849 	switch (chan->type) {
850 	case IIO_PROXIMITY:
851 		return isl29501_register_write(isl29501,
852 					      REG_DISTANCE_BIAS,
853 					      bias);
854 	case IIO_TEMP:
855 		return isl29501_register_write(isl29501,
856 					       REG_TEMPERATURE_BIAS,
857 					       bias);
858 	default:
859 		return -EINVAL;
860 	}
861 }
862 
isl29501_set_freq(struct isl29501_private * isl29501,int val,int val2)863 static int isl29501_set_freq(struct isl29501_private *isl29501,
864 			     int val, int val2)
865 {
866 	int freq;
867 	unsigned long long sample_time;
868 
869 	/* sample_freq = 1 / (0.000450 * (sample_time + 1) * 10^-6) */
870 	freq = val * 1000000 + val2 % 1000000;
871 	sample_time = 2222ULL * 1000000ULL;
872 	do_div(sample_time, freq);
873 
874 	sample_time -= 1;
875 
876 	if (sample_time > 255)
877 		return -ERANGE;
878 
879 	return isl29501_register_write(isl29501, REG_SAMPLE_TIME, sample_time);
880 }
881 
isl29501_write_raw(struct iio_dev * indio_dev,struct iio_chan_spec const * chan,int val,int val2,long mask)882 static int isl29501_write_raw(struct iio_dev *indio_dev,
883 			      struct iio_chan_spec const *chan,
884 			      int val, int val2, long mask)
885 {
886 	struct isl29501_private *isl29501 = iio_priv(indio_dev);
887 
888 	switch (mask) {
889 	case IIO_CHAN_INFO_RAW:
890 		return isl29501_set_raw(isl29501, chan, val);
891 	case IIO_CHAN_INFO_INT_TIME:
892 		return isl29501_set_inttime(isl29501, val, val2);
893 	case IIO_CHAN_INFO_SAMP_FREQ:
894 		return isl29501_set_freq(isl29501, val, val2);
895 	case IIO_CHAN_INFO_SCALE:
896 		return isl29501_set_scale(isl29501, chan, val, val2);
897 	case IIO_CHAN_INFO_CALIBBIAS:
898 		return isl29501_set_calibbias(isl29501, chan, val);
899 	default:
900 		return -EINVAL;
901 	}
902 }
903 
904 static const struct iio_info isl29501_info = {
905 	.read_raw = &isl29501_read_raw,
906 	.write_raw = &isl29501_write_raw,
907 	.attrs = &isl29501_attribute_group,
908 };
909 
isl29501_init_chip(struct isl29501_private * isl29501)910 static int isl29501_init_chip(struct isl29501_private *isl29501)
911 {
912 	int ret;
913 
914 	ret = i2c_smbus_read_byte_data(isl29501->client, ISL29501_DEVICE_ID);
915 	if (ret < 0) {
916 		dev_err(&isl29501->client->dev, "Error reading device id\n");
917 		return ret;
918 	}
919 
920 	if (ret != ISL29501_ID) {
921 		dev_err(&isl29501->client->dev,
922 			"Wrong chip id, got %x expected %x\n",
923 			ret, ISL29501_DEVICE_ID);
924 		return -ENODEV;
925 	}
926 
927 	ret = isl29501_reset_registers(isl29501);
928 	if (ret < 0)
929 		return ret;
930 
931 	return isl29501_begin_acquisition(isl29501);
932 }
933 
isl29501_trigger_handler(int irq,void * p)934 static irqreturn_t isl29501_trigger_handler(int irq, void *p)
935 {
936 	struct iio_poll_func *pf = p;
937 	struct iio_dev *indio_dev = pf->indio_dev;
938 	struct isl29501_private *isl29501 = iio_priv(indio_dev);
939 	const unsigned long *active_mask = indio_dev->active_scan_mask;
940 	u32 value;
941 	struct {
942 		u16 data;
943 		aligned_s64 ts;
944 	} scan = { };
945 
946 	if (test_bit(ISL29501_DISTANCE_SCAN_INDEX, active_mask)) {
947 		isl29501_register_read(isl29501, REG_DISTANCE, &value);
948 		scan.data = value;
949 	}
950 
951 	iio_push_to_buffers_with_timestamp(indio_dev, &scan, pf->timestamp);
952 	iio_trigger_notify_done(indio_dev->trig);
953 
954 	return IRQ_HANDLED;
955 }
956 
isl29501_probe(struct i2c_client * client)957 static int isl29501_probe(struct i2c_client *client)
958 {
959 	struct iio_dev *indio_dev;
960 	struct isl29501_private *isl29501;
961 	int ret;
962 
963 	indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*isl29501));
964 	if (!indio_dev)
965 		return -ENOMEM;
966 
967 	isl29501 = iio_priv(indio_dev);
968 
969 	i2c_set_clientdata(client, indio_dev);
970 	isl29501->client = client;
971 
972 	mutex_init(&isl29501->lock);
973 
974 	ret = isl29501_init_chip(isl29501);
975 	if (ret < 0)
976 		return ret;
977 
978 	indio_dev->modes = INDIO_DIRECT_MODE;
979 	indio_dev->channels = isl29501_channels;
980 	indio_dev->num_channels = ARRAY_SIZE(isl29501_channels);
981 	indio_dev->name = client->name;
982 	indio_dev->info = &isl29501_info;
983 
984 	ret = devm_iio_triggered_buffer_setup(&client->dev, indio_dev,
985 					      iio_pollfunc_store_time,
986 					      isl29501_trigger_handler,
987 					      NULL);
988 	if (ret < 0) {
989 		dev_err(&client->dev, "unable to setup iio triggered buffer\n");
990 		return ret;
991 	}
992 
993 	return devm_iio_device_register(&client->dev, indio_dev);
994 }
995 
996 static const struct i2c_device_id isl29501_id[] = {
997 	{ .name = "isl29501" },
998 	{ }
999 };
1000 
1001 MODULE_DEVICE_TABLE(i2c, isl29501_id);
1002 
1003 static const struct of_device_id isl29501_i2c_matches[] = {
1004 	{ .compatible = "renesas,isl29501" },
1005 	{ }
1006 };
1007 MODULE_DEVICE_TABLE(of, isl29501_i2c_matches);
1008 
1009 static struct i2c_driver isl29501_driver = {
1010 	.driver = {
1011 		.name	= "isl29501",
1012 		.of_match_table = isl29501_i2c_matches,
1013 	},
1014 	.id_table	= isl29501_id,
1015 	.probe		= isl29501_probe,
1016 };
1017 module_i2c_driver(isl29501_driver);
1018 
1019 MODULE_AUTHOR("Mathieu Othacehe <m.othacehe@gmail.com>");
1020 MODULE_DESCRIPTION("ISL29501 Time of Flight sensor driver");
1021 MODULE_LICENSE("GPL v2");
1022