1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* |
3 | * drivers/iio/light/tsl2563.c |
4 | * |
5 | * Copyright (C) 2008 Nokia Corporation |
6 | * |
7 | * Written by Timo O. Karjalainen <timo.o.karjalainen@nokia.com> |
8 | * Contact: Amit Kucheria <amit.kucheria@verdurent.com> |
9 | * |
10 | * Converted to IIO driver |
11 | * Amit Kucheria <amit.kucheria@verdurent.com> |
12 | */ |
13 | |
14 | #include <linux/bits.h> |
15 | #include <linux/delay.h> |
16 | #include <linux/err.h> |
17 | #include <linux/i2c.h> |
18 | #include <linux/interrupt.h> |
19 | #include <linux/irq.h> |
20 | #include <linux/math.h> |
21 | #include <linux/mod_devicetable.h> |
22 | #include <linux/module.h> |
23 | #include <linux/mutex.h> |
24 | #include <linux/pm.h> |
25 | #include <linux/property.h> |
26 | #include <linux/sched.h> |
27 | #include <linux/slab.h> |
28 | |
29 | #include <linux/iio/events.h> |
30 | #include <linux/iio/iio.h> |
31 | #include <linux/iio/sysfs.h> |
32 | |
33 | /* Use this many bits for fraction part. */ |
34 | #define ADC_FRAC_BITS 14 |
35 | |
36 | /* Given number of 1/10000's in ADC_FRAC_BITS precision. */ |
37 | #define FRAC10K(f) (((f) * BIT(ADC_FRAC_BITS)) / (10000)) |
38 | |
39 | /* Bits used for fraction in calibration coefficients.*/ |
40 | #define CALIB_FRAC_BITS 10 |
41 | /* Decimal 10^(digits in sysfs presentation) */ |
42 | #define CALIB_BASE_SYSFS 1000 |
43 | |
44 | #define TSL2563_CMD BIT(7) |
45 | #define TSL2563_CLEARINT BIT(6) |
46 | |
47 | #define TSL2563_REG_CTRL 0x00 |
48 | #define TSL2563_REG_TIMING 0x01 |
49 | #define TSL2563_REG_LOW 0x02 /* data0 low threshold, 2 bytes */ |
50 | #define TSL2563_REG_HIGH 0x04 /* data0 high threshold, 2 bytes */ |
51 | #define TSL2563_REG_INT 0x06 |
52 | #define TSL2563_REG_ID 0x0a |
53 | #define TSL2563_REG_DATA0 0x0c /* broadband sensor value, 2 bytes */ |
54 | #define TSL2563_REG_DATA1 0x0e /* infrared sensor value, 2 bytes */ |
55 | |
56 | #define TSL2563_CMD_POWER_ON 0x03 |
57 | #define TSL2563_CMD_POWER_OFF 0x00 |
58 | #define TSL2563_CTRL_POWER_MASK GENMASK(1, 0) |
59 | |
60 | #define TSL2563_TIMING_13MS 0x00 |
61 | #define TSL2563_TIMING_100MS 0x01 |
62 | #define TSL2563_TIMING_400MS 0x02 |
63 | #define TSL2563_TIMING_MASK GENMASK(1, 0) |
64 | #define TSL2563_TIMING_GAIN16 0x10 |
65 | #define TSL2563_TIMING_GAIN1 0x00 |
66 | |
67 | #define TSL2563_INT_DISABLED 0x00 |
68 | #define TSL2563_INT_LEVEL 0x10 |
69 | #define TSL2563_INT_MASK GENMASK(5, 4) |
70 | #define TSL2563_INT_PERSIST(n) ((n) & GENMASK(3, 0)) |
71 | |
72 | struct tsl2563_gainlevel_coeff { |
73 | u8 gaintime; |
74 | u16 min; |
75 | u16 max; |
76 | }; |
77 | |
78 | static const struct tsl2563_gainlevel_coeff tsl2563_gainlevel_table[] = { |
79 | { |
80 | .gaintime = TSL2563_TIMING_400MS | TSL2563_TIMING_GAIN16, |
81 | .min = 0, |
82 | .max = 65534, |
83 | }, { |
84 | .gaintime = TSL2563_TIMING_400MS | TSL2563_TIMING_GAIN1, |
85 | .min = 2048, |
86 | .max = 65534, |
87 | }, { |
88 | .gaintime = TSL2563_TIMING_100MS | TSL2563_TIMING_GAIN1, |
89 | .min = 4095, |
90 | .max = 37177, |
91 | }, { |
92 | .gaintime = TSL2563_TIMING_13MS | TSL2563_TIMING_GAIN1, |
93 | .min = 3000, |
94 | .max = 65535, |
95 | }, |
96 | }; |
97 | |
98 | struct tsl2563_chip { |
99 | struct mutex lock; |
100 | struct i2c_client *client; |
101 | struct delayed_work poweroff_work; |
102 | |
103 | /* Remember state for suspend and resume functions */ |
104 | bool suspended; |
105 | |
106 | struct tsl2563_gainlevel_coeff const *gainlevel; |
107 | |
108 | u16 low_thres; |
109 | u16 high_thres; |
110 | u8 intr; |
111 | bool int_enabled; |
112 | |
113 | /* Calibration coefficients */ |
114 | u32 calib0; |
115 | u32 calib1; |
116 | int cover_comp_gain; |
117 | |
118 | /* Cache current values, to be returned while suspended */ |
119 | u32 data0; |
120 | u32 data1; |
121 | }; |
122 | |
123 | static int tsl2563_set_power(struct tsl2563_chip *chip, int on) |
124 | { |
125 | struct i2c_client *client = chip->client; |
126 | u8 cmd; |
127 | |
128 | cmd = on ? TSL2563_CMD_POWER_ON : TSL2563_CMD_POWER_OFF; |
129 | return i2c_smbus_write_byte_data(client, |
130 | TSL2563_CMD | TSL2563_REG_CTRL, value: cmd); |
131 | } |
132 | |
133 | /* |
134 | * Return value is 0 for off, 1 for on, or a negative error |
135 | * code if reading failed. |
136 | */ |
137 | static int tsl2563_get_power(struct tsl2563_chip *chip) |
138 | { |
139 | struct i2c_client *client = chip->client; |
140 | int ret; |
141 | |
142 | ret = i2c_smbus_read_byte_data(client, TSL2563_CMD | TSL2563_REG_CTRL); |
143 | if (ret < 0) |
144 | return ret; |
145 | |
146 | return (ret & TSL2563_CTRL_POWER_MASK) == TSL2563_CMD_POWER_ON; |
147 | } |
148 | |
149 | static int tsl2563_configure(struct tsl2563_chip *chip) |
150 | { |
151 | int ret; |
152 | |
153 | ret = i2c_smbus_write_byte_data(client: chip->client, |
154 | TSL2563_CMD | TSL2563_REG_TIMING, |
155 | value: chip->gainlevel->gaintime); |
156 | if (ret) |
157 | goto error_ret; |
158 | ret = i2c_smbus_write_word_data(client: chip->client, |
159 | TSL2563_CMD | TSL2563_REG_HIGH, |
160 | value: chip->high_thres); |
161 | if (ret) |
162 | goto error_ret; |
163 | ret = i2c_smbus_write_word_data(client: chip->client, |
164 | TSL2563_CMD | TSL2563_REG_LOW, |
165 | value: chip->low_thres); |
166 | if (ret) |
167 | goto error_ret; |
168 | /* |
169 | * Interrupt register is automatically written anyway if it is relevant |
170 | * so is not here. |
171 | */ |
172 | error_ret: |
173 | return ret; |
174 | } |
175 | |
176 | static void tsl2563_poweroff_work(struct work_struct *work) |
177 | { |
178 | struct tsl2563_chip *chip = |
179 | container_of(work, struct tsl2563_chip, poweroff_work.work); |
180 | tsl2563_set_power(chip, on: 0); |
181 | } |
182 | |
183 | static int tsl2563_detect(struct tsl2563_chip *chip) |
184 | { |
185 | int ret; |
186 | |
187 | ret = tsl2563_set_power(chip, on: 1); |
188 | if (ret) |
189 | return ret; |
190 | |
191 | ret = tsl2563_get_power(chip); |
192 | if (ret < 0) |
193 | return ret; |
194 | |
195 | return ret ? 0 : -ENODEV; |
196 | } |
197 | |
198 | static int tsl2563_read_id(struct tsl2563_chip *chip, u8 *id) |
199 | { |
200 | struct i2c_client *client = chip->client; |
201 | int ret; |
202 | |
203 | ret = i2c_smbus_read_byte_data(client, TSL2563_CMD | TSL2563_REG_ID); |
204 | if (ret < 0) |
205 | return ret; |
206 | |
207 | *id = ret; |
208 | |
209 | return 0; |
210 | } |
211 | |
212 | static int tsl2563_configure_irq(struct tsl2563_chip *chip, bool enable) |
213 | { |
214 | int ret; |
215 | |
216 | chip->intr &= ~TSL2563_INT_MASK; |
217 | if (enable) |
218 | chip->intr |= TSL2563_INT_LEVEL; |
219 | |
220 | ret = i2c_smbus_write_byte_data(client: chip->client, |
221 | TSL2563_CMD | TSL2563_REG_INT, |
222 | value: chip->intr); |
223 | if (ret < 0) |
224 | return ret; |
225 | |
226 | chip->int_enabled = enable; |
227 | return 0; |
228 | } |
229 | |
230 | /* |
231 | * "Normalized" ADC value is one obtained with 400ms of integration time and |
232 | * 16x gain. This function returns the number of bits of shift needed to |
233 | * convert between normalized values and HW values obtained using given |
234 | * timing and gain settings. |
235 | */ |
236 | static int tsl2563_adc_shiftbits(u8 timing) |
237 | { |
238 | int shift = 0; |
239 | |
240 | switch (timing & TSL2563_TIMING_MASK) { |
241 | case TSL2563_TIMING_13MS: |
242 | shift += 5; |
243 | break; |
244 | case TSL2563_TIMING_100MS: |
245 | shift += 2; |
246 | break; |
247 | case TSL2563_TIMING_400MS: |
248 | /* no-op */ |
249 | break; |
250 | } |
251 | |
252 | if (!(timing & TSL2563_TIMING_GAIN16)) |
253 | shift += 4; |
254 | |
255 | return shift; |
256 | } |
257 | |
258 | /* Convert a HW ADC value to normalized scale. */ |
259 | static u32 tsl2563_normalize_adc(u16 adc, u8 timing) |
260 | { |
261 | return adc << tsl2563_adc_shiftbits(timing); |
262 | } |
263 | |
264 | static void tsl2563_wait_adc(struct tsl2563_chip *chip) |
265 | { |
266 | unsigned int delay; |
267 | |
268 | switch (chip->gainlevel->gaintime & TSL2563_TIMING_MASK) { |
269 | case TSL2563_TIMING_13MS: |
270 | delay = 14; |
271 | break; |
272 | case TSL2563_TIMING_100MS: |
273 | delay = 101; |
274 | break; |
275 | default: |
276 | delay = 402; |
277 | } |
278 | /* |
279 | * TODO: Make sure that we wait at least required delay but why we |
280 | * have to extend it one tick more? |
281 | */ |
282 | schedule_timeout_interruptible(timeout: msecs_to_jiffies(m: delay) + 2); |
283 | } |
284 | |
285 | static int tsl2563_adjust_gainlevel(struct tsl2563_chip *chip, u16 adc) |
286 | { |
287 | struct i2c_client *client = chip->client; |
288 | |
289 | if (adc > chip->gainlevel->max || adc < chip->gainlevel->min) { |
290 | |
291 | (adc > chip->gainlevel->max) ? |
292 | chip->gainlevel++ : chip->gainlevel--; |
293 | |
294 | i2c_smbus_write_byte_data(client, |
295 | TSL2563_CMD | TSL2563_REG_TIMING, |
296 | value: chip->gainlevel->gaintime); |
297 | |
298 | tsl2563_wait_adc(chip); |
299 | tsl2563_wait_adc(chip); |
300 | |
301 | return 1; |
302 | } else |
303 | return 0; |
304 | } |
305 | |
306 | static int tsl2563_get_adc(struct tsl2563_chip *chip) |
307 | { |
308 | struct i2c_client *client = chip->client; |
309 | u16 adc0, adc1; |
310 | int retry = 1; |
311 | int ret = 0; |
312 | |
313 | if (chip->suspended) |
314 | goto out; |
315 | |
316 | if (!chip->int_enabled) { |
317 | cancel_delayed_work_sync(dwork: &chip->poweroff_work); |
318 | |
319 | if (!tsl2563_get_power(chip)) { |
320 | ret = tsl2563_set_power(chip, on: 1); |
321 | if (ret) |
322 | goto out; |
323 | ret = tsl2563_configure(chip); |
324 | if (ret) |
325 | goto out; |
326 | tsl2563_wait_adc(chip); |
327 | } |
328 | } |
329 | |
330 | while (retry) { |
331 | ret = i2c_smbus_read_word_data(client, |
332 | TSL2563_CMD | TSL2563_REG_DATA0); |
333 | if (ret < 0) |
334 | goto out; |
335 | adc0 = ret; |
336 | |
337 | ret = i2c_smbus_read_word_data(client, |
338 | TSL2563_CMD | TSL2563_REG_DATA1); |
339 | if (ret < 0) |
340 | goto out; |
341 | adc1 = ret; |
342 | |
343 | retry = tsl2563_adjust_gainlevel(chip, adc: adc0); |
344 | } |
345 | |
346 | chip->data0 = tsl2563_normalize_adc(adc: adc0, timing: chip->gainlevel->gaintime); |
347 | chip->data1 = tsl2563_normalize_adc(adc: adc1, timing: chip->gainlevel->gaintime); |
348 | |
349 | if (!chip->int_enabled) |
350 | schedule_delayed_work(dwork: &chip->poweroff_work, delay: 5 * HZ); |
351 | |
352 | ret = 0; |
353 | out: |
354 | return ret; |
355 | } |
356 | |
357 | static inline int tsl2563_calib_to_sysfs(u32 calib) |
358 | { |
359 | return (int)DIV_ROUND_CLOSEST(calib * CALIB_BASE_SYSFS, BIT(CALIB_FRAC_BITS)); |
360 | } |
361 | |
362 | static inline u32 tsl2563_calib_from_sysfs(int value) |
363 | { |
364 | /* Make a fraction from a number n that was multiplied with b. */ |
365 | return (((u32) value) << CALIB_FRAC_BITS) / CALIB_BASE_SYSFS; |
366 | } |
367 | |
368 | /* |
369 | * Conversions between lux and ADC values. |
370 | * |
371 | * The basic formula is lux = c0 * adc0 - c1 * adc1, where c0 and c1 are |
372 | * appropriate constants. Different constants are needed for different |
373 | * kinds of light, determined by the ratio adc1/adc0 (basically the ratio |
374 | * of the intensities in infrared and visible wavelengths). lux_table below |
375 | * lists the upper threshold of the adc1/adc0 ratio and the corresponding |
376 | * constants. |
377 | */ |
378 | |
379 | struct tsl2563_lux_coeff { |
380 | unsigned long ch_ratio; |
381 | unsigned long ch0_coeff; |
382 | unsigned long ch1_coeff; |
383 | }; |
384 | |
385 | static const struct tsl2563_lux_coeff lux_table[] = { |
386 | { |
387 | .ch_ratio = FRAC10K(1300), |
388 | .ch0_coeff = FRAC10K(315), |
389 | .ch1_coeff = FRAC10K(262), |
390 | }, { |
391 | .ch_ratio = FRAC10K(2600), |
392 | .ch0_coeff = FRAC10K(337), |
393 | .ch1_coeff = FRAC10K(430), |
394 | }, { |
395 | .ch_ratio = FRAC10K(3900), |
396 | .ch0_coeff = FRAC10K(363), |
397 | .ch1_coeff = FRAC10K(529), |
398 | }, { |
399 | .ch_ratio = FRAC10K(5200), |
400 | .ch0_coeff = FRAC10K(392), |
401 | .ch1_coeff = FRAC10K(605), |
402 | }, { |
403 | .ch_ratio = FRAC10K(6500), |
404 | .ch0_coeff = FRAC10K(229), |
405 | .ch1_coeff = FRAC10K(291), |
406 | }, { |
407 | .ch_ratio = FRAC10K(8000), |
408 | .ch0_coeff = FRAC10K(157), |
409 | .ch1_coeff = FRAC10K(180), |
410 | }, { |
411 | .ch_ratio = FRAC10K(13000), |
412 | .ch0_coeff = FRAC10K(34), |
413 | .ch1_coeff = FRAC10K(26), |
414 | }, { |
415 | .ch_ratio = ULONG_MAX, |
416 | .ch0_coeff = 0, |
417 | .ch1_coeff = 0, |
418 | }, |
419 | }; |
420 | |
421 | /* Convert normalized, scaled ADC values to lux. */ |
422 | static unsigned int tsl2563_adc_to_lux(u32 adc0, u32 adc1) |
423 | { |
424 | const struct tsl2563_lux_coeff *lp = lux_table; |
425 | unsigned long ratio, lux, ch0 = adc0, ch1 = adc1; |
426 | |
427 | ratio = ch0 ? ((ch1 << ADC_FRAC_BITS) / ch0) : ULONG_MAX; |
428 | |
429 | while (lp->ch_ratio < ratio) |
430 | lp++; |
431 | |
432 | lux = ch0 * lp->ch0_coeff - ch1 * lp->ch1_coeff; |
433 | |
434 | return (unsigned int) (lux >> ADC_FRAC_BITS); |
435 | } |
436 | |
437 | /* Apply calibration coefficient to ADC count. */ |
438 | static u32 tsl2563_calib_adc(u32 adc, u32 calib) |
439 | { |
440 | unsigned long scaled = adc; |
441 | |
442 | scaled *= calib; |
443 | scaled >>= CALIB_FRAC_BITS; |
444 | |
445 | return (u32) scaled; |
446 | } |
447 | |
448 | static int tsl2563_write_raw(struct iio_dev *indio_dev, |
449 | struct iio_chan_spec const *chan, |
450 | int val, |
451 | int val2, |
452 | long mask) |
453 | { |
454 | struct tsl2563_chip *chip = iio_priv(indio_dev); |
455 | |
456 | if (mask != IIO_CHAN_INFO_CALIBSCALE) |
457 | return -EINVAL; |
458 | if (chan->channel2 == IIO_MOD_LIGHT_BOTH) |
459 | chip->calib0 = tsl2563_calib_from_sysfs(value: val); |
460 | else if (chan->channel2 == IIO_MOD_LIGHT_IR) |
461 | chip->calib1 = tsl2563_calib_from_sysfs(value: val); |
462 | else |
463 | return -EINVAL; |
464 | |
465 | return 0; |
466 | } |
467 | |
468 | static int tsl2563_read_raw(struct iio_dev *indio_dev, |
469 | struct iio_chan_spec const *chan, |
470 | int *val, |
471 | int *val2, |
472 | long mask) |
473 | { |
474 | int ret = -EINVAL; |
475 | u32 calib0, calib1; |
476 | struct tsl2563_chip *chip = iio_priv(indio_dev); |
477 | |
478 | mutex_lock(&chip->lock); |
479 | switch (mask) { |
480 | case IIO_CHAN_INFO_RAW: |
481 | case IIO_CHAN_INFO_PROCESSED: |
482 | switch (chan->type) { |
483 | case IIO_LIGHT: |
484 | ret = tsl2563_get_adc(chip); |
485 | if (ret) |
486 | goto error_ret; |
487 | calib0 = tsl2563_calib_adc(adc: chip->data0, calib: chip->calib0) * |
488 | chip->cover_comp_gain; |
489 | calib1 = tsl2563_calib_adc(adc: chip->data1, calib: chip->calib1) * |
490 | chip->cover_comp_gain; |
491 | *val = tsl2563_adc_to_lux(adc0: calib0, adc1: calib1); |
492 | ret = IIO_VAL_INT; |
493 | break; |
494 | case IIO_INTENSITY: |
495 | ret = tsl2563_get_adc(chip); |
496 | if (ret) |
497 | goto error_ret; |
498 | if (chan->channel2 == IIO_MOD_LIGHT_BOTH) |
499 | *val = chip->data0; |
500 | else |
501 | *val = chip->data1; |
502 | ret = IIO_VAL_INT; |
503 | break; |
504 | default: |
505 | break; |
506 | } |
507 | break; |
508 | |
509 | case IIO_CHAN_INFO_CALIBSCALE: |
510 | if (chan->channel2 == IIO_MOD_LIGHT_BOTH) |
511 | *val = tsl2563_calib_to_sysfs(calib: chip->calib0); |
512 | else |
513 | *val = tsl2563_calib_to_sysfs(calib: chip->calib1); |
514 | ret = IIO_VAL_INT; |
515 | break; |
516 | default: |
517 | ret = -EINVAL; |
518 | goto error_ret; |
519 | } |
520 | |
521 | error_ret: |
522 | mutex_unlock(lock: &chip->lock); |
523 | return ret; |
524 | } |
525 | |
526 | static const struct iio_event_spec tsl2563_events[] = { |
527 | { |
528 | .type = IIO_EV_TYPE_THRESH, |
529 | .dir = IIO_EV_DIR_RISING, |
530 | .mask_separate = BIT(IIO_EV_INFO_VALUE) | |
531 | BIT(IIO_EV_INFO_ENABLE), |
532 | }, { |
533 | .type = IIO_EV_TYPE_THRESH, |
534 | .dir = IIO_EV_DIR_FALLING, |
535 | .mask_separate = BIT(IIO_EV_INFO_VALUE) | |
536 | BIT(IIO_EV_INFO_ENABLE), |
537 | }, |
538 | }; |
539 | |
540 | static const struct iio_chan_spec tsl2563_channels[] = { |
541 | { |
542 | .type = IIO_LIGHT, |
543 | .indexed = 1, |
544 | .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED), |
545 | .channel = 0, |
546 | }, { |
547 | .type = IIO_INTENSITY, |
548 | .modified = 1, |
549 | .channel2 = IIO_MOD_LIGHT_BOTH, |
550 | .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | |
551 | BIT(IIO_CHAN_INFO_CALIBSCALE), |
552 | .event_spec = tsl2563_events, |
553 | .num_event_specs = ARRAY_SIZE(tsl2563_events), |
554 | }, { |
555 | .type = IIO_INTENSITY, |
556 | .modified = 1, |
557 | .channel2 = IIO_MOD_LIGHT_IR, |
558 | .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | |
559 | BIT(IIO_CHAN_INFO_CALIBSCALE), |
560 | } |
561 | }; |
562 | |
563 | static int tsl2563_read_thresh(struct iio_dev *indio_dev, |
564 | const struct iio_chan_spec *chan, enum iio_event_type type, |
565 | enum iio_event_direction dir, enum iio_event_info info, int *val, |
566 | int *val2) |
567 | { |
568 | struct tsl2563_chip *chip = iio_priv(indio_dev); |
569 | |
570 | switch (dir) { |
571 | case IIO_EV_DIR_RISING: |
572 | *val = chip->high_thres; |
573 | break; |
574 | case IIO_EV_DIR_FALLING: |
575 | *val = chip->low_thres; |
576 | break; |
577 | default: |
578 | return -EINVAL; |
579 | } |
580 | |
581 | return IIO_VAL_INT; |
582 | } |
583 | |
584 | static int tsl2563_write_thresh(struct iio_dev *indio_dev, |
585 | const struct iio_chan_spec *chan, enum iio_event_type type, |
586 | enum iio_event_direction dir, enum iio_event_info info, int val, |
587 | int val2) |
588 | { |
589 | struct tsl2563_chip *chip = iio_priv(indio_dev); |
590 | int ret; |
591 | |
592 | mutex_lock(&chip->lock); |
593 | |
594 | if (dir == IIO_EV_DIR_RISING) |
595 | ret = i2c_smbus_write_word_data(client: chip->client, |
596 | TSL2563_CMD | TSL2563_REG_HIGH, value: val); |
597 | else |
598 | ret = i2c_smbus_write_word_data(client: chip->client, |
599 | TSL2563_CMD | TSL2563_REG_LOW, value: val); |
600 | if (ret) |
601 | goto error_ret; |
602 | |
603 | if (dir == IIO_EV_DIR_RISING) |
604 | chip->high_thres = val; |
605 | else |
606 | chip->low_thres = val; |
607 | |
608 | error_ret: |
609 | mutex_unlock(lock: &chip->lock); |
610 | |
611 | return ret; |
612 | } |
613 | |
614 | static irqreturn_t tsl2563_event_handler(int irq, void *private) |
615 | { |
616 | struct iio_dev *dev_info = private; |
617 | struct tsl2563_chip *chip = iio_priv(indio_dev: dev_info); |
618 | |
619 | iio_push_event(indio_dev: dev_info, |
620 | IIO_UNMOD_EVENT_CODE(IIO_INTENSITY, |
621 | 0, |
622 | IIO_EV_TYPE_THRESH, |
623 | IIO_EV_DIR_EITHER), |
624 | timestamp: iio_get_time_ns(indio_dev: dev_info)); |
625 | |
626 | /* clear the interrupt and push the event */ |
627 | i2c_smbus_write_byte(client: chip->client, TSL2563_CMD | TSL2563_CLEARINT); |
628 | return IRQ_HANDLED; |
629 | } |
630 | |
631 | static int tsl2563_write_interrupt_config(struct iio_dev *indio_dev, |
632 | const struct iio_chan_spec *chan, enum iio_event_type type, |
633 | enum iio_event_direction dir, int state) |
634 | { |
635 | struct tsl2563_chip *chip = iio_priv(indio_dev); |
636 | int ret = 0; |
637 | |
638 | mutex_lock(&chip->lock); |
639 | if (state && !(chip->intr & TSL2563_INT_MASK)) { |
640 | /* ensure the chip is actually on */ |
641 | cancel_delayed_work_sync(dwork: &chip->poweroff_work); |
642 | if (!tsl2563_get_power(chip)) { |
643 | ret = tsl2563_set_power(chip, on: 1); |
644 | if (ret) |
645 | goto out; |
646 | ret = tsl2563_configure(chip); |
647 | if (ret) |
648 | goto out; |
649 | } |
650 | ret = tsl2563_configure_irq(chip, enable: true); |
651 | } |
652 | |
653 | if (!state && (chip->intr & TSL2563_INT_MASK)) { |
654 | ret = tsl2563_configure_irq(chip, enable: false); |
655 | /* now the interrupt is not enabled, we can go to sleep */ |
656 | schedule_delayed_work(dwork: &chip->poweroff_work, delay: 5 * HZ); |
657 | } |
658 | out: |
659 | mutex_unlock(lock: &chip->lock); |
660 | |
661 | return ret; |
662 | } |
663 | |
664 | static int tsl2563_read_interrupt_config(struct iio_dev *indio_dev, |
665 | const struct iio_chan_spec *chan, enum iio_event_type type, |
666 | enum iio_event_direction dir) |
667 | { |
668 | struct tsl2563_chip *chip = iio_priv(indio_dev); |
669 | int ret; |
670 | |
671 | mutex_lock(&chip->lock); |
672 | ret = i2c_smbus_read_byte_data(client: chip->client, |
673 | TSL2563_CMD | TSL2563_REG_INT); |
674 | mutex_unlock(lock: &chip->lock); |
675 | if (ret < 0) |
676 | return ret; |
677 | |
678 | return !!(ret & TSL2563_INT_MASK); |
679 | } |
680 | |
681 | static const struct iio_info tsl2563_info_no_irq = { |
682 | .read_raw = &tsl2563_read_raw, |
683 | .write_raw = &tsl2563_write_raw, |
684 | }; |
685 | |
686 | static const struct iio_info tsl2563_info = { |
687 | .read_raw = &tsl2563_read_raw, |
688 | .write_raw = &tsl2563_write_raw, |
689 | .read_event_value = &tsl2563_read_thresh, |
690 | .write_event_value = &tsl2563_write_thresh, |
691 | .read_event_config = &tsl2563_read_interrupt_config, |
692 | .write_event_config = &tsl2563_write_interrupt_config, |
693 | }; |
694 | |
695 | static int tsl2563_probe(struct i2c_client *client) |
696 | { |
697 | struct device *dev = &client->dev; |
698 | struct iio_dev *indio_dev; |
699 | struct tsl2563_chip *chip; |
700 | unsigned long irq_flags; |
701 | u8 id = 0; |
702 | int err; |
703 | |
704 | indio_dev = devm_iio_device_alloc(parent: dev, sizeof_priv: sizeof(*chip)); |
705 | if (!indio_dev) |
706 | return -ENOMEM; |
707 | |
708 | chip = iio_priv(indio_dev); |
709 | |
710 | i2c_set_clientdata(client, data: indio_dev); |
711 | chip->client = client; |
712 | |
713 | err = tsl2563_detect(chip); |
714 | if (err) |
715 | return dev_err_probe(dev, err, fmt: "detect error\n" ); |
716 | |
717 | err = tsl2563_read_id(chip, id: &id); |
718 | if (err) |
719 | return dev_err_probe(dev, err, fmt: "read id error\n" ); |
720 | |
721 | mutex_init(&chip->lock); |
722 | |
723 | /* Default values used until userspace says otherwise */ |
724 | chip->low_thres = 0x0; |
725 | chip->high_thres = 0xffff; |
726 | chip->gainlevel = tsl2563_gainlevel_table; |
727 | chip->intr = TSL2563_INT_PERSIST(4); |
728 | chip->calib0 = tsl2563_calib_from_sysfs(CALIB_BASE_SYSFS); |
729 | chip->calib1 = tsl2563_calib_from_sysfs(CALIB_BASE_SYSFS); |
730 | |
731 | chip->cover_comp_gain = 1; |
732 | device_property_read_u32(dev, propname: "amstaos,cover-comp-gain" , val: &chip->cover_comp_gain); |
733 | |
734 | dev_info(dev, "model %d, rev. %d\n" , id >> 4, id & 0x0f); |
735 | indio_dev->name = client->name; |
736 | indio_dev->channels = tsl2563_channels; |
737 | indio_dev->num_channels = ARRAY_SIZE(tsl2563_channels); |
738 | indio_dev->modes = INDIO_DIRECT_MODE; |
739 | |
740 | if (client->irq) |
741 | indio_dev->info = &tsl2563_info; |
742 | else |
743 | indio_dev->info = &tsl2563_info_no_irq; |
744 | |
745 | if (client->irq) { |
746 | irq_flags = irq_get_trigger_type(irq: client->irq); |
747 | if (irq_flags == IRQF_TRIGGER_NONE) |
748 | irq_flags = IRQF_TRIGGER_RISING; |
749 | irq_flags |= IRQF_ONESHOT; |
750 | |
751 | err = devm_request_threaded_irq(dev, irq: client->irq, |
752 | NULL, |
753 | thread_fn: &tsl2563_event_handler, |
754 | irqflags: irq_flags, |
755 | devname: "tsl2563_event" , |
756 | dev_id: indio_dev); |
757 | if (err) |
758 | return dev_err_probe(dev, err, fmt: "irq request error\n" ); |
759 | } |
760 | |
761 | err = tsl2563_configure(chip); |
762 | if (err) |
763 | return dev_err_probe(dev, err, fmt: "configure error\n" ); |
764 | |
765 | INIT_DELAYED_WORK(&chip->poweroff_work, tsl2563_poweroff_work); |
766 | |
767 | /* The interrupt cannot yet be enabled so this is fine without lock */ |
768 | schedule_delayed_work(dwork: &chip->poweroff_work, delay: 5 * HZ); |
769 | |
770 | err = iio_device_register(indio_dev); |
771 | if (err) { |
772 | dev_err_probe(dev, err, fmt: "iio registration error\n" ); |
773 | goto fail; |
774 | } |
775 | |
776 | return 0; |
777 | |
778 | fail: |
779 | cancel_delayed_work_sync(dwork: &chip->poweroff_work); |
780 | return err; |
781 | } |
782 | |
783 | static void tsl2563_remove(struct i2c_client *client) |
784 | { |
785 | struct iio_dev *indio_dev = i2c_get_clientdata(client); |
786 | struct tsl2563_chip *chip = iio_priv(indio_dev); |
787 | |
788 | iio_device_unregister(indio_dev); |
789 | if (!chip->int_enabled) |
790 | cancel_delayed_work_sync(dwork: &chip->poweroff_work); |
791 | /* Ensure that interrupts are disabled - then flush any bottom halves */ |
792 | tsl2563_configure_irq(chip, enable: false); |
793 | tsl2563_set_power(chip, on: 0); |
794 | } |
795 | |
796 | static int tsl2563_suspend(struct device *dev) |
797 | { |
798 | struct iio_dev *indio_dev = dev_get_drvdata(dev); |
799 | struct tsl2563_chip *chip = iio_priv(indio_dev); |
800 | int ret; |
801 | |
802 | mutex_lock(&chip->lock); |
803 | |
804 | ret = tsl2563_set_power(chip, on: 0); |
805 | if (ret) |
806 | goto out; |
807 | |
808 | chip->suspended = true; |
809 | |
810 | out: |
811 | mutex_unlock(lock: &chip->lock); |
812 | return ret; |
813 | } |
814 | |
815 | static int tsl2563_resume(struct device *dev) |
816 | { |
817 | struct iio_dev *indio_dev = dev_get_drvdata(dev); |
818 | struct tsl2563_chip *chip = iio_priv(indio_dev); |
819 | int ret; |
820 | |
821 | mutex_lock(&chip->lock); |
822 | |
823 | ret = tsl2563_set_power(chip, on: 1); |
824 | if (ret) |
825 | goto out; |
826 | |
827 | ret = tsl2563_configure(chip); |
828 | if (ret) |
829 | goto out; |
830 | |
831 | chip->suspended = false; |
832 | |
833 | out: |
834 | mutex_unlock(lock: &chip->lock); |
835 | return ret; |
836 | } |
837 | |
838 | static DEFINE_SIMPLE_DEV_PM_OPS(tsl2563_pm_ops, tsl2563_suspend, |
839 | tsl2563_resume); |
840 | |
841 | static const struct i2c_device_id tsl2563_id[] = { |
842 | { "tsl2560" , 0 }, |
843 | { "tsl2561" , 1 }, |
844 | { "tsl2562" , 2 }, |
845 | { "tsl2563" , 3 }, |
846 | {} |
847 | }; |
848 | MODULE_DEVICE_TABLE(i2c, tsl2563_id); |
849 | |
850 | static const struct of_device_id tsl2563_of_match[] = { |
851 | { .compatible = "amstaos,tsl2560" }, |
852 | { .compatible = "amstaos,tsl2561" }, |
853 | { .compatible = "amstaos,tsl2562" }, |
854 | { .compatible = "amstaos,tsl2563" }, |
855 | {} |
856 | }; |
857 | MODULE_DEVICE_TABLE(of, tsl2563_of_match); |
858 | |
859 | static struct i2c_driver tsl2563_i2c_driver = { |
860 | .driver = { |
861 | .name = "tsl2563" , |
862 | .of_match_table = tsl2563_of_match, |
863 | .pm = pm_sleep_ptr(&tsl2563_pm_ops), |
864 | }, |
865 | .probe = tsl2563_probe, |
866 | .remove = tsl2563_remove, |
867 | .id_table = tsl2563_id, |
868 | }; |
869 | module_i2c_driver(tsl2563_i2c_driver); |
870 | |
871 | MODULE_AUTHOR("Nokia Corporation" ); |
872 | MODULE_DESCRIPTION("tsl2563 light sensor driver" ); |
873 | MODULE_LICENSE("GPL" ); |
874 | |