root/drivers/iio/light/vcnl4035.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. vcnl4035_is_triggered
  2. vcnl4035_drdy_irq_thread
  3. vcnl4035_trigger_consumer_handler
  4. vcnl4035_als_drdy_set_state
  5. vcnl4035_set_pm_runtime_state
  6. vcnl4035_read_raw
  7. vcnl4035_write_raw
  8. vcnl4035_read_thresh
  9. vcnl4035_write_thresh
  10. vcnl4035_set_als_power_state
  11. vcnl4035_init
  12. vcnl4035_is_volatile_reg
  13. vcnl4035_probe_trigger
  14. vcnl4035_probe
  15. vcnl4035_remove
  16. vcnl4035_runtime_suspend
  17. vcnl4035_runtime_resume

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

/* [<][>][^][v][top][bottom][index][help] */