1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* |
3 | * ROHM Colour Sensor driver for |
4 | * - BU27008 RGBC sensor |
5 | * - BU27010 RGBC + Flickering sensor |
6 | * |
7 | * Copyright (c) 2023, ROHM Semiconductor. |
8 | */ |
9 | |
10 | #include <linux/bitfield.h> |
11 | #include <linux/bitops.h> |
12 | #include <linux/device.h> |
13 | #include <linux/i2c.h> |
14 | #include <linux/interrupt.h> |
15 | #include <linux/module.h> |
16 | #include <linux/property.h> |
17 | #include <linux/regmap.h> |
18 | #include <linux/regulator/consumer.h> |
19 | #include <linux/units.h> |
20 | |
21 | #include <linux/iio/iio.h> |
22 | #include <linux/iio/iio-gts-helper.h> |
23 | #include <linux/iio/trigger.h> |
24 | #include <linux/iio/trigger_consumer.h> |
25 | #include <linux/iio/triggered_buffer.h> |
26 | |
27 | /* |
28 | * A word about register address and mask definitions. |
29 | * |
30 | * At a quick glance to the data-sheet register tables, the BU27010 has all the |
31 | * registers that the BU27008 has. On top of that the BU27010 adds couple of new |
32 | * ones. |
33 | * |
34 | * So, all definitions BU27008_REG_* are there also for BU27010 but none of the |
35 | * BU27010_REG_* are present on BU27008. This makes sense as BU27010 just adds |
36 | * some features (Flicker FIFO, more power control) on top of the BU27008. |
37 | * |
38 | * Unfortunately, some of the wheel has been re-invented. Even though the names |
39 | * of the registers have stayed the same, pretty much all of the functionality |
40 | * provided by the registers has changed place. Contents of all MODE_CONTROL |
41 | * registers on BU27008 and BU27010 are different. |
42 | * |
43 | * Chip-specific mapping from register addresses/bits to functionality is done |
44 | * in bu27_chip_data structures. |
45 | */ |
46 | #define BU27008_REG_SYSTEM_CONTROL 0x40 |
47 | #define BU27008_MASK_SW_RESET BIT(7) |
48 | #define BU27008_MASK_PART_ID GENMASK(5, 0) |
49 | #define BU27008_ID 0x1a |
50 | #define BU27008_REG_MODE_CONTROL1 0x41 |
51 | #define BU27008_MASK_MEAS_MODE GENMASK(2, 0) |
52 | #define BU27008_MASK_CHAN_SEL GENMASK(3, 2) |
53 | |
54 | #define BU27008_REG_MODE_CONTROL2 0x42 |
55 | #define BU27008_MASK_RGBC_GAIN GENMASK(7, 3) |
56 | #define BU27008_MASK_IR_GAIN_LO GENMASK(2, 0) |
57 | #define BU27008_SHIFT_IR_GAIN 3 |
58 | |
59 | #define BU27008_REG_MODE_CONTROL3 0x43 |
60 | #define BU27008_MASK_VALID BIT(7) |
61 | #define BU27008_MASK_INT_EN BIT(1) |
62 | #define BU27008_INT_EN BU27008_MASK_INT_EN |
63 | #define BU27008_INT_DIS 0 |
64 | #define BU27008_MASK_MEAS_EN BIT(0) |
65 | #define BU27008_MEAS_EN BIT(0) |
66 | #define BU27008_MEAS_DIS 0 |
67 | |
68 | #define BU27008_REG_DATA0_LO 0x50 |
69 | #define BU27008_REG_DATA1_LO 0x52 |
70 | #define BU27008_REG_DATA2_LO 0x54 |
71 | #define BU27008_REG_DATA3_LO 0x56 |
72 | #define BU27008_REG_DATA3_HI 0x57 |
73 | #define BU27008_REG_MANUFACTURER_ID 0x92 |
74 | #define BU27008_REG_MAX BU27008_REG_MANUFACTURER_ID |
75 | |
76 | /* BU27010 specific definitions */ |
77 | |
78 | #define BU27010_MASK_SW_RESET BIT(7) |
79 | #define BU27010_ID 0x1b |
80 | #define BU27010_REG_POWER 0x3e |
81 | #define BU27010_MASK_POWER BIT(0) |
82 | |
83 | #define BU27010_REG_RESET 0x3f |
84 | #define BU27010_MASK_RESET BIT(0) |
85 | #define BU27010_RESET_RELEASE BU27010_MASK_RESET |
86 | |
87 | #define BU27010_MASK_MEAS_EN BIT(1) |
88 | |
89 | #define BU27010_MASK_CHAN_SEL GENMASK(7, 6) |
90 | #define BU27010_MASK_MEAS_MODE GENMASK(5, 4) |
91 | #define BU27010_MASK_RGBC_GAIN GENMASK(3, 0) |
92 | |
93 | #define BU27010_MASK_DATA3_GAIN GENMASK(7, 6) |
94 | #define BU27010_MASK_DATA2_GAIN GENMASK(5, 4) |
95 | #define BU27010_MASK_DATA1_GAIN GENMASK(3, 2) |
96 | #define BU27010_MASK_DATA0_GAIN GENMASK(1, 0) |
97 | |
98 | #define BU27010_MASK_FLC_MODE BIT(7) |
99 | #define BU27010_MASK_FLC_GAIN GENMASK(4, 0) |
100 | |
101 | #define BU27010_REG_MODE_CONTROL4 0x44 |
102 | /* If flicker is ever to be supported the IRQ must be handled as a field */ |
103 | #define BU27010_IRQ_DIS_ALL GENMASK(1, 0) |
104 | #define BU27010_DRDY_EN BIT(0) |
105 | #define BU27010_MASK_INT_SEL GENMASK(1, 0) |
106 | |
107 | #define BU27010_REG_MODE_CONTROL5 0x45 |
108 | #define BU27010_MASK_RGB_VALID BIT(7) |
109 | #define BU27010_MASK_FLC_VALID BIT(6) |
110 | #define BU27010_MASK_WAIT_EN BIT(3) |
111 | #define BU27010_MASK_FIFO_EN BIT(2) |
112 | #define BU27010_MASK_RGB_EN BIT(1) |
113 | #define BU27010_MASK_FLC_EN BIT(0) |
114 | |
115 | #define BU27010_REG_DATA_FLICKER_LO 0x56 |
116 | #define BU27010_MASK_DATA_FLICKER_HI GENMASK(2, 0) |
117 | #define BU27010_REG_FLICKER_COUNT 0x5a |
118 | #define BU27010_REG_FIFO_LEVEL_LO 0x5b |
119 | #define BU27010_MASK_FIFO_LEVEL_HI BIT(0) |
120 | #define BU27010_REG_FIFO_DATA_LO 0x5d |
121 | #define BU27010_REG_FIFO_DATA_HI 0x5e |
122 | #define BU27010_MASK_FIFO_DATA_HI GENMASK(2, 0) |
123 | #define BU27010_REG_MANUFACTURER_ID 0x92 |
124 | #define BU27010_REG_MAX BU27010_REG_MANUFACTURER_ID |
125 | |
126 | /** |
127 | * enum bu27008_chan_type - BU27008 channel types |
128 | * @BU27008_RED: Red channel. Always via data0. |
129 | * @BU27008_GREEN: Green channel. Always via data1. |
130 | * @BU27008_BLUE: Blue channel. Via data2 (when used). |
131 | * @BU27008_CLEAR: Clear channel. Via data2 or data3 (when used). |
132 | * @BU27008_IR: IR channel. Via data3 (when used). |
133 | * @BU27008_LUX: Illuminance channel, computed using RGB and IR. |
134 | * @BU27008_NUM_CHANS: Number of channel types. |
135 | */ |
136 | enum bu27008_chan_type { |
137 | BU27008_RED, |
138 | BU27008_GREEN, |
139 | BU27008_BLUE, |
140 | BU27008_CLEAR, |
141 | BU27008_IR, |
142 | BU27008_LUX, |
143 | BU27008_NUM_CHANS |
144 | }; |
145 | |
146 | /** |
147 | * enum bu27008_chan - BU27008 physical data channel |
148 | * @BU27008_DATA0: Always red. |
149 | * @BU27008_DATA1: Always green. |
150 | * @BU27008_DATA2: Blue or clear. |
151 | * @BU27008_DATA3: IR or clear. |
152 | * @BU27008_NUM_HW_CHANS: Number of physical channels |
153 | */ |
154 | enum bu27008_chan { |
155 | BU27008_DATA0, |
156 | BU27008_DATA1, |
157 | BU27008_DATA2, |
158 | BU27008_DATA3, |
159 | BU27008_NUM_HW_CHANS |
160 | }; |
161 | |
162 | /* We can always measure red and green at same time */ |
163 | #define ALWAYS_SCANNABLE (BIT(BU27008_RED) | BIT(BU27008_GREEN)) |
164 | |
165 | /* We use these data channel configs. Ensure scan_masks below follow them too */ |
166 | #define BU27008_BLUE2_CLEAR3 0x0 /* buffer is R, G, B, C */ |
167 | #define BU27008_CLEAR2_IR3 0x1 /* buffer is R, G, C, IR */ |
168 | #define BU27008_BLUE2_IR3 0x2 /* buffer is R, G, B, IR */ |
169 | |
170 | static const unsigned long bu27008_scan_masks[] = { |
171 | /* buffer is R, G, B, C */ |
172 | ALWAYS_SCANNABLE | BIT(BU27008_BLUE) | BIT(BU27008_CLEAR), |
173 | /* buffer is R, G, C, IR */ |
174 | ALWAYS_SCANNABLE | BIT(BU27008_CLEAR) | BIT(BU27008_IR), |
175 | /* buffer is R, G, B, IR */ |
176 | ALWAYS_SCANNABLE | BIT(BU27008_BLUE) | BIT(BU27008_IR), |
177 | /* buffer is R, G, B, IR, LUX */ |
178 | ALWAYS_SCANNABLE | BIT(BU27008_BLUE) | BIT(BU27008_IR) | BIT(BU27008_LUX), |
179 | 0 |
180 | }; |
181 | |
182 | /* |
183 | * Available scales with gain 1x - 1024x, timings 55, 100, 200, 400 mS |
184 | * Time impacts to gain: 1x, 2x, 4x, 8x. |
185 | * |
186 | * => Max total gain is HWGAIN * gain by integration time (8 * 1024) = 8192 |
187 | * |
188 | * Max amplification is (HWGAIN * MAX integration-time multiplier) 1024 * 8 |
189 | * = 8192. With NANO scale we get rid of accuracy loss when we start with the |
190 | * scale 16.0 for HWGAIN1, INT-TIME 55 mS. This way the nano scale for MAX |
191 | * total gain 8192 will be 1953125 |
192 | */ |
193 | #define BU27008_SCALE_1X 16 |
194 | |
195 | /* |
196 | * On BU27010 available scales with gain 1x - 4096x, |
197 | * timings 55, 100, 200, 400 mS. Time impacts to gain: 1x, 2x, 4x, 8x. |
198 | * |
199 | * => Max total gain is HWGAIN * gain by integration time (8 * 4096) |
200 | * |
201 | * Using NANO precision for scale we must use scale 64x corresponding gain 1x |
202 | * to avoid precision loss. |
203 | */ |
204 | #define BU27010_SCALE_1X 64 |
205 | |
206 | /* See the data sheet for the "Gain Setting" table */ |
207 | #define BU27008_GSEL_1X 0x00 |
208 | #define BU27008_GSEL_4X 0x08 |
209 | #define BU27008_GSEL_8X 0x09 |
210 | #define BU27008_GSEL_16X 0x0a |
211 | #define BU27008_GSEL_32X 0x0b |
212 | #define BU27008_GSEL_64X 0x0c |
213 | #define BU27008_GSEL_256X 0x18 |
214 | #define BU27008_GSEL_512X 0x19 |
215 | #define BU27008_GSEL_1024X 0x1a |
216 | |
217 | static const struct iio_gain_sel_pair bu27008_gains[] = { |
218 | GAIN_SCALE_GAIN(1, BU27008_GSEL_1X), |
219 | GAIN_SCALE_GAIN(4, BU27008_GSEL_4X), |
220 | GAIN_SCALE_GAIN(8, BU27008_GSEL_8X), |
221 | GAIN_SCALE_GAIN(16, BU27008_GSEL_16X), |
222 | GAIN_SCALE_GAIN(32, BU27008_GSEL_32X), |
223 | GAIN_SCALE_GAIN(64, BU27008_GSEL_64X), |
224 | GAIN_SCALE_GAIN(256, BU27008_GSEL_256X), |
225 | GAIN_SCALE_GAIN(512, BU27008_GSEL_512X), |
226 | GAIN_SCALE_GAIN(1024, BU27008_GSEL_1024X), |
227 | }; |
228 | |
229 | static const struct iio_gain_sel_pair bu27008_gains_ir[] = { |
230 | GAIN_SCALE_GAIN(2, BU27008_GSEL_1X), |
231 | GAIN_SCALE_GAIN(4, BU27008_GSEL_4X), |
232 | GAIN_SCALE_GAIN(8, BU27008_GSEL_8X), |
233 | GAIN_SCALE_GAIN(16, BU27008_GSEL_16X), |
234 | GAIN_SCALE_GAIN(32, BU27008_GSEL_32X), |
235 | GAIN_SCALE_GAIN(64, BU27008_GSEL_64X), |
236 | GAIN_SCALE_GAIN(256, BU27008_GSEL_256X), |
237 | GAIN_SCALE_GAIN(512, BU27008_GSEL_512X), |
238 | GAIN_SCALE_GAIN(1024, BU27008_GSEL_1024X), |
239 | }; |
240 | |
241 | #define BU27010_GSEL_1X 0x00 /* 000000 */ |
242 | #define BU27010_GSEL_4X 0x08 /* 001000 */ |
243 | #define BU27010_GSEL_16X 0x09 /* 001001 */ |
244 | #define BU27010_GSEL_64X 0x0e /* 001110 */ |
245 | #define BU27010_GSEL_256X 0x1e /* 011110 */ |
246 | #define BU27010_GSEL_1024X 0x2e /* 101110 */ |
247 | #define BU27010_GSEL_4096X 0x3f /* 111111 */ |
248 | |
249 | static const struct iio_gain_sel_pair bu27010_gains[] = { |
250 | GAIN_SCALE_GAIN(1, BU27010_GSEL_1X), |
251 | GAIN_SCALE_GAIN(4, BU27010_GSEL_4X), |
252 | GAIN_SCALE_GAIN(16, BU27010_GSEL_16X), |
253 | GAIN_SCALE_GAIN(64, BU27010_GSEL_64X), |
254 | GAIN_SCALE_GAIN(256, BU27010_GSEL_256X), |
255 | GAIN_SCALE_GAIN(1024, BU27010_GSEL_1024X), |
256 | GAIN_SCALE_GAIN(4096, BU27010_GSEL_4096X), |
257 | }; |
258 | |
259 | static const struct iio_gain_sel_pair bu27010_gains_ir[] = { |
260 | GAIN_SCALE_GAIN(2, BU27010_GSEL_1X), |
261 | GAIN_SCALE_GAIN(4, BU27010_GSEL_4X), |
262 | GAIN_SCALE_GAIN(16, BU27010_GSEL_16X), |
263 | GAIN_SCALE_GAIN(64, BU27010_GSEL_64X), |
264 | GAIN_SCALE_GAIN(256, BU27010_GSEL_256X), |
265 | GAIN_SCALE_GAIN(1024, BU27010_GSEL_1024X), |
266 | GAIN_SCALE_GAIN(4096, BU27010_GSEL_4096X), |
267 | }; |
268 | |
269 | #define BU27008_MEAS_MODE_100MS 0x00 |
270 | #define BU27008_MEAS_MODE_55MS 0x01 |
271 | #define BU27008_MEAS_MODE_200MS 0x02 |
272 | #define BU27008_MEAS_MODE_400MS 0x04 |
273 | |
274 | #define BU27010_MEAS_MODE_100MS 0x00 |
275 | #define BU27010_MEAS_MODE_55MS 0x03 |
276 | #define BU27010_MEAS_MODE_200MS 0x01 |
277 | #define BU27010_MEAS_MODE_400MS 0x02 |
278 | |
279 | #define BU27008_MEAS_TIME_MAX_MS 400 |
280 | |
281 | static const struct iio_itime_sel_mul bu27008_itimes[] = { |
282 | GAIN_SCALE_ITIME_US(400000, BU27008_MEAS_MODE_400MS, 8), |
283 | GAIN_SCALE_ITIME_US(200000, BU27008_MEAS_MODE_200MS, 4), |
284 | GAIN_SCALE_ITIME_US(100000, BU27008_MEAS_MODE_100MS, 2), |
285 | GAIN_SCALE_ITIME_US(55000, BU27008_MEAS_MODE_55MS, 1), |
286 | }; |
287 | |
288 | static const struct iio_itime_sel_mul bu27010_itimes[] = { |
289 | GAIN_SCALE_ITIME_US(400000, BU27010_MEAS_MODE_400MS, 8), |
290 | GAIN_SCALE_ITIME_US(200000, BU27010_MEAS_MODE_200MS, 4), |
291 | GAIN_SCALE_ITIME_US(100000, BU27010_MEAS_MODE_100MS, 2), |
292 | GAIN_SCALE_ITIME_US(55000, BU27010_MEAS_MODE_55MS, 1), |
293 | }; |
294 | |
295 | /* |
296 | * All the RGBC channels share the same gain. |
297 | * IR gain can be fine-tuned from the gain set for the RGBC by 2 bit, but this |
298 | * would yield quite complex gain setting. Especially since not all bit |
299 | * compinations are supported. And in any case setting GAIN for RGBC will |
300 | * always also change the IR-gain. |
301 | * |
302 | * On top of this, the selector '0' which corresponds to hw-gain 1X on RGBC, |
303 | * corresponds to gain 2X on IR. Rest of the selctors correspond to same gains |
304 | * though. This, however, makes it not possible to use shared gain for all |
305 | * RGBC and IR settings even though they are all changed at the one go. |
306 | */ |
307 | #define BU27008_CHAN(color, data, separate_avail) \ |
308 | { \ |
309 | .type = IIO_INTENSITY, \ |
310 | .modified = 1, \ |
311 | .channel2 = IIO_MOD_LIGHT_##color, \ |
312 | .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ |
313 | BIT(IIO_CHAN_INFO_SCALE), \ |
314 | .info_mask_separate_available = (separate_avail), \ |
315 | .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_INT_TIME), \ |
316 | .info_mask_shared_by_all_available = BIT(IIO_CHAN_INFO_INT_TIME), \ |
317 | .address = BU27008_REG_##data##_LO, \ |
318 | .scan_index = BU27008_##color, \ |
319 | .scan_type = { \ |
320 | .sign = 'u', \ |
321 | .realbits = 16, \ |
322 | .storagebits = 16, \ |
323 | .endianness = IIO_LE, \ |
324 | }, \ |
325 | } |
326 | |
327 | /* For raw reads we always configure DATA3 for CLEAR */ |
328 | static const struct iio_chan_spec bu27008_channels[] = { |
329 | BU27008_CHAN(RED, DATA0, BIT(IIO_CHAN_INFO_SCALE)), |
330 | BU27008_CHAN(GREEN, DATA1, BIT(IIO_CHAN_INFO_SCALE)), |
331 | BU27008_CHAN(BLUE, DATA2, BIT(IIO_CHAN_INFO_SCALE)), |
332 | BU27008_CHAN(CLEAR, DATA2, BIT(IIO_CHAN_INFO_SCALE)), |
333 | /* |
334 | * We don't allow setting scale for IR (because of shared gain bits). |
335 | * Hence we don't advertise available ones either. |
336 | */ |
337 | BU27008_CHAN(IR, DATA3, 0), |
338 | { |
339 | .type = IIO_LIGHT, |
340 | .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | |
341 | BIT(IIO_CHAN_INFO_SCALE), |
342 | .channel = BU27008_LUX, |
343 | .scan_index = BU27008_LUX, |
344 | .scan_type = { |
345 | .sign = 'u', |
346 | .realbits = 64, |
347 | .storagebits = 64, |
348 | .endianness = IIO_CPU, |
349 | }, |
350 | }, |
351 | IIO_CHAN_SOFT_TIMESTAMP(BU27008_NUM_CHANS), |
352 | }; |
353 | |
354 | struct bu27008_data; |
355 | |
356 | struct bu27_chip_data { |
357 | const char *name; |
358 | int (*chip_init)(struct bu27008_data *data); |
359 | int (*get_gain_sel)(struct bu27008_data *data, int *sel); |
360 | int (*write_gain_sel)(struct bu27008_data *data, int sel); |
361 | const struct regmap_config *regmap_cfg; |
362 | const struct iio_gain_sel_pair *gains; |
363 | const struct iio_gain_sel_pair *gains_ir; |
364 | const struct iio_itime_sel_mul *itimes; |
365 | int num_gains; |
366 | int num_gains_ir; |
367 | int num_itimes; |
368 | int scale1x; |
369 | |
370 | int drdy_en_reg; |
371 | int drdy_en_mask; |
372 | int meas_en_reg; |
373 | int meas_en_mask; |
374 | int valid_reg; |
375 | int chan_sel_reg; |
376 | int chan_sel_mask; |
377 | int int_time_mask; |
378 | u8 part_id; |
379 | }; |
380 | |
381 | struct bu27008_data { |
382 | const struct bu27_chip_data *cd; |
383 | struct regmap *regmap; |
384 | struct iio_trigger *trig; |
385 | struct device *dev; |
386 | struct iio_gts gts; |
387 | struct iio_gts gts_ir; |
388 | int irq; |
389 | |
390 | /* |
391 | * Prevent changing gain/time config when scale is read/written. |
392 | * Similarly, protect the integration_time read/change sequence. |
393 | * Prevent changing gain/time when data is read. |
394 | */ |
395 | struct mutex mutex; |
396 | }; |
397 | |
398 | static const struct regmap_range bu27008_volatile_ranges[] = { |
399 | { |
400 | .range_min = BU27008_REG_SYSTEM_CONTROL, /* SWRESET */ |
401 | .range_max = BU27008_REG_SYSTEM_CONTROL, |
402 | }, { |
403 | .range_min = BU27008_REG_MODE_CONTROL3, /* VALID */ |
404 | .range_max = BU27008_REG_MODE_CONTROL3, |
405 | }, { |
406 | .range_min = BU27008_REG_DATA0_LO, /* DATA */ |
407 | .range_max = BU27008_REG_DATA3_HI, |
408 | }, |
409 | }; |
410 | |
411 | static const struct regmap_range bu27010_volatile_ranges[] = { |
412 | { |
413 | .range_min = BU27010_REG_RESET, /* RSTB */ |
414 | .range_max = BU27008_REG_SYSTEM_CONTROL, /* RESET */ |
415 | }, { |
416 | .range_min = BU27010_REG_MODE_CONTROL5, /* VALID bits */ |
417 | .range_max = BU27010_REG_MODE_CONTROL5, |
418 | }, { |
419 | .range_min = BU27008_REG_DATA0_LO, |
420 | .range_max = BU27010_REG_FIFO_DATA_HI, |
421 | }, |
422 | }; |
423 | |
424 | static const struct regmap_access_table bu27008_volatile_regs = { |
425 | .yes_ranges = &bu27008_volatile_ranges[0], |
426 | .n_yes_ranges = ARRAY_SIZE(bu27008_volatile_ranges), |
427 | }; |
428 | |
429 | static const struct regmap_access_table bu27010_volatile_regs = { |
430 | .yes_ranges = &bu27010_volatile_ranges[0], |
431 | .n_yes_ranges = ARRAY_SIZE(bu27010_volatile_ranges), |
432 | }; |
433 | |
434 | static const struct regmap_range bu27008_read_only_ranges[] = { |
435 | { |
436 | .range_min = BU27008_REG_DATA0_LO, |
437 | .range_max = BU27008_REG_DATA3_HI, |
438 | }, { |
439 | .range_min = BU27008_REG_MANUFACTURER_ID, |
440 | .range_max = BU27008_REG_MANUFACTURER_ID, |
441 | }, |
442 | }; |
443 | |
444 | static const struct regmap_range bu27010_read_only_ranges[] = { |
445 | { |
446 | .range_min = BU27008_REG_DATA0_LO, |
447 | .range_max = BU27010_REG_FIFO_DATA_HI, |
448 | }, { |
449 | .range_min = BU27010_REG_MANUFACTURER_ID, |
450 | .range_max = BU27010_REG_MANUFACTURER_ID, |
451 | } |
452 | }; |
453 | |
454 | static const struct regmap_access_table bu27008_ro_regs = { |
455 | .no_ranges = &bu27008_read_only_ranges[0], |
456 | .n_no_ranges = ARRAY_SIZE(bu27008_read_only_ranges), |
457 | }; |
458 | |
459 | static const struct regmap_access_table bu27010_ro_regs = { |
460 | .no_ranges = &bu27010_read_only_ranges[0], |
461 | .n_no_ranges = ARRAY_SIZE(bu27010_read_only_ranges), |
462 | }; |
463 | |
464 | static const struct regmap_config bu27008_regmap = { |
465 | .reg_bits = 8, |
466 | .val_bits = 8, |
467 | .max_register = BU27008_REG_MAX, |
468 | .cache_type = REGCACHE_RBTREE, |
469 | .volatile_table = &bu27008_volatile_regs, |
470 | .wr_table = &bu27008_ro_regs, |
471 | /* |
472 | * All register writes are serialized by the mutex which protects the |
473 | * scale setting/getting. This is needed because scale is combined by |
474 | * gain and integration time settings and we need to ensure those are |
475 | * not read / written when scale is being computed. |
476 | * |
477 | * As a result of this serializing, we don't need regmap locking. Note, |
478 | * this is not true if we add any configurations which are not |
479 | * serialized by the mutex and which may need for example a protected |
480 | * read-modify-write cycle (eg. regmap_update_bits()). Please, revise |
481 | * this when adding features to the driver. |
482 | */ |
483 | .disable_locking = true, |
484 | }; |
485 | |
486 | static const struct regmap_config bu27010_regmap = { |
487 | .reg_bits = 8, |
488 | .val_bits = 8, |
489 | |
490 | .max_register = BU27010_REG_MAX, |
491 | .cache_type = REGCACHE_RBTREE, |
492 | .volatile_table = &bu27010_volatile_regs, |
493 | .wr_table = &bu27010_ro_regs, |
494 | .disable_locking = true, |
495 | }; |
496 | |
497 | static int bu27008_write_gain_sel(struct bu27008_data *data, int sel) |
498 | { |
499 | int regval; |
500 | |
501 | regval = FIELD_PREP(BU27008_MASK_RGBC_GAIN, sel); |
502 | |
503 | /* |
504 | * We do always set also the LOW bits of IR-gain because othervice we |
505 | * would risk resulting an invalid GAIN register value. |
506 | * |
507 | * We could allow setting separate gains for RGBC and IR when the |
508 | * values were such that HW could support both gain settings. |
509 | * Eg, when the shared bits were same for both gain values. |
510 | * |
511 | * This, however, has a negligible benefit compared to the increased |
512 | * software complexity when we would need to go through the gains |
513 | * for both channels separately when the integration time changes. |
514 | * This would end up with nasty logic for computing gain values for |
515 | * both channels - and rejecting them if shared bits changed. |
516 | * |
517 | * We should then build the logic by guessing what a user prefers. |
518 | * RGBC or IR gains correctly set while other jumps to odd value? |
519 | * Maybe look-up a value where both gains are somehow optimized |
520 | * <what this somehow is, is ATM unknown to us>. Or maybe user would |
521 | * expect us to reject changes when optimal gains can't be set to both |
522 | * channels w/given integration time. At best that would result |
523 | * solution that works well for a very specific subset of |
524 | * configurations but causes unexpected corner-cases. |
525 | * |
526 | * So, we keep it simple. Always set same selector to IR and RGBC. |
527 | * We disallow setting IR (as I expect that most of the users are |
528 | * interested in RGBC). This way we can show the user that the scales |
529 | * for RGBC and IR channels are different (1X Vs 2X with sel 0) while |
530 | * still keeping the operation deterministic. |
531 | */ |
532 | regval |= FIELD_PREP(BU27008_MASK_IR_GAIN_LO, sel); |
533 | |
534 | return regmap_update_bits(map: data->regmap, BU27008_REG_MODE_CONTROL2, |
535 | BU27008_MASK_RGBC_GAIN, val: regval); |
536 | } |
537 | |
538 | static int bu27010_write_gain_sel(struct bu27008_data *data, int sel) |
539 | { |
540 | unsigned int regval; |
541 | int ret, chan_selector; |
542 | |
543 | /* |
544 | * Gain 'selector' is composed of two registers. Selector is 6bit value, |
545 | * 4 high bits being the RGBC gain fieild in MODE_CONTROL1 register and |
546 | * two low bits being the channel specific gain in MODE_CONTROL2. |
547 | * |
548 | * Let's take the 4 high bits of whole 6 bit selector, and prepare |
549 | * the MODE_CONTROL1 value (RGBC gain part). |
550 | */ |
551 | regval = FIELD_PREP(BU27010_MASK_RGBC_GAIN, (sel >> 2)); |
552 | |
553 | ret = regmap_update_bits(map: data->regmap, BU27008_REG_MODE_CONTROL1, |
554 | BU27010_MASK_RGBC_GAIN, val: regval); |
555 | if (ret) |
556 | return ret; |
557 | |
558 | /* |
559 | * Two low two bits of the selector must be written for all 4 |
560 | * channels in the MODE_CONTROL2 register. Copy these two bits for |
561 | * all channels. |
562 | */ |
563 | chan_selector = sel & GENMASK(1, 0); |
564 | |
565 | regval = FIELD_PREP(BU27010_MASK_DATA0_GAIN, chan_selector); |
566 | regval |= FIELD_PREP(BU27010_MASK_DATA1_GAIN, chan_selector); |
567 | regval |= FIELD_PREP(BU27010_MASK_DATA2_GAIN, chan_selector); |
568 | regval |= FIELD_PREP(BU27010_MASK_DATA3_GAIN, chan_selector); |
569 | |
570 | return regmap_write(map: data->regmap, BU27008_REG_MODE_CONTROL2, val: regval); |
571 | } |
572 | |
573 | static int bu27008_get_gain_sel(struct bu27008_data *data, int *sel) |
574 | { |
575 | int ret; |
576 | |
577 | /* |
578 | * If we always "lock" the gain selectors for all channels to prevent |
579 | * unsupported configs, then it does not matter which channel is used |
580 | * we can just return selector from any of them. |
581 | * |
582 | * This, however is not true if we decide to support only 4X and 16X |
583 | * and then individual gains for channels. Currently this is not the |
584 | * case. |
585 | * |
586 | * If we some day decide to support individual gains, then we need to |
587 | * have channel information here. |
588 | */ |
589 | |
590 | ret = regmap_read(map: data->regmap, BU27008_REG_MODE_CONTROL2, val: sel); |
591 | if (ret) |
592 | return ret; |
593 | |
594 | *sel = FIELD_GET(BU27008_MASK_RGBC_GAIN, *sel); |
595 | |
596 | return 0; |
597 | } |
598 | |
599 | static int bu27010_get_gain_sel(struct bu27008_data *data, int *sel) |
600 | { |
601 | int ret, tmp; |
602 | |
603 | /* |
604 | * We always "lock" the gain selectors for all channels to prevent |
605 | * unsupported configs. It does not matter which channel is used |
606 | * we can just return selector from any of them. |
607 | * |
608 | * Read the channel0 gain. |
609 | */ |
610 | ret = regmap_read(map: data->regmap, BU27008_REG_MODE_CONTROL2, val: sel); |
611 | if (ret) |
612 | return ret; |
613 | |
614 | *sel = FIELD_GET(BU27010_MASK_DATA0_GAIN, *sel); |
615 | |
616 | /* Read the shared gain */ |
617 | ret = regmap_read(map: data->regmap, BU27008_REG_MODE_CONTROL1, val: &tmp); |
618 | if (ret) |
619 | return ret; |
620 | |
621 | /* |
622 | * The gain selector is made as a combination of common RGBC gain and |
623 | * the channel specific gain. The channel specific gain forms the low |
624 | * bits of selector and RGBC gain is appended right after it. |
625 | * |
626 | * Compose the selector from channel0 gain and shared RGBC gain. |
627 | */ |
628 | *sel |= FIELD_GET(BU27010_MASK_RGBC_GAIN, tmp) << fls(BU27010_MASK_DATA0_GAIN); |
629 | |
630 | return ret; |
631 | } |
632 | |
633 | static int bu27008_chip_init(struct bu27008_data *data) |
634 | { |
635 | int ret; |
636 | |
637 | ret = regmap_write_bits(map: data->regmap, BU27008_REG_SYSTEM_CONTROL, |
638 | BU27008_MASK_SW_RESET, BU27008_MASK_SW_RESET); |
639 | if (ret) |
640 | return dev_err_probe(dev: data->dev, err: ret, fmt: "Sensor reset failed\n" ); |
641 | |
642 | /* |
643 | * The data-sheet does not tell how long performing the IC reset takes. |
644 | * However, the data-sheet says the minimum time it takes the IC to be |
645 | * able to take inputs after power is applied, is 100 uS. I'd assume |
646 | * > 1 mS is enough. |
647 | */ |
648 | msleep(msecs: 1); |
649 | |
650 | ret = regmap_reinit_cache(map: data->regmap, config: data->cd->regmap_cfg); |
651 | if (ret) |
652 | dev_err(data->dev, "Failed to reinit reg cache\n" ); |
653 | |
654 | return ret; |
655 | } |
656 | |
657 | static int bu27010_chip_init(struct bu27008_data *data) |
658 | { |
659 | int ret; |
660 | |
661 | ret = regmap_write_bits(map: data->regmap, BU27008_REG_SYSTEM_CONTROL, |
662 | BU27010_MASK_SW_RESET, BU27010_MASK_SW_RESET); |
663 | if (ret) |
664 | return dev_err_probe(dev: data->dev, err: ret, fmt: "Sensor reset failed\n" ); |
665 | |
666 | msleep(msecs: 1); |
667 | |
668 | /* Power ON*/ |
669 | ret = regmap_write_bits(map: data->regmap, BU27010_REG_POWER, |
670 | BU27010_MASK_POWER, BU27010_MASK_POWER); |
671 | if (ret) |
672 | return dev_err_probe(dev: data->dev, err: ret, fmt: "Sensor power-on failed\n" ); |
673 | |
674 | msleep(msecs: 1); |
675 | |
676 | /* Release blocks from reset */ |
677 | ret = regmap_write_bits(map: data->regmap, BU27010_REG_RESET, |
678 | BU27010_MASK_RESET, BU27010_RESET_RELEASE); |
679 | if (ret) |
680 | return dev_err_probe(dev: data->dev, err: ret, fmt: "Sensor powering failed\n" ); |
681 | |
682 | msleep(msecs: 1); |
683 | |
684 | /* |
685 | * The IRQ enabling on BU27010 is done in a peculiar way. The IRQ |
686 | * enabling is not a bit mask where individual IRQs could be enabled but |
687 | * a field which values are: |
688 | * 00 => IRQs disabled |
689 | * 01 => Data-ready (RGBC/IR) |
690 | * 10 => Data-ready (flicker) |
691 | * 11 => Flicker FIFO |
692 | * |
693 | * So, only one IRQ can be enabled at a time and enabling for example |
694 | * flicker FIFO would automagically disable data-ready IRQ. |
695 | * |
696 | * Currently the driver does not support the flicker. Hence, we can |
697 | * just treat the RGBC data-ready as single bit which can be enabled / |
698 | * disabled. This works for as long as the second bit in the field |
699 | * stays zero. Here we ensure it gets zeroed. |
700 | */ |
701 | return regmap_clear_bits(map: data->regmap, BU27010_REG_MODE_CONTROL4, |
702 | BU27010_IRQ_DIS_ALL); |
703 | } |
704 | |
705 | static const struct bu27_chip_data bu27010_chip = { |
706 | .name = "bu27010" , |
707 | .chip_init = bu27010_chip_init, |
708 | .get_gain_sel = bu27010_get_gain_sel, |
709 | .write_gain_sel = bu27010_write_gain_sel, |
710 | .regmap_cfg = &bu27010_regmap, |
711 | .gains = &bu27010_gains[0], |
712 | .gains_ir = &bu27010_gains_ir[0], |
713 | .itimes = &bu27010_itimes[0], |
714 | .num_gains = ARRAY_SIZE(bu27010_gains), |
715 | .num_gains_ir = ARRAY_SIZE(bu27010_gains_ir), |
716 | .num_itimes = ARRAY_SIZE(bu27010_itimes), |
717 | .scale1x = BU27010_SCALE_1X, |
718 | .drdy_en_reg = BU27010_REG_MODE_CONTROL4, |
719 | .drdy_en_mask = BU27010_DRDY_EN, |
720 | .meas_en_reg = BU27010_REG_MODE_CONTROL5, |
721 | .meas_en_mask = BU27010_MASK_MEAS_EN, |
722 | .valid_reg = BU27010_REG_MODE_CONTROL5, |
723 | .chan_sel_reg = BU27008_REG_MODE_CONTROL1, |
724 | .chan_sel_mask = BU27010_MASK_CHAN_SEL, |
725 | .int_time_mask = BU27010_MASK_MEAS_MODE, |
726 | .part_id = BU27010_ID, |
727 | }; |
728 | |
729 | static const struct bu27_chip_data bu27008_chip = { |
730 | .name = "bu27008" , |
731 | .chip_init = bu27008_chip_init, |
732 | .get_gain_sel = bu27008_get_gain_sel, |
733 | .write_gain_sel = bu27008_write_gain_sel, |
734 | .regmap_cfg = &bu27008_regmap, |
735 | .gains = &bu27008_gains[0], |
736 | .gains_ir = &bu27008_gains_ir[0], |
737 | .itimes = &bu27008_itimes[0], |
738 | .num_gains = ARRAY_SIZE(bu27008_gains), |
739 | .num_gains_ir = ARRAY_SIZE(bu27008_gains_ir), |
740 | .num_itimes = ARRAY_SIZE(bu27008_itimes), |
741 | .scale1x = BU27008_SCALE_1X, |
742 | .drdy_en_reg = BU27008_REG_MODE_CONTROL3, |
743 | .drdy_en_mask = BU27008_MASK_INT_EN, |
744 | .valid_reg = BU27008_REG_MODE_CONTROL3, |
745 | .meas_en_reg = BU27008_REG_MODE_CONTROL3, |
746 | .meas_en_mask = BU27008_MASK_MEAS_EN, |
747 | .chan_sel_reg = BU27008_REG_MODE_CONTROL3, |
748 | .chan_sel_mask = BU27008_MASK_CHAN_SEL, |
749 | .int_time_mask = BU27008_MASK_MEAS_MODE, |
750 | .part_id = BU27008_ID, |
751 | }; |
752 | |
753 | #define BU27008_MAX_VALID_RESULT_WAIT_US 50000 |
754 | #define BU27008_VALID_RESULT_WAIT_QUANTA_US 1000 |
755 | |
756 | static int bu27008_chan_read_data(struct bu27008_data *data, int reg, int *val) |
757 | { |
758 | int ret, valid; |
759 | __le16 tmp; |
760 | |
761 | ret = regmap_read_poll_timeout(data->regmap, data->cd->valid_reg, |
762 | valid, (valid & BU27008_MASK_VALID), |
763 | BU27008_VALID_RESULT_WAIT_QUANTA_US, |
764 | BU27008_MAX_VALID_RESULT_WAIT_US); |
765 | if (ret) |
766 | return ret; |
767 | |
768 | ret = regmap_bulk_read(map: data->regmap, reg, val: &tmp, val_count: sizeof(tmp)); |
769 | if (ret) |
770 | dev_err(data->dev, "Reading channel data failed\n" ); |
771 | |
772 | *val = le16_to_cpu(tmp); |
773 | |
774 | return ret; |
775 | } |
776 | |
777 | static int bu27008_get_gain(struct bu27008_data *data, struct iio_gts *gts, int *gain) |
778 | { |
779 | int ret, sel; |
780 | |
781 | ret = data->cd->get_gain_sel(data, &sel); |
782 | if (ret) |
783 | return ret; |
784 | |
785 | ret = iio_gts_find_gain_by_sel(gts, sel); |
786 | if (ret < 0) { |
787 | dev_err(data->dev, "unknown gain value 0x%x\n" , sel); |
788 | return ret; |
789 | } |
790 | |
791 | *gain = ret; |
792 | |
793 | return 0; |
794 | } |
795 | |
796 | static int bu27008_set_gain(struct bu27008_data *data, int gain) |
797 | { |
798 | int ret; |
799 | |
800 | ret = iio_gts_find_sel_by_gain(gts: &data->gts, gain); |
801 | if (ret < 0) |
802 | return ret; |
803 | |
804 | return data->cd->write_gain_sel(data, ret); |
805 | } |
806 | |
807 | static int bu27008_get_int_time_sel(struct bu27008_data *data, int *sel) |
808 | { |
809 | int ret, val; |
810 | |
811 | ret = regmap_read(map: data->regmap, BU27008_REG_MODE_CONTROL1, val: &val); |
812 | if (ret) |
813 | return ret; |
814 | |
815 | val &= data->cd->int_time_mask; |
816 | val >>= ffs(data->cd->int_time_mask) - 1; |
817 | |
818 | *sel = val; |
819 | |
820 | return 0; |
821 | } |
822 | |
823 | static int bu27008_set_int_time_sel(struct bu27008_data *data, int sel) |
824 | { |
825 | sel <<= ffs(data->cd->int_time_mask) - 1; |
826 | |
827 | return regmap_update_bits(map: data->regmap, BU27008_REG_MODE_CONTROL1, |
828 | mask: data->cd->int_time_mask, val: sel); |
829 | } |
830 | |
831 | static int bu27008_get_int_time_us(struct bu27008_data *data) |
832 | { |
833 | int ret, sel; |
834 | |
835 | ret = bu27008_get_int_time_sel(data, sel: &sel); |
836 | if (ret) |
837 | return ret; |
838 | |
839 | return iio_gts_find_int_time_by_sel(gts: &data->gts, sel); |
840 | } |
841 | |
842 | static int _bu27008_get_scale(struct bu27008_data *data, bool ir, int *val, |
843 | int *val2) |
844 | { |
845 | struct iio_gts *gts; |
846 | int gain, ret; |
847 | |
848 | if (ir) |
849 | gts = &data->gts_ir; |
850 | else |
851 | gts = &data->gts; |
852 | |
853 | ret = bu27008_get_gain(data, gts, gain: &gain); |
854 | if (ret) |
855 | return ret; |
856 | |
857 | ret = bu27008_get_int_time_us(data); |
858 | if (ret < 0) |
859 | return ret; |
860 | |
861 | return iio_gts_get_scale(gts, gain, time: ret, scale_int: val, scale_nano: val2); |
862 | } |
863 | |
864 | static int bu27008_get_scale(struct bu27008_data *data, bool ir, int *val, |
865 | int *val2) |
866 | { |
867 | int ret; |
868 | |
869 | mutex_lock(&data->mutex); |
870 | ret = _bu27008_get_scale(data, ir, val, val2); |
871 | mutex_unlock(lock: &data->mutex); |
872 | |
873 | return ret; |
874 | } |
875 | |
876 | static int bu27008_set_int_time(struct bu27008_data *data, int time) |
877 | { |
878 | int ret; |
879 | |
880 | ret = iio_gts_find_sel_by_int_time(gts: &data->gts, time); |
881 | if (ret < 0) |
882 | return ret; |
883 | |
884 | return bu27008_set_int_time_sel(data, sel: ret); |
885 | } |
886 | |
887 | /* Try to change the time so that the scale is maintained */ |
888 | static int bu27008_try_set_int_time(struct bu27008_data *data, int int_time_new) |
889 | { |
890 | int ret, old_time_sel, new_time_sel, old_gain, new_gain; |
891 | |
892 | mutex_lock(&data->mutex); |
893 | |
894 | ret = bu27008_get_int_time_sel(data, sel: &old_time_sel); |
895 | if (ret < 0) |
896 | goto unlock_out; |
897 | |
898 | if (!iio_gts_valid_time(gts: &data->gts, time_us: int_time_new)) { |
899 | dev_dbg(data->dev, "Unsupported integration time %u\n" , |
900 | int_time_new); |
901 | |
902 | ret = -EINVAL; |
903 | goto unlock_out; |
904 | } |
905 | |
906 | /* If we already use requested time, then we're done */ |
907 | new_time_sel = iio_gts_find_sel_by_int_time(gts: &data->gts, time: int_time_new); |
908 | if (new_time_sel == old_time_sel) |
909 | goto unlock_out; |
910 | |
911 | ret = bu27008_get_gain(data, gts: &data->gts, gain: &old_gain); |
912 | if (ret) |
913 | goto unlock_out; |
914 | |
915 | ret = iio_gts_find_new_gain_sel_by_old_gain_time(gts: &data->gts, old_gain, |
916 | old_time_sel, new_time_sel, new_gain: &new_gain); |
917 | if (ret) { |
918 | int scale1, scale2; |
919 | bool ok; |
920 | |
921 | _bu27008_get_scale(data, ir: false, val: &scale1, val2: &scale2); |
922 | dev_dbg(data->dev, |
923 | "Can't support time %u with current scale %u %u\n" , |
924 | int_time_new, scale1, scale2); |
925 | |
926 | if (new_gain < 0) |
927 | goto unlock_out; |
928 | |
929 | /* |
930 | * If caller requests for integration time change and we |
931 | * can't support the scale - then the caller should be |
932 | * prepared to 'pick up the pieces and deal with the |
933 | * fact that the scale changed'. |
934 | */ |
935 | ret = iio_find_closest_gain_low(gts: &data->gts, gain: new_gain, in_range: &ok); |
936 | if (!ok) |
937 | dev_dbg(data->dev, "optimal gain out of range\n" ); |
938 | |
939 | if (ret < 0) { |
940 | dev_dbg(data->dev, |
941 | "Total gain increase. Risk of saturation" ); |
942 | ret = iio_gts_get_min_gain(gts: &data->gts); |
943 | if (ret < 0) |
944 | goto unlock_out; |
945 | } |
946 | new_gain = ret; |
947 | dev_dbg(data->dev, "scale changed, new gain %u\n" , new_gain); |
948 | } |
949 | |
950 | ret = bu27008_set_gain(data, gain: new_gain); |
951 | if (ret) |
952 | goto unlock_out; |
953 | |
954 | ret = bu27008_set_int_time(data, time: int_time_new); |
955 | |
956 | unlock_out: |
957 | mutex_unlock(lock: &data->mutex); |
958 | |
959 | return ret; |
960 | } |
961 | |
962 | static int bu27008_meas_set(struct bu27008_data *data, bool enable) |
963 | { |
964 | if (enable) |
965 | return regmap_set_bits(map: data->regmap, reg: data->cd->meas_en_reg, |
966 | bits: data->cd->meas_en_mask); |
967 | return regmap_clear_bits(map: data->regmap, reg: data->cd->meas_en_reg, |
968 | bits: data->cd->meas_en_mask); |
969 | } |
970 | |
971 | static int bu27008_chan_cfg(struct bu27008_data *data, |
972 | struct iio_chan_spec const *chan) |
973 | { |
974 | int chan_sel; |
975 | |
976 | if (chan->scan_index == BU27008_BLUE) |
977 | chan_sel = BU27008_BLUE2_CLEAR3; |
978 | else |
979 | chan_sel = BU27008_CLEAR2_IR3; |
980 | |
981 | /* |
982 | * prepare bitfield for channel sel. The FIELD_PREP works only when |
983 | * mask is constant. In our case the mask is assigned based on the |
984 | * chip type. Hence the open-coded FIELD_PREP here. We don't bother |
985 | * zeroing the irrelevant bits though - update_bits takes care of that. |
986 | */ |
987 | chan_sel <<= ffs(data->cd->chan_sel_mask) - 1; |
988 | |
989 | return regmap_update_bits(map: data->regmap, reg: data->cd->chan_sel_reg, |
990 | BU27008_MASK_CHAN_SEL, val: chan_sel); |
991 | } |
992 | |
993 | static int bu27008_read_one(struct bu27008_data *data, struct iio_dev *idev, |
994 | struct iio_chan_spec const *chan, int *val, int *val2) |
995 | { |
996 | int ret, int_time; |
997 | |
998 | ret = bu27008_chan_cfg(data, chan); |
999 | if (ret) |
1000 | return ret; |
1001 | |
1002 | ret = bu27008_meas_set(data, enable: true); |
1003 | if (ret) |
1004 | return ret; |
1005 | |
1006 | ret = bu27008_get_int_time_us(data); |
1007 | if (ret < 0) |
1008 | int_time = BU27008_MEAS_TIME_MAX_MS; |
1009 | else |
1010 | int_time = ret / USEC_PER_MSEC; |
1011 | |
1012 | msleep(msecs: int_time); |
1013 | |
1014 | ret = bu27008_chan_read_data(data, reg: chan->address, val); |
1015 | if (!ret) |
1016 | ret = IIO_VAL_INT; |
1017 | |
1018 | if (bu27008_meas_set(data, enable: false)) |
1019 | dev_warn(data->dev, "measurement disabling failed\n" ); |
1020 | |
1021 | return ret; |
1022 | } |
1023 | |
1024 | #define BU27008_LUX_DATA_RED 0 |
1025 | #define BU27008_LUX_DATA_GREEN 1 |
1026 | #define BU27008_LUX_DATA_BLUE 2 |
1027 | #define BU27008_LUX_DATA_IR 3 |
1028 | #define LUX_DATA_SIZE (BU27008_NUM_HW_CHANS * sizeof(__le16)) |
1029 | |
1030 | static int bu27008_read_lux_chans(struct bu27008_data *data, unsigned int time, |
1031 | __le16 *chan_data) |
1032 | { |
1033 | int ret, chan_sel, tmpret, valid; |
1034 | |
1035 | chan_sel = BU27008_BLUE2_IR3 << (ffs(data->cd->chan_sel_mask) - 1); |
1036 | |
1037 | ret = regmap_update_bits(map: data->regmap, reg: data->cd->chan_sel_reg, |
1038 | mask: data->cd->chan_sel_mask, val: chan_sel); |
1039 | if (ret) |
1040 | return ret; |
1041 | |
1042 | ret = bu27008_meas_set(data, enable: true); |
1043 | if (ret) |
1044 | return ret; |
1045 | |
1046 | msleep(msecs: time / USEC_PER_MSEC); |
1047 | |
1048 | ret = regmap_read_poll_timeout(data->regmap, data->cd->valid_reg, |
1049 | valid, (valid & BU27008_MASK_VALID), |
1050 | BU27008_VALID_RESULT_WAIT_QUANTA_US, |
1051 | BU27008_MAX_VALID_RESULT_WAIT_US); |
1052 | if (ret) |
1053 | goto out; |
1054 | |
1055 | ret = regmap_bulk_read(map: data->regmap, BU27008_REG_DATA0_LO, val: chan_data, |
1056 | LUX_DATA_SIZE); |
1057 | if (ret) |
1058 | goto out; |
1059 | out: |
1060 | tmpret = bu27008_meas_set(data, enable: false); |
1061 | if (tmpret) |
1062 | dev_warn(data->dev, "Stopping measurement failed\n" ); |
1063 | |
1064 | return ret; |
1065 | } |
1066 | |
1067 | /* |
1068 | * Following equation for computing lux out of register values was given by |
1069 | * ROHM HW colleagues; |
1070 | * |
1071 | * Red = RedData*1024 / Gain * 20 / meas_mode |
1072 | * Green = GreenData* 1024 / Gain * 20 / meas_mode |
1073 | * Blue = BlueData* 1024 / Gain * 20 / meas_mode |
1074 | * IR = IrData* 1024 / Gain * 20 / meas_mode |
1075 | * |
1076 | * where meas_mode is the integration time in mS / 10 |
1077 | * |
1078 | * IRratio = (IR > 0.18 * Green) ? 0 : 1 |
1079 | * |
1080 | * Lx = max(c1*Red + c2*Green + c3*Blue,0) |
1081 | * |
1082 | * for |
1083 | * IRratio 0: c1 = -0.00002237, c2 = 0.0003219, c3 = -0.000120371 |
1084 | * IRratio 1: c1 = -0.00001074, c2 = 0.000305415, c3 = -0.000129367 |
1085 | */ |
1086 | |
1087 | /* |
1088 | * The max chan data is 0xffff. When we multiply it by 1024 * 20, we'll get |
1089 | * 0x4FFFB000 which still fits in 32-bit integer. This won't overflow. |
1090 | */ |
1091 | #define NORM_CHAN_DATA_FOR_LX_CALC(chan, gain, time) (le16_to_cpu(chan) * \ |
1092 | 1024 * 20 / (gain) / (time)) |
1093 | static u64 bu27008_calc_nlux(struct bu27008_data *data, __le16 *lux_data, |
1094 | unsigned int gain, unsigned int gain_ir, unsigned int time) |
1095 | { |
1096 | unsigned int red, green, blue, ir; |
1097 | s64 c1, c2, c3, nlux; |
1098 | |
1099 | time /= 10000; |
1100 | ir = NORM_CHAN_DATA_FOR_LX_CALC(lux_data[BU27008_LUX_DATA_IR], gain_ir, time); |
1101 | red = NORM_CHAN_DATA_FOR_LX_CALC(lux_data[BU27008_LUX_DATA_RED], gain, time); |
1102 | green = NORM_CHAN_DATA_FOR_LX_CALC(lux_data[BU27008_LUX_DATA_GREEN], gain, time); |
1103 | blue = NORM_CHAN_DATA_FOR_LX_CALC(lux_data[BU27008_LUX_DATA_BLUE], gain, time); |
1104 | |
1105 | if ((u64)ir * 100LLU > (u64)green * 18LLU) { |
1106 | c1 = -22370; |
1107 | c2 = 321900; |
1108 | c3 = -120371; |
1109 | } else { |
1110 | c1 = -10740; |
1111 | c2 = 305415; |
1112 | c3 = -129367; |
1113 | } |
1114 | nlux = c1 * red + c2 * green + c3 * blue; |
1115 | |
1116 | return max_t(s64, 0, nlux); |
1117 | } |
1118 | |
1119 | static int bu27008_get_time_n_gains(struct bu27008_data *data, |
1120 | unsigned int *gain, unsigned int *gain_ir, unsigned int *time) |
1121 | { |
1122 | int ret; |
1123 | |
1124 | ret = bu27008_get_gain(data, gts: &data->gts, gain); |
1125 | if (ret < 0) |
1126 | return ret; |
1127 | |
1128 | ret = bu27008_get_gain(data, gts: &data->gts_ir, gain: gain_ir); |
1129 | if (ret < 0) |
1130 | return ret; |
1131 | |
1132 | ret = bu27008_get_int_time_us(data); |
1133 | if (ret < 0) |
1134 | return ret; |
1135 | |
1136 | /* Max integration time is 400000. Fits in signed int. */ |
1137 | *time = ret; |
1138 | |
1139 | return 0; |
1140 | } |
1141 | |
1142 | struct bu27008_buf { |
1143 | __le16 chan[BU27008_NUM_HW_CHANS]; |
1144 | u64 lux __aligned(8); |
1145 | s64 ts __aligned(8); |
1146 | }; |
1147 | |
1148 | static int bu27008_buffer_fill_lux(struct bu27008_data *data, |
1149 | struct bu27008_buf *raw) |
1150 | { |
1151 | unsigned int gain, gain_ir, time; |
1152 | int ret; |
1153 | |
1154 | ret = bu27008_get_time_n_gains(data, gain: &gain, gain_ir: &gain_ir, time: &time); |
1155 | if (ret) |
1156 | return ret; |
1157 | |
1158 | raw->lux = bu27008_calc_nlux(data, lux_data: raw->chan, gain, gain_ir, time); |
1159 | |
1160 | return 0; |
1161 | } |
1162 | |
1163 | static int bu27008_read_lux(struct bu27008_data *data, struct iio_dev *idev, |
1164 | struct iio_chan_spec const *chan, |
1165 | int *val, int *val2) |
1166 | { |
1167 | __le16 lux_data[BU27008_NUM_HW_CHANS]; |
1168 | unsigned int gain, gain_ir, time; |
1169 | u64 nlux; |
1170 | int ret; |
1171 | |
1172 | ret = bu27008_get_time_n_gains(data, gain: &gain, gain_ir: &gain_ir, time: &time); |
1173 | if (ret) |
1174 | return ret; |
1175 | |
1176 | ret = bu27008_read_lux_chans(data, time, chan_data: lux_data); |
1177 | if (ret) |
1178 | return ret; |
1179 | |
1180 | nlux = bu27008_calc_nlux(data, lux_data, gain, gain_ir, time); |
1181 | *val = (int)nlux; |
1182 | *val2 = nlux >> 32LLU; |
1183 | |
1184 | return IIO_VAL_INT_64; |
1185 | } |
1186 | |
1187 | static int bu27008_read_raw(struct iio_dev *idev, |
1188 | struct iio_chan_spec const *chan, |
1189 | int *val, int *val2, long mask) |
1190 | { |
1191 | struct bu27008_data *data = iio_priv(indio_dev: idev); |
1192 | int busy, ret; |
1193 | |
1194 | switch (mask) { |
1195 | case IIO_CHAN_INFO_RAW: |
1196 | busy = iio_device_claim_direct_mode(indio_dev: idev); |
1197 | if (busy) |
1198 | return -EBUSY; |
1199 | |
1200 | mutex_lock(&data->mutex); |
1201 | if (chan->type == IIO_LIGHT) |
1202 | ret = bu27008_read_lux(data, idev, chan, val, val2); |
1203 | else |
1204 | ret = bu27008_read_one(data, idev, chan, val, val2); |
1205 | mutex_unlock(lock: &data->mutex); |
1206 | |
1207 | iio_device_release_direct_mode(indio_dev: idev); |
1208 | |
1209 | return ret; |
1210 | |
1211 | case IIO_CHAN_INFO_SCALE: |
1212 | if (chan->type == IIO_LIGHT) { |
1213 | *val = 0; |
1214 | *val2 = 1; |
1215 | return IIO_VAL_INT_PLUS_NANO; |
1216 | } |
1217 | ret = bu27008_get_scale(data, ir: chan->scan_index == BU27008_IR, |
1218 | val, val2); |
1219 | if (ret) |
1220 | return ret; |
1221 | |
1222 | return IIO_VAL_INT_PLUS_NANO; |
1223 | |
1224 | case IIO_CHAN_INFO_INT_TIME: |
1225 | ret = bu27008_get_int_time_us(data); |
1226 | if (ret < 0) |
1227 | return ret; |
1228 | |
1229 | *val = 0; |
1230 | *val2 = ret; |
1231 | |
1232 | return IIO_VAL_INT_PLUS_MICRO; |
1233 | |
1234 | default: |
1235 | return -EINVAL; |
1236 | } |
1237 | } |
1238 | |
1239 | /* Called if the new scale could not be supported with existing int-time */ |
1240 | static int bu27008_try_find_new_time_gain(struct bu27008_data *data, int val, |
1241 | int val2, int *gain_sel) |
1242 | { |
1243 | int i, ret, new_time_sel; |
1244 | |
1245 | for (i = 0; i < data->gts.num_itime; i++) { |
1246 | new_time_sel = data->gts.itime_table[i].sel; |
1247 | ret = iio_gts_find_gain_sel_for_scale_using_time(gts: &data->gts, |
1248 | time_sel: new_time_sel, scale_int: val, scale_nano: val2, gain_sel); |
1249 | if (!ret) |
1250 | break; |
1251 | } |
1252 | if (i == data->gts.num_itime) { |
1253 | dev_err(data->dev, "Can't support scale %u %u\n" , val, val2); |
1254 | |
1255 | return -EINVAL; |
1256 | } |
1257 | |
1258 | return bu27008_set_int_time_sel(data, sel: new_time_sel); |
1259 | } |
1260 | |
1261 | static int bu27008_set_scale(struct bu27008_data *data, |
1262 | struct iio_chan_spec const *chan, |
1263 | int val, int val2) |
1264 | { |
1265 | int ret, gain_sel, time_sel; |
1266 | |
1267 | if (chan->scan_index == BU27008_IR) |
1268 | return -EINVAL; |
1269 | |
1270 | mutex_lock(&data->mutex); |
1271 | |
1272 | ret = bu27008_get_int_time_sel(data, sel: &time_sel); |
1273 | if (ret < 0) |
1274 | goto unlock_out; |
1275 | |
1276 | ret = iio_gts_find_gain_sel_for_scale_using_time(gts: &data->gts, time_sel, |
1277 | scale_int: val, scale_nano: val2, gain_sel: &gain_sel); |
1278 | if (ret) { |
1279 | ret = bu27008_try_find_new_time_gain(data, val, val2, gain_sel: &gain_sel); |
1280 | if (ret) |
1281 | goto unlock_out; |
1282 | |
1283 | } |
1284 | ret = data->cd->write_gain_sel(data, gain_sel); |
1285 | |
1286 | unlock_out: |
1287 | mutex_unlock(lock: &data->mutex); |
1288 | |
1289 | return ret; |
1290 | } |
1291 | |
1292 | static int bu27008_write_raw_get_fmt(struct iio_dev *indio_dev, |
1293 | struct iio_chan_spec const *chan, |
1294 | long mask) |
1295 | { |
1296 | |
1297 | switch (mask) { |
1298 | case IIO_CHAN_INFO_SCALE: |
1299 | return IIO_VAL_INT_PLUS_NANO; |
1300 | case IIO_CHAN_INFO_INT_TIME: |
1301 | return IIO_VAL_INT_PLUS_MICRO; |
1302 | default: |
1303 | return -EINVAL; |
1304 | } |
1305 | } |
1306 | |
1307 | static int bu27008_write_raw(struct iio_dev *idev, |
1308 | struct iio_chan_spec const *chan, |
1309 | int val, int val2, long mask) |
1310 | { |
1311 | struct bu27008_data *data = iio_priv(indio_dev: idev); |
1312 | int ret; |
1313 | |
1314 | /* |
1315 | * Do not allow changing scale when measurement is ongoing as doing so |
1316 | * could make values in the buffer inconsistent. |
1317 | */ |
1318 | ret = iio_device_claim_direct_mode(indio_dev: idev); |
1319 | if (ret) |
1320 | return ret; |
1321 | |
1322 | switch (mask) { |
1323 | case IIO_CHAN_INFO_SCALE: |
1324 | ret = bu27008_set_scale(data, chan, val, val2); |
1325 | break; |
1326 | case IIO_CHAN_INFO_INT_TIME: |
1327 | if (val) { |
1328 | ret = -EINVAL; |
1329 | break; |
1330 | } |
1331 | ret = bu27008_try_set_int_time(data, int_time_new: val2); |
1332 | break; |
1333 | default: |
1334 | ret = -EINVAL; |
1335 | break; |
1336 | } |
1337 | iio_device_release_direct_mode(indio_dev: idev); |
1338 | |
1339 | return ret; |
1340 | } |
1341 | |
1342 | static int bu27008_read_avail(struct iio_dev *idev, |
1343 | struct iio_chan_spec const *chan, const int **vals, |
1344 | int *type, int *length, long mask) |
1345 | { |
1346 | struct bu27008_data *data = iio_priv(indio_dev: idev); |
1347 | |
1348 | switch (mask) { |
1349 | case IIO_CHAN_INFO_INT_TIME: |
1350 | return iio_gts_avail_times(gts: &data->gts, vals, type, length); |
1351 | case IIO_CHAN_INFO_SCALE: |
1352 | if (chan->channel2 == IIO_MOD_LIGHT_IR) |
1353 | return iio_gts_all_avail_scales(gts: &data->gts_ir, vals, |
1354 | type, length); |
1355 | return iio_gts_all_avail_scales(gts: &data->gts, vals, type, length); |
1356 | default: |
1357 | return -EINVAL; |
1358 | } |
1359 | } |
1360 | |
1361 | static int bu27008_update_scan_mode(struct iio_dev *idev, |
1362 | const unsigned long *scan_mask) |
1363 | { |
1364 | struct bu27008_data *data = iio_priv(indio_dev: idev); |
1365 | int chan_sel; |
1366 | |
1367 | /* Configure channel selection */ |
1368 | if (test_bit(BU27008_BLUE, idev->active_scan_mask)) { |
1369 | if (test_bit(BU27008_CLEAR, idev->active_scan_mask)) |
1370 | chan_sel = BU27008_BLUE2_CLEAR3; |
1371 | else |
1372 | chan_sel = BU27008_BLUE2_IR3; |
1373 | } else { |
1374 | chan_sel = BU27008_CLEAR2_IR3; |
1375 | } |
1376 | |
1377 | chan_sel <<= ffs(data->cd->chan_sel_mask) - 1; |
1378 | |
1379 | return regmap_update_bits(map: data->regmap, reg: data->cd->chan_sel_reg, |
1380 | mask: data->cd->chan_sel_mask, val: chan_sel); |
1381 | } |
1382 | |
1383 | static const struct iio_info bu27008_info = { |
1384 | .read_raw = &bu27008_read_raw, |
1385 | .write_raw = &bu27008_write_raw, |
1386 | .write_raw_get_fmt = &bu27008_write_raw_get_fmt, |
1387 | .read_avail = &bu27008_read_avail, |
1388 | .update_scan_mode = bu27008_update_scan_mode, |
1389 | .validate_trigger = iio_validate_own_trigger, |
1390 | }; |
1391 | |
1392 | static int bu27008_trigger_set_state(struct iio_trigger *trig, bool state) |
1393 | { |
1394 | struct bu27008_data *data = iio_trigger_get_drvdata(trig); |
1395 | int ret; |
1396 | |
1397 | |
1398 | if (state) |
1399 | ret = regmap_set_bits(map: data->regmap, reg: data->cd->drdy_en_reg, |
1400 | bits: data->cd->drdy_en_mask); |
1401 | else |
1402 | ret = regmap_clear_bits(map: data->regmap, reg: data->cd->drdy_en_reg, |
1403 | bits: data->cd->drdy_en_mask); |
1404 | if (ret) |
1405 | dev_err(data->dev, "Failed to set trigger state\n" ); |
1406 | |
1407 | return ret; |
1408 | } |
1409 | |
1410 | static void bu27008_trigger_reenable(struct iio_trigger *trig) |
1411 | { |
1412 | struct bu27008_data *data = iio_trigger_get_drvdata(trig); |
1413 | |
1414 | enable_irq(irq: data->irq); |
1415 | } |
1416 | |
1417 | static const struct iio_trigger_ops bu27008_trigger_ops = { |
1418 | .set_trigger_state = bu27008_trigger_set_state, |
1419 | .reenable = bu27008_trigger_reenable, |
1420 | }; |
1421 | |
1422 | static irqreturn_t bu27008_trigger_handler(int irq, void *p) |
1423 | { |
1424 | struct iio_poll_func *pf = p; |
1425 | struct iio_dev *idev = pf->indio_dev; |
1426 | struct bu27008_data *data = iio_priv(indio_dev: idev); |
1427 | struct bu27008_buf raw; |
1428 | int ret, dummy; |
1429 | |
1430 | memset(&raw, 0, sizeof(raw)); |
1431 | |
1432 | /* |
1433 | * After some measurements, it seems reading the |
1434 | * BU27008_REG_MODE_CONTROL3 debounces the IRQ line |
1435 | */ |
1436 | ret = regmap_read(map: data->regmap, reg: data->cd->valid_reg, val: &dummy); |
1437 | if (ret < 0) |
1438 | goto err_read; |
1439 | |
1440 | ret = regmap_bulk_read(map: data->regmap, BU27008_REG_DATA0_LO, val: &raw.chan, |
1441 | val_count: sizeof(raw.chan)); |
1442 | if (ret < 0) |
1443 | goto err_read; |
1444 | |
1445 | if (test_bit(BU27008_LUX, idev->active_scan_mask)) { |
1446 | ret = bu27008_buffer_fill_lux(data, raw: &raw); |
1447 | if (ret) |
1448 | goto err_read; |
1449 | } |
1450 | |
1451 | iio_push_to_buffers_with_timestamp(indio_dev: idev, data: &raw, timestamp: pf->timestamp); |
1452 | err_read: |
1453 | iio_trigger_notify_done(trig: idev->trig); |
1454 | |
1455 | return IRQ_HANDLED; |
1456 | } |
1457 | |
1458 | static int bu27008_buffer_preenable(struct iio_dev *idev) |
1459 | { |
1460 | struct bu27008_data *data = iio_priv(indio_dev: idev); |
1461 | |
1462 | return bu27008_meas_set(data, enable: true); |
1463 | } |
1464 | |
1465 | static int bu27008_buffer_postdisable(struct iio_dev *idev) |
1466 | { |
1467 | struct bu27008_data *data = iio_priv(indio_dev: idev); |
1468 | |
1469 | return bu27008_meas_set(data, enable: false); |
1470 | } |
1471 | |
1472 | static const struct iio_buffer_setup_ops bu27008_buffer_ops = { |
1473 | .preenable = bu27008_buffer_preenable, |
1474 | .postdisable = bu27008_buffer_postdisable, |
1475 | }; |
1476 | |
1477 | static irqreturn_t bu27008_data_rdy_poll(int irq, void *private) |
1478 | { |
1479 | /* |
1480 | * The BU27008 keeps IRQ asserted until we read the VALID bit from |
1481 | * a register. We need to keep the IRQ disabled until then. |
1482 | */ |
1483 | disable_irq_nosync(irq); |
1484 | iio_trigger_poll(trig: private); |
1485 | |
1486 | return IRQ_HANDLED; |
1487 | } |
1488 | |
1489 | static int bu27008_setup_trigger(struct bu27008_data *data, struct iio_dev *idev) |
1490 | { |
1491 | struct iio_trigger *itrig; |
1492 | char *name; |
1493 | int ret; |
1494 | |
1495 | ret = devm_iio_triggered_buffer_setup(data->dev, idev, |
1496 | &iio_pollfunc_store_time, |
1497 | bu27008_trigger_handler, |
1498 | &bu27008_buffer_ops); |
1499 | if (ret) |
1500 | return dev_err_probe(dev: data->dev, err: ret, |
1501 | fmt: "iio_triggered_buffer_setup_ext FAIL\n" ); |
1502 | |
1503 | itrig = devm_iio_trigger_alloc(data->dev, "%sdata-rdy-dev%d" , |
1504 | idev->name, iio_device_id(idev)); |
1505 | if (!itrig) |
1506 | return -ENOMEM; |
1507 | |
1508 | data->trig = itrig; |
1509 | |
1510 | itrig->ops = &bu27008_trigger_ops; |
1511 | iio_trigger_set_drvdata(trig: itrig, data); |
1512 | |
1513 | name = devm_kasprintf(dev: data->dev, GFP_KERNEL, fmt: "%s-bu27008" , |
1514 | dev_name(dev: data->dev)); |
1515 | |
1516 | ret = devm_request_irq(dev: data->dev, irq: data->irq, |
1517 | handler: &bu27008_data_rdy_poll, |
1518 | irqflags: 0, devname: name, dev_id: itrig); |
1519 | if (ret) |
1520 | return dev_err_probe(dev: data->dev, err: ret, fmt: "Could not request IRQ\n" ); |
1521 | |
1522 | ret = devm_iio_trigger_register(dev: data->dev, trig_info: itrig); |
1523 | if (ret) |
1524 | return dev_err_probe(dev: data->dev, err: ret, |
1525 | fmt: "Trigger registration failed\n" ); |
1526 | |
1527 | /* set default trigger */ |
1528 | idev->trig = iio_trigger_get(trig: itrig); |
1529 | |
1530 | return 0; |
1531 | } |
1532 | |
1533 | static int bu27008_probe(struct i2c_client *i2c) |
1534 | { |
1535 | struct device *dev = &i2c->dev; |
1536 | struct bu27008_data *data; |
1537 | struct regmap *regmap; |
1538 | unsigned int part_id, reg; |
1539 | struct iio_dev *idev; |
1540 | int ret; |
1541 | |
1542 | idev = devm_iio_device_alloc(parent: dev, sizeof_priv: sizeof(*data)); |
1543 | if (!idev) |
1544 | return -ENOMEM; |
1545 | |
1546 | ret = devm_regulator_get_enable(dev, id: "vdd" ); |
1547 | if (ret) |
1548 | return dev_err_probe(dev, err: ret, fmt: "Failed to get regulator\n" ); |
1549 | |
1550 | data = iio_priv(indio_dev: idev); |
1551 | |
1552 | data->cd = device_get_match_data(dev: &i2c->dev); |
1553 | if (!data->cd) |
1554 | return -ENODEV; |
1555 | |
1556 | regmap = devm_regmap_init_i2c(i2c, data->cd->regmap_cfg); |
1557 | if (IS_ERR(ptr: regmap)) |
1558 | return dev_err_probe(dev, err: PTR_ERR(ptr: regmap), |
1559 | fmt: "Failed to initialize Regmap\n" ); |
1560 | |
1561 | |
1562 | ret = regmap_read(map: regmap, BU27008_REG_SYSTEM_CONTROL, val: ®); |
1563 | if (ret) |
1564 | return dev_err_probe(dev, err: ret, fmt: "Failed to access sensor\n" ); |
1565 | |
1566 | part_id = FIELD_GET(BU27008_MASK_PART_ID, reg); |
1567 | |
1568 | if (part_id != data->cd->part_id) |
1569 | dev_warn(dev, "unknown device 0x%x\n" , part_id); |
1570 | |
1571 | ret = devm_iio_init_iio_gts(dev, max_scale_int: data->cd->scale1x, max_scale_nano: 0, gain_tbl: data->cd->gains, |
1572 | num_gain: data->cd->num_gains, tim_tbl: data->cd->itimes, |
1573 | num_times: data->cd->num_itimes, gts: &data->gts); |
1574 | if (ret) |
1575 | return ret; |
1576 | |
1577 | ret = devm_iio_init_iio_gts(dev, max_scale_int: data->cd->scale1x, max_scale_nano: 0, gain_tbl: data->cd->gains_ir, |
1578 | num_gain: data->cd->num_gains_ir, tim_tbl: data->cd->itimes, |
1579 | num_times: data->cd->num_itimes, gts: &data->gts_ir); |
1580 | if (ret) |
1581 | return ret; |
1582 | |
1583 | mutex_init(&data->mutex); |
1584 | data->regmap = regmap; |
1585 | data->dev = dev; |
1586 | data->irq = i2c->irq; |
1587 | |
1588 | idev->channels = bu27008_channels; |
1589 | idev->num_channels = ARRAY_SIZE(bu27008_channels); |
1590 | idev->name = data->cd->name; |
1591 | idev->info = &bu27008_info; |
1592 | idev->modes = INDIO_DIRECT_MODE; |
1593 | idev->available_scan_masks = bu27008_scan_masks; |
1594 | |
1595 | ret = data->cd->chip_init(data); |
1596 | if (ret) |
1597 | return ret; |
1598 | |
1599 | if (i2c->irq) { |
1600 | ret = bu27008_setup_trigger(data, idev); |
1601 | if (ret) |
1602 | return ret; |
1603 | } else { |
1604 | dev_info(dev, "No IRQ, buffered mode disabled\n" ); |
1605 | } |
1606 | |
1607 | ret = devm_iio_device_register(dev, idev); |
1608 | if (ret) |
1609 | return dev_err_probe(dev, err: ret, |
1610 | fmt: "Unable to register iio device\n" ); |
1611 | |
1612 | return 0; |
1613 | } |
1614 | |
1615 | static const struct of_device_id bu27008_of_match[] = { |
1616 | { .compatible = "rohm,bu27008" , .data = &bu27008_chip }, |
1617 | { .compatible = "rohm,bu27010" , .data = &bu27010_chip }, |
1618 | { } |
1619 | }; |
1620 | MODULE_DEVICE_TABLE(of, bu27008_of_match); |
1621 | |
1622 | static struct i2c_driver bu27008_i2c_driver = { |
1623 | .driver = { |
1624 | .name = "bu27008" , |
1625 | .of_match_table = bu27008_of_match, |
1626 | .probe_type = PROBE_PREFER_ASYNCHRONOUS, |
1627 | }, |
1628 | .probe = bu27008_probe, |
1629 | }; |
1630 | module_i2c_driver(bu27008_i2c_driver); |
1631 | |
1632 | MODULE_DESCRIPTION("ROHM BU27008 and BU27010 colour sensor driver" ); |
1633 | MODULE_AUTHOR("Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com>" ); |
1634 | MODULE_LICENSE("GPL" ); |
1635 | MODULE_IMPORT_NS(IIO_GTS_HELPER); |
1636 | |