0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020 #include <linux/module.h>
0021 #include <linux/i2c.h>
0022 #include <linux/err.h>
0023 #include <linux/delay.h>
0024 #include <linux/pm_runtime.h>
0025 #include <linux/interrupt.h>
0026
0027 #include <linux/iio/buffer.h>
0028 #include <linux/iio/events.h>
0029 #include <linux/iio/iio.h>
0030 #include <linux/iio/sysfs.h>
0031 #include <linux/iio/trigger.h>
0032 #include <linux/iio/trigger_consumer.h>
0033 #include <linux/iio/triggered_buffer.h>
0034
0035 #define VCNL4000_DRV_NAME "vcnl4000"
0036 #define VCNL4000_PROD_ID 0x01
0037 #define VCNL4010_PROD_ID 0x02
0038 #define VCNL4040_PROD_ID 0x86
0039 #define VCNL4200_PROD_ID 0x58
0040
0041 #define VCNL4000_COMMAND 0x80
0042 #define VCNL4000_PROD_REV 0x81
0043 #define VCNL4010_PROX_RATE 0x82
0044 #define VCNL4000_LED_CURRENT 0x83
0045 #define VCNL4000_AL_PARAM 0x84
0046 #define VCNL4010_ALS_PARAM 0x84
0047 #define VCNL4000_AL_RESULT_HI 0x85
0048 #define VCNL4000_AL_RESULT_LO 0x86
0049 #define VCNL4000_PS_RESULT_HI 0x87
0050 #define VCNL4000_PS_RESULT_LO 0x88
0051 #define VCNL4000_PS_MEAS_FREQ 0x89
0052 #define VCNL4010_INT_CTRL 0x89
0053 #define VCNL4000_PS_MOD_ADJ 0x8a
0054 #define VCNL4010_LOW_THR_HI 0x8a
0055 #define VCNL4010_LOW_THR_LO 0x8b
0056 #define VCNL4010_HIGH_THR_HI 0x8c
0057 #define VCNL4010_HIGH_THR_LO 0x8d
0058 #define VCNL4010_ISR 0x8e
0059
0060 #define VCNL4200_AL_CONF 0x00
0061 #define VCNL4200_PS_CONF1 0x03
0062 #define VCNL4200_PS_DATA 0x08
0063 #define VCNL4200_AL_DATA 0x09
0064 #define VCNL4200_DEV_ID 0x0e
0065
0066 #define VCNL4040_DEV_ID 0x0c
0067
0068
0069 #define VCNL4000_AL_RDY BIT(6)
0070 #define VCNL4000_PS_RDY BIT(5)
0071 #define VCNL4000_AL_OD BIT(4)
0072 #define VCNL4000_PS_OD BIT(3)
0073 #define VCNL4000_ALS_EN BIT(2)
0074 #define VCNL4000_PROX_EN BIT(1)
0075 #define VCNL4000_SELF_TIMED_EN BIT(0)
0076
0077
0078 #define VCNL4010_INT_THR_SEL BIT(0)
0079 #define VCNL4010_INT_THR_EN BIT(1)
0080 #define VCNL4010_INT_ALS_EN BIT(2)
0081 #define VCNL4010_INT_PROX_EN BIT(3)
0082
0083 #define VCNL4010_INT_THR_HIGH 0
0084 #define VCNL4010_INT_THR_LOW 1
0085 #define VCNL4010_INT_ALS 2
0086 #define VCNL4010_INT_PROXIMITY 3
0087
0088 #define VCNL4010_INT_THR \
0089 (BIT(VCNL4010_INT_THR_LOW) | BIT(VCNL4010_INT_THR_HIGH))
0090 #define VCNL4010_INT_DRDY \
0091 (BIT(VCNL4010_INT_PROXIMITY) | BIT(VCNL4010_INT_ALS))
0092
0093 static const int vcnl4010_prox_sampling_frequency[][2] = {
0094 {1, 950000},
0095 {3, 906250},
0096 {7, 812500},
0097 {16, 625000},
0098 {31, 250000},
0099 {62, 500000},
0100 {125, 0},
0101 {250, 0},
0102 };
0103
0104 #define VCNL4000_SLEEP_DELAY_MS 2000
0105
0106 enum vcnl4000_device_ids {
0107 VCNL4000,
0108 VCNL4010,
0109 VCNL4040,
0110 VCNL4200,
0111 };
0112
0113 struct vcnl4200_channel {
0114 u8 reg;
0115 ktime_t last_measurement;
0116 ktime_t sampling_rate;
0117 struct mutex lock;
0118 };
0119
0120 struct vcnl4000_data {
0121 struct i2c_client *client;
0122 enum vcnl4000_device_ids id;
0123 int rev;
0124 int al_scale;
0125 const struct vcnl4000_chip_spec *chip_spec;
0126 struct mutex vcnl4000_lock;
0127 struct vcnl4200_channel vcnl4200_al;
0128 struct vcnl4200_channel vcnl4200_ps;
0129 uint32_t near_level;
0130 };
0131
0132 struct vcnl4000_chip_spec {
0133 const char *prod;
0134 struct iio_chan_spec const *channels;
0135 const int num_channels;
0136 const struct iio_info *info;
0137 bool irq_support;
0138 int (*init)(struct vcnl4000_data *data);
0139 int (*measure_light)(struct vcnl4000_data *data, int *val);
0140 int (*measure_proximity)(struct vcnl4000_data *data, int *val);
0141 int (*set_power_state)(struct vcnl4000_data *data, bool on);
0142 };
0143
0144 static const struct i2c_device_id vcnl4000_id[] = {
0145 { "vcnl4000", VCNL4000 },
0146 { "vcnl4010", VCNL4010 },
0147 { "vcnl4020", VCNL4010 },
0148 { "vcnl4040", VCNL4040 },
0149 { "vcnl4200", VCNL4200 },
0150 { }
0151 };
0152 MODULE_DEVICE_TABLE(i2c, vcnl4000_id);
0153
0154 static int vcnl4000_set_power_state(struct vcnl4000_data *data, bool on)
0155 {
0156
0157 return 0;
0158 }
0159
0160 static int vcnl4000_init(struct vcnl4000_data *data)
0161 {
0162 int ret, prod_id;
0163
0164 ret = i2c_smbus_read_byte_data(data->client, VCNL4000_PROD_REV);
0165 if (ret < 0)
0166 return ret;
0167
0168 prod_id = ret >> 4;
0169 switch (prod_id) {
0170 case VCNL4000_PROD_ID:
0171 if (data->id != VCNL4000)
0172 dev_warn(&data->client->dev,
0173 "wrong device id, use vcnl4000");
0174 break;
0175 case VCNL4010_PROD_ID:
0176 if (data->id != VCNL4010)
0177 dev_warn(&data->client->dev,
0178 "wrong device id, use vcnl4010/4020");
0179 break;
0180 default:
0181 return -ENODEV;
0182 }
0183
0184 data->rev = ret & 0xf;
0185 data->al_scale = 250000;
0186 mutex_init(&data->vcnl4000_lock);
0187
0188 return data->chip_spec->set_power_state(data, true);
0189 };
0190
0191 static int vcnl4200_set_power_state(struct vcnl4000_data *data, bool on)
0192 {
0193 u16 val = on ? 0 : 1 ;
0194 int ret;
0195
0196 ret = i2c_smbus_write_word_data(data->client, VCNL4200_AL_CONF, val);
0197 if (ret < 0)
0198 return ret;
0199
0200 ret = i2c_smbus_write_word_data(data->client, VCNL4200_PS_CONF1, val);
0201 if (ret < 0)
0202 return ret;
0203
0204 if (on) {
0205
0206 data->vcnl4200_al.last_measurement = ktime_get();
0207 data->vcnl4200_ps.last_measurement = ktime_get();
0208 }
0209
0210 return 0;
0211 }
0212
0213 static int vcnl4200_init(struct vcnl4000_data *data)
0214 {
0215 int ret, id;
0216
0217 ret = i2c_smbus_read_word_data(data->client, VCNL4200_DEV_ID);
0218 if (ret < 0)
0219 return ret;
0220
0221 id = ret & 0xff;
0222
0223 if (id != VCNL4200_PROD_ID) {
0224 ret = i2c_smbus_read_word_data(data->client, VCNL4040_DEV_ID);
0225 if (ret < 0)
0226 return ret;
0227
0228 id = ret & 0xff;
0229
0230 if (id != VCNL4040_PROD_ID)
0231 return -ENODEV;
0232 }
0233
0234 dev_dbg(&data->client->dev, "device id 0x%x", id);
0235
0236 data->rev = (ret >> 8) & 0xf;
0237
0238 data->vcnl4200_al.reg = VCNL4200_AL_DATA;
0239 data->vcnl4200_ps.reg = VCNL4200_PS_DATA;
0240 switch (id) {
0241 case VCNL4200_PROD_ID:
0242
0243 data->vcnl4200_al.sampling_rate = ktime_set(0, 60000 * 1000);
0244
0245 data->vcnl4200_ps.sampling_rate = ktime_set(0, 5760 * 1000);
0246 data->al_scale = 24000;
0247 break;
0248 case VCNL4040_PROD_ID:
0249
0250 data->vcnl4200_al.sampling_rate = ktime_set(0, 96000 * 1000);
0251
0252 data->vcnl4200_ps.sampling_rate = ktime_set(0, 6000 * 1000);
0253 data->al_scale = 120000;
0254 break;
0255 }
0256 mutex_init(&data->vcnl4200_al.lock);
0257 mutex_init(&data->vcnl4200_ps.lock);
0258
0259 ret = data->chip_spec->set_power_state(data, true);
0260 if (ret < 0)
0261 return ret;
0262
0263 return 0;
0264 };
0265
0266 static int vcnl4000_read_data(struct vcnl4000_data *data, u8 data_reg, int *val)
0267 {
0268 s32 ret;
0269
0270 ret = i2c_smbus_read_word_swapped(data->client, data_reg);
0271 if (ret < 0)
0272 return ret;
0273
0274 *val = ret;
0275 return 0;
0276 }
0277
0278 static int vcnl4000_write_data(struct vcnl4000_data *data, u8 data_reg, int val)
0279 {
0280 if (val > U16_MAX)
0281 return -ERANGE;
0282
0283 return i2c_smbus_write_word_swapped(data->client, data_reg, val);
0284 }
0285
0286
0287 static int vcnl4000_measure(struct vcnl4000_data *data, u8 req_mask,
0288 u8 rdy_mask, u8 data_reg, int *val)
0289 {
0290 int tries = 20;
0291 int ret;
0292
0293 mutex_lock(&data->vcnl4000_lock);
0294
0295 ret = i2c_smbus_write_byte_data(data->client, VCNL4000_COMMAND,
0296 req_mask);
0297 if (ret < 0)
0298 goto fail;
0299
0300
0301 while (tries--) {
0302 ret = i2c_smbus_read_byte_data(data->client, VCNL4000_COMMAND);
0303 if (ret < 0)
0304 goto fail;
0305 if (ret & rdy_mask)
0306 break;
0307 msleep(20);
0308 }
0309
0310 if (tries < 0) {
0311 dev_err(&data->client->dev,
0312 "vcnl4000_measure() failed, data not ready\n");
0313 ret = -EIO;
0314 goto fail;
0315 }
0316
0317 ret = vcnl4000_read_data(data, data_reg, val);
0318 if (ret < 0)
0319 goto fail;
0320
0321 mutex_unlock(&data->vcnl4000_lock);
0322
0323 return 0;
0324
0325 fail:
0326 mutex_unlock(&data->vcnl4000_lock);
0327 return ret;
0328 }
0329
0330 static int vcnl4200_measure(struct vcnl4000_data *data,
0331 struct vcnl4200_channel *chan, int *val)
0332 {
0333 int ret;
0334 s64 delta;
0335 ktime_t next_measurement;
0336
0337 mutex_lock(&chan->lock);
0338
0339 next_measurement = ktime_add(chan->last_measurement,
0340 chan->sampling_rate);
0341 delta = ktime_us_delta(next_measurement, ktime_get());
0342 if (delta > 0)
0343 usleep_range(delta, delta + 500);
0344 chan->last_measurement = ktime_get();
0345
0346 mutex_unlock(&chan->lock);
0347
0348 ret = i2c_smbus_read_word_data(data->client, chan->reg);
0349 if (ret < 0)
0350 return ret;
0351
0352 *val = ret;
0353
0354 return 0;
0355 }
0356
0357 static int vcnl4000_measure_light(struct vcnl4000_data *data, int *val)
0358 {
0359 return vcnl4000_measure(data,
0360 VCNL4000_AL_OD, VCNL4000_AL_RDY,
0361 VCNL4000_AL_RESULT_HI, val);
0362 }
0363
0364 static int vcnl4200_measure_light(struct vcnl4000_data *data, int *val)
0365 {
0366 return vcnl4200_measure(data, &data->vcnl4200_al, val);
0367 }
0368
0369 static int vcnl4000_measure_proximity(struct vcnl4000_data *data, int *val)
0370 {
0371 return vcnl4000_measure(data,
0372 VCNL4000_PS_OD, VCNL4000_PS_RDY,
0373 VCNL4000_PS_RESULT_HI, val);
0374 }
0375
0376 static int vcnl4200_measure_proximity(struct vcnl4000_data *data, int *val)
0377 {
0378 return vcnl4200_measure(data, &data->vcnl4200_ps, val);
0379 }
0380
0381 static int vcnl4010_read_proxy_samp_freq(struct vcnl4000_data *data, int *val,
0382 int *val2)
0383 {
0384 int ret;
0385
0386 ret = i2c_smbus_read_byte_data(data->client, VCNL4010_PROX_RATE);
0387 if (ret < 0)
0388 return ret;
0389
0390 if (ret >= ARRAY_SIZE(vcnl4010_prox_sampling_frequency))
0391 return -EINVAL;
0392
0393 *val = vcnl4010_prox_sampling_frequency[ret][0];
0394 *val2 = vcnl4010_prox_sampling_frequency[ret][1];
0395
0396 return 0;
0397 }
0398
0399 static bool vcnl4010_is_in_periodic_mode(struct vcnl4000_data *data)
0400 {
0401 int ret;
0402
0403 ret = i2c_smbus_read_byte_data(data->client, VCNL4000_COMMAND);
0404 if (ret < 0)
0405 return false;
0406
0407 return !!(ret & VCNL4000_SELF_TIMED_EN);
0408 }
0409
0410 static int vcnl4000_set_pm_runtime_state(struct vcnl4000_data *data, bool on)
0411 {
0412 struct device *dev = &data->client->dev;
0413 int ret;
0414
0415 if (on) {
0416 ret = pm_runtime_resume_and_get(dev);
0417 } else {
0418 pm_runtime_mark_last_busy(dev);
0419 ret = pm_runtime_put_autosuspend(dev);
0420 }
0421
0422 return ret;
0423 }
0424
0425 static int vcnl4000_read_raw(struct iio_dev *indio_dev,
0426 struct iio_chan_spec const *chan,
0427 int *val, int *val2, long mask)
0428 {
0429 int ret;
0430 struct vcnl4000_data *data = iio_priv(indio_dev);
0431
0432 switch (mask) {
0433 case IIO_CHAN_INFO_RAW:
0434 ret = vcnl4000_set_pm_runtime_state(data, true);
0435 if (ret < 0)
0436 return ret;
0437
0438 switch (chan->type) {
0439 case IIO_LIGHT:
0440 ret = data->chip_spec->measure_light(data, val);
0441 if (!ret)
0442 ret = IIO_VAL_INT;
0443 break;
0444 case IIO_PROXIMITY:
0445 ret = data->chip_spec->measure_proximity(data, val);
0446 if (!ret)
0447 ret = IIO_VAL_INT;
0448 break;
0449 default:
0450 ret = -EINVAL;
0451 }
0452 vcnl4000_set_pm_runtime_state(data, false);
0453 return ret;
0454 case IIO_CHAN_INFO_SCALE:
0455 if (chan->type != IIO_LIGHT)
0456 return -EINVAL;
0457
0458 *val = 0;
0459 *val2 = data->al_scale;
0460 return IIO_VAL_INT_PLUS_MICRO;
0461 default:
0462 return -EINVAL;
0463 }
0464 }
0465
0466 static int vcnl4010_read_raw(struct iio_dev *indio_dev,
0467 struct iio_chan_spec const *chan,
0468 int *val, int *val2, long mask)
0469 {
0470 int ret;
0471 struct vcnl4000_data *data = iio_priv(indio_dev);
0472
0473 switch (mask) {
0474 case IIO_CHAN_INFO_RAW:
0475 case IIO_CHAN_INFO_SCALE:
0476 ret = iio_device_claim_direct_mode(indio_dev);
0477 if (ret)
0478 return ret;
0479
0480
0481 if (vcnl4010_is_in_periodic_mode(data)) {
0482 ret = -EBUSY;
0483 } else {
0484 ret = vcnl4000_read_raw(indio_dev, chan, val, val2,
0485 mask);
0486 }
0487
0488 iio_device_release_direct_mode(indio_dev);
0489 return ret;
0490 case IIO_CHAN_INFO_SAMP_FREQ:
0491 switch (chan->type) {
0492 case IIO_PROXIMITY:
0493 ret = vcnl4010_read_proxy_samp_freq(data, val, val2);
0494 if (ret < 0)
0495 return ret;
0496 return IIO_VAL_INT_PLUS_MICRO;
0497 default:
0498 return -EINVAL;
0499 }
0500 default:
0501 return -EINVAL;
0502 }
0503 }
0504
0505 static int vcnl4010_read_avail(struct iio_dev *indio_dev,
0506 struct iio_chan_spec const *chan,
0507 const int **vals, int *type, int *length,
0508 long mask)
0509 {
0510 switch (mask) {
0511 case IIO_CHAN_INFO_SAMP_FREQ:
0512 *vals = (int *)vcnl4010_prox_sampling_frequency;
0513 *type = IIO_VAL_INT_PLUS_MICRO;
0514 *length = 2 * ARRAY_SIZE(vcnl4010_prox_sampling_frequency);
0515 return IIO_AVAIL_LIST;
0516 default:
0517 return -EINVAL;
0518 }
0519 }
0520
0521 static int vcnl4010_write_proxy_samp_freq(struct vcnl4000_data *data, int val,
0522 int val2)
0523 {
0524 unsigned int i;
0525 int index = -1;
0526
0527 for (i = 0; i < ARRAY_SIZE(vcnl4010_prox_sampling_frequency); i++) {
0528 if (val == vcnl4010_prox_sampling_frequency[i][0] &&
0529 val2 == vcnl4010_prox_sampling_frequency[i][1]) {
0530 index = i;
0531 break;
0532 }
0533 }
0534
0535 if (index < 0)
0536 return -EINVAL;
0537
0538 return i2c_smbus_write_byte_data(data->client, VCNL4010_PROX_RATE,
0539 index);
0540 }
0541
0542 static int vcnl4010_write_raw(struct iio_dev *indio_dev,
0543 struct iio_chan_spec const *chan,
0544 int val, int val2, long mask)
0545 {
0546 int ret;
0547 struct vcnl4000_data *data = iio_priv(indio_dev);
0548
0549 ret = iio_device_claim_direct_mode(indio_dev);
0550 if (ret)
0551 return ret;
0552
0553
0554 if (vcnl4010_is_in_periodic_mode(data)) {
0555 ret = -EBUSY;
0556 goto end;
0557 }
0558
0559 switch (mask) {
0560 case IIO_CHAN_INFO_SAMP_FREQ:
0561 switch (chan->type) {
0562 case IIO_PROXIMITY:
0563 ret = vcnl4010_write_proxy_samp_freq(data, val, val2);
0564 goto end;
0565 default:
0566 ret = -EINVAL;
0567 goto end;
0568 }
0569 default:
0570 ret = -EINVAL;
0571 goto end;
0572 }
0573
0574 end:
0575 iio_device_release_direct_mode(indio_dev);
0576 return ret;
0577 }
0578
0579 static int vcnl4010_read_event(struct iio_dev *indio_dev,
0580 const struct iio_chan_spec *chan,
0581 enum iio_event_type type,
0582 enum iio_event_direction dir,
0583 enum iio_event_info info,
0584 int *val, int *val2)
0585 {
0586 int ret;
0587 struct vcnl4000_data *data = iio_priv(indio_dev);
0588
0589 switch (info) {
0590 case IIO_EV_INFO_VALUE:
0591 switch (dir) {
0592 case IIO_EV_DIR_RISING:
0593 ret = vcnl4000_read_data(data, VCNL4010_HIGH_THR_HI,
0594 val);
0595 if (ret < 0)
0596 return ret;
0597 return IIO_VAL_INT;
0598 case IIO_EV_DIR_FALLING:
0599 ret = vcnl4000_read_data(data, VCNL4010_LOW_THR_HI,
0600 val);
0601 if (ret < 0)
0602 return ret;
0603 return IIO_VAL_INT;
0604 default:
0605 return -EINVAL;
0606 }
0607 default:
0608 return -EINVAL;
0609 }
0610 }
0611
0612 static int vcnl4010_write_event(struct iio_dev *indio_dev,
0613 const struct iio_chan_spec *chan,
0614 enum iio_event_type type,
0615 enum iio_event_direction dir,
0616 enum iio_event_info info,
0617 int val, int val2)
0618 {
0619 int ret;
0620 struct vcnl4000_data *data = iio_priv(indio_dev);
0621
0622 switch (info) {
0623 case IIO_EV_INFO_VALUE:
0624 switch (dir) {
0625 case IIO_EV_DIR_RISING:
0626 ret = vcnl4000_write_data(data, VCNL4010_HIGH_THR_HI,
0627 val);
0628 if (ret < 0)
0629 return ret;
0630 return IIO_VAL_INT;
0631 case IIO_EV_DIR_FALLING:
0632 ret = vcnl4000_write_data(data, VCNL4010_LOW_THR_HI,
0633 val);
0634 if (ret < 0)
0635 return ret;
0636 return IIO_VAL_INT;
0637 default:
0638 return -EINVAL;
0639 }
0640 default:
0641 return -EINVAL;
0642 }
0643 }
0644
0645 static bool vcnl4010_is_thr_enabled(struct vcnl4000_data *data)
0646 {
0647 int ret;
0648
0649 ret = i2c_smbus_read_byte_data(data->client, VCNL4010_INT_CTRL);
0650 if (ret < 0)
0651 return false;
0652
0653 return !!(ret & VCNL4010_INT_THR_EN);
0654 }
0655
0656 static int vcnl4010_read_event_config(struct iio_dev *indio_dev,
0657 const struct iio_chan_spec *chan,
0658 enum iio_event_type type,
0659 enum iio_event_direction dir)
0660 {
0661 struct vcnl4000_data *data = iio_priv(indio_dev);
0662
0663 switch (chan->type) {
0664 case IIO_PROXIMITY:
0665 return vcnl4010_is_thr_enabled(data);
0666 default:
0667 return -EINVAL;
0668 }
0669 }
0670
0671 static int vcnl4010_config_threshold(struct iio_dev *indio_dev, bool state)
0672 {
0673 struct vcnl4000_data *data = iio_priv(indio_dev);
0674 int ret;
0675 int icr;
0676 int command;
0677
0678 if (state) {
0679 ret = iio_device_claim_direct_mode(indio_dev);
0680 if (ret)
0681 return ret;
0682
0683
0684 command = VCNL4000_SELF_TIMED_EN | VCNL4000_PROX_EN;
0685
0686
0687
0688
0689
0690 icr = VCNL4010_INT_THR_EN;
0691 } else {
0692 if (!vcnl4010_is_thr_enabled(data))
0693 return 0;
0694
0695 command = 0;
0696 icr = 0;
0697 }
0698
0699 ret = i2c_smbus_write_byte_data(data->client, VCNL4000_COMMAND,
0700 command);
0701 if (ret < 0)
0702 goto end;
0703
0704 ret = i2c_smbus_write_byte_data(data->client, VCNL4010_INT_CTRL, icr);
0705
0706 end:
0707 if (state)
0708 iio_device_release_direct_mode(indio_dev);
0709
0710 return ret;
0711 }
0712
0713 static int vcnl4010_write_event_config(struct iio_dev *indio_dev,
0714 const struct iio_chan_spec *chan,
0715 enum iio_event_type type,
0716 enum iio_event_direction dir,
0717 int state)
0718 {
0719 switch (chan->type) {
0720 case IIO_PROXIMITY:
0721 return vcnl4010_config_threshold(indio_dev, state);
0722 default:
0723 return -EINVAL;
0724 }
0725 }
0726
0727 static ssize_t vcnl4000_read_near_level(struct iio_dev *indio_dev,
0728 uintptr_t priv,
0729 const struct iio_chan_spec *chan,
0730 char *buf)
0731 {
0732 struct vcnl4000_data *data = iio_priv(indio_dev);
0733
0734 return sprintf(buf, "%u\n", data->near_level);
0735 }
0736
0737 static const struct iio_chan_spec_ext_info vcnl4000_ext_info[] = {
0738 {
0739 .name = "nearlevel",
0740 .shared = IIO_SEPARATE,
0741 .read = vcnl4000_read_near_level,
0742 },
0743 { }
0744 };
0745
0746 static const struct iio_event_spec vcnl4000_event_spec[] = {
0747 {
0748 .type = IIO_EV_TYPE_THRESH,
0749 .dir = IIO_EV_DIR_RISING,
0750 .mask_separate = BIT(IIO_EV_INFO_VALUE),
0751 }, {
0752 .type = IIO_EV_TYPE_THRESH,
0753 .dir = IIO_EV_DIR_FALLING,
0754 .mask_separate = BIT(IIO_EV_INFO_VALUE),
0755 }, {
0756 .type = IIO_EV_TYPE_THRESH,
0757 .dir = IIO_EV_DIR_EITHER,
0758 .mask_separate = BIT(IIO_EV_INFO_ENABLE),
0759 }
0760 };
0761
0762 static const struct iio_chan_spec vcnl4000_channels[] = {
0763 {
0764 .type = IIO_LIGHT,
0765 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
0766 BIT(IIO_CHAN_INFO_SCALE),
0767 }, {
0768 .type = IIO_PROXIMITY,
0769 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
0770 .ext_info = vcnl4000_ext_info,
0771 }
0772 };
0773
0774 static const struct iio_chan_spec vcnl4010_channels[] = {
0775 {
0776 .type = IIO_LIGHT,
0777 .scan_index = -1,
0778 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
0779 BIT(IIO_CHAN_INFO_SCALE),
0780 }, {
0781 .type = IIO_PROXIMITY,
0782 .scan_index = 0,
0783 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
0784 BIT(IIO_CHAN_INFO_SAMP_FREQ),
0785 .info_mask_separate_available = BIT(IIO_CHAN_INFO_SAMP_FREQ),
0786 .event_spec = vcnl4000_event_spec,
0787 .num_event_specs = ARRAY_SIZE(vcnl4000_event_spec),
0788 .ext_info = vcnl4000_ext_info,
0789 .scan_type = {
0790 .sign = 'u',
0791 .realbits = 16,
0792 .storagebits = 16,
0793 .endianness = IIO_CPU,
0794 },
0795 },
0796 IIO_CHAN_SOFT_TIMESTAMP(1),
0797 };
0798
0799 static const struct iio_info vcnl4000_info = {
0800 .read_raw = vcnl4000_read_raw,
0801 };
0802
0803 static const struct iio_info vcnl4010_info = {
0804 .read_raw = vcnl4010_read_raw,
0805 .read_avail = vcnl4010_read_avail,
0806 .write_raw = vcnl4010_write_raw,
0807 .read_event_value = vcnl4010_read_event,
0808 .write_event_value = vcnl4010_write_event,
0809 .read_event_config = vcnl4010_read_event_config,
0810 .write_event_config = vcnl4010_write_event_config,
0811 };
0812
0813 static const struct vcnl4000_chip_spec vcnl4000_chip_spec_cfg[] = {
0814 [VCNL4000] = {
0815 .prod = "VCNL4000",
0816 .init = vcnl4000_init,
0817 .measure_light = vcnl4000_measure_light,
0818 .measure_proximity = vcnl4000_measure_proximity,
0819 .set_power_state = vcnl4000_set_power_state,
0820 .channels = vcnl4000_channels,
0821 .num_channels = ARRAY_SIZE(vcnl4000_channels),
0822 .info = &vcnl4000_info,
0823 .irq_support = false,
0824 },
0825 [VCNL4010] = {
0826 .prod = "VCNL4010/4020",
0827 .init = vcnl4000_init,
0828 .measure_light = vcnl4000_measure_light,
0829 .measure_proximity = vcnl4000_measure_proximity,
0830 .set_power_state = vcnl4000_set_power_state,
0831 .channels = vcnl4010_channels,
0832 .num_channels = ARRAY_SIZE(vcnl4010_channels),
0833 .info = &vcnl4010_info,
0834 .irq_support = true,
0835 },
0836 [VCNL4040] = {
0837 .prod = "VCNL4040",
0838 .init = vcnl4200_init,
0839 .measure_light = vcnl4200_measure_light,
0840 .measure_proximity = vcnl4200_measure_proximity,
0841 .set_power_state = vcnl4200_set_power_state,
0842 .channels = vcnl4000_channels,
0843 .num_channels = ARRAY_SIZE(vcnl4000_channels),
0844 .info = &vcnl4000_info,
0845 .irq_support = false,
0846 },
0847 [VCNL4200] = {
0848 .prod = "VCNL4200",
0849 .init = vcnl4200_init,
0850 .measure_light = vcnl4200_measure_light,
0851 .measure_proximity = vcnl4200_measure_proximity,
0852 .set_power_state = vcnl4200_set_power_state,
0853 .channels = vcnl4000_channels,
0854 .num_channels = ARRAY_SIZE(vcnl4000_channels),
0855 .info = &vcnl4000_info,
0856 .irq_support = false,
0857 },
0858 };
0859
0860 static irqreturn_t vcnl4010_irq_thread(int irq, void *p)
0861 {
0862 struct iio_dev *indio_dev = p;
0863 struct vcnl4000_data *data = iio_priv(indio_dev);
0864 unsigned long isr;
0865 int ret;
0866
0867 ret = i2c_smbus_read_byte_data(data->client, VCNL4010_ISR);
0868 if (ret < 0)
0869 goto end;
0870
0871 isr = ret;
0872
0873 if (isr & VCNL4010_INT_THR) {
0874 if (test_bit(VCNL4010_INT_THR_LOW, &isr)) {
0875 iio_push_event(indio_dev,
0876 IIO_UNMOD_EVENT_CODE(
0877 IIO_PROXIMITY,
0878 1,
0879 IIO_EV_TYPE_THRESH,
0880 IIO_EV_DIR_FALLING),
0881 iio_get_time_ns(indio_dev));
0882 }
0883
0884 if (test_bit(VCNL4010_INT_THR_HIGH, &isr)) {
0885 iio_push_event(indio_dev,
0886 IIO_UNMOD_EVENT_CODE(
0887 IIO_PROXIMITY,
0888 1,
0889 IIO_EV_TYPE_THRESH,
0890 IIO_EV_DIR_RISING),
0891 iio_get_time_ns(indio_dev));
0892 }
0893
0894 i2c_smbus_write_byte_data(data->client, VCNL4010_ISR,
0895 isr & VCNL4010_INT_THR);
0896 }
0897
0898 if (isr & VCNL4010_INT_DRDY && iio_buffer_enabled(indio_dev))
0899 iio_trigger_poll_chained(indio_dev->trig);
0900
0901 end:
0902 return IRQ_HANDLED;
0903 }
0904
0905 static irqreturn_t vcnl4010_trigger_handler(int irq, void *p)
0906 {
0907 struct iio_poll_func *pf = p;
0908 struct iio_dev *indio_dev = pf->indio_dev;
0909 struct vcnl4000_data *data = iio_priv(indio_dev);
0910 const unsigned long *active_scan_mask = indio_dev->active_scan_mask;
0911 u16 buffer[8] __aligned(8) = {0};
0912 bool data_read = false;
0913 unsigned long isr;
0914 int val = 0;
0915 int ret;
0916
0917 ret = i2c_smbus_read_byte_data(data->client, VCNL4010_ISR);
0918 if (ret < 0)
0919 goto end;
0920
0921 isr = ret;
0922
0923 if (test_bit(0, active_scan_mask)) {
0924 if (test_bit(VCNL4010_INT_PROXIMITY, &isr)) {
0925 ret = vcnl4000_read_data(data,
0926 VCNL4000_PS_RESULT_HI,
0927 &val);
0928 if (ret < 0)
0929 goto end;
0930
0931 buffer[0] = val;
0932 data_read = true;
0933 }
0934 }
0935
0936 ret = i2c_smbus_write_byte_data(data->client, VCNL4010_ISR,
0937 isr & VCNL4010_INT_DRDY);
0938 if (ret < 0)
0939 goto end;
0940
0941 if (!data_read)
0942 goto end;
0943
0944 iio_push_to_buffers_with_timestamp(indio_dev, buffer,
0945 iio_get_time_ns(indio_dev));
0946
0947 end:
0948 iio_trigger_notify_done(indio_dev->trig);
0949 return IRQ_HANDLED;
0950 }
0951
0952 static int vcnl4010_buffer_postenable(struct iio_dev *indio_dev)
0953 {
0954 struct vcnl4000_data *data = iio_priv(indio_dev);
0955 int ret;
0956 int cmd;
0957
0958
0959 if (vcnl4010_is_in_periodic_mode(data))
0960 return -EBUSY;
0961
0962 ret = i2c_smbus_write_byte_data(data->client, VCNL4010_INT_CTRL,
0963 VCNL4010_INT_PROX_EN);
0964 if (ret < 0)
0965 return ret;
0966
0967 cmd = VCNL4000_SELF_TIMED_EN | VCNL4000_PROX_EN;
0968 return i2c_smbus_write_byte_data(data->client, VCNL4000_COMMAND, cmd);
0969 }
0970
0971 static int vcnl4010_buffer_predisable(struct iio_dev *indio_dev)
0972 {
0973 struct vcnl4000_data *data = iio_priv(indio_dev);
0974 int ret;
0975
0976 ret = i2c_smbus_write_byte_data(data->client, VCNL4010_INT_CTRL, 0);
0977 if (ret < 0)
0978 return ret;
0979
0980 return i2c_smbus_write_byte_data(data->client, VCNL4000_COMMAND, 0);
0981 }
0982
0983 static const struct iio_buffer_setup_ops vcnl4010_buffer_ops = {
0984 .postenable = &vcnl4010_buffer_postenable,
0985 .predisable = &vcnl4010_buffer_predisable,
0986 };
0987
0988 static const struct iio_trigger_ops vcnl4010_trigger_ops = {
0989 .validate_device = iio_trigger_validate_own_device,
0990 };
0991
0992 static int vcnl4010_probe_trigger(struct iio_dev *indio_dev)
0993 {
0994 struct vcnl4000_data *data = iio_priv(indio_dev);
0995 struct i2c_client *client = data->client;
0996 struct iio_trigger *trigger;
0997
0998 trigger = devm_iio_trigger_alloc(&client->dev, "%s-dev%d",
0999 indio_dev->name,
1000 iio_device_id(indio_dev));
1001 if (!trigger)
1002 return -ENOMEM;
1003
1004 trigger->ops = &vcnl4010_trigger_ops;
1005 iio_trigger_set_drvdata(trigger, indio_dev);
1006
1007 return devm_iio_trigger_register(&client->dev, trigger);
1008 }
1009
1010 static int vcnl4000_probe(struct i2c_client *client,
1011 const struct i2c_device_id *id)
1012 {
1013 struct vcnl4000_data *data;
1014 struct iio_dev *indio_dev;
1015 int ret;
1016
1017 indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
1018 if (!indio_dev)
1019 return -ENOMEM;
1020
1021 data = iio_priv(indio_dev);
1022 i2c_set_clientdata(client, indio_dev);
1023 data->client = client;
1024 data->id = id->driver_data;
1025 data->chip_spec = &vcnl4000_chip_spec_cfg[data->id];
1026
1027 ret = data->chip_spec->init(data);
1028 if (ret < 0)
1029 return ret;
1030
1031 dev_dbg(&client->dev, "%s Ambient light/proximity sensor, Rev: %02x\n",
1032 data->chip_spec->prod, data->rev);
1033
1034 if (device_property_read_u32(&client->dev, "proximity-near-level",
1035 &data->near_level))
1036 data->near_level = 0;
1037
1038 indio_dev->info = data->chip_spec->info;
1039 indio_dev->channels = data->chip_spec->channels;
1040 indio_dev->num_channels = data->chip_spec->num_channels;
1041 indio_dev->name = VCNL4000_DRV_NAME;
1042 indio_dev->modes = INDIO_DIRECT_MODE;
1043
1044 if (client->irq && data->chip_spec->irq_support) {
1045 ret = devm_iio_triggered_buffer_setup(&client->dev, indio_dev,
1046 NULL,
1047 vcnl4010_trigger_handler,
1048 &vcnl4010_buffer_ops);
1049 if (ret < 0) {
1050 dev_err(&client->dev,
1051 "unable to setup iio triggered buffer\n");
1052 return ret;
1053 }
1054
1055 ret = devm_request_threaded_irq(&client->dev, client->irq,
1056 NULL, vcnl4010_irq_thread,
1057 IRQF_TRIGGER_FALLING |
1058 IRQF_ONESHOT,
1059 "vcnl4010_irq",
1060 indio_dev);
1061 if (ret < 0) {
1062 dev_err(&client->dev, "irq request failed\n");
1063 return ret;
1064 }
1065
1066 ret = vcnl4010_probe_trigger(indio_dev);
1067 if (ret < 0)
1068 return ret;
1069 }
1070
1071 ret = pm_runtime_set_active(&client->dev);
1072 if (ret < 0)
1073 goto fail_poweroff;
1074
1075 ret = iio_device_register(indio_dev);
1076 if (ret < 0)
1077 goto fail_poweroff;
1078
1079 pm_runtime_enable(&client->dev);
1080 pm_runtime_set_autosuspend_delay(&client->dev, VCNL4000_SLEEP_DELAY_MS);
1081 pm_runtime_use_autosuspend(&client->dev);
1082
1083 return 0;
1084 fail_poweroff:
1085 data->chip_spec->set_power_state(data, false);
1086 return ret;
1087 }
1088
1089 static const struct of_device_id vcnl_4000_of_match[] = {
1090 {
1091 .compatible = "vishay,vcnl4000",
1092 .data = (void *)VCNL4000,
1093 },
1094 {
1095 .compatible = "vishay,vcnl4010",
1096 .data = (void *)VCNL4010,
1097 },
1098 {
1099 .compatible = "vishay,vcnl4020",
1100 .data = (void *)VCNL4010,
1101 },
1102 {
1103 .compatible = "vishay,vcnl4040",
1104 .data = (void *)VCNL4040,
1105 },
1106 {
1107 .compatible = "vishay,vcnl4200",
1108 .data = (void *)VCNL4200,
1109 },
1110 {},
1111 };
1112 MODULE_DEVICE_TABLE(of, vcnl_4000_of_match);
1113
1114 static int vcnl4000_remove(struct i2c_client *client)
1115 {
1116 struct iio_dev *indio_dev = i2c_get_clientdata(client);
1117 struct vcnl4000_data *data = iio_priv(indio_dev);
1118 int ret;
1119
1120 pm_runtime_dont_use_autosuspend(&client->dev);
1121 pm_runtime_disable(&client->dev);
1122 iio_device_unregister(indio_dev);
1123 pm_runtime_set_suspended(&client->dev);
1124
1125 ret = data->chip_spec->set_power_state(data, false);
1126 if (ret)
1127 dev_warn(&client->dev, "Failed to power down (%pe)\n",
1128 ERR_PTR(ret));
1129
1130 return 0;
1131 }
1132
1133 static int vcnl4000_runtime_suspend(struct device *dev)
1134 {
1135 struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
1136 struct vcnl4000_data *data = iio_priv(indio_dev);
1137
1138 return data->chip_spec->set_power_state(data, false);
1139 }
1140
1141 static int vcnl4000_runtime_resume(struct device *dev)
1142 {
1143 struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
1144 struct vcnl4000_data *data = iio_priv(indio_dev);
1145
1146 return data->chip_spec->set_power_state(data, true);
1147 }
1148
1149 static DEFINE_RUNTIME_DEV_PM_OPS(vcnl4000_pm_ops, vcnl4000_runtime_suspend,
1150 vcnl4000_runtime_resume, NULL);
1151
1152 static struct i2c_driver vcnl4000_driver = {
1153 .driver = {
1154 .name = VCNL4000_DRV_NAME,
1155 .pm = pm_ptr(&vcnl4000_pm_ops),
1156 .of_match_table = vcnl_4000_of_match,
1157 },
1158 .probe = vcnl4000_probe,
1159 .id_table = vcnl4000_id,
1160 .remove = vcnl4000_remove,
1161 };
1162
1163 module_i2c_driver(vcnl4000_driver);
1164
1165 MODULE_AUTHOR("Peter Meerwald <pmeerw@pmeerw.net>");
1166 MODULE_AUTHOR("Mathieu Othacehe <m.othacehe@gmail.com>");
1167 MODULE_DESCRIPTION("Vishay VCNL4000 proximity/ambient light sensor driver");
1168 MODULE_LICENSE("GPL");