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/bitfield.h> 12 #include <linux/i2c.h> 13 #include <linux/module.h> 14 #include <linux/pm_runtime.h> 15 #include <linux/regmap.h> 16 17 #include <linux/iio/buffer.h> 18 #include <linux/iio/events.h> 19 #include <linux/iio/iio.h> 20 #include <linux/iio/sysfs.h> 21 #include <linux/iio/trigger.h> 22 #include <linux/iio/trigger_consumer.h> 23 #include <linux/iio/triggered_buffer.h> 24 25 #define VCNL4035_DRV_NAME "vcnl4035" 26 27 /* Device registers */ 28 #define VCNL4035_ALS_CONF 0x00 29 #define VCNL4035_ALS_THDH 0x01 30 #define VCNL4035_ALS_THDL 0x02 31 #define VCNL4035_ALS_DATA 0x0B 32 #define VCNL4035_WHITE_DATA 0x0C 33 #define VCNL4035_INT_FLAG 0x0D 34 #define VCNL4035_DEV_ID 0x0E 35 36 /* Register masks */ 37 #define VCNL4035_MODE_ALS_MASK BIT(0) 38 #define VCNL4035_MODE_ALS_WHITE_CHAN BIT(8) 39 #define VCNL4035_MODE_ALS_INT_MASK BIT(1) 40 #define VCNL4035_ALS_IT_MASK GENMASK(7, 5) 41 #define VCNL4035_ALS_PERS_MASK GENMASK(3, 2) 42 #define VCNL4035_INT_ALS_IF_H_MASK BIT(12) 43 #define VCNL4035_INT_ALS_IF_L_MASK BIT(13) 44 #define VCNL4035_DEV_ID_MASK GENMASK(7, 0) 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_nested(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 /* Ensure naturally aligned timestamp */ 106 struct { 107 u16 als_data; 108 aligned_s64 timestamp; 109 } buffer = { }; 110 unsigned int val; 111 int ret; 112 113 ret = regmap_read(data->regmap, VCNL4035_ALS_DATA, &val); 114 if (ret < 0) { 115 dev_err(&data->client->dev, 116 "Trigger consumer can't read from sensor.\n"); 117 goto fail_read; 118 } 119 120 buffer.als_data = val; 121 iio_push_to_buffers_with_timestamp(indio_dev, &buffer, 122 iio_get_time_ns(indio_dev)); 123 124 fail_read: 125 iio_trigger_notify_done(indio_dev->trig); 126 127 return IRQ_HANDLED; 128 } 129 130 static int vcnl4035_als_drdy_set_state(struct iio_trigger *trigger, 131 bool enable_drdy) 132 { 133 struct iio_dev *indio_dev = iio_trigger_get_drvdata(trigger); 134 struct vcnl4035_data *data = iio_priv(indio_dev); 135 int val = enable_drdy ? VCNL4035_MODE_ALS_INT_ENABLE : 136 VCNL4035_MODE_ALS_INT_DISABLE; 137 138 return regmap_update_bits(data->regmap, VCNL4035_ALS_CONF, 139 VCNL4035_MODE_ALS_INT_MASK, 140 val); 141 } 142 143 static const struct iio_trigger_ops vcnl4035_trigger_ops = { 144 .validate_device = iio_trigger_validate_own_device, 145 .set_trigger_state = vcnl4035_als_drdy_set_state, 146 }; 147 148 static int vcnl4035_read_info_raw(struct iio_dev *indio_dev, 149 struct iio_chan_spec const *chan, int *val) 150 { 151 struct vcnl4035_data *data = iio_priv(indio_dev); 152 int ret; 153 int raw_data; 154 unsigned int reg; 155 156 if (!iio_device_claim_direct(indio_dev)) 157 return -EBUSY; 158 159 if (chan->channel) 160 reg = VCNL4035_ALS_DATA; 161 else 162 reg = VCNL4035_WHITE_DATA; 163 ret = regmap_read(data->regmap, reg, &raw_data); 164 iio_device_release_direct(indio_dev); 165 if (ret) 166 return ret; 167 168 *val = raw_data; 169 170 return IIO_VAL_INT; 171 } 172 173 /* 174 * Device IT INT Time (ms) Scale (lux/step) 175 * 000 50 0.064 176 * 001 100 0.032 177 * 010 200 0.016 178 * 100 400 0.008 179 * 101 - 111 800 0.004 180 * Values are proportional, so ALS INT is selected for input due to 181 * simplicity reason. Integration time value and scaling is 182 * calculated based on device INT value 183 * 184 * Raw value needs to be scaled using ALS steps 185 */ 186 static int vcnl4035_read_raw(struct iio_dev *indio_dev, 187 struct iio_chan_spec const *chan, int *val, 188 int *val2, long mask) 189 { 190 struct vcnl4035_data *data = iio_priv(indio_dev); 191 int ret; 192 193 switch (mask) { 194 case IIO_CHAN_INFO_RAW: 195 ret = pm_runtime_resume_and_get(&data->client->dev); 196 if (ret < 0) 197 return ret; 198 ret = vcnl4035_read_info_raw(indio_dev, chan, val); 199 pm_runtime_put_autosuspend(&data->client->dev); 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 = pm_runtime_resume_and_get(&data->client->dev); 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 pm_runtime_put_autosuspend(&data->client->dev); 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_CPU, 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_CPU, 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 id = FIELD_GET(VCNL4035_DEV_ID_MASK, id); 418 if (id != VCNL4035_DEV_ID_VAL) { 419 dev_err(&data->client->dev, "Wrong id, got %x, expected %x\n", 420 id, VCNL4035_DEV_ID_VAL); 421 return -ENODEV; 422 } 423 424 ret = vcnl4035_set_als_power_state(data, VCNL4035_MODE_ALS_ENABLE); 425 if (ret < 0) 426 return ret; 427 428 /* ALS white channel enable */ 429 ret = regmap_update_bits(data->regmap, VCNL4035_ALS_CONF, 430 VCNL4035_MODE_ALS_WHITE_CHAN, 431 1); 432 if (ret) { 433 dev_err(&data->client->dev, "set white channel enable %d\n", 434 ret); 435 return ret; 436 } 437 438 /* set default integration time - 100 ms for ALS */ 439 ret = regmap_update_bits(data->regmap, VCNL4035_ALS_CONF, 440 VCNL4035_ALS_IT_MASK, 441 VCNL4035_ALS_IT_DEFAULT); 442 if (ret) { 443 dev_err(&data->client->dev, "set default ALS IT returned %d\n", 444 ret); 445 return ret; 446 } 447 data->als_it_val = VCNL4035_ALS_IT_DEFAULT; 448 449 /* set default persistence time - 1 for ALS */ 450 ret = regmap_update_bits(data->regmap, VCNL4035_ALS_CONF, 451 VCNL4035_ALS_PERS_MASK, 452 VCNL4035_ALS_PERS_DEFAULT); 453 if (ret) { 454 dev_err(&data->client->dev, "set default PERS returned %d\n", 455 ret); 456 return ret; 457 } 458 data->als_persistence = VCNL4035_ALS_PERS_DEFAULT; 459 460 /* set default HIGH threshold for ALS */ 461 ret = regmap_write(data->regmap, VCNL4035_ALS_THDH, 462 VCNL4035_ALS_THDH_DEFAULT); 463 if (ret) { 464 dev_err(&data->client->dev, "set default THDH returned %d\n", 465 ret); 466 return ret; 467 } 468 data->als_thresh_high = VCNL4035_ALS_THDH_DEFAULT; 469 470 /* set default LOW threshold for ALS */ 471 ret = regmap_write(data->regmap, VCNL4035_ALS_THDL, 472 VCNL4035_ALS_THDL_DEFAULT); 473 if (ret) { 474 dev_err(&data->client->dev, "set default THDL returned %d\n", 475 ret); 476 return ret; 477 } 478 data->als_thresh_low = VCNL4035_ALS_THDL_DEFAULT; 479 480 return 0; 481 } 482 483 static bool vcnl4035_is_volatile_reg(struct device *dev, unsigned int reg) 484 { 485 switch (reg) { 486 case VCNL4035_ALS_CONF: 487 case VCNL4035_DEV_ID: 488 return false; 489 default: 490 return true; 491 } 492 } 493 494 static const struct regmap_config vcnl4035_regmap_config = { 495 .name = "vcnl4035_regmap", 496 .reg_bits = 8, 497 .val_bits = 16, 498 .max_register = VCNL4035_DEV_ID, 499 .cache_type = REGCACHE_RBTREE, 500 .volatile_reg = vcnl4035_is_volatile_reg, 501 .val_format_endian = REGMAP_ENDIAN_LITTLE, 502 }; 503 504 static int vcnl4035_probe_trigger(struct iio_dev *indio_dev) 505 { 506 int ret; 507 struct vcnl4035_data *data = iio_priv(indio_dev); 508 509 data->drdy_trigger0 = devm_iio_trigger_alloc( 510 indio_dev->dev.parent, 511 "%s-dev%d", indio_dev->name, iio_device_id(indio_dev)); 512 if (!data->drdy_trigger0) 513 return -ENOMEM; 514 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_event", 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 { 546 struct vcnl4035_data *data; 547 struct iio_dev *indio_dev; 548 struct regmap *regmap; 549 int ret; 550 551 indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); 552 if (!indio_dev) 553 return -ENOMEM; 554 555 regmap = devm_regmap_init_i2c(client, &vcnl4035_regmap_config); 556 if (IS_ERR(regmap)) { 557 dev_err(&client->dev, "regmap_init failed!\n"); 558 return PTR_ERR(regmap); 559 } 560 561 data = iio_priv(indio_dev); 562 i2c_set_clientdata(client, indio_dev); 563 data->client = client; 564 data->regmap = regmap; 565 566 indio_dev->info = &vcnl4035_info; 567 indio_dev->name = VCNL4035_DRV_NAME; 568 indio_dev->channels = vcnl4035_channels; 569 indio_dev->num_channels = ARRAY_SIZE(vcnl4035_channels); 570 indio_dev->modes = INDIO_DIRECT_MODE; 571 572 ret = vcnl4035_init(data); 573 if (ret < 0) { 574 dev_err(&client->dev, "vcnl4035 chip init failed\n"); 575 return ret; 576 } 577 578 if (client->irq > 0) { 579 ret = vcnl4035_probe_trigger(indio_dev); 580 if (ret < 0) { 581 dev_err(&client->dev, "vcnl4035 unable init trigger\n"); 582 goto fail_poweroff; 583 } 584 } 585 586 ret = pm_runtime_set_active(&client->dev); 587 if (ret < 0) 588 goto fail_poweroff; 589 590 ret = iio_device_register(indio_dev); 591 if (ret < 0) 592 goto fail_poweroff; 593 594 pm_runtime_enable(&client->dev); 595 pm_runtime_set_autosuspend_delay(&client->dev, VCNL4035_SLEEP_DELAY_MS); 596 pm_runtime_use_autosuspend(&client->dev); 597 598 return 0; 599 600 fail_poweroff: 601 vcnl4035_set_als_power_state(data, VCNL4035_MODE_ALS_DISABLE); 602 return ret; 603 } 604 605 static void vcnl4035_remove(struct i2c_client *client) 606 { 607 struct iio_dev *indio_dev = i2c_get_clientdata(client); 608 int ret; 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 ret = vcnl4035_set_als_power_state(iio_priv(indio_dev), 616 VCNL4035_MODE_ALS_DISABLE); 617 if (ret) 618 dev_warn(&client->dev, "Failed to put device into standby (%pe)\n", 619 ERR_PTR(ret)); 620 } 621 622 static int vcnl4035_runtime_suspend(struct device *dev) 623 { 624 struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev)); 625 struct vcnl4035_data *data = iio_priv(indio_dev); 626 int ret; 627 628 ret = vcnl4035_set_als_power_state(data, VCNL4035_MODE_ALS_DISABLE); 629 regcache_mark_dirty(data->regmap); 630 631 return ret; 632 } 633 634 static int vcnl4035_runtime_resume(struct device *dev) 635 { 636 struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev)); 637 struct vcnl4035_data *data = iio_priv(indio_dev); 638 int ret; 639 640 ret = regcache_sync(data->regmap); 641 if (ret < 0) 642 return ret; 643 644 ret = vcnl4035_set_als_power_state(data, VCNL4035_MODE_ALS_ENABLE); 645 if (ret < 0) 646 return ret; 647 648 /* wait for 1 ALS integration cycle */ 649 msleep(data->als_it_val * 100); 650 651 return 0; 652 } 653 654 static DEFINE_RUNTIME_DEV_PM_OPS(vcnl4035_pm_ops, vcnl4035_runtime_suspend, 655 vcnl4035_runtime_resume, NULL); 656 657 static const struct i2c_device_id vcnl4035_id[] = { 658 { .name = "vcnl4035" }, 659 { } 660 }; 661 MODULE_DEVICE_TABLE(i2c, vcnl4035_id); 662 663 static const struct of_device_id vcnl4035_of_match[] = { 664 { .compatible = "vishay,vcnl4035", }, 665 { } 666 }; 667 MODULE_DEVICE_TABLE(of, vcnl4035_of_match); 668 669 static struct i2c_driver vcnl4035_driver = { 670 .driver = { 671 .name = VCNL4035_DRV_NAME, 672 .pm = pm_ptr(&vcnl4035_pm_ops), 673 .of_match_table = vcnl4035_of_match, 674 }, 675 .probe = vcnl4035_probe, 676 .remove = vcnl4035_remove, 677 .id_table = vcnl4035_id, 678 }; 679 680 module_i2c_driver(vcnl4035_driver); 681 682 MODULE_AUTHOR("Parthiban Nallathambi <pn@denx.de>"); 683 MODULE_DESCRIPTION("VCNL4035 Ambient Light Sensor driver"); 684 MODULE_LICENSE("GPL v2"); 685