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 * 9 * IIO driver for: 10 * VCNL4000/10/20 (7-bit I2C slave address 0x13) 11 * VCNL4040 (7-bit I2C slave address 0x60) 12 * VCNL4200 (7-bit I2C slave address 0x51) 13 * 14 * TODO: 15 * allow to adjust IR current 16 * proximity threshold and event handling 17 * periodic ALS/proximity measurement (VCNL4010/20) 18 * interrupts (VCNL4010/20/40, VCNL4200) 19 */ 20 21 #include <linux/module.h> 22 #include <linux/i2c.h> 23 #include <linux/err.h> 24 #include <linux/delay.h> 25 #include <linux/pm_runtime.h> 26 27 #include <linux/iio/iio.h> 28 #include <linux/iio/sysfs.h> 29 30 #define VCNL4000_DRV_NAME "vcnl4000" 31 #define VCNL4000_PROD_ID 0x01 32 #define VCNL4010_PROD_ID 0x02 /* for VCNL4020, VCNL4010 */ 33 #define VCNL4040_PROD_ID 0x86 34 #define VCNL4200_PROD_ID 0x58 35 36 #define VCNL4000_COMMAND 0x80 /* Command register */ 37 #define VCNL4000_PROD_REV 0x81 /* Product ID and Revision ID */ 38 #define VCNL4000_LED_CURRENT 0x83 /* IR LED current for proximity mode */ 39 #define VCNL4000_AL_PARAM 0x84 /* Ambient light parameter register */ 40 #define VCNL4000_AL_RESULT_HI 0x85 /* Ambient light result register, MSB */ 41 #define VCNL4000_AL_RESULT_LO 0x86 /* Ambient light result register, LSB */ 42 #define VCNL4000_PS_RESULT_HI 0x87 /* Proximity result register, MSB */ 43 #define VCNL4000_PS_RESULT_LO 0x88 /* Proximity result register, LSB */ 44 #define VCNL4000_PS_MEAS_FREQ 0x89 /* Proximity test signal frequency */ 45 #define VCNL4000_PS_MOD_ADJ 0x8a /* Proximity modulator timing adjustment */ 46 47 #define VCNL4200_AL_CONF 0x00 /* Ambient light configuration */ 48 #define VCNL4200_PS_CONF1 0x03 /* Proximity configuration */ 49 #define VCNL4200_PS_DATA 0x08 /* Proximity data */ 50 #define VCNL4200_AL_DATA 0x09 /* Ambient light data */ 51 #define VCNL4200_DEV_ID 0x0e /* Device ID, slave address and version */ 52 53 #define VCNL4040_DEV_ID 0x0c /* Device ID and version */ 54 55 /* Bit masks for COMMAND register */ 56 #define VCNL4000_AL_RDY BIT(6) /* ALS data ready? */ 57 #define VCNL4000_PS_RDY BIT(5) /* proximity data ready? */ 58 #define VCNL4000_AL_OD BIT(4) /* start on-demand ALS measurement */ 59 #define VCNL4000_PS_OD BIT(3) /* start on-demand proximity measurement */ 60 61 #define VCNL4000_SLEEP_DELAY_MS 2000 /* before we enter pm_runtime_suspend */ 62 63 enum vcnl4000_device_ids { 64 VCNL4000, 65 VCNL4010, 66 VCNL4040, 67 VCNL4200, 68 }; 69 70 struct vcnl4200_channel { 71 u8 reg; 72 ktime_t last_measurement; 73 ktime_t sampling_rate; 74 struct mutex lock; 75 }; 76 77 struct vcnl4000_data { 78 struct i2c_client *client; 79 enum vcnl4000_device_ids id; 80 int rev; 81 int al_scale; 82 const struct vcnl4000_chip_spec *chip_spec; 83 struct mutex vcnl4000_lock; 84 struct vcnl4200_channel vcnl4200_al; 85 struct vcnl4200_channel vcnl4200_ps; 86 }; 87 88 struct vcnl4000_chip_spec { 89 const char *prod; 90 int (*init)(struct vcnl4000_data *data); 91 int (*measure_light)(struct vcnl4000_data *data, int *val); 92 int (*measure_proximity)(struct vcnl4000_data *data, int *val); 93 int (*set_power_state)(struct vcnl4000_data *data, bool on); 94 }; 95 96 static const struct i2c_device_id vcnl4000_id[] = { 97 { "vcnl4000", VCNL4000 }, 98 { "vcnl4010", VCNL4010 }, 99 { "vcnl4020", VCNL4010 }, 100 { "vcnl4040", VCNL4040 }, 101 { "vcnl4200", VCNL4200 }, 102 { } 103 }; 104 MODULE_DEVICE_TABLE(i2c, vcnl4000_id); 105 106 static int vcnl4000_set_power_state(struct vcnl4000_data *data, bool on) 107 { 108 /* no suspend op */ 109 return 0; 110 } 111 112 static int vcnl4000_init(struct vcnl4000_data *data) 113 { 114 int ret, prod_id; 115 116 ret = i2c_smbus_read_byte_data(data->client, VCNL4000_PROD_REV); 117 if (ret < 0) 118 return ret; 119 120 prod_id = ret >> 4; 121 switch (prod_id) { 122 case VCNL4000_PROD_ID: 123 if (data->id != VCNL4000) 124 dev_warn(&data->client->dev, 125 "wrong device id, use vcnl4000"); 126 break; 127 case VCNL4010_PROD_ID: 128 if (data->id != VCNL4010) 129 dev_warn(&data->client->dev, 130 "wrong device id, use vcnl4010/4020"); 131 break; 132 default: 133 return -ENODEV; 134 } 135 136 data->rev = ret & 0xf; 137 data->al_scale = 250000; 138 mutex_init(&data->vcnl4000_lock); 139 140 return data->chip_spec->set_power_state(data, true); 141 }; 142 143 static int vcnl4200_set_power_state(struct vcnl4000_data *data, bool on) 144 { 145 u16 val = on ? 0 /* power on */ : 1 /* shut down */; 146 int ret; 147 148 ret = i2c_smbus_write_word_data(data->client, VCNL4200_AL_CONF, val); 149 if (ret < 0) 150 return ret; 151 152 ret = i2c_smbus_write_word_data(data->client, VCNL4200_PS_CONF1, val); 153 if (ret < 0) 154 return ret; 155 156 if (on) { 157 /* Wait at least one integration cycle before fetching data */ 158 data->vcnl4200_al.last_measurement = ktime_get(); 159 data->vcnl4200_ps.last_measurement = ktime_get(); 160 } 161 162 return 0; 163 } 164 165 static int vcnl4200_init(struct vcnl4000_data *data) 166 { 167 int ret, id; 168 169 ret = i2c_smbus_read_word_data(data->client, VCNL4200_DEV_ID); 170 if (ret < 0) 171 return ret; 172 173 id = ret & 0xff; 174 175 if (id != VCNL4200_PROD_ID) { 176 ret = i2c_smbus_read_word_data(data->client, VCNL4040_DEV_ID); 177 if (ret < 0) 178 return ret; 179 180 id = ret & 0xff; 181 182 if (id != VCNL4040_PROD_ID) 183 return -ENODEV; 184 } 185 186 dev_dbg(&data->client->dev, "device id 0x%x", id); 187 188 data->rev = (ret >> 8) & 0xf; 189 190 data->vcnl4200_al.reg = VCNL4200_AL_DATA; 191 data->vcnl4200_ps.reg = VCNL4200_PS_DATA; 192 switch (id) { 193 case VCNL4200_PROD_ID: 194 /* Default wait time is 50ms, add 20% tolerance. */ 195 data->vcnl4200_al.sampling_rate = ktime_set(0, 60000 * 1000); 196 /* Default wait time is 4.8ms, add 20% tolerance. */ 197 data->vcnl4200_ps.sampling_rate = ktime_set(0, 5760 * 1000); 198 data->al_scale = 24000; 199 break; 200 case VCNL4040_PROD_ID: 201 /* Default wait time is 80ms, add 20% tolerance. */ 202 data->vcnl4200_al.sampling_rate = ktime_set(0, 96000 * 1000); 203 /* Default wait time is 5ms, add 20% tolerance. */ 204 data->vcnl4200_ps.sampling_rate = ktime_set(0, 6000 * 1000); 205 data->al_scale = 120000; 206 break; 207 } 208 mutex_init(&data->vcnl4200_al.lock); 209 mutex_init(&data->vcnl4200_ps.lock); 210 211 ret = data->chip_spec->set_power_state(data, true); 212 if (ret < 0) 213 return ret; 214 215 return 0; 216 }; 217 218 static int vcnl4000_measure(struct vcnl4000_data *data, u8 req_mask, 219 u8 rdy_mask, u8 data_reg, int *val) 220 { 221 int tries = 20; 222 __be16 buf; 223 int ret; 224 225 mutex_lock(&data->vcnl4000_lock); 226 227 ret = i2c_smbus_write_byte_data(data->client, VCNL4000_COMMAND, 228 req_mask); 229 if (ret < 0) 230 goto fail; 231 232 /* wait for data to become ready */ 233 while (tries--) { 234 ret = i2c_smbus_read_byte_data(data->client, VCNL4000_COMMAND); 235 if (ret < 0) 236 goto fail; 237 if (ret & rdy_mask) 238 break; 239 msleep(20); /* measurement takes up to 100 ms */ 240 } 241 242 if (tries < 0) { 243 dev_err(&data->client->dev, 244 "vcnl4000_measure() failed, data not ready\n"); 245 ret = -EIO; 246 goto fail; 247 } 248 249 ret = i2c_smbus_read_i2c_block_data(data->client, 250 data_reg, sizeof(buf), (u8 *) &buf); 251 if (ret < 0) 252 goto fail; 253 254 mutex_unlock(&data->vcnl4000_lock); 255 *val = be16_to_cpu(buf); 256 257 return 0; 258 259 fail: 260 mutex_unlock(&data->vcnl4000_lock); 261 return ret; 262 } 263 264 static int vcnl4200_measure(struct vcnl4000_data *data, 265 struct vcnl4200_channel *chan, int *val) 266 { 267 int ret; 268 s64 delta; 269 ktime_t next_measurement; 270 271 mutex_lock(&chan->lock); 272 273 next_measurement = ktime_add(chan->last_measurement, 274 chan->sampling_rate); 275 delta = ktime_us_delta(next_measurement, ktime_get()); 276 if (delta > 0) 277 usleep_range(delta, delta + 500); 278 chan->last_measurement = ktime_get(); 279 280 mutex_unlock(&chan->lock); 281 282 ret = i2c_smbus_read_word_data(data->client, chan->reg); 283 if (ret < 0) 284 return ret; 285 286 *val = ret; 287 288 return 0; 289 } 290 291 static int vcnl4000_measure_light(struct vcnl4000_data *data, int *val) 292 { 293 return vcnl4000_measure(data, 294 VCNL4000_AL_OD, VCNL4000_AL_RDY, 295 VCNL4000_AL_RESULT_HI, val); 296 } 297 298 static int vcnl4200_measure_light(struct vcnl4000_data *data, int *val) 299 { 300 return vcnl4200_measure(data, &data->vcnl4200_al, val); 301 } 302 303 static int vcnl4000_measure_proximity(struct vcnl4000_data *data, int *val) 304 { 305 return vcnl4000_measure(data, 306 VCNL4000_PS_OD, VCNL4000_PS_RDY, 307 VCNL4000_PS_RESULT_HI, val); 308 } 309 310 static int vcnl4200_measure_proximity(struct vcnl4000_data *data, int *val) 311 { 312 return vcnl4200_measure(data, &data->vcnl4200_ps, val); 313 } 314 315 static const struct vcnl4000_chip_spec vcnl4000_chip_spec_cfg[] = { 316 [VCNL4000] = { 317 .prod = "VCNL4000", 318 .init = vcnl4000_init, 319 .measure_light = vcnl4000_measure_light, 320 .measure_proximity = vcnl4000_measure_proximity, 321 .set_power_state = vcnl4000_set_power_state, 322 }, 323 [VCNL4010] = { 324 .prod = "VCNL4010/4020", 325 .init = vcnl4000_init, 326 .measure_light = vcnl4000_measure_light, 327 .measure_proximity = vcnl4000_measure_proximity, 328 .set_power_state = vcnl4000_set_power_state, 329 }, 330 [VCNL4040] = { 331 .prod = "VCNL4040", 332 .init = vcnl4200_init, 333 .measure_light = vcnl4200_measure_light, 334 .measure_proximity = vcnl4200_measure_proximity, 335 .set_power_state = vcnl4200_set_power_state, 336 }, 337 [VCNL4200] = { 338 .prod = "VCNL4200", 339 .init = vcnl4200_init, 340 .measure_light = vcnl4200_measure_light, 341 .measure_proximity = vcnl4200_measure_proximity, 342 .set_power_state = vcnl4200_set_power_state, 343 }, 344 }; 345 346 static const struct iio_chan_spec vcnl4000_channels[] = { 347 { 348 .type = IIO_LIGHT, 349 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | 350 BIT(IIO_CHAN_INFO_SCALE), 351 }, { 352 .type = IIO_PROXIMITY, 353 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), 354 } 355 }; 356 357 static int vcnl4000_set_pm_runtime_state(struct vcnl4000_data *data, bool on) 358 { 359 struct device *dev = &data->client->dev; 360 int ret; 361 362 if (on) { 363 ret = pm_runtime_get_sync(dev); 364 if (ret < 0) 365 pm_runtime_put_noidle(dev); 366 } else { 367 pm_runtime_mark_last_busy(dev); 368 ret = pm_runtime_put_autosuspend(dev); 369 } 370 371 return ret; 372 } 373 374 static int vcnl4000_read_raw(struct iio_dev *indio_dev, 375 struct iio_chan_spec const *chan, 376 int *val, int *val2, long mask) 377 { 378 int ret; 379 struct vcnl4000_data *data = iio_priv(indio_dev); 380 381 switch (mask) { 382 case IIO_CHAN_INFO_RAW: 383 ret = vcnl4000_set_pm_runtime_state(data, true); 384 if (ret < 0) 385 return ret; 386 387 switch (chan->type) { 388 case IIO_LIGHT: 389 ret = data->chip_spec->measure_light(data, val); 390 if (!ret) 391 ret = IIO_VAL_INT; 392 break; 393 case IIO_PROXIMITY: 394 ret = data->chip_spec->measure_proximity(data, val); 395 if (!ret) 396 ret = IIO_VAL_INT; 397 break; 398 default: 399 ret = -EINVAL; 400 } 401 vcnl4000_set_pm_runtime_state(data, false); 402 return ret; 403 case IIO_CHAN_INFO_SCALE: 404 if (chan->type != IIO_LIGHT) 405 return -EINVAL; 406 407 *val = 0; 408 *val2 = data->al_scale; 409 return IIO_VAL_INT_PLUS_MICRO; 410 default: 411 return -EINVAL; 412 } 413 } 414 415 static const struct iio_info vcnl4000_info = { 416 .read_raw = vcnl4000_read_raw, 417 }; 418 419 static int vcnl4000_probe(struct i2c_client *client, 420 const struct i2c_device_id *id) 421 { 422 struct vcnl4000_data *data; 423 struct iio_dev *indio_dev; 424 int ret; 425 426 indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); 427 if (!indio_dev) 428 return -ENOMEM; 429 430 data = iio_priv(indio_dev); 431 i2c_set_clientdata(client, indio_dev); 432 data->client = client; 433 data->id = id->driver_data; 434 data->chip_spec = &vcnl4000_chip_spec_cfg[data->id]; 435 436 ret = data->chip_spec->init(data); 437 if (ret < 0) 438 return ret; 439 440 dev_dbg(&client->dev, "%s Ambient light/proximity sensor, Rev: %02x\n", 441 data->chip_spec->prod, data->rev); 442 443 indio_dev->dev.parent = &client->dev; 444 indio_dev->info = &vcnl4000_info; 445 indio_dev->channels = vcnl4000_channels; 446 indio_dev->num_channels = ARRAY_SIZE(vcnl4000_channels); 447 indio_dev->name = VCNL4000_DRV_NAME; 448 indio_dev->modes = INDIO_DIRECT_MODE; 449 450 ret = pm_runtime_set_active(&client->dev); 451 if (ret < 0) 452 goto fail_poweroff; 453 454 ret = iio_device_register(indio_dev); 455 if (ret < 0) 456 goto fail_poweroff; 457 458 pm_runtime_enable(&client->dev); 459 pm_runtime_set_autosuspend_delay(&client->dev, VCNL4000_SLEEP_DELAY_MS); 460 pm_runtime_use_autosuspend(&client->dev); 461 462 return 0; 463 fail_poweroff: 464 data->chip_spec->set_power_state(data, false); 465 return ret; 466 } 467 468 static const struct of_device_id vcnl_4000_of_match[] = { 469 { 470 .compatible = "vishay,vcnl4000", 471 .data = (void *)VCNL4000, 472 }, 473 { 474 .compatible = "vishay,vcnl4010", 475 .data = (void *)VCNL4010, 476 }, 477 { 478 .compatible = "vishay,vcnl4020", 479 .data = (void *)VCNL4010, 480 }, 481 { 482 .compatible = "vishay,vcnl4040", 483 .data = (void *)VCNL4040, 484 }, 485 { 486 .compatible = "vishay,vcnl4200", 487 .data = (void *)VCNL4200, 488 }, 489 {}, 490 }; 491 MODULE_DEVICE_TABLE(of, vcnl_4000_of_match); 492 493 static int vcnl4000_remove(struct i2c_client *client) 494 { 495 struct iio_dev *indio_dev = i2c_get_clientdata(client); 496 struct vcnl4000_data *data = iio_priv(indio_dev); 497 498 pm_runtime_dont_use_autosuspend(&client->dev); 499 pm_runtime_disable(&client->dev); 500 iio_device_unregister(indio_dev); 501 pm_runtime_set_suspended(&client->dev); 502 503 return data->chip_spec->set_power_state(data, false); 504 } 505 506 static int __maybe_unused vcnl4000_runtime_suspend(struct device *dev) 507 { 508 struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev)); 509 struct vcnl4000_data *data = iio_priv(indio_dev); 510 511 return data->chip_spec->set_power_state(data, false); 512 } 513 514 static int __maybe_unused vcnl4000_runtime_resume(struct device *dev) 515 { 516 struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev)); 517 struct vcnl4000_data *data = iio_priv(indio_dev); 518 519 return data->chip_spec->set_power_state(data, true); 520 } 521 522 static const struct dev_pm_ops vcnl4000_pm_ops = { 523 SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, 524 pm_runtime_force_resume) 525 SET_RUNTIME_PM_OPS(vcnl4000_runtime_suspend, 526 vcnl4000_runtime_resume, NULL) 527 }; 528 529 static struct i2c_driver vcnl4000_driver = { 530 .driver = { 531 .name = VCNL4000_DRV_NAME, 532 .pm = &vcnl4000_pm_ops, 533 .of_match_table = vcnl_4000_of_match, 534 }, 535 .probe = vcnl4000_probe, 536 .id_table = vcnl4000_id, 537 .remove = vcnl4000_remove, 538 }; 539 540 module_i2c_driver(vcnl4000_driver); 541 542 MODULE_AUTHOR("Peter Meerwald <pmeerw@pmeerw.net>"); 543 MODULE_DESCRIPTION("Vishay VCNL4000 proximity/ambient light sensor driver"); 544 MODULE_LICENSE("GPL"); 545