Version:  2.0.40 2.2.26 2.4.37 3.1 3.2 3.3 3.4 3.5 3.6 3.7 3.8 3.9 3.10 3.11 3.12 3.13 3.14 3.15 3.16 3.17

Linux/drivers/iio/light/lm3533-als.c

  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 
 54 struct 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 
 66 static 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 
 90 static 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 
108 static 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  */
128 static inline u8 lm3533_als_get_target_reg(unsigned channel, unsigned zone)
129 {
130         return LM3533_REG_ALS_TARGET_BASE + 5 * channel + zone;
131 }
132 
133 static 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 
154 static 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 
175 static 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 
195 static 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 
237 static 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 
250 static 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());
271 out:
272         return IRQ_HANDLED;
273 }
274 
275 static 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 
297 static 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 
315 static 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 
322 static 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 
340 static 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         }
375 out:
376         mutex_unlock(&als->thresh_mutex);
377 
378         return ret;
379 }
380 
381 static 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;
401 out:
402         mutex_unlock(&als->thresh_mutex);
403 
404         return ret;
405 }
406 
407 static 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 
427 static 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 
470 static 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 
484 enum 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 
491 struct lm3533_als_attribute {
492         struct device_attribute dev_attr;
493         enum lm3533_als_attribute_type type;
494         u8 val1;
495         u8 val2;
496 };
497 
498 static inline struct lm3533_als_attribute *
499 to_lm3533_als_attr(struct device_attribute *attr)
500 {
501         return container_of(attr, struct lm3533_als_attribute, dev_attr);
502 }
503 
504 static 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 
540 static 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  */
595 static ALS_TARGET_ATTR_RW(0, 0);
596 static ALS_TARGET_ATTR_RW(0, 1);
597 static ALS_TARGET_ATTR_RW(0, 2);
598 static ALS_TARGET_ATTR_RW(0, 3);
599 static ALS_TARGET_ATTR_RW(0, 4);
600 
601 static ALS_TARGET_ATTR_RW(1, 0);
602 static ALS_TARGET_ATTR_RW(1, 1);
603 static ALS_TARGET_ATTR_RW(1, 2);
604 static ALS_TARGET_ATTR_RW(1, 3);
605 static ALS_TARGET_ATTR_RW(1, 4);
606 
607 static ALS_TARGET_ATTR_RW(2, 0);
608 static ALS_TARGET_ATTR_RW(2, 1);
609 static ALS_TARGET_ATTR_RW(2, 2);
610 static ALS_TARGET_ATTR_RW(2, 3);
611 static 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  */
630 static ALS_THRESH_FALLING_ATTR_RW(0);
631 static ALS_THRESH_FALLING_ATTR_RW(1);
632 static ALS_THRESH_FALLING_ATTR_RW(2);
633 static ALS_THRESH_FALLING_ATTR_RW(3);
634 
635 static ALS_THRESH_RAISING_ATTR_RW(0);
636 static ALS_THRESH_RAISING_ATTR_RW(1);
637 static ALS_THRESH_RAISING_ATTR_RW(2);
638 static 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  */
652 static ALS_HYSTERESIS_ATTR_RO(0);
653 static ALS_HYSTERESIS_ATTR_RO(1);
654 static ALS_HYSTERESIS_ATTR_RO(2);
655 static 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  */
667 static ILLUMINANCE_ATTR_RW(thresh_either_en);
668 
669 /*
670  * ALS Current Zone
671  *
672  * in_illuminance0_zone         0-4
673  */
674 static ILLUMINANCE_ATTR_RO(zone);
675 
676 static 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 
693 static struct attribute_group lm3533_als_event_attribute_group = {
694         .attrs = lm3533_als_event_attributes
695 };
696 
697 static 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 
717 static struct attribute_group lm3533_als_attribute_group = {
718         .attrs = lm3533_als_attributes
719 };
720 
721 static 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 
742 static 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 
758 static 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 
777 static 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 
801 static 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 
813 static 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 
825 static 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 
832 static 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 
892 err_disable:
893         lm3533_als_disable(als);
894 err_free_irq:
895         if (als->irq)
896                 free_irq(als->irq, indio_dev);
897 
898         return ret;
899 }
900 
901 static 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 
915 static struct platform_driver lm3533_als_driver = {
916         .driver = {
917                 .name   = "lm3533-als",
918                 .owner  = THIS_MODULE,
919         },
920         .probe          = lm3533_als_probe,
921         .remove         = lm3533_als_remove,
922 };
923 module_platform_driver(lm3533_als_driver);
924 
925 MODULE_AUTHOR("Johan Hovold <jhovold@gmail.com>");
926 MODULE_DESCRIPTION("LM3533 Ambient Light Sensor driver");
927 MODULE_LICENSE("GPL");
928 MODULE_ALIAS("platform:lm3533-als");
929 

This page was automatically generated by LXR 0.3.1 (source).  •  Linux is a registered trademark of Linus Torvalds  •  Contact us