18b0d4c40SAnshul Dalal // SPDX-License-Identifier: GPL-2.0-or-later
28b0d4c40SAnshul Dalal /*
38b0d4c40SAnshul Dalal * IIO driver for Lite-On LTR390 ALS and UV sensor
48b0d4c40SAnshul Dalal * (7-bit I2C slave address 0x53)
58b0d4c40SAnshul Dalal *
68b0d4c40SAnshul Dalal * Based on the work of:
78b0d4c40SAnshul Dalal * Shreeya Patel and Shi Zhigang (LTRF216 Driver)
88b0d4c40SAnshul Dalal *
98b0d4c40SAnshul Dalal * Copyright (C) 2023 Anshul Dalal <anshulusr@gmail.com>
108b0d4c40SAnshul Dalal *
118b0d4c40SAnshul Dalal * Datasheet:
128b0d4c40SAnshul Dalal * https://optoelectronics.liteon.com/upload/download/DS86-2015-0004/LTR-390UV_Final_%20DS_V1%201.pdf
138b0d4c40SAnshul Dalal *
148b0d4c40SAnshul Dalal * TODO:
158b0d4c40SAnshul Dalal * - Support for configurable gain and resolution
168b0d4c40SAnshul Dalal * - Sensor suspend/resume support
178b0d4c40SAnshul Dalal * - Add support for reading the ALS
188b0d4c40SAnshul Dalal * - Interrupt support
198b0d4c40SAnshul Dalal */
208b0d4c40SAnshul Dalal
218b0d4c40SAnshul Dalal #include <linux/i2c.h>
228b0d4c40SAnshul Dalal #include <linux/math.h>
238b0d4c40SAnshul Dalal #include <linux/module.h>
248b0d4c40SAnshul Dalal #include <linux/mutex.h>
258b0d4c40SAnshul Dalal #include <linux/regmap.h>
2613fad260SAbhash Jha #include <linux/bitfield.h>
278b0d4c40SAnshul Dalal
288b0d4c40SAnshul Dalal #include <linux/iio/iio.h>
298b0d4c40SAnshul Dalal
30*5f60d5f6SAl Viro #include <linux/unaligned.h>
318b0d4c40SAnshul Dalal
328b0d4c40SAnshul Dalal #define LTR390_MAIN_CTRL 0x00
3313fad260SAbhash Jha #define LTR390_ALS_UVS_MEAS_RATE 0x04
3413fad260SAbhash Jha #define LTR390_ALS_UVS_GAIN 0x05
358b0d4c40SAnshul Dalal #define LTR390_PART_ID 0x06
3613fad260SAbhash Jha #define LTR390_ALS_DATA 0x0D
378b0d4c40SAnshul Dalal #define LTR390_UVS_DATA 0x10
3813fad260SAbhash Jha #define LTR390_INT_CFG 0x19
3913fad260SAbhash Jha
4013fad260SAbhash Jha #define LTR390_PART_NUMBER_ID 0xb
4113fad260SAbhash Jha #define LTR390_ALS_UVS_GAIN_MASK 0x07
4213fad260SAbhash Jha #define LTR390_ALS_UVS_INT_TIME_MASK 0x70
4313fad260SAbhash Jha #define LTR390_ALS_UVS_INT_TIME(x) FIELD_PREP(LTR390_ALS_UVS_INT_TIME_MASK, (x))
448b0d4c40SAnshul Dalal
458b0d4c40SAnshul Dalal #define LTR390_SW_RESET BIT(4)
468b0d4c40SAnshul Dalal #define LTR390_UVS_MODE BIT(3)
478b0d4c40SAnshul Dalal #define LTR390_SENSOR_ENABLE BIT(1)
488b0d4c40SAnshul Dalal
494bd7e5ceSAbhash Jha #define LTR390_FRACTIONAL_PRECISION 100
504bd7e5ceSAbhash Jha
518b0d4c40SAnshul Dalal /*
528b0d4c40SAnshul Dalal * At 20-bit resolution (integration time: 400ms) and 18x gain, 2300 counts of
538b0d4c40SAnshul Dalal * the sensor are equal to 1 UV Index [Datasheet Page#8].
548b0d4c40SAnshul Dalal *
558b0d4c40SAnshul Dalal * For the default resolution of 18-bit (integration time: 100ms) and default
568b0d4c40SAnshul Dalal * gain of 3x, the counts/uvi are calculated as follows:
578b0d4c40SAnshul Dalal * 2300 / ((3/18) * (100/400)) = 95.83
588b0d4c40SAnshul Dalal */
598b0d4c40SAnshul Dalal #define LTR390_COUNTS_PER_UVI 96
608b0d4c40SAnshul Dalal
618b0d4c40SAnshul Dalal /*
628b0d4c40SAnshul Dalal * Window Factor is needed when the device is under Window glass with coated
638b0d4c40SAnshul Dalal * tinted ink. This is to compensate for the light loss due to the lower
648b0d4c40SAnshul Dalal * transmission rate of the window glass and helps * in calculating lux.
658b0d4c40SAnshul Dalal */
668b0d4c40SAnshul Dalal #define LTR390_WINDOW_FACTOR 1
678b0d4c40SAnshul Dalal
6814e0d914SAbhash Jha enum ltr390_mode {
6914e0d914SAbhash Jha LTR390_SET_ALS_MODE,
7014e0d914SAbhash Jha LTR390_SET_UVS_MODE,
7114e0d914SAbhash Jha };
7214e0d914SAbhash Jha
738b0d4c40SAnshul Dalal struct ltr390_data {
748b0d4c40SAnshul Dalal struct regmap *regmap;
758b0d4c40SAnshul Dalal struct i2c_client *client;
768b0d4c40SAnshul Dalal /* Protects device from simulataneous reads */
778b0d4c40SAnshul Dalal struct mutex lock;
7814e0d914SAbhash Jha enum ltr390_mode mode;
7913fad260SAbhash Jha int gain;
8013fad260SAbhash Jha int int_time_us;
818b0d4c40SAnshul Dalal };
828b0d4c40SAnshul Dalal
838b0d4c40SAnshul Dalal static const struct regmap_config ltr390_regmap_config = {
848b0d4c40SAnshul Dalal .name = "ltr390",
858b0d4c40SAnshul Dalal .reg_bits = 8,
868b0d4c40SAnshul Dalal .reg_stride = 1,
878b0d4c40SAnshul Dalal .val_bits = 8,
888b0d4c40SAnshul Dalal };
898b0d4c40SAnshul Dalal
ltr390_register_read(struct ltr390_data * data,u8 register_address)908b0d4c40SAnshul Dalal static int ltr390_register_read(struct ltr390_data *data, u8 register_address)
918b0d4c40SAnshul Dalal {
928b0d4c40SAnshul Dalal struct device *dev = &data->client->dev;
938b0d4c40SAnshul Dalal int ret;
948b0d4c40SAnshul Dalal u8 recieve_buffer[3];
958b0d4c40SAnshul Dalal
968b0d4c40SAnshul Dalal ret = regmap_bulk_read(data->regmap, register_address, recieve_buffer,
978b0d4c40SAnshul Dalal sizeof(recieve_buffer));
988b0d4c40SAnshul Dalal if (ret) {
998b0d4c40SAnshul Dalal dev_err(dev, "failed to read measurement data");
1008b0d4c40SAnshul Dalal return ret;
1018b0d4c40SAnshul Dalal }
1028b0d4c40SAnshul Dalal
1038b0d4c40SAnshul Dalal return get_unaligned_le24(recieve_buffer);
1048b0d4c40SAnshul Dalal }
1058b0d4c40SAnshul Dalal
ltr390_set_mode(struct ltr390_data * data,enum ltr390_mode mode)10614e0d914SAbhash Jha static int ltr390_set_mode(struct ltr390_data *data, enum ltr390_mode mode)
10714e0d914SAbhash Jha {
10814e0d914SAbhash Jha int ret;
10914e0d914SAbhash Jha
11014e0d914SAbhash Jha if (data->mode == mode)
11114e0d914SAbhash Jha return 0;
11214e0d914SAbhash Jha
11314e0d914SAbhash Jha switch (mode) {
11414e0d914SAbhash Jha case LTR390_SET_ALS_MODE:
11514e0d914SAbhash Jha ret = regmap_clear_bits(data->regmap, LTR390_MAIN_CTRL, LTR390_UVS_MODE);
11614e0d914SAbhash Jha break;
11714e0d914SAbhash Jha
11814e0d914SAbhash Jha case LTR390_SET_UVS_MODE:
11914e0d914SAbhash Jha ret = regmap_set_bits(data->regmap, LTR390_MAIN_CTRL, LTR390_UVS_MODE);
12014e0d914SAbhash Jha break;
12114e0d914SAbhash Jha }
12214e0d914SAbhash Jha
12314e0d914SAbhash Jha if (ret)
12414e0d914SAbhash Jha return ret;
12514e0d914SAbhash Jha
12614e0d914SAbhash Jha data->mode = mode;
12714e0d914SAbhash Jha return 0;
12814e0d914SAbhash Jha }
12914e0d914SAbhash Jha
ltr390_counts_per_uvi(struct ltr390_data * data)1304bd7e5ceSAbhash Jha static int ltr390_counts_per_uvi(struct ltr390_data *data)
1314bd7e5ceSAbhash Jha {
1324bd7e5ceSAbhash Jha const int orig_gain = 18;
1334bd7e5ceSAbhash Jha const int orig_int_time = 400;
1344bd7e5ceSAbhash Jha
1354bd7e5ceSAbhash Jha return DIV_ROUND_CLOSEST(23 * data->gain * data->int_time_us, 10 * orig_gain * orig_int_time);
1364bd7e5ceSAbhash Jha }
1374bd7e5ceSAbhash Jha
ltr390_read_raw(struct iio_dev * iio_device,struct iio_chan_spec const * chan,int * val,int * val2,long mask)1388b0d4c40SAnshul Dalal static int ltr390_read_raw(struct iio_dev *iio_device,
1398b0d4c40SAnshul Dalal struct iio_chan_spec const *chan, int *val,
1408b0d4c40SAnshul Dalal int *val2, long mask)
1418b0d4c40SAnshul Dalal {
1428b0d4c40SAnshul Dalal int ret;
1438b0d4c40SAnshul Dalal struct ltr390_data *data = iio_priv(iio_device);
1448b0d4c40SAnshul Dalal
14513fad260SAbhash Jha guard(mutex)(&data->lock);
1468b0d4c40SAnshul Dalal switch (mask) {
1478b0d4c40SAnshul Dalal case IIO_CHAN_INFO_RAW:
14814e0d914SAbhash Jha switch (chan->type) {
14914e0d914SAbhash Jha case IIO_UVINDEX:
15014e0d914SAbhash Jha ret = ltr390_set_mode(data, LTR390_SET_UVS_MODE);
15114e0d914SAbhash Jha if (ret < 0)
15214e0d914SAbhash Jha return ret;
15314e0d914SAbhash Jha
1548b0d4c40SAnshul Dalal ret = ltr390_register_read(data, LTR390_UVS_DATA);
1558b0d4c40SAnshul Dalal if (ret < 0)
1568b0d4c40SAnshul Dalal return ret;
15714e0d914SAbhash Jha break;
15814e0d914SAbhash Jha
15914e0d914SAbhash Jha case IIO_LIGHT:
16014e0d914SAbhash Jha ret = ltr390_set_mode(data, LTR390_SET_ALS_MODE);
16114e0d914SAbhash Jha if (ret < 0)
16214e0d914SAbhash Jha return ret;
16314e0d914SAbhash Jha
16414e0d914SAbhash Jha ret = ltr390_register_read(data, LTR390_ALS_DATA);
16514e0d914SAbhash Jha if (ret < 0)
16614e0d914SAbhash Jha return ret;
16714e0d914SAbhash Jha break;
16814e0d914SAbhash Jha
16914e0d914SAbhash Jha default:
17014e0d914SAbhash Jha return -EINVAL;
17114e0d914SAbhash Jha }
1728b0d4c40SAnshul Dalal *val = ret;
1738b0d4c40SAnshul Dalal return IIO_VAL_INT;
1748b0d4c40SAnshul Dalal case IIO_CHAN_INFO_SCALE:
17514e0d914SAbhash Jha switch (chan->type) {
17614e0d914SAbhash Jha case IIO_UVINDEX:
1774bd7e5ceSAbhash Jha *val = LTR390_WINDOW_FACTOR * LTR390_FRACTIONAL_PRECISION;
1784bd7e5ceSAbhash Jha *val2 = ltr390_counts_per_uvi(data);
1798b0d4c40SAnshul Dalal return IIO_VAL_FRACTIONAL;
18013fad260SAbhash Jha
18114e0d914SAbhash Jha case IIO_LIGHT:
18214e0d914SAbhash Jha *val = LTR390_WINDOW_FACTOR * 6 * 100;
18314e0d914SAbhash Jha *val2 = data->gain * data->int_time_us;
18414e0d914SAbhash Jha return IIO_VAL_FRACTIONAL;
18514e0d914SAbhash Jha
18614e0d914SAbhash Jha default:
18714e0d914SAbhash Jha return -EINVAL;
18814e0d914SAbhash Jha }
18914e0d914SAbhash Jha
19013fad260SAbhash Jha case IIO_CHAN_INFO_INT_TIME:
19113fad260SAbhash Jha *val = data->int_time_us;
19213fad260SAbhash Jha return IIO_VAL_INT;
19313fad260SAbhash Jha
19413fad260SAbhash Jha default:
19513fad260SAbhash Jha return -EINVAL;
19613fad260SAbhash Jha }
19713fad260SAbhash Jha }
19813fad260SAbhash Jha
19913fad260SAbhash Jha /* integration time in us */
20013fad260SAbhash Jha static const int ltr390_int_time_map_us[] = { 400000, 200000, 100000, 50000, 25000, 12500 };
20113fad260SAbhash Jha static const int ltr390_gain_map[] = { 1, 3, 6, 9, 18 };
20213fad260SAbhash Jha
20314e0d914SAbhash Jha static const struct iio_chan_spec ltr390_channels[] = {
20414e0d914SAbhash Jha /* UV sensor */
20514e0d914SAbhash Jha {
20613fad260SAbhash Jha .type = IIO_UVINDEX,
20714e0d914SAbhash Jha .scan_index = 0,
20813fad260SAbhash Jha .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),
20913fad260SAbhash Jha .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_INT_TIME),
21013fad260SAbhash Jha .info_mask_shared_by_all_available = BIT(IIO_CHAN_INFO_INT_TIME) | BIT(IIO_CHAN_INFO_SCALE)
21114e0d914SAbhash Jha },
21214e0d914SAbhash Jha /* ALS sensor */
21314e0d914SAbhash Jha {
21414e0d914SAbhash Jha .type = IIO_LIGHT,
21514e0d914SAbhash Jha .scan_index = 1,
21614e0d914SAbhash Jha .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),
21714e0d914SAbhash Jha .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_INT_TIME),
21814e0d914SAbhash Jha .info_mask_shared_by_all_available = BIT(IIO_CHAN_INFO_INT_TIME) | BIT(IIO_CHAN_INFO_SCALE)
21914e0d914SAbhash Jha },
22013fad260SAbhash Jha };
22113fad260SAbhash Jha
ltr390_set_gain(struct ltr390_data * data,int val)22213fad260SAbhash Jha static int ltr390_set_gain(struct ltr390_data *data, int val)
22313fad260SAbhash Jha {
22413fad260SAbhash Jha int ret, idx;
22513fad260SAbhash Jha
22613fad260SAbhash Jha for (idx = 0; idx < ARRAY_SIZE(ltr390_gain_map); idx++) {
22713fad260SAbhash Jha if (ltr390_gain_map[idx] != val)
22813fad260SAbhash Jha continue;
22913fad260SAbhash Jha
23013fad260SAbhash Jha guard(mutex)(&data->lock);
23113fad260SAbhash Jha ret = regmap_update_bits(data->regmap,
23213fad260SAbhash Jha LTR390_ALS_UVS_GAIN,
23313fad260SAbhash Jha LTR390_ALS_UVS_GAIN_MASK, idx);
23413fad260SAbhash Jha if (ret)
23513fad260SAbhash Jha return ret;
23613fad260SAbhash Jha
23713fad260SAbhash Jha data->gain = ltr390_gain_map[idx];
23813fad260SAbhash Jha return 0;
23913fad260SAbhash Jha }
24013fad260SAbhash Jha
24113fad260SAbhash Jha return -EINVAL;
24213fad260SAbhash Jha }
24313fad260SAbhash Jha
ltr390_set_int_time(struct ltr390_data * data,int val)24413fad260SAbhash Jha static int ltr390_set_int_time(struct ltr390_data *data, int val)
24513fad260SAbhash Jha {
24613fad260SAbhash Jha int ret, idx;
24713fad260SAbhash Jha
24813fad260SAbhash Jha for (idx = 0; idx < ARRAY_SIZE(ltr390_int_time_map_us); idx++) {
24913fad260SAbhash Jha if (ltr390_int_time_map_us[idx] != val)
25013fad260SAbhash Jha continue;
25113fad260SAbhash Jha
25213fad260SAbhash Jha guard(mutex)(&data->lock);
25313fad260SAbhash Jha ret = regmap_update_bits(data->regmap,
25413fad260SAbhash Jha LTR390_ALS_UVS_MEAS_RATE,
25513fad260SAbhash Jha LTR390_ALS_UVS_INT_TIME_MASK,
25613fad260SAbhash Jha LTR390_ALS_UVS_INT_TIME(idx));
25713fad260SAbhash Jha if (ret)
25813fad260SAbhash Jha return ret;
25913fad260SAbhash Jha
26013fad260SAbhash Jha data->int_time_us = ltr390_int_time_map_us[idx];
26113fad260SAbhash Jha return 0;
26213fad260SAbhash Jha }
26313fad260SAbhash Jha
26413fad260SAbhash Jha return -EINVAL;
26513fad260SAbhash Jha }
26613fad260SAbhash Jha
ltr390_read_avail(struct iio_dev * indio_dev,struct iio_chan_spec const * chan,const int ** vals,int * type,int * length,long mask)26713fad260SAbhash Jha static int ltr390_read_avail(struct iio_dev *indio_dev, struct iio_chan_spec const *chan,
26813fad260SAbhash Jha const int **vals, int *type, int *length, long mask)
26913fad260SAbhash Jha {
27013fad260SAbhash Jha switch (mask) {
27113fad260SAbhash Jha case IIO_CHAN_INFO_SCALE:
27213fad260SAbhash Jha *length = ARRAY_SIZE(ltr390_gain_map);
27313fad260SAbhash Jha *type = IIO_VAL_INT;
27413fad260SAbhash Jha *vals = ltr390_gain_map;
27513fad260SAbhash Jha return IIO_AVAIL_LIST;
27613fad260SAbhash Jha case IIO_CHAN_INFO_INT_TIME:
27713fad260SAbhash Jha *length = ARRAY_SIZE(ltr390_int_time_map_us);
27813fad260SAbhash Jha *type = IIO_VAL_INT;
27913fad260SAbhash Jha *vals = ltr390_int_time_map_us;
28013fad260SAbhash Jha return IIO_AVAIL_LIST;
28113fad260SAbhash Jha default:
28213fad260SAbhash Jha return -EINVAL;
28313fad260SAbhash Jha }
28413fad260SAbhash Jha }
28513fad260SAbhash Jha
ltr390_write_raw(struct iio_dev * indio_dev,struct iio_chan_spec const * chan,int val,int val2,long mask)28613fad260SAbhash Jha static int ltr390_write_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan,
28713fad260SAbhash Jha int val, int val2, long mask)
28813fad260SAbhash Jha {
28913fad260SAbhash Jha struct ltr390_data *data = iio_priv(indio_dev);
29013fad260SAbhash Jha
29113fad260SAbhash Jha switch (mask) {
29213fad260SAbhash Jha case IIO_CHAN_INFO_SCALE:
29313fad260SAbhash Jha if (val2 != 0)
29413fad260SAbhash Jha return -EINVAL;
29513fad260SAbhash Jha
29613fad260SAbhash Jha return ltr390_set_gain(data, val);
29713fad260SAbhash Jha
29813fad260SAbhash Jha case IIO_CHAN_INFO_INT_TIME:
29913fad260SAbhash Jha if (val2 != 0)
30013fad260SAbhash Jha return -EINVAL;
30113fad260SAbhash Jha
30213fad260SAbhash Jha return ltr390_set_int_time(data, val);
30313fad260SAbhash Jha
3048b0d4c40SAnshul Dalal default:
3058b0d4c40SAnshul Dalal return -EINVAL;
3068b0d4c40SAnshul Dalal }
3078b0d4c40SAnshul Dalal }
3088b0d4c40SAnshul Dalal
3098b0d4c40SAnshul Dalal static const struct iio_info ltr390_info = {
3108b0d4c40SAnshul Dalal .read_raw = ltr390_read_raw,
31113fad260SAbhash Jha .write_raw = ltr390_write_raw,
31213fad260SAbhash Jha .read_avail = ltr390_read_avail,
3138b0d4c40SAnshul Dalal };
3148b0d4c40SAnshul Dalal
ltr390_probe(struct i2c_client * client)3158b0d4c40SAnshul Dalal static int ltr390_probe(struct i2c_client *client)
3168b0d4c40SAnshul Dalal {
3178b0d4c40SAnshul Dalal struct ltr390_data *data;
3188b0d4c40SAnshul Dalal struct iio_dev *indio_dev;
3198b0d4c40SAnshul Dalal struct device *dev;
3208b0d4c40SAnshul Dalal int ret, part_number;
3218b0d4c40SAnshul Dalal
3228b0d4c40SAnshul Dalal dev = &client->dev;
3238b0d4c40SAnshul Dalal indio_dev = devm_iio_device_alloc(dev, sizeof(*data));
3248b0d4c40SAnshul Dalal if (!indio_dev)
3258b0d4c40SAnshul Dalal return -ENOMEM;
3268b0d4c40SAnshul Dalal
3278b0d4c40SAnshul Dalal data = iio_priv(indio_dev);
3288b0d4c40SAnshul Dalal
3298b0d4c40SAnshul Dalal data->regmap = devm_regmap_init_i2c(client, <r390_regmap_config);
3308b0d4c40SAnshul Dalal if (IS_ERR(data->regmap))
3318b0d4c40SAnshul Dalal return dev_err_probe(dev, PTR_ERR(data->regmap),
3328b0d4c40SAnshul Dalal "regmap initialization failed\n");
3338b0d4c40SAnshul Dalal
3348b0d4c40SAnshul Dalal data->client = client;
33513fad260SAbhash Jha /* default value of integration time from pg: 15 of the datasheet */
33613fad260SAbhash Jha data->int_time_us = 100000;
33713fad260SAbhash Jha /* default value of gain from pg: 16 of the datasheet */
33813fad260SAbhash Jha data->gain = 3;
33914e0d914SAbhash Jha /* default mode for ltr390 is ALS mode */
34014e0d914SAbhash Jha data->mode = LTR390_SET_ALS_MODE;
34113fad260SAbhash Jha
3428b0d4c40SAnshul Dalal mutex_init(&data->lock);
3438b0d4c40SAnshul Dalal
3448b0d4c40SAnshul Dalal indio_dev->info = <r390_info;
34514e0d914SAbhash Jha indio_dev->channels = ltr390_channels;
34614e0d914SAbhash Jha indio_dev->num_channels = ARRAY_SIZE(ltr390_channels);
3478b0d4c40SAnshul Dalal indio_dev->name = "ltr390";
3488b0d4c40SAnshul Dalal
3498b0d4c40SAnshul Dalal ret = regmap_read(data->regmap, LTR390_PART_ID, &part_number);
3508b0d4c40SAnshul Dalal if (ret)
3518b0d4c40SAnshul Dalal return dev_err_probe(dev, ret,
3528b0d4c40SAnshul Dalal "failed to get sensor's part id\n");
3538b0d4c40SAnshul Dalal /* Lower 4 bits of `part_number` change with hardware revisions */
3548b0d4c40SAnshul Dalal if (part_number >> 4 != LTR390_PART_NUMBER_ID)
3558b0d4c40SAnshul Dalal dev_info(dev, "received invalid product id: 0x%x", part_number);
3568b0d4c40SAnshul Dalal dev_dbg(dev, "LTR390, product id: 0x%x\n", part_number);
3578b0d4c40SAnshul Dalal
3588b0d4c40SAnshul Dalal /* reset sensor, chip fails to respond to this, so ignore any errors */
3598b0d4c40SAnshul Dalal regmap_set_bits(data->regmap, LTR390_MAIN_CTRL, LTR390_SW_RESET);
3608b0d4c40SAnshul Dalal
3618b0d4c40SAnshul Dalal /* Wait for the registers to reset before proceeding */
3628b0d4c40SAnshul Dalal usleep_range(1000, 2000);
3638b0d4c40SAnshul Dalal
36414e0d914SAbhash Jha ret = regmap_set_bits(data->regmap, LTR390_MAIN_CTRL, LTR390_SENSOR_ENABLE);
3658b0d4c40SAnshul Dalal if (ret)
3668b0d4c40SAnshul Dalal return dev_err_probe(dev, ret, "failed to enable the sensor\n");
3678b0d4c40SAnshul Dalal
3688b0d4c40SAnshul Dalal return devm_iio_device_register(dev, indio_dev);
3698b0d4c40SAnshul Dalal }
3708b0d4c40SAnshul Dalal
3718b0d4c40SAnshul Dalal static const struct i2c_device_id ltr390_id[] = {
3728b0d4c40SAnshul Dalal { "ltr390" },
3738b0d4c40SAnshul Dalal { /* Sentinel */ }
3748b0d4c40SAnshul Dalal };
3758b0d4c40SAnshul Dalal MODULE_DEVICE_TABLE(i2c, ltr390_id);
3768b0d4c40SAnshul Dalal
3778b0d4c40SAnshul Dalal static const struct of_device_id ltr390_of_table[] = {
3788b0d4c40SAnshul Dalal { .compatible = "liteon,ltr390" },
3798b0d4c40SAnshul Dalal { /* Sentinel */ }
3808b0d4c40SAnshul Dalal };
3818b0d4c40SAnshul Dalal MODULE_DEVICE_TABLE(of, ltr390_of_table);
3828b0d4c40SAnshul Dalal
3838b0d4c40SAnshul Dalal static struct i2c_driver ltr390_driver = {
3848b0d4c40SAnshul Dalal .driver = {
3858b0d4c40SAnshul Dalal .name = "ltr390",
3868b0d4c40SAnshul Dalal .of_match_table = ltr390_of_table,
3878b0d4c40SAnshul Dalal },
3888b0d4c40SAnshul Dalal .probe = ltr390_probe,
3898b0d4c40SAnshul Dalal .id_table = ltr390_id,
3908b0d4c40SAnshul Dalal };
3918b0d4c40SAnshul Dalal module_i2c_driver(ltr390_driver);
3928b0d4c40SAnshul Dalal
3938b0d4c40SAnshul Dalal MODULE_AUTHOR("Anshul Dalal <anshulusr@gmail.com>");
3948b0d4c40SAnshul Dalal MODULE_DESCRIPTION("Lite-On LTR390 ALS and UV sensor Driver");
3958b0d4c40SAnshul Dalal MODULE_LICENSE("GPL");
396