linux/drivers/iio/light/vcnl4000.c
<<
>>
Prefs
   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");
1167