linux/drivers/iio/light/lm3533-als.c
<<
>>
Prefs
   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 = iio_device_alloc(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                        goto err_free_dev;
 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);
 897err_free_dev:
 898        iio_device_free(indio_dev);
 899
 900        return ret;
 901}
 902
 903static int lm3533_als_remove(struct platform_device *pdev)
 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);
 913        iio_device_free(indio_dev);
 914
 915        return 0;
 916}
 917
 918static struct platform_driver lm3533_als_driver = {
 919        .driver = {
 920                .name   = "lm3533-als",
 921                .owner  = THIS_MODULE,
 922        },
 923        .probe          = lm3533_als_probe,
 924        .remove         = lm3533_als_remove,
 925};
 926module_platform_driver(lm3533_als_driver);
 927
 928MODULE_AUTHOR("Johan Hovold <jhovold@gmail.com>");
 929MODULE_DESCRIPTION("LM3533 Ambient Light Sensor driver");
 930MODULE_LICENSE("GPL");
 931MODULE_ALIAS("platform:lm3533-als");
 932