vcnl4000.c (29077B)
1// SPDX-License-Identifier: GPL-2.0-only 2/* 3 * vcnl4000.c - Support for Vishay VCNL4000/4010/4020/4040/4200 combined ambient 4 * light and proximity sensor 5 * 6 * Copyright 2012 Peter Meerwald <pmeerw@pmeerw.net> 7 * Copyright 2019 Pursim SPC 8 * Copyright 2020 Mathieu Othacehe <m.othacehe@gmail.com> 9 * 10 * IIO driver for: 11 * VCNL4000/10/20 (7-bit I2C slave address 0x13) 12 * VCNL4040 (7-bit I2C slave address 0x60) 13 * VCNL4200 (7-bit I2C slave address 0x51) 14 * 15 * TODO: 16 * allow to adjust IR current 17 * interrupts (VCNL4040, VCNL4200) 18 */ 19 20#include <linux/module.h> 21#include <linux/i2c.h> 22#include <linux/err.h> 23#include <linux/delay.h> 24#include <linux/pm_runtime.h> 25#include <linux/interrupt.h> 26 27#include <linux/iio/buffer.h> 28#include <linux/iio/events.h> 29#include <linux/iio/iio.h> 30#include <linux/iio/sysfs.h> 31#include <linux/iio/trigger.h> 32#include <linux/iio/trigger_consumer.h> 33#include <linux/iio/triggered_buffer.h> 34 35#define VCNL4000_DRV_NAME "vcnl4000" 36#define VCNL4000_PROD_ID 0x01 37#define VCNL4010_PROD_ID 0x02 /* for VCNL4020, VCNL4010 */ 38#define VCNL4040_PROD_ID 0x86 39#define VCNL4200_PROD_ID 0x58 40 41#define VCNL4000_COMMAND 0x80 /* Command register */ 42#define VCNL4000_PROD_REV 0x81 /* Product ID and Revision ID */ 43#define VCNL4010_PROX_RATE 0x82 /* Proximity rate */ 44#define VCNL4000_LED_CURRENT 0x83 /* IR LED current for proximity mode */ 45#define VCNL4000_AL_PARAM 0x84 /* Ambient light parameter register */ 46#define VCNL4010_ALS_PARAM 0x84 /* ALS rate */ 47#define VCNL4000_AL_RESULT_HI 0x85 /* Ambient light result register, MSB */ 48#define VCNL4000_AL_RESULT_LO 0x86 /* Ambient light result register, LSB */ 49#define VCNL4000_PS_RESULT_HI 0x87 /* Proximity result register, MSB */ 50#define VCNL4000_PS_RESULT_LO 0x88 /* Proximity result register, LSB */ 51#define VCNL4000_PS_MEAS_FREQ 0x89 /* Proximity test signal frequency */ 52#define VCNL4010_INT_CTRL 0x89 /* Interrupt control */ 53#define VCNL4000_PS_MOD_ADJ 0x8a /* Proximity modulator timing adjustment */ 54#define VCNL4010_LOW_THR_HI 0x8a /* Low threshold, MSB */ 55#define VCNL4010_LOW_THR_LO 0x8b /* Low threshold, LSB */ 56#define VCNL4010_HIGH_THR_HI 0x8c /* High threshold, MSB */ 57#define VCNL4010_HIGH_THR_LO 0x8d /* High threshold, LSB */ 58#define VCNL4010_ISR 0x8e /* Interrupt status */ 59 60#define VCNL4200_AL_CONF 0x00 /* Ambient light configuration */ 61#define VCNL4200_PS_CONF1 0x03 /* Proximity configuration */ 62#define VCNL4200_PS_DATA 0x08 /* Proximity data */ 63#define VCNL4200_AL_DATA 0x09 /* Ambient light data */ 64#define VCNL4200_DEV_ID 0x0e /* Device ID, slave address and version */ 65 66#define VCNL4040_DEV_ID 0x0c /* Device ID and version */ 67 68/* Bit masks for COMMAND register */ 69#define VCNL4000_AL_RDY BIT(6) /* ALS data ready? */ 70#define VCNL4000_PS_RDY BIT(5) /* proximity data ready? */ 71#define VCNL4000_AL_OD BIT(4) /* start on-demand ALS measurement */ 72#define VCNL4000_PS_OD BIT(3) /* start on-demand proximity measurement */ 73#define VCNL4000_ALS_EN BIT(2) /* start ALS measurement */ 74#define VCNL4000_PROX_EN BIT(1) /* start proximity measurement */ 75#define VCNL4000_SELF_TIMED_EN BIT(0) /* start self-timed measurement */ 76 77/* Bit masks for interrupt registers. */ 78#define VCNL4010_INT_THR_SEL BIT(0) /* Select threshold interrupt source */ 79#define VCNL4010_INT_THR_EN BIT(1) /* Threshold interrupt type */ 80#define VCNL4010_INT_ALS_EN BIT(2) /* Enable on ALS data ready */ 81#define VCNL4010_INT_PROX_EN BIT(3) /* Enable on proximity data ready */ 82 83#define VCNL4010_INT_THR_HIGH 0 /* High threshold exceeded */ 84#define VCNL4010_INT_THR_LOW 1 /* Low threshold exceeded */ 85#define VCNL4010_INT_ALS 2 /* ALS data ready */ 86#define VCNL4010_INT_PROXIMITY 3 /* Proximity data ready */ 87 88#define VCNL4010_INT_THR \ 89 (BIT(VCNL4010_INT_THR_LOW) | BIT(VCNL4010_INT_THR_HIGH)) 90#define VCNL4010_INT_DRDY \ 91 (BIT(VCNL4010_INT_PROXIMITY) | BIT(VCNL4010_INT_ALS)) 92 93static const int vcnl4010_prox_sampling_frequency[][2] = { 94 {1, 950000}, 95 {3, 906250}, 96 {7, 812500}, 97 {16, 625000}, 98 {31, 250000}, 99 {62, 500000}, 100 {125, 0}, 101 {250, 0}, 102}; 103 104#define VCNL4000_SLEEP_DELAY_MS 2000 /* before we enter pm_runtime_suspend */ 105 106enum vcnl4000_device_ids { 107 VCNL4000, 108 VCNL4010, 109 VCNL4040, 110 VCNL4200, 111}; 112 113struct vcnl4200_channel { 114 u8 reg; 115 ktime_t last_measurement; 116 ktime_t sampling_rate; 117 struct mutex lock; 118}; 119 120struct vcnl4000_data { 121 struct i2c_client *client; 122 enum vcnl4000_device_ids id; 123 int rev; 124 int al_scale; 125 const struct vcnl4000_chip_spec *chip_spec; 126 struct mutex vcnl4000_lock; 127 struct vcnl4200_channel vcnl4200_al; 128 struct vcnl4200_channel vcnl4200_ps; 129 uint32_t near_level; 130}; 131 132struct vcnl4000_chip_spec { 133 const char *prod; 134 struct iio_chan_spec const *channels; 135 const int num_channels; 136 const struct iio_info *info; 137 bool irq_support; 138 int (*init)(struct vcnl4000_data *data); 139 int (*measure_light)(struct vcnl4000_data *data, int *val); 140 int (*measure_proximity)(struct vcnl4000_data *data, int *val); 141 int (*set_power_state)(struct vcnl4000_data *data, bool on); 142}; 143 144static const struct i2c_device_id vcnl4000_id[] = { 145 { "vcnl4000", VCNL4000 }, 146 { "vcnl4010", VCNL4010 }, 147 { "vcnl4020", VCNL4010 }, 148 { "vcnl4040", VCNL4040 }, 149 { "vcnl4200", VCNL4200 }, 150 { } 151}; 152MODULE_DEVICE_TABLE(i2c, vcnl4000_id); 153 154static int vcnl4000_set_power_state(struct vcnl4000_data *data, bool on) 155{ 156 /* no suspend op */ 157 return 0; 158} 159 160static int vcnl4000_init(struct vcnl4000_data *data) 161{ 162 int ret, prod_id; 163 164 ret = i2c_smbus_read_byte_data(data->client, VCNL4000_PROD_REV); 165 if (ret < 0) 166 return ret; 167 168 prod_id = ret >> 4; 169 switch (prod_id) { 170 case VCNL4000_PROD_ID: 171 if (data->id != VCNL4000) 172 dev_warn(&data->client->dev, 173 "wrong device id, use vcnl4000"); 174 break; 175 case VCNL4010_PROD_ID: 176 if (data->id != VCNL4010) 177 dev_warn(&data->client->dev, 178 "wrong device id, use vcnl4010/4020"); 179 break; 180 default: 181 return -ENODEV; 182 } 183 184 data->rev = ret & 0xf; 185 data->al_scale = 250000; 186 mutex_init(&data->vcnl4000_lock); 187 188 return data->chip_spec->set_power_state(data, true); 189}; 190 191static int vcnl4200_set_power_state(struct vcnl4000_data *data, bool on) 192{ 193 u16 val = on ? 0 /* power on */ : 1 /* shut down */; 194 int ret; 195 196 ret = i2c_smbus_write_word_data(data->client, VCNL4200_AL_CONF, val); 197 if (ret < 0) 198 return ret; 199 200 ret = i2c_smbus_write_word_data(data->client, VCNL4200_PS_CONF1, val); 201 if (ret < 0) 202 return ret; 203 204 if (on) { 205 /* Wait at least one integration cycle before fetching data */ 206 data->vcnl4200_al.last_measurement = ktime_get(); 207 data->vcnl4200_ps.last_measurement = ktime_get(); 208 } 209 210 return 0; 211} 212 213static int vcnl4200_init(struct vcnl4000_data *data) 214{ 215 int ret, id; 216 217 ret = i2c_smbus_read_word_data(data->client, VCNL4200_DEV_ID); 218 if (ret < 0) 219 return ret; 220 221 id = ret & 0xff; 222 223 if (id != VCNL4200_PROD_ID) { 224 ret = i2c_smbus_read_word_data(data->client, VCNL4040_DEV_ID); 225 if (ret < 0) 226 return ret; 227 228 id = ret & 0xff; 229 230 if (id != VCNL4040_PROD_ID) 231 return -ENODEV; 232 } 233 234 dev_dbg(&data->client->dev, "device id 0x%x", id); 235 236 data->rev = (ret >> 8) & 0xf; 237 238 data->vcnl4200_al.reg = VCNL4200_AL_DATA; 239 data->vcnl4200_ps.reg = VCNL4200_PS_DATA; 240 switch (id) { 241 case VCNL4200_PROD_ID: 242 /* Default wait time is 50ms, add 20% tolerance. */ 243 data->vcnl4200_al.sampling_rate = ktime_set(0, 60000 * 1000); 244 /* Default wait time is 4.8ms, add 20% tolerance. */ 245 data->vcnl4200_ps.sampling_rate = ktime_set(0, 5760 * 1000); 246 data->al_scale = 24000; 247 break; 248 case VCNL4040_PROD_ID: 249 /* Default wait time is 80ms, add 20% tolerance. */ 250 data->vcnl4200_al.sampling_rate = ktime_set(0, 96000 * 1000); 251 /* Default wait time is 5ms, add 20% tolerance. */ 252 data->vcnl4200_ps.sampling_rate = ktime_set(0, 6000 * 1000); 253 data->al_scale = 120000; 254 break; 255 } 256 mutex_init(&data->vcnl4200_al.lock); 257 mutex_init(&data->vcnl4200_ps.lock); 258 259 ret = data->chip_spec->set_power_state(data, true); 260 if (ret < 0) 261 return ret; 262 263 return 0; 264}; 265 266static int vcnl4000_read_data(struct vcnl4000_data *data, u8 data_reg, int *val) 267{ 268 s32 ret; 269 270 ret = i2c_smbus_read_word_swapped(data->client, data_reg); 271 if (ret < 0) 272 return ret; 273 274 *val = ret; 275 return 0; 276} 277 278static int vcnl4000_write_data(struct vcnl4000_data *data, u8 data_reg, int val) 279{ 280 if (val > U16_MAX) 281 return -ERANGE; 282 283 return i2c_smbus_write_word_swapped(data->client, data_reg, val); 284} 285 286 287static int vcnl4000_measure(struct vcnl4000_data *data, u8 req_mask, 288 u8 rdy_mask, u8 data_reg, int *val) 289{ 290 int tries = 20; 291 int ret; 292 293 mutex_lock(&data->vcnl4000_lock); 294 295 ret = i2c_smbus_write_byte_data(data->client, VCNL4000_COMMAND, 296 req_mask); 297 if (ret < 0) 298 goto fail; 299 300 /* wait for data to become ready */ 301 while (tries--) { 302 ret = i2c_smbus_read_byte_data(data->client, VCNL4000_COMMAND); 303 if (ret < 0) 304 goto fail; 305 if (ret & rdy_mask) 306 break; 307 msleep(20); /* measurement takes up to 100 ms */ 308 } 309 310 if (tries < 0) { 311 dev_err(&data->client->dev, 312 "vcnl4000_measure() failed, data not ready\n"); 313 ret = -EIO; 314 goto fail; 315 } 316 317 ret = vcnl4000_read_data(data, data_reg, val); 318 if (ret < 0) 319 goto fail; 320 321 mutex_unlock(&data->vcnl4000_lock); 322 323 return 0; 324 325fail: 326 mutex_unlock(&data->vcnl4000_lock); 327 return ret; 328} 329 330static int vcnl4200_measure(struct vcnl4000_data *data, 331 struct vcnl4200_channel *chan, int *val) 332{ 333 int ret; 334 s64 delta; 335 ktime_t next_measurement; 336 337 mutex_lock(&chan->lock); 338 339 next_measurement = ktime_add(chan->last_measurement, 340 chan->sampling_rate); 341 delta = ktime_us_delta(next_measurement, ktime_get()); 342 if (delta > 0) 343 usleep_range(delta, delta + 500); 344 chan->last_measurement = ktime_get(); 345 346 mutex_unlock(&chan->lock); 347 348 ret = i2c_smbus_read_word_data(data->client, chan->reg); 349 if (ret < 0) 350 return ret; 351 352 *val = ret; 353 354 return 0; 355} 356 357static int vcnl4000_measure_light(struct vcnl4000_data *data, int *val) 358{ 359 return vcnl4000_measure(data, 360 VCNL4000_AL_OD, VCNL4000_AL_RDY, 361 VCNL4000_AL_RESULT_HI, val); 362} 363 364static int vcnl4200_measure_light(struct vcnl4000_data *data, int *val) 365{ 366 return vcnl4200_measure(data, &data->vcnl4200_al, val); 367} 368 369static int vcnl4000_measure_proximity(struct vcnl4000_data *data, int *val) 370{ 371 return vcnl4000_measure(data, 372 VCNL4000_PS_OD, VCNL4000_PS_RDY, 373 VCNL4000_PS_RESULT_HI, val); 374} 375 376static int vcnl4200_measure_proximity(struct vcnl4000_data *data, int *val) 377{ 378 return vcnl4200_measure(data, &data->vcnl4200_ps, val); 379} 380 381static int vcnl4010_read_proxy_samp_freq(struct vcnl4000_data *data, int *val, 382 int *val2) 383{ 384 int ret; 385 386 ret = i2c_smbus_read_byte_data(data->client, VCNL4010_PROX_RATE); 387 if (ret < 0) 388 return ret; 389 390 if (ret >= ARRAY_SIZE(vcnl4010_prox_sampling_frequency)) 391 return -EINVAL; 392 393 *val = vcnl4010_prox_sampling_frequency[ret][0]; 394 *val2 = vcnl4010_prox_sampling_frequency[ret][1]; 395 396 return 0; 397} 398 399static bool vcnl4010_is_in_periodic_mode(struct vcnl4000_data *data) 400{ 401 int ret; 402 403 ret = i2c_smbus_read_byte_data(data->client, VCNL4000_COMMAND); 404 if (ret < 0) 405 return false; 406 407 return !!(ret & VCNL4000_SELF_TIMED_EN); 408} 409 410static int vcnl4000_set_pm_runtime_state(struct vcnl4000_data *data, bool on) 411{ 412 struct device *dev = &data->client->dev; 413 int ret; 414 415 if (on) { 416 ret = pm_runtime_resume_and_get(dev); 417 } else { 418 pm_runtime_mark_last_busy(dev); 419 ret = pm_runtime_put_autosuspend(dev); 420 } 421 422 return ret; 423} 424 425static int vcnl4000_read_raw(struct iio_dev *indio_dev, 426 struct iio_chan_spec const *chan, 427 int *val, int *val2, long mask) 428{ 429 int ret; 430 struct vcnl4000_data *data = iio_priv(indio_dev); 431 432 switch (mask) { 433 case IIO_CHAN_INFO_RAW: 434 ret = vcnl4000_set_pm_runtime_state(data, true); 435 if (ret < 0) 436 return ret; 437 438 switch (chan->type) { 439 case IIO_LIGHT: 440 ret = data->chip_spec->measure_light(data, val); 441 if (!ret) 442 ret = IIO_VAL_INT; 443 break; 444 case IIO_PROXIMITY: 445 ret = data->chip_spec->measure_proximity(data, val); 446 if (!ret) 447 ret = IIO_VAL_INT; 448 break; 449 default: 450 ret = -EINVAL; 451 } 452 vcnl4000_set_pm_runtime_state(data, false); 453 return ret; 454 case IIO_CHAN_INFO_SCALE: 455 if (chan->type != IIO_LIGHT) 456 return -EINVAL; 457 458 *val = 0; 459 *val2 = data->al_scale; 460 return IIO_VAL_INT_PLUS_MICRO; 461 default: 462 return -EINVAL; 463 } 464} 465 466static int vcnl4010_read_raw(struct iio_dev *indio_dev, 467 struct iio_chan_spec const *chan, 468 int *val, int *val2, long mask) 469{ 470 int ret; 471 struct vcnl4000_data *data = iio_priv(indio_dev); 472 473 switch (mask) { 474 case IIO_CHAN_INFO_RAW: 475 case IIO_CHAN_INFO_SCALE: 476 ret = iio_device_claim_direct_mode(indio_dev); 477 if (ret) 478 return ret; 479 480 /* Protect against event capture. */ 481 if (vcnl4010_is_in_periodic_mode(data)) { 482 ret = -EBUSY; 483 } else { 484 ret = vcnl4000_read_raw(indio_dev, chan, val, val2, 485 mask); 486 } 487 488 iio_device_release_direct_mode(indio_dev); 489 return ret; 490 case IIO_CHAN_INFO_SAMP_FREQ: 491 switch (chan->type) { 492 case IIO_PROXIMITY: 493 ret = vcnl4010_read_proxy_samp_freq(data, val, val2); 494 if (ret < 0) 495 return ret; 496 return IIO_VAL_INT_PLUS_MICRO; 497 default: 498 return -EINVAL; 499 } 500 default: 501 return -EINVAL; 502 } 503} 504 505static int vcnl4010_read_avail(struct iio_dev *indio_dev, 506 struct iio_chan_spec const *chan, 507 const int **vals, int *type, int *length, 508 long mask) 509{ 510 switch (mask) { 511 case IIO_CHAN_INFO_SAMP_FREQ: 512 *vals = (int *)vcnl4010_prox_sampling_frequency; 513 *type = IIO_VAL_INT_PLUS_MICRO; 514 *length = 2 * ARRAY_SIZE(vcnl4010_prox_sampling_frequency); 515 return IIO_AVAIL_LIST; 516 default: 517 return -EINVAL; 518 } 519} 520 521static int vcnl4010_write_proxy_samp_freq(struct vcnl4000_data *data, int val, 522 int val2) 523{ 524 unsigned int i; 525 int index = -1; 526 527 for (i = 0; i < ARRAY_SIZE(vcnl4010_prox_sampling_frequency); i++) { 528 if (val == vcnl4010_prox_sampling_frequency[i][0] && 529 val2 == vcnl4010_prox_sampling_frequency[i][1]) { 530 index = i; 531 break; 532 } 533 } 534 535 if (index < 0) 536 return -EINVAL; 537 538 return i2c_smbus_write_byte_data(data->client, VCNL4010_PROX_RATE, 539 index); 540} 541 542static int vcnl4010_write_raw(struct iio_dev *indio_dev, 543 struct iio_chan_spec const *chan, 544 int val, int val2, long mask) 545{ 546 int ret; 547 struct vcnl4000_data *data = iio_priv(indio_dev); 548 549 ret = iio_device_claim_direct_mode(indio_dev); 550 if (ret) 551 return ret; 552 553 /* Protect against event capture. */ 554 if (vcnl4010_is_in_periodic_mode(data)) { 555 ret = -EBUSY; 556 goto end; 557 } 558 559 switch (mask) { 560 case IIO_CHAN_INFO_SAMP_FREQ: 561 switch (chan->type) { 562 case IIO_PROXIMITY: 563 ret = vcnl4010_write_proxy_samp_freq(data, val, val2); 564 goto end; 565 default: 566 ret = -EINVAL; 567 goto end; 568 } 569 default: 570 ret = -EINVAL; 571 goto end; 572 } 573 574end: 575 iio_device_release_direct_mode(indio_dev); 576 return ret; 577} 578 579static int vcnl4010_read_event(struct iio_dev *indio_dev, 580 const struct iio_chan_spec *chan, 581 enum iio_event_type type, 582 enum iio_event_direction dir, 583 enum iio_event_info info, 584 int *val, int *val2) 585{ 586 int ret; 587 struct vcnl4000_data *data = iio_priv(indio_dev); 588 589 switch (info) { 590 case IIO_EV_INFO_VALUE: 591 switch (dir) { 592 case IIO_EV_DIR_RISING: 593 ret = vcnl4000_read_data(data, VCNL4010_HIGH_THR_HI, 594 val); 595 if (ret < 0) 596 return ret; 597 return IIO_VAL_INT; 598 case IIO_EV_DIR_FALLING: 599 ret = vcnl4000_read_data(data, VCNL4010_LOW_THR_HI, 600 val); 601 if (ret < 0) 602 return ret; 603 return IIO_VAL_INT; 604 default: 605 return -EINVAL; 606 } 607 default: 608 return -EINVAL; 609 } 610} 611 612static int vcnl4010_write_event(struct iio_dev *indio_dev, 613 const struct iio_chan_spec *chan, 614 enum iio_event_type type, 615 enum iio_event_direction dir, 616 enum iio_event_info info, 617 int val, int val2) 618{ 619 int ret; 620 struct vcnl4000_data *data = iio_priv(indio_dev); 621 622 switch (info) { 623 case IIO_EV_INFO_VALUE: 624 switch (dir) { 625 case IIO_EV_DIR_RISING: 626 ret = vcnl4000_write_data(data, VCNL4010_HIGH_THR_HI, 627 val); 628 if (ret < 0) 629 return ret; 630 return IIO_VAL_INT; 631 case IIO_EV_DIR_FALLING: 632 ret = vcnl4000_write_data(data, VCNL4010_LOW_THR_HI, 633 val); 634 if (ret < 0) 635 return ret; 636 return IIO_VAL_INT; 637 default: 638 return -EINVAL; 639 } 640 default: 641 return -EINVAL; 642 } 643} 644 645static bool vcnl4010_is_thr_enabled(struct vcnl4000_data *data) 646{ 647 int ret; 648 649 ret = i2c_smbus_read_byte_data(data->client, VCNL4010_INT_CTRL); 650 if (ret < 0) 651 return false; 652 653 return !!(ret & VCNL4010_INT_THR_EN); 654} 655 656static int vcnl4010_read_event_config(struct iio_dev *indio_dev, 657 const struct iio_chan_spec *chan, 658 enum iio_event_type type, 659 enum iio_event_direction dir) 660{ 661 struct vcnl4000_data *data = iio_priv(indio_dev); 662 663 switch (chan->type) { 664 case IIO_PROXIMITY: 665 return vcnl4010_is_thr_enabled(data); 666 default: 667 return -EINVAL; 668 } 669} 670 671static int vcnl4010_config_threshold(struct iio_dev *indio_dev, bool state) 672{ 673 struct vcnl4000_data *data = iio_priv(indio_dev); 674 int ret; 675 int icr; 676 int command; 677 678 if (state) { 679 ret = iio_device_claim_direct_mode(indio_dev); 680 if (ret) 681 return ret; 682 683 /* Enable periodic measurement of proximity data. */ 684 command = VCNL4000_SELF_TIMED_EN | VCNL4000_PROX_EN; 685 686 /* 687 * Enable interrupts on threshold, for proximity data by 688 * default. 689 */ 690 icr = VCNL4010_INT_THR_EN; 691 } else { 692 if (!vcnl4010_is_thr_enabled(data)) 693 return 0; 694 695 command = 0; 696 icr = 0; 697 } 698 699 ret = i2c_smbus_write_byte_data(data->client, VCNL4000_COMMAND, 700 command); 701 if (ret < 0) 702 goto end; 703 704 ret = i2c_smbus_write_byte_data(data->client, VCNL4010_INT_CTRL, icr); 705 706end: 707 if (state) 708 iio_device_release_direct_mode(indio_dev); 709 710 return ret; 711} 712 713static int vcnl4010_write_event_config(struct iio_dev *indio_dev, 714 const struct iio_chan_spec *chan, 715 enum iio_event_type type, 716 enum iio_event_direction dir, 717 int state) 718{ 719 switch (chan->type) { 720 case IIO_PROXIMITY: 721 return vcnl4010_config_threshold(indio_dev, state); 722 default: 723 return -EINVAL; 724 } 725} 726 727static ssize_t vcnl4000_read_near_level(struct iio_dev *indio_dev, 728 uintptr_t priv, 729 const struct iio_chan_spec *chan, 730 char *buf) 731{ 732 struct vcnl4000_data *data = iio_priv(indio_dev); 733 734 return sprintf(buf, "%u\n", data->near_level); 735} 736 737static const struct iio_chan_spec_ext_info vcnl4000_ext_info[] = { 738 { 739 .name = "nearlevel", 740 .shared = IIO_SEPARATE, 741 .read = vcnl4000_read_near_level, 742 }, 743 { /* sentinel */ } 744}; 745 746static const struct iio_event_spec vcnl4000_event_spec[] = { 747 { 748 .type = IIO_EV_TYPE_THRESH, 749 .dir = IIO_EV_DIR_RISING, 750 .mask_separate = BIT(IIO_EV_INFO_VALUE), 751 }, { 752 .type = IIO_EV_TYPE_THRESH, 753 .dir = IIO_EV_DIR_FALLING, 754 .mask_separate = BIT(IIO_EV_INFO_VALUE), 755 }, { 756 .type = IIO_EV_TYPE_THRESH, 757 .dir = IIO_EV_DIR_EITHER, 758 .mask_separate = BIT(IIO_EV_INFO_ENABLE), 759 } 760}; 761 762static const struct iio_chan_spec vcnl4000_channels[] = { 763 { 764 .type = IIO_LIGHT, 765 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | 766 BIT(IIO_CHAN_INFO_SCALE), 767 }, { 768 .type = IIO_PROXIMITY, 769 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), 770 .ext_info = vcnl4000_ext_info, 771 } 772}; 773 774static const struct iio_chan_spec vcnl4010_channels[] = { 775 { 776 .type = IIO_LIGHT, 777 .scan_index = -1, 778 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | 779 BIT(IIO_CHAN_INFO_SCALE), 780 }, { 781 .type = IIO_PROXIMITY, 782 .scan_index = 0, 783 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | 784 BIT(IIO_CHAN_INFO_SAMP_FREQ), 785 .info_mask_separate_available = BIT(IIO_CHAN_INFO_SAMP_FREQ), 786 .event_spec = vcnl4000_event_spec, 787 .num_event_specs = ARRAY_SIZE(vcnl4000_event_spec), 788 .ext_info = vcnl4000_ext_info, 789 .scan_type = { 790 .sign = 'u', 791 .realbits = 16, 792 .storagebits = 16, 793 .endianness = IIO_CPU, 794 }, 795 }, 796 IIO_CHAN_SOFT_TIMESTAMP(1), 797}; 798 799static const struct iio_info vcnl4000_info = { 800 .read_raw = vcnl4000_read_raw, 801}; 802 803static const struct iio_info vcnl4010_info = { 804 .read_raw = vcnl4010_read_raw, 805 .read_avail = vcnl4010_read_avail, 806 .write_raw = vcnl4010_write_raw, 807 .read_event_value = vcnl4010_read_event, 808 .write_event_value = vcnl4010_write_event, 809 .read_event_config = vcnl4010_read_event_config, 810 .write_event_config = vcnl4010_write_event_config, 811}; 812 813static const struct vcnl4000_chip_spec vcnl4000_chip_spec_cfg[] = { 814 [VCNL4000] = { 815 .prod = "VCNL4000", 816 .init = vcnl4000_init, 817 .measure_light = vcnl4000_measure_light, 818 .measure_proximity = vcnl4000_measure_proximity, 819 .set_power_state = vcnl4000_set_power_state, 820 .channels = vcnl4000_channels, 821 .num_channels = ARRAY_SIZE(vcnl4000_channels), 822 .info = &vcnl4000_info, 823 .irq_support = false, 824 }, 825 [VCNL4010] = { 826 .prod = "VCNL4010/4020", 827 .init = vcnl4000_init, 828 .measure_light = vcnl4000_measure_light, 829 .measure_proximity = vcnl4000_measure_proximity, 830 .set_power_state = vcnl4000_set_power_state, 831 .channels = vcnl4010_channels, 832 .num_channels = ARRAY_SIZE(vcnl4010_channels), 833 .info = &vcnl4010_info, 834 .irq_support = true, 835 }, 836 [VCNL4040] = { 837 .prod = "VCNL4040", 838 .init = vcnl4200_init, 839 .measure_light = vcnl4200_measure_light, 840 .measure_proximity = vcnl4200_measure_proximity, 841 .set_power_state = vcnl4200_set_power_state, 842 .channels = vcnl4000_channels, 843 .num_channels = ARRAY_SIZE(vcnl4000_channels), 844 .info = &vcnl4000_info, 845 .irq_support = false, 846 }, 847 [VCNL4200] = { 848 .prod = "VCNL4200", 849 .init = vcnl4200_init, 850 .measure_light = vcnl4200_measure_light, 851 .measure_proximity = vcnl4200_measure_proximity, 852 .set_power_state = vcnl4200_set_power_state, 853 .channels = vcnl4000_channels, 854 .num_channels = ARRAY_SIZE(vcnl4000_channels), 855 .info = &vcnl4000_info, 856 .irq_support = false, 857 }, 858}; 859 860static irqreturn_t vcnl4010_irq_thread(int irq, void *p) 861{ 862 struct iio_dev *indio_dev = p; 863 struct vcnl4000_data *data = iio_priv(indio_dev); 864 unsigned long isr; 865 int ret; 866 867 ret = i2c_smbus_read_byte_data(data->client, VCNL4010_ISR); 868 if (ret < 0) 869 goto end; 870 871 isr = ret; 872 873 if (isr & VCNL4010_INT_THR) { 874 if (test_bit(VCNL4010_INT_THR_LOW, &isr)) { 875 iio_push_event(indio_dev, 876 IIO_UNMOD_EVENT_CODE( 877 IIO_PROXIMITY, 878 1, 879 IIO_EV_TYPE_THRESH, 880 IIO_EV_DIR_FALLING), 881 iio_get_time_ns(indio_dev)); 882 } 883 884 if (test_bit(VCNL4010_INT_THR_HIGH, &isr)) { 885 iio_push_event(indio_dev, 886 IIO_UNMOD_EVENT_CODE( 887 IIO_PROXIMITY, 888 1, 889 IIO_EV_TYPE_THRESH, 890 IIO_EV_DIR_RISING), 891 iio_get_time_ns(indio_dev)); 892 } 893 894 i2c_smbus_write_byte_data(data->client, VCNL4010_ISR, 895 isr & VCNL4010_INT_THR); 896 } 897 898 if (isr & VCNL4010_INT_DRDY && iio_buffer_enabled(indio_dev)) 899 iio_trigger_poll_chained(indio_dev->trig); 900 901end: 902 return IRQ_HANDLED; 903} 904 905static irqreturn_t vcnl4010_trigger_handler(int irq, void *p) 906{ 907 struct iio_poll_func *pf = p; 908 struct iio_dev *indio_dev = pf->indio_dev; 909 struct vcnl4000_data *data = iio_priv(indio_dev); 910 const unsigned long *active_scan_mask = indio_dev->active_scan_mask; 911 u16 buffer[8] __aligned(8) = {0}; /* 1x16-bit + naturally aligned ts */ 912 bool data_read = false; 913 unsigned long isr; 914 int val = 0; 915 int ret; 916 917 ret = i2c_smbus_read_byte_data(data->client, VCNL4010_ISR); 918 if (ret < 0) 919 goto end; 920 921 isr = ret; 922 923 if (test_bit(0, active_scan_mask)) { 924 if (test_bit(VCNL4010_INT_PROXIMITY, &isr)) { 925 ret = vcnl4000_read_data(data, 926 VCNL4000_PS_RESULT_HI, 927 &val); 928 if (ret < 0) 929 goto end; 930 931 buffer[0] = val; 932 data_read = true; 933 } 934 } 935 936 ret = i2c_smbus_write_byte_data(data->client, VCNL4010_ISR, 937 isr & VCNL4010_INT_DRDY); 938 if (ret < 0) 939 goto end; 940 941 if (!data_read) 942 goto end; 943 944 iio_push_to_buffers_with_timestamp(indio_dev, buffer, 945 iio_get_time_ns(indio_dev)); 946 947end: 948 iio_trigger_notify_done(indio_dev->trig); 949 return IRQ_HANDLED; 950} 951 952static int vcnl4010_buffer_postenable(struct iio_dev *indio_dev) 953{ 954 struct vcnl4000_data *data = iio_priv(indio_dev); 955 int ret; 956 int cmd; 957 958 /* Do not enable the buffer if we are already capturing events. */ 959 if (vcnl4010_is_in_periodic_mode(data)) 960 return -EBUSY; 961 962 ret = i2c_smbus_write_byte_data(data->client, VCNL4010_INT_CTRL, 963 VCNL4010_INT_PROX_EN); 964 if (ret < 0) 965 return ret; 966 967 cmd = VCNL4000_SELF_TIMED_EN | VCNL4000_PROX_EN; 968 return i2c_smbus_write_byte_data(data->client, VCNL4000_COMMAND, cmd); 969} 970 971static int vcnl4010_buffer_predisable(struct iio_dev *indio_dev) 972{ 973 struct vcnl4000_data *data = iio_priv(indio_dev); 974 int ret; 975 976 ret = i2c_smbus_write_byte_data(data->client, VCNL4010_INT_CTRL, 0); 977 if (ret < 0) 978 return ret; 979 980 return i2c_smbus_write_byte_data(data->client, VCNL4000_COMMAND, 0); 981} 982 983static const struct iio_buffer_setup_ops vcnl4010_buffer_ops = { 984 .postenable = &vcnl4010_buffer_postenable, 985 .predisable = &vcnl4010_buffer_predisable, 986}; 987 988static const struct iio_trigger_ops vcnl4010_trigger_ops = { 989 .validate_device = iio_trigger_validate_own_device, 990}; 991 992static int vcnl4010_probe_trigger(struct iio_dev *indio_dev) 993{ 994 struct vcnl4000_data *data = iio_priv(indio_dev); 995 struct i2c_client *client = data->client; 996 struct iio_trigger *trigger; 997 998 trigger = devm_iio_trigger_alloc(&client->dev, "%s-dev%d", 999 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 1010static 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; 1084fail_poweroff: 1085 data->chip_spec->set_power_state(data, false); 1086 return ret; 1087} 1088 1089static 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}; 1112MODULE_DEVICE_TABLE(of, vcnl_4000_of_match); 1113 1114static 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 1119 pm_runtime_dont_use_autosuspend(&client->dev); 1120 pm_runtime_disable(&client->dev); 1121 iio_device_unregister(indio_dev); 1122 pm_runtime_set_suspended(&client->dev); 1123 1124 return data->chip_spec->set_power_state(data, false); 1125} 1126 1127static int __maybe_unused vcnl4000_runtime_suspend(struct device *dev) 1128{ 1129 struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev)); 1130 struct vcnl4000_data *data = iio_priv(indio_dev); 1131 1132 return data->chip_spec->set_power_state(data, false); 1133} 1134 1135static int __maybe_unused vcnl4000_runtime_resume(struct device *dev) 1136{ 1137 struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev)); 1138 struct vcnl4000_data *data = iio_priv(indio_dev); 1139 1140 return data->chip_spec->set_power_state(data, true); 1141} 1142 1143static const struct dev_pm_ops vcnl4000_pm_ops = { 1144 SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, 1145 pm_runtime_force_resume) 1146 SET_RUNTIME_PM_OPS(vcnl4000_runtime_suspend, 1147 vcnl4000_runtime_resume, NULL) 1148}; 1149 1150static struct i2c_driver vcnl4000_driver = { 1151 .driver = { 1152 .name = VCNL4000_DRV_NAME, 1153 .pm = &vcnl4000_pm_ops, 1154 .of_match_table = vcnl_4000_of_match, 1155 }, 1156 .probe = vcnl4000_probe, 1157 .id_table = vcnl4000_id, 1158 .remove = vcnl4000_remove, 1159}; 1160 1161module_i2c_driver(vcnl4000_driver); 1162 1163MODULE_AUTHOR("Peter Meerwald <pmeerw@pmeerw.net>"); 1164MODULE_AUTHOR("Mathieu Othacehe <m.othacehe@gmail.com>"); 1165MODULE_DESCRIPTION("Vishay VCNL4000 proximity/ambient light sensor driver"); 1166MODULE_LICENSE("GPL");