linux/drivers/iio/light/vcnl4035.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * VCNL4035 Ambient Light and Proximity Sensor - 7-bit I2C slave address 0x60
   4 *
   5 * Copyright (c) 2018, DENX Software Engineering GmbH
   6 * Author: Parthiban Nallathambi <pn@denx.de>
   7 *
   8 * TODO: Proximity
   9 */
  10#include <linux/bitops.h>
  11#include <linux/i2c.h>
  12#include <linux/module.h>
  13#include <linux/pm_runtime.h>
  14#include <linux/regmap.h>
  15
  16#include <linux/iio/buffer.h>
  17#include <linux/iio/events.h>
  18#include <linux/iio/iio.h>
  19#include <linux/iio/sysfs.h>
  20#include <linux/iio/trigger.h>
  21#include <linux/iio/trigger_consumer.h>
  22#include <linux/iio/triggered_buffer.h>
  23
  24#define VCNL4035_DRV_NAME       "vcnl4035"
  25#define VCNL4035_IRQ_NAME       "vcnl4035_event"
  26#define VCNL4035_REGMAP_NAME    "vcnl4035_regmap"
  27
  28/* Device registers */
  29#define VCNL4035_ALS_CONF       0x00
  30#define VCNL4035_ALS_THDH       0x01
  31#define VCNL4035_ALS_THDL       0x02
  32#define VCNL4035_ALS_DATA       0x0B
  33#define VCNL4035_WHITE_DATA     0x0C
  34#define VCNL4035_INT_FLAG       0x0D
  35#define VCNL4035_DEV_ID         0x0E
  36
  37/* Register masks */
  38#define VCNL4035_MODE_ALS_MASK          BIT(0)
  39#define VCNL4035_MODE_ALS_WHITE_CHAN    BIT(8)
  40#define VCNL4035_MODE_ALS_INT_MASK      BIT(1)
  41#define VCNL4035_ALS_IT_MASK            GENMASK(7, 5)
  42#define VCNL4035_ALS_PERS_MASK          GENMASK(3, 2)
  43#define VCNL4035_INT_ALS_IF_H_MASK      BIT(12)
  44#define VCNL4035_INT_ALS_IF_L_MASK      BIT(13)
  45
  46/* Default values */
  47#define VCNL4035_MODE_ALS_ENABLE        BIT(0)
  48#define VCNL4035_MODE_ALS_DISABLE       0x00
  49#define VCNL4035_MODE_ALS_INT_ENABLE    BIT(1)
  50#define VCNL4035_MODE_ALS_INT_DISABLE   0
  51#define VCNL4035_DEV_ID_VAL             0x80
  52#define VCNL4035_ALS_IT_DEFAULT         0x01
  53#define VCNL4035_ALS_PERS_DEFAULT       0x00
  54#define VCNL4035_ALS_THDH_DEFAULT       5000
  55#define VCNL4035_ALS_THDL_DEFAULT       100
  56#define VCNL4035_SLEEP_DELAY_MS         2000
  57
  58struct vcnl4035_data {
  59        struct i2c_client *client;
  60        struct regmap *regmap;
  61        unsigned int als_it_val;
  62        unsigned int als_persistence;
  63        unsigned int als_thresh_low;
  64        unsigned int als_thresh_high;
  65        struct iio_trigger *drdy_trigger0;
  66};
  67
  68static inline bool vcnl4035_is_triggered(struct vcnl4035_data *data)
  69{
  70        int ret;
  71        int reg;
  72
  73        ret = regmap_read(data->regmap, VCNL4035_INT_FLAG, &reg);
  74        if (ret < 0)
  75                return false;
  76
  77        return !!(reg &
  78                (VCNL4035_INT_ALS_IF_H_MASK | VCNL4035_INT_ALS_IF_L_MASK));
  79}
  80
  81static irqreturn_t vcnl4035_drdy_irq_thread(int irq, void *private)
  82{
  83        struct iio_dev *indio_dev = private;
  84        struct vcnl4035_data *data = iio_priv(indio_dev);
  85
  86        if (vcnl4035_is_triggered(data)) {
  87                iio_push_event(indio_dev, IIO_UNMOD_EVENT_CODE(IIO_LIGHT,
  88                                                        0,
  89                                                        IIO_EV_TYPE_THRESH,
  90                                                        IIO_EV_DIR_EITHER),
  91                                iio_get_time_ns(indio_dev));
  92                iio_trigger_poll_chained(data->drdy_trigger0);
  93                return IRQ_HANDLED;
  94        }
  95
  96        return IRQ_NONE;
  97}
  98
  99/* Triggered buffer */
 100static irqreturn_t vcnl4035_trigger_consumer_handler(int irq, void *p)
 101{
 102        struct iio_poll_func *pf = p;
 103        struct iio_dev *indio_dev = pf->indio_dev;
 104        struct vcnl4035_data *data = iio_priv(indio_dev);
 105        /* Ensure naturally aligned timestamp */
 106        u8 buffer[ALIGN(sizeof(u16), sizeof(s64)) + sizeof(s64)]  __aligned(8);
 107        int ret;
 108
 109        ret = regmap_read(data->regmap, VCNL4035_ALS_DATA, (int *)buffer);
 110        if (ret < 0) {
 111                dev_err(&data->client->dev,
 112                        "Trigger consumer can't read from sensor.\n");
 113                goto fail_read;
 114        }
 115        iio_push_to_buffers_with_timestamp(indio_dev, buffer,
 116                                        iio_get_time_ns(indio_dev));
 117
 118fail_read:
 119        iio_trigger_notify_done(indio_dev->trig);
 120
 121        return IRQ_HANDLED;
 122}
 123
 124static int vcnl4035_als_drdy_set_state(struct iio_trigger *trigger,
 125                                        bool enable_drdy)
 126{
 127        struct iio_dev *indio_dev = iio_trigger_get_drvdata(trigger);
 128        struct vcnl4035_data *data = iio_priv(indio_dev);
 129        int val = enable_drdy ? VCNL4035_MODE_ALS_INT_ENABLE :
 130                                        VCNL4035_MODE_ALS_INT_DISABLE;
 131
 132        return regmap_update_bits(data->regmap, VCNL4035_ALS_CONF,
 133                                 VCNL4035_MODE_ALS_INT_MASK,
 134                                 val);
 135}
 136
 137static const struct iio_trigger_ops vcnl4035_trigger_ops = {
 138        .validate_device = iio_trigger_validate_own_device,
 139        .set_trigger_state = vcnl4035_als_drdy_set_state,
 140};
 141
 142static int vcnl4035_set_pm_runtime_state(struct vcnl4035_data *data, bool on)
 143{
 144        int ret;
 145        struct device *dev = &data->client->dev;
 146
 147        if (on) {
 148                ret = pm_runtime_resume_and_get(dev);
 149        } else {
 150                pm_runtime_mark_last_busy(dev);
 151                ret = pm_runtime_put_autosuspend(dev);
 152        }
 153
 154        return ret;
 155}
 156
 157/*
 158 *      Device IT       INT Time (ms)   Scale (lux/step)
 159 *      000             50              0.064
 160 *      001             100             0.032
 161 *      010             200             0.016
 162 *      100             400             0.008
 163 *      101 - 111       800             0.004
 164 * Values are proportional, so ALS INT is selected for input due to
 165 * simplicity reason. Integration time value and scaling is
 166 * calculated based on device INT value
 167 *
 168 * Raw value needs to be scaled using ALS steps
 169 */
 170static int vcnl4035_read_raw(struct iio_dev *indio_dev,
 171                            struct iio_chan_spec const *chan, int *val,
 172                            int *val2, long mask)
 173{
 174        struct vcnl4035_data *data = iio_priv(indio_dev);
 175        int ret;
 176        int raw_data;
 177        unsigned int reg;
 178
 179        switch (mask) {
 180        case IIO_CHAN_INFO_RAW:
 181                ret = vcnl4035_set_pm_runtime_state(data, true);
 182                if  (ret < 0)
 183                        return ret;
 184
 185                ret = iio_device_claim_direct_mode(indio_dev);
 186                if (!ret) {
 187                        if (chan->channel)
 188                                reg = VCNL4035_ALS_DATA;
 189                        else
 190                                reg = VCNL4035_WHITE_DATA;
 191                        ret = regmap_read(data->regmap, reg, &raw_data);
 192                        iio_device_release_direct_mode(indio_dev);
 193                        if (!ret) {
 194                                *val = raw_data;
 195                                ret = IIO_VAL_INT;
 196                        }
 197                }
 198                vcnl4035_set_pm_runtime_state(data, false);
 199                return ret;
 200        case IIO_CHAN_INFO_INT_TIME:
 201                *val = 50;
 202                if (data->als_it_val)
 203                        *val = data->als_it_val * 100;
 204                return IIO_VAL_INT;
 205        case IIO_CHAN_INFO_SCALE:
 206                *val = 64;
 207                if (!data->als_it_val)
 208                        *val2 = 1000;
 209                else
 210                        *val2 = data->als_it_val * 2 * 1000;
 211                return IIO_VAL_FRACTIONAL;
 212        default:
 213                return -EINVAL;
 214        }
 215}
 216
 217static int vcnl4035_write_raw(struct iio_dev *indio_dev,
 218                                struct iio_chan_spec const *chan,
 219                                int val, int val2, long mask)
 220{
 221        int ret;
 222        struct vcnl4035_data *data = iio_priv(indio_dev);
 223
 224        switch (mask) {
 225        case IIO_CHAN_INFO_INT_TIME:
 226                if (val <= 0 || val > 800)
 227                        return -EINVAL;
 228
 229                ret = vcnl4035_set_pm_runtime_state(data, true);
 230                if  (ret < 0)
 231                        return ret;
 232
 233                ret = regmap_update_bits(data->regmap, VCNL4035_ALS_CONF,
 234                                         VCNL4035_ALS_IT_MASK,
 235                                         val / 100);
 236                if (!ret)
 237                        data->als_it_val = val / 100;
 238
 239                vcnl4035_set_pm_runtime_state(data, false);
 240                return ret;
 241        default:
 242                return -EINVAL;
 243        }
 244}
 245
 246/* No direct ABI for persistence and threshold, so eventing */
 247static int vcnl4035_read_thresh(struct iio_dev *indio_dev,
 248                const struct iio_chan_spec *chan, enum iio_event_type type,
 249                enum iio_event_direction dir, enum iio_event_info info,
 250                int *val, int *val2)
 251{
 252        struct vcnl4035_data *data = iio_priv(indio_dev);
 253
 254        switch (info) {
 255        case IIO_EV_INFO_VALUE:
 256                switch (dir) {
 257                case IIO_EV_DIR_RISING:
 258                        *val = data->als_thresh_high;
 259                        return IIO_VAL_INT;
 260                case IIO_EV_DIR_FALLING:
 261                        *val = data->als_thresh_low;
 262                        return IIO_VAL_INT;
 263                default:
 264                        return -EINVAL;
 265                }
 266                break;
 267        case IIO_EV_INFO_PERIOD:
 268                *val = data->als_persistence;
 269                return IIO_VAL_INT;
 270        default:
 271                return -EINVAL;
 272        }
 273
 274}
 275
 276static int vcnl4035_write_thresh(struct iio_dev *indio_dev,
 277                const struct iio_chan_spec *chan, enum iio_event_type type,
 278                enum iio_event_direction dir, enum iio_event_info info, int val,
 279                int val2)
 280{
 281        struct vcnl4035_data *data = iio_priv(indio_dev);
 282        int ret;
 283
 284        switch (info) {
 285        case IIO_EV_INFO_VALUE:
 286                /* 16 bit threshold range 0 - 65535 */
 287                if (val < 0 || val > 65535)
 288                        return -EINVAL;
 289                if (dir == IIO_EV_DIR_RISING) {
 290                        if (val < data->als_thresh_low)
 291                                return -EINVAL;
 292                        ret = regmap_write(data->regmap, VCNL4035_ALS_THDH,
 293                                           val);
 294                        if (ret)
 295                                return ret;
 296                        data->als_thresh_high = val;
 297                } else {
 298                        if (val > data->als_thresh_high)
 299                                return -EINVAL;
 300                        ret = regmap_write(data->regmap, VCNL4035_ALS_THDL,
 301                                           val);
 302                        if (ret)
 303                                return ret;
 304                        data->als_thresh_low = val;
 305                }
 306                return ret;
 307        case IIO_EV_INFO_PERIOD:
 308                /* allow only 1 2 4 8 as persistence value */
 309                if (val < 0 || val > 8 || hweight8(val) != 1)
 310                        return -EINVAL;
 311                ret = regmap_update_bits(data->regmap, VCNL4035_ALS_CONF,
 312                                         VCNL4035_ALS_PERS_MASK, val);
 313                if (!ret)
 314                        data->als_persistence = val;
 315                return ret;
 316        default:
 317                return -EINVAL;
 318        }
 319}
 320
 321static IIO_CONST_ATTR_INT_TIME_AVAIL("50 100 200 400 800");
 322
 323static struct attribute *vcnl4035_attributes[] = {
 324        &iio_const_attr_integration_time_available.dev_attr.attr,
 325        NULL,
 326};
 327
 328static const struct attribute_group vcnl4035_attribute_group = {
 329        .attrs = vcnl4035_attributes,
 330};
 331
 332static const struct iio_info vcnl4035_info = {
 333        .read_raw               = vcnl4035_read_raw,
 334        .write_raw              = vcnl4035_write_raw,
 335        .read_event_value       = vcnl4035_read_thresh,
 336        .write_event_value      = vcnl4035_write_thresh,
 337        .attrs                  = &vcnl4035_attribute_group,
 338};
 339
 340static const struct iio_event_spec vcnl4035_event_spec[] = {
 341        {
 342                .type = IIO_EV_TYPE_THRESH,
 343                .dir = IIO_EV_DIR_RISING,
 344                .mask_separate = BIT(IIO_EV_INFO_VALUE),
 345        }, {
 346                .type = IIO_EV_TYPE_THRESH,
 347                .dir = IIO_EV_DIR_FALLING,
 348                .mask_separate = BIT(IIO_EV_INFO_VALUE),
 349        }, {
 350                .type = IIO_EV_TYPE_THRESH,
 351                .dir = IIO_EV_DIR_EITHER,
 352                .mask_separate = BIT(IIO_EV_INFO_PERIOD),
 353        },
 354};
 355
 356enum vcnl4035_scan_index_order {
 357        VCNL4035_CHAN_INDEX_LIGHT,
 358        VCNL4035_CHAN_INDEX_WHITE_LED,
 359};
 360
 361static const struct iio_buffer_setup_ops iio_triggered_buffer_setup_ops = {
 362        .validate_scan_mask = &iio_validate_scan_mask_onehot,
 363};
 364
 365static const struct iio_chan_spec vcnl4035_channels[] = {
 366        {
 367                .type = IIO_LIGHT,
 368                .channel = 0,
 369                .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
 370                                BIT(IIO_CHAN_INFO_INT_TIME) |
 371                                BIT(IIO_CHAN_INFO_SCALE),
 372                .event_spec = vcnl4035_event_spec,
 373                .num_event_specs = ARRAY_SIZE(vcnl4035_event_spec),
 374                .scan_index = VCNL4035_CHAN_INDEX_LIGHT,
 375                .scan_type = {
 376                        .sign = 'u',
 377                        .realbits = 16,
 378                        .storagebits = 16,
 379                        .endianness = IIO_LE,
 380                },
 381        },
 382        {
 383                .type = IIO_INTENSITY,
 384                .channel = 1,
 385                .modified = 1,
 386                .channel2 = IIO_MOD_LIGHT_BOTH,
 387                .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
 388                .scan_index = VCNL4035_CHAN_INDEX_WHITE_LED,
 389                .scan_type = {
 390                        .sign = 'u',
 391                        .realbits = 16,
 392                        .storagebits = 16,
 393                        .endianness = IIO_LE,
 394                },
 395        },
 396};
 397
 398static int vcnl4035_set_als_power_state(struct vcnl4035_data *data, u8 status)
 399{
 400        return regmap_update_bits(data->regmap, VCNL4035_ALS_CONF,
 401                                        VCNL4035_MODE_ALS_MASK,
 402                                        status);
 403}
 404
 405static int vcnl4035_init(struct vcnl4035_data *data)
 406{
 407        int ret;
 408        int id;
 409
 410        ret = regmap_read(data->regmap, VCNL4035_DEV_ID, &id);
 411        if (ret < 0) {
 412                dev_err(&data->client->dev, "Failed to read DEV_ID register\n");
 413                return ret;
 414        }
 415
 416        if (id != VCNL4035_DEV_ID_VAL) {
 417                dev_err(&data->client->dev, "Wrong id, got %x, expected %x\n",
 418                        id, VCNL4035_DEV_ID_VAL);
 419                return -ENODEV;
 420        }
 421
 422        ret = vcnl4035_set_als_power_state(data, VCNL4035_MODE_ALS_ENABLE);
 423        if (ret < 0)
 424                return ret;
 425
 426        /* ALS white channel enable */
 427        ret = regmap_update_bits(data->regmap, VCNL4035_ALS_CONF,
 428                                 VCNL4035_MODE_ALS_WHITE_CHAN,
 429                                 1);
 430        if (ret) {
 431                dev_err(&data->client->dev, "set white channel enable %d\n",
 432                        ret);
 433                return ret;
 434        }
 435
 436        /* set default integration time - 100 ms for ALS */
 437        ret = regmap_update_bits(data->regmap, VCNL4035_ALS_CONF,
 438                                 VCNL4035_ALS_IT_MASK,
 439                                 VCNL4035_ALS_IT_DEFAULT);
 440        if (ret) {
 441                dev_err(&data->client->dev, "set default ALS IT returned %d\n",
 442                        ret);
 443                return ret;
 444        }
 445        data->als_it_val = VCNL4035_ALS_IT_DEFAULT;
 446
 447        /* set default persistence time - 1 for ALS */
 448        ret = regmap_update_bits(data->regmap, VCNL4035_ALS_CONF,
 449                                 VCNL4035_ALS_PERS_MASK,
 450                                 VCNL4035_ALS_PERS_DEFAULT);
 451        if (ret) {
 452                dev_err(&data->client->dev, "set default PERS returned %d\n",
 453                        ret);
 454                return ret;
 455        }
 456        data->als_persistence = VCNL4035_ALS_PERS_DEFAULT;
 457
 458        /* set default HIGH threshold for ALS */
 459        ret = regmap_write(data->regmap, VCNL4035_ALS_THDH,
 460                                VCNL4035_ALS_THDH_DEFAULT);
 461        if (ret) {
 462                dev_err(&data->client->dev, "set default THDH returned %d\n",
 463                        ret);
 464                return ret;
 465        }
 466        data->als_thresh_high = VCNL4035_ALS_THDH_DEFAULT;
 467
 468        /* set default LOW threshold for ALS */
 469        ret = regmap_write(data->regmap, VCNL4035_ALS_THDL,
 470                                VCNL4035_ALS_THDL_DEFAULT);
 471        if (ret) {
 472                dev_err(&data->client->dev, "set default THDL returned %d\n",
 473                        ret);
 474                return ret;
 475        }
 476        data->als_thresh_low = VCNL4035_ALS_THDL_DEFAULT;
 477
 478        return 0;
 479}
 480
 481static bool vcnl4035_is_volatile_reg(struct device *dev, unsigned int reg)
 482{
 483        switch (reg) {
 484        case VCNL4035_ALS_CONF:
 485        case VCNL4035_DEV_ID:
 486                return false;
 487        default:
 488                return true;
 489        }
 490}
 491
 492static const struct regmap_config vcnl4035_regmap_config = {
 493        .name           = VCNL4035_REGMAP_NAME,
 494        .reg_bits       = 8,
 495        .val_bits       = 16,
 496        .max_register   = VCNL4035_DEV_ID,
 497        .cache_type     = REGCACHE_RBTREE,
 498        .volatile_reg   = vcnl4035_is_volatile_reg,
 499        .val_format_endian = REGMAP_ENDIAN_LITTLE,
 500};
 501
 502static int vcnl4035_probe_trigger(struct iio_dev *indio_dev)
 503{
 504        int ret;
 505        struct vcnl4035_data *data = iio_priv(indio_dev);
 506
 507        data->drdy_trigger0 = devm_iio_trigger_alloc(
 508                        indio_dev->dev.parent,
 509                        "%s-dev%d", indio_dev->name, iio_device_id(indio_dev));
 510        if (!data->drdy_trigger0)
 511                return -ENOMEM;
 512
 513        data->drdy_trigger0->ops = &vcnl4035_trigger_ops;
 514        iio_trigger_set_drvdata(data->drdy_trigger0, indio_dev);
 515        ret = devm_iio_trigger_register(indio_dev->dev.parent,
 516                                        data->drdy_trigger0);
 517        if (ret) {
 518                dev_err(&data->client->dev, "iio trigger register failed\n");
 519                return ret;
 520        }
 521
 522        /* Trigger setup */
 523        ret = devm_iio_triggered_buffer_setup(indio_dev->dev.parent, indio_dev,
 524                                        NULL, vcnl4035_trigger_consumer_handler,
 525                                        &iio_triggered_buffer_setup_ops);
 526        if (ret < 0) {
 527                dev_err(&data->client->dev, "iio triggered buffer setup failed\n");
 528                return ret;
 529        }
 530
 531        /* IRQ to trigger mapping */
 532        ret = devm_request_threaded_irq(&data->client->dev, data->client->irq,
 533                        NULL, vcnl4035_drdy_irq_thread,
 534                        IRQF_TRIGGER_LOW | IRQF_ONESHOT,
 535                        VCNL4035_IRQ_NAME, indio_dev);
 536        if (ret < 0)
 537                dev_err(&data->client->dev, "request irq %d for trigger0 failed\n",
 538                                data->client->irq);
 539        return ret;
 540}
 541
 542static int vcnl4035_probe(struct i2c_client *client,
 543                                const struct i2c_device_id *id)
 544{
 545        struct vcnl4035_data *data;
 546        struct iio_dev *indio_dev;
 547        struct regmap *regmap;
 548        int ret;
 549
 550        indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
 551        if (!indio_dev)
 552                return -ENOMEM;
 553
 554        regmap = devm_regmap_init_i2c(client, &vcnl4035_regmap_config);
 555        if (IS_ERR(regmap)) {
 556                dev_err(&client->dev, "regmap_init failed!\n");
 557                return PTR_ERR(regmap);
 558        }
 559
 560        data = iio_priv(indio_dev);
 561        i2c_set_clientdata(client, indio_dev);
 562        data->client = client;
 563        data->regmap = regmap;
 564
 565        indio_dev->info = &vcnl4035_info;
 566        indio_dev->name = VCNL4035_DRV_NAME;
 567        indio_dev->channels = vcnl4035_channels;
 568        indio_dev->num_channels = ARRAY_SIZE(vcnl4035_channels);
 569        indio_dev->modes = INDIO_DIRECT_MODE;
 570
 571        ret = vcnl4035_init(data);
 572        if (ret < 0) {
 573                dev_err(&client->dev, "vcnl4035 chip init failed\n");
 574                return ret;
 575        }
 576
 577        if (client->irq > 0) {
 578                ret = vcnl4035_probe_trigger(indio_dev);
 579                if (ret < 0) {
 580                        dev_err(&client->dev, "vcnl4035 unable init trigger\n");
 581                        goto fail_poweroff;
 582                }
 583        }
 584
 585        ret = pm_runtime_set_active(&client->dev);
 586        if (ret < 0)
 587                goto fail_poweroff;
 588
 589        ret = iio_device_register(indio_dev);
 590        if (ret < 0)
 591                goto fail_poweroff;
 592
 593        pm_runtime_enable(&client->dev);
 594        pm_runtime_set_autosuspend_delay(&client->dev, VCNL4035_SLEEP_DELAY_MS);
 595        pm_runtime_use_autosuspend(&client->dev);
 596
 597        return 0;
 598
 599fail_poweroff:
 600        vcnl4035_set_als_power_state(data, VCNL4035_MODE_ALS_DISABLE);
 601        return ret;
 602}
 603
 604static int vcnl4035_remove(struct i2c_client *client)
 605{
 606        struct iio_dev *indio_dev = i2c_get_clientdata(client);
 607
 608        pm_runtime_dont_use_autosuspend(&client->dev);
 609        pm_runtime_disable(&client->dev);
 610        iio_device_unregister(indio_dev);
 611        pm_runtime_set_suspended(&client->dev);
 612
 613        return vcnl4035_set_als_power_state(iio_priv(indio_dev),
 614                                        VCNL4035_MODE_ALS_DISABLE);
 615}
 616
 617static int __maybe_unused vcnl4035_runtime_suspend(struct device *dev)
 618{
 619        struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
 620        struct vcnl4035_data *data = iio_priv(indio_dev);
 621        int ret;
 622
 623        ret = vcnl4035_set_als_power_state(data, VCNL4035_MODE_ALS_DISABLE);
 624        regcache_mark_dirty(data->regmap);
 625
 626        return ret;
 627}
 628
 629static int __maybe_unused vcnl4035_runtime_resume(struct device *dev)
 630{
 631        struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
 632        struct vcnl4035_data *data = iio_priv(indio_dev);
 633        int ret;
 634
 635        regcache_sync(data->regmap);
 636        ret = vcnl4035_set_als_power_state(data, VCNL4035_MODE_ALS_ENABLE);
 637        if (ret < 0)
 638                return ret;
 639
 640        /* wait for 1 ALS integration cycle */
 641        msleep(data->als_it_val * 100);
 642
 643        return 0;
 644}
 645
 646static const struct dev_pm_ops vcnl4035_pm_ops = {
 647        SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
 648                                pm_runtime_force_resume)
 649        SET_RUNTIME_PM_OPS(vcnl4035_runtime_suspend,
 650                           vcnl4035_runtime_resume, NULL)
 651};
 652
 653static const struct i2c_device_id vcnl4035_id[] = {
 654        { "vcnl4035", 0},
 655        { }
 656};
 657MODULE_DEVICE_TABLE(i2c, vcnl4035_id);
 658
 659static const struct of_device_id vcnl4035_of_match[] = {
 660        { .compatible = "vishay,vcnl4035", },
 661        { }
 662};
 663MODULE_DEVICE_TABLE(of, vcnl4035_of_match);
 664
 665static struct i2c_driver vcnl4035_driver = {
 666        .driver = {
 667                .name   = VCNL4035_DRV_NAME,
 668                .pm     = &vcnl4035_pm_ops,
 669                .of_match_table = vcnl4035_of_match,
 670        },
 671        .probe  = vcnl4035_probe,
 672        .remove = vcnl4035_remove,
 673        .id_table = vcnl4035_id,
 674};
 675
 676module_i2c_driver(vcnl4035_driver);
 677
 678MODULE_AUTHOR("Parthiban Nallathambi <pn@denx.de>");
 679MODULE_DESCRIPTION("VCNL4035 Ambient Light Sensor driver");
 680MODULE_LICENSE("GPL v2");
 681