1 /* 2 * Copyright (c) 2015 Intel Corporation 3 * 4 * Driver for UPISEMI us5182d Proximity and Ambient Light Sensor. 5 * 6 * This program is free software; you can redistribute it and/or modify it 7 * under the terms of the GNU General Public License version 2 as published by 8 * the Free Software Foundation. 9 * 10 * This program is distributed in the hope it will be useful, but WITHOUT 11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 13 * more details. 14 * 15 * To do: Interrupt support. 16 */ 17 18 #include <linux/kernel.h> 19 #include <linux/module.h> 20 #include <linux/acpi.h> 21 #include <linux/delay.h> 22 #include <linux/i2c.h> 23 #include <linux/iio/iio.h> 24 #include <linux/iio/sysfs.h> 25 #include <linux/mutex.h> 26 27 #define US5182D_REG_CFG0 0x00 28 #define US5182D_CFG0_ONESHOT_EN BIT(6) 29 #define US5182D_CFG0_SHUTDOWN_EN BIT(7) 30 #define US5182D_CFG0_WORD_ENABLE BIT(0) 31 32 #define US5182D_REG_CFG1 0x01 33 #define US5182D_CFG1_ALS_RES16 BIT(4) 34 #define US5182D_CFG1_AGAIN_DEFAULT 0x00 35 36 #define US5182D_REG_CFG2 0x02 37 #define US5182D_CFG2_PX_RES16 BIT(4) 38 #define US5182D_CFG2_PXGAIN_DEFAULT BIT(2) 39 40 #define US5182D_REG_CFG3 0x03 41 #define US5182D_CFG3_LED_CURRENT100 (BIT(4) | BIT(5)) 42 43 #define US5182D_REG_CFG4 0x10 44 45 /* 46 * Registers for tuning the auto dark current cancelling feature. 47 * DARK_TH(reg 0x27,0x28) - threshold (counts) for auto dark cancelling. 48 * when ALS > DARK_TH --> ALS_Code = ALS - Upper(0x2A) * Dark 49 * when ALS < DARK_TH --> ALS_Code = ALS - Lower(0x29) * Dark 50 */ 51 #define US5182D_REG_UDARK_TH 0x27 52 #define US5182D_REG_DARK_AUTO_EN 0x2b 53 #define US5182D_REG_AUTO_LDARK_GAIN 0x29 54 #define US5182D_REG_AUTO_HDARK_GAIN 0x2a 55 56 #define US5182D_OPMODE_ALS 0x01 57 #define US5182D_OPMODE_PX 0x02 58 #define US5182D_OPMODE_SHIFT 4 59 60 #define US5182D_REG_DARK_AUTO_EN_DEFAULT 0x80 61 #define US5182D_REG_AUTO_LDARK_GAIN_DEFAULT 0x16 62 #define US5182D_REG_AUTO_HDARK_GAIN_DEFAULT 0x00 63 64 #define US5182D_REG_ADL 0x0c 65 #define US5182D_REG_PDL 0x0e 66 67 #define US5182D_REG_MODE_STORE 0x21 68 #define US5182D_STORE_MODE 0x01 69 70 #define US5182D_REG_CHIPID 0xb2 71 72 #define US5182D_OPMODE_MASK GENMASK(5, 4) 73 #define US5182D_AGAIN_MASK 0x07 74 #define US5182D_RESET_CHIP 0x01 75 76 #define US5182D_CHIPID 0x26 77 #define US5182D_DRV_NAME "us5182d" 78 79 #define US5182D_GA_RESOLUTION 1000 80 81 #define US5182D_READ_BYTE 1 82 #define US5182D_READ_WORD 2 83 #define US5182D_OPSTORE_SLEEP_TIME 20 /* ms */ 84 85 /* Available ranges: [12354, 7065, 3998, 2202, 1285, 498, 256, 138] lux */ 86 static const int us5182d_scales[] = {188500, 107800, 61000, 33600, 19600, 7600, 87 3900, 2100}; 88 89 /* 90 * Experimental thresholds that work with US5182D sensor on evaluation board 91 * roughly between 12-32 lux 92 */ 93 static u16 us5182d_dark_ths_vals[] = {170, 200, 512, 512, 800, 2000, 4000, 94 8000}; 95 96 enum mode { 97 US5182D_ALS_PX, 98 US5182D_ALS_ONLY, 99 US5182D_PX_ONLY 100 }; 101 102 struct us5182d_data { 103 struct i2c_client *client; 104 struct mutex lock; 105 106 /* Glass attenuation factor */ 107 u32 ga; 108 109 /* Dark gain tuning */ 110 u8 lower_dark_gain; 111 u8 upper_dark_gain; 112 u16 *us5182d_dark_ths; 113 114 u8 opmode; 115 }; 116 117 static IIO_CONST_ATTR(in_illuminance_scale_available, 118 "0.0021 0.0039 0.0076 0.0196 0.0336 0.061 0.1078 0.1885"); 119 120 static struct attribute *us5182d_attrs[] = { 121 &iio_const_attr_in_illuminance_scale_available.dev_attr.attr, 122 NULL 123 }; 124 125 static const struct attribute_group us5182d_attr_group = { 126 .attrs = us5182d_attrs, 127 }; 128 129 static const struct { 130 u8 reg; 131 u8 val; 132 } us5182d_regvals[] = { 133 {US5182D_REG_CFG0, (US5182D_CFG0_SHUTDOWN_EN | 134 US5182D_CFG0_WORD_ENABLE)}, 135 {US5182D_REG_CFG1, US5182D_CFG1_ALS_RES16}, 136 {US5182D_REG_CFG2, (US5182D_CFG2_PX_RES16 | 137 US5182D_CFG2_PXGAIN_DEFAULT)}, 138 {US5182D_REG_CFG3, US5182D_CFG3_LED_CURRENT100}, 139 {US5182D_REG_MODE_STORE, US5182D_STORE_MODE}, 140 {US5182D_REG_CFG4, 0x00}, 141 }; 142 143 static const struct iio_chan_spec us5182d_channels[] = { 144 { 145 .type = IIO_LIGHT, 146 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | 147 BIT(IIO_CHAN_INFO_SCALE), 148 }, 149 { 150 .type = IIO_PROXIMITY, 151 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), 152 } 153 }; 154 155 static int us5182d_get_als(struct us5182d_data *data) 156 { 157 int ret; 158 unsigned long result; 159 160 ret = i2c_smbus_read_word_data(data->client, 161 US5182D_REG_ADL); 162 if (ret < 0) 163 return ret; 164 165 result = ret * data->ga / US5182D_GA_RESOLUTION; 166 if (result > 0xffff) 167 result = 0xffff; 168 169 return result; 170 } 171 172 static int us5182d_set_opmode(struct us5182d_data *data, u8 mode) 173 { 174 int ret; 175 176 ret = i2c_smbus_read_byte_data(data->client, US5182D_REG_CFG0); 177 if (ret < 0) 178 return ret; 179 180 /* 181 * In oneshot mode the chip will power itself down after taking the 182 * required measurement. 183 */ 184 ret = ret | US5182D_CFG0_ONESHOT_EN; 185 186 /* update mode */ 187 ret = ret & ~US5182D_OPMODE_MASK; 188 ret = ret | (mode << US5182D_OPMODE_SHIFT); 189 190 /* 191 * After updating the operating mode, the chip requires that 192 * the operation is stored, by writing 1 in the STORE_MODE 193 * register (auto-clearing). 194 */ 195 ret = i2c_smbus_write_byte_data(data->client, US5182D_REG_CFG0, ret); 196 if (ret < 0) 197 return ret; 198 199 if (mode == data->opmode) 200 return 0; 201 202 ret = i2c_smbus_write_byte_data(data->client, US5182D_REG_MODE_STORE, 203 US5182D_STORE_MODE); 204 if (ret < 0) 205 return ret; 206 207 data->opmode = mode; 208 msleep(US5182D_OPSTORE_SLEEP_TIME); 209 210 return 0; 211 } 212 213 static int us5182d_read_raw(struct iio_dev *indio_dev, 214 struct iio_chan_spec const *chan, int *val, 215 int *val2, long mask) 216 { 217 struct us5182d_data *data = iio_priv(indio_dev); 218 int ret; 219 220 switch (mask) { 221 case IIO_CHAN_INFO_RAW: 222 switch (chan->type) { 223 case IIO_LIGHT: 224 mutex_lock(&data->lock); 225 ret = us5182d_set_opmode(data, US5182D_OPMODE_ALS); 226 if (ret < 0) 227 goto out_err; 228 229 ret = us5182d_get_als(data); 230 if (ret < 0) 231 goto out_err; 232 mutex_unlock(&data->lock); 233 *val = ret; 234 return IIO_VAL_INT; 235 case IIO_PROXIMITY: 236 mutex_lock(&data->lock); 237 ret = us5182d_set_opmode(data, US5182D_OPMODE_PX); 238 if (ret < 0) 239 goto out_err; 240 241 ret = i2c_smbus_read_word_data(data->client, 242 US5182D_REG_PDL); 243 if (ret < 0) 244 goto out_err; 245 mutex_unlock(&data->lock); 246 *val = ret; 247 return IIO_VAL_INT; 248 default: 249 return -EINVAL; 250 } 251 252 case IIO_CHAN_INFO_SCALE: 253 ret = i2c_smbus_read_byte_data(data->client, US5182D_REG_CFG1); 254 if (ret < 0) 255 return ret; 256 257 *val = 0; 258 *val2 = us5182d_scales[ret & US5182D_AGAIN_MASK]; 259 260 return IIO_VAL_INT_PLUS_MICRO; 261 default: 262 return -EINVAL; 263 } 264 265 return -EINVAL; 266 out_err: 267 mutex_unlock(&data->lock); 268 return ret; 269 } 270 271 /** 272 * us5182d_update_dark_th - update Darh_Th registers 273 * @data us5182d_data structure 274 * @index index in us5182d_dark_ths array to use for the updated value 275 * 276 * Function needs to be called with a lock held because it needs two i2c write 277 * byte operations as these registers (0x27 0x28) don't work in word mode 278 * accessing. 279 */ 280 static int us5182d_update_dark_th(struct us5182d_data *data, int index) 281 { 282 __be16 dark_th = cpu_to_be16(data->us5182d_dark_ths[index]); 283 int ret; 284 285 ret = i2c_smbus_write_byte_data(data->client, US5182D_REG_UDARK_TH, 286 ((u8 *)&dark_th)[0]); 287 if (ret < 0) 288 return ret; 289 290 return i2c_smbus_write_byte_data(data->client, US5182D_REG_UDARK_TH + 1, 291 ((u8 *)&dark_th)[1]); 292 } 293 294 /** 295 * us5182d_apply_scale - update the ALS scale 296 * @data us5182d_data structure 297 * @index index in us5182d_scales array to use for the updated value 298 * 299 * Function needs to be called with a lock held as we're having more than one 300 * i2c operation. 301 */ 302 static int us5182d_apply_scale(struct us5182d_data *data, int index) 303 { 304 int ret; 305 306 ret = i2c_smbus_read_byte_data(data->client, US5182D_REG_CFG1); 307 if (ret < 0) 308 return ret; 309 310 ret = ret & (~US5182D_AGAIN_MASK); 311 ret |= index; 312 313 ret = i2c_smbus_write_byte_data(data->client, US5182D_REG_CFG1, ret); 314 if (ret < 0) 315 return ret; 316 317 return us5182d_update_dark_th(data, index); 318 } 319 320 static int us5182d_write_raw(struct iio_dev *indio_dev, 321 struct iio_chan_spec const *chan, int val, 322 int val2, long mask) 323 { 324 struct us5182d_data *data = iio_priv(indio_dev); 325 int ret, i; 326 327 switch (mask) { 328 case IIO_CHAN_INFO_SCALE: 329 if (val != 0) 330 return -EINVAL; 331 for (i = 0; i < ARRAY_SIZE(us5182d_scales); i++) 332 if (val2 == us5182d_scales[i]) { 333 mutex_lock(&data->lock); 334 ret = us5182d_apply_scale(data, i); 335 mutex_unlock(&data->lock); 336 return ret; 337 } 338 break; 339 default: 340 return -EINVAL; 341 } 342 343 return -EINVAL; 344 } 345 346 static const struct iio_info us5182d_info = { 347 .driver_module = THIS_MODULE, 348 .read_raw = us5182d_read_raw, 349 .write_raw = us5182d_write_raw, 350 .attrs = &us5182d_attr_group, 351 }; 352 353 static int us5182d_reset(struct iio_dev *indio_dev) 354 { 355 struct us5182d_data *data = iio_priv(indio_dev); 356 357 return i2c_smbus_write_byte_data(data->client, US5182D_REG_CFG3, 358 US5182D_RESET_CHIP); 359 } 360 361 static int us5182d_init(struct iio_dev *indio_dev) 362 { 363 struct us5182d_data *data = iio_priv(indio_dev); 364 int i, ret; 365 366 ret = us5182d_reset(indio_dev); 367 if (ret < 0) 368 return ret; 369 370 data->opmode = 0; 371 for (i = 0; i < ARRAY_SIZE(us5182d_regvals); i++) { 372 ret = i2c_smbus_write_byte_data(data->client, 373 us5182d_regvals[i].reg, 374 us5182d_regvals[i].val); 375 if (ret < 0) 376 return ret; 377 } 378 379 return 0; 380 } 381 382 static void us5182d_get_platform_data(struct iio_dev *indio_dev) 383 { 384 struct us5182d_data *data = iio_priv(indio_dev); 385 386 if (device_property_read_u32(&data->client->dev, "upisemi,glass-coef", 387 &data->ga)) 388 data->ga = US5182D_GA_RESOLUTION; 389 if (device_property_read_u16_array(&data->client->dev, 390 "upisemi,dark-ths", 391 data->us5182d_dark_ths, 392 ARRAY_SIZE(us5182d_dark_ths_vals))) 393 data->us5182d_dark_ths = us5182d_dark_ths_vals; 394 if (device_property_read_u8(&data->client->dev, 395 "upisemi,upper-dark-gain", 396 &data->upper_dark_gain)) 397 data->upper_dark_gain = US5182D_REG_AUTO_HDARK_GAIN_DEFAULT; 398 if (device_property_read_u8(&data->client->dev, 399 "upisemi,lower-dark-gain", 400 &data->lower_dark_gain)) 401 data->lower_dark_gain = US5182D_REG_AUTO_LDARK_GAIN_DEFAULT; 402 } 403 404 static int us5182d_dark_gain_config(struct iio_dev *indio_dev) 405 { 406 struct us5182d_data *data = iio_priv(indio_dev); 407 int ret; 408 409 ret = us5182d_update_dark_th(data, US5182D_CFG1_AGAIN_DEFAULT); 410 if (ret < 0) 411 return ret; 412 413 ret = i2c_smbus_write_byte_data(data->client, 414 US5182D_REG_AUTO_LDARK_GAIN, 415 data->lower_dark_gain); 416 if (ret < 0) 417 return ret; 418 419 ret = i2c_smbus_write_byte_data(data->client, 420 US5182D_REG_AUTO_HDARK_GAIN, 421 data->upper_dark_gain); 422 if (ret < 0) 423 return ret; 424 425 return i2c_smbus_write_byte_data(data->client, US5182D_REG_DARK_AUTO_EN, 426 US5182D_REG_DARK_AUTO_EN_DEFAULT); 427 } 428 429 static int us5182d_probe(struct i2c_client *client, 430 const struct i2c_device_id *id) 431 { 432 struct us5182d_data *data; 433 struct iio_dev *indio_dev; 434 int ret; 435 436 indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); 437 if (!indio_dev) 438 return -ENOMEM; 439 440 data = iio_priv(indio_dev); 441 i2c_set_clientdata(client, indio_dev); 442 data->client = client; 443 444 mutex_init(&data->lock); 445 446 indio_dev->dev.parent = &client->dev; 447 indio_dev->info = &us5182d_info; 448 indio_dev->name = US5182D_DRV_NAME; 449 indio_dev->channels = us5182d_channels; 450 indio_dev->num_channels = ARRAY_SIZE(us5182d_channels); 451 indio_dev->modes = INDIO_DIRECT_MODE; 452 453 ret = i2c_smbus_read_byte_data(data->client, US5182D_REG_CHIPID); 454 if (ret != US5182D_CHIPID) { 455 dev_err(&data->client->dev, 456 "Failed to detect US5182 light chip\n"); 457 return (ret < 0) ? ret : -ENODEV; 458 } 459 460 us5182d_get_platform_data(indio_dev); 461 ret = us5182d_init(indio_dev); 462 if (ret < 0) 463 return ret; 464 465 ret = us5182d_dark_gain_config(indio_dev); 466 if (ret < 0) 467 return ret; 468 469 return iio_device_register(indio_dev); 470 } 471 472 static int us5182d_remove(struct i2c_client *client) 473 { 474 iio_device_unregister(i2c_get_clientdata(client)); 475 return i2c_smbus_write_byte_data(client, US5182D_REG_CFG0, 476 US5182D_CFG0_SHUTDOWN_EN); 477 } 478 479 static const struct acpi_device_id us5182d_acpi_match[] = { 480 { "USD5182", 0}, 481 {} 482 }; 483 484 MODULE_DEVICE_TABLE(acpi, us5182d_acpi_match); 485 486 static const struct i2c_device_id us5182d_id[] = { 487 {"usd5182", 0}, 488 {} 489 }; 490 491 MODULE_DEVICE_TABLE(i2c, us5182d_id); 492 493 static struct i2c_driver us5182d_driver = { 494 .driver = { 495 .name = US5182D_DRV_NAME, 496 .acpi_match_table = ACPI_PTR(us5182d_acpi_match), 497 }, 498 .probe = us5182d_probe, 499 .remove = us5182d_remove, 500 .id_table = us5182d_id, 501 502 }; 503 module_i2c_driver(us5182d_driver); 504 505 MODULE_AUTHOR("Adriana Reus <adriana.reus@intel.com>"); 506 MODULE_DESCRIPTION("Driver for us5182d Proximity and Light Sensor"); 507 MODULE_LICENSE("GPL v2"); 508