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        u8 buffer[16]; /* 32-bit channel + 16-bit channel + padding + ts */
 148        int ret, pos = 0;
 149
 150        mutex_lock(&data->lock);
 151        ret = mpl3115_request(data);
 152        if (ret < 0) {
 153                mutex_unlock(&data->lock);
 154                goto done;
 155        }
 156
 157        memset(buffer, 0, sizeof(buffer));
 158        if (test_bit(0, indio_dev->active_scan_mask)) {
 159                ret = i2c_smbus_read_i2c_block_data(data->client,
 160                        MPL3115_OUT_PRESS, 3, &buffer[pos]);
 161                if (ret < 0) {
 162                        mutex_unlock(&data->lock);
 163                        goto done;
 164                }
 165                pos += 4;
 166        }
 167
 168        if (test_bit(1, indio_dev->active_scan_mask)) {
 169                ret = i2c_smbus_read_i2c_block_data(data->client,
 170                        MPL3115_OUT_TEMP, 2, &buffer[pos]);
 171                if (ret < 0) {
 172                        mutex_unlock(&data->lock);
 173                        goto done;
 174                }
 175        }
 176        mutex_unlock(&data->lock);
 177
 178        iio_push_to_buffers_with_timestamp(indio_dev, buffer,
 179                iio_get_time_ns(indio_dev));
 180
 181done:
 182        iio_trigger_notify_done(indio_dev->trig);
 183        return IRQ_HANDLED;
 184}
 185
 186static const struct iio_chan_spec mpl3115_channels[] = {
 187        {
 188                .type = IIO_PRESSURE,
 189                .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
 190                .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),
 191                .scan_index = 0,
 192                .scan_type = {
 193                        .sign = 'u',
 194                        .realbits = 20,
 195                        .storagebits = 32,
 196                        .shift = 12,
 197                        .endianness = IIO_BE,
 198                }
 199        },
 200        {
 201                .type = IIO_TEMP,
 202                .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
 203                .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),
 204                .scan_index = 1,
 205                .scan_type = {
 206                        .sign = 's',
 207                        .realbits = 12,
 208                        .storagebits = 16,
 209                        .shift = 4,
 210                        .endianness = IIO_BE,
 211                }
 212        },
 213        IIO_CHAN_SOFT_TIMESTAMP(2),
 214};
 215
 216static const struct iio_info mpl3115_info = {
 217        .read_raw = &mpl3115_read_raw,
 218};
 219
 220static int mpl3115_probe(struct i2c_client *client,
 221                         const struct i2c_device_id *id)
 222{
 223        struct mpl3115_data *data;
 224        struct iio_dev *indio_dev;
 225        int ret;
 226
 227        ret = i2c_smbus_read_byte_data(client, MPL3115_WHO_AM_I);
 228        if (ret < 0)
 229                return ret;
 230        if (ret != MPL3115_DEVICE_ID)
 231                return -ENODEV;
 232
 233        indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
 234        if (!indio_dev)
 235                return -ENOMEM;
 236
 237        data = iio_priv(indio_dev);
 238        data->client = client;
 239        mutex_init(&data->lock);
 240
 241        i2c_set_clientdata(client, indio_dev);
 242        indio_dev->info = &mpl3115_info;
 243        indio_dev->name = id->name;
 244        indio_dev->dev.parent = &client->dev;
 245        indio_dev->modes = INDIO_DIRECT_MODE;
 246        indio_dev->channels = mpl3115_channels;
 247        indio_dev->num_channels = ARRAY_SIZE(mpl3115_channels);
 248
 249        /* software reset, I2C transfer is aborted (fails) */
 250        i2c_smbus_write_byte_data(client, MPL3115_CTRL_REG1,
 251                MPL3115_CTRL_RESET);
 252        msleep(50);
 253
 254        data->ctrl_reg1 = MPL3115_CTRL_OS_258MS;
 255        ret = i2c_smbus_write_byte_data(client, MPL3115_CTRL_REG1,
 256                data->ctrl_reg1);
 257        if (ret < 0)
 258                return ret;
 259
 260        ret = iio_triggered_buffer_setup(indio_dev, NULL,
 261                mpl3115_trigger_handler, NULL);
 262        if (ret < 0)
 263                return ret;
 264
 265        ret = iio_device_register(indio_dev);
 266        if (ret < 0)
 267                goto buffer_cleanup;
 268        return 0;
 269
 270buffer_cleanup:
 271        iio_triggered_buffer_cleanup(indio_dev);
 272        return ret;
 273}
 274
 275static int mpl3115_standby(struct mpl3115_data *data)
 276{
 277        return i2c_smbus_write_byte_data(data->client, MPL3115_CTRL_REG1,
 278                data->ctrl_reg1 & ~MPL3115_CTRL_ACTIVE);
 279}
 280
 281static int mpl3115_remove(struct i2c_client *client)
 282{
 283        struct iio_dev *indio_dev = i2c_get_clientdata(client);
 284
 285        iio_device_unregister(indio_dev);
 286        iio_triggered_buffer_cleanup(indio_dev);
 287        mpl3115_standby(iio_priv(indio_dev));
 288
 289        return 0;
 290}
 291
 292#ifdef CONFIG_PM_SLEEP
 293static int mpl3115_suspend(struct device *dev)
 294{
 295        return mpl3115_standby(iio_priv(i2c_get_clientdata(
 296                to_i2c_client(dev))));
 297}
 298
 299static int mpl3115_resume(struct device *dev)
 300{
 301        struct mpl3115_data *data = iio_priv(i2c_get_clientdata(
 302                to_i2c_client(dev)));
 303
 304        return i2c_smbus_write_byte_data(data->client, MPL3115_CTRL_REG1,
 305                data->ctrl_reg1);
 306}
 307
 308static SIMPLE_DEV_PM_OPS(mpl3115_pm_ops, mpl3115_suspend, mpl3115_resume);
 309#define MPL3115_PM_OPS (&mpl3115_pm_ops)
 310#else
 311#define MPL3115_PM_OPS NULL
 312#endif
 313
 314static const struct i2c_device_id mpl3115_id[] = {
 315        { "mpl3115", 0 },
 316        { }
 317};
 318MODULE_DEVICE_TABLE(i2c, mpl3115_id);
 319
 320static const struct of_device_id mpl3115_of_match[] = {
 321        { .compatible = "fsl,mpl3115" },
 322        { }
 323};
 324MODULE_DEVICE_TABLE(of, mpl3115_of_match);
 325
 326static struct i2c_driver mpl3115_driver = {
 327        .driver = {
 328                .name   = "mpl3115",
 329                .of_match_table = mpl3115_of_match,
 330                .pm     = MPL3115_PM_OPS,
 331        },
 332        .probe = mpl3115_probe,
 333        .remove = mpl3115_remove,
 334        .id_table = mpl3115_id,
 335};
 336module_i2c_driver(mpl3115_driver);
 337
 338MODULE_AUTHOR("Peter Meerwald <pmeerw@pmeerw.net>");
 339MODULE_DESCRIPTION("Freescale MPL3115 pressure/temperature driver");
 340MODULE_LICENSE("GPL");
 341