linux/drivers/iio/pressure/mpl3115.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * mpl3115.c - Support for Freescale MPL3115A2 pressure/temperature sensor
   4 *
   5 * Copyright (c) 2013 Peter Meerwald <pmeerw@pmeerw.net>
   6 *
   7 * (7-bit I2C slave address 0x60)
   8 *
   9 * TODO: FIFO buffer, altimeter mode, oversampling, continuous mode,
  10 * interrupts, user offset correction, raw mode
  11 */
  12
  13#include <linux/module.h>
  14#include <linux/i2c.h>
  15#include <linux/iio/iio.h>
  16#include <linux/iio/sysfs.h>
  17#include <linux/iio/trigger_consumer.h>
  18#include <linux/iio/buffer.h>
  19#include <linux/iio/triggered_buffer.h>
  20#include <linux/delay.h>
  21
  22#define MPL3115_STATUS 0x00
  23#define MPL3115_OUT_PRESS 0x01 /* MSB first, 20 bit */
  24#define MPL3115_OUT_TEMP 0x04 /* MSB first, 12 bit */
  25#define MPL3115_WHO_AM_I 0x0c
  26#define MPL3115_CTRL_REG1 0x26
  27
  28#define MPL3115_DEVICE_ID 0xc4
  29
  30#define MPL3115_STATUS_PRESS_RDY BIT(2)
  31#define MPL3115_STATUS_TEMP_RDY BIT(1)
  32
  33#define MPL3115_CTRL_RESET BIT(2) /* software reset */
  34#define MPL3115_CTRL_OST BIT(1) /* initiate measurement */
  35#define MPL3115_CTRL_ACTIVE BIT(0) /* continuous measurement */
  36#define MPL3115_CTRL_OS_258MS (BIT(5) | BIT(4)) /* 64x oversampling */
  37
  38struct mpl3115_data {
  39        struct i2c_client *client;
  40        struct mutex lock;
  41        u8 ctrl_reg1;
  42};
  43
  44static int mpl3115_request(struct mpl3115_data *data)
  45{
  46        int ret, tries = 15;
  47
  48        /* trigger measurement */
  49        ret = i2c_smbus_write_byte_data(data->client, MPL3115_CTRL_REG1,
  50                data->ctrl_reg1 | MPL3115_CTRL_OST);
  51        if (ret < 0)
  52                return ret;
  53
  54        while (tries-- > 0) {
  55                ret = i2c_smbus_read_byte_data(data->client, MPL3115_CTRL_REG1);
  56                if (ret < 0)
  57                        return ret;
  58                /* wait for data ready, i.e. OST cleared */
  59                if (!(ret & MPL3115_CTRL_OST))
  60                        break;
  61                msleep(20);
  62        }
  63
  64        if (tries < 0) {
  65                dev_err(&data->client->dev, "data not ready\n");
  66                return -EIO;
  67        }
  68
  69        return 0;
  70}
  71
  72static int mpl3115_read_raw(struct iio_dev *indio_dev,
  73                            struct iio_chan_spec const *chan,
  74                            int *val, int *val2, long mask)
  75{
  76        struct mpl3115_data *data = iio_priv(indio_dev);
  77        __be32 tmp = 0;
  78        int ret;
  79
  80        switch (mask) {
  81        case IIO_CHAN_INFO_RAW:
  82                ret = iio_device_claim_direct_mode(indio_dev);
  83                if (ret)
  84                        return ret;
  85
  86                switch (chan->type) {
  87                case IIO_PRESSURE: /* in 0.25 pascal / LSB */
  88                        mutex_lock(&data->lock);
  89                        ret = mpl3115_request(data);
  90                        if (ret < 0) {
  91                                mutex_unlock(&data->lock);
  92                                break;
  93                        }
  94                        ret = i2c_smbus_read_i2c_block_data(data->client,
  95                                MPL3115_OUT_PRESS, 3, (u8 *) &tmp);
  96                        mutex_unlock(&data->lock);
  97                        if (ret < 0)
  98                                break;
  99                        *val = be32_to_cpu(tmp) >> 12;
 100                        ret = IIO_VAL_INT;
 101                        break;
 102                case IIO_TEMP: /* in 0.0625 celsius / LSB */
 103                        mutex_lock(&data->lock);
 104                        ret = mpl3115_request(data);
 105                        if (ret < 0) {
 106                                mutex_unlock(&data->lock);
 107                                break;
 108                        }
 109                        ret = i2c_smbus_read_i2c_block_data(data->client,
 110                                MPL3115_OUT_TEMP, 2, (u8 *) &tmp);
 111                        mutex_unlock(&data->lock);
 112                        if (ret < 0)
 113                                break;
 114                        *val = sign_extend32(be32_to_cpu(tmp) >> 20, 11);
 115                        ret = IIO_VAL_INT;
 116                        break;
 117                default:
 118                        ret = -EINVAL;
 119                        break;
 120                }
 121
 122                iio_device_release_direct_mode(indio_dev);
 123                return ret;
 124
 125        case IIO_CHAN_INFO_SCALE:
 126                switch (chan->type) {
 127                case IIO_PRESSURE:
 128                        *val = 0;
 129                        *val2 = 250; /* want kilopascal */
 130                        return IIO_VAL_INT_PLUS_MICRO;
 131                case IIO_TEMP:
 132                        *val = 0;
 133                        *val2 = 62500;
 134                        return IIO_VAL_INT_PLUS_MICRO;
 135                default:
 136                        return -EINVAL;
 137                }
 138        }
 139        return -EINVAL;
 140}
 141
 142static irqreturn_t mpl3115_trigger_handler(int irq, void *p)
 143{
 144        struct iio_poll_func *pf = p;
 145        struct iio_dev *indio_dev = pf->indio_dev;
 146        struct mpl3115_data *data = iio_priv(indio_dev);
 147        /*
 148         * 32-bit channel + 16-bit channel + padding + ts
 149         * Note that it is possible for only one of the first 2
 150         * channels to be enabled. If that happens, the first element
 151         * of the buffer may be either 16 or 32-bits.  As such we cannot
 152         * use a simple structure definition to express this data layout.
 153         */
 154        u8 buffer[16] __aligned(8);
 155        int ret, pos = 0;
 156
 157        mutex_lock(&data->lock);
 158        ret = mpl3115_request(data);
 159        if (ret < 0) {
 160                mutex_unlock(&data->lock);
 161                goto done;
 162        }
 163
 164        memset(buffer, 0, sizeof(buffer));
 165        if (test_bit(0, indio_dev->active_scan_mask)) {
 166                ret = i2c_smbus_read_i2c_block_data(data->client,
 167                        MPL3115_OUT_PRESS, 3, &buffer[pos]);
 168                if (ret < 0) {
 169                        mutex_unlock(&data->lock);
 170                        goto done;
 171                }
 172                pos += 4;
 173        }
 174
 175        if (test_bit(1, indio_dev->active_scan_mask)) {
 176                ret = i2c_smbus_read_i2c_block_data(data->client,
 177                        MPL3115_OUT_TEMP, 2, &buffer[pos]);
 178                if (ret < 0) {
 179                        mutex_unlock(&data->lock);
 180                        goto done;
 181                }
 182        }
 183        mutex_unlock(&data->lock);
 184
 185        iio_push_to_buffers_with_timestamp(indio_dev, buffer,
 186                iio_get_time_ns(indio_dev));
 187
 188done:
 189        iio_trigger_notify_done(indio_dev->trig);
 190        return IRQ_HANDLED;
 191}
 192
 193static const struct iio_chan_spec mpl3115_channels[] = {
 194        {
 195                .type = IIO_PRESSURE,
 196                .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
 197                .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),
 198                .scan_index = 0,
 199                .scan_type = {
 200                        .sign = 'u',
 201                        .realbits = 20,
 202                        .storagebits = 32,
 203                        .shift = 12,
 204                        .endianness = IIO_BE,
 205                }
 206        },
 207        {
 208                .type = IIO_TEMP,
 209                .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
 210                .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),
 211                .scan_index = 1,
 212                .scan_type = {
 213                        .sign = 's',
 214                        .realbits = 12,
 215                        .storagebits = 16,
 216                        .shift = 4,
 217                        .endianness = IIO_BE,
 218                }
 219        },
 220        IIO_CHAN_SOFT_TIMESTAMP(2),
 221};
 222
 223static const struct iio_info mpl3115_info = {
 224        .read_raw = &mpl3115_read_raw,
 225};
 226
 227static int mpl3115_probe(struct i2c_client *client,
 228                         const struct i2c_device_id *id)
 229{
 230        struct mpl3115_data *data;
 231        struct iio_dev *indio_dev;
 232        int ret;
 233
 234        ret = i2c_smbus_read_byte_data(client, MPL3115_WHO_AM_I);
 235        if (ret < 0)
 236                return ret;
 237        if (ret != MPL3115_DEVICE_ID)
 238                return -ENODEV;
 239
 240        indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
 241        if (!indio_dev)
 242                return -ENOMEM;
 243
 244        data = iio_priv(indio_dev);
 245        data->client = client;
 246        mutex_init(&data->lock);
 247
 248        i2c_set_clientdata(client, indio_dev);
 249        indio_dev->info = &mpl3115_info;
 250        indio_dev->name = id->name;
 251        indio_dev->modes = INDIO_DIRECT_MODE;
 252        indio_dev->channels = mpl3115_channels;
 253        indio_dev->num_channels = ARRAY_SIZE(mpl3115_channels);
 254
 255        /* software reset, I2C transfer is aborted (fails) */
 256        i2c_smbus_write_byte_data(client, MPL3115_CTRL_REG1,
 257                MPL3115_CTRL_RESET);
 258        msleep(50);
 259
 260        data->ctrl_reg1 = MPL3115_CTRL_OS_258MS;
 261        ret = i2c_smbus_write_byte_data(client, MPL3115_CTRL_REG1,
 262                data->ctrl_reg1);
 263        if (ret < 0)
 264                return ret;
 265
 266        ret = iio_triggered_buffer_setup(indio_dev, NULL,
 267                mpl3115_trigger_handler, NULL);
 268        if (ret < 0)
 269                return ret;
 270
 271        ret = iio_device_register(indio_dev);
 272        if (ret < 0)
 273                goto buffer_cleanup;
 274        return 0;
 275
 276buffer_cleanup:
 277        iio_triggered_buffer_cleanup(indio_dev);
 278        return ret;
 279}
 280
 281static int mpl3115_standby(struct mpl3115_data *data)
 282{
 283        return i2c_smbus_write_byte_data(data->client, MPL3115_CTRL_REG1,
 284                data->ctrl_reg1 & ~MPL3115_CTRL_ACTIVE);
 285}
 286
 287static int mpl3115_remove(struct i2c_client *client)
 288{
 289        struct iio_dev *indio_dev = i2c_get_clientdata(client);
 290
 291        iio_device_unregister(indio_dev);
 292        iio_triggered_buffer_cleanup(indio_dev);
 293        mpl3115_standby(iio_priv(indio_dev));
 294
 295        return 0;
 296}
 297
 298#ifdef CONFIG_PM_SLEEP
 299static int mpl3115_suspend(struct device *dev)
 300{
 301        return mpl3115_standby(iio_priv(i2c_get_clientdata(
 302                to_i2c_client(dev))));
 303}
 304
 305static int mpl3115_resume(struct device *dev)
 306{
 307        struct mpl3115_data *data = iio_priv(i2c_get_clientdata(
 308                to_i2c_client(dev)));
 309
 310        return i2c_smbus_write_byte_data(data->client, MPL3115_CTRL_REG1,
 311                data->ctrl_reg1);
 312}
 313
 314static SIMPLE_DEV_PM_OPS(mpl3115_pm_ops, mpl3115_suspend, mpl3115_resume);
 315#define MPL3115_PM_OPS (&mpl3115_pm_ops)
 316#else
 317#define MPL3115_PM_OPS NULL
 318#endif
 319
 320static const struct i2c_device_id mpl3115_id[] = {
 321        { "mpl3115", 0 },
 322        { }
 323};
 324MODULE_DEVICE_TABLE(i2c, mpl3115_id);
 325
 326static const struct of_device_id mpl3115_of_match[] = {
 327        { .compatible = "fsl,mpl3115" },
 328        { }
 329};
 330MODULE_DEVICE_TABLE(of, mpl3115_of_match);
 331
 332static struct i2c_driver mpl3115_driver = {
 333        .driver = {
 334                .name   = "mpl3115",
 335                .of_match_table = mpl3115_of_match,
 336                .pm     = MPL3115_PM_OPS,
 337        },
 338        .probe = mpl3115_probe,
 339        .remove = mpl3115_remove,
 340        .id_table = mpl3115_id,
 341};
 342module_i2c_driver(mpl3115_driver);
 343
 344MODULE_AUTHOR("Peter Meerwald <pmeerw@pmeerw.net>");
 345MODULE_DESCRIPTION("Freescale MPL3115 pressure/temperature driver");
 346MODULE_LICENSE("GPL");
 347