regmap-i2c: Use i2c block command only if register value width is 8 bit
[deliverable/linux.git] / drivers / iio / light / lm3533-als.c
CommitLineData
9c8ea1b2
JH
1/*
2 * lm3533-als.c -- LM3533 Ambient Light Sensor driver
3 *
4 * Copyright (C) 2011-2012 Texas Instruments
5 *
6 * Author: Johan Hovold <jhovold@gmail.com>
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2 of the License, or (at your
11 * option) any later version.
12 */
13
14#include <linux/atomic.h>
15#include <linux/fs.h>
16#include <linux/interrupt.h>
17#include <linux/io.h>
18#include <linux/iio/events.h>
19#include <linux/iio/iio.h>
20#include <linux/module.h>
21#include <linux/mutex.h>
22#include <linux/mfd/core.h>
23#include <linux/platform_device.h>
24#include <linux/slab.h>
25#include <linux/uaccess.h>
26
27#include <linux/mfd/lm3533.h>
28
29
30#define LM3533_ALS_RESISTOR_MIN 1
31#define LM3533_ALS_RESISTOR_MAX 127
32#define LM3533_ALS_CHANNEL_CURRENT_MAX 2
33#define LM3533_ALS_THRESH_MAX 3
34#define LM3533_ALS_ZONE_MAX 4
35
36#define LM3533_REG_ALS_RESISTOR_SELECT 0x30
37#define LM3533_REG_ALS_CONF 0x31
38#define LM3533_REG_ALS_ZONE_INFO 0x34
39#define LM3533_REG_ALS_READ_ADC_RAW 0x37
40#define LM3533_REG_ALS_READ_ADC_AVERAGE 0x38
41#define LM3533_REG_ALS_BOUNDARY_BASE 0x50
42#define LM3533_REG_ALS_TARGET_BASE 0x60
43
44#define LM3533_ALS_ENABLE_MASK 0x01
45#define LM3533_ALS_INPUT_MODE_MASK 0x02
46#define LM3533_ALS_INT_ENABLE_MASK 0x01
47
48#define LM3533_ALS_ZONE_SHIFT 2
49#define LM3533_ALS_ZONE_MASK 0x1c
50
51#define LM3533_ALS_FLAG_INT_ENABLED 1
52
53
54struct lm3533_als {
55 struct lm3533 *lm3533;
56 struct platform_device *pdev;
57
58 unsigned long flags;
59 int irq;
60
61 atomic_t zone;
62 struct mutex thresh_mutex;
63};
64
65
66static int lm3533_als_get_adc(struct iio_dev *indio_dev, bool average,
67 int *adc)
68{
69 struct lm3533_als *als = iio_priv(indio_dev);
70 u8 reg;
71 u8 val;
72 int ret;
73
74 if (average)
75 reg = LM3533_REG_ALS_READ_ADC_AVERAGE;
76 else
77 reg = LM3533_REG_ALS_READ_ADC_RAW;
78
79 ret = lm3533_read(als->lm3533, reg, &val);
80 if (ret) {
81 dev_err(&indio_dev->dev, "failed to read adc\n");
82 return ret;
83 }
84
85 *adc = val;
86
87 return 0;
88}
89
90static int _lm3533_als_get_zone(struct iio_dev *indio_dev, u8 *zone)
91{
92 struct lm3533_als *als = iio_priv(indio_dev);
93 u8 val;
94 int ret;
95
96 ret = lm3533_read(als->lm3533, LM3533_REG_ALS_ZONE_INFO, &val);
97 if (ret) {
98 dev_err(&indio_dev->dev, "failed to read zone\n");
99 return ret;
100 }
101
102 val = (val & LM3533_ALS_ZONE_MASK) >> LM3533_ALS_ZONE_SHIFT;
103 *zone = min_t(u8, val, LM3533_ALS_ZONE_MAX);
104
105 return 0;
106}
107
108static int lm3533_als_get_zone(struct iio_dev *indio_dev, u8 *zone)
109{
110 struct lm3533_als *als = iio_priv(indio_dev);
111 int ret;
112
113 if (test_bit(LM3533_ALS_FLAG_INT_ENABLED, &als->flags)) {
114 *zone = atomic_read(&als->zone);
115 } else {
116 ret = _lm3533_als_get_zone(indio_dev, zone);
117 if (ret)
118 return ret;
119 }
120
121 return 0;
122}
123
124/*
125 * channel output channel 0..2
126 * zone zone 0..4
127 */
128static inline u8 lm3533_als_get_target_reg(unsigned channel, unsigned zone)
129{
130 return LM3533_REG_ALS_TARGET_BASE + 5 * channel + zone;
131}
132
133static int lm3533_als_get_target(struct iio_dev *indio_dev, unsigned channel,
134 unsigned zone, u8 *val)
135{
136 struct lm3533_als *als = iio_priv(indio_dev);
137 u8 reg;
138 int ret;
139
140 if (channel > LM3533_ALS_CHANNEL_CURRENT_MAX)
141 return -EINVAL;
142
143 if (zone > LM3533_ALS_ZONE_MAX)
144 return -EINVAL;
145
146 reg = lm3533_als_get_target_reg(channel, zone);
147 ret = lm3533_read(als->lm3533, reg, val);
148 if (ret)
149 dev_err(&indio_dev->dev, "failed to get target current\n");
150
151 return ret;
152}
153
154static int lm3533_als_set_target(struct iio_dev *indio_dev, unsigned channel,
155 unsigned zone, u8 val)
156{
157 struct lm3533_als *als = iio_priv(indio_dev);
158 u8 reg;
159 int ret;
160
161 if (channel > LM3533_ALS_CHANNEL_CURRENT_MAX)
162 return -EINVAL;
163
164 if (zone > LM3533_ALS_ZONE_MAX)
165 return -EINVAL;
166
167 reg = lm3533_als_get_target_reg(channel, zone);
168 ret = lm3533_write(als->lm3533, reg, val);
169 if (ret)
170 dev_err(&indio_dev->dev, "failed to set target current\n");
171
172 return ret;
173}
174
175static int lm3533_als_get_current(struct iio_dev *indio_dev, unsigned channel,
176 int *val)
177{
178 u8 zone;
179 u8 target;
180 int ret;
181
182 ret = lm3533_als_get_zone(indio_dev, &zone);
183 if (ret)
184 return ret;
185
186 ret = lm3533_als_get_target(indio_dev, channel, zone, &target);
187 if (ret)
188 return ret;
189
190 *val = target;
191
192 return 0;
193}
194
195static int lm3533_als_read_raw(struct iio_dev *indio_dev,
196 struct iio_chan_spec const *chan,
197 int *val, int *val2, long mask)
198{
199 int ret;
200
201 switch (mask) {
202 case 0:
203 switch (chan->type) {
204 case IIO_LIGHT:
205 ret = lm3533_als_get_adc(indio_dev, false, val);
206 break;
207 case IIO_CURRENT:
208 ret = lm3533_als_get_current(indio_dev, chan->channel,
209 val);
210 break;
211 default:
212 return -EINVAL;
213 }
214 break;
215 case IIO_CHAN_INFO_AVERAGE_RAW:
216 ret = lm3533_als_get_adc(indio_dev, true, val);
217 break;
218 default:
219 return -EINVAL;
220 }
221
222 if (ret)
223 return ret;
224
225 return IIO_VAL_INT;
226}
227
228#define CHANNEL_CURRENT(_channel) \
229 { \
230 .type = IIO_CURRENT, \
231 .channel = _channel, \
232 .indexed = true, \
233 .output = true, \
d113de62 234 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
9c8ea1b2
JH
235 }
236
237static const struct iio_chan_spec lm3533_als_channels[] = {
238 {
239 .type = IIO_LIGHT,
240 .channel = 0,
241 .indexed = true,
d113de62
JC
242 .info_mask_separate = BIT(IIO_CHAN_INFO_AVERAGE_RAW) |
243 BIT(IIO_CHAN_INFO_RAW),
9c8ea1b2
JH
244 },
245 CHANNEL_CURRENT(0),
246 CHANNEL_CURRENT(1),
247 CHANNEL_CURRENT(2),
248};
249
250static irqreturn_t lm3533_als_isr(int irq, void *dev_id)
251{
252
253 struct iio_dev *indio_dev = dev_id;
254 struct lm3533_als *als = iio_priv(indio_dev);
255 u8 zone;
256 int ret;
257
258 /* Clear interrupt by reading the ALS zone register. */
259 ret = _lm3533_als_get_zone(indio_dev, &zone);
260 if (ret)
261 goto out;
262
263 atomic_set(&als->zone, zone);
264
265 iio_push_event(indio_dev,
266 IIO_UNMOD_EVENT_CODE(IIO_LIGHT,
267 0,
268 IIO_EV_TYPE_THRESH,
269 IIO_EV_DIR_EITHER),
270 iio_get_time_ns());
271out:
272 return IRQ_HANDLED;
273}
274
275static int lm3533_als_set_int_mode(struct iio_dev *indio_dev, int enable)
276{
277 struct lm3533_als *als = iio_priv(indio_dev);
278 u8 mask = LM3533_ALS_INT_ENABLE_MASK;
279 u8 val;
280 int ret;
281
282 if (enable)
283 val = mask;
284 else
285 val = 0;
286
287 ret = lm3533_update(als->lm3533, LM3533_REG_ALS_ZONE_INFO, val, mask);
288 if (ret) {
289 dev_err(&indio_dev->dev, "failed to set int mode %d\n",
290 enable);
291 return ret;
292 }
293
294 return 0;
295}
296
297static int lm3533_als_get_int_mode(struct iio_dev *indio_dev, int *enable)
298{
299 struct lm3533_als *als = iio_priv(indio_dev);
300 u8 mask = LM3533_ALS_INT_ENABLE_MASK;
301 u8 val;
302 int ret;
303
304 ret = lm3533_read(als->lm3533, LM3533_REG_ALS_ZONE_INFO, &val);
305 if (ret) {
306 dev_err(&indio_dev->dev, "failed to get int mode\n");
307 return ret;
308 }
309
310 *enable = !!(val & mask);
311
312 return 0;
313}
314
315static inline u8 lm3533_als_get_threshold_reg(unsigned nr, bool raising)
316{
317 u8 offset = !raising;
318
319 return LM3533_REG_ALS_BOUNDARY_BASE + 2 * nr + offset;
320}
321
322static int lm3533_als_get_threshold(struct iio_dev *indio_dev, unsigned nr,
323 bool raising, u8 *val)
324{
325 struct lm3533_als *als = iio_priv(indio_dev);
326 u8 reg;
327 int ret;
328
329 if (nr > LM3533_ALS_THRESH_MAX)
330 return -EINVAL;
331
332 reg = lm3533_als_get_threshold_reg(nr, raising);
333 ret = lm3533_read(als->lm3533, reg, val);
334 if (ret)
335 dev_err(&indio_dev->dev, "failed to get threshold\n");
336
337 return ret;
338}
339
340static int lm3533_als_set_threshold(struct iio_dev *indio_dev, unsigned nr,
341 bool raising, u8 val)
342{
343 struct lm3533_als *als = iio_priv(indio_dev);
344 u8 val2;
345 u8 reg, reg2;
346 int ret;
347
348 if (nr > LM3533_ALS_THRESH_MAX)
349 return -EINVAL;
350
351 reg = lm3533_als_get_threshold_reg(nr, raising);
352 reg2 = lm3533_als_get_threshold_reg(nr, !raising);
353
354 mutex_lock(&als->thresh_mutex);
355 ret = lm3533_read(als->lm3533, reg2, &val2);
356 if (ret) {
357 dev_err(&indio_dev->dev, "failed to get threshold\n");
358 goto out;
359 }
360 /*
361 * This device does not allow negative hysteresis (in fact, it uses
362 * whichever value is smaller as the lower bound) so we need to make
363 * sure that thresh_falling <= thresh_raising.
364 */
365 if ((raising && (val < val2)) || (!raising && (val > val2))) {
366 ret = -EINVAL;
367 goto out;
368 }
369
370 ret = lm3533_write(als->lm3533, reg, val);
371 if (ret) {
372 dev_err(&indio_dev->dev, "failed to set threshold\n");
373 goto out;
374 }
375out:
376 mutex_unlock(&als->thresh_mutex);
377
378 return ret;
379}
380
381static int lm3533_als_get_hysteresis(struct iio_dev *indio_dev, unsigned nr,
382 u8 *val)
383{
384 struct lm3533_als *als = iio_priv(indio_dev);
385 u8 falling;
386 u8 raising;
387 int ret;
388
389 if (nr > LM3533_ALS_THRESH_MAX)
390 return -EINVAL;
391
392 mutex_lock(&als->thresh_mutex);
393 ret = lm3533_als_get_threshold(indio_dev, nr, false, &falling);
394 if (ret)
395 goto out;
396 ret = lm3533_als_get_threshold(indio_dev, nr, true, &raising);
397 if (ret)
398 goto out;
399
400 *val = raising - falling;
401out:
402 mutex_unlock(&als->thresh_mutex);
403
404 return ret;
405}
406
95d1c8c7 407static ssize_t show_thresh_either_en(struct device *dev,
9c8ea1b2
JH
408 struct device_attribute *attr,
409 char *buf)
410{
411 struct iio_dev *indio_dev = dev_to_iio_dev(dev);
412 struct lm3533_als *als = iio_priv(indio_dev);
413 int enable;
414 int ret;
415
416 if (als->irq) {
417 ret = lm3533_als_get_int_mode(indio_dev, &enable);
418 if (ret)
419 return ret;
420 } else {
421 enable = 0;
422 }
423
424 return scnprintf(buf, PAGE_SIZE, "%u\n", enable);
425}
426
95d1c8c7 427static ssize_t store_thresh_either_en(struct device *dev,
9c8ea1b2
JH
428 struct device_attribute *attr,
429 const char *buf, size_t len)
430{
431 struct iio_dev *indio_dev = dev_to_iio_dev(dev);
432 struct lm3533_als *als = iio_priv(indio_dev);
433 unsigned long enable;
434 bool int_enabled;
435 u8 zone;
436 int ret;
437
438 if (!als->irq)
439 return -EBUSY;
440
441 if (kstrtoul(buf, 0, &enable))
442 return -EINVAL;
443
444 int_enabled = test_bit(LM3533_ALS_FLAG_INT_ENABLED, &als->flags);
445
446 if (enable && !int_enabled) {
447 ret = lm3533_als_get_zone(indio_dev, &zone);
448 if (ret)
449 return ret;
450
451 atomic_set(&als->zone, zone);
452
453 set_bit(LM3533_ALS_FLAG_INT_ENABLED, &als->flags);
454 }
455
456 ret = lm3533_als_set_int_mode(indio_dev, enable);
457 if (ret) {
458 if (!int_enabled)
459 clear_bit(LM3533_ALS_FLAG_INT_ENABLED, &als->flags);
460
461 return ret;
462 }
463
464 if (!enable)
465 clear_bit(LM3533_ALS_FLAG_INT_ENABLED, &als->flags);
466
467 return len;
468}
469
470static ssize_t show_zone(struct device *dev,
471 struct device_attribute *attr, char *buf)
472{
473 struct iio_dev *indio_dev = dev_to_iio_dev(dev);
474 u8 zone;
475 int ret;
476
477 ret = lm3533_als_get_zone(indio_dev, &zone);
478 if (ret)
479 return ret;
480
481 return scnprintf(buf, PAGE_SIZE, "%u\n", zone);
482}
483
484enum lm3533_als_attribute_type {
485 LM3533_ATTR_TYPE_HYSTERESIS,
486 LM3533_ATTR_TYPE_TARGET,
487 LM3533_ATTR_TYPE_THRESH_FALLING,
488 LM3533_ATTR_TYPE_THRESH_RAISING,
489};
490
491struct lm3533_als_attribute {
492 struct device_attribute dev_attr;
493 enum lm3533_als_attribute_type type;
494 u8 val1;
495 u8 val2;
496};
497
498static inline struct lm3533_als_attribute *
499to_lm3533_als_attr(struct device_attribute *attr)
500{
501 return container_of(attr, struct lm3533_als_attribute, dev_attr);
502}
503
504static ssize_t show_als_attr(struct device *dev,
505 struct device_attribute *attr,
506 char *buf)
507{
508 struct iio_dev *indio_dev = dev_to_iio_dev(dev);
509 struct lm3533_als_attribute *als_attr = to_lm3533_als_attr(attr);
510 u8 val;
511 int ret;
512
513 switch (als_attr->type) {
514 case LM3533_ATTR_TYPE_HYSTERESIS:
515 ret = lm3533_als_get_hysteresis(indio_dev, als_attr->val1,
516 &val);
517 break;
518 case LM3533_ATTR_TYPE_TARGET:
519 ret = lm3533_als_get_target(indio_dev, als_attr->val1,
520 als_attr->val2, &val);
521 break;
522 case LM3533_ATTR_TYPE_THRESH_FALLING:
523 ret = lm3533_als_get_threshold(indio_dev, als_attr->val1,
524 false, &val);
525 break;
526 case LM3533_ATTR_TYPE_THRESH_RAISING:
527 ret = lm3533_als_get_threshold(indio_dev, als_attr->val1,
528 true, &val);
529 break;
530 default:
531 ret = -ENXIO;
532 }
533
534 if (ret)
535 return ret;
536
537 return scnprintf(buf, PAGE_SIZE, "%u\n", val);
538}
539
540static ssize_t store_als_attr(struct device *dev,
541 struct device_attribute *attr,
542 const char *buf, size_t len)
543{
544 struct iio_dev *indio_dev = dev_to_iio_dev(dev);
545 struct lm3533_als_attribute *als_attr = to_lm3533_als_attr(attr);
546 u8 val;
547 int ret;
548
549 if (kstrtou8(buf, 0, &val))
550 return -EINVAL;
551
552 switch (als_attr->type) {
553 case LM3533_ATTR_TYPE_TARGET:
554 ret = lm3533_als_set_target(indio_dev, als_attr->val1,
555 als_attr->val2, val);
556 break;
557 case LM3533_ATTR_TYPE_THRESH_FALLING:
558 ret = lm3533_als_set_threshold(indio_dev, als_attr->val1,
559 false, val);
560 break;
561 case LM3533_ATTR_TYPE_THRESH_RAISING:
562 ret = lm3533_als_set_threshold(indio_dev, als_attr->val1,
563 true, val);
564 break;
565 default:
566 ret = -ENXIO;
567 }
568
569 if (ret)
570 return ret;
571
572 return len;
573}
574
575#define ALS_ATTR(_name, _mode, _show, _store, _type, _val1, _val2) \
576 { .dev_attr = __ATTR(_name, _mode, _show, _store), \
577 .type = _type, \
578 .val1 = _val1, \
579 .val2 = _val2 }
580
581#define LM3533_ALS_ATTR(_name, _mode, _show, _store, _type, _val1, _val2) \
582 struct lm3533_als_attribute lm3533_als_attr_##_name = \
583 ALS_ATTR(_name, _mode, _show, _store, _type, _val1, _val2)
584
585#define ALS_TARGET_ATTR_RW(_channel, _zone) \
586 LM3533_ALS_ATTR(out_current##_channel##_current##_zone##_raw, \
587 S_IRUGO | S_IWUSR, \
588 show_als_attr, store_als_attr, \
589 LM3533_ATTR_TYPE_TARGET, _channel, _zone)
590/*
591 * ALS output current values (ALS mapper targets)
592 *
593 * out_current[0-2]_current[0-4]_raw 0-255
594 */
595static ALS_TARGET_ATTR_RW(0, 0);
596static ALS_TARGET_ATTR_RW(0, 1);
597static ALS_TARGET_ATTR_RW(0, 2);
598static ALS_TARGET_ATTR_RW(0, 3);
599static ALS_TARGET_ATTR_RW(0, 4);
600
601static ALS_TARGET_ATTR_RW(1, 0);
602static ALS_TARGET_ATTR_RW(1, 1);
603static ALS_TARGET_ATTR_RW(1, 2);
604static ALS_TARGET_ATTR_RW(1, 3);
605static ALS_TARGET_ATTR_RW(1, 4);
606
607static ALS_TARGET_ATTR_RW(2, 0);
608static ALS_TARGET_ATTR_RW(2, 1);
609static ALS_TARGET_ATTR_RW(2, 2);
610static ALS_TARGET_ATTR_RW(2, 3);
611static ALS_TARGET_ATTR_RW(2, 4);
612
613#define ALS_THRESH_FALLING_ATTR_RW(_nr) \
614 LM3533_ALS_ATTR(in_illuminance0_thresh##_nr##_falling_value, \
615 S_IRUGO | S_IWUSR, \
616 show_als_attr, store_als_attr, \
617 LM3533_ATTR_TYPE_THRESH_FALLING, _nr, 0)
618
619#define ALS_THRESH_RAISING_ATTR_RW(_nr) \
620 LM3533_ALS_ATTR(in_illuminance0_thresh##_nr##_raising_value, \
621 S_IRUGO | S_IWUSR, \
622 show_als_attr, store_als_attr, \
623 LM3533_ATTR_TYPE_THRESH_RAISING, _nr, 0)
624/*
625 * ALS Zone thresholds (boundaries)
626 *
627 * in_illuminance0_thresh[0-3]_falling_value 0-255
628 * in_illuminance0_thresh[0-3]_raising_value 0-255
629 */
630static ALS_THRESH_FALLING_ATTR_RW(0);
631static ALS_THRESH_FALLING_ATTR_RW(1);
632static ALS_THRESH_FALLING_ATTR_RW(2);
633static ALS_THRESH_FALLING_ATTR_RW(3);
634
635static ALS_THRESH_RAISING_ATTR_RW(0);
636static ALS_THRESH_RAISING_ATTR_RW(1);
637static ALS_THRESH_RAISING_ATTR_RW(2);
638static ALS_THRESH_RAISING_ATTR_RW(3);
639
640#define ALS_HYSTERESIS_ATTR_RO(_nr) \
641 LM3533_ALS_ATTR(in_illuminance0_thresh##_nr##_hysteresis, \
642 S_IRUGO, show_als_attr, NULL, \
643 LM3533_ATTR_TYPE_HYSTERESIS, _nr, 0)
644/*
645 * ALS Zone threshold hysteresis
646 *
647 * threshY_hysteresis = threshY_raising - threshY_falling
648 *
649 * in_illuminance0_thresh[0-3]_hysteresis 0-255
650 * in_illuminance0_thresh[0-3]_hysteresis 0-255
651 */
652static ALS_HYSTERESIS_ATTR_RO(0);
653static ALS_HYSTERESIS_ATTR_RO(1);
654static ALS_HYSTERESIS_ATTR_RO(2);
655static ALS_HYSTERESIS_ATTR_RO(3);
656
657#define ILLUMINANCE_ATTR_RO(_name) \
658 DEVICE_ATTR(in_illuminance0_##_name, S_IRUGO, show_##_name, NULL)
659#define ILLUMINANCE_ATTR_RW(_name) \
586d48f9 660 DEVICE_ATTR(in_illuminance0_##_name, S_IRUGO | S_IWUSR, \
9c8ea1b2
JH
661 show_##_name, store_##_name)
662/*
663 * ALS Zone threshold-event enable
664 *
665 * in_illuminance0_thresh_either_en 0,1
666 */
667static ILLUMINANCE_ATTR_RW(thresh_either_en);
668
669/*
670 * ALS Current Zone
671 *
672 * in_illuminance0_zone 0-4
673 */
674static ILLUMINANCE_ATTR_RO(zone);
675
676static struct attribute *lm3533_als_event_attributes[] = {
677 &dev_attr_in_illuminance0_thresh_either_en.attr,
678 &lm3533_als_attr_in_illuminance0_thresh0_falling_value.dev_attr.attr,
679 &lm3533_als_attr_in_illuminance0_thresh0_hysteresis.dev_attr.attr,
680 &lm3533_als_attr_in_illuminance0_thresh0_raising_value.dev_attr.attr,
681 &lm3533_als_attr_in_illuminance0_thresh1_falling_value.dev_attr.attr,
682 &lm3533_als_attr_in_illuminance0_thresh1_hysteresis.dev_attr.attr,
683 &lm3533_als_attr_in_illuminance0_thresh1_raising_value.dev_attr.attr,
684 &lm3533_als_attr_in_illuminance0_thresh2_falling_value.dev_attr.attr,
685 &lm3533_als_attr_in_illuminance0_thresh2_hysteresis.dev_attr.attr,
686 &lm3533_als_attr_in_illuminance0_thresh2_raising_value.dev_attr.attr,
687 &lm3533_als_attr_in_illuminance0_thresh3_falling_value.dev_attr.attr,
688 &lm3533_als_attr_in_illuminance0_thresh3_hysteresis.dev_attr.attr,
689 &lm3533_als_attr_in_illuminance0_thresh3_raising_value.dev_attr.attr,
690 NULL
691};
692
693static struct attribute_group lm3533_als_event_attribute_group = {
694 .attrs = lm3533_als_event_attributes
695};
696
697static struct attribute *lm3533_als_attributes[] = {
698 &dev_attr_in_illuminance0_zone.attr,
699 &lm3533_als_attr_out_current0_current0_raw.dev_attr.attr,
700 &lm3533_als_attr_out_current0_current1_raw.dev_attr.attr,
701 &lm3533_als_attr_out_current0_current2_raw.dev_attr.attr,
702 &lm3533_als_attr_out_current0_current3_raw.dev_attr.attr,
703 &lm3533_als_attr_out_current0_current4_raw.dev_attr.attr,
704 &lm3533_als_attr_out_current1_current0_raw.dev_attr.attr,
705 &lm3533_als_attr_out_current1_current1_raw.dev_attr.attr,
706 &lm3533_als_attr_out_current1_current2_raw.dev_attr.attr,
707 &lm3533_als_attr_out_current1_current3_raw.dev_attr.attr,
708 &lm3533_als_attr_out_current1_current4_raw.dev_attr.attr,
709 &lm3533_als_attr_out_current2_current0_raw.dev_attr.attr,
710 &lm3533_als_attr_out_current2_current1_raw.dev_attr.attr,
711 &lm3533_als_attr_out_current2_current2_raw.dev_attr.attr,
712 &lm3533_als_attr_out_current2_current3_raw.dev_attr.attr,
713 &lm3533_als_attr_out_current2_current4_raw.dev_attr.attr,
714 NULL
715};
716
717static struct attribute_group lm3533_als_attribute_group = {
718 .attrs = lm3533_als_attributes
719};
720
fc52692c 721static int lm3533_als_set_input_mode(struct lm3533_als *als, bool pwm_mode)
9c8ea1b2
JH
722{
723 u8 mask = LM3533_ALS_INPUT_MODE_MASK;
724 u8 val;
725 int ret;
726
727 if (pwm_mode)
728 val = mask; /* pwm input */
729 else
730 val = 0; /* analog input */
731
732 ret = lm3533_update(als->lm3533, LM3533_REG_ALS_CONF, val, mask);
733 if (ret) {
734 dev_err(&als->pdev->dev, "failed to set input mode %d\n",
735 pwm_mode);
736 return ret;
737 }
738
739 return 0;
740}
741
fc52692c 742static int lm3533_als_set_resistor(struct lm3533_als *als, u8 val)
9c8ea1b2
JH
743{
744 int ret;
745
18fb1ab0
BA
746 if (val < LM3533_ALS_RESISTOR_MIN || val > LM3533_ALS_RESISTOR_MAX) {
747 dev_err(&als->pdev->dev, "invalid resistor value\n");
9c8ea1b2 748 return -EINVAL;
18fb1ab0 749 };
9c8ea1b2
JH
750
751 ret = lm3533_write(als->lm3533, LM3533_REG_ALS_RESISTOR_SELECT, val);
752 if (ret) {
753 dev_err(&als->pdev->dev, "failed to set resistor\n");
754 return ret;
755 }
756
757 return 0;
758}
759
fc52692c
GKH
760static int lm3533_als_setup(struct lm3533_als *als,
761 struct lm3533_als_platform_data *pdata)
9c8ea1b2
JH
762{
763 int ret;
764
765 ret = lm3533_als_set_input_mode(als, pdata->pwm_mode);
766 if (ret)
767 return ret;
768
769 /* ALS input is always high impedance in PWM-mode. */
770 if (!pdata->pwm_mode) {
771 ret = lm3533_als_set_resistor(als, pdata->r_select);
772 if (ret)
773 return ret;
774 }
775
776 return 0;
777}
778
fc52692c 779static int lm3533_als_setup_irq(struct lm3533_als *als, void *dev)
9c8ea1b2
JH
780{
781 u8 mask = LM3533_ALS_INT_ENABLE_MASK;
782 int ret;
783
784 /* Make sure interrupts are disabled. */
785 ret = lm3533_update(als->lm3533, LM3533_REG_ALS_ZONE_INFO, 0, mask);
786 if (ret) {
787 dev_err(&als->pdev->dev, "failed to disable interrupts\n");
788 return ret;
789 }
790
791 ret = request_threaded_irq(als->irq, NULL, lm3533_als_isr,
792 IRQF_TRIGGER_LOW | IRQF_ONESHOT,
793 dev_name(&als->pdev->dev), dev);
794 if (ret) {
795 dev_err(&als->pdev->dev, "failed to request irq %d\n",
796 als->irq);
797 return ret;
798 }
799
800 return 0;
801}
802
fc52692c 803static int lm3533_als_enable(struct lm3533_als *als)
9c8ea1b2
JH
804{
805 u8 mask = LM3533_ALS_ENABLE_MASK;
806 int ret;
807
808 ret = lm3533_update(als->lm3533, LM3533_REG_ALS_CONF, mask, mask);
809 if (ret)
810 dev_err(&als->pdev->dev, "failed to enable ALS\n");
811
812 return ret;
813}
814
815static int lm3533_als_disable(struct lm3533_als *als)
816{
817 u8 mask = LM3533_ALS_ENABLE_MASK;
818 int ret;
819
820 ret = lm3533_update(als->lm3533, LM3533_REG_ALS_CONF, 0, mask);
821 if (ret)
822 dev_err(&als->pdev->dev, "failed to disable ALS\n");
823
824 return ret;
825}
826
827static const struct iio_info lm3533_als_info = {
828 .attrs = &lm3533_als_attribute_group,
829 .event_attrs = &lm3533_als_event_attribute_group,
830 .driver_module = THIS_MODULE,
831 .read_raw = &lm3533_als_read_raw,
832};
833
fc52692c 834static int lm3533_als_probe(struct platform_device *pdev)
9c8ea1b2
JH
835{
836 struct lm3533 *lm3533;
837 struct lm3533_als_platform_data *pdata;
838 struct lm3533_als *als;
839 struct iio_dev *indio_dev;
840 int ret;
841
842 lm3533 = dev_get_drvdata(pdev->dev.parent);
843 if (!lm3533)
844 return -EINVAL;
845
846 pdata = pdev->dev.platform_data;
847 if (!pdata) {
848 dev_err(&pdev->dev, "no platform data\n");
849 return -EINVAL;
850 }
851
3d0ccbaf 852 indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*als));
9c8ea1b2
JH
853 if (!indio_dev)
854 return -ENOMEM;
855
856 indio_dev->info = &lm3533_als_info;
857 indio_dev->channels = lm3533_als_channels;
858 indio_dev->num_channels = ARRAY_SIZE(lm3533_als_channels);
859 indio_dev->name = dev_name(&pdev->dev);
860 indio_dev->dev.parent = pdev->dev.parent;
861 indio_dev->modes = INDIO_DIRECT_MODE;
862
863 als = iio_priv(indio_dev);
864 als->lm3533 = lm3533;
865 als->pdev = pdev;
866 als->irq = lm3533->irq;
867 atomic_set(&als->zone, 0);
868 mutex_init(&als->thresh_mutex);
869
870 platform_set_drvdata(pdev, indio_dev);
871
872 if (als->irq) {
873 ret = lm3533_als_setup_irq(als, indio_dev);
874 if (ret)
3d0ccbaf 875 return ret;
9c8ea1b2
JH
876 }
877
878 ret = lm3533_als_setup(als, pdata);
879 if (ret)
880 goto err_free_irq;
881
882 ret = lm3533_als_enable(als);
883 if (ret)
884 goto err_free_irq;
885
886 ret = iio_device_register(indio_dev);
887 if (ret) {
888 dev_err(&pdev->dev, "failed to register ALS\n");
889 goto err_disable;
890 }
891
892 return 0;
893
894err_disable:
895 lm3533_als_disable(als);
896err_free_irq:
897 if (als->irq)
898 free_irq(als->irq, indio_dev);
9c8ea1b2
JH
899
900 return ret;
901}
902
fc52692c 903static int lm3533_als_remove(struct platform_device *pdev)
9c8ea1b2
JH
904{
905 struct iio_dev *indio_dev = platform_get_drvdata(pdev);
906 struct lm3533_als *als = iio_priv(indio_dev);
907
908 lm3533_als_set_int_mode(indio_dev, false);
909 iio_device_unregister(indio_dev);
910 lm3533_als_disable(als);
911 if (als->irq)
912 free_irq(als->irq, indio_dev);
9c8ea1b2
JH
913
914 return 0;
915}
916
917static struct platform_driver lm3533_als_driver = {
918 .driver = {
919 .name = "lm3533-als",
9c8ea1b2
JH
920 },
921 .probe = lm3533_als_probe,
fc52692c 922 .remove = lm3533_als_remove,
9c8ea1b2
JH
923};
924module_platform_driver(lm3533_als_driver);
925
926MODULE_AUTHOR("Johan Hovold <jhovold@gmail.com>");
927MODULE_DESCRIPTION("LM3533 Ambient Light Sensor driver");
928MODULE_LICENSE("GPL");
929MODULE_ALIAS("platform:lm3533-als");
This page took 0.441283 seconds and 5 git commands to generate.