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