root/drivers/iio/pressure/t5403.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. t5403_read
  2. t5403_comp_pressure
  3. t5403_comp_temp
  4. t5403_read_raw
  5. t5403_write_raw
  6. t5403_probe

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * t5403.c - Support for EPCOS T5403 pressure/temperature sensor
   4  *
   5  * Copyright (c) 2014 Peter Meerwald <pmeerw@pmeerw.net>
   6  *
   7  * (7-bit I2C slave address 0x77)
   8  *
   9  * TODO: end-of-conversion irq
  10  */
  11 
  12 #include <linux/module.h>
  13 #include <linux/i2c.h>
  14 #include <linux/iio/iio.h>
  15 #include <linux/iio/sysfs.h>
  16 #include <linux/delay.h>
  17 
  18 #define T5403_DATA 0xf5 /* data, LSB first, 16 bit */
  19 #define T5403_CALIB_DATA 0x8e /* 10 calibration coeff., LSB first, 16 bit */
  20 #define T5403_SLAVE_ADDR 0x88 /* I2C slave address, 0x77 */
  21 #define T5403_COMMAND 0xf1
  22 
  23 /* command bits */
  24 #define T5403_MODE_SHIFT 3 /* conversion time: 2, 8, 16, 66 ms */
  25 #define T5403_PT BIT(1) /* 0 .. pressure, 1 .. temperature measurement */
  26 #define T5403_SCO BIT(0) /* start conversion */
  27 
  28 #define T5403_MODE_LOW 0
  29 #define T5403_MODE_STANDARD 1
  30 #define T5403_MODE_HIGH 2
  31 #define T5403_MODE_ULTRA_HIGH 3
  32 
  33 #define T5403_I2C_MASK (~BIT(7))
  34 #define T5403_I2C_ADDR 0x77
  35 
  36 static const int t5403_pressure_conv_ms[] = {2, 8, 16, 66};
  37 
  38 struct t5403_data {
  39         struct i2c_client *client;
  40         struct mutex lock;
  41         int mode;
  42         __le16 c[10];
  43 };
  44 
  45 #define T5403_C_U16(i) le16_to_cpu(data->c[(i) - 1])
  46 #define T5403_C(i) sign_extend32(T5403_C_U16(i), 15)
  47 
  48 static int t5403_read(struct t5403_data *data, bool pressure)
  49 {
  50         int wait_time = 3;  /* wakeup time in ms */
  51 
  52         int ret = i2c_smbus_write_byte_data(data->client, T5403_COMMAND,
  53                 (pressure ? (data->mode << T5403_MODE_SHIFT) : T5403_PT) |
  54                 T5403_SCO);
  55         if (ret < 0)
  56                 return ret;
  57 
  58         wait_time += pressure ? t5403_pressure_conv_ms[data->mode] : 2;
  59 
  60         msleep(wait_time);
  61 
  62         return i2c_smbus_read_word_data(data->client, T5403_DATA);
  63 }
  64 
  65 static int t5403_comp_pressure(struct t5403_data *data, int *val, int *val2)
  66 {
  67         int ret;
  68         s16 t_r;
  69         u16 p_r;
  70         s32 S, O, X;
  71 
  72         mutex_lock(&data->lock);
  73 
  74         ret = t5403_read(data, false);
  75         if (ret < 0)
  76                 goto done;
  77         t_r = ret;
  78 
  79         ret = t5403_read(data, true);
  80         if (ret < 0)
  81                 goto done;
  82         p_r = ret;
  83 
  84         /* see EPCOS application note */
  85         S = T5403_C_U16(3) + (s32) T5403_C_U16(4) * t_r / 0x20000 +
  86                 T5403_C(5) * t_r / 0x8000 * t_r / 0x80000 +
  87                 T5403_C(9) * t_r / 0x8000 * t_r / 0x8000 * t_r / 0x10000;
  88 
  89         O = T5403_C(6) * 0x4000 + T5403_C(7) * t_r / 8 +
  90                 T5403_C(8) * t_r / 0x8000 * t_r / 16 +
  91                 T5403_C(9) * t_r / 0x8000 * t_r / 0x10000 * t_r;
  92 
  93         X = (S * p_r + O) / 0x4000;
  94 
  95         X += ((X - 75000) * (X - 75000) / 0x10000 - 9537) *
  96             T5403_C(10) / 0x10000;
  97 
  98         *val = X / 1000;
  99         *val2 = (X % 1000) * 1000;
 100 
 101 done:
 102         mutex_unlock(&data->lock);
 103         return ret;
 104 }
 105 
 106 static int t5403_comp_temp(struct t5403_data *data, int *val)
 107 {
 108         int ret;
 109         s16 t_r;
 110 
 111         mutex_lock(&data->lock);
 112         ret = t5403_read(data, false);
 113         if (ret < 0)
 114                 goto done;
 115         t_r = ret;
 116 
 117         /* see EPCOS application note */
 118         *val = ((s32) T5403_C_U16(1) * t_r / 0x100 +
 119                 (s32) T5403_C_U16(2) * 0x40) * 1000 / 0x10000;
 120 
 121 done:
 122         mutex_unlock(&data->lock);
 123         return ret;
 124 }
 125 
 126 static int t5403_read_raw(struct iio_dev *indio_dev,
 127                           struct iio_chan_spec const *chan,
 128                           int *val, int *val2, long mask)
 129 {
 130         struct t5403_data *data = iio_priv(indio_dev);
 131         int ret;
 132 
 133         switch (mask) {
 134         case IIO_CHAN_INFO_PROCESSED:
 135                 switch (chan->type) {
 136                 case IIO_PRESSURE:
 137                         ret = t5403_comp_pressure(data, val, val2);
 138                         if (ret < 0)
 139                                 return ret;
 140                         return IIO_VAL_INT_PLUS_MICRO;
 141                 case IIO_TEMP:
 142                         ret = t5403_comp_temp(data, val);
 143                         if (ret < 0)
 144                                 return ret;
 145                         return IIO_VAL_INT;
 146                 default:
 147                         return -EINVAL;
 148             }
 149         case IIO_CHAN_INFO_INT_TIME:
 150                 *val = 0;
 151                 *val2 = t5403_pressure_conv_ms[data->mode] * 1000;
 152                 return IIO_VAL_INT_PLUS_MICRO;
 153         default:
 154                 return -EINVAL;
 155         }
 156 }
 157 
 158 static int t5403_write_raw(struct iio_dev *indio_dev,
 159                            struct iio_chan_spec const *chan,
 160                            int val, int val2, long mask)
 161 {
 162         struct t5403_data *data = iio_priv(indio_dev);
 163         int i;
 164 
 165         switch (mask) {
 166         case IIO_CHAN_INFO_INT_TIME:
 167                 if (val != 0)
 168                         return -EINVAL;
 169                 for (i = 0; i < ARRAY_SIZE(t5403_pressure_conv_ms); i++)
 170                         if (val2 == t5403_pressure_conv_ms[i] * 1000) {
 171                                 mutex_lock(&data->lock);
 172                                 data->mode = i;
 173                                 mutex_unlock(&data->lock);
 174                                 return 0;
 175                         }
 176                 return -EINVAL;
 177         default:
 178                 return -EINVAL;
 179         }
 180 }
 181 
 182 static const struct iio_chan_spec t5403_channels[] = {
 183         {
 184                 .type = IIO_PRESSURE,
 185                 .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED) |
 186                     BIT(IIO_CHAN_INFO_INT_TIME),
 187         },
 188         {
 189                 .type = IIO_TEMP,
 190                 .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED),
 191         },
 192 };
 193 
 194 static IIO_CONST_ATTR_INT_TIME_AVAIL("0.002 0.008 0.016 0.066");
 195 
 196 static struct attribute *t5403_attributes[] = {
 197         &iio_const_attr_integration_time_available.dev_attr.attr,
 198         NULL
 199 };
 200 
 201 static const struct attribute_group t5403_attribute_group = {
 202         .attrs = t5403_attributes,
 203 };
 204 
 205 static const struct iio_info t5403_info = {
 206         .read_raw = &t5403_read_raw,
 207         .write_raw = &t5403_write_raw,
 208         .attrs = &t5403_attribute_group,
 209 };
 210 
 211 static int t5403_probe(struct i2c_client *client,
 212                          const struct i2c_device_id *id)
 213 {
 214         struct t5403_data *data;
 215         struct iio_dev *indio_dev;
 216         int ret;
 217 
 218         if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_WORD_DATA |
 219             I2C_FUNC_SMBUS_I2C_BLOCK))
 220                 return -EOPNOTSUPP;
 221 
 222         ret = i2c_smbus_read_byte_data(client, T5403_SLAVE_ADDR);
 223         if (ret < 0)
 224                 return ret;
 225         if ((ret & T5403_I2C_MASK) != T5403_I2C_ADDR)
 226                 return -ENODEV;
 227 
 228         indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
 229         if (!indio_dev)
 230                 return -ENOMEM;
 231 
 232         data = iio_priv(indio_dev);
 233         data->client = client;
 234         mutex_init(&data->lock);
 235 
 236         i2c_set_clientdata(client, indio_dev);
 237         indio_dev->info = &t5403_info;
 238         indio_dev->name = id->name;
 239         indio_dev->dev.parent = &client->dev;
 240         indio_dev->modes = INDIO_DIRECT_MODE;
 241         indio_dev->channels = t5403_channels;
 242         indio_dev->num_channels = ARRAY_SIZE(t5403_channels);
 243 
 244         data->mode = T5403_MODE_STANDARD;
 245 
 246         ret = i2c_smbus_read_i2c_block_data(data->client, T5403_CALIB_DATA,
 247             sizeof(data->c), (u8 *) data->c);
 248         if (ret < 0)
 249                 return ret;
 250 
 251         return devm_iio_device_register(&client->dev, indio_dev);
 252 }
 253 
 254 static const struct i2c_device_id t5403_id[] = {
 255         { "t5403", 0 },
 256         { }
 257 };
 258 MODULE_DEVICE_TABLE(i2c, t5403_id);
 259 
 260 static struct i2c_driver t5403_driver = {
 261         .driver = {
 262                 .name   = "t5403",
 263         },
 264         .probe = t5403_probe,
 265         .id_table = t5403_id,
 266 };
 267 module_i2c_driver(t5403_driver);
 268 
 269 MODULE_AUTHOR("Peter Meerwald <pmeerw@pmeerw.net>");
 270 MODULE_DESCRIPTION("EPCOS T5403 pressure/temperature sensor driver");
 271 MODULE_LICENSE("GPL");

/* [<][>][^][v][top][bottom][index][help] */