1 // SPDX-License-Identifier: GPL-2.0-only
3 * ms5637.c - Support for Measurement-Specialties MS5637, MS5805
4 * MS5837 and MS8607 pressure & temperature sensor
6 * Copyright (c) 2015 Measurement-Specialties
8 * (7-bit I2C slave address 0x76)
11 * http://www.meas-spec.com/downloads/MS5637-02BA03.pdf
13 * http://www.meas-spec.com/downloads/MS5805-02BA01.pdf
15 * http://www.meas-spec.com/downloads/MS5837-30BA.pdf
17 * http://www.meas-spec.com/downloads/MS8607-02BA01.pdf
20 #include <linux/init.h>
21 #include <linux/device.h>
22 #include <linux/kernel.h>
23 #include <linux/stat.h>
24 #include <linux/module.h>
25 #include <linux/mod_devicetable.h>
26 #include <linux/i2c.h>
27 #include <linux/iio/iio.h>
28 #include <linux/iio/sysfs.h>
29 #include <linux/mutex.h>
31 #include "../common/ms_sensors/ms_sensors_i2c.h"
35 const struct ms_tp_hw_data
*hw
;
38 static const int ms5637_samp_freq
[6] = { 960, 480, 240, 120, 60, 30 };
40 static ssize_t
ms5637_show_samp_freq(struct device
*dev
, struct device_attribute
*attr
, char *buf
)
42 struct iio_dev
*indio_dev
= dev_to_iio_dev(dev
);
43 struct ms_tp_dev
*dev_data
= iio_priv(indio_dev
);
46 for (i
= 0; i
<= dev_data
->hw
->max_res_index
; i
++)
47 len
+= sysfs_emit_at(buf
, len
, "%u ", ms5637_samp_freq
[i
]);
48 sysfs_emit_at(buf
, len
- 1, "\n");
53 static int ms5637_read_raw(struct iio_dev
*indio_dev
,
54 struct iio_chan_spec
const *channel
, int *val
,
59 unsigned int pressure
;
60 struct ms_tp_dev
*dev_data
= iio_priv(indio_dev
);
63 case IIO_CHAN_INFO_PROCESSED
:
64 ret
= ms_sensors_read_temp_and_pressure(dev_data
,
70 switch (channel
->type
) {
71 case IIO_TEMP
: /* in milli °C */
75 case IIO_PRESSURE
: /* in kPa */
76 *val
= pressure
/ 1000;
77 *val2
= (pressure
% 1000) * 1000;
79 return IIO_VAL_INT_PLUS_MICRO
;
83 case IIO_CHAN_INFO_SAMP_FREQ
:
84 *val
= ms5637_samp_freq
[dev_data
->res_index
];
92 static int ms5637_write_raw(struct iio_dev
*indio_dev
,
93 struct iio_chan_spec
const *chan
,
94 int val
, int val2
, long mask
)
96 struct ms_tp_dev
*dev_data
= iio_priv(indio_dev
);
100 case IIO_CHAN_INFO_SAMP_FREQ
:
101 i
= ARRAY_SIZE(ms5637_samp_freq
);
103 if (val
== ms5637_samp_freq
[i
])
107 dev_data
->res_index
= i
;
115 static const struct iio_chan_spec ms5637_channels
[] = {
118 .info_mask_separate
= BIT(IIO_CHAN_INFO_PROCESSED
),
119 .info_mask_shared_by_all
= BIT(IIO_CHAN_INFO_SAMP_FREQ
),
122 .type
= IIO_PRESSURE
,
123 .info_mask_separate
= BIT(IIO_CHAN_INFO_PROCESSED
),
124 .info_mask_shared_by_all
= BIT(IIO_CHAN_INFO_SAMP_FREQ
),
128 static IIO_DEV_ATTR_SAMP_FREQ_AVAIL(ms5637_show_samp_freq
);
130 static struct attribute
*ms5637_attributes
[] = {
131 &iio_dev_attr_sampling_frequency_available
.dev_attr
.attr
,
135 static const struct attribute_group ms5637_attribute_group
= {
136 .attrs
= ms5637_attributes
,
139 static const struct iio_info ms5637_info
= {
140 .read_raw
= ms5637_read_raw
,
141 .write_raw
= ms5637_write_raw
,
142 .attrs
= &ms5637_attribute_group
,
145 static int ms5637_probe(struct i2c_client
*client
)
147 const struct ms_tp_data
*data
;
148 struct ms_tp_dev
*dev_data
;
149 struct iio_dev
*indio_dev
;
152 if (!i2c_check_functionality(client
->adapter
,
153 I2C_FUNC_SMBUS_READ_WORD_DATA
|
154 I2C_FUNC_SMBUS_WRITE_BYTE
|
155 I2C_FUNC_SMBUS_READ_I2C_BLOCK
)) {
156 dev_err(&client
->dev
,
157 "Adapter does not support some i2c transaction\n");
161 data
= i2c_get_match_data(client
);
165 indio_dev
= devm_iio_device_alloc(&client
->dev
, sizeof(*dev_data
));
169 dev_data
= iio_priv(indio_dev
);
170 dev_data
->client
= client
;
171 dev_data
->res_index
= data
->hw
->max_res_index
;
172 dev_data
->hw
= data
->hw
;
173 mutex_init(&dev_data
->lock
);
175 indio_dev
->info
= &ms5637_info
;
176 indio_dev
->name
= data
->name
;
177 indio_dev
->modes
= INDIO_DIRECT_MODE
;
178 indio_dev
->channels
= ms5637_channels
;
179 indio_dev
->num_channels
= ARRAY_SIZE(ms5637_channels
);
181 i2c_set_clientdata(client
, indio_dev
);
183 ret
= ms_sensors_reset(client
, 0x1E, 3000);
187 ret
= ms_sensors_tp_read_prom(dev_data
);
191 return devm_iio_device_register(&client
->dev
, indio_dev
);
194 static const struct ms_tp_hw_data ms5637_hw_data
= {
199 static const struct ms_tp_hw_data ms5803_hw_data
= {
204 static const struct ms_tp_data ms5637_data
= { .name
= "ms5637", .hw
= &ms5637_hw_data
};
206 static const struct ms_tp_data ms5803_data
= { .name
= "ms5803", .hw
= &ms5803_hw_data
};
208 static const struct ms_tp_data ms5805_data
= { .name
= "ms5805", .hw
= &ms5637_hw_data
};
210 static const struct ms_tp_data ms5837_data
= { .name
= "ms5837", .hw
= &ms5637_hw_data
};
212 static const struct ms_tp_data ms8607_data
= {
213 .name
= "ms8607-temppressure",
214 .hw
= &ms5637_hw_data
,
217 static const struct i2c_device_id ms5637_id
[] = {
218 {"ms5637", (kernel_ulong_t
)&ms5637_data
},
219 {"ms5805", (kernel_ulong_t
)&ms5805_data
},
220 {"ms5837", (kernel_ulong_t
)&ms5837_data
},
221 {"ms8607-temppressure", (kernel_ulong_t
)&ms8607_data
},
224 MODULE_DEVICE_TABLE(i2c
, ms5637_id
);
226 static const struct of_device_id ms5637_of_match
[] = {
227 { .compatible
= "meas,ms5637", .data
= &ms5637_data
},
228 { .compatible
= "meas,ms5803", .data
= &ms5803_data
},
229 { .compatible
= "meas,ms5805", .data
= &ms5805_data
},
230 { .compatible
= "meas,ms5837", .data
= &ms5837_data
},
231 { .compatible
= "meas,ms8607-temppressure", .data
= &ms8607_data
},
234 MODULE_DEVICE_TABLE(of
, ms5637_of_match
);
236 static struct i2c_driver ms5637_driver
= {
237 .probe
= ms5637_probe
,
238 .id_table
= ms5637_id
,
241 .of_match_table
= ms5637_of_match
,
245 module_i2c_driver(ms5637_driver
);
247 MODULE_DESCRIPTION("Measurement-Specialties ms5637 temperature & pressure driver");
248 MODULE_AUTHOR("William Markezana <william.markezana@meas-spec.com>");
249 MODULE_AUTHOR("Ludovic Tancerel <ludovic.tancerel@maplehightech.com>");
250 MODULE_LICENSE("GPL v2");
251 MODULE_IMPORT_NS("IIO_MEAS_SPEC_SENSORS");