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, ®); 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->info = &vcnl4035_info; 568 indio_dev->name = VCNL4035_DRV_NAME; 569 indio_dev->channels = vcnl4035_channels; 570 indio_dev->num_channels = ARRAY_SIZE(vcnl4035_channels); 571 indio_dev->modes = INDIO_DIRECT_MODE; 572 573 ret = vcnl4035_init(data); 574 if (ret < 0) { 575 dev_err(&client->dev, "vcnl4035 chip init failed\n"); 576 return ret; 577 } 578 579 if (client->irq > 0) { 580 ret = vcnl4035_probe_trigger(indio_dev); 581 if (ret < 0) { 582 dev_err(&client->dev, "vcnl4035 unable init trigger\n"); 583 goto fail_poweroff; 584 } 585 } 586 587 ret = pm_runtime_set_active(&client->dev); 588 if (ret < 0) 589 goto fail_poweroff; 590 591 ret = iio_device_register(indio_dev); 592 if (ret < 0) 593 goto fail_poweroff; 594 595 pm_runtime_enable(&client->dev); 596 pm_runtime_set_autosuspend_delay(&client->dev, VCNL4035_SLEEP_DELAY_MS); 597 pm_runtime_use_autosuspend(&client->dev); 598 599 return 0; 600 601 fail_poweroff: 602 vcnl4035_set_als_power_state(data, VCNL4035_MODE_ALS_DISABLE); 603 return ret; 604 } 605 606 static int vcnl4035_remove(struct i2c_client *client) 607 { 608 struct iio_dev *indio_dev = i2c_get_clientdata(client); 609 610 pm_runtime_dont_use_autosuspend(&client->dev); 611 pm_runtime_disable(&client->dev); 612 iio_device_unregister(indio_dev); 613 pm_runtime_set_suspended(&client->dev); 614 615 return vcnl4035_set_als_power_state(iio_priv(indio_dev), 616 VCNL4035_MODE_ALS_DISABLE); 617 } 618 619 static int __maybe_unused vcnl4035_runtime_suspend(struct device *dev) 620 { 621 struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev)); 622 struct vcnl4035_data *data = iio_priv(indio_dev); 623 int ret; 624 625 ret = vcnl4035_set_als_power_state(data, VCNL4035_MODE_ALS_DISABLE); 626 regcache_mark_dirty(data->regmap); 627 628 return ret; 629 } 630 631 static int __maybe_unused vcnl4035_runtime_resume(struct device *dev) 632 { 633 struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev)); 634 struct vcnl4035_data *data = iio_priv(indio_dev); 635 int ret; 636 637 regcache_sync(data->regmap); 638 ret = vcnl4035_set_als_power_state(data, VCNL4035_MODE_ALS_ENABLE); 639 if (ret < 0) 640 return ret; 641 642 /* wait for 1 ALS integration cycle */ 643 msleep(data->als_it_val * 100); 644 645 return 0; 646 } 647 648 static const struct dev_pm_ops vcnl4035_pm_ops = { 649 SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, 650 pm_runtime_force_resume) 651 SET_RUNTIME_PM_OPS(vcnl4035_runtime_suspend, 652 vcnl4035_runtime_resume, NULL) 653 }; 654 655 static const struct of_device_id vcnl4035_of_match[] = { 656 { .compatible = "vishay,vcnl4035", }, 657 { } 658 }; 659 MODULE_DEVICE_TABLE(of, vcnl4035_of_match); 660 661 static struct i2c_driver vcnl4035_driver = { 662 .driver = { 663 .name = VCNL4035_DRV_NAME, 664 .pm = &vcnl4035_pm_ops, 665 .of_match_table = vcnl4035_of_match, 666 }, 667 .probe = vcnl4035_probe, 668 .remove = vcnl4035_remove, 669 }; 670 671 module_i2c_driver(vcnl4035_driver); 672 673 MODULE_AUTHOR("Parthiban Nallathambi <pn@denx.de>"); 674 MODULE_DESCRIPTION("VCNL4035 Ambient Light Sensor driver"); 675 MODULE_LICENSE("GPL v2"); 676