linux/drivers/iio/light/apds9300.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * apds9300.c - IIO driver for Avago APDS9300 ambient light sensor
   4 *
   5 * Copyright 2013 Oleksandr Kravchenko <o.v.kravchenko@globallogic.com>
   6 */
   7
   8#include <linux/module.h>
   9#include <linux/slab.h>
  10#include <linux/pm.h>
  11#include <linux/i2c.h>
  12#include <linux/err.h>
  13#include <linux/mutex.h>
  14#include <linux/interrupt.h>
  15#include <linux/iio/iio.h>
  16#include <linux/iio/sysfs.h>
  17#include <linux/iio/events.h>
  18
  19#define APDS9300_DRV_NAME "apds9300"
  20#define APDS9300_IRQ_NAME "apds9300_event"
  21
  22/* Command register bits */
  23#define APDS9300_CMD    BIT(7) /* Select command register. Must write as 1 */
  24#define APDS9300_WORD   BIT(5) /* I2C write/read: if 1 word, if 0 byte */
  25#define APDS9300_CLEAR  BIT(6) /* Interrupt clear. Clears pending interrupt */
  26
  27/* Register set */
  28#define APDS9300_CONTROL        0x00 /* Control of basic functions */
  29#define APDS9300_THRESHLOWLOW   0x02 /* Low byte of low interrupt threshold */
  30#define APDS9300_THRESHHIGHLOW  0x04 /* Low byte of high interrupt threshold */
  31#define APDS9300_INTERRUPT      0x06 /* Interrupt control */
  32#define APDS9300_DATA0LOW       0x0c /* Low byte of ADC channel 0 */
  33#define APDS9300_DATA1LOW       0x0e /* Low byte of ADC channel 1 */
  34
  35/* Power on/off value for APDS9300_CONTROL register */
  36#define APDS9300_POWER_ON       0x03
  37#define APDS9300_POWER_OFF      0x00
  38
  39/* Interrupts */
  40#define APDS9300_INTR_ENABLE    0x10
  41/* Interrupt Persist Function: Any value outside of threshold range */
  42#define APDS9300_THRESH_INTR    0x01
  43
  44#define APDS9300_THRESH_MAX     0xffff /* Max threshold value */
  45
  46struct apds9300_data {
  47        struct i2c_client *client;
  48        struct mutex mutex;
  49        int power_state;
  50        int thresh_low;
  51        int thresh_hi;
  52        int intr_en;
  53};
  54
  55/* Lux calculation */
  56
  57/* Calculated values 1000 * (CH1/CH0)^1.4 for CH1/CH0 from 0 to 0.52 */
  58static const u16 apds9300_lux_ratio[] = {
  59        0, 2, 4, 7, 11, 15, 19, 24, 29, 34, 40, 45, 51, 57, 64, 70, 77, 84, 91,
  60        98, 105, 112, 120, 128, 136, 144, 152, 160, 168, 177, 185, 194, 203,
  61        212, 221, 230, 239, 249, 258, 268, 277, 287, 297, 307, 317, 327, 337,
  62        347, 358, 368, 379, 390, 400,
  63};
  64
  65static unsigned long apds9300_calculate_lux(u16 ch0, u16 ch1)
  66{
  67        unsigned long lux, tmp;
  68
  69        /* avoid division by zero */
  70        if (ch0 == 0)
  71                return 0;
  72
  73        tmp = DIV_ROUND_UP(ch1 * 100, ch0);
  74        if (tmp <= 52) {
  75                lux = 3150 * ch0 - (unsigned long)DIV_ROUND_UP_ULL(ch0
  76                                * apds9300_lux_ratio[tmp] * 5930ull, 1000);
  77        } else if (tmp <= 65) {
  78                lux = 2290 * ch0 - 2910 * ch1;
  79        } else if (tmp <= 80) {
  80                lux = 1570 * ch0 - 1800 * ch1;
  81        } else if (tmp <= 130) {
  82                lux = 338 * ch0 - 260 * ch1;
  83        } else {
  84                lux = 0;
  85        }
  86
  87        return lux / 100000;
  88}
  89
  90static int apds9300_get_adc_val(struct apds9300_data *data, int adc_number)
  91{
  92        int ret;
  93        u8 flags = APDS9300_CMD | APDS9300_WORD;
  94
  95        if (!data->power_state)
  96                return -EBUSY;
  97
  98        /* Select ADC0 or ADC1 data register */
  99        flags |= adc_number ? APDS9300_DATA1LOW : APDS9300_DATA0LOW;
 100
 101        ret = i2c_smbus_read_word_data(data->client, flags);
 102        if (ret < 0)
 103                dev_err(&data->client->dev,
 104                        "failed to read ADC%d value\n", adc_number);
 105
 106        return ret;
 107}
 108
 109static int apds9300_set_thresh_low(struct apds9300_data *data, int value)
 110{
 111        int ret;
 112
 113        if (!data->power_state)
 114                return -EBUSY;
 115
 116        if (value > APDS9300_THRESH_MAX)
 117                return -EINVAL;
 118
 119        ret = i2c_smbus_write_word_data(data->client, APDS9300_THRESHLOWLOW
 120                        | APDS9300_CMD | APDS9300_WORD, value);
 121        if (ret) {
 122                dev_err(&data->client->dev, "failed to set thresh_low\n");
 123                return ret;
 124        }
 125        data->thresh_low = value;
 126
 127        return 0;
 128}
 129
 130static int apds9300_set_thresh_hi(struct apds9300_data *data, int value)
 131{
 132        int ret;
 133
 134        if (!data->power_state)
 135                return -EBUSY;
 136
 137        if (value > APDS9300_THRESH_MAX)
 138                return -EINVAL;
 139
 140        ret = i2c_smbus_write_word_data(data->client, APDS9300_THRESHHIGHLOW
 141                        | APDS9300_CMD | APDS9300_WORD, value);
 142        if (ret) {
 143                dev_err(&data->client->dev, "failed to set thresh_hi\n");
 144                return ret;
 145        }
 146        data->thresh_hi = value;
 147
 148        return 0;
 149}
 150
 151static int apds9300_set_intr_state(struct apds9300_data *data, int state)
 152{
 153        int ret;
 154        u8 cmd;
 155
 156        if (!data->power_state)
 157                return -EBUSY;
 158
 159        cmd = state ? APDS9300_INTR_ENABLE | APDS9300_THRESH_INTR : 0x00;
 160        ret = i2c_smbus_write_byte_data(data->client,
 161                        APDS9300_INTERRUPT | APDS9300_CMD, cmd);
 162        if (ret) {
 163                dev_err(&data->client->dev,
 164                        "failed to set interrupt state %d\n", state);
 165                return ret;
 166        }
 167        data->intr_en = state;
 168
 169        return 0;
 170}
 171
 172static int apds9300_set_power_state(struct apds9300_data *data, int state)
 173{
 174        int ret;
 175        u8 cmd;
 176
 177        cmd = state ? APDS9300_POWER_ON : APDS9300_POWER_OFF;
 178        ret = i2c_smbus_write_byte_data(data->client,
 179                        APDS9300_CONTROL | APDS9300_CMD, cmd);
 180        if (ret) {
 181                dev_err(&data->client->dev,
 182                        "failed to set power state %d\n", state);
 183                return ret;
 184        }
 185        data->power_state = state;
 186
 187        return 0;
 188}
 189
 190static void apds9300_clear_intr(struct apds9300_data *data)
 191{
 192        int ret;
 193
 194        ret = i2c_smbus_write_byte(data->client, APDS9300_CLEAR | APDS9300_CMD);
 195        if (ret < 0)
 196                dev_err(&data->client->dev, "failed to clear interrupt\n");
 197}
 198
 199static int apds9300_chip_init(struct apds9300_data *data)
 200{
 201        int ret;
 202
 203        /* Need to set power off to ensure that the chip is off */
 204        ret = apds9300_set_power_state(data, 0);
 205        if (ret < 0)
 206                goto err;
 207        /*
 208         * Probe the chip. To do so we try to power up the device and then to
 209         * read back the 0x03 code
 210         */
 211        ret = apds9300_set_power_state(data, 1);
 212        if (ret < 0)
 213                goto err;
 214        ret = i2c_smbus_read_byte_data(data->client,
 215                        APDS9300_CONTROL | APDS9300_CMD);
 216        if (ret != APDS9300_POWER_ON) {
 217                ret = -ENODEV;
 218                goto err;
 219        }
 220        /*
 221         * Disable interrupt to ensure thai it is doesn't enable
 222         * i.e. after device soft reset
 223         */
 224        ret = apds9300_set_intr_state(data, 0);
 225        if (ret < 0)
 226                goto err;
 227
 228        return 0;
 229
 230err:
 231        dev_err(&data->client->dev, "failed to init the chip\n");
 232        return ret;
 233}
 234
 235static int apds9300_read_raw(struct iio_dev *indio_dev,
 236                struct iio_chan_spec const *chan, int *val, int *val2,
 237                long mask)
 238{
 239        int ch0, ch1, ret = -EINVAL;
 240        struct apds9300_data *data = iio_priv(indio_dev);
 241
 242        mutex_lock(&data->mutex);
 243        switch (chan->type) {
 244        case IIO_LIGHT:
 245                ch0 = apds9300_get_adc_val(data, 0);
 246                if (ch0 < 0) {
 247                        ret = ch0;
 248                        break;
 249                }
 250                ch1 = apds9300_get_adc_val(data, 1);
 251                if (ch1 < 0) {
 252                        ret = ch1;
 253                        break;
 254                }
 255                *val = apds9300_calculate_lux(ch0, ch1);
 256                ret = IIO_VAL_INT;
 257                break;
 258        case IIO_INTENSITY:
 259                ret = apds9300_get_adc_val(data, chan->channel);
 260                if (ret < 0)
 261                        break;
 262                *val = ret;
 263                ret = IIO_VAL_INT;
 264                break;
 265        default:
 266                break;
 267        }
 268        mutex_unlock(&data->mutex);
 269
 270        return ret;
 271}
 272
 273static int apds9300_read_thresh(struct iio_dev *indio_dev,
 274                const struct iio_chan_spec *chan, enum iio_event_type type,
 275                enum iio_event_direction dir, enum iio_event_info info,
 276                int *val, int *val2)
 277{
 278        struct apds9300_data *data = iio_priv(indio_dev);
 279
 280        switch (dir) {
 281        case IIO_EV_DIR_RISING:
 282                *val = data->thresh_hi;
 283                break;
 284        case IIO_EV_DIR_FALLING:
 285                *val = data->thresh_low;
 286                break;
 287        default:
 288                return -EINVAL;
 289        }
 290
 291        return IIO_VAL_INT;
 292}
 293
 294static int apds9300_write_thresh(struct iio_dev *indio_dev,
 295                const struct iio_chan_spec *chan, enum iio_event_type type,
 296                enum iio_event_direction dir, enum iio_event_info info, int val,
 297                int val2)
 298{
 299        struct apds9300_data *data = iio_priv(indio_dev);
 300        int ret;
 301
 302        mutex_lock(&data->mutex);
 303        if (dir == IIO_EV_DIR_RISING)
 304                ret = apds9300_set_thresh_hi(data, val);
 305        else
 306                ret = apds9300_set_thresh_low(data, val);
 307        mutex_unlock(&data->mutex);
 308
 309        return ret;
 310}
 311
 312static int apds9300_read_interrupt_config(struct iio_dev *indio_dev,
 313                const struct iio_chan_spec *chan,
 314                enum iio_event_type type,
 315                enum iio_event_direction dir)
 316{
 317        struct apds9300_data *data = iio_priv(indio_dev);
 318
 319        return data->intr_en;
 320}
 321
 322static int apds9300_write_interrupt_config(struct iio_dev *indio_dev,
 323                const struct iio_chan_spec *chan, enum iio_event_type type,
 324                enum iio_event_direction dir, int state)
 325{
 326        struct apds9300_data *data = iio_priv(indio_dev);
 327        int ret;
 328
 329        mutex_lock(&data->mutex);
 330        ret = apds9300_set_intr_state(data, state);
 331        mutex_unlock(&data->mutex);
 332
 333        return ret;
 334}
 335
 336static const struct iio_info apds9300_info_no_irq = {
 337        .read_raw       = apds9300_read_raw,
 338};
 339
 340static const struct iio_info apds9300_info = {
 341        .read_raw               = apds9300_read_raw,
 342        .read_event_value       = apds9300_read_thresh,
 343        .write_event_value      = apds9300_write_thresh,
 344        .read_event_config      = apds9300_read_interrupt_config,
 345        .write_event_config     = apds9300_write_interrupt_config,
 346};
 347
 348static const struct iio_event_spec apds9300_event_spec[] = {
 349        {
 350                .type = IIO_EV_TYPE_THRESH,
 351                .dir = IIO_EV_DIR_RISING,
 352                .mask_separate = BIT(IIO_EV_INFO_VALUE) |
 353                        BIT(IIO_EV_INFO_ENABLE),
 354        }, {
 355                .type = IIO_EV_TYPE_THRESH,
 356                .dir = IIO_EV_DIR_FALLING,
 357                .mask_separate = BIT(IIO_EV_INFO_VALUE) |
 358                        BIT(IIO_EV_INFO_ENABLE),
 359        },
 360};
 361
 362static const struct iio_chan_spec apds9300_channels[] = {
 363        {
 364                .type = IIO_LIGHT,
 365                .channel = 0,
 366                .indexed = true,
 367                .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED),
 368        }, {
 369                .type = IIO_INTENSITY,
 370                .channel = 0,
 371                .channel2 = IIO_MOD_LIGHT_BOTH,
 372                .indexed = true,
 373                .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
 374                .event_spec = apds9300_event_spec,
 375                .num_event_specs = ARRAY_SIZE(apds9300_event_spec),
 376        }, {
 377                .type = IIO_INTENSITY,
 378                .channel = 1,
 379                .channel2 = IIO_MOD_LIGHT_IR,
 380                .indexed = true,
 381                .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
 382        },
 383};
 384
 385static irqreturn_t apds9300_interrupt_handler(int irq, void *private)
 386{
 387        struct iio_dev *dev_info = private;
 388        struct apds9300_data *data = iio_priv(dev_info);
 389
 390        iio_push_event(dev_info,
 391                       IIO_UNMOD_EVENT_CODE(IIO_INTENSITY, 0,
 392                                            IIO_EV_TYPE_THRESH,
 393                                            IIO_EV_DIR_EITHER),
 394                       iio_get_time_ns(dev_info));
 395
 396        apds9300_clear_intr(data);
 397
 398        return IRQ_HANDLED;
 399}
 400
 401static int apds9300_probe(struct i2c_client *client,
 402                const struct i2c_device_id *id)
 403{
 404        struct apds9300_data *data;
 405        struct iio_dev *indio_dev;
 406        int ret;
 407
 408        indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
 409        if (!indio_dev)
 410                return -ENOMEM;
 411
 412        data = iio_priv(indio_dev);
 413        i2c_set_clientdata(client, indio_dev);
 414        data->client = client;
 415
 416        ret = apds9300_chip_init(data);
 417        if (ret < 0)
 418                goto err;
 419
 420        mutex_init(&data->mutex);
 421
 422        indio_dev->dev.parent = &client->dev;
 423        indio_dev->channels = apds9300_channels;
 424        indio_dev->num_channels = ARRAY_SIZE(apds9300_channels);
 425        indio_dev->name = APDS9300_DRV_NAME;
 426        indio_dev->modes = INDIO_DIRECT_MODE;
 427
 428        if (client->irq)
 429                indio_dev->info = &apds9300_info;
 430        else
 431                indio_dev->info = &apds9300_info_no_irq;
 432
 433        if (client->irq) {
 434                ret = devm_request_threaded_irq(&client->dev, client->irq,
 435                                NULL, apds9300_interrupt_handler,
 436                                IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
 437                                APDS9300_IRQ_NAME, indio_dev);
 438                if (ret) {
 439                        dev_err(&client->dev, "irq request error %d\n", -ret);
 440                        goto err;
 441                }
 442        }
 443
 444        ret = iio_device_register(indio_dev);
 445        if (ret < 0)
 446                goto err;
 447
 448        return 0;
 449
 450err:
 451        /* Ensure that power off in case of error */
 452        apds9300_set_power_state(data, 0);
 453        return ret;
 454}
 455
 456static int apds9300_remove(struct i2c_client *client)
 457{
 458        struct iio_dev *indio_dev = i2c_get_clientdata(client);
 459        struct apds9300_data *data = iio_priv(indio_dev);
 460
 461        iio_device_unregister(indio_dev);
 462
 463        /* Ensure that power off and interrupts are disabled */
 464        apds9300_set_intr_state(data, 0);
 465        apds9300_set_power_state(data, 0);
 466
 467        return 0;
 468}
 469
 470#ifdef CONFIG_PM_SLEEP
 471static int apds9300_suspend(struct device *dev)
 472{
 473        struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
 474        struct apds9300_data *data = iio_priv(indio_dev);
 475        int ret;
 476
 477        mutex_lock(&data->mutex);
 478        ret = apds9300_set_power_state(data, 0);
 479        mutex_unlock(&data->mutex);
 480
 481        return ret;
 482}
 483
 484static int apds9300_resume(struct device *dev)
 485{
 486        struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
 487        struct apds9300_data *data = iio_priv(indio_dev);
 488        int ret;
 489
 490        mutex_lock(&data->mutex);
 491        ret = apds9300_set_power_state(data, 1);
 492        mutex_unlock(&data->mutex);
 493
 494        return ret;
 495}
 496
 497static SIMPLE_DEV_PM_OPS(apds9300_pm_ops, apds9300_suspend, apds9300_resume);
 498#define APDS9300_PM_OPS (&apds9300_pm_ops)
 499#else
 500#define APDS9300_PM_OPS NULL
 501#endif
 502
 503static const struct i2c_device_id apds9300_id[] = {
 504        { APDS9300_DRV_NAME, 0 },
 505        { }
 506};
 507
 508MODULE_DEVICE_TABLE(i2c, apds9300_id);
 509
 510static struct i2c_driver apds9300_driver = {
 511        .driver = {
 512                .name   = APDS9300_DRV_NAME,
 513                .pm     = APDS9300_PM_OPS,
 514        },
 515        .probe          = apds9300_probe,
 516        .remove         = apds9300_remove,
 517        .id_table       = apds9300_id,
 518};
 519
 520module_i2c_driver(apds9300_driver);
 521
 522MODULE_AUTHOR("Kravchenko Oleksandr <o.v.kravchenko@globallogic.com>");
 523MODULE_AUTHOR("GlobalLogic inc.");
 524MODULE_DESCRIPTION("APDS9300 ambient light photo sensor driver");
 525MODULE_LICENSE("GPL");
 526