]>
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> | |
7a948c5e | 20 | #include <linux/of_device.h> |
c0644160 TD |
21 | |
22 | #include "ms5611.h" | |
23 | ||
24 | static int ms5611_i2c_reset(struct device *dev) | |
25 | { | |
26 | struct ms5611_state *st = iio_priv(dev_to_iio_dev(dev)); | |
27 | ||
28 | return i2c_smbus_write_byte(st->client, MS5611_RESET); | |
29 | } | |
30 | ||
31 | static int ms5611_i2c_read_prom_word(struct device *dev, int index, u16 *word) | |
32 | { | |
33 | int ret; | |
34 | struct ms5611_state *st = iio_priv(dev_to_iio_dev(dev)); | |
35 | ||
36 | ret = i2c_smbus_read_word_swapped(st->client, | |
37 | MS5611_READ_PROM_WORD + (index << 1)); | |
38 | if (ret < 0) | |
39 | return ret; | |
40 | ||
41 | *word = ret; | |
42 | ||
43 | return 0; | |
44 | } | |
45 | ||
46 | static int ms5611_i2c_read_adc(struct ms5611_state *st, s32 *val) | |
47 | { | |
48 | int ret; | |
49 | u8 buf[3]; | |
50 | ||
51 | ret = i2c_smbus_read_i2c_block_data(st->client, MS5611_READ_ADC, | |
52 | 3, buf); | |
53 | if (ret < 0) | |
54 | return ret; | |
55 | ||
56 | *val = (buf[0] << 16) | (buf[1] << 8) | buf[2]; | |
57 | ||
58 | return 0; | |
59 | } | |
60 | ||
61 | static int ms5611_i2c_read_adc_temp_and_pressure(struct device *dev, | |
62 | s32 *temp, s32 *pressure) | |
63 | { | |
64 | int ret; | |
65 | struct ms5611_state *st = iio_priv(dev_to_iio_dev(dev)); | |
033691a9 | 66 | const struct ms5611_osr *osr = st->temp_osr; |
c0644160 | 67 | |
033691a9 | 68 | ret = i2c_smbus_write_byte(st->client, osr->cmd); |
c0644160 TD |
69 | if (ret < 0) |
70 | return ret; | |
71 | ||
033691a9 | 72 | usleep_range(osr->conv_usec, osr->conv_usec + (osr->conv_usec / 10UL)); |
c0644160 TD |
73 | ret = ms5611_i2c_read_adc(st, temp); |
74 | if (ret < 0) | |
75 | return ret; | |
76 | ||
033691a9 GB |
77 | osr = st->pressure_osr; |
78 | ret = i2c_smbus_write_byte(st->client, osr->cmd); | |
c0644160 TD |
79 | if (ret < 0) |
80 | return ret; | |
81 | ||
033691a9 | 82 | usleep_range(osr->conv_usec, osr->conv_usec + (osr->conv_usec / 10UL)); |
c0644160 TD |
83 | return ms5611_i2c_read_adc(st, pressure); |
84 | } | |
85 | ||
86 | static int ms5611_i2c_probe(struct i2c_client *client, | |
87 | const struct i2c_device_id *id) | |
88 | { | |
89 | struct ms5611_state *st; | |
90 | struct iio_dev *indio_dev; | |
91 | ||
92 | if (!i2c_check_functionality(client->adapter, | |
93 | I2C_FUNC_SMBUS_WRITE_BYTE | | |
94 | I2C_FUNC_SMBUS_READ_WORD_DATA | | |
95 | I2C_FUNC_SMBUS_READ_I2C_BLOCK)) | |
f8d9d3b4 | 96 | return -EOPNOTSUPP; |
c0644160 TD |
97 | |
98 | indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*st)); | |
99 | if (!indio_dev) | |
100 | return -ENOMEM; | |
101 | ||
102 | st = iio_priv(indio_dev); | |
713bbb4e | 103 | i2c_set_clientdata(client, indio_dev); |
c0644160 TD |
104 | st->reset = ms5611_i2c_reset; |
105 | st->read_prom_word = ms5611_i2c_read_prom_word; | |
106 | st->read_adc_temp_and_pressure = ms5611_i2c_read_adc_temp_and_pressure; | |
107 | st->client = client; | |
108 | ||
eac635eb | 109 | return ms5611_probe(indio_dev, &client->dev, id->name, id->driver_data); |
c0644160 TD |
110 | } |
111 | ||
713bbb4e DB |
112 | static int ms5611_i2c_remove(struct i2c_client *client) |
113 | { | |
114 | return ms5611_remove(i2c_get_clientdata(client)); | |
115 | } | |
116 | ||
7a948c5e GB |
117 | #if defined(CONFIG_OF) |
118 | static const struct of_device_id ms5611_i2c_matches[] = { | |
119 | { .compatible = "meas,ms5611" }, | |
120 | { .compatible = "ms5611" }, | |
121 | { .compatible = "meas,ms5607" }, | |
122 | { .compatible = "ms5607" }, | |
123 | { } | |
124 | }; | |
125 | MODULE_DEVICE_TABLE(of, ms5611_i2c_matches); | |
126 | #endif | |
127 | ||
c0644160 | 128 | static const struct i2c_device_id ms5611_id[] = { |
9690d81a TD |
129 | { "ms5611", MS5611 }, |
130 | { "ms5607", MS5607 }, | |
c0644160 TD |
131 | { } |
132 | }; | |
133 | MODULE_DEVICE_TABLE(i2c, ms5611_id); | |
134 | ||
135 | static struct i2c_driver ms5611_driver = { | |
136 | .driver = { | |
137 | .name = "ms5611", | |
7a948c5e | 138 | .of_match_table = of_match_ptr(ms5611_i2c_matches) |
c0644160 TD |
139 | }, |
140 | .id_table = ms5611_id, | |
141 | .probe = ms5611_i2c_probe, | |
713bbb4e | 142 | .remove = ms5611_i2c_remove, |
c0644160 TD |
143 | }; |
144 | module_i2c_driver(ms5611_driver); | |
145 | ||
146 | MODULE_AUTHOR("Tomasz Duszynski <tduszyns@gmail.com>"); | |
147 | MODULE_DESCRIPTION("MS5611 i2c driver"); | |
148 | MODULE_LICENSE("GPL v2"); |