0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #include <linux/kernel.h>
0012 #include <linux/module.h>
0013 #include <linux/i2c.h>
0014 #include <linux/err.h>
0015 #include <linux/of_device.h>
0016 #include <linux/iio/iio.h>
0017 #include <linux/iio/sysfs.h>
0018
0019 #include <linux/iio/trigger_consumer.h>
0020 #include <linux/iio/buffer.h>
0021 #include <linux/iio/triggered_buffer.h>
0022
0023
0024 #define ISL29501_DEVICE_ID 0x00
0025 #define ISL29501_ID 0x0A
0026
0027
0028 #define ISL29501_INTEGRATION_PERIOD 0x10
0029 #define ISL29501_SAMPLE_PERIOD 0x11
0030
0031
0032 #define ISL29501_CROSSTALK_I_MSB 0x24
0033 #define ISL29501_CROSSTALK_I_LSB 0x25
0034 #define ISL29501_CROSSTALK_I_EXPONENT 0x26
0035 #define ISL29501_CROSSTALK_Q_MSB 0x27
0036 #define ISL29501_CROSSTALK_Q_LSB 0x28
0037 #define ISL29501_CROSSTALK_Q_EXPONENT 0x29
0038 #define ISL29501_CROSSTALK_GAIN_MSB 0x2A
0039 #define ISL29501_CROSSTALK_GAIN_LSB 0x2B
0040 #define ISL29501_MAGNITUDE_REF_EXP 0x2C
0041 #define ISL29501_MAGNITUDE_REF_MSB 0x2D
0042 #define ISL29501_MAGNITUDE_REF_LSB 0x2E
0043 #define ISL29501_PHASE_OFFSET_MSB 0x2F
0044 #define ISL29501_PHASE_OFFSET_LSB 0x30
0045
0046
0047 #define ISL29501_DRIVER_RANGE 0x90
0048 #define ISL29501_EMITTER_DAC 0x91
0049
0050 #define ISL29501_COMMAND_REGISTER 0xB0
0051
0052
0053 #define ISL29501_EMUL_SAMPLE_START_PIN 0x49
0054 #define ISL29501_RESET_ALL_REGISTERS 0xD7
0055 #define ISL29501_RESET_INT_SM 0xD1
0056
0057
0058 #define ISL29501_TEMP_REFERENCE 0x31
0059 #define ISL29501_PHASE_EXPONENT 0x33
0060 #define ISL29501_TEMP_COEFF_A 0x34
0061 #define ISL29501_TEMP_COEFF_B 0x39
0062 #define ISL29501_AMBIANT_COEFF_A 0x36
0063 #define ISL29501_AMBIANT_COEFF_B 0x3B
0064
0065
0066 #define ISL29501_DISTANCE_MSB_DATA 0xD1
0067 #define ISL29501_DISTANCE_LSB_DATA 0xD2
0068 #define ISL29501_PRECISION_MSB 0xD3
0069 #define ISL29501_PRECISION_LSB 0xD4
0070 #define ISL29501_MAGNITUDE_EXPONENT 0xD5
0071 #define ISL29501_MAGNITUDE_MSB 0xD6
0072 #define ISL29501_MAGNITUDE_LSB 0xD7
0073 #define ISL29501_PHASE_MSB 0xD8
0074 #define ISL29501_PHASE_LSB 0xD9
0075 #define ISL29501_I_RAW_EXPONENT 0xDA
0076 #define ISL29501_I_RAW_MSB 0xDB
0077 #define ISL29501_I_RAW_LSB 0xDC
0078 #define ISL29501_Q_RAW_EXPONENT 0xDD
0079 #define ISL29501_Q_RAW_MSB 0xDE
0080 #define ISL29501_Q_RAW_LSB 0xDF
0081 #define ISL29501_DIE_TEMPERATURE 0xE2
0082 #define ISL29501_AMBIENT_LIGHT 0xE3
0083 #define ISL29501_GAIN_MSB 0xE6
0084 #define ISL29501_GAIN_LSB 0xE7
0085
0086 #define ISL29501_MAX_EXP_VAL 15
0087
0088 #define ISL29501_INT_TIME_AVAILABLE \
0089 "0.00007 0.00014 0.00028 0.00057 0.00114 " \
0090 "0.00228 0.00455 0.00910 0.01820 0.03640 " \
0091 "0.07281 0.14561"
0092
0093 #define ISL29501_CURRENT_SCALE_AVAILABLE \
0094 "0.0039 0.0078 0.0118 0.0157 0.0196 " \
0095 "0.0235 0.0275 0.0314 0.0352 0.0392 " \
0096 "0.0431 0.0471 0.0510 0.0549 0.0588"
0097
0098 enum isl29501_correction_coeff {
0099 COEFF_TEMP_A,
0100 COEFF_TEMP_B,
0101 COEFF_LIGHT_A,
0102 COEFF_LIGHT_B,
0103 COEFF_MAX,
0104 };
0105
0106 struct isl29501_private {
0107 struct i2c_client *client;
0108 struct mutex lock;
0109
0110 unsigned int shadow_coeffs[COEFF_MAX];
0111 };
0112
0113 enum isl29501_register_name {
0114 REG_DISTANCE,
0115 REG_PHASE,
0116 REG_TEMPERATURE,
0117 REG_AMBIENT_LIGHT,
0118 REG_GAIN,
0119 REG_GAIN_BIAS,
0120 REG_PHASE_EXP,
0121 REG_CALIB_PHASE_TEMP_A,
0122 REG_CALIB_PHASE_TEMP_B,
0123 REG_CALIB_PHASE_LIGHT_A,
0124 REG_CALIB_PHASE_LIGHT_B,
0125 REG_DISTANCE_BIAS,
0126 REG_TEMPERATURE_BIAS,
0127 REG_INT_TIME,
0128 REG_SAMPLE_TIME,
0129 REG_DRIVER_RANGE,
0130 REG_EMITTER_DAC,
0131 };
0132
0133 struct isl29501_register_desc {
0134 u8 msb;
0135 u8 lsb;
0136 };
0137
0138 static const struct isl29501_register_desc isl29501_registers[] = {
0139 [REG_DISTANCE] = {
0140 .msb = ISL29501_DISTANCE_MSB_DATA,
0141 .lsb = ISL29501_DISTANCE_LSB_DATA,
0142 },
0143 [REG_PHASE] = {
0144 .msb = ISL29501_PHASE_MSB,
0145 .lsb = ISL29501_PHASE_LSB,
0146 },
0147 [REG_TEMPERATURE] = {
0148 .lsb = ISL29501_DIE_TEMPERATURE,
0149 },
0150 [REG_AMBIENT_LIGHT] = {
0151 .lsb = ISL29501_AMBIENT_LIGHT,
0152 },
0153 [REG_GAIN] = {
0154 .msb = ISL29501_GAIN_MSB,
0155 .lsb = ISL29501_GAIN_LSB,
0156 },
0157 [REG_GAIN_BIAS] = {
0158 .msb = ISL29501_CROSSTALK_GAIN_MSB,
0159 .lsb = ISL29501_CROSSTALK_GAIN_LSB,
0160 },
0161 [REG_PHASE_EXP] = {
0162 .lsb = ISL29501_PHASE_EXPONENT,
0163 },
0164 [REG_CALIB_PHASE_TEMP_A] = {
0165 .lsb = ISL29501_TEMP_COEFF_A,
0166 },
0167 [REG_CALIB_PHASE_TEMP_B] = {
0168 .lsb = ISL29501_TEMP_COEFF_B,
0169 },
0170 [REG_CALIB_PHASE_LIGHT_A] = {
0171 .lsb = ISL29501_AMBIANT_COEFF_A,
0172 },
0173 [REG_CALIB_PHASE_LIGHT_B] = {
0174 .lsb = ISL29501_AMBIANT_COEFF_B,
0175 },
0176 [REG_DISTANCE_BIAS] = {
0177 .msb = ISL29501_PHASE_OFFSET_MSB,
0178 .lsb = ISL29501_PHASE_OFFSET_LSB,
0179 },
0180 [REG_TEMPERATURE_BIAS] = {
0181 .lsb = ISL29501_TEMP_REFERENCE,
0182 },
0183 [REG_INT_TIME] = {
0184 .lsb = ISL29501_INTEGRATION_PERIOD,
0185 },
0186 [REG_SAMPLE_TIME] = {
0187 .lsb = ISL29501_SAMPLE_PERIOD,
0188 },
0189 [REG_DRIVER_RANGE] = {
0190 .lsb = ISL29501_DRIVER_RANGE,
0191 },
0192 [REG_EMITTER_DAC] = {
0193 .lsb = ISL29501_EMITTER_DAC,
0194 },
0195 };
0196
0197 static int isl29501_register_read(struct isl29501_private *isl29501,
0198 enum isl29501_register_name name,
0199 u32 *val)
0200 {
0201 const struct isl29501_register_desc *reg = &isl29501_registers[name];
0202 u8 msb = 0, lsb = 0;
0203 s32 ret;
0204
0205 mutex_lock(&isl29501->lock);
0206 if (reg->msb) {
0207 ret = i2c_smbus_read_byte_data(isl29501->client, reg->msb);
0208 if (ret < 0)
0209 goto err;
0210 msb = ret;
0211 }
0212
0213 if (reg->lsb) {
0214 ret = i2c_smbus_read_byte_data(isl29501->client, reg->lsb);
0215 if (ret < 0)
0216 goto err;
0217 lsb = ret;
0218 }
0219 mutex_unlock(&isl29501->lock);
0220
0221 *val = (msb << 8) + lsb;
0222
0223 return 0;
0224 err:
0225 mutex_unlock(&isl29501->lock);
0226
0227 return ret;
0228 }
0229
0230 static u32 isl29501_register_write(struct isl29501_private *isl29501,
0231 enum isl29501_register_name name,
0232 u32 value)
0233 {
0234 const struct isl29501_register_desc *reg = &isl29501_registers[name];
0235 int ret;
0236
0237 if (!reg->msb && value > U8_MAX)
0238 return -ERANGE;
0239
0240 if (value > U16_MAX)
0241 return -ERANGE;
0242
0243 mutex_lock(&isl29501->lock);
0244 if (reg->msb) {
0245 ret = i2c_smbus_write_byte_data(isl29501->client,
0246 reg->msb, value >> 8);
0247 if (ret < 0)
0248 goto err;
0249 }
0250
0251 ret = i2c_smbus_write_byte_data(isl29501->client, reg->lsb, value);
0252
0253 err:
0254 mutex_unlock(&isl29501->lock);
0255 return ret;
0256 }
0257
0258 static ssize_t isl29501_read_ext(struct iio_dev *indio_dev,
0259 uintptr_t private,
0260 const struct iio_chan_spec *chan,
0261 char *buf)
0262 {
0263 struct isl29501_private *isl29501 = iio_priv(indio_dev);
0264 enum isl29501_register_name reg = private;
0265 int ret;
0266 u32 value, gain, coeff, exp;
0267
0268 switch (reg) {
0269 case REG_GAIN:
0270 case REG_GAIN_BIAS:
0271 ret = isl29501_register_read(isl29501, reg, &gain);
0272 if (ret < 0)
0273 return ret;
0274
0275 value = gain;
0276 break;
0277 case REG_CALIB_PHASE_TEMP_A:
0278 case REG_CALIB_PHASE_TEMP_B:
0279 case REG_CALIB_PHASE_LIGHT_A:
0280 case REG_CALIB_PHASE_LIGHT_B:
0281 ret = isl29501_register_read(isl29501, REG_PHASE_EXP, &exp);
0282 if (ret < 0)
0283 return ret;
0284
0285 ret = isl29501_register_read(isl29501, reg, &coeff);
0286 if (ret < 0)
0287 return ret;
0288
0289 value = coeff << exp;
0290 break;
0291 default:
0292 return -EINVAL;
0293 }
0294
0295 return sprintf(buf, "%u\n", value);
0296 }
0297
0298 static int isl29501_set_shadow_coeff(struct isl29501_private *isl29501,
0299 enum isl29501_register_name reg,
0300 unsigned int val)
0301 {
0302 enum isl29501_correction_coeff coeff;
0303
0304 switch (reg) {
0305 case REG_CALIB_PHASE_TEMP_A:
0306 coeff = COEFF_TEMP_A;
0307 break;
0308 case REG_CALIB_PHASE_TEMP_B:
0309 coeff = COEFF_TEMP_B;
0310 break;
0311 case REG_CALIB_PHASE_LIGHT_A:
0312 coeff = COEFF_LIGHT_A;
0313 break;
0314 case REG_CALIB_PHASE_LIGHT_B:
0315 coeff = COEFF_LIGHT_B;
0316 break;
0317 default:
0318 return -EINVAL;
0319 }
0320 isl29501->shadow_coeffs[coeff] = val;
0321
0322 return 0;
0323 }
0324
0325 static int isl29501_write_coeff(struct isl29501_private *isl29501,
0326 enum isl29501_correction_coeff coeff,
0327 int val)
0328 {
0329 enum isl29501_register_name reg;
0330
0331 switch (coeff) {
0332 case COEFF_TEMP_A:
0333 reg = REG_CALIB_PHASE_TEMP_A;
0334 break;
0335 case COEFF_TEMP_B:
0336 reg = REG_CALIB_PHASE_TEMP_B;
0337 break;
0338 case COEFF_LIGHT_A:
0339 reg = REG_CALIB_PHASE_LIGHT_A;
0340 break;
0341 case COEFF_LIGHT_B:
0342 reg = REG_CALIB_PHASE_LIGHT_B;
0343 break;
0344 default:
0345 return -EINVAL;
0346 }
0347
0348 return isl29501_register_write(isl29501, reg, val);
0349 }
0350
0351 static unsigned int isl29501_find_corr_exp(unsigned int val,
0352 unsigned int max_exp,
0353 unsigned int max_mantissa)
0354 {
0355 unsigned int exp = 1;
0356
0357
0358
0359
0360
0361
0362
0363
0364
0365
0366
0367 if (val <= max_mantissa)
0368 return 0;
0369
0370 while ((val >> exp) > max_mantissa) {
0371 exp++;
0372
0373 if (exp > max_exp)
0374 return max_exp;
0375 }
0376
0377 return exp;
0378 }
0379
0380 static ssize_t isl29501_write_ext(struct iio_dev *indio_dev,
0381 uintptr_t private,
0382 const struct iio_chan_spec *chan,
0383 const char *buf, size_t len)
0384 {
0385 struct isl29501_private *isl29501 = iio_priv(indio_dev);
0386 enum isl29501_register_name reg = private;
0387 unsigned int val;
0388 int max_exp = 0;
0389 int ret;
0390 int i;
0391
0392 ret = kstrtouint(buf, 10, &val);
0393 if (ret)
0394 return ret;
0395
0396 switch (reg) {
0397 case REG_GAIN_BIAS:
0398 if (val > U16_MAX)
0399 return -ERANGE;
0400
0401 ret = isl29501_register_write(isl29501, reg, val);
0402 if (ret < 0)
0403 return ret;
0404
0405 break;
0406 case REG_CALIB_PHASE_TEMP_A:
0407 case REG_CALIB_PHASE_TEMP_B:
0408 case REG_CALIB_PHASE_LIGHT_A:
0409 case REG_CALIB_PHASE_LIGHT_B:
0410
0411 if (val > (U8_MAX << ISL29501_MAX_EXP_VAL))
0412 return -ERANGE;
0413
0414
0415 ret = isl29501_set_shadow_coeff(isl29501, reg, val);
0416 if (ret < 0)
0417 return ret;
0418
0419
0420
0421
0422
0423 for (i = 0; i < COEFF_MAX; i++) {
0424 int corr;
0425 int corr_exp;
0426
0427 corr = isl29501->shadow_coeffs[i];
0428 corr_exp = isl29501_find_corr_exp(corr,
0429 ISL29501_MAX_EXP_VAL,
0430 U8_MAX / 2);
0431 dev_dbg(&isl29501->client->dev,
0432 "found exp of corr(%d) = %d\n", corr, corr_exp);
0433
0434 max_exp = max(max_exp, corr_exp);
0435 }
0436
0437
0438
0439
0440
0441
0442 for (i = 0; i < COEFF_MAX; i++) {
0443 int corr;
0444 int mantissa;
0445
0446 corr = isl29501->shadow_coeffs[i];
0447 if (!corr)
0448 continue;
0449
0450 mantissa = corr >> max_exp;
0451
0452 ret = isl29501_write_coeff(isl29501, i, mantissa);
0453 if (ret < 0)
0454 return ret;
0455 }
0456
0457 ret = isl29501_register_write(isl29501, REG_PHASE_EXP, max_exp);
0458 if (ret < 0)
0459 return ret;
0460
0461 break;
0462 default:
0463 return -EINVAL;
0464 }
0465
0466 return len;
0467 }
0468
0469 #define _ISL29501_EXT_INFO(_name, _ident) { \
0470 .name = _name, \
0471 .read = isl29501_read_ext, \
0472 .write = isl29501_write_ext, \
0473 .private = _ident, \
0474 .shared = IIO_SEPARATE, \
0475 }
0476
0477 static const struct iio_chan_spec_ext_info isl29501_ext_info[] = {
0478 _ISL29501_EXT_INFO("agc_gain", REG_GAIN),
0479 _ISL29501_EXT_INFO("agc_gain_bias", REG_GAIN_BIAS),
0480 _ISL29501_EXT_INFO("calib_phase_temp_a", REG_CALIB_PHASE_TEMP_A),
0481 _ISL29501_EXT_INFO("calib_phase_temp_b", REG_CALIB_PHASE_TEMP_B),
0482 _ISL29501_EXT_INFO("calib_phase_light_a", REG_CALIB_PHASE_LIGHT_A),
0483 _ISL29501_EXT_INFO("calib_phase_light_b", REG_CALIB_PHASE_LIGHT_B),
0484 { },
0485 };
0486
0487 #define ISL29501_DISTANCE_SCAN_INDEX 0
0488 #define ISL29501_TIMESTAMP_SCAN_INDEX 1
0489
0490 static const struct iio_chan_spec isl29501_channels[] = {
0491 {
0492 .type = IIO_PROXIMITY,
0493 .scan_index = ISL29501_DISTANCE_SCAN_INDEX,
0494 .info_mask_separate =
0495 BIT(IIO_CHAN_INFO_RAW) |
0496 BIT(IIO_CHAN_INFO_SCALE) |
0497 BIT(IIO_CHAN_INFO_CALIBBIAS),
0498 .scan_type = {
0499 .sign = 'u',
0500 .realbits = 16,
0501 .storagebits = 16,
0502 .endianness = IIO_CPU,
0503 },
0504 .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_INT_TIME) |
0505 BIT(IIO_CHAN_INFO_SAMP_FREQ),
0506 .ext_info = isl29501_ext_info,
0507 },
0508 {
0509 .type = IIO_PHASE,
0510 .scan_index = -1,
0511 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
0512 BIT(IIO_CHAN_INFO_SCALE),
0513 },
0514 {
0515 .type = IIO_CURRENT,
0516 .scan_index = -1,
0517 .output = 1,
0518 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
0519 BIT(IIO_CHAN_INFO_SCALE),
0520 },
0521 {
0522 .type = IIO_TEMP,
0523 .scan_index = -1,
0524 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
0525 BIT(IIO_CHAN_INFO_SCALE) |
0526 BIT(IIO_CHAN_INFO_CALIBBIAS),
0527 },
0528 {
0529 .type = IIO_INTENSITY,
0530 .scan_index = -1,
0531 .modified = 1,
0532 .channel2 = IIO_MOD_LIGHT_CLEAR,
0533 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
0534 BIT(IIO_CHAN_INFO_SCALE),
0535 },
0536 IIO_CHAN_SOFT_TIMESTAMP(ISL29501_TIMESTAMP_SCAN_INDEX),
0537 };
0538
0539 static int isl29501_reset_registers(struct isl29501_private *isl29501)
0540 {
0541 int ret;
0542
0543 ret = i2c_smbus_write_byte_data(isl29501->client,
0544 ISL29501_COMMAND_REGISTER,
0545 ISL29501_RESET_ALL_REGISTERS);
0546 if (ret < 0) {
0547 dev_err(&isl29501->client->dev,
0548 "cannot reset registers %d\n", ret);
0549 return ret;
0550 }
0551
0552 ret = i2c_smbus_write_byte_data(isl29501->client,
0553 ISL29501_COMMAND_REGISTER,
0554 ISL29501_RESET_INT_SM);
0555 if (ret < 0)
0556 dev_err(&isl29501->client->dev,
0557 "cannot reset state machine %d\n", ret);
0558
0559 return ret;
0560 }
0561
0562 static int isl29501_begin_acquisition(struct isl29501_private *isl29501)
0563 {
0564 int ret;
0565
0566 ret = i2c_smbus_write_byte_data(isl29501->client,
0567 ISL29501_COMMAND_REGISTER,
0568 ISL29501_EMUL_SAMPLE_START_PIN);
0569 if (ret < 0)
0570 dev_err(&isl29501->client->dev,
0571 "cannot begin acquisition %d\n", ret);
0572
0573 return ret;
0574 }
0575
0576 static IIO_CONST_ATTR_INT_TIME_AVAIL(ISL29501_INT_TIME_AVAILABLE);
0577 static IIO_CONST_ATTR(out_current_scale_available,
0578 ISL29501_CURRENT_SCALE_AVAILABLE);
0579
0580 static struct attribute *isl29501_attributes[] = {
0581 &iio_const_attr_integration_time_available.dev_attr.attr,
0582 &iio_const_attr_out_current_scale_available.dev_attr.attr,
0583 NULL
0584 };
0585
0586 static const struct attribute_group isl29501_attribute_group = {
0587 .attrs = isl29501_attributes,
0588 };
0589
0590 static const int isl29501_current_scale_table[][2] = {
0591 {0, 3900}, {0, 7800}, {0, 11800}, {0, 15700},
0592 {0, 19600}, {0, 23500}, {0, 27500}, {0, 31400},
0593 {0, 35200}, {0, 39200}, {0, 43100}, {0, 47100},
0594 {0, 51000}, {0, 54900}, {0, 58800},
0595 };
0596
0597 static const int isl29501_int_time[][2] = {
0598 {0, 70},
0599 {0, 140},
0600 {0, 280},
0601 {0, 570},
0602 {0, 1140},
0603 {0, 2280},
0604 {0, 4550},
0605 {0, 9100},
0606 {0, 18200},
0607 {0, 36400},
0608 {0, 72810},
0609 {0, 145610}
0610 };
0611
0612 static int isl29501_get_raw(struct isl29501_private *isl29501,
0613 const struct iio_chan_spec *chan,
0614 int *raw)
0615 {
0616 int ret;
0617
0618 switch (chan->type) {
0619 case IIO_PROXIMITY:
0620 ret = isl29501_register_read(isl29501, REG_DISTANCE, raw);
0621 if (ret < 0)
0622 return ret;
0623
0624 return IIO_VAL_INT;
0625 case IIO_INTENSITY:
0626 ret = isl29501_register_read(isl29501,
0627 REG_AMBIENT_LIGHT,
0628 raw);
0629 if (ret < 0)
0630 return ret;
0631
0632 return IIO_VAL_INT;
0633 case IIO_PHASE:
0634 ret = isl29501_register_read(isl29501, REG_PHASE, raw);
0635 if (ret < 0)
0636 return ret;
0637
0638 return IIO_VAL_INT;
0639 case IIO_CURRENT:
0640 ret = isl29501_register_read(isl29501, REG_EMITTER_DAC, raw);
0641 if (ret < 0)
0642 return ret;
0643
0644 return IIO_VAL_INT;
0645 case IIO_TEMP:
0646 ret = isl29501_register_read(isl29501, REG_TEMPERATURE, raw);
0647 if (ret < 0)
0648 return ret;
0649
0650 return IIO_VAL_INT;
0651 default:
0652 return -EINVAL;
0653 }
0654 }
0655
0656 static int isl29501_get_scale(struct isl29501_private *isl29501,
0657 const struct iio_chan_spec *chan,
0658 int *val, int *val2)
0659 {
0660 int ret;
0661 u32 current_scale;
0662
0663 switch (chan->type) {
0664 case IIO_PROXIMITY:
0665
0666 *val = 3331;
0667 *val2 = 6553600;
0668
0669 return IIO_VAL_FRACTIONAL;
0670 case IIO_PHASE:
0671
0672 *val = 0;
0673 *val2 = 95874;
0674
0675 return IIO_VAL_INT_PLUS_NANO;
0676 case IIO_INTENSITY:
0677
0678 *val = 35;
0679 *val2 = 10000;
0680
0681 return IIO_VAL_FRACTIONAL;
0682 case IIO_CURRENT:
0683 ret = isl29501_register_read(isl29501,
0684 REG_DRIVER_RANGE,
0685 ¤t_scale);
0686 if (ret < 0)
0687 return ret;
0688
0689 if (current_scale > ARRAY_SIZE(isl29501_current_scale_table))
0690 return -EINVAL;
0691
0692 if (!current_scale) {
0693 *val = 0;
0694 *val2 = 0;
0695 return IIO_VAL_INT;
0696 }
0697
0698 *val = isl29501_current_scale_table[current_scale - 1][0];
0699 *val2 = isl29501_current_scale_table[current_scale - 1][1];
0700
0701 return IIO_VAL_INT_PLUS_MICRO;
0702 case IIO_TEMP:
0703
0704 *val = 125;
0705 *val2 = 100000;
0706
0707 return IIO_VAL_FRACTIONAL;
0708 default:
0709 return -EINVAL;
0710 }
0711 }
0712
0713 static int isl29501_get_calibbias(struct isl29501_private *isl29501,
0714 const struct iio_chan_spec *chan,
0715 int *bias)
0716 {
0717 switch (chan->type) {
0718 case IIO_PROXIMITY:
0719 return isl29501_register_read(isl29501,
0720 REG_DISTANCE_BIAS,
0721 bias);
0722 case IIO_TEMP:
0723 return isl29501_register_read(isl29501,
0724 REG_TEMPERATURE_BIAS,
0725 bias);
0726 default:
0727 return -EINVAL;
0728 }
0729 }
0730
0731 static int isl29501_get_inttime(struct isl29501_private *isl29501,
0732 int *val, int *val2)
0733 {
0734 int ret;
0735 u32 inttime;
0736
0737 ret = isl29501_register_read(isl29501, REG_INT_TIME, &inttime);
0738 if (ret < 0)
0739 return ret;
0740
0741 if (inttime >= ARRAY_SIZE(isl29501_int_time))
0742 return -EINVAL;
0743
0744 *val = isl29501_int_time[inttime][0];
0745 *val2 = isl29501_int_time[inttime][1];
0746
0747 return IIO_VAL_INT_PLUS_MICRO;
0748 }
0749
0750 static int isl29501_get_freq(struct isl29501_private *isl29501,
0751 int *val, int *val2)
0752 {
0753 int ret;
0754 int sample_time;
0755 unsigned long long freq;
0756 u32 temp;
0757
0758 ret = isl29501_register_read(isl29501, REG_SAMPLE_TIME, &sample_time);
0759 if (ret < 0)
0760 return ret;
0761
0762
0763 freq = 1000000ULL * 1000000ULL;
0764
0765 do_div(freq, 450 * (sample_time + 1));
0766
0767 temp = do_div(freq, 1000000);
0768 *val = freq;
0769 *val2 = temp;
0770
0771 return IIO_VAL_INT_PLUS_MICRO;
0772 }
0773
0774 static int isl29501_read_raw(struct iio_dev *indio_dev,
0775 struct iio_chan_spec const *chan, int *val,
0776 int *val2, long mask)
0777 {
0778 struct isl29501_private *isl29501 = iio_priv(indio_dev);
0779
0780 switch (mask) {
0781 case IIO_CHAN_INFO_RAW:
0782 return isl29501_get_raw(isl29501, chan, val);
0783 case IIO_CHAN_INFO_SCALE:
0784 return isl29501_get_scale(isl29501, chan, val, val2);
0785 case IIO_CHAN_INFO_INT_TIME:
0786 return isl29501_get_inttime(isl29501, val, val2);
0787 case IIO_CHAN_INFO_SAMP_FREQ:
0788 return isl29501_get_freq(isl29501, val, val2);
0789 case IIO_CHAN_INFO_CALIBBIAS:
0790 return isl29501_get_calibbias(isl29501, chan, val);
0791 default:
0792 return -EINVAL;
0793 }
0794 }
0795
0796 static int isl29501_set_raw(struct isl29501_private *isl29501,
0797 const struct iio_chan_spec *chan,
0798 int raw)
0799 {
0800 switch (chan->type) {
0801 case IIO_CURRENT:
0802 return isl29501_register_write(isl29501, REG_EMITTER_DAC, raw);
0803 default:
0804 return -EINVAL;
0805 }
0806 }
0807
0808 static int isl29501_set_inttime(struct isl29501_private *isl29501,
0809 int val, int val2)
0810 {
0811 int i;
0812
0813 for (i = 0; i < ARRAY_SIZE(isl29501_int_time); i++) {
0814 if (isl29501_int_time[i][0] == val &&
0815 isl29501_int_time[i][1] == val2) {
0816 return isl29501_register_write(isl29501,
0817 REG_INT_TIME,
0818 i);
0819 }
0820 }
0821
0822 return -EINVAL;
0823 }
0824
0825 static int isl29501_set_scale(struct isl29501_private *isl29501,
0826 const struct iio_chan_spec *chan,
0827 int val, int val2)
0828 {
0829 int i;
0830
0831 if (chan->type != IIO_CURRENT)
0832 return -EINVAL;
0833
0834 for (i = 0; i < ARRAY_SIZE(isl29501_current_scale_table); i++) {
0835 if (isl29501_current_scale_table[i][0] == val &&
0836 isl29501_current_scale_table[i][1] == val2) {
0837 return isl29501_register_write(isl29501,
0838 REG_DRIVER_RANGE,
0839 i + 1);
0840 }
0841 }
0842
0843 return -EINVAL;
0844 }
0845
0846 static int isl29501_set_calibbias(struct isl29501_private *isl29501,
0847 const struct iio_chan_spec *chan,
0848 int bias)
0849 {
0850 switch (chan->type) {
0851 case IIO_PROXIMITY:
0852 return isl29501_register_write(isl29501,
0853 REG_DISTANCE_BIAS,
0854 bias);
0855 case IIO_TEMP:
0856 return isl29501_register_write(isl29501,
0857 REG_TEMPERATURE_BIAS,
0858 bias);
0859 default:
0860 return -EINVAL;
0861 }
0862 }
0863
0864 static int isl29501_set_freq(struct isl29501_private *isl29501,
0865 int val, int val2)
0866 {
0867 int freq;
0868 unsigned long long sample_time;
0869
0870
0871 freq = val * 1000000 + val2 % 1000000;
0872 sample_time = 2222ULL * 1000000ULL;
0873 do_div(sample_time, freq);
0874
0875 sample_time -= 1;
0876
0877 if (sample_time > 255)
0878 return -ERANGE;
0879
0880 return isl29501_register_write(isl29501, REG_SAMPLE_TIME, sample_time);
0881 }
0882
0883 static int isl29501_write_raw(struct iio_dev *indio_dev,
0884 struct iio_chan_spec const *chan,
0885 int val, int val2, long mask)
0886 {
0887 struct isl29501_private *isl29501 = iio_priv(indio_dev);
0888
0889 switch (mask) {
0890 case IIO_CHAN_INFO_RAW:
0891 return isl29501_set_raw(isl29501, chan, val);
0892 case IIO_CHAN_INFO_INT_TIME:
0893 return isl29501_set_inttime(isl29501, val, val2);
0894 case IIO_CHAN_INFO_SAMP_FREQ:
0895 return isl29501_set_freq(isl29501, val, val2);
0896 case IIO_CHAN_INFO_SCALE:
0897 return isl29501_set_scale(isl29501, chan, val, val2);
0898 case IIO_CHAN_INFO_CALIBBIAS:
0899 return isl29501_set_calibbias(isl29501, chan, val);
0900 default:
0901 return -EINVAL;
0902 }
0903 }
0904
0905 static const struct iio_info isl29501_info = {
0906 .read_raw = &isl29501_read_raw,
0907 .write_raw = &isl29501_write_raw,
0908 .attrs = &isl29501_attribute_group,
0909 };
0910
0911 static int isl29501_init_chip(struct isl29501_private *isl29501)
0912 {
0913 int ret;
0914
0915 ret = i2c_smbus_read_byte_data(isl29501->client, ISL29501_DEVICE_ID);
0916 if (ret < 0) {
0917 dev_err(&isl29501->client->dev, "Error reading device id\n");
0918 return ret;
0919 }
0920
0921 if (ret != ISL29501_ID) {
0922 dev_err(&isl29501->client->dev,
0923 "Wrong chip id, got %x expected %x\n",
0924 ret, ISL29501_DEVICE_ID);
0925 return -ENODEV;
0926 }
0927
0928 ret = isl29501_reset_registers(isl29501);
0929 if (ret < 0)
0930 return ret;
0931
0932 return isl29501_begin_acquisition(isl29501);
0933 }
0934
0935 static irqreturn_t isl29501_trigger_handler(int irq, void *p)
0936 {
0937 struct iio_poll_func *pf = p;
0938 struct iio_dev *indio_dev = pf->indio_dev;
0939 struct isl29501_private *isl29501 = iio_priv(indio_dev);
0940 const unsigned long *active_mask = indio_dev->active_scan_mask;
0941 u32 buffer[4] __aligned(8) = {};
0942
0943 if (test_bit(ISL29501_DISTANCE_SCAN_INDEX, active_mask))
0944 isl29501_register_read(isl29501, REG_DISTANCE, buffer);
0945
0946 iio_push_to_buffers_with_timestamp(indio_dev, buffer, pf->timestamp);
0947 iio_trigger_notify_done(indio_dev->trig);
0948
0949 return IRQ_HANDLED;
0950 }
0951
0952 static int isl29501_probe(struct i2c_client *client,
0953 const struct i2c_device_id *id)
0954 {
0955 struct iio_dev *indio_dev;
0956 struct isl29501_private *isl29501;
0957 int ret;
0958
0959 indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*isl29501));
0960 if (!indio_dev)
0961 return -ENOMEM;
0962
0963 isl29501 = iio_priv(indio_dev);
0964
0965 i2c_set_clientdata(client, indio_dev);
0966 isl29501->client = client;
0967
0968 mutex_init(&isl29501->lock);
0969
0970 ret = isl29501_init_chip(isl29501);
0971 if (ret < 0)
0972 return ret;
0973
0974 indio_dev->modes = INDIO_DIRECT_MODE;
0975 indio_dev->channels = isl29501_channels;
0976 indio_dev->num_channels = ARRAY_SIZE(isl29501_channels);
0977 indio_dev->name = client->name;
0978 indio_dev->info = &isl29501_info;
0979
0980 ret = devm_iio_triggered_buffer_setup(&client->dev, indio_dev,
0981 iio_pollfunc_store_time,
0982 isl29501_trigger_handler,
0983 NULL);
0984 if (ret < 0) {
0985 dev_err(&client->dev, "unable to setup iio triggered buffer\n");
0986 return ret;
0987 }
0988
0989 return devm_iio_device_register(&client->dev, indio_dev);
0990 }
0991
0992 static const struct i2c_device_id isl29501_id[] = {
0993 {"isl29501", 0},
0994 {}
0995 };
0996
0997 MODULE_DEVICE_TABLE(i2c, isl29501_id);
0998
0999 #if defined(CONFIG_OF)
1000 static const struct of_device_id isl29501_i2c_matches[] = {
1001 { .compatible = "renesas,isl29501" },
1002 { }
1003 };
1004 MODULE_DEVICE_TABLE(of, isl29501_i2c_matches);
1005 #endif
1006
1007 static struct i2c_driver isl29501_driver = {
1008 .driver = {
1009 .name = "isl29501",
1010 },
1011 .id_table = isl29501_id,
1012 .probe = isl29501_probe,
1013 };
1014 module_i2c_driver(isl29501_driver);
1015
1016 MODULE_AUTHOR("Mathieu Othacehe <m.othacehe@gmail.com>");
1017 MODULE_DESCRIPTION("ISL29501 Time of Flight sensor driver");
1018 MODULE_LICENSE("GPL v2");