]>
Commit | Line | Data |
---|---|---|
c0644160 TD |
1 | /* |
2 | * MS5611 pressure and temperature sensor driver (I2C bus) | |
3 | * | |
4 | * Copyright (c) Tomasz Duszynski <tduszyns@gmail.com> | |
5 | * | |
6 | * This program is free software; you can redistribute it and/or modify | |
7 | * it under the terms of the GNU General Public License version 2 as | |
8 | * published by the Free Software Foundation. | |
9 | * | |
10 | * 7-bit I2C slave addresses: | |
11 | * | |
12 | * 0x77 (CSB pin low) | |
13 | * 0x76 (CSB pin high) | |
14 | * | |
15 | */ | |
16 | ||
17 | #include <linux/delay.h> | |
18 | #include <linux/i2c.h> | |
19 | #include <linux/module.h> | |
20 | ||
21 | #include "ms5611.h" | |
22 | ||
23 | static int ms5611_i2c_reset(struct device *dev) | |
24 | { | |
25 | struct ms5611_state *st = iio_priv(dev_to_iio_dev(dev)); | |
26 | ||
27 | return i2c_smbus_write_byte(st->client, MS5611_RESET); | |
28 | } | |
29 | ||
30 | static int ms5611_i2c_read_prom_word(struct device *dev, int index, u16 *word) | |
31 | { | |
32 | int ret; | |
33 | struct ms5611_state *st = iio_priv(dev_to_iio_dev(dev)); | |
34 | ||
35 | ret = i2c_smbus_read_word_swapped(st->client, | |
36 | MS5611_READ_PROM_WORD + (index << 1)); | |
37 | if (ret < 0) | |
38 | return ret; | |
39 | ||
40 | *word = ret; | |
41 | ||
42 | return 0; | |
43 | } | |
44 | ||
45 | static int ms5611_i2c_read_adc(struct ms5611_state *st, s32 *val) | |
46 | { | |
47 | int ret; | |
48 | u8 buf[3]; | |
49 | ||
50 | ret = i2c_smbus_read_i2c_block_data(st->client, MS5611_READ_ADC, | |
51 | 3, buf); | |
52 | if (ret < 0) | |
53 | return ret; | |
54 | ||
55 | *val = (buf[0] << 16) | (buf[1] << 8) | buf[2]; | |
56 | ||
57 | return 0; | |
58 | } | |
59 | ||
60 | static int ms5611_i2c_read_adc_temp_and_pressure(struct device *dev, | |
61 | s32 *temp, s32 *pressure) | |
62 | { | |
63 | int ret; | |
64 | struct ms5611_state *st = iio_priv(dev_to_iio_dev(dev)); | |
65 | ||
66 | ret = i2c_smbus_write_byte(st->client, MS5611_START_TEMP_CONV); | |
67 | if (ret < 0) | |
68 | return ret; | |
69 | ||
70 | usleep_range(MS5611_CONV_TIME_MIN, MS5611_CONV_TIME_MAX); | |
71 | ||
72 | ret = ms5611_i2c_read_adc(st, temp); | |
73 | if (ret < 0) | |
74 | return ret; | |
75 | ||
76 | ret = i2c_smbus_write_byte(st->client, MS5611_START_PRESSURE_CONV); | |
77 | if (ret < 0) | |
78 | return ret; | |
79 | ||
80 | usleep_range(MS5611_CONV_TIME_MIN, MS5611_CONV_TIME_MAX); | |
81 | ||
82 | return ms5611_i2c_read_adc(st, pressure); | |
83 | } | |
84 | ||
85 | static int ms5611_i2c_probe(struct i2c_client *client, | |
86 | const struct i2c_device_id *id) | |
87 | { | |
88 | struct ms5611_state *st; | |
89 | struct iio_dev *indio_dev; | |
90 | ||
91 | if (!i2c_check_functionality(client->adapter, | |
92 | I2C_FUNC_SMBUS_WRITE_BYTE | | |
93 | I2C_FUNC_SMBUS_READ_WORD_DATA | | |
94 | I2C_FUNC_SMBUS_READ_I2C_BLOCK)) | |
95 | return -ENODEV; | |
96 | ||
97 | indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*st)); | |
98 | if (!indio_dev) | |
99 | return -ENOMEM; | |
100 | ||
101 | st = iio_priv(indio_dev); | |
102 | st->reset = ms5611_i2c_reset; | |
103 | st->read_prom_word = ms5611_i2c_read_prom_word; | |
104 | st->read_adc_temp_and_pressure = ms5611_i2c_read_adc_temp_and_pressure; | |
105 | st->client = client; | |
106 | ||
107 | return ms5611_probe(indio_dev, &client->dev); | |
108 | } | |
109 | ||
110 | static const struct i2c_device_id ms5611_id[] = { | |
111 | { "ms5611", 0 }, | |
112 | { } | |
113 | }; | |
114 | MODULE_DEVICE_TABLE(i2c, ms5611_id); | |
115 | ||
116 | static struct i2c_driver ms5611_driver = { | |
117 | .driver = { | |
118 | .name = "ms5611", | |
119 | .owner = THIS_MODULE, | |
120 | }, | |
121 | .id_table = ms5611_id, | |
122 | .probe = ms5611_i2c_probe, | |
123 | }; | |
124 | module_i2c_driver(ms5611_driver); | |
125 | ||
126 | MODULE_AUTHOR("Tomasz Duszynski <tduszyns@gmail.com>"); | |
127 | MODULE_DESCRIPTION("MS5611 i2c driver"); | |
128 | MODULE_LICENSE("GPL v2"); |