1*eab35358SMudit Sharma // SPDX-License-Identifier: GPL-2.0
2*eab35358SMudit Sharma /*
3*eab35358SMudit Sharma * ROHM BH1745 digital colour sensor driver
4*eab35358SMudit Sharma *
5*eab35358SMudit Sharma * Copyright (C) Mudit Sharma <muditsharma.info@gmail.com>
6*eab35358SMudit Sharma *
7*eab35358SMudit Sharma * 7-bit I2C slave addresses:
8*eab35358SMudit Sharma * 0x38 (ADDR pin low)
9*eab35358SMudit Sharma * 0x39 (ADDR pin high)
10*eab35358SMudit Sharma */
11*eab35358SMudit Sharma
12*eab35358SMudit Sharma #include <linux/i2c.h>
13*eab35358SMudit Sharma #include <linux/mutex.h>
14*eab35358SMudit Sharma #include <linux/util_macros.h>
15*eab35358SMudit Sharma #include <linux/iio/events.h>
16*eab35358SMudit Sharma #include <linux/regmap.h>
17*eab35358SMudit Sharma #include <linux/bits.h>
18*eab35358SMudit Sharma #include <linux/bitfield.h>
19*eab35358SMudit Sharma
20*eab35358SMudit Sharma #include <linux/iio/iio.h>
21*eab35358SMudit Sharma #include <linux/iio/sysfs.h>
22*eab35358SMudit Sharma #include <linux/iio/trigger.h>
23*eab35358SMudit Sharma #include <linux/iio/trigger_consumer.h>
24*eab35358SMudit Sharma #include <linux/iio/triggered_buffer.h>
25*eab35358SMudit Sharma #include <linux/iio/iio-gts-helper.h>
26*eab35358SMudit Sharma
27*eab35358SMudit Sharma /* BH1745 configuration registers */
28*eab35358SMudit Sharma
29*eab35358SMudit Sharma /* System control */
30*eab35358SMudit Sharma #define BH1745_SYS_CTRL 0x40
31*eab35358SMudit Sharma #define BH1745_SYS_CTRL_SW_RESET BIT(7)
32*eab35358SMudit Sharma #define BH1745_SYS_CTRL_INTR_RESET BIT(6)
33*eab35358SMudit Sharma #define BH1745_SYS_CTRL_PART_ID_MASK GENMASK(5, 0)
34*eab35358SMudit Sharma #define BH1745_PART_ID 0x0B
35*eab35358SMudit Sharma
36*eab35358SMudit Sharma /* Mode control 1 */
37*eab35358SMudit Sharma #define BH1745_MODE_CTRL1 0x41
38*eab35358SMudit Sharma #define BH1745_CTRL1_MEASUREMENT_TIME_MASK GENMASK(2, 0)
39*eab35358SMudit Sharma
40*eab35358SMudit Sharma /* Mode control 2 */
41*eab35358SMudit Sharma #define BH1745_MODE_CTRL2 0x42
42*eab35358SMudit Sharma #define BH1745_CTRL2_RGBC_EN BIT(4)
43*eab35358SMudit Sharma #define BH1745_CTRL2_ADC_GAIN_MASK GENMASK(1, 0)
44*eab35358SMudit Sharma
45*eab35358SMudit Sharma /* Interrupt */
46*eab35358SMudit Sharma #define BH1745_INTR 0x60
47*eab35358SMudit Sharma #define BH1745_INTR_STATUS BIT(7)
48*eab35358SMudit Sharma #define BH1745_INTR_SOURCE_MASK GENMASK(3, 2)
49*eab35358SMudit Sharma #define BH1745_INTR_ENABLE BIT(0)
50*eab35358SMudit Sharma
51*eab35358SMudit Sharma #define BH1745_PERSISTENCE 0x61
52*eab35358SMudit Sharma
53*eab35358SMudit Sharma /* Threshold high */
54*eab35358SMudit Sharma #define BH1745_TH_LSB 0x62
55*eab35358SMudit Sharma #define BH1745_TH_MSB 0x63
56*eab35358SMudit Sharma
57*eab35358SMudit Sharma /* Threshold low */
58*eab35358SMudit Sharma #define BH1745_TL_LSB 0x64
59*eab35358SMudit Sharma #define BH1745_TL_MSB 0x65
60*eab35358SMudit Sharma
61*eab35358SMudit Sharma /* BH1745 data output regs */
62*eab35358SMudit Sharma #define BH1745_RED_LSB 0x50
63*eab35358SMudit Sharma #define BH1745_RED_MSB 0x51
64*eab35358SMudit Sharma #define BH1745_GREEN_LSB 0x52
65*eab35358SMudit Sharma #define BH1745_GREEN_MSB 0x53
66*eab35358SMudit Sharma #define BH1745_BLUE_LSB 0x54
67*eab35358SMudit Sharma #define BH1745_BLUE_MSB 0x55
68*eab35358SMudit Sharma #define BH1745_CLEAR_LSB 0x56
69*eab35358SMudit Sharma #define BH1745_CLEAR_MSB 0x57
70*eab35358SMudit Sharma
71*eab35358SMudit Sharma #define BH1745_MANU_ID_REG 0x92
72*eab35358SMudit Sharma
73*eab35358SMudit Sharma /* From 16x max HW gain and 32x max integration time */
74*eab35358SMudit Sharma #define BH1745_MAX_GAIN 512
75*eab35358SMudit Sharma
76*eab35358SMudit Sharma enum bh1745_int_source {
77*eab35358SMudit Sharma BH1745_INTR_SOURCE_RED,
78*eab35358SMudit Sharma BH1745_INTR_SOURCE_GREEN,
79*eab35358SMudit Sharma BH1745_INTR_SOURCE_BLUE,
80*eab35358SMudit Sharma BH1745_INTR_SOURCE_CLEAR,
81*eab35358SMudit Sharma };
82*eab35358SMudit Sharma
83*eab35358SMudit Sharma enum bh1745_gain {
84*eab35358SMudit Sharma BH1745_ADC_GAIN_1X,
85*eab35358SMudit Sharma BH1745_ADC_GAIN_2X,
86*eab35358SMudit Sharma BH1745_ADC_GAIN_16X,
87*eab35358SMudit Sharma };
88*eab35358SMudit Sharma
89*eab35358SMudit Sharma enum bh1745_measurement_time {
90*eab35358SMudit Sharma BH1745_MEASUREMENT_TIME_160MS,
91*eab35358SMudit Sharma BH1745_MEASUREMENT_TIME_320MS,
92*eab35358SMudit Sharma BH1745_MEASUREMENT_TIME_640MS,
93*eab35358SMudit Sharma BH1745_MEASUREMENT_TIME_1280MS,
94*eab35358SMudit Sharma BH1745_MEASUREMENT_TIME_2560MS,
95*eab35358SMudit Sharma BH1745_MEASUREMENT_TIME_5120MS,
96*eab35358SMudit Sharma };
97*eab35358SMudit Sharma
98*eab35358SMudit Sharma enum bh1745_presistence_value {
99*eab35358SMudit Sharma BH1745_PRESISTENCE_UPDATE_TOGGLE,
100*eab35358SMudit Sharma BH1745_PRESISTENCE_UPDATE_EACH_MEASUREMENT,
101*eab35358SMudit Sharma BH1745_PRESISTENCE_UPDATE_FOUR_MEASUREMENT,
102*eab35358SMudit Sharma BH1745_PRESISTENCE_UPDATE_EIGHT_MEASUREMENT,
103*eab35358SMudit Sharma };
104*eab35358SMudit Sharma
105*eab35358SMudit Sharma static const struct iio_gain_sel_pair bh1745_gain[] = {
106*eab35358SMudit Sharma GAIN_SCALE_GAIN(1, BH1745_ADC_GAIN_1X),
107*eab35358SMudit Sharma GAIN_SCALE_GAIN(2, BH1745_ADC_GAIN_2X),
108*eab35358SMudit Sharma GAIN_SCALE_GAIN(16, BH1745_ADC_GAIN_16X),
109*eab35358SMudit Sharma };
110*eab35358SMudit Sharma
111*eab35358SMudit Sharma static const struct iio_itime_sel_mul bh1745_itimes[] = {
112*eab35358SMudit Sharma GAIN_SCALE_ITIME_US(5120000, BH1745_MEASUREMENT_TIME_5120MS, 32),
113*eab35358SMudit Sharma GAIN_SCALE_ITIME_US(2560000, BH1745_MEASUREMENT_TIME_2560MS, 16),
114*eab35358SMudit Sharma GAIN_SCALE_ITIME_US(1280000, BH1745_MEASUREMENT_TIME_1280MS, 8),
115*eab35358SMudit Sharma GAIN_SCALE_ITIME_US(640000, BH1745_MEASUREMENT_TIME_640MS, 4),
116*eab35358SMudit Sharma GAIN_SCALE_ITIME_US(320000, BH1745_MEASUREMENT_TIME_320MS, 2),
117*eab35358SMudit Sharma GAIN_SCALE_ITIME_US(160000, BH1745_MEASUREMENT_TIME_160MS, 1),
118*eab35358SMudit Sharma };
119*eab35358SMudit Sharma
120*eab35358SMudit Sharma struct bh1745_data {
121*eab35358SMudit Sharma /*
122*eab35358SMudit Sharma * Lock to prevent device setting update or read before
123*eab35358SMudit Sharma * related calculations are completed
124*eab35358SMudit Sharma */
125*eab35358SMudit Sharma struct mutex lock;
126*eab35358SMudit Sharma struct regmap *regmap;
127*eab35358SMudit Sharma struct device *dev;
128*eab35358SMudit Sharma struct iio_trigger *trig;
129*eab35358SMudit Sharma struct iio_gts gts;
130*eab35358SMudit Sharma };
131*eab35358SMudit Sharma
132*eab35358SMudit Sharma static const struct regmap_range bh1745_volatile_ranges[] = {
133*eab35358SMudit Sharma regmap_reg_range(BH1745_MODE_CTRL2, BH1745_MODE_CTRL2), /* VALID */
134*eab35358SMudit Sharma regmap_reg_range(BH1745_RED_LSB, BH1745_CLEAR_MSB), /* Data */
135*eab35358SMudit Sharma regmap_reg_range(BH1745_INTR, BH1745_INTR), /* Interrupt */
136*eab35358SMudit Sharma };
137*eab35358SMudit Sharma
138*eab35358SMudit Sharma static const struct regmap_access_table bh1745_volatile_regs = {
139*eab35358SMudit Sharma .yes_ranges = bh1745_volatile_ranges,
140*eab35358SMudit Sharma .n_yes_ranges = ARRAY_SIZE(bh1745_volatile_ranges),
141*eab35358SMudit Sharma };
142*eab35358SMudit Sharma
143*eab35358SMudit Sharma static const struct regmap_range bh1745_readable_ranges[] = {
144*eab35358SMudit Sharma regmap_reg_range(BH1745_SYS_CTRL, BH1745_MODE_CTRL2),
145*eab35358SMudit Sharma regmap_reg_range(BH1745_RED_LSB, BH1745_CLEAR_MSB),
146*eab35358SMudit Sharma regmap_reg_range(BH1745_INTR, BH1745_INTR),
147*eab35358SMudit Sharma regmap_reg_range(BH1745_PERSISTENCE, BH1745_TL_MSB),
148*eab35358SMudit Sharma regmap_reg_range(BH1745_MANU_ID_REG, BH1745_MANU_ID_REG),
149*eab35358SMudit Sharma };
150*eab35358SMudit Sharma
151*eab35358SMudit Sharma static const struct regmap_access_table bh1745_readable_regs = {
152*eab35358SMudit Sharma .yes_ranges = bh1745_readable_ranges,
153*eab35358SMudit Sharma .n_yes_ranges = ARRAY_SIZE(bh1745_readable_ranges),
154*eab35358SMudit Sharma };
155*eab35358SMudit Sharma
156*eab35358SMudit Sharma static const struct regmap_range bh1745_writable_ranges[] = {
157*eab35358SMudit Sharma regmap_reg_range(BH1745_SYS_CTRL, BH1745_MODE_CTRL2),
158*eab35358SMudit Sharma regmap_reg_range(BH1745_INTR, BH1745_INTR),
159*eab35358SMudit Sharma regmap_reg_range(BH1745_PERSISTENCE, BH1745_TL_MSB),
160*eab35358SMudit Sharma };
161*eab35358SMudit Sharma
162*eab35358SMudit Sharma static const struct regmap_access_table bh1745_writable_regs = {
163*eab35358SMudit Sharma .yes_ranges = bh1745_writable_ranges,
164*eab35358SMudit Sharma .n_yes_ranges = ARRAY_SIZE(bh1745_writable_ranges),
165*eab35358SMudit Sharma };
166*eab35358SMudit Sharma
167*eab35358SMudit Sharma static const struct regmap_config bh1745_regmap = {
168*eab35358SMudit Sharma .reg_bits = 8,
169*eab35358SMudit Sharma .val_bits = 8,
170*eab35358SMudit Sharma .max_register = BH1745_MANU_ID_REG,
171*eab35358SMudit Sharma .cache_type = REGCACHE_RBTREE,
172*eab35358SMudit Sharma .volatile_table = &bh1745_volatile_regs,
173*eab35358SMudit Sharma .wr_table = &bh1745_writable_regs,
174*eab35358SMudit Sharma .rd_table = &bh1745_readable_regs,
175*eab35358SMudit Sharma };
176*eab35358SMudit Sharma
177*eab35358SMudit Sharma static const struct iio_event_spec bh1745_event_spec[] = {
178*eab35358SMudit Sharma {
179*eab35358SMudit Sharma .type = IIO_EV_TYPE_THRESH,
180*eab35358SMudit Sharma .dir = IIO_EV_DIR_RISING,
181*eab35358SMudit Sharma .mask_shared_by_type = BIT(IIO_EV_INFO_VALUE),
182*eab35358SMudit Sharma },
183*eab35358SMudit Sharma {
184*eab35358SMudit Sharma .type = IIO_EV_TYPE_THRESH,
185*eab35358SMudit Sharma .dir = IIO_EV_DIR_FALLING,
186*eab35358SMudit Sharma .mask_shared_by_type = BIT(IIO_EV_INFO_VALUE),
187*eab35358SMudit Sharma },
188*eab35358SMudit Sharma {
189*eab35358SMudit Sharma .type = IIO_EV_TYPE_THRESH,
190*eab35358SMudit Sharma .dir = IIO_EV_DIR_EITHER,
191*eab35358SMudit Sharma .mask_shared_by_type = BIT(IIO_EV_INFO_PERIOD),
192*eab35358SMudit Sharma .mask_separate = BIT(IIO_EV_INFO_ENABLE),
193*eab35358SMudit Sharma },
194*eab35358SMudit Sharma };
195*eab35358SMudit Sharma
196*eab35358SMudit Sharma #define BH1745_CHANNEL(_colour, _si, _addr) \
197*eab35358SMudit Sharma { \
198*eab35358SMudit Sharma .type = IIO_INTENSITY, .modified = 1, \
199*eab35358SMudit Sharma .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
200*eab35358SMudit Sharma .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SCALE) | \
201*eab35358SMudit Sharma BIT(IIO_CHAN_INFO_INT_TIME), \
202*eab35358SMudit Sharma .info_mask_shared_by_all_available = \
203*eab35358SMudit Sharma BIT(IIO_CHAN_INFO_SCALE) | \
204*eab35358SMudit Sharma BIT(IIO_CHAN_INFO_INT_TIME), \
205*eab35358SMudit Sharma .event_spec = bh1745_event_spec, \
206*eab35358SMudit Sharma .num_event_specs = ARRAY_SIZE(bh1745_event_spec), \
207*eab35358SMudit Sharma .channel2 = IIO_MOD_LIGHT_##_colour, .address = _addr, \
208*eab35358SMudit Sharma .scan_index = _si, \
209*eab35358SMudit Sharma .scan_type = { \
210*eab35358SMudit Sharma .sign = 'u', \
211*eab35358SMudit Sharma .realbits = 16, \
212*eab35358SMudit Sharma .storagebits = 16, \
213*eab35358SMudit Sharma .endianness = IIO_CPU, \
214*eab35358SMudit Sharma }, \
215*eab35358SMudit Sharma }
216*eab35358SMudit Sharma
217*eab35358SMudit Sharma static const struct iio_chan_spec bh1745_channels[] = {
218*eab35358SMudit Sharma BH1745_CHANNEL(RED, 0, BH1745_RED_LSB),
219*eab35358SMudit Sharma BH1745_CHANNEL(GREEN, 1, BH1745_GREEN_LSB),
220*eab35358SMudit Sharma BH1745_CHANNEL(BLUE, 2, BH1745_BLUE_LSB),
221*eab35358SMudit Sharma BH1745_CHANNEL(CLEAR, 3, BH1745_CLEAR_LSB),
222*eab35358SMudit Sharma IIO_CHAN_SOFT_TIMESTAMP(4),
223*eab35358SMudit Sharma };
224*eab35358SMudit Sharma
bh1745_reset(struct bh1745_data * data)225*eab35358SMudit Sharma static int bh1745_reset(struct bh1745_data *data)
226*eab35358SMudit Sharma {
227*eab35358SMudit Sharma return regmap_set_bits(data->regmap, BH1745_SYS_CTRL,
228*eab35358SMudit Sharma BH1745_SYS_CTRL_SW_RESET |
229*eab35358SMudit Sharma BH1745_SYS_CTRL_INTR_RESET);
230*eab35358SMudit Sharma }
231*eab35358SMudit Sharma
bh1745_power_on(struct bh1745_data * data)232*eab35358SMudit Sharma static int bh1745_power_on(struct bh1745_data *data)
233*eab35358SMudit Sharma {
234*eab35358SMudit Sharma return regmap_set_bits(data->regmap, BH1745_MODE_CTRL2,
235*eab35358SMudit Sharma BH1745_CTRL2_RGBC_EN);
236*eab35358SMudit Sharma }
237*eab35358SMudit Sharma
bh1745_power_off(void * data_ptr)238*eab35358SMudit Sharma static void bh1745_power_off(void *data_ptr)
239*eab35358SMudit Sharma {
240*eab35358SMudit Sharma struct bh1745_data *data = data_ptr;
241*eab35358SMudit Sharma struct device *dev = data->dev;
242*eab35358SMudit Sharma int ret;
243*eab35358SMudit Sharma
244*eab35358SMudit Sharma ret = regmap_clear_bits(data->regmap, BH1745_MODE_CTRL2,
245*eab35358SMudit Sharma BH1745_CTRL2_RGBC_EN);
246*eab35358SMudit Sharma if (ret)
247*eab35358SMudit Sharma dev_err(dev, "Failed to turn off device\n");
248*eab35358SMudit Sharma }
249*eab35358SMudit Sharma
bh1745_get_scale(struct bh1745_data * data,int * val,int * val2)250*eab35358SMudit Sharma static int bh1745_get_scale(struct bh1745_data *data, int *val, int *val2)
251*eab35358SMudit Sharma {
252*eab35358SMudit Sharma int ret;
253*eab35358SMudit Sharma int value;
254*eab35358SMudit Sharma int gain_sel, int_time_sel;
255*eab35358SMudit Sharma int gain;
256*eab35358SMudit Sharma const struct iio_itime_sel_mul *int_time;
257*eab35358SMudit Sharma
258*eab35358SMudit Sharma ret = regmap_read(data->regmap, BH1745_MODE_CTRL2, &value);
259*eab35358SMudit Sharma if (ret)
260*eab35358SMudit Sharma return ret;
261*eab35358SMudit Sharma
262*eab35358SMudit Sharma gain_sel = FIELD_GET(BH1745_CTRL2_ADC_GAIN_MASK, value);
263*eab35358SMudit Sharma gain = iio_gts_find_gain_by_sel(&data->gts, gain_sel);
264*eab35358SMudit Sharma
265*eab35358SMudit Sharma ret = regmap_read(data->regmap, BH1745_MODE_CTRL1, &value);
266*eab35358SMudit Sharma if (ret)
267*eab35358SMudit Sharma return ret;
268*eab35358SMudit Sharma
269*eab35358SMudit Sharma int_time_sel = FIELD_GET(BH1745_CTRL1_MEASUREMENT_TIME_MASK, value);
270*eab35358SMudit Sharma int_time = iio_gts_find_itime_by_sel(&data->gts, int_time_sel);
271*eab35358SMudit Sharma
272*eab35358SMudit Sharma return iio_gts_get_scale(&data->gts, gain, int_time->time_us, val,
273*eab35358SMudit Sharma val2);
274*eab35358SMudit Sharma }
275*eab35358SMudit Sharma
bh1745_set_scale(struct bh1745_data * data,int val)276*eab35358SMudit Sharma static int bh1745_set_scale(struct bh1745_data *data, int val)
277*eab35358SMudit Sharma {
278*eab35358SMudit Sharma struct device *dev = data->dev;
279*eab35358SMudit Sharma int ret;
280*eab35358SMudit Sharma int value;
281*eab35358SMudit Sharma int hw_gain_sel, current_int_time_sel, new_int_time_sel;
282*eab35358SMudit Sharma
283*eab35358SMudit Sharma ret = regmap_read(data->regmap, BH1745_MODE_CTRL1, &value);
284*eab35358SMudit Sharma if (ret)
285*eab35358SMudit Sharma return ret;
286*eab35358SMudit Sharma
287*eab35358SMudit Sharma current_int_time_sel = FIELD_GET(BH1745_CTRL1_MEASUREMENT_TIME_MASK,
288*eab35358SMudit Sharma value);
289*eab35358SMudit Sharma ret = iio_gts_find_gain_sel_for_scale_using_time(&data->gts,
290*eab35358SMudit Sharma current_int_time_sel,
291*eab35358SMudit Sharma val, 0, &hw_gain_sel);
292*eab35358SMudit Sharma if (ret) {
293*eab35358SMudit Sharma for (int i = 0; i < data->gts.num_itime; i++) {
294*eab35358SMudit Sharma new_int_time_sel = data->gts.itime_table[i].sel;
295*eab35358SMudit Sharma
296*eab35358SMudit Sharma if (new_int_time_sel == current_int_time_sel)
297*eab35358SMudit Sharma continue;
298*eab35358SMudit Sharma
299*eab35358SMudit Sharma ret = iio_gts_find_gain_sel_for_scale_using_time(&data->gts,
300*eab35358SMudit Sharma new_int_time_sel,
301*eab35358SMudit Sharma val, 0,
302*eab35358SMudit Sharma &hw_gain_sel);
303*eab35358SMudit Sharma if (!ret)
304*eab35358SMudit Sharma break;
305*eab35358SMudit Sharma }
306*eab35358SMudit Sharma
307*eab35358SMudit Sharma if (ret) {
308*eab35358SMudit Sharma dev_dbg(dev, "Unsupported scale value requested: %d\n",
309*eab35358SMudit Sharma val);
310*eab35358SMudit Sharma return -EINVAL;
311*eab35358SMudit Sharma }
312*eab35358SMudit Sharma
313*eab35358SMudit Sharma ret = regmap_write_bits(data->regmap, BH1745_MODE_CTRL1,
314*eab35358SMudit Sharma BH1745_CTRL1_MEASUREMENT_TIME_MASK,
315*eab35358SMudit Sharma new_int_time_sel);
316*eab35358SMudit Sharma if (ret)
317*eab35358SMudit Sharma return ret;
318*eab35358SMudit Sharma }
319*eab35358SMudit Sharma
320*eab35358SMudit Sharma return regmap_write_bits(data->regmap, BH1745_MODE_CTRL2,
321*eab35358SMudit Sharma BH1745_CTRL2_ADC_GAIN_MASK, hw_gain_sel);
322*eab35358SMudit Sharma }
323*eab35358SMudit Sharma
bh1745_get_int_time(struct bh1745_data * data,int * val)324*eab35358SMudit Sharma static int bh1745_get_int_time(struct bh1745_data *data, int *val)
325*eab35358SMudit Sharma {
326*eab35358SMudit Sharma int ret;
327*eab35358SMudit Sharma int value;
328*eab35358SMudit Sharma int int_time, int_time_sel;
329*eab35358SMudit Sharma
330*eab35358SMudit Sharma ret = regmap_read(data->regmap, BH1745_MODE_CTRL1, &value);
331*eab35358SMudit Sharma if (ret)
332*eab35358SMudit Sharma return ret;
333*eab35358SMudit Sharma
334*eab35358SMudit Sharma int_time_sel = FIELD_GET(BH1745_CTRL1_MEASUREMENT_TIME_MASK, value);
335*eab35358SMudit Sharma int_time = iio_gts_find_int_time_by_sel(&data->gts, int_time_sel);
336*eab35358SMudit Sharma if (int_time < 0)
337*eab35358SMudit Sharma return int_time;
338*eab35358SMudit Sharma
339*eab35358SMudit Sharma *val = int_time;
340*eab35358SMudit Sharma
341*eab35358SMudit Sharma return 0;
342*eab35358SMudit Sharma }
343*eab35358SMudit Sharma
bh1745_set_int_time(struct bh1745_data * data,int val,int val2)344*eab35358SMudit Sharma static int bh1745_set_int_time(struct bh1745_data *data, int val, int val2)
345*eab35358SMudit Sharma {
346*eab35358SMudit Sharma struct device *dev = data->dev;
347*eab35358SMudit Sharma int ret;
348*eab35358SMudit Sharma int value;
349*eab35358SMudit Sharma int current_int_time, current_hwgain_sel, current_hwgain;
350*eab35358SMudit Sharma int new_hwgain, new_hwgain_sel, new_int_time_sel;
351*eab35358SMudit Sharma int req_int_time = (1000000 * val) + val2;
352*eab35358SMudit Sharma
353*eab35358SMudit Sharma if (!iio_gts_valid_time(&data->gts, req_int_time)) {
354*eab35358SMudit Sharma dev_dbg(dev, "Unsupported integration time requested: %d\n",
355*eab35358SMudit Sharma req_int_time);
356*eab35358SMudit Sharma return -EINVAL;
357*eab35358SMudit Sharma }
358*eab35358SMudit Sharma
359*eab35358SMudit Sharma ret = bh1745_get_int_time(data, ¤t_int_time);
360*eab35358SMudit Sharma if (ret)
361*eab35358SMudit Sharma return ret;
362*eab35358SMudit Sharma
363*eab35358SMudit Sharma if (current_int_time == req_int_time)
364*eab35358SMudit Sharma return 0;
365*eab35358SMudit Sharma
366*eab35358SMudit Sharma ret = regmap_read(data->regmap, BH1745_MODE_CTRL2, &value);
367*eab35358SMudit Sharma if (ret)
368*eab35358SMudit Sharma return ret;
369*eab35358SMudit Sharma
370*eab35358SMudit Sharma current_hwgain_sel = FIELD_GET(BH1745_CTRL2_ADC_GAIN_MASK, value);
371*eab35358SMudit Sharma current_hwgain = iio_gts_find_gain_by_sel(&data->gts,
372*eab35358SMudit Sharma current_hwgain_sel);
373*eab35358SMudit Sharma ret = iio_gts_find_new_gain_by_old_gain_time(&data->gts, current_hwgain,
374*eab35358SMudit Sharma current_int_time,
375*eab35358SMudit Sharma req_int_time,
376*eab35358SMudit Sharma &new_hwgain);
377*eab35358SMudit Sharma if (new_hwgain < 0) {
378*eab35358SMudit Sharma dev_dbg(dev, "No corresponding gain for requested integration time\n");
379*eab35358SMudit Sharma return ret;
380*eab35358SMudit Sharma }
381*eab35358SMudit Sharma
382*eab35358SMudit Sharma if (ret) {
383*eab35358SMudit Sharma bool in_range;
384*eab35358SMudit Sharma
385*eab35358SMudit Sharma new_hwgain = iio_find_closest_gain_low(&data->gts, new_hwgain,
386*eab35358SMudit Sharma &in_range);
387*eab35358SMudit Sharma if (new_hwgain < 0) {
388*eab35358SMudit Sharma new_hwgain = iio_gts_get_min_gain(&data->gts);
389*eab35358SMudit Sharma if (new_hwgain < 0)
390*eab35358SMudit Sharma return ret;
391*eab35358SMudit Sharma }
392*eab35358SMudit Sharma
393*eab35358SMudit Sharma if (!in_range)
394*eab35358SMudit Sharma dev_dbg(dev, "Optimal gain out of range\n");
395*eab35358SMudit Sharma
396*eab35358SMudit Sharma dev_dbg(dev, "Scale changed, new hw_gain %d\n", new_hwgain);
397*eab35358SMudit Sharma }
398*eab35358SMudit Sharma
399*eab35358SMudit Sharma new_hwgain_sel = iio_gts_find_sel_by_gain(&data->gts, new_hwgain);
400*eab35358SMudit Sharma if (new_hwgain_sel < 0)
401*eab35358SMudit Sharma return new_hwgain_sel;
402*eab35358SMudit Sharma
403*eab35358SMudit Sharma ret = regmap_write_bits(data->regmap, BH1745_MODE_CTRL2,
404*eab35358SMudit Sharma BH1745_CTRL2_ADC_GAIN_MASK,
405*eab35358SMudit Sharma new_hwgain_sel);
406*eab35358SMudit Sharma if (ret)
407*eab35358SMudit Sharma return ret;
408*eab35358SMudit Sharma
409*eab35358SMudit Sharma new_int_time_sel = iio_gts_find_sel_by_int_time(&data->gts,
410*eab35358SMudit Sharma req_int_time);
411*eab35358SMudit Sharma if (new_int_time_sel < 0)
412*eab35358SMudit Sharma return new_int_time_sel;
413*eab35358SMudit Sharma
414*eab35358SMudit Sharma return regmap_write_bits(data->regmap, BH1745_MODE_CTRL1,
415*eab35358SMudit Sharma BH1745_CTRL1_MEASUREMENT_TIME_MASK,
416*eab35358SMudit Sharma new_int_time_sel);
417*eab35358SMudit Sharma }
418*eab35358SMudit Sharma
bh1745_read_raw(struct iio_dev * indio_dev,struct iio_chan_spec const * chan,int * val,int * val2,long mask)419*eab35358SMudit Sharma static int bh1745_read_raw(struct iio_dev *indio_dev,
420*eab35358SMudit Sharma struct iio_chan_spec const *chan,
421*eab35358SMudit Sharma int *val, int *val2, long mask)
422*eab35358SMudit Sharma {
423*eab35358SMudit Sharma struct bh1745_data *data = iio_priv(indio_dev);
424*eab35358SMudit Sharma int ret;
425*eab35358SMudit Sharma int value;
426*eab35358SMudit Sharma
427*eab35358SMudit Sharma switch (mask) {
428*eab35358SMudit Sharma case IIO_CHAN_INFO_RAW:
429*eab35358SMudit Sharma iio_device_claim_direct_scoped(return -EBUSY, indio_dev) {
430*eab35358SMudit Sharma ret = regmap_bulk_read(data->regmap, chan->address,
431*eab35358SMudit Sharma &value, 2);
432*eab35358SMudit Sharma if (ret)
433*eab35358SMudit Sharma return ret;
434*eab35358SMudit Sharma *val = value;
435*eab35358SMudit Sharma
436*eab35358SMudit Sharma return IIO_VAL_INT;
437*eab35358SMudit Sharma }
438*eab35358SMudit Sharma unreachable();
439*eab35358SMudit Sharma
440*eab35358SMudit Sharma case IIO_CHAN_INFO_SCALE: {
441*eab35358SMudit Sharma guard(mutex)(&data->lock);
442*eab35358SMudit Sharma ret = bh1745_get_scale(data, val, val2);
443*eab35358SMudit Sharma if (ret)
444*eab35358SMudit Sharma return ret;
445*eab35358SMudit Sharma
446*eab35358SMudit Sharma return IIO_VAL_INT;
447*eab35358SMudit Sharma }
448*eab35358SMudit Sharma
449*eab35358SMudit Sharma case IIO_CHAN_INFO_INT_TIME: {
450*eab35358SMudit Sharma guard(mutex)(&data->lock);
451*eab35358SMudit Sharma *val = 0;
452*eab35358SMudit Sharma ret = bh1745_get_int_time(data, val2);
453*eab35358SMudit Sharma if (ret)
454*eab35358SMudit Sharma return 0;
455*eab35358SMudit Sharma
456*eab35358SMudit Sharma return IIO_VAL_INT_PLUS_MICRO;
457*eab35358SMudit Sharma }
458*eab35358SMudit Sharma
459*eab35358SMudit Sharma default:
460*eab35358SMudit Sharma return -EINVAL;
461*eab35358SMudit Sharma }
462*eab35358SMudit Sharma }
463*eab35358SMudit Sharma
bh1745_write_raw(struct iio_dev * indio_dev,struct iio_chan_spec const * chan,int val,int val2,long mask)464*eab35358SMudit Sharma static int bh1745_write_raw(struct iio_dev *indio_dev,
465*eab35358SMudit Sharma struct iio_chan_spec const *chan,
466*eab35358SMudit Sharma int val, int val2, long mask)
467*eab35358SMudit Sharma {
468*eab35358SMudit Sharma struct bh1745_data *data = iio_priv(indio_dev);
469*eab35358SMudit Sharma
470*eab35358SMudit Sharma guard(mutex)(&data->lock);
471*eab35358SMudit Sharma switch (mask) {
472*eab35358SMudit Sharma case IIO_CHAN_INFO_SCALE:
473*eab35358SMudit Sharma return bh1745_set_scale(data, val);
474*eab35358SMudit Sharma
475*eab35358SMudit Sharma case IIO_CHAN_INFO_INT_TIME:
476*eab35358SMudit Sharma return bh1745_set_int_time(data, val, val2);
477*eab35358SMudit Sharma
478*eab35358SMudit Sharma default:
479*eab35358SMudit Sharma return -EINVAL;
480*eab35358SMudit Sharma }
481*eab35358SMudit Sharma }
482*eab35358SMudit Sharma
bh1745_write_raw_get_fmt(struct iio_dev * indio_dev,struct iio_chan_spec const * chan,long mask)483*eab35358SMudit Sharma static int bh1745_write_raw_get_fmt(struct iio_dev *indio_dev,
484*eab35358SMudit Sharma struct iio_chan_spec const *chan,
485*eab35358SMudit Sharma long mask)
486*eab35358SMudit Sharma {
487*eab35358SMudit Sharma switch (mask) {
488*eab35358SMudit Sharma case IIO_CHAN_INFO_SCALE:
489*eab35358SMudit Sharma return IIO_VAL_INT;
490*eab35358SMudit Sharma
491*eab35358SMudit Sharma case IIO_CHAN_INFO_INT_TIME:
492*eab35358SMudit Sharma return IIO_VAL_INT_PLUS_MICRO;
493*eab35358SMudit Sharma
494*eab35358SMudit Sharma default:
495*eab35358SMudit Sharma return -EINVAL;
496*eab35358SMudit Sharma }
497*eab35358SMudit Sharma }
498*eab35358SMudit Sharma
bh1745_read_thresh(struct iio_dev * indio_dev,const struct iio_chan_spec * chan,enum iio_event_type type,enum iio_event_direction dir,enum iio_event_info info,int * val,int * val2)499*eab35358SMudit Sharma static int bh1745_read_thresh(struct iio_dev *indio_dev,
500*eab35358SMudit Sharma const struct iio_chan_spec *chan,
501*eab35358SMudit Sharma enum iio_event_type type,
502*eab35358SMudit Sharma enum iio_event_direction dir,
503*eab35358SMudit Sharma enum iio_event_info info, int *val, int *val2)
504*eab35358SMudit Sharma {
505*eab35358SMudit Sharma struct bh1745_data *data = iio_priv(indio_dev);
506*eab35358SMudit Sharma int ret;
507*eab35358SMudit Sharma
508*eab35358SMudit Sharma switch (info) {
509*eab35358SMudit Sharma case IIO_EV_INFO_VALUE:
510*eab35358SMudit Sharma switch (dir) {
511*eab35358SMudit Sharma case IIO_EV_DIR_RISING:
512*eab35358SMudit Sharma ret = regmap_bulk_read(data->regmap, BH1745_TH_LSB,
513*eab35358SMudit Sharma val, 2);
514*eab35358SMudit Sharma if (ret)
515*eab35358SMudit Sharma return ret;
516*eab35358SMudit Sharma
517*eab35358SMudit Sharma return IIO_VAL_INT;
518*eab35358SMudit Sharma
519*eab35358SMudit Sharma case IIO_EV_DIR_FALLING:
520*eab35358SMudit Sharma ret = regmap_bulk_read(data->regmap, BH1745_TL_LSB,
521*eab35358SMudit Sharma val, 2);
522*eab35358SMudit Sharma if (ret)
523*eab35358SMudit Sharma return ret;
524*eab35358SMudit Sharma
525*eab35358SMudit Sharma return IIO_VAL_INT;
526*eab35358SMudit Sharma
527*eab35358SMudit Sharma default:
528*eab35358SMudit Sharma return -EINVAL;
529*eab35358SMudit Sharma }
530*eab35358SMudit Sharma
531*eab35358SMudit Sharma case IIO_EV_INFO_PERIOD:
532*eab35358SMudit Sharma ret = regmap_read(data->regmap, BH1745_PERSISTENCE, val);
533*eab35358SMudit Sharma if (ret)
534*eab35358SMudit Sharma return ret;
535*eab35358SMudit Sharma
536*eab35358SMudit Sharma return IIO_VAL_INT;
537*eab35358SMudit Sharma
538*eab35358SMudit Sharma default:
539*eab35358SMudit Sharma return -EINVAL;
540*eab35358SMudit Sharma }
541*eab35358SMudit Sharma }
542*eab35358SMudit Sharma
bh1745_write_thresh(struct iio_dev * indio_dev,const struct iio_chan_spec * chan,enum iio_event_type type,enum iio_event_direction dir,enum iio_event_info info,int val,int val2)543*eab35358SMudit Sharma static int bh1745_write_thresh(struct iio_dev *indio_dev,
544*eab35358SMudit Sharma const struct iio_chan_spec *chan,
545*eab35358SMudit Sharma enum iio_event_type type,
546*eab35358SMudit Sharma enum iio_event_direction dir,
547*eab35358SMudit Sharma enum iio_event_info info, int val, int val2)
548*eab35358SMudit Sharma {
549*eab35358SMudit Sharma struct bh1745_data *data = iio_priv(indio_dev);
550*eab35358SMudit Sharma int ret;
551*eab35358SMudit Sharma
552*eab35358SMudit Sharma switch (info) {
553*eab35358SMudit Sharma case IIO_EV_INFO_VALUE:
554*eab35358SMudit Sharma if (val < 0x0 || val > 0xFFFF)
555*eab35358SMudit Sharma return -EINVAL;
556*eab35358SMudit Sharma
557*eab35358SMudit Sharma switch (dir) {
558*eab35358SMudit Sharma case IIO_EV_DIR_RISING:
559*eab35358SMudit Sharma ret = regmap_bulk_write(data->regmap, BH1745_TH_LSB,
560*eab35358SMudit Sharma &val, 2);
561*eab35358SMudit Sharma if (ret)
562*eab35358SMudit Sharma return ret;
563*eab35358SMudit Sharma
564*eab35358SMudit Sharma return IIO_VAL_INT;
565*eab35358SMudit Sharma
566*eab35358SMudit Sharma case IIO_EV_DIR_FALLING:
567*eab35358SMudit Sharma ret = regmap_bulk_write(data->regmap, BH1745_TL_LSB,
568*eab35358SMudit Sharma &val, 2);
569*eab35358SMudit Sharma if (ret)
570*eab35358SMudit Sharma return ret;
571*eab35358SMudit Sharma
572*eab35358SMudit Sharma return IIO_VAL_INT;
573*eab35358SMudit Sharma
574*eab35358SMudit Sharma default:
575*eab35358SMudit Sharma return -EINVAL;
576*eab35358SMudit Sharma }
577*eab35358SMudit Sharma
578*eab35358SMudit Sharma case IIO_EV_INFO_PERIOD:
579*eab35358SMudit Sharma if (val < BH1745_PRESISTENCE_UPDATE_TOGGLE ||
580*eab35358SMudit Sharma val > BH1745_PRESISTENCE_UPDATE_EIGHT_MEASUREMENT)
581*eab35358SMudit Sharma return -EINVAL;
582*eab35358SMudit Sharma ret = regmap_write(data->regmap, BH1745_PERSISTENCE, val);
583*eab35358SMudit Sharma if (ret)
584*eab35358SMudit Sharma return ret;
585*eab35358SMudit Sharma
586*eab35358SMudit Sharma return IIO_VAL_INT;
587*eab35358SMudit Sharma
588*eab35358SMudit Sharma default:
589*eab35358SMudit Sharma return -EINVAL;
590*eab35358SMudit Sharma }
591*eab35358SMudit Sharma }
592*eab35358SMudit Sharma
bh1745_read_event_config(struct iio_dev * indio_dev,const struct iio_chan_spec * chan,enum iio_event_type type,enum iio_event_direction dir)593*eab35358SMudit Sharma static int bh1745_read_event_config(struct iio_dev *indio_dev,
594*eab35358SMudit Sharma const struct iio_chan_spec *chan,
595*eab35358SMudit Sharma enum iio_event_type type,
596*eab35358SMudit Sharma enum iio_event_direction dir)
597*eab35358SMudit Sharma {
598*eab35358SMudit Sharma struct bh1745_data *data = iio_priv(indio_dev);
599*eab35358SMudit Sharma int ret;
600*eab35358SMudit Sharma int value;
601*eab35358SMudit Sharma int int_src;
602*eab35358SMudit Sharma
603*eab35358SMudit Sharma ret = regmap_read(data->regmap, BH1745_INTR, &value);
604*eab35358SMudit Sharma if (ret)
605*eab35358SMudit Sharma return ret;
606*eab35358SMudit Sharma
607*eab35358SMudit Sharma if (!FIELD_GET(BH1745_INTR_ENABLE, value))
608*eab35358SMudit Sharma return 0;
609*eab35358SMudit Sharma
610*eab35358SMudit Sharma int_src = FIELD_GET(BH1745_INTR_SOURCE_MASK, value);
611*eab35358SMudit Sharma
612*eab35358SMudit Sharma switch (chan->channel2) {
613*eab35358SMudit Sharma case IIO_MOD_LIGHT_RED:
614*eab35358SMudit Sharma if (int_src == BH1745_INTR_SOURCE_RED)
615*eab35358SMudit Sharma return 1;
616*eab35358SMudit Sharma return 0;
617*eab35358SMudit Sharma
618*eab35358SMudit Sharma case IIO_MOD_LIGHT_GREEN:
619*eab35358SMudit Sharma if (int_src == BH1745_INTR_SOURCE_GREEN)
620*eab35358SMudit Sharma return 1;
621*eab35358SMudit Sharma return 0;
622*eab35358SMudit Sharma
623*eab35358SMudit Sharma case IIO_MOD_LIGHT_BLUE:
624*eab35358SMudit Sharma if (int_src == BH1745_INTR_SOURCE_BLUE)
625*eab35358SMudit Sharma return 1;
626*eab35358SMudit Sharma return 0;
627*eab35358SMudit Sharma
628*eab35358SMudit Sharma case IIO_MOD_LIGHT_CLEAR:
629*eab35358SMudit Sharma if (int_src == BH1745_INTR_SOURCE_CLEAR)
630*eab35358SMudit Sharma return 1;
631*eab35358SMudit Sharma return 0;
632*eab35358SMudit Sharma
633*eab35358SMudit Sharma default:
634*eab35358SMudit Sharma return -EINVAL;
635*eab35358SMudit Sharma }
636*eab35358SMudit Sharma }
637*eab35358SMudit Sharma
bh1745_write_event_config(struct iio_dev * indio_dev,const struct iio_chan_spec * chan,enum iio_event_type type,enum iio_event_direction dir,int state)638*eab35358SMudit Sharma static int bh1745_write_event_config(struct iio_dev *indio_dev,
639*eab35358SMudit Sharma const struct iio_chan_spec *chan,
640*eab35358SMudit Sharma enum iio_event_type type,
641*eab35358SMudit Sharma enum iio_event_direction dir, int state)
642*eab35358SMudit Sharma {
643*eab35358SMudit Sharma struct bh1745_data *data = iio_priv(indio_dev);
644*eab35358SMudit Sharma int value;
645*eab35358SMudit Sharma
646*eab35358SMudit Sharma if (state == 0)
647*eab35358SMudit Sharma return regmap_clear_bits(data->regmap,
648*eab35358SMudit Sharma BH1745_INTR, BH1745_INTR_ENABLE);
649*eab35358SMudit Sharma
650*eab35358SMudit Sharma if (state == 1) {
651*eab35358SMudit Sharma /* Latch is always enabled when enabling interrupt */
652*eab35358SMudit Sharma value = BH1745_INTR_ENABLE;
653*eab35358SMudit Sharma
654*eab35358SMudit Sharma switch (chan->channel2) {
655*eab35358SMudit Sharma case IIO_MOD_LIGHT_RED:
656*eab35358SMudit Sharma return regmap_write(data->regmap, BH1745_INTR,
657*eab35358SMudit Sharma value | FIELD_PREP(BH1745_INTR_SOURCE_MASK,
658*eab35358SMudit Sharma BH1745_INTR_SOURCE_RED));
659*eab35358SMudit Sharma
660*eab35358SMudit Sharma case IIO_MOD_LIGHT_GREEN:
661*eab35358SMudit Sharma return regmap_write(data->regmap, BH1745_INTR,
662*eab35358SMudit Sharma value | FIELD_PREP(BH1745_INTR_SOURCE_MASK,
663*eab35358SMudit Sharma BH1745_INTR_SOURCE_GREEN));
664*eab35358SMudit Sharma
665*eab35358SMudit Sharma case IIO_MOD_LIGHT_BLUE:
666*eab35358SMudit Sharma return regmap_write(data->regmap, BH1745_INTR,
667*eab35358SMudit Sharma value | FIELD_PREP(BH1745_INTR_SOURCE_MASK,
668*eab35358SMudit Sharma BH1745_INTR_SOURCE_BLUE));
669*eab35358SMudit Sharma
670*eab35358SMudit Sharma case IIO_MOD_LIGHT_CLEAR:
671*eab35358SMudit Sharma return regmap_write(data->regmap, BH1745_INTR,
672*eab35358SMudit Sharma value | FIELD_PREP(BH1745_INTR_SOURCE_MASK,
673*eab35358SMudit Sharma BH1745_INTR_SOURCE_CLEAR));
674*eab35358SMudit Sharma
675*eab35358SMudit Sharma default:
676*eab35358SMudit Sharma return -EINVAL;
677*eab35358SMudit Sharma }
678*eab35358SMudit Sharma }
679*eab35358SMudit Sharma
680*eab35358SMudit Sharma return -EINVAL;
681*eab35358SMudit Sharma }
682*eab35358SMudit Sharma
bh1745_read_avail(struct iio_dev * indio_dev,struct iio_chan_spec const * chan,const int ** vals,int * type,int * length,long mask)683*eab35358SMudit Sharma static int bh1745_read_avail(struct iio_dev *indio_dev,
684*eab35358SMudit Sharma struct iio_chan_spec const *chan, const int **vals,
685*eab35358SMudit Sharma int *type, int *length, long mask)
686*eab35358SMudit Sharma {
687*eab35358SMudit Sharma struct bh1745_data *data = iio_priv(indio_dev);
688*eab35358SMudit Sharma
689*eab35358SMudit Sharma switch (mask) {
690*eab35358SMudit Sharma case IIO_CHAN_INFO_INT_TIME:
691*eab35358SMudit Sharma return iio_gts_avail_times(&data->gts, vals, type, length);
692*eab35358SMudit Sharma
693*eab35358SMudit Sharma case IIO_CHAN_INFO_SCALE:
694*eab35358SMudit Sharma return iio_gts_all_avail_scales(&data->gts, vals, type, length);
695*eab35358SMudit Sharma
696*eab35358SMudit Sharma default:
697*eab35358SMudit Sharma return -EINVAL;
698*eab35358SMudit Sharma }
699*eab35358SMudit Sharma }
700*eab35358SMudit Sharma
701*eab35358SMudit Sharma static const struct iio_info bh1745_info = {
702*eab35358SMudit Sharma .read_raw = bh1745_read_raw,
703*eab35358SMudit Sharma .write_raw = bh1745_write_raw,
704*eab35358SMudit Sharma .write_raw_get_fmt = bh1745_write_raw_get_fmt,
705*eab35358SMudit Sharma .read_event_value = bh1745_read_thresh,
706*eab35358SMudit Sharma .write_event_value = bh1745_write_thresh,
707*eab35358SMudit Sharma .read_event_config = bh1745_read_event_config,
708*eab35358SMudit Sharma .write_event_config = bh1745_write_event_config,
709*eab35358SMudit Sharma .read_avail = bh1745_read_avail,
710*eab35358SMudit Sharma };
711*eab35358SMudit Sharma
bh1745_interrupt_handler(int interrupt,void * p)712*eab35358SMudit Sharma static irqreturn_t bh1745_interrupt_handler(int interrupt, void *p)
713*eab35358SMudit Sharma {
714*eab35358SMudit Sharma struct iio_dev *indio_dev = p;
715*eab35358SMudit Sharma struct bh1745_data *data = iio_priv(indio_dev);
716*eab35358SMudit Sharma int ret;
717*eab35358SMudit Sharma int value;
718*eab35358SMudit Sharma int int_src;
719*eab35358SMudit Sharma
720*eab35358SMudit Sharma ret = regmap_read(data->regmap, BH1745_INTR, &value);
721*eab35358SMudit Sharma if (ret)
722*eab35358SMudit Sharma return IRQ_NONE;
723*eab35358SMudit Sharma
724*eab35358SMudit Sharma int_src = FIELD_GET(BH1745_INTR_SOURCE_MASK, value);
725*eab35358SMudit Sharma
726*eab35358SMudit Sharma if (value & BH1745_INTR_STATUS) {
727*eab35358SMudit Sharma iio_push_event(indio_dev,
728*eab35358SMudit Sharma IIO_UNMOD_EVENT_CODE(IIO_INTENSITY, int_src,
729*eab35358SMudit Sharma IIO_EV_TYPE_THRESH,
730*eab35358SMudit Sharma IIO_EV_DIR_EITHER),
731*eab35358SMudit Sharma iio_get_time_ns(indio_dev));
732*eab35358SMudit Sharma
733*eab35358SMudit Sharma return IRQ_HANDLED;
734*eab35358SMudit Sharma }
735*eab35358SMudit Sharma
736*eab35358SMudit Sharma return IRQ_NONE;
737*eab35358SMudit Sharma }
738*eab35358SMudit Sharma
bh1745_trigger_handler(int interrupt,void * p)739*eab35358SMudit Sharma static irqreturn_t bh1745_trigger_handler(int interrupt, void *p)
740*eab35358SMudit Sharma {
741*eab35358SMudit Sharma struct iio_poll_func *pf = p;
742*eab35358SMudit Sharma struct iio_dev *indio_dev = pf->indio_dev;
743*eab35358SMudit Sharma struct bh1745_data *data = iio_priv(indio_dev);
744*eab35358SMudit Sharma struct {
745*eab35358SMudit Sharma u16 chans[4];
746*eab35358SMudit Sharma s64 timestamp __aligned(8);
747*eab35358SMudit Sharma } scan;
748*eab35358SMudit Sharma u16 value;
749*eab35358SMudit Sharma int ret;
750*eab35358SMudit Sharma int i;
751*eab35358SMudit Sharma int j = 0;
752*eab35358SMudit Sharma
753*eab35358SMudit Sharma iio_for_each_active_channel(indio_dev, i) {
754*eab35358SMudit Sharma ret = regmap_bulk_read(data->regmap, BH1745_RED_LSB + 2 * i,
755*eab35358SMudit Sharma &value, 2);
756*eab35358SMudit Sharma if (ret)
757*eab35358SMudit Sharma goto err;
758*eab35358SMudit Sharma
759*eab35358SMudit Sharma scan.chans[j++] = value;
760*eab35358SMudit Sharma }
761*eab35358SMudit Sharma
762*eab35358SMudit Sharma iio_push_to_buffers_with_timestamp(indio_dev, &scan,
763*eab35358SMudit Sharma iio_get_time_ns(indio_dev));
764*eab35358SMudit Sharma
765*eab35358SMudit Sharma err:
766*eab35358SMudit Sharma iio_trigger_notify_done(indio_dev->trig);
767*eab35358SMudit Sharma
768*eab35358SMudit Sharma return IRQ_HANDLED;
769*eab35358SMudit Sharma }
770*eab35358SMudit Sharma
bh1745_setup_triggered_buffer(struct iio_dev * indio_dev,struct device * parent,int irq)771*eab35358SMudit Sharma static int bh1745_setup_triggered_buffer(struct iio_dev *indio_dev,
772*eab35358SMudit Sharma struct device *parent,
773*eab35358SMudit Sharma int irq)
774*eab35358SMudit Sharma {
775*eab35358SMudit Sharma struct bh1745_data *data = iio_priv(indio_dev);
776*eab35358SMudit Sharma struct device *dev = data->dev;
777*eab35358SMudit Sharma int ret;
778*eab35358SMudit Sharma
779*eab35358SMudit Sharma ret = devm_iio_triggered_buffer_setup(parent, indio_dev, NULL,
780*eab35358SMudit Sharma bh1745_trigger_handler, NULL);
781*eab35358SMudit Sharma if (ret)
782*eab35358SMudit Sharma return dev_err_probe(dev, ret,
783*eab35358SMudit Sharma "Triggered buffer setup failed\n");
784*eab35358SMudit Sharma
785*eab35358SMudit Sharma if (irq) {
786*eab35358SMudit Sharma ret = devm_request_threaded_irq(dev, irq, NULL,
787*eab35358SMudit Sharma bh1745_interrupt_handler,
788*eab35358SMudit Sharma IRQF_ONESHOT,
789*eab35358SMudit Sharma "bh1745_interrupt", indio_dev);
790*eab35358SMudit Sharma if (ret)
791*eab35358SMudit Sharma return dev_err_probe(dev, ret,
792*eab35358SMudit Sharma "Request for IRQ failed\n");
793*eab35358SMudit Sharma }
794*eab35358SMudit Sharma
795*eab35358SMudit Sharma return 0;
796*eab35358SMudit Sharma }
797*eab35358SMudit Sharma
bh1745_init(struct bh1745_data * data)798*eab35358SMudit Sharma static int bh1745_init(struct bh1745_data *data)
799*eab35358SMudit Sharma {
800*eab35358SMudit Sharma int ret;
801*eab35358SMudit Sharma struct device *dev = data->dev;
802*eab35358SMudit Sharma
803*eab35358SMudit Sharma mutex_init(&data->lock);
804*eab35358SMudit Sharma
805*eab35358SMudit Sharma ret = devm_iio_init_iio_gts(dev, BH1745_MAX_GAIN, 0, bh1745_gain,
806*eab35358SMudit Sharma ARRAY_SIZE(bh1745_gain), bh1745_itimes,
807*eab35358SMudit Sharma ARRAY_SIZE(bh1745_itimes), &data->gts);
808*eab35358SMudit Sharma if (ret)
809*eab35358SMudit Sharma return ret;
810*eab35358SMudit Sharma
811*eab35358SMudit Sharma ret = bh1745_reset(data);
812*eab35358SMudit Sharma if (ret)
813*eab35358SMudit Sharma return dev_err_probe(dev, ret, "Failed to reset sensor\n");
814*eab35358SMudit Sharma
815*eab35358SMudit Sharma ret = bh1745_power_on(data);
816*eab35358SMudit Sharma if (ret)
817*eab35358SMudit Sharma return dev_err_probe(dev, ret, "Failed to turn on sensor\n");
818*eab35358SMudit Sharma
819*eab35358SMudit Sharma ret = devm_add_action_or_reset(dev, bh1745_power_off, data);
820*eab35358SMudit Sharma if (ret)
821*eab35358SMudit Sharma return dev_err_probe(dev, ret,
822*eab35358SMudit Sharma "Failed to add action or reset\n");
823*eab35358SMudit Sharma
824*eab35358SMudit Sharma return 0;
825*eab35358SMudit Sharma }
826*eab35358SMudit Sharma
bh1745_probe(struct i2c_client * client)827*eab35358SMudit Sharma static int bh1745_probe(struct i2c_client *client)
828*eab35358SMudit Sharma {
829*eab35358SMudit Sharma int ret;
830*eab35358SMudit Sharma int value;
831*eab35358SMudit Sharma int part_id;
832*eab35358SMudit Sharma struct bh1745_data *data;
833*eab35358SMudit Sharma struct iio_dev *indio_dev;
834*eab35358SMudit Sharma struct device *dev = &client->dev;
835*eab35358SMudit Sharma
836*eab35358SMudit Sharma indio_dev = devm_iio_device_alloc(dev, sizeof(*data));
837*eab35358SMudit Sharma if (!indio_dev)
838*eab35358SMudit Sharma return -ENOMEM;
839*eab35358SMudit Sharma
840*eab35358SMudit Sharma indio_dev->info = &bh1745_info;
841*eab35358SMudit Sharma indio_dev->name = "bh1745";
842*eab35358SMudit Sharma indio_dev->channels = bh1745_channels;
843*eab35358SMudit Sharma indio_dev->modes = INDIO_DIRECT_MODE;
844*eab35358SMudit Sharma indio_dev->num_channels = ARRAY_SIZE(bh1745_channels);
845*eab35358SMudit Sharma data = iio_priv(indio_dev);
846*eab35358SMudit Sharma data->dev = &client->dev;
847*eab35358SMudit Sharma data->regmap = devm_regmap_init_i2c(client, &bh1745_regmap);
848*eab35358SMudit Sharma if (IS_ERR(data->regmap))
849*eab35358SMudit Sharma return dev_err_probe(dev, PTR_ERR(data->regmap),
850*eab35358SMudit Sharma "Failed to initialize Regmap\n");
851*eab35358SMudit Sharma
852*eab35358SMudit Sharma ret = regmap_read(data->regmap, BH1745_SYS_CTRL, &value);
853*eab35358SMudit Sharma if (ret)
854*eab35358SMudit Sharma return ret;
855*eab35358SMudit Sharma
856*eab35358SMudit Sharma part_id = FIELD_GET(BH1745_SYS_CTRL_PART_ID_MASK, value);
857*eab35358SMudit Sharma if (part_id != BH1745_PART_ID)
858*eab35358SMudit Sharma dev_warn(dev, "Unknown part ID 0x%x\n", part_id);
859*eab35358SMudit Sharma
860*eab35358SMudit Sharma ret = devm_regulator_get_enable(dev, "vdd");
861*eab35358SMudit Sharma if (ret)
862*eab35358SMudit Sharma return dev_err_probe(dev, ret,
863*eab35358SMudit Sharma "Failed to get and enable regulator\n");
864*eab35358SMudit Sharma
865*eab35358SMudit Sharma ret = bh1745_init(data);
866*eab35358SMudit Sharma if (ret)
867*eab35358SMudit Sharma return ret;
868*eab35358SMudit Sharma
869*eab35358SMudit Sharma ret = bh1745_setup_triggered_buffer(indio_dev, indio_dev->dev.parent,
870*eab35358SMudit Sharma client->irq);
871*eab35358SMudit Sharma if (ret)
872*eab35358SMudit Sharma return ret;
873*eab35358SMudit Sharma
874*eab35358SMudit Sharma ret = devm_iio_device_register(dev, indio_dev);
875*eab35358SMudit Sharma if (ret)
876*eab35358SMudit Sharma return dev_err_probe(dev, ret, "Failed to register device\n");
877*eab35358SMudit Sharma
878*eab35358SMudit Sharma return 0;
879*eab35358SMudit Sharma }
880*eab35358SMudit Sharma
881*eab35358SMudit Sharma static const struct i2c_device_id bh1745_idtable[] = {
882*eab35358SMudit Sharma { "bh1745" },
883*eab35358SMudit Sharma { }
884*eab35358SMudit Sharma };
885*eab35358SMudit Sharma MODULE_DEVICE_TABLE(i2c, bh1745_idtable);
886*eab35358SMudit Sharma
887*eab35358SMudit Sharma static const struct of_device_id bh1745_of_match[] = {
888*eab35358SMudit Sharma { .compatible = "rohm,bh1745" },
889*eab35358SMudit Sharma { }
890*eab35358SMudit Sharma };
891*eab35358SMudit Sharma MODULE_DEVICE_TABLE(of, bh1745_of_match);
892*eab35358SMudit Sharma
893*eab35358SMudit Sharma static struct i2c_driver bh1745_driver = {
894*eab35358SMudit Sharma .driver = {
895*eab35358SMudit Sharma .name = "bh1745",
896*eab35358SMudit Sharma .of_match_table = bh1745_of_match,
897*eab35358SMudit Sharma },
898*eab35358SMudit Sharma .probe = bh1745_probe,
899*eab35358SMudit Sharma .id_table = bh1745_idtable,
900*eab35358SMudit Sharma };
901*eab35358SMudit Sharma module_i2c_driver(bh1745_driver);
902*eab35358SMudit Sharma
903*eab35358SMudit Sharma MODULE_LICENSE("GPL");
904*eab35358SMudit Sharma MODULE_AUTHOR("Mudit Sharma <muditsharma.info@gmail.com>");
905*eab35358SMudit Sharma MODULE_DESCRIPTION("BH1745 colour sensor driver");
906*eab35358SMudit Sharma MODULE_IMPORT_NS(IIO_GTS_HELPER);
907