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 ¤t_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