1 // SPDX-License-Identifier: GPL-2.0
3 * MS5611 pressure and temperature sensor driver (I2C bus)
5 * Copyright (c) Tomasz Duszynski <tduszyns@gmail.com>
7 * 7-bit I2C slave addresses:
14 #include <linux/delay.h>
15 #include <linux/i2c.h>
16 #include <linux/module.h>
17 #include <linux/mod_devicetable.h>
19 #include <asm/unaligned.h>
23 static int ms5611_i2c_reset(struct device
*dev
)
25 struct ms5611_state
*st
= iio_priv(dev_to_iio_dev(dev
));
27 return i2c_smbus_write_byte(st
->client
, MS5611_RESET
);
30 static int ms5611_i2c_read_prom_word(struct device
*dev
, int index
, u16
*word
)
33 struct ms5611_state
*st
= iio_priv(dev_to_iio_dev(dev
));
35 ret
= i2c_smbus_read_word_swapped(st
->client
,
36 MS5611_READ_PROM_WORD
+ (index
<< 1));
45 static int ms5611_i2c_read_adc(struct ms5611_state
*st
, s32
*val
)
50 ret
= i2c_smbus_read_i2c_block_data(st
->client
, MS5611_READ_ADC
,
55 *val
= get_unaligned_be24(&buf
[0]);
60 static int ms5611_i2c_read_adc_temp_and_pressure(struct device
*dev
,
61 s32
*temp
, s32
*pressure
)
64 struct ms5611_state
*st
= iio_priv(dev_to_iio_dev(dev
));
65 const struct ms5611_osr
*osr
= st
->temp_osr
;
67 ret
= i2c_smbus_write_byte(st
->client
, osr
->cmd
);
71 usleep_range(osr
->conv_usec
, osr
->conv_usec
+ (osr
->conv_usec
/ 10UL));
72 ret
= ms5611_i2c_read_adc(st
, temp
);
76 osr
= st
->pressure_osr
;
77 ret
= i2c_smbus_write_byte(st
->client
, osr
->cmd
);
81 usleep_range(osr
->conv_usec
, osr
->conv_usec
+ (osr
->conv_usec
/ 10UL));
82 return ms5611_i2c_read_adc(st
, pressure
);
85 static int ms5611_i2c_probe(struct i2c_client
*client
,
86 const struct i2c_device_id
*id
)
88 struct ms5611_state
*st
;
89 struct iio_dev
*indio_dev
;
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
))
97 indio_dev
= devm_iio_device_alloc(&client
->dev
, sizeof(*st
));
101 st
= iio_priv(indio_dev
);
102 i2c_set_clientdata(client
, indio_dev
);
103 st
->reset
= ms5611_i2c_reset
;
104 st
->read_prom_word
= ms5611_i2c_read_prom_word
;
105 st
->read_adc_temp_and_pressure
= ms5611_i2c_read_adc_temp_and_pressure
;
108 return ms5611_probe(indio_dev
, &client
->dev
, id
->name
, id
->driver_data
);
111 static int ms5611_i2c_remove(struct i2c_client
*client
)
113 return ms5611_remove(i2c_get_clientdata(client
));
116 static const struct of_device_id ms5611_i2c_matches
[] = {
117 { .compatible
= "meas,ms5611" },
118 { .compatible
= "meas,ms5607" },
121 MODULE_DEVICE_TABLE(of
, ms5611_i2c_matches
);
123 static const struct i2c_device_id ms5611_id
[] = {
124 { "ms5611", MS5611
},
125 { "ms5607", MS5607
},
128 MODULE_DEVICE_TABLE(i2c
, ms5611_id
);
130 static struct i2c_driver ms5611_driver
= {
133 .of_match_table
= ms5611_i2c_matches
,
135 .id_table
= ms5611_id
,
136 .probe
= ms5611_i2c_probe
,
137 .remove
= ms5611_i2c_remove
,
139 module_i2c_driver(ms5611_driver
);
141 MODULE_AUTHOR("Tomasz Duszynski <tduszyns@gmail.com>");
142 MODULE_DESCRIPTION("MS5611 i2c driver");
143 MODULE_LICENSE("GPL v2");