linux/drivers/iio/light/pa12203001.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * Copyright (c) 2015 Intel Corporation
   4 *
   5 * Driver for TXC PA12203001 Proximity and Ambient Light Sensor.
   6 *
   7 * To do: Interrupt support.
   8 */
   9
  10#include <linux/kernel.h>
  11#include <linux/module.h>
  12#include <linux/acpi.h>
  13#include <linux/delay.h>
  14#include <linux/i2c.h>
  15#include <linux/iio/iio.h>
  16#include <linux/iio/sysfs.h>
  17#include <linux/mutex.h>
  18#include <linux/pm.h>
  19#include <linux/pm_runtime.h>
  20#include <linux/regmap.h>
  21
  22#define PA12203001_DRIVER_NAME  "pa12203001"
  23
  24#define PA12203001_REG_CFG0             0x00
  25#define PA12203001_REG_CFG1             0x01
  26#define PA12203001_REG_CFG2             0x02
  27#define PA12203001_REG_CFG3             0x03
  28
  29#define PA12203001_REG_ADL              0x0b
  30#define PA12203001_REG_PDH              0x0e
  31
  32#define PA12203001_REG_POFS             0x10
  33#define PA12203001_REG_PSET             0x11
  34
  35#define PA12203001_ALS_EN_MASK          BIT(0)
  36#define PA12203001_PX_EN_MASK           BIT(1)
  37#define PA12203001_PX_NORMAL_MODE_MASK          GENMASK(7, 6)
  38#define PA12203001_AFSR_MASK            GENMASK(5, 4)
  39#define PA12203001_AFSR_SHIFT           4
  40
  41#define PA12203001_PSCAN                        0x03
  42
  43/* als range 31000, ps, als disabled */
  44#define PA12203001_REG_CFG0_DEFAULT             0x30
  45
  46/* led current: 100 mA */
  47#define PA12203001_REG_CFG1_DEFAULT             0x20
  48
  49/* ps mode: normal, interrupts not active */
  50#define PA12203001_REG_CFG2_DEFAULT             0xcc
  51
  52#define PA12203001_REG_CFG3_DEFAULT             0x00
  53
  54#define PA12203001_SLEEP_DELAY_MS               3000
  55
  56#define PA12203001_CHIP_ENABLE          0xff
  57#define PA12203001_CHIP_DISABLE         0x00
  58
  59/* available scales: corresponding to [500, 4000, 7000, 31000]  lux */
  60static const int pa12203001_scales[] = { 7629, 61036, 106813, 473029};
  61
  62struct pa12203001_data {
  63        struct i2c_client *client;
  64
  65        /* protect device states */
  66        struct mutex lock;
  67
  68        bool als_enabled;
  69        bool px_enabled;
  70        bool als_needs_enable;
  71        bool px_needs_enable;
  72
  73        struct regmap *map;
  74};
  75
  76static const struct {
  77        u8 reg;
  78        u8 val;
  79} regvals[] = {
  80        {PA12203001_REG_CFG0, PA12203001_REG_CFG0_DEFAULT},
  81        {PA12203001_REG_CFG1, PA12203001_REG_CFG1_DEFAULT},
  82        {PA12203001_REG_CFG2, PA12203001_REG_CFG2_DEFAULT},
  83        {PA12203001_REG_CFG3, PA12203001_REG_CFG3_DEFAULT},
  84        {PA12203001_REG_PSET, PA12203001_PSCAN},
  85};
  86
  87static IIO_CONST_ATTR(in_illuminance_scale_available,
  88                      "0.007629 0.061036 0.106813 0.473029");
  89
  90static struct attribute *pa12203001_attrs[] = {
  91        &iio_const_attr_in_illuminance_scale_available.dev_attr.attr,
  92        NULL
  93};
  94
  95static const struct attribute_group pa12203001_attr_group = {
  96        .attrs = pa12203001_attrs,
  97};
  98
  99static const struct iio_chan_spec pa12203001_channels[] = {
 100        {
 101                .type = IIO_LIGHT,
 102                .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
 103                                      BIT(IIO_CHAN_INFO_SCALE),
 104        },
 105        {
 106                .type = IIO_PROXIMITY,
 107                .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
 108        }
 109};
 110
 111static const struct regmap_range pa12203001_volatile_regs_ranges[] = {
 112        regmap_reg_range(PA12203001_REG_ADL, PA12203001_REG_ADL + 1),
 113        regmap_reg_range(PA12203001_REG_PDH, PA12203001_REG_PDH),
 114};
 115
 116static const struct regmap_access_table pa12203001_volatile_regs = {
 117        .yes_ranges = pa12203001_volatile_regs_ranges,
 118        .n_yes_ranges = ARRAY_SIZE(pa12203001_volatile_regs_ranges),
 119};
 120
 121static const struct regmap_config pa12203001_regmap_config = {
 122        .reg_bits = 8,
 123        .val_bits = 8,
 124        .max_register = PA12203001_REG_PSET,
 125        .cache_type = REGCACHE_RBTREE,
 126        .volatile_table = &pa12203001_volatile_regs,
 127};
 128
 129static inline int pa12203001_als_enable(struct pa12203001_data *data, u8 enable)
 130{
 131        int ret;
 132
 133        ret = regmap_update_bits(data->map, PA12203001_REG_CFG0,
 134                                 PA12203001_ALS_EN_MASK, enable);
 135        if (ret < 0)
 136                return ret;
 137
 138        data->als_enabled = !!enable;
 139
 140        return 0;
 141}
 142
 143static inline int pa12203001_px_enable(struct pa12203001_data *data, u8 enable)
 144{
 145        int ret;
 146
 147        ret = regmap_update_bits(data->map, PA12203001_REG_CFG0,
 148                                 PA12203001_PX_EN_MASK, enable);
 149        if (ret < 0)
 150                return ret;
 151
 152        data->px_enabled = !!enable;
 153
 154        return 0;
 155}
 156
 157static int pa12203001_set_power_state(struct pa12203001_data *data, bool on,
 158                                      u8 mask)
 159{
 160#ifdef CONFIG_PM
 161        int ret;
 162
 163        if (on && (mask & PA12203001_ALS_EN_MASK)) {
 164                mutex_lock(&data->lock);
 165                if (data->px_enabled) {
 166                        ret = pa12203001_als_enable(data,
 167                                                    PA12203001_ALS_EN_MASK);
 168                        if (ret < 0)
 169                                goto err;
 170                } else {
 171                        data->als_needs_enable = true;
 172                }
 173                mutex_unlock(&data->lock);
 174        }
 175
 176        if (on && (mask & PA12203001_PX_EN_MASK)) {
 177                mutex_lock(&data->lock);
 178                if (data->als_enabled) {
 179                        ret = pa12203001_px_enable(data, PA12203001_PX_EN_MASK);
 180                        if (ret < 0)
 181                                goto err;
 182                } else {
 183                        data->px_needs_enable = true;
 184                }
 185                mutex_unlock(&data->lock);
 186        }
 187
 188        if (on) {
 189                ret = pm_runtime_get_sync(&data->client->dev);
 190                if (ret < 0)
 191                        pm_runtime_put_noidle(&data->client->dev);
 192
 193        } else {
 194                pm_runtime_mark_last_busy(&data->client->dev);
 195                ret = pm_runtime_put_autosuspend(&data->client->dev);
 196        }
 197
 198        return ret;
 199
 200err:
 201        mutex_unlock(&data->lock);
 202        return ret;
 203
 204#endif
 205        return 0;
 206}
 207
 208static int pa12203001_read_raw(struct iio_dev *indio_dev,
 209                               struct iio_chan_spec const *chan, int *val,
 210                               int *val2, long mask)
 211{
 212        struct pa12203001_data *data = iio_priv(indio_dev);
 213        int ret;
 214        u8 dev_mask;
 215        unsigned int reg_byte;
 216        __le16 reg_word;
 217
 218        switch (mask) {
 219        case IIO_CHAN_INFO_RAW:
 220                switch (chan->type) {
 221                case IIO_LIGHT:
 222                        dev_mask = PA12203001_ALS_EN_MASK;
 223                        ret = pa12203001_set_power_state(data, true, dev_mask);
 224                        if (ret < 0)
 225                                return ret;
 226                        /*
 227                         * ALS ADC value is stored in registers
 228                         * PA12203001_REG_ADL and in PA12203001_REG_ADL + 1.
 229                         */
 230                        ret = regmap_bulk_read(data->map, PA12203001_REG_ADL,
 231                                               &reg_word, 2);
 232                        if (ret < 0)
 233                                goto reg_err;
 234
 235                        *val = le16_to_cpu(reg_word);
 236                        ret = pa12203001_set_power_state(data, false, dev_mask);
 237                        if (ret < 0)
 238                                return ret;
 239                        break;
 240                case IIO_PROXIMITY:
 241                        dev_mask = PA12203001_PX_EN_MASK;
 242                        ret = pa12203001_set_power_state(data, true, dev_mask);
 243                        if (ret < 0)
 244                                return ret;
 245                        ret = regmap_read(data->map, PA12203001_REG_PDH,
 246                                          &reg_byte);
 247                        if (ret < 0)
 248                                goto reg_err;
 249
 250                        *val = reg_byte;
 251                        ret = pa12203001_set_power_state(data, false, dev_mask);
 252                        if (ret < 0)
 253                                return ret;
 254                        break;
 255                default:
 256                        return -EINVAL;
 257                }
 258                return IIO_VAL_INT;
 259        case IIO_CHAN_INFO_SCALE:
 260                ret = regmap_read(data->map, PA12203001_REG_CFG0, &reg_byte);
 261                if (ret < 0)
 262                        return ret;
 263                *val = 0;
 264                reg_byte = (reg_byte & PA12203001_AFSR_MASK);
 265                *val2 = pa12203001_scales[reg_byte >> 4];
 266                return IIO_VAL_INT_PLUS_MICRO;
 267        default:
 268                return -EINVAL;
 269        }
 270
 271reg_err:
 272        pa12203001_set_power_state(data, false, dev_mask);
 273        return ret;
 274}
 275
 276static int pa12203001_write_raw(struct iio_dev *indio_dev,
 277                                struct iio_chan_spec const *chan, int val,
 278                                int val2, long mask)
 279{
 280        struct pa12203001_data *data = iio_priv(indio_dev);
 281        int i, ret, new_val;
 282        unsigned int reg_byte;
 283
 284        switch (mask) {
 285        case IIO_CHAN_INFO_SCALE:
 286                ret = regmap_read(data->map, PA12203001_REG_CFG0, &reg_byte);
 287                if (val != 0 || ret < 0)
 288                        return -EINVAL;
 289                for (i = 0; i < ARRAY_SIZE(pa12203001_scales); i++) {
 290                        if (val2 == pa12203001_scales[i]) {
 291                                new_val = i << PA12203001_AFSR_SHIFT;
 292                                return regmap_update_bits(data->map,
 293                                                          PA12203001_REG_CFG0,
 294                                                          PA12203001_AFSR_MASK,
 295                                                          new_val);
 296                        }
 297                }
 298                break;
 299        default:
 300                break;
 301        }
 302
 303        return -EINVAL;
 304}
 305
 306static const struct iio_info pa12203001_info = {
 307        .read_raw = pa12203001_read_raw,
 308        .write_raw = pa12203001_write_raw,
 309        .attrs = &pa12203001_attr_group,
 310};
 311
 312static int pa12203001_init(struct iio_dev *indio_dev)
 313{
 314        struct pa12203001_data *data = iio_priv(indio_dev);
 315        int i, ret;
 316
 317        for (i = 0; i < ARRAY_SIZE(regvals); i++) {
 318                ret = regmap_write(data->map, regvals[i].reg, regvals[i].val);
 319                if (ret < 0)
 320                        return ret;
 321        }
 322
 323        return 0;
 324}
 325
 326static int pa12203001_power_chip(struct iio_dev *indio_dev, u8 state)
 327{
 328        struct pa12203001_data *data = iio_priv(indio_dev);
 329        int ret;
 330
 331        mutex_lock(&data->lock);
 332        ret = pa12203001_als_enable(data, state);
 333        if (ret < 0)
 334                goto out;
 335
 336        ret = pa12203001_px_enable(data, state);
 337
 338out:
 339        mutex_unlock(&data->lock);
 340        return ret;
 341}
 342
 343static int pa12203001_probe(struct i2c_client *client,
 344                            const struct i2c_device_id *id)
 345{
 346        struct pa12203001_data *data;
 347        struct iio_dev *indio_dev;
 348        int ret;
 349
 350        indio_dev = devm_iio_device_alloc(&client->dev,
 351                                          sizeof(struct pa12203001_data));
 352        if (!indio_dev)
 353                return -ENOMEM;
 354
 355        data = iio_priv(indio_dev);
 356        i2c_set_clientdata(client, indio_dev);
 357        data->client = client;
 358
 359        data->map = devm_regmap_init_i2c(client, &pa12203001_regmap_config);
 360        if (IS_ERR(data->map))
 361                return PTR_ERR(data->map);
 362
 363        mutex_init(&data->lock);
 364
 365        indio_dev->dev.parent = &client->dev;
 366        indio_dev->info = &pa12203001_info;
 367        indio_dev->name = PA12203001_DRIVER_NAME;
 368        indio_dev->channels = pa12203001_channels;
 369        indio_dev->num_channels = ARRAY_SIZE(pa12203001_channels);
 370        indio_dev->modes = INDIO_DIRECT_MODE;
 371
 372        ret = pa12203001_init(indio_dev);
 373        if (ret < 0)
 374                return ret;
 375
 376        ret = pa12203001_power_chip(indio_dev, PA12203001_CHIP_ENABLE);
 377        if (ret < 0)
 378                return ret;
 379
 380        ret = pm_runtime_set_active(&client->dev);
 381        if (ret < 0)
 382                goto out_err;
 383
 384        pm_runtime_enable(&client->dev);
 385        pm_runtime_set_autosuspend_delay(&client->dev,
 386                                         PA12203001_SLEEP_DELAY_MS);
 387        pm_runtime_use_autosuspend(&client->dev);
 388
 389        ret = iio_device_register(indio_dev);
 390        if (ret < 0)
 391                goto out_err;
 392
 393        return 0;
 394
 395out_err:
 396        pa12203001_power_chip(indio_dev, PA12203001_CHIP_DISABLE);
 397        return ret;
 398}
 399
 400static int pa12203001_remove(struct i2c_client *client)
 401{
 402        struct iio_dev *indio_dev = i2c_get_clientdata(client);
 403
 404        iio_device_unregister(indio_dev);
 405
 406        pm_runtime_disable(&client->dev);
 407        pm_runtime_set_suspended(&client->dev);
 408
 409        return pa12203001_power_chip(indio_dev, PA12203001_CHIP_DISABLE);
 410}
 411
 412#if defined(CONFIG_PM_SLEEP) || defined(CONFIG_PM)
 413static int pa12203001_suspend(struct device *dev)
 414{
 415        struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
 416
 417        return pa12203001_power_chip(indio_dev, PA12203001_CHIP_DISABLE);
 418}
 419#endif
 420
 421#ifdef CONFIG_PM_SLEEP
 422static int pa12203001_resume(struct device *dev)
 423{
 424        struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
 425
 426        return pa12203001_power_chip(indio_dev, PA12203001_CHIP_ENABLE);
 427}
 428#endif
 429
 430#ifdef CONFIG_PM
 431static int pa12203001_runtime_resume(struct device *dev)
 432{
 433        struct pa12203001_data *data;
 434
 435        data = iio_priv(i2c_get_clientdata(to_i2c_client(dev)));
 436
 437        mutex_lock(&data->lock);
 438        if (data->als_needs_enable) {
 439                pa12203001_als_enable(data, PA12203001_ALS_EN_MASK);
 440                data->als_needs_enable = false;
 441        }
 442        if (data->px_needs_enable) {
 443                pa12203001_px_enable(data, PA12203001_PX_EN_MASK);
 444                data->px_needs_enable = false;
 445        }
 446        mutex_unlock(&data->lock);
 447
 448        return 0;
 449}
 450#endif
 451
 452static const struct dev_pm_ops pa12203001_pm_ops = {
 453        SET_SYSTEM_SLEEP_PM_OPS(pa12203001_suspend, pa12203001_resume)
 454        SET_RUNTIME_PM_OPS(pa12203001_suspend, pa12203001_runtime_resume, NULL)
 455};
 456
 457static const struct acpi_device_id pa12203001_acpi_match[] = {
 458        { "TXCPA122", 0},
 459        {}
 460};
 461
 462MODULE_DEVICE_TABLE(acpi, pa12203001_acpi_match);
 463
 464static const struct i2c_device_id pa12203001_id[] = {
 465                {"txcpa122", 0},
 466                {}
 467};
 468
 469MODULE_DEVICE_TABLE(i2c, pa12203001_id);
 470
 471static struct i2c_driver pa12203001_driver = {
 472        .driver = {
 473                .name = PA12203001_DRIVER_NAME,
 474                .pm = &pa12203001_pm_ops,
 475                .acpi_match_table = ACPI_PTR(pa12203001_acpi_match),
 476        },
 477        .probe = pa12203001_probe,
 478        .remove = pa12203001_remove,
 479        .id_table = pa12203001_id,
 480
 481};
 482module_i2c_driver(pa12203001_driver);
 483
 484MODULE_AUTHOR("Adriana Reus <adriana.reus@intel.com>");
 485MODULE_DESCRIPTION("Driver for TXC PA12203001 Proximity and Light Sensor");
 486MODULE_LICENSE("GPL v2");
 487