1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * isl29003.c - Linux kernel module for 4 * Intersil ISL29003 ambient light sensor 5 * 6 * See file:Documentation/misc-devices/isl29003.rst 7 * 8 * Copyright (c) 2009 Daniel Mack <daniel@caiaq.de> 9 * 10 * Based on code written by 11 * Rodolfo Giometti <giometti@linux.it> 12 * Eurotech S.p.A. <info@eurotech.it> 13 */ 14 15 #include <linux/module.h> 16 #include <linux/slab.h> 17 #include <linux/i2c.h> 18 #include <linux/mutex.h> 19 #include <linux/delay.h> 20 21 #define ISL29003_DRV_NAME "isl29003" 22 #define DRIVER_VERSION "1.0" 23 24 #define ISL29003_REG_COMMAND 0x00 25 #define ISL29003_ADC_ENABLED (1 << 7) 26 #define ISL29003_ADC_PD (1 << 6) 27 #define ISL29003_TIMING_INT (1 << 5) 28 #define ISL29003_MODE_SHIFT (2) 29 #define ISL29003_MODE_MASK (0x3 << ISL29003_MODE_SHIFT) 30 #define ISL29003_RES_SHIFT (0) 31 #define ISL29003_RES_MASK (0x3 << ISL29003_RES_SHIFT) 32 33 #define ISL29003_REG_CONTROL 0x01 34 #define ISL29003_INT_FLG (1 << 5) 35 #define ISL29003_RANGE_SHIFT (2) 36 #define ISL29003_RANGE_MASK (0x3 << ISL29003_RANGE_SHIFT) 37 #define ISL29003_INT_PERSISTS_SHIFT (0) 38 #define ISL29003_INT_PERSISTS_MASK (0xf << ISL29003_INT_PERSISTS_SHIFT) 39 40 #define ISL29003_REG_IRQ_THRESH_HI 0x02 41 #define ISL29003_REG_IRQ_THRESH_LO 0x03 42 #define ISL29003_REG_LSB_SENSOR 0x04 43 #define ISL29003_REG_MSB_SENSOR 0x05 44 #define ISL29003_REG_LSB_TIMER 0x06 45 #define ISL29003_REG_MSB_TIMER 0x07 46 47 #define ISL29003_NUM_CACHABLE_REGS 4 48 49 struct isl29003_data { 50 struct i2c_client *client; 51 struct mutex lock; 52 u8 reg_cache[ISL29003_NUM_CACHABLE_REGS]; 53 u8 power_state_before_suspend; 54 }; 55 56 static int gain_range[] = { 57 1000, 4000, 16000, 64000 58 }; 59 60 /* 61 * register access helpers 62 */ 63 64 static int __isl29003_read_reg(struct i2c_client *client, 65 u32 reg, u8 mask, u8 shift) 66 { 67 struct isl29003_data *data = i2c_get_clientdata(client); 68 69 return (data->reg_cache[reg] & mask) >> shift; 70 } 71 72 static int __isl29003_write_reg(struct i2c_client *client, 73 u32 reg, u8 mask, u8 shift, u8 val) 74 { 75 struct isl29003_data *data = i2c_get_clientdata(client); 76 int ret = 0; 77 u8 tmp; 78 79 if (reg >= ISL29003_NUM_CACHABLE_REGS) 80 return -EINVAL; 81 82 mutex_lock(&data->lock); 83 84 tmp = data->reg_cache[reg]; 85 tmp &= ~mask; 86 tmp |= val << shift; 87 88 ret = i2c_smbus_write_byte_data(client, reg, tmp); 89 if (!ret) 90 data->reg_cache[reg] = tmp; 91 92 mutex_unlock(&data->lock); 93 return ret; 94 } 95 96 /* 97 * internally used functions 98 */ 99 100 /* range */ 101 static int isl29003_get_range(struct i2c_client *client) 102 { 103 return __isl29003_read_reg(client, ISL29003_REG_CONTROL, 104 ISL29003_RANGE_MASK, ISL29003_RANGE_SHIFT); 105 } 106 107 static int isl29003_set_range(struct i2c_client *client, int range) 108 { 109 return __isl29003_write_reg(client, ISL29003_REG_CONTROL, 110 ISL29003_RANGE_MASK, ISL29003_RANGE_SHIFT, range); 111 } 112 113 /* resolution */ 114 static int isl29003_get_resolution(struct i2c_client *client) 115 { 116 return __isl29003_read_reg(client, ISL29003_REG_COMMAND, 117 ISL29003_RES_MASK, ISL29003_RES_SHIFT); 118 } 119 120 static int isl29003_set_resolution(struct i2c_client *client, int res) 121 { 122 return __isl29003_write_reg(client, ISL29003_REG_COMMAND, 123 ISL29003_RES_MASK, ISL29003_RES_SHIFT, res); 124 } 125 126 /* mode */ 127 static int isl29003_get_mode(struct i2c_client *client) 128 { 129 return __isl29003_read_reg(client, ISL29003_REG_COMMAND, 130 ISL29003_RES_MASK, ISL29003_RES_SHIFT); 131 } 132 133 static int isl29003_set_mode(struct i2c_client *client, int mode) 134 { 135 return __isl29003_write_reg(client, ISL29003_REG_COMMAND, 136 ISL29003_RES_MASK, ISL29003_RES_SHIFT, mode); 137 } 138 139 /* power_state */ 140 static int isl29003_set_power_state(struct i2c_client *client, int state) 141 { 142 return __isl29003_write_reg(client, ISL29003_REG_COMMAND, 143 ISL29003_ADC_ENABLED | ISL29003_ADC_PD, 0, 144 state ? ISL29003_ADC_ENABLED : ISL29003_ADC_PD); 145 } 146 147 static int isl29003_get_power_state(struct i2c_client *client) 148 { 149 struct isl29003_data *data = i2c_get_clientdata(client); 150 u8 cmdreg = data->reg_cache[ISL29003_REG_COMMAND]; 151 152 return ~cmdreg & ISL29003_ADC_PD; 153 } 154 155 static int isl29003_get_adc_value(struct i2c_client *client) 156 { 157 struct isl29003_data *data = i2c_get_clientdata(client); 158 int lsb, msb, range, bitdepth; 159 160 mutex_lock(&data->lock); 161 lsb = i2c_smbus_read_byte_data(client, ISL29003_REG_LSB_SENSOR); 162 163 if (lsb < 0) { 164 mutex_unlock(&data->lock); 165 return lsb; 166 } 167 168 msb = i2c_smbus_read_byte_data(client, ISL29003_REG_MSB_SENSOR); 169 mutex_unlock(&data->lock); 170 171 if (msb < 0) 172 return msb; 173 174 range = isl29003_get_range(client); 175 bitdepth = (4 - isl29003_get_resolution(client)) * 4; 176 return (((msb << 8) | lsb) * gain_range[range]) >> bitdepth; 177 } 178 179 /* 180 * sysfs layer 181 */ 182 183 /* range */ 184 static ssize_t isl29003_show_range(struct device *dev, 185 struct device_attribute *attr, char *buf) 186 { 187 struct i2c_client *client = to_i2c_client(dev); 188 189 return sprintf(buf, "%i\n", isl29003_get_range(client)); 190 } 191 192 static ssize_t isl29003_store_range(struct device *dev, 193 struct device_attribute *attr, 194 const char *buf, size_t count) 195 { 196 struct i2c_client *client = to_i2c_client(dev); 197 unsigned long val; 198 int ret; 199 200 ret = kstrtoul(buf, 10, &val); 201 if (ret) 202 return ret; 203 204 if (val > 3) 205 return -EINVAL; 206 207 ret = isl29003_set_range(client, val); 208 if (ret < 0) 209 return ret; 210 211 return count; 212 } 213 214 static DEVICE_ATTR(range, S_IWUSR | S_IRUGO, 215 isl29003_show_range, isl29003_store_range); 216 217 218 /* resolution */ 219 static ssize_t isl29003_show_resolution(struct device *dev, 220 struct device_attribute *attr, 221 char *buf) 222 { 223 struct i2c_client *client = to_i2c_client(dev); 224 225 return sprintf(buf, "%d\n", isl29003_get_resolution(client)); 226 } 227 228 static ssize_t isl29003_store_resolution(struct device *dev, 229 struct device_attribute *attr, 230 const char *buf, size_t count) 231 { 232 struct i2c_client *client = to_i2c_client(dev); 233 unsigned long val; 234 int ret; 235 236 ret = kstrtoul(buf, 10, &val); 237 if (ret) 238 return ret; 239 240 if (val > 3) 241 return -EINVAL; 242 243 ret = isl29003_set_resolution(client, val); 244 if (ret < 0) 245 return ret; 246 247 return count; 248 } 249 250 static DEVICE_ATTR(resolution, S_IWUSR | S_IRUGO, 251 isl29003_show_resolution, isl29003_store_resolution); 252 253 /* mode */ 254 static ssize_t isl29003_show_mode(struct device *dev, 255 struct device_attribute *attr, char *buf) 256 { 257 struct i2c_client *client = to_i2c_client(dev); 258 259 return sprintf(buf, "%d\n", isl29003_get_mode(client)); 260 } 261 262 static ssize_t isl29003_store_mode(struct device *dev, 263 struct device_attribute *attr, const char *buf, size_t count) 264 { 265 struct i2c_client *client = to_i2c_client(dev); 266 unsigned long val; 267 int ret; 268 269 ret = kstrtoul(buf, 10, &val); 270 if (ret) 271 return ret; 272 273 if (val > 2) 274 return -EINVAL; 275 276 ret = isl29003_set_mode(client, val); 277 if (ret < 0) 278 return ret; 279 280 return count; 281 } 282 283 static DEVICE_ATTR(mode, S_IWUSR | S_IRUGO, 284 isl29003_show_mode, isl29003_store_mode); 285 286 287 /* power state */ 288 static ssize_t isl29003_show_power_state(struct device *dev, 289 struct device_attribute *attr, 290 char *buf) 291 { 292 struct i2c_client *client = to_i2c_client(dev); 293 294 return sprintf(buf, "%d\n", isl29003_get_power_state(client)); 295 } 296 297 static ssize_t isl29003_store_power_state(struct device *dev, 298 struct device_attribute *attr, 299 const char *buf, size_t count) 300 { 301 struct i2c_client *client = to_i2c_client(dev); 302 unsigned long val; 303 int ret; 304 305 ret = kstrtoul(buf, 10, &val); 306 if (ret) 307 return ret; 308 309 if (val > 1) 310 return -EINVAL; 311 312 ret = isl29003_set_power_state(client, val); 313 return ret ? ret : count; 314 } 315 316 static DEVICE_ATTR(power_state, S_IWUSR | S_IRUGO, 317 isl29003_show_power_state, isl29003_store_power_state); 318 319 320 /* lux */ 321 static ssize_t isl29003_show_lux(struct device *dev, 322 struct device_attribute *attr, char *buf) 323 { 324 struct i2c_client *client = to_i2c_client(dev); 325 326 /* No LUX data if not operational */ 327 if (!isl29003_get_power_state(client)) 328 return -EBUSY; 329 330 return sprintf(buf, "%d\n", isl29003_get_adc_value(client)); 331 } 332 333 static DEVICE_ATTR(lux, S_IRUGO, isl29003_show_lux, NULL); 334 335 static struct attribute *isl29003_attributes[] = { 336 &dev_attr_range.attr, 337 &dev_attr_resolution.attr, 338 &dev_attr_mode.attr, 339 &dev_attr_power_state.attr, 340 &dev_attr_lux.attr, 341 NULL 342 }; 343 344 static const struct attribute_group isl29003_attr_group = { 345 .attrs = isl29003_attributes, 346 }; 347 348 static int isl29003_init_client(struct i2c_client *client) 349 { 350 struct isl29003_data *data = i2c_get_clientdata(client); 351 int i; 352 353 /* read all the registers once to fill the cache. 354 * if one of the reads fails, we consider the init failed */ 355 for (i = 0; i < ARRAY_SIZE(data->reg_cache); i++) { 356 int v = i2c_smbus_read_byte_data(client, i); 357 358 if (v < 0) 359 return -ENODEV; 360 361 data->reg_cache[i] = v; 362 } 363 364 /* set defaults */ 365 isl29003_set_range(client, 0); 366 isl29003_set_resolution(client, 0); 367 isl29003_set_mode(client, 0); 368 isl29003_set_power_state(client, 0); 369 370 return 0; 371 } 372 373 /* 374 * I2C layer 375 */ 376 377 static int isl29003_probe(struct i2c_client *client, 378 const struct i2c_device_id *id) 379 { 380 struct i2c_adapter *adapter = client->adapter; 381 struct isl29003_data *data; 382 int err = 0; 383 384 if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE)) 385 return -EIO; 386 387 data = kzalloc(sizeof(struct isl29003_data), GFP_KERNEL); 388 if (!data) 389 return -ENOMEM; 390 391 data->client = client; 392 i2c_set_clientdata(client, data); 393 mutex_init(&data->lock); 394 395 /* initialize the ISL29003 chip */ 396 err = isl29003_init_client(client); 397 if (err) 398 goto exit_kfree; 399 400 /* register sysfs hooks */ 401 err = sysfs_create_group(&client->dev.kobj, &isl29003_attr_group); 402 if (err) 403 goto exit_kfree; 404 405 dev_info(&client->dev, "driver version %s enabled\n", DRIVER_VERSION); 406 return 0; 407 408 exit_kfree: 409 kfree(data); 410 return err; 411 } 412 413 static int isl29003_remove(struct i2c_client *client) 414 { 415 sysfs_remove_group(&client->dev.kobj, &isl29003_attr_group); 416 isl29003_set_power_state(client, 0); 417 kfree(i2c_get_clientdata(client)); 418 return 0; 419 } 420 421 #ifdef CONFIG_PM_SLEEP 422 static int isl29003_suspend(struct device *dev) 423 { 424 struct i2c_client *client = to_i2c_client(dev); 425 struct isl29003_data *data = i2c_get_clientdata(client); 426 427 data->power_state_before_suspend = isl29003_get_power_state(client); 428 return isl29003_set_power_state(client, 0); 429 } 430 431 static int isl29003_resume(struct device *dev) 432 { 433 int i; 434 struct i2c_client *client = to_i2c_client(dev); 435 struct isl29003_data *data = i2c_get_clientdata(client); 436 437 /* restore registers from cache */ 438 for (i = 0; i < ARRAY_SIZE(data->reg_cache); i++) 439 if (i2c_smbus_write_byte_data(client, i, data->reg_cache[i])) 440 return -EIO; 441 442 return isl29003_set_power_state(client, 443 data->power_state_before_suspend); 444 } 445 446 static SIMPLE_DEV_PM_OPS(isl29003_pm_ops, isl29003_suspend, isl29003_resume); 447 #define ISL29003_PM_OPS (&isl29003_pm_ops) 448 449 #else 450 #define ISL29003_PM_OPS NULL 451 #endif /* CONFIG_PM_SLEEP */ 452 453 static const struct i2c_device_id isl29003_id[] = { 454 { "isl29003", 0 }, 455 {} 456 }; 457 MODULE_DEVICE_TABLE(i2c, isl29003_id); 458 459 static struct i2c_driver isl29003_driver = { 460 .driver = { 461 .name = ISL29003_DRV_NAME, 462 .pm = ISL29003_PM_OPS, 463 }, 464 .probe = isl29003_probe, 465 .remove = isl29003_remove, 466 .id_table = isl29003_id, 467 }; 468 469 module_i2c_driver(isl29003_driver); 470 471 MODULE_AUTHOR("Daniel Mack <daniel@caiaq.de>"); 472 MODULE_DESCRIPTION("ISL29003 ambient light sensor driver"); 473 MODULE_LICENSE("GPL v2"); 474 MODULE_VERSION(DRIVER_VERSION); 475