1 /* 2 * RPR-0521 ROHM Ambient Light and Proximity Sensor 3 * 4 * Copyright (c) 2015, Intel Corporation. 5 * 6 * This file is subject to the terms and conditions of version 2 of 7 * the GNU General Public License. See the file COPYING in the main 8 * directory of this archive for more details. 9 * 10 * IIO driver for RPR-0521RS (7-bit I2C slave address 0x38). 11 * 12 * TODO: illuminance channel, PM support, buffer 13 */ 14 15 #include <linux/module.h> 16 #include <linux/init.h> 17 #include <linux/i2c.h> 18 #include <linux/regmap.h> 19 #include <linux/delay.h> 20 #include <linux/acpi.h> 21 22 #include <linux/iio/iio.h> 23 #include <linux/iio/sysfs.h> 24 #include <linux/pm_runtime.h> 25 26 #define RPR0521_REG_SYSTEM_CTRL 0x40 27 #define RPR0521_REG_MODE_CTRL 0x41 28 #define RPR0521_REG_ALS_CTRL 0x42 29 #define RPR0521_REG_PXS_CTRL 0x43 30 #define RPR0521_REG_PXS_DATA 0x44 /* 16-bit, little endian */ 31 #define RPR0521_REG_ALS_DATA0 0x46 /* 16-bit, little endian */ 32 #define RPR0521_REG_ALS_DATA1 0x48 /* 16-bit, little endian */ 33 #define RPR0521_REG_ID 0x92 34 35 #define RPR0521_MODE_ALS_MASK BIT(7) 36 #define RPR0521_MODE_PXS_MASK BIT(6) 37 #define RPR0521_MODE_MEAS_TIME_MASK GENMASK(3, 0) 38 #define RPR0521_ALS_DATA0_GAIN_MASK GENMASK(5, 4) 39 #define RPR0521_ALS_DATA0_GAIN_SHIFT 4 40 #define RPR0521_ALS_DATA1_GAIN_MASK GENMASK(3, 2) 41 #define RPR0521_ALS_DATA1_GAIN_SHIFT 2 42 #define RPR0521_PXS_GAIN_MASK GENMASK(5, 4) 43 #define RPR0521_PXS_GAIN_SHIFT 4 44 45 #define RPR0521_MODE_ALS_ENABLE BIT(7) 46 #define RPR0521_MODE_ALS_DISABLE 0x00 47 #define RPR0521_MODE_PXS_ENABLE BIT(6) 48 #define RPR0521_MODE_PXS_DISABLE 0x00 49 50 #define RPR0521_MANUFACT_ID 0xE0 51 #define RPR0521_DEFAULT_MEAS_TIME 0x06 /* ALS - 100ms, PXS - 100ms */ 52 53 #define RPR0521_DRV_NAME "RPR0521" 54 #define RPR0521_REGMAP_NAME "rpr0521_regmap" 55 56 #define RPR0521_SLEEP_DELAY_MS 2000 57 58 #define RPR0521_ALS_SCALE_AVAIL "0.007812 0.015625 0.5 1" 59 #define RPR0521_PXS_SCALE_AVAIL "0.125 0.5 1" 60 61 struct rpr0521_gain { 62 int scale; 63 int uscale; 64 }; 65 66 static const struct rpr0521_gain rpr0521_als_gain[4] = { 67 {1, 0}, /* x1 */ 68 {0, 500000}, /* x2 */ 69 {0, 15625}, /* x64 */ 70 {0, 7812}, /* x128 */ 71 }; 72 73 static const struct rpr0521_gain rpr0521_pxs_gain[3] = { 74 {1, 0}, /* x1 */ 75 {0, 500000}, /* x2 */ 76 {0, 125000}, /* x4 */ 77 }; 78 79 enum rpr0521_channel { 80 RPR0521_CHAN_ALS_DATA0, 81 RPR0521_CHAN_ALS_DATA1, 82 RPR0521_CHAN_PXS, 83 }; 84 85 struct rpr0521_reg_desc { 86 u8 address; 87 u8 device_mask; 88 }; 89 90 static const struct rpr0521_reg_desc rpr0521_data_reg[] = { 91 [RPR0521_CHAN_ALS_DATA0] = { 92 .address = RPR0521_REG_ALS_DATA0, 93 .device_mask = RPR0521_MODE_ALS_MASK, 94 }, 95 [RPR0521_CHAN_ALS_DATA1] = { 96 .address = RPR0521_REG_ALS_DATA1, 97 .device_mask = RPR0521_MODE_ALS_MASK, 98 }, 99 [RPR0521_CHAN_PXS] = { 100 .address = RPR0521_REG_PXS_DATA, 101 .device_mask = RPR0521_MODE_PXS_MASK, 102 }, 103 }; 104 105 static const struct rpr0521_gain_info { 106 u8 reg; 107 u8 mask; 108 u8 shift; 109 const struct rpr0521_gain *gain; 110 int size; 111 } rpr0521_gain[] = { 112 [RPR0521_CHAN_ALS_DATA0] = { 113 .reg = RPR0521_REG_ALS_CTRL, 114 .mask = RPR0521_ALS_DATA0_GAIN_MASK, 115 .shift = RPR0521_ALS_DATA0_GAIN_SHIFT, 116 .gain = rpr0521_als_gain, 117 .size = ARRAY_SIZE(rpr0521_als_gain), 118 }, 119 [RPR0521_CHAN_ALS_DATA1] = { 120 .reg = RPR0521_REG_ALS_CTRL, 121 .mask = RPR0521_ALS_DATA1_GAIN_MASK, 122 .shift = RPR0521_ALS_DATA1_GAIN_SHIFT, 123 .gain = rpr0521_als_gain, 124 .size = ARRAY_SIZE(rpr0521_als_gain), 125 }, 126 [RPR0521_CHAN_PXS] = { 127 .reg = RPR0521_REG_PXS_CTRL, 128 .mask = RPR0521_PXS_GAIN_MASK, 129 .shift = RPR0521_PXS_GAIN_SHIFT, 130 .gain = rpr0521_pxs_gain, 131 .size = ARRAY_SIZE(rpr0521_pxs_gain), 132 }, 133 }; 134 135 struct rpr0521_data { 136 struct i2c_client *client; 137 138 /* protect device params updates (e.g state, gain) */ 139 struct mutex lock; 140 141 /* device active status */ 142 bool als_dev_en; 143 bool pxs_dev_en; 144 145 /* optimize runtime pm ops - enable device only if needed */ 146 bool als_ps_need_en; 147 bool pxs_ps_need_en; 148 149 struct regmap *regmap; 150 }; 151 152 static IIO_CONST_ATTR(in_intensity_scale_available, RPR0521_ALS_SCALE_AVAIL); 153 static IIO_CONST_ATTR(in_proximity_scale_available, RPR0521_PXS_SCALE_AVAIL); 154 155 static struct attribute *rpr0521_attributes[] = { 156 &iio_const_attr_in_intensity_scale_available.dev_attr.attr, 157 &iio_const_attr_in_proximity_scale_available.dev_attr.attr, 158 NULL, 159 }; 160 161 static const struct attribute_group rpr0521_attribute_group = { 162 .attrs = rpr0521_attributes, 163 }; 164 165 static const struct iio_chan_spec rpr0521_channels[] = { 166 { 167 .type = IIO_INTENSITY, 168 .modified = 1, 169 .address = RPR0521_CHAN_ALS_DATA0, 170 .channel2 = IIO_MOD_LIGHT_BOTH, 171 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | 172 BIT(IIO_CHAN_INFO_SCALE), 173 }, 174 { 175 .type = IIO_INTENSITY, 176 .modified = 1, 177 .address = RPR0521_CHAN_ALS_DATA1, 178 .channel2 = IIO_MOD_LIGHT_IR, 179 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | 180 BIT(IIO_CHAN_INFO_SCALE), 181 }, 182 { 183 .type = IIO_PROXIMITY, 184 .address = RPR0521_CHAN_PXS, 185 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | 186 BIT(IIO_CHAN_INFO_SCALE), 187 } 188 }; 189 190 static int rpr0521_als_enable(struct rpr0521_data *data, u8 status) 191 { 192 int ret; 193 194 ret = regmap_update_bits(data->regmap, RPR0521_REG_MODE_CTRL, 195 RPR0521_MODE_ALS_MASK, 196 status); 197 if (ret < 0) 198 return ret; 199 200 data->als_dev_en = true; 201 202 return 0; 203 } 204 205 static int rpr0521_pxs_enable(struct rpr0521_data *data, u8 status) 206 { 207 int ret; 208 209 ret = regmap_update_bits(data->regmap, RPR0521_REG_MODE_CTRL, 210 RPR0521_MODE_PXS_MASK, 211 status); 212 if (ret < 0) 213 return ret; 214 215 data->pxs_dev_en = true; 216 217 return 0; 218 } 219 220 /** 221 * rpr0521_set_power_state - handles runtime PM state and sensors enabled status 222 * 223 * @data: rpr0521 device private data 224 * @on: state to be set for devices in @device_mask 225 * @device_mask: bitmask specifying for which device we need to update @on state 226 * 227 * We rely on rpr0521_runtime_resume to enable our @device_mask devices, but 228 * if (for example) PXS was enabled (pxs_dev_en = true) by a previous call to 229 * rpr0521_runtime_resume and we want to enable ALS we MUST set ALS enable 230 * bit of RPR0521_REG_MODE_CTRL here because rpr0521_runtime_resume will not 231 * be called twice. 232 */ 233 static int rpr0521_set_power_state(struct rpr0521_data *data, bool on, 234 u8 device_mask) 235 { 236 #ifdef CONFIG_PM 237 int ret; 238 u8 update_mask = 0; 239 240 if (device_mask & RPR0521_MODE_ALS_MASK) { 241 if (on && !data->als_ps_need_en && data->pxs_dev_en) 242 update_mask |= RPR0521_MODE_ALS_MASK; 243 else 244 data->als_ps_need_en = on; 245 } 246 247 if (device_mask & RPR0521_MODE_PXS_MASK) { 248 if (on && !data->pxs_ps_need_en && data->als_dev_en) 249 update_mask |= RPR0521_MODE_PXS_MASK; 250 else 251 data->pxs_ps_need_en = on; 252 } 253 254 if (update_mask) { 255 ret = regmap_update_bits(data->regmap, RPR0521_REG_MODE_CTRL, 256 update_mask, update_mask); 257 if (ret < 0) 258 return ret; 259 } 260 261 if (on) { 262 ret = pm_runtime_get_sync(&data->client->dev); 263 } else { 264 pm_runtime_mark_last_busy(&data->client->dev); 265 ret = pm_runtime_put_autosuspend(&data->client->dev); 266 } 267 if (ret < 0) { 268 dev_err(&data->client->dev, 269 "Failed: rpr0521_set_power_state for %d, ret %d\n", 270 on, ret); 271 if (on) 272 pm_runtime_put_noidle(&data->client->dev); 273 274 return ret; 275 } 276 #endif 277 return 0; 278 } 279 280 static int rpr0521_get_gain(struct rpr0521_data *data, int chan, 281 int *val, int *val2) 282 { 283 int ret, reg, idx; 284 285 ret = regmap_read(data->regmap, rpr0521_gain[chan].reg, ®); 286 if (ret < 0) 287 return ret; 288 289 idx = (rpr0521_gain[chan].mask & reg) >> rpr0521_gain[chan].shift; 290 *val = rpr0521_gain[chan].gain[idx].scale; 291 *val2 = rpr0521_gain[chan].gain[idx].uscale; 292 293 return 0; 294 } 295 296 static int rpr0521_set_gain(struct rpr0521_data *data, int chan, 297 int val, int val2) 298 { 299 int i, idx = -EINVAL; 300 301 /* get gain index */ 302 for (i = 0; i < rpr0521_gain[chan].size; i++) 303 if (val == rpr0521_gain[chan].gain[i].scale && 304 val2 == rpr0521_gain[chan].gain[i].uscale) { 305 idx = i; 306 break; 307 } 308 309 if (idx < 0) 310 return idx; 311 312 return regmap_update_bits(data->regmap, rpr0521_gain[chan].reg, 313 rpr0521_gain[chan].mask, 314 idx << rpr0521_gain[chan].shift); 315 } 316 317 static int rpr0521_read_raw(struct iio_dev *indio_dev, 318 struct iio_chan_spec const *chan, int *val, 319 int *val2, long mask) 320 { 321 struct rpr0521_data *data = iio_priv(indio_dev); 322 int ret; 323 u8 device_mask; 324 __le16 raw_data; 325 326 switch (mask) { 327 case IIO_CHAN_INFO_RAW: 328 if (chan->type != IIO_INTENSITY && chan->type != IIO_PROXIMITY) 329 return -EINVAL; 330 331 device_mask = rpr0521_data_reg[chan->address].device_mask; 332 333 mutex_lock(&data->lock); 334 ret = rpr0521_set_power_state(data, true, device_mask); 335 if (ret < 0) { 336 mutex_unlock(&data->lock); 337 return ret; 338 } 339 340 ret = regmap_bulk_read(data->regmap, 341 rpr0521_data_reg[chan->address].address, 342 &raw_data, 2); 343 if (ret < 0) { 344 rpr0521_set_power_state(data, false, device_mask); 345 mutex_unlock(&data->lock); 346 return ret; 347 } 348 349 ret = rpr0521_set_power_state(data, false, device_mask); 350 mutex_unlock(&data->lock); 351 if (ret < 0) 352 return ret; 353 354 *val = le16_to_cpu(raw_data); 355 356 return IIO_VAL_INT; 357 case IIO_CHAN_INFO_SCALE: 358 mutex_lock(&data->lock); 359 ret = rpr0521_get_gain(data, chan->address, val, val2); 360 mutex_unlock(&data->lock); 361 if (ret < 0) 362 return ret; 363 364 return IIO_VAL_INT_PLUS_MICRO; 365 default: 366 return -EINVAL; 367 } 368 } 369 370 static int rpr0521_write_raw(struct iio_dev *indio_dev, 371 struct iio_chan_spec const *chan, int val, 372 int val2, long mask) 373 { 374 struct rpr0521_data *data = iio_priv(indio_dev); 375 int ret; 376 377 switch (mask) { 378 case IIO_CHAN_INFO_SCALE: 379 mutex_lock(&data->lock); 380 ret = rpr0521_set_gain(data, chan->address, val, val2); 381 mutex_unlock(&data->lock); 382 383 return ret; 384 default: 385 return -EINVAL; 386 } 387 } 388 389 static const struct iio_info rpr0521_info = { 390 .driver_module = THIS_MODULE, 391 .read_raw = rpr0521_read_raw, 392 .write_raw = rpr0521_write_raw, 393 .attrs = &rpr0521_attribute_group, 394 }; 395 396 static int rpr0521_init(struct rpr0521_data *data) 397 { 398 int ret; 399 int id; 400 401 ret = regmap_read(data->regmap, RPR0521_REG_ID, &id); 402 if (ret < 0) { 403 dev_err(&data->client->dev, "Failed to read REG_ID register\n"); 404 return ret; 405 } 406 407 if (id != RPR0521_MANUFACT_ID) { 408 dev_err(&data->client->dev, "Wrong id, got %x, expected %x\n", 409 id, RPR0521_MANUFACT_ID); 410 return -ENODEV; 411 } 412 413 /* set default measurement time - 100 ms for both ALS and PS */ 414 ret = regmap_update_bits(data->regmap, RPR0521_REG_MODE_CTRL, 415 RPR0521_MODE_MEAS_TIME_MASK, 416 RPR0521_DEFAULT_MEAS_TIME); 417 if (ret) { 418 pr_err("regmap_update_bits returned %d\n", ret); 419 return ret; 420 } 421 422 ret = rpr0521_als_enable(data, RPR0521_MODE_ALS_ENABLE); 423 if (ret < 0) 424 return ret; 425 ret = rpr0521_pxs_enable(data, RPR0521_MODE_PXS_ENABLE); 426 if (ret < 0) 427 return ret; 428 429 return 0; 430 } 431 432 static int rpr0521_poweroff(struct rpr0521_data *data) 433 { 434 int ret; 435 436 ret = regmap_update_bits(data->regmap, RPR0521_REG_MODE_CTRL, 437 RPR0521_MODE_ALS_MASK | 438 RPR0521_MODE_PXS_MASK, 439 RPR0521_MODE_ALS_DISABLE | 440 RPR0521_MODE_PXS_DISABLE); 441 if (ret < 0) 442 return ret; 443 444 data->als_dev_en = false; 445 data->pxs_dev_en = false; 446 447 return 0; 448 } 449 450 static bool rpr0521_is_volatile_reg(struct device *dev, unsigned int reg) 451 { 452 switch (reg) { 453 case RPR0521_REG_MODE_CTRL: 454 case RPR0521_REG_ALS_CTRL: 455 case RPR0521_REG_PXS_CTRL: 456 return false; 457 default: 458 return true; 459 } 460 } 461 462 static const struct regmap_config rpr0521_regmap_config = { 463 .name = RPR0521_REGMAP_NAME, 464 465 .reg_bits = 8, 466 .val_bits = 8, 467 468 .max_register = RPR0521_REG_ID, 469 .cache_type = REGCACHE_RBTREE, 470 .volatile_reg = rpr0521_is_volatile_reg, 471 }; 472 473 static int rpr0521_probe(struct i2c_client *client, 474 const struct i2c_device_id *id) 475 { 476 struct rpr0521_data *data; 477 struct iio_dev *indio_dev; 478 struct regmap *regmap; 479 int ret; 480 481 indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); 482 if (!indio_dev) 483 return -ENOMEM; 484 485 regmap = devm_regmap_init_i2c(client, &rpr0521_regmap_config); 486 if (IS_ERR(regmap)) { 487 dev_err(&client->dev, "regmap_init failed!\n"); 488 return PTR_ERR(regmap); 489 } 490 491 data = iio_priv(indio_dev); 492 i2c_set_clientdata(client, indio_dev); 493 data->client = client; 494 data->regmap = regmap; 495 496 mutex_init(&data->lock); 497 498 indio_dev->dev.parent = &client->dev; 499 indio_dev->info = &rpr0521_info; 500 indio_dev->name = RPR0521_DRV_NAME; 501 indio_dev->channels = rpr0521_channels; 502 indio_dev->num_channels = ARRAY_SIZE(rpr0521_channels); 503 indio_dev->modes = INDIO_DIRECT_MODE; 504 505 ret = rpr0521_init(data); 506 if (ret < 0) { 507 dev_err(&client->dev, "rpr0521 chip init failed\n"); 508 return ret; 509 } 510 511 ret = pm_runtime_set_active(&client->dev); 512 if (ret < 0) 513 return ret; 514 515 pm_runtime_enable(&client->dev); 516 pm_runtime_set_autosuspend_delay(&client->dev, RPR0521_SLEEP_DELAY_MS); 517 pm_runtime_use_autosuspend(&client->dev); 518 519 return iio_device_register(indio_dev); 520 } 521 522 static int rpr0521_remove(struct i2c_client *client) 523 { 524 struct iio_dev *indio_dev = i2c_get_clientdata(client); 525 526 iio_device_unregister(indio_dev); 527 528 pm_runtime_disable(&client->dev); 529 pm_runtime_set_suspended(&client->dev); 530 pm_runtime_put_noidle(&client->dev); 531 532 rpr0521_poweroff(iio_priv(indio_dev)); 533 534 return 0; 535 } 536 537 #ifdef CONFIG_PM 538 static int rpr0521_runtime_suspend(struct device *dev) 539 { 540 struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev)); 541 struct rpr0521_data *data = iio_priv(indio_dev); 542 int ret; 543 544 /* disable channels and sets {als,pxs}_dev_en to false */ 545 mutex_lock(&data->lock); 546 ret = rpr0521_poweroff(data); 547 mutex_unlock(&data->lock); 548 549 return ret; 550 } 551 552 static int rpr0521_runtime_resume(struct device *dev) 553 { 554 struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev)); 555 struct rpr0521_data *data = iio_priv(indio_dev); 556 int ret; 557 558 if (data->als_ps_need_en) { 559 ret = rpr0521_als_enable(data, RPR0521_MODE_ALS_ENABLE); 560 if (ret < 0) 561 return ret; 562 data->als_ps_need_en = false; 563 } 564 565 if (data->pxs_ps_need_en) { 566 ret = rpr0521_pxs_enable(data, RPR0521_MODE_PXS_ENABLE); 567 if (ret < 0) 568 return ret; 569 data->pxs_ps_need_en = false; 570 } 571 572 return 0; 573 } 574 #endif 575 576 static const struct dev_pm_ops rpr0521_pm_ops = { 577 SET_RUNTIME_PM_OPS(rpr0521_runtime_suspend, 578 rpr0521_runtime_resume, NULL) 579 }; 580 581 static const struct acpi_device_id rpr0521_acpi_match[] = { 582 {"RPR0521", 0}, 583 { } 584 }; 585 MODULE_DEVICE_TABLE(acpi, rpr0521_acpi_match); 586 587 static const struct i2c_device_id rpr0521_id[] = { 588 {"rpr0521", 0}, 589 { } 590 }; 591 592 MODULE_DEVICE_TABLE(i2c, rpr0521_id); 593 594 static struct i2c_driver rpr0521_driver = { 595 .driver = { 596 .name = RPR0521_DRV_NAME, 597 .pm = &rpr0521_pm_ops, 598 .acpi_match_table = ACPI_PTR(rpr0521_acpi_match), 599 }, 600 .probe = rpr0521_probe, 601 .remove = rpr0521_remove, 602 .id_table = rpr0521_id, 603 }; 604 605 module_i2c_driver(rpr0521_driver); 606 607 MODULE_AUTHOR("Daniel Baluta <daniel.baluta@intel.com>"); 608 MODULE_DESCRIPTION("RPR0521 ROHM Ambient Light and Proximity Sensor driver"); 609 MODULE_LICENSE("GPL v2"); 610