1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * IIO driver for Lite-On LTR390 ALS and UV sensor
4 * (7-bit I2C slave address 0x53)
6 * Based on the work of:
7 * Shreeya Patel and Shi Zhigang (LTRF216 Driver)
9 * Copyright (C) 2023 Anshul Dalal <anshulusr@gmail.com>
12 * https://optoelectronics.liteon.com/upload/download/DS86-2015-0004/LTR-390UV_Final_%20DS_V1%201.pdf
15 * - Support for configurable gain and resolution
16 * - Sensor suspend/resume support
17 * - Add support for reading the ALS
21 #include <linux/bitfield.h>
22 #include <linux/device.h>
23 #include <linux/i2c.h>
24 #include <linux/irq.h>
25 #include <linux/interrupt.h>
26 #include <linux/math.h>
27 #include <linux/module.h>
28 #include <linux/mutex.h>
29 #include <linux/regmap.h>
31 #include <linux/iio/iio.h>
32 #include <linux/iio/events.h>
34 #include <linux/unaligned.h>
36 #define LTR390_MAIN_CTRL 0x00
37 #define LTR390_ALS_UVS_MEAS_RATE 0x04
38 #define LTR390_ALS_UVS_GAIN 0x05
39 #define LTR390_PART_ID 0x06
40 #define LTR390_MAIN_STATUS 0x07
41 #define LTR390_ALS_DATA 0x0D
42 #define LTR390_UVS_DATA 0x10
43 #define LTR390_INT_CFG 0x19
44 #define LTR390_INT_PST 0x1A
45 #define LTR390_THRESH_UP 0x21
46 #define LTR390_THRESH_LOW 0x24
48 #define LTR390_PART_NUMBER_ID 0xb
49 #define LTR390_ALS_UVS_GAIN_MASK GENMASK(2, 0)
50 #define LTR390_ALS_UVS_MEAS_RATE_MASK GENMASK(2, 0)
51 #define LTR390_ALS_UVS_INT_TIME_MASK GENMASK(6, 4)
52 #define LTR390_ALS_UVS_INT_TIME(x) FIELD_PREP(LTR390_ALS_UVS_INT_TIME_MASK, (x))
53 #define LTR390_INT_PST_MASK GENMASK(7, 4)
54 #define LTR390_INT_PST_VAL(x) FIELD_PREP(LTR390_INT_PST_MASK, (x))
56 #define LTR390_SW_RESET BIT(4)
57 #define LTR390_UVS_MODE BIT(3)
58 #define LTR390_SENSOR_ENABLE BIT(1)
59 #define LTR390_LS_INT_EN BIT(2)
60 #define LTR390_LS_INT_SEL_UVS BIT(5)
62 #define LTR390_FRACTIONAL_PRECISION 100
65 * At 20-bit resolution (integration time: 400ms) and 18x gain, 2300 counts of
66 * the sensor are equal to 1 UV Index [Datasheet Page#8].
68 * For the default resolution of 18-bit (integration time: 100ms) and default
69 * gain of 3x, the counts/uvi are calculated as follows:
70 * 2300 / ((3/18) * (100/400)) = 95.83
72 #define LTR390_COUNTS_PER_UVI 96
75 * Window Factor is needed when the device is under Window glass with coated
76 * tinted ink. This is to compensate for the light loss due to the lower
77 * transmission rate of the window glass and helps * in calculating lux.
79 #define LTR390_WINDOW_FACTOR 1
86 enum ltr390_meas_rate
{
92 struct regmap
*regmap
;
93 struct i2c_client
*client
;
94 /* Protects device from simulataneous reads */
96 enum ltr390_mode mode
;
101 static const struct regmap_config ltr390_regmap_config
= {
108 /* Sampling frequency is in mili Hz and mili Seconds */
109 static const int ltr390_samp_freq_table
[][2] = {
112 [2] = { 10000, 100 },
115 [5] = { 1000, 1000 },
120 static int ltr390_register_read(struct ltr390_data
*data
, u8 register_address
)
122 struct device
*dev
= &data
->client
->dev
;
124 u8 recieve_buffer
[3];
126 ret
= regmap_bulk_read(data
->regmap
, register_address
, recieve_buffer
,
127 sizeof(recieve_buffer
));
129 dev_err(dev
, "failed to read measurement data");
133 return get_unaligned_le24(recieve_buffer
);
136 static int ltr390_set_mode(struct ltr390_data
*data
, enum ltr390_mode mode
)
140 if (data
->mode
== mode
)
144 case LTR390_SET_ALS_MODE
:
145 ret
= regmap_clear_bits(data
->regmap
, LTR390_MAIN_CTRL
, LTR390_UVS_MODE
);
148 case LTR390_SET_UVS_MODE
:
149 ret
= regmap_set_bits(data
->regmap
, LTR390_MAIN_CTRL
, LTR390_UVS_MODE
);
160 static int ltr390_counts_per_uvi(struct ltr390_data
*data
)
162 const int orig_gain
= 18;
163 const int orig_int_time
= 400;
165 return DIV_ROUND_CLOSEST(23 * data
->gain
* data
->int_time_us
, 10 * orig_gain
* orig_int_time
);
168 static int ltr390_get_samp_freq_or_period(struct ltr390_data
*data
,
169 enum ltr390_meas_rate option
)
173 ret
= regmap_read(data
->regmap
, LTR390_ALS_UVS_MEAS_RATE
, &value
);
176 value
= FIELD_GET(LTR390_ALS_UVS_MEAS_RATE_MASK
, value
);
178 return ltr390_samp_freq_table
[value
][option
];
181 static int ltr390_read_raw(struct iio_dev
*iio_device
,
182 struct iio_chan_spec
const *chan
, int *val
,
183 int *val2
, long mask
)
186 struct ltr390_data
*data
= iio_priv(iio_device
);
188 guard(mutex
)(&data
->lock
);
190 case IIO_CHAN_INFO_RAW
:
191 switch (chan
->type
) {
193 ret
= ltr390_set_mode(data
, LTR390_SET_UVS_MODE
);
197 ret
= ltr390_register_read(data
, LTR390_UVS_DATA
);
203 ret
= ltr390_set_mode(data
, LTR390_SET_ALS_MODE
);
207 ret
= ltr390_register_read(data
, LTR390_ALS_DATA
);
217 case IIO_CHAN_INFO_SCALE
:
218 switch (chan
->type
) {
220 *val
= LTR390_WINDOW_FACTOR
* LTR390_FRACTIONAL_PRECISION
;
221 *val2
= ltr390_counts_per_uvi(data
);
222 return IIO_VAL_FRACTIONAL
;
225 *val
= LTR390_WINDOW_FACTOR
* 6 * 100;
226 *val2
= data
->gain
* data
->int_time_us
;
227 return IIO_VAL_FRACTIONAL
;
233 case IIO_CHAN_INFO_INT_TIME
:
234 *val
= data
->int_time_us
;
237 case IIO_CHAN_INFO_SAMP_FREQ
:
238 *val
= ltr390_get_samp_freq_or_period(data
, LTR390_GET_FREQ
);
246 /* integration time in us */
247 static const int ltr390_int_time_map_us
[] = { 400000, 200000, 100000, 50000, 25000, 12500 };
248 static const int ltr390_gain_map
[] = { 1, 3, 6, 9, 18 };
249 static const int ltr390_freq_map
[] = { 40000, 20000, 10000, 5000, 2000, 1000, 500, 500 };
251 static const struct iio_event_spec ltr390_event_spec
[] = {
253 .type
= IIO_EV_TYPE_THRESH
,
254 .dir
= IIO_EV_DIR_RISING
,
255 .mask_separate
= BIT(IIO_EV_INFO_VALUE
),
257 .type
= IIO_EV_TYPE_THRESH
,
258 .dir
= IIO_EV_DIR_FALLING
,
259 .mask_separate
= BIT(IIO_EV_INFO_VALUE
),
261 .type
= IIO_EV_TYPE_THRESH
,
262 .dir
= IIO_EV_DIR_EITHER
,
263 .mask_separate
= BIT(IIO_EV_INFO_ENABLE
) |
264 BIT(IIO_EV_INFO_PERIOD
),
268 static const struct iio_chan_spec ltr390_channels
[] = {
273 .info_mask_separate
= BIT(IIO_CHAN_INFO_RAW
) | BIT(IIO_CHAN_INFO_SCALE
),
274 .info_mask_shared_by_all
= BIT(IIO_CHAN_INFO_INT_TIME
) | BIT(IIO_CHAN_INFO_SAMP_FREQ
),
275 .info_mask_shared_by_all_available
= BIT(IIO_CHAN_INFO_INT_TIME
) |
276 BIT(IIO_CHAN_INFO_SCALE
) |
277 BIT(IIO_CHAN_INFO_SAMP_FREQ
),
278 .event_spec
= ltr390_event_spec
,
279 .num_event_specs
= ARRAY_SIZE(ltr390_event_spec
),
285 .info_mask_separate
= BIT(IIO_CHAN_INFO_RAW
) | BIT(IIO_CHAN_INFO_SCALE
),
286 .info_mask_shared_by_all
= BIT(IIO_CHAN_INFO_INT_TIME
) | BIT(IIO_CHAN_INFO_SAMP_FREQ
),
287 .info_mask_shared_by_all_available
= BIT(IIO_CHAN_INFO_INT_TIME
) |
288 BIT(IIO_CHAN_INFO_SCALE
) |
289 BIT(IIO_CHAN_INFO_SAMP_FREQ
),
290 .event_spec
= ltr390_event_spec
,
291 .num_event_specs
= ARRAY_SIZE(ltr390_event_spec
),
295 static int ltr390_set_gain(struct ltr390_data
*data
, int val
)
299 for (idx
= 0; idx
< ARRAY_SIZE(ltr390_gain_map
); idx
++) {
300 if (ltr390_gain_map
[idx
] != val
)
303 guard(mutex
)(&data
->lock
);
304 ret
= regmap_update_bits(data
->regmap
,
306 LTR390_ALS_UVS_GAIN_MASK
, idx
);
310 data
->gain
= ltr390_gain_map
[idx
];
317 static int ltr390_set_int_time(struct ltr390_data
*data
, int val
)
321 for (idx
= 0; idx
< ARRAY_SIZE(ltr390_int_time_map_us
); idx
++) {
322 if (ltr390_int_time_map_us
[idx
] != val
)
325 guard(mutex
)(&data
->lock
);
326 ret
= regmap_update_bits(data
->regmap
,
327 LTR390_ALS_UVS_MEAS_RATE
,
328 LTR390_ALS_UVS_INT_TIME_MASK
,
329 LTR390_ALS_UVS_INT_TIME(idx
));
333 data
->int_time_us
= ltr390_int_time_map_us
[idx
];
340 static int ltr390_set_samp_freq(struct ltr390_data
*data
, int val
)
344 for (idx
= 0; idx
< ARRAY_SIZE(ltr390_samp_freq_table
); idx
++) {
345 if (ltr390_samp_freq_table
[idx
][0] != val
)
348 guard(mutex
)(&data
->lock
);
349 return regmap_update_bits(data
->regmap
,
350 LTR390_ALS_UVS_MEAS_RATE
,
351 LTR390_ALS_UVS_MEAS_RATE_MASK
, idx
);
357 static int ltr390_read_avail(struct iio_dev
*indio_dev
, struct iio_chan_spec
const *chan
,
358 const int **vals
, int *type
, int *length
, long mask
)
361 case IIO_CHAN_INFO_SCALE
:
362 *length
= ARRAY_SIZE(ltr390_gain_map
);
364 *vals
= ltr390_gain_map
;
365 return IIO_AVAIL_LIST
;
366 case IIO_CHAN_INFO_INT_TIME
:
367 *length
= ARRAY_SIZE(ltr390_int_time_map_us
);
369 *vals
= ltr390_int_time_map_us
;
370 return IIO_AVAIL_LIST
;
371 case IIO_CHAN_INFO_SAMP_FREQ
:
372 *length
= ARRAY_SIZE(ltr390_freq_map
);
374 *vals
= ltr390_freq_map
;
375 return IIO_AVAIL_LIST
;
381 static int ltr390_write_raw(struct iio_dev
*indio_dev
, struct iio_chan_spec
const *chan
,
382 int val
, int val2
, long mask
)
384 struct ltr390_data
*data
= iio_priv(indio_dev
);
387 case IIO_CHAN_INFO_SCALE
:
391 return ltr390_set_gain(data
, val
);
393 case IIO_CHAN_INFO_INT_TIME
:
397 return ltr390_set_int_time(data
, val
);
399 case IIO_CHAN_INFO_SAMP_FREQ
:
403 return ltr390_set_samp_freq(data
, val
);
410 static int ltr390_read_intr_prst(struct ltr390_data
*data
, int *val
)
412 int ret
, prst
, samp_period
;
414 samp_period
= ltr390_get_samp_freq_or_period(data
, LTR390_GET_PERIOD
);
415 ret
= regmap_read(data
->regmap
, LTR390_INT_PST
, &prst
);
418 *val
= prst
* samp_period
;
423 static int ltr390_write_intr_prst(struct ltr390_data
*data
, int val
)
425 int ret
, samp_period
, new_val
;
427 samp_period
= ltr390_get_samp_freq_or_period(data
, LTR390_GET_PERIOD
);
429 /* persist period should be greater than or equal to samp period */
430 if (val
< samp_period
)
433 new_val
= DIV_ROUND_UP(val
, samp_period
);
434 if (new_val
< 0 || new_val
> 0x0f)
437 guard(mutex
)(&data
->lock
);
438 ret
= regmap_update_bits(data
->regmap
,
441 LTR390_INT_PST_VAL(new_val
));
448 static int ltr390_read_threshold(struct iio_dev
*indio_dev
,
449 enum iio_event_direction dir
,
452 struct ltr390_data
*data
= iio_priv(indio_dev
);
456 case IIO_EV_DIR_RISING
:
457 ret
= ltr390_register_read(data
, LTR390_THRESH_UP
);
463 case IIO_EV_DIR_FALLING
:
464 ret
= ltr390_register_read(data
, LTR390_THRESH_LOW
);
474 static int ltr390_write_threshold(struct iio_dev
*indio_dev
,
475 enum iio_event_direction dir
,
478 struct ltr390_data
*data
= iio_priv(indio_dev
);
480 guard(mutex
)(&data
->lock
);
482 case IIO_EV_DIR_RISING
:
483 return regmap_bulk_write(data
->regmap
, LTR390_THRESH_UP
, &val
, 3);
485 case IIO_EV_DIR_FALLING
:
486 return regmap_bulk_write(data
->regmap
, LTR390_THRESH_LOW
, &val
, 3);
493 static int ltr390_read_event_value(struct iio_dev
*indio_dev
,
494 const struct iio_chan_spec
*chan
,
495 enum iio_event_type type
,
496 enum iio_event_direction dir
,
497 enum iio_event_info info
,
501 case IIO_EV_INFO_VALUE
:
502 return ltr390_read_threshold(indio_dev
, dir
, val
, val2
);
504 case IIO_EV_INFO_PERIOD
:
505 return ltr390_read_intr_prst(iio_priv(indio_dev
), val
);
512 static int ltr390_write_event_value(struct iio_dev
*indio_dev
,
513 const struct iio_chan_spec
*chan
,
514 enum iio_event_type type
,
515 enum iio_event_direction dir
,
516 enum iio_event_info info
,
520 case IIO_EV_INFO_VALUE
:
524 return ltr390_write_threshold(indio_dev
, dir
, val
, val2
);
526 case IIO_EV_INFO_PERIOD
:
530 return ltr390_write_intr_prst(iio_priv(indio_dev
), val
);
537 static int ltr390_read_event_config(struct iio_dev
*indio_dev
,
538 const struct iio_chan_spec
*chan
,
539 enum iio_event_type type
,
540 enum iio_event_direction dir
)
542 struct ltr390_data
*data
= iio_priv(indio_dev
);
545 ret
= regmap_read(data
->regmap
, LTR390_INT_CFG
, &status
);
549 return FIELD_GET(LTR390_LS_INT_EN
, status
);
552 static int ltr390_write_event_config(struct iio_dev
*indio_dev
,
553 const struct iio_chan_spec
*chan
,
554 enum iio_event_type type
,
555 enum iio_event_direction dir
,
558 struct ltr390_data
*data
= iio_priv(indio_dev
);
562 return regmap_clear_bits(data
->regmap
, LTR390_INT_CFG
, LTR390_LS_INT_EN
);
564 guard(mutex
)(&data
->lock
);
565 ret
= regmap_set_bits(data
->regmap
, LTR390_INT_CFG
, LTR390_LS_INT_EN
);
569 switch (chan
->type
) {
571 ret
= ltr390_set_mode(data
, LTR390_SET_ALS_MODE
);
575 return regmap_clear_bits(data
->regmap
, LTR390_INT_CFG
, LTR390_LS_INT_SEL_UVS
);
578 ret
= ltr390_set_mode(data
, LTR390_SET_UVS_MODE
);
582 return regmap_set_bits(data
->regmap
, LTR390_INT_CFG
, LTR390_LS_INT_SEL_UVS
);
589 static const struct iio_info ltr390_info
= {
590 .read_raw
= ltr390_read_raw
,
591 .write_raw
= ltr390_write_raw
,
592 .read_avail
= ltr390_read_avail
,
593 .read_event_value
= ltr390_read_event_value
,
594 .read_event_config
= ltr390_read_event_config
,
595 .write_event_value
= ltr390_write_event_value
,
596 .write_event_config
= ltr390_write_event_config
,
599 static irqreturn_t
ltr390_interrupt_handler(int irq
, void *private)
601 struct iio_dev
*indio_dev
= private;
602 struct ltr390_data
*data
= iio_priv(indio_dev
);
605 /* Reading the status register to clear the interrupt flag, Datasheet pg: 17*/
606 ret
= regmap_read(data
->regmap
, LTR390_MAIN_STATUS
, &status
);
610 switch (data
->mode
) {
611 case LTR390_SET_ALS_MODE
:
612 iio_push_event(indio_dev
,
613 IIO_UNMOD_EVENT_CODE(IIO_LIGHT
, 0,
616 iio_get_time_ns(indio_dev
));
619 case LTR390_SET_UVS_MODE
:
620 iio_push_event(indio_dev
,
621 IIO_UNMOD_EVENT_CODE(IIO_UVINDEX
, 0,
624 iio_get_time_ns(indio_dev
));
631 static int ltr390_probe(struct i2c_client
*client
)
633 struct ltr390_data
*data
;
634 struct iio_dev
*indio_dev
;
636 int ret
, part_number
;
639 indio_dev
= devm_iio_device_alloc(dev
, sizeof(*data
));
643 data
= iio_priv(indio_dev
);
645 data
->regmap
= devm_regmap_init_i2c(client
, <r390_regmap_config
);
646 if (IS_ERR(data
->regmap
))
647 return dev_err_probe(dev
, PTR_ERR(data
->regmap
),
648 "regmap initialization failed\n");
650 data
->client
= client
;
651 /* default value of integration time from pg: 15 of the datasheet */
652 data
->int_time_us
= 100000;
653 /* default value of gain from pg: 16 of the datasheet */
655 /* default mode for ltr390 is ALS mode */
656 data
->mode
= LTR390_SET_ALS_MODE
;
658 mutex_init(&data
->lock
);
660 indio_dev
->info
= <r390_info
;
661 indio_dev
->channels
= ltr390_channels
;
662 indio_dev
->num_channels
= ARRAY_SIZE(ltr390_channels
);
663 indio_dev
->name
= "ltr390";
665 ret
= regmap_read(data
->regmap
, LTR390_PART_ID
, &part_number
);
667 return dev_err_probe(dev
, ret
,
668 "failed to get sensor's part id\n");
669 /* Lower 4 bits of `part_number` change with hardware revisions */
670 if (part_number
>> 4 != LTR390_PART_NUMBER_ID
)
671 dev_info(dev
, "received invalid product id: 0x%x", part_number
);
672 dev_dbg(dev
, "LTR390, product id: 0x%x\n", part_number
);
674 /* reset sensor, chip fails to respond to this, so ignore any errors */
675 regmap_set_bits(data
->regmap
, LTR390_MAIN_CTRL
, LTR390_SW_RESET
);
677 /* Wait for the registers to reset before proceeding */
678 usleep_range(1000, 2000);
680 ret
= regmap_set_bits(data
->regmap
, LTR390_MAIN_CTRL
, LTR390_SENSOR_ENABLE
);
682 return dev_err_probe(dev
, ret
, "failed to enable the sensor\n");
685 ret
= devm_request_threaded_irq(dev
, client
->irq
,
686 NULL
, ltr390_interrupt_handler
,
688 "ltr390_thresh_event",
691 return dev_err_probe(dev
, ret
,
692 "request irq (%d) failed\n", client
->irq
);
695 return devm_iio_device_register(dev
, indio_dev
);
698 static int ltr390_suspend(struct device
*dev
)
700 struct iio_dev
*indio_dev
= dev_get_drvdata(dev
);
701 struct ltr390_data
*data
= iio_priv(indio_dev
);
703 return regmap_clear_bits(data
->regmap
, LTR390_MAIN_CTRL
,
704 LTR390_SENSOR_ENABLE
);
707 static int ltr390_resume(struct device
*dev
)
709 struct iio_dev
*indio_dev
= dev_get_drvdata(dev
);
710 struct ltr390_data
*data
= iio_priv(indio_dev
);
712 return regmap_set_bits(data
->regmap
, LTR390_MAIN_CTRL
,
713 LTR390_SENSOR_ENABLE
);
716 static DEFINE_SIMPLE_DEV_PM_OPS(ltr390_pm_ops
, ltr390_suspend
, ltr390_resume
);
718 static const struct i2c_device_id ltr390_id
[] = {
722 MODULE_DEVICE_TABLE(i2c
, ltr390_id
);
724 static const struct of_device_id ltr390_of_table
[] = {
725 { .compatible
= "liteon,ltr390" },
728 MODULE_DEVICE_TABLE(of
, ltr390_of_table
);
730 static struct i2c_driver ltr390_driver
= {
733 .of_match_table
= ltr390_of_table
,
734 .pm
= pm_sleep_ptr(<r390_pm_ops
),
736 .probe
= ltr390_probe
,
737 .id_table
= ltr390_id
,
739 module_i2c_driver(ltr390_driver
);
741 MODULE_AUTHOR("Anshul Dalal <anshulusr@gmail.com>");
742 MODULE_DESCRIPTION("Lite-On LTR390 ALS and UV sensor Driver");
743 MODULE_LICENSE("GPL");