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