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