linux/drivers/iio/pressure/ms5637.c
<<
>>
Prefs
   1/*
   2 * ms5637.c - Support for Measurement-Specialties MS5637, MS5805
   3 *            MS5837 and MS8607 pressure & temperature sensor
   4 *
   5 * Copyright (c) 2015 Measurement-Specialties
   6 *
   7 * Licensed under the GPL-2.
   8 *
   9 * (7-bit I2C slave address 0x76)
  10 *
  11 * Datasheet:
  12 *  http://www.meas-spec.com/downloads/MS5637-02BA03.pdf
  13 * Datasheet:
  14 *  http://www.meas-spec.com/downloads/MS5805-02BA01.pdf
  15 * Datasheet:
  16 *  http://www.meas-spec.com/downloads/MS5837-30BA.pdf
  17 * Datasheet:
  18 *  http://www.meas-spec.com/downloads/MS8607-02BA01.pdf
  19 */
  20
  21#include <linux/init.h>
  22#include <linux/device.h>
  23#include <linux/kernel.h>
  24#include <linux/stat.h>
  25#include <linux/module.h>
  26#include <linux/i2c.h>
  27#include <linux/iio/iio.h>
  28#include <linux/iio/sysfs.h>
  29#include <linux/mutex.h>
  30
  31#include "../common/ms_sensors/ms_sensors_i2c.h"
  32
  33static const int ms5637_samp_freq[6] = { 960, 480, 240, 120, 60, 30 };
  34/* String copy of the above const for readability purpose */
  35static const char ms5637_show_samp_freq[] = "960 480 240 120 60 30";
  36
  37static int ms5637_read_raw(struct iio_dev *indio_dev,
  38                           struct iio_chan_spec const *channel, int *val,
  39                           int *val2, long mask)
  40{
  41        int ret;
  42        int temperature;
  43        unsigned int pressure;
  44        struct ms_tp_dev *dev_data = iio_priv(indio_dev);
  45
  46        switch (mask) {
  47        case IIO_CHAN_INFO_PROCESSED:
  48                ret = ms_sensors_read_temp_and_pressure(dev_data,
  49                                                        &temperature,
  50                                                        &pressure);
  51                if (ret)
  52                        return ret;
  53
  54                switch (channel->type) {
  55                case IIO_TEMP:  /* in milli °C */
  56                        *val = temperature;
  57
  58                        return IIO_VAL_INT;
  59                case IIO_PRESSURE:      /* in kPa */
  60                        *val = pressure / 1000;
  61                        *val2 = (pressure % 1000) * 1000;
  62
  63                        return IIO_VAL_INT_PLUS_MICRO;
  64                default:
  65                        return -EINVAL;
  66                }
  67        case IIO_CHAN_INFO_SAMP_FREQ:
  68                *val = ms5637_samp_freq[dev_data->res_index];
  69
  70                return IIO_VAL_INT;
  71        default:
  72                return -EINVAL;
  73        }
  74}
  75
  76static int ms5637_write_raw(struct iio_dev *indio_dev,
  77                            struct iio_chan_spec const *chan,
  78                            int val, int val2, long mask)
  79{
  80        struct ms_tp_dev *dev_data = iio_priv(indio_dev);
  81        int i;
  82
  83        switch (mask) {
  84        case IIO_CHAN_INFO_SAMP_FREQ:
  85                i = ARRAY_SIZE(ms5637_samp_freq);
  86                while (i-- > 0)
  87                        if (val == ms5637_samp_freq[i])
  88                                break;
  89                if (i < 0)
  90                        return -EINVAL;
  91                dev_data->res_index = i;
  92
  93                return 0;
  94        default:
  95                return -EINVAL;
  96        }
  97}
  98
  99static const struct iio_chan_spec ms5637_channels[] = {
 100        {
 101                .type = IIO_TEMP,
 102                .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED),
 103                .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ),
 104        },
 105        {
 106                .type = IIO_PRESSURE,
 107                .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED),
 108                .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ),
 109        }
 110};
 111
 112static IIO_CONST_ATTR_SAMP_FREQ_AVAIL(ms5637_show_samp_freq);
 113
 114static struct attribute *ms5637_attributes[] = {
 115        &iio_const_attr_sampling_frequency_available.dev_attr.attr,
 116        NULL,
 117};
 118
 119static const struct attribute_group ms5637_attribute_group = {
 120        .attrs = ms5637_attributes,
 121};
 122
 123static const struct iio_info ms5637_info = {
 124        .read_raw = ms5637_read_raw,
 125        .write_raw = ms5637_write_raw,
 126        .attrs = &ms5637_attribute_group,
 127        .driver_module = THIS_MODULE,
 128};
 129
 130static int ms5637_probe(struct i2c_client *client,
 131                        const struct i2c_device_id *id)
 132{
 133        struct ms_tp_dev *dev_data;
 134        struct iio_dev *indio_dev;
 135        int ret;
 136
 137        if (!i2c_check_functionality(client->adapter,
 138                                     I2C_FUNC_SMBUS_READ_WORD_DATA |
 139                                     I2C_FUNC_SMBUS_WRITE_BYTE |
 140                                     I2C_FUNC_SMBUS_READ_I2C_BLOCK)) {
 141                dev_err(&client->dev,
 142                        "Adapter does not support some i2c transaction\n");
 143                return -EOPNOTSUPP;
 144        }
 145
 146        indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*dev_data));
 147        if (!indio_dev)
 148                return -ENOMEM;
 149
 150        dev_data = iio_priv(indio_dev);
 151        dev_data->client = client;
 152        dev_data->res_index = 5;
 153        mutex_init(&dev_data->lock);
 154
 155        indio_dev->info = &ms5637_info;
 156        indio_dev->name = id->name;
 157        indio_dev->dev.parent = &client->dev;
 158        indio_dev->modes = INDIO_DIRECT_MODE;
 159        indio_dev->channels = ms5637_channels;
 160        indio_dev->num_channels = ARRAY_SIZE(ms5637_channels);
 161
 162        i2c_set_clientdata(client, indio_dev);
 163
 164        ret = ms_sensors_reset(client, 0x1E, 3000);
 165        if (ret)
 166                return ret;
 167
 168        ret = ms_sensors_tp_read_prom(dev_data);
 169        if (ret)
 170                return ret;
 171
 172        return devm_iio_device_register(&client->dev, indio_dev);
 173}
 174
 175static const struct i2c_device_id ms5637_id[] = {
 176        {"ms5637", 0},
 177        {"ms5805", 0},
 178        {"ms5837", 0},
 179        {"ms8607-temppressure", 0},
 180        {}
 181};
 182MODULE_DEVICE_TABLE(i2c, ms5637_id);
 183
 184static struct i2c_driver ms5637_driver = {
 185        .probe = ms5637_probe,
 186        .id_table = ms5637_id,
 187        .driver = {
 188                   .name = "ms5637"
 189                   },
 190};
 191
 192module_i2c_driver(ms5637_driver);
 193
 194MODULE_DESCRIPTION("Measurement-Specialties ms5637 temperature & pressure driver");
 195MODULE_AUTHOR("William Markezana <william.markezana@meas-spec.com>");
 196MODULE_AUTHOR("Ludovic Tancerel <ludovic.tancerel@maplehightech.com>");
 197MODULE_LICENSE("GPL v2");
 198