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,					\
234		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),		\
235	}
236
237static const struct iio_chan_spec lm3533_als_channels[] = {
238	{
239		.type		= IIO_LIGHT,
240		.channel	= 0,
241		.indexed	= true,
242		.info_mask_separate = BIT(IIO_CHAN_INFO_AVERAGE_RAW) |
243				   BIT(IIO_CHAN_INFO_RAW),
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
407static ssize_t show_thresh_either_en(struct device *dev,
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
427static ssize_t store_thresh_either_en(struct device *dev,
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) \
660	DEVICE_ATTR(in_illuminance0_##_name, S_IRUGO | S_IWUSR, \
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
721static int lm3533_als_set_input_mode(struct lm3533_als *als, bool pwm_mode)
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
742static int lm3533_als_set_resistor(struct lm3533_als *als, u8 val)
743{
744	int ret;
745
746	if (val < LM3533_ALS_RESISTOR_MIN || val > LM3533_ALS_RESISTOR_MAX)
747		return -EINVAL;
748
749	ret = lm3533_write(als->lm3533, LM3533_REG_ALS_RESISTOR_SELECT, val);
750	if (ret) {
751		dev_err(&als->pdev->dev, "failed to set resistor\n");
752		return ret;
753	}
754
755	return 0;
756}
757
758static int lm3533_als_setup(struct lm3533_als *als,
759			    struct lm3533_als_platform_data *pdata)
760{
761	int ret;
762
763	ret = lm3533_als_set_input_mode(als, pdata->pwm_mode);
764	if (ret)
765		return ret;
766
767	/* ALS input is always high impedance in PWM-mode. */
768	if (!pdata->pwm_mode) {
769		ret = lm3533_als_set_resistor(als, pdata->r_select);
770		if (ret)
771			return ret;
772	}
773
774	return 0;
775}
776
777static int lm3533_als_setup_irq(struct lm3533_als *als, void *dev)
778{
779	u8 mask = LM3533_ALS_INT_ENABLE_MASK;
780	int ret;
781
782	/* Make sure interrupts are disabled. */
783	ret = lm3533_update(als->lm3533, LM3533_REG_ALS_ZONE_INFO, 0, mask);
784	if (ret) {
785		dev_err(&als->pdev->dev, "failed to disable interrupts\n");
786		return ret;
787	}
788
789	ret = request_threaded_irq(als->irq, NULL, lm3533_als_isr,
790					IRQF_TRIGGER_LOW | IRQF_ONESHOT,
791					dev_name(&als->pdev->dev), dev);
792	if (ret) {
793		dev_err(&als->pdev->dev, "failed to request irq %d\n",
794								als->irq);
795		return ret;
796	}
797
798	return 0;
799}
800
801static int lm3533_als_enable(struct lm3533_als *als)
802{
803	u8 mask = LM3533_ALS_ENABLE_MASK;
804	int ret;
805
806	ret = lm3533_update(als->lm3533, LM3533_REG_ALS_CONF, mask, mask);
807	if (ret)
808		dev_err(&als->pdev->dev, "failed to enable ALS\n");
809
810	return ret;
811}
812
813static int lm3533_als_disable(struct lm3533_als *als)
814{
815	u8 mask = LM3533_ALS_ENABLE_MASK;
816	int ret;
817
818	ret = lm3533_update(als->lm3533, LM3533_REG_ALS_CONF, 0, mask);
819	if (ret)
820		dev_err(&als->pdev->dev, "failed to disable ALS\n");
821
822	return ret;
823}
824
825static const struct iio_info lm3533_als_info = {
826	.attrs		= &lm3533_als_attribute_group,
827	.event_attrs	= &lm3533_als_event_attribute_group,
828	.driver_module	= THIS_MODULE,
829	.read_raw	= &lm3533_als_read_raw,
830};
831
832static int lm3533_als_probe(struct platform_device *pdev)
833{
834	struct lm3533 *lm3533;
835	struct lm3533_als_platform_data *pdata;
836	struct lm3533_als *als;
837	struct iio_dev *indio_dev;
838	int ret;
839
840	lm3533 = dev_get_drvdata(pdev->dev.parent);
841	if (!lm3533)
842		return -EINVAL;
843
844	pdata = pdev->dev.platform_data;
845	if (!pdata) {
846		dev_err(&pdev->dev, "no platform data\n");
847		return -EINVAL;
848	}
849
850	indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*als));
851	if (!indio_dev)
852		return -ENOMEM;
853
854	indio_dev->info = &lm3533_als_info;
855	indio_dev->channels = lm3533_als_channels;
856	indio_dev->num_channels = ARRAY_SIZE(lm3533_als_channels);
857	indio_dev->name = dev_name(&pdev->dev);
858	indio_dev->dev.parent = pdev->dev.parent;
859	indio_dev->modes = INDIO_DIRECT_MODE;
860
861	als = iio_priv(indio_dev);
862	als->lm3533 = lm3533;
863	als->pdev = pdev;
864	als->irq = lm3533->irq;
865	atomic_set(&als->zone, 0);
866	mutex_init(&als->thresh_mutex);
867
868	platform_set_drvdata(pdev, indio_dev);
869
870	if (als->irq) {
871		ret = lm3533_als_setup_irq(als, indio_dev);
872		if (ret)
873			return ret;
874	}
875
876	ret = lm3533_als_setup(als, pdata);
877	if (ret)
878		goto err_free_irq;
879
880	ret = lm3533_als_enable(als);
881	if (ret)
882		goto err_free_irq;
883
884	ret = iio_device_register(indio_dev);
885	if (ret) {
886		dev_err(&pdev->dev, "failed to register ALS\n");
887		goto err_disable;
888	}
889
890	return 0;
891
892err_disable:
893	lm3533_als_disable(als);
894err_free_irq:
895	if (als->irq)
896		free_irq(als->irq, indio_dev);
897
898	return ret;
899}
900
901static int lm3533_als_remove(struct platform_device *pdev)
902{
903	struct iio_dev *indio_dev = platform_get_drvdata(pdev);
904	struct lm3533_als *als = iio_priv(indio_dev);
905
906	lm3533_als_set_int_mode(indio_dev, false);
907	iio_device_unregister(indio_dev);
908	lm3533_als_disable(als);
909	if (als->irq)
910		free_irq(als->irq, indio_dev);
911
912	return 0;
913}
914
915static struct platform_driver lm3533_als_driver = {
916	.driver	= {
917		.name	= "lm3533-als",
918	},
919	.probe		= lm3533_als_probe,
920	.remove		= lm3533_als_remove,
921};
922module_platform_driver(lm3533_als_driver);
923
924MODULE_AUTHOR("Johan Hovold <jhovold@gmail.com>");
925MODULE_DESCRIPTION("LM3533 Ambient Light Sensor driver");
926MODULE_LICENSE("GPL");
927MODULE_ALIAS("platform:lm3533-als");
928