1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * max44009.c - Support for MAX44009 Ambient Light Sensor 4 * 5 * Copyright (c) 2019 Robert Eshleman <bobbyeshleman@gmail.com> 6 * 7 * Datasheet: https://datasheets.maximintegrated.com/en/ds/MAX44009.pdf 8 * 9 * TODO: Support continuous mode and configuring from manual mode to 10 * automatic mode. 11 * 12 * Default I2C address: 0x4a 13 */ 14 15 #include <linux/init.h> 16 #include <linux/kernel.h> 17 #include <linux/bits.h> 18 #include <linux/i2c.h> 19 #include <linux/iio/events.h> 20 #include <linux/iio/iio.h> 21 #include <linux/iio/sysfs.h> 22 #include <linux/interrupt.h> 23 #include <linux/module.h> 24 #include <linux/util_macros.h> 25 26 #define MAX44009_DRV_NAME "max44009" 27 28 /* Registers in datasheet order */ 29 #define MAX44009_REG_INT_STATUS 0x0 30 #define MAX44009_REG_INT_EN 0x1 31 #define MAX44009_REG_CFG 0x2 32 #define MAX44009_REG_LUX_HI 0x3 33 #define MAX44009_REG_LUX_LO 0x4 34 #define MAX44009_REG_UPPER_THR 0x5 35 #define MAX44009_REG_LOWER_THR 0x6 36 #define MAX44009_REG_THR_TIMER 0x7 37 38 #define MAX44009_CFG_TIM_MASK GENMASK(2, 0) 39 #define MAX44009_CFG_MAN_MODE_MASK BIT(6) 40 41 /* The maximum rising threshold for the max44009 */ 42 #define MAX44009_MAXIMUM_THRESHOLD 7520256 43 44 #define MAX44009_THRESH_EXP_MASK (0xf << 4) 45 #define MAX44009_THRESH_EXP_RSHIFT 4 46 #define MAX44009_THRESH_MANT_LSHIFT 4 47 #define MAX44009_THRESH_MANT_MASK 0xf 48 49 #define MAX44009_UPPER_THR_MINIMUM 15 50 51 /* The max44009 always scales raw readings by 0.045 and is non-configurable */ 52 #define MAX44009_SCALE_NUMERATOR 45 53 #define MAX44009_SCALE_DENOMINATOR 1000 54 55 /* The fixed-point fractional multiplier for de-scaling threshold values */ 56 #define MAX44009_FRACT_MULT 1000000 57 58 static const u32 max44009_int_time_ns_array[] = { 59 800000000, 60 400000000, 61 200000000, 62 100000000, 63 50000000, /* Manual mode only */ 64 25000000, /* Manual mode only */ 65 12500000, /* Manual mode only */ 66 6250000, /* Manual mode only */ 67 }; 68 69 static const char max44009_int_time_str[] = 70 "0.8 " 71 "0.4 " 72 "0.2 " 73 "0.1 " 74 "0.05 " 75 "0.025 " 76 "0.0125 " 77 "0.00625"; 78 79 struct max44009_data { 80 struct i2c_client *client; 81 struct mutex lock; 82 }; 83 84 static const struct iio_event_spec max44009_event_spec[] = { 85 { 86 .type = IIO_EV_TYPE_THRESH, 87 .dir = IIO_EV_DIR_RISING, 88 .mask_separate = BIT(IIO_EV_INFO_VALUE) | 89 BIT(IIO_EV_INFO_ENABLE), 90 }, 91 { 92 .type = IIO_EV_TYPE_THRESH, 93 .dir = IIO_EV_DIR_FALLING, 94 .mask_separate = BIT(IIO_EV_INFO_VALUE) | 95 BIT(IIO_EV_INFO_ENABLE), 96 }, 97 }; 98 99 static const struct iio_chan_spec max44009_channels[] = { 100 { 101 .type = IIO_LIGHT, 102 .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED) | 103 BIT(IIO_CHAN_INFO_INT_TIME), 104 .event_spec = max44009_event_spec, 105 .num_event_specs = ARRAY_SIZE(max44009_event_spec), 106 }, 107 }; 108 109 static int max44009_read_int_time(struct max44009_data *data) 110 { 111 112 int ret = i2c_smbus_read_byte_data(data->client, MAX44009_REG_CFG); 113 114 if (ret < 0) 115 return ret; 116 117 return max44009_int_time_ns_array[ret & MAX44009_CFG_TIM_MASK]; 118 } 119 120 static int max44009_write_int_time(struct max44009_data *data, 121 int val, int val2) 122 { 123 struct i2c_client *client = data->client; 124 int ret, int_time, config; 125 s64 ns; 126 127 ns = val * NSEC_PER_SEC + val2; 128 int_time = find_closest_descending( 129 ns, 130 max44009_int_time_ns_array, 131 ARRAY_SIZE(max44009_int_time_ns_array)); 132 133 ret = i2c_smbus_read_byte_data(client, MAX44009_REG_CFG); 134 if (ret < 0) 135 return ret; 136 137 config = ret; 138 config &= int_time; 139 140 /* 141 * To set the integration time, the device must also be in manual 142 * mode. 143 */ 144 config |= MAX44009_CFG_MAN_MODE_MASK; 145 146 return i2c_smbus_write_byte_data(client, MAX44009_REG_CFG, config); 147 } 148 149 static int max44009_write_raw(struct iio_dev *indio_dev, 150 struct iio_chan_spec const *chan, int val, 151 int val2, long mask) 152 { 153 struct max44009_data *data = iio_priv(indio_dev); 154 int ret; 155 156 if (mask == IIO_CHAN_INFO_INT_TIME && chan->type == IIO_LIGHT) { 157 mutex_lock(&data->lock); 158 ret = max44009_write_int_time(data, val, val2); 159 mutex_unlock(&data->lock); 160 return ret; 161 } 162 return -EINVAL; 163 } 164 165 static int max44009_write_raw_get_fmt(struct iio_dev *indio_dev, 166 struct iio_chan_spec const *chan, 167 long mask) 168 { 169 return IIO_VAL_INT_PLUS_NANO; 170 } 171 172 static int max44009_lux_raw(u8 hi, u8 lo) 173 { 174 int mantissa; 175 int exponent; 176 177 /* 178 * The mantissa consists of the low nibble of the Lux High Byte 179 * and the low nibble of the Lux Low Byte. 180 */ 181 mantissa = ((hi & 0xf) << 4) | (lo & 0xf); 182 183 /* The exponent byte is just the upper nibble of the Lux High Byte */ 184 exponent = (hi >> 4) & 0xf; 185 186 /* 187 * The exponent value is base 2 to the power of the raw exponent byte. 188 */ 189 exponent = 1 << exponent; 190 191 return exponent * mantissa; 192 } 193 194 #define MAX44009_READ_LUX_XFER_LEN (4) 195 196 static int max44009_read_lux_raw(struct max44009_data *data) 197 { 198 int ret; 199 u8 hireg = MAX44009_REG_LUX_HI; 200 u8 loreg = MAX44009_REG_LUX_LO; 201 u8 lo = 0; 202 u8 hi = 0; 203 204 struct i2c_msg msgs[] = { 205 { 206 .addr = data->client->addr, 207 .flags = 0, 208 .len = sizeof(hireg), 209 .buf = &hireg, 210 }, 211 { 212 .addr = data->client->addr, 213 .flags = I2C_M_RD, 214 .len = sizeof(hi), 215 .buf = &hi, 216 }, 217 { 218 .addr = data->client->addr, 219 .flags = 0, 220 .len = sizeof(loreg), 221 .buf = &loreg, 222 }, 223 { 224 .addr = data->client->addr, 225 .flags = I2C_M_RD, 226 .len = sizeof(lo), 227 .buf = &lo, 228 } 229 }; 230 231 /* 232 * Use i2c_transfer instead of smbus read because i2c_transfer 233 * does NOT use a stop bit between address write and data read. 234 * Using a stop bit causes disjoint upper/lower byte reads and 235 * reduces accuracy. 236 */ 237 ret = i2c_transfer(data->client->adapter, 238 msgs, MAX44009_READ_LUX_XFER_LEN); 239 240 if (ret != MAX44009_READ_LUX_XFER_LEN) 241 return -EIO; 242 243 return max44009_lux_raw(hi, lo); 244 } 245 246 static int max44009_read_raw(struct iio_dev *indio_dev, 247 struct iio_chan_spec const *chan, int *val, 248 int *val2, long mask) 249 { 250 struct max44009_data *data = iio_priv(indio_dev); 251 int lux_raw; 252 int ret; 253 254 switch (mask) { 255 case IIO_CHAN_INFO_PROCESSED: 256 switch (chan->type) { 257 case IIO_LIGHT: 258 ret = max44009_read_lux_raw(data); 259 if (ret < 0) 260 return ret; 261 lux_raw = ret; 262 263 *val = lux_raw * MAX44009_SCALE_NUMERATOR; 264 *val2 = MAX44009_SCALE_DENOMINATOR; 265 return IIO_VAL_FRACTIONAL; 266 default: 267 return -EINVAL; 268 } 269 case IIO_CHAN_INFO_INT_TIME: 270 switch (chan->type) { 271 case IIO_LIGHT: 272 ret = max44009_read_int_time(data); 273 if (ret < 0) 274 return ret; 275 276 *val2 = ret; 277 *val = 0; 278 return IIO_VAL_INT_PLUS_NANO; 279 default: 280 return -EINVAL; 281 } 282 default: 283 return -EINVAL; 284 } 285 } 286 287 static IIO_CONST_ATTR(illuminance_integration_time_available, 288 max44009_int_time_str); 289 290 static struct attribute *max44009_attributes[] = { 291 &iio_const_attr_illuminance_integration_time_available.dev_attr.attr, 292 NULL, 293 }; 294 295 static const struct attribute_group max44009_attribute_group = { 296 .attrs = max44009_attributes, 297 }; 298 299 static int max44009_threshold_byte_from_fraction(int integral, int fractional) 300 { 301 int mantissa, exp; 302 303 if ((integral <= 0 && fractional <= 0) || 304 integral > MAX44009_MAXIMUM_THRESHOLD || 305 (integral == MAX44009_MAXIMUM_THRESHOLD && fractional != 0)) 306 return -EINVAL; 307 308 /* Reverse scaling of fixed-point integral */ 309 mantissa = integral * MAX44009_SCALE_DENOMINATOR; 310 mantissa /= MAX44009_SCALE_NUMERATOR; 311 312 /* Reverse scaling of fixed-point fractional */ 313 mantissa += fractional / MAX44009_FRACT_MULT * 314 (MAX44009_SCALE_DENOMINATOR / MAX44009_SCALE_NUMERATOR); 315 316 for (exp = 0; mantissa > 0xff; exp++) 317 mantissa >>= 1; 318 319 mantissa >>= 4; 320 mantissa &= 0xf; 321 exp <<= 4; 322 323 return exp | mantissa; 324 } 325 326 static int max44009_get_thr_reg(enum iio_event_direction dir) 327 { 328 switch (dir) { 329 case IIO_EV_DIR_RISING: 330 return MAX44009_REG_UPPER_THR; 331 case IIO_EV_DIR_FALLING: 332 return MAX44009_REG_LOWER_THR; 333 default: 334 return -EINVAL; 335 } 336 } 337 338 static int max44009_write_event_value(struct iio_dev *indio_dev, 339 const struct iio_chan_spec *chan, 340 enum iio_event_type type, 341 enum iio_event_direction dir, 342 enum iio_event_info info, 343 int val, int val2) 344 { 345 struct max44009_data *data = iio_priv(indio_dev); 346 int reg, threshold; 347 348 if (info != IIO_EV_INFO_VALUE || chan->type != IIO_LIGHT) 349 return -EINVAL; 350 351 threshold = max44009_threshold_byte_from_fraction(val, val2); 352 if (threshold < 0) 353 return threshold; 354 355 reg = max44009_get_thr_reg(dir); 356 if (reg < 0) 357 return reg; 358 359 return i2c_smbus_write_byte_data(data->client, reg, threshold); 360 } 361 362 static int max44009_read_threshold(struct iio_dev *indio_dev, 363 enum iio_event_direction dir) 364 { 365 struct max44009_data *data = iio_priv(indio_dev); 366 int byte, reg; 367 int mantissa, exponent; 368 369 reg = max44009_get_thr_reg(dir); 370 if (reg < 0) 371 return reg; 372 373 byte = i2c_smbus_read_byte_data(data->client, reg); 374 if (byte < 0) 375 return byte; 376 377 mantissa = byte & MAX44009_THRESH_MANT_MASK; 378 mantissa <<= MAX44009_THRESH_MANT_LSHIFT; 379 380 /* 381 * To get the upper threshold, always adds the minimum upper threshold 382 * value to the shifted byte value (see datasheet). 383 */ 384 if (dir == IIO_EV_DIR_RISING) 385 mantissa += MAX44009_UPPER_THR_MINIMUM; 386 387 /* 388 * Exponent is base 2 to the power of the threshold exponent byte 389 * value 390 */ 391 exponent = byte & MAX44009_THRESH_EXP_MASK; 392 exponent >>= MAX44009_THRESH_EXP_RSHIFT; 393 394 return (1 << exponent) * mantissa; 395 } 396 397 static int max44009_read_event_value(struct iio_dev *indio_dev, 398 const struct iio_chan_spec *chan, 399 enum iio_event_type type, 400 enum iio_event_direction dir, 401 enum iio_event_info info, 402 int *val, int *val2) 403 { 404 int ret; 405 int threshold; 406 407 if (chan->type != IIO_LIGHT || type != IIO_EV_TYPE_THRESH) 408 return -EINVAL; 409 410 ret = max44009_read_threshold(indio_dev, dir); 411 if (ret < 0) 412 return ret; 413 threshold = ret; 414 415 *val = threshold * MAX44009_SCALE_NUMERATOR; 416 *val2 = MAX44009_SCALE_DENOMINATOR; 417 418 return IIO_VAL_FRACTIONAL; 419 } 420 421 static int max44009_write_event_config(struct iio_dev *indio_dev, 422 const struct iio_chan_spec *chan, 423 enum iio_event_type type, 424 enum iio_event_direction dir, 425 int state) 426 { 427 struct max44009_data *data = iio_priv(indio_dev); 428 int ret; 429 430 if (chan->type != IIO_LIGHT || type != IIO_EV_TYPE_THRESH) 431 return -EINVAL; 432 433 ret = i2c_smbus_write_byte_data(data->client, 434 MAX44009_REG_INT_EN, state); 435 if (ret < 0) 436 return ret; 437 438 /* 439 * Set device to trigger interrupt immediately upon exceeding 440 * the threshold limit. 441 */ 442 return i2c_smbus_write_byte_data(data->client, 443 MAX44009_REG_THR_TIMER, 0); 444 } 445 446 static int max44009_read_event_config(struct iio_dev *indio_dev, 447 const struct iio_chan_spec *chan, 448 enum iio_event_type type, 449 enum iio_event_direction dir) 450 { 451 struct max44009_data *data = iio_priv(indio_dev); 452 453 if (chan->type != IIO_LIGHT || type != IIO_EV_TYPE_THRESH) 454 return -EINVAL; 455 456 return i2c_smbus_read_byte_data(data->client, MAX44009_REG_INT_EN); 457 } 458 459 static const struct iio_info max44009_info = { 460 .read_raw = max44009_read_raw, 461 .write_raw = max44009_write_raw, 462 .write_raw_get_fmt = max44009_write_raw_get_fmt, 463 .read_event_value = max44009_read_event_value, 464 .read_event_config = max44009_read_event_config, 465 .write_event_value = max44009_write_event_value, 466 .write_event_config = max44009_write_event_config, 467 .attrs = &max44009_attribute_group, 468 }; 469 470 static irqreturn_t max44009_threaded_irq_handler(int irq, void *p) 471 { 472 struct iio_dev *indio_dev = p; 473 struct max44009_data *data = iio_priv(indio_dev); 474 int ret; 475 476 ret = i2c_smbus_read_byte_data(data->client, MAX44009_REG_INT_STATUS); 477 if (ret) { 478 iio_push_event(indio_dev, 479 IIO_UNMOD_EVENT_CODE(IIO_LIGHT, 0, 480 IIO_EV_TYPE_THRESH, 481 IIO_EV_DIR_EITHER), 482 iio_get_time_ns(indio_dev)); 483 484 return IRQ_HANDLED; 485 } 486 487 return IRQ_NONE; 488 } 489 490 static int max44009_probe(struct i2c_client *client) 491 { 492 struct max44009_data *data; 493 struct iio_dev *indio_dev; 494 int ret; 495 496 indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); 497 if (!indio_dev) 498 return -ENOMEM; 499 500 data = iio_priv(indio_dev); 501 i2c_set_clientdata(client, indio_dev); 502 data->client = client; 503 indio_dev->info = &max44009_info; 504 indio_dev->modes = INDIO_DIRECT_MODE; 505 indio_dev->name = MAX44009_DRV_NAME; 506 indio_dev->channels = max44009_channels; 507 indio_dev->num_channels = ARRAY_SIZE(max44009_channels); 508 mutex_init(&data->lock); 509 510 /* Clear any stale interrupt bit */ 511 ret = i2c_smbus_read_byte_data(client, MAX44009_REG_CFG); 512 if (ret < 0) 513 return ret; 514 515 if (client->irq > 0) { 516 ret = devm_request_threaded_irq(&client->dev, client->irq, 517 NULL, 518 max44009_threaded_irq_handler, 519 IRQF_TRIGGER_FALLING | 520 IRQF_ONESHOT | IRQF_SHARED, 521 "max44009_event", 522 indio_dev); 523 if (ret < 0) 524 return ret; 525 } 526 527 return devm_iio_device_register(&client->dev, indio_dev); 528 } 529 530 static const struct i2c_device_id max44009_id[] = { 531 { "max44009", 0 }, 532 { } 533 }; 534 MODULE_DEVICE_TABLE(i2c, max44009_id); 535 536 static struct i2c_driver max44009_driver = { 537 .driver = { 538 .name = MAX44009_DRV_NAME, 539 }, 540 .probe_new = max44009_probe, 541 .id_table = max44009_id, 542 }; 543 module_i2c_driver(max44009_driver); 544 545 static const struct of_device_id max44009_of_match[] = { 546 { .compatible = "maxim,max44009" }, 547 { } 548 }; 549 MODULE_DEVICE_TABLE(of, max44009_of_match); 550 551 MODULE_AUTHOR("Robert Eshleman <bobbyeshleman@gmail.com>"); 552 MODULE_LICENSE("GPL v2"); 553 MODULE_DESCRIPTION("MAX44009 ambient light sensor driver"); 554