16cfdb150STomasz Duszynski // SPDX-License-Identifier: GPL-2.0
2c0644160STomasz Duszynski /*
3c0644160STomasz Duszynski * MS5611 pressure and temperature sensor driver (I2C bus)
4c0644160STomasz Duszynski *
5c0644160STomasz Duszynski * Copyright (c) Tomasz Duszynski <tduszyns@gmail.com>
6c0644160STomasz Duszynski *
7c0644160STomasz Duszynski * 7-bit I2C slave addresses:
8c0644160STomasz Duszynski *
9c0644160STomasz Duszynski * 0x77 (CSB pin low)
10c0644160STomasz Duszynski * 0x76 (CSB pin high)
11c0644160STomasz Duszynski *
12c0644160STomasz Duszynski */
13c0644160STomasz Duszynski
14c0644160STomasz Duszynski #include <linux/delay.h>
15c0644160STomasz Duszynski #include <linux/i2c.h>
16c0644160STomasz Duszynski #include <linux/module.h>
170e624706SJonathan Cameron #include <linux/mod_devicetable.h>
18c0644160STomasz Duszynski
1900d5e7b2SAndy Shevchenko #include <asm/unaligned.h>
2000d5e7b2SAndy Shevchenko
21c0644160STomasz Duszynski #include "ms5611.h"
22c0644160STomasz Duszynski
ms5611_i2c_reset(struct ms5611_state * st)23dc19fa63SLars-Peter Clausen static int ms5611_i2c_reset(struct ms5611_state *st)
24c0644160STomasz Duszynski {
25c0644160STomasz Duszynski return i2c_smbus_write_byte(st->client, MS5611_RESET);
26c0644160STomasz Duszynski }
27c0644160STomasz Duszynski
ms5611_i2c_read_prom_word(struct ms5611_state * st,int index,u16 * word)28dc19fa63SLars-Peter Clausen static int ms5611_i2c_read_prom_word(struct ms5611_state *st, int index,
29dc19fa63SLars-Peter Clausen u16 *word)
30c0644160STomasz Duszynski {
31c0644160STomasz Duszynski int ret;
32c0644160STomasz Duszynski
33c0644160STomasz Duszynski ret = i2c_smbus_read_word_swapped(st->client,
34c0644160STomasz Duszynski MS5611_READ_PROM_WORD + (index << 1));
35c0644160STomasz Duszynski if (ret < 0)
36c0644160STomasz Duszynski return ret;
37c0644160STomasz Duszynski
38c0644160STomasz Duszynski *word = ret;
39c0644160STomasz Duszynski
40c0644160STomasz Duszynski return 0;
41c0644160STomasz Duszynski }
42c0644160STomasz Duszynski
ms5611_i2c_read_adc(struct ms5611_state * st,s32 * val)43c0644160STomasz Duszynski static int ms5611_i2c_read_adc(struct ms5611_state *st, s32 *val)
44c0644160STomasz Duszynski {
45c0644160STomasz Duszynski int ret;
46c0644160STomasz Duszynski u8 buf[3];
47c0644160STomasz Duszynski
48c0644160STomasz Duszynski ret = i2c_smbus_read_i2c_block_data(st->client, MS5611_READ_ADC,
49c0644160STomasz Duszynski 3, buf);
50c0644160STomasz Duszynski if (ret < 0)
51c0644160STomasz Duszynski return ret;
52c0644160STomasz Duszynski
5300d5e7b2SAndy Shevchenko *val = get_unaligned_be24(&buf[0]);
54c0644160STomasz Duszynski
55c0644160STomasz Duszynski return 0;
56c0644160STomasz Duszynski }
57c0644160STomasz Duszynski
ms5611_i2c_read_adc_temp_and_pressure(struct ms5611_state * st,s32 * temp,s32 * pressure)58dc19fa63SLars-Peter Clausen static int ms5611_i2c_read_adc_temp_and_pressure(struct ms5611_state *st,
59c0644160STomasz Duszynski s32 *temp, s32 *pressure)
60c0644160STomasz Duszynski {
61c0644160STomasz Duszynski int ret;
62033691a9SGregor Boirie const struct ms5611_osr *osr = st->temp_osr;
63c0644160STomasz Duszynski
64033691a9SGregor Boirie ret = i2c_smbus_write_byte(st->client, osr->cmd);
65c0644160STomasz Duszynski if (ret < 0)
66c0644160STomasz Duszynski return ret;
67c0644160STomasz Duszynski
68033691a9SGregor Boirie usleep_range(osr->conv_usec, osr->conv_usec + (osr->conv_usec / 10UL));
69c0644160STomasz Duszynski ret = ms5611_i2c_read_adc(st, temp);
70c0644160STomasz Duszynski if (ret < 0)
71c0644160STomasz Duszynski return ret;
72c0644160STomasz Duszynski
73033691a9SGregor Boirie osr = st->pressure_osr;
74033691a9SGregor Boirie ret = i2c_smbus_write_byte(st->client, osr->cmd);
75c0644160STomasz Duszynski if (ret < 0)
76c0644160STomasz Duszynski return ret;
77c0644160STomasz Duszynski
78033691a9SGregor Boirie usleep_range(osr->conv_usec, osr->conv_usec + (osr->conv_usec / 10UL));
79c0644160STomasz Duszynski return ms5611_i2c_read_adc(st, pressure);
80c0644160STomasz Duszynski }
81c0644160STomasz Duszynski
ms5611_i2c_probe(struct i2c_client * client)82eba7dcb6SUwe Kleine-König static int ms5611_i2c_probe(struct i2c_client *client)
83c0644160STomasz Duszynski {
84eba7dcb6SUwe Kleine-König const struct i2c_device_id *id = i2c_client_get_device_id(client);
85c0644160STomasz Duszynski struct ms5611_state *st;
86c0644160STomasz Duszynski struct iio_dev *indio_dev;
87c0644160STomasz Duszynski
88c0644160STomasz Duszynski if (!i2c_check_functionality(client->adapter,
89c0644160STomasz Duszynski I2C_FUNC_SMBUS_WRITE_BYTE |
90c0644160STomasz Duszynski I2C_FUNC_SMBUS_READ_WORD_DATA |
91c0644160STomasz Duszynski I2C_FUNC_SMBUS_READ_I2C_BLOCK))
92f8d9d3b4SMatt Ranostay return -EOPNOTSUPP;
93c0644160STomasz Duszynski
94c0644160STomasz Duszynski indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*st));
95c0644160STomasz Duszynski if (!indio_dev)
96c0644160STomasz Duszynski return -ENOMEM;
97c0644160STomasz Duszynski
98c0644160STomasz Duszynski st = iio_priv(indio_dev);
99713bbb4eSDaniel Baluta i2c_set_clientdata(client, indio_dev);
100c0644160STomasz Duszynski st->reset = ms5611_i2c_reset;
101c0644160STomasz Duszynski st->read_prom_word = ms5611_i2c_read_prom_word;
102c0644160STomasz Duszynski st->read_adc_temp_and_pressure = ms5611_i2c_read_adc_temp_and_pressure;
103c0644160STomasz Duszynski st->client = client;
104c0644160STomasz Duszynski
105eac635ebSGrégor Boirie return ms5611_probe(indio_dev, &client->dev, id->name, id->driver_data);
106c0644160STomasz Duszynski }
107c0644160STomasz Duszynski
1087a948c5eSGrégor Boirie static const struct of_device_id ms5611_i2c_matches[] = {
1097a948c5eSGrégor Boirie { .compatible = "meas,ms5611" },
1107a948c5eSGrégor Boirie { .compatible = "meas,ms5607" },
1117a948c5eSGrégor Boirie { }
1127a948c5eSGrégor Boirie };
1137a948c5eSGrégor Boirie MODULE_DEVICE_TABLE(of, ms5611_i2c_matches);
1147a948c5eSGrégor Boirie
115c0644160STomasz Duszynski static const struct i2c_device_id ms5611_id[] = {
1169690d81aSTomasz Duszynski { "ms5611", MS5611 },
1179690d81aSTomasz Duszynski { "ms5607", MS5607 },
118c0644160STomasz Duszynski { }
119c0644160STomasz Duszynski };
120c0644160STomasz Duszynski MODULE_DEVICE_TABLE(i2c, ms5611_id);
121c0644160STomasz Duszynski
122c0644160STomasz Duszynski static struct i2c_driver ms5611_driver = {
123c0644160STomasz Duszynski .driver = {
124c0644160STomasz Duszynski .name = "ms5611",
1250e624706SJonathan Cameron .of_match_table = ms5611_i2c_matches,
126c0644160STomasz Duszynski },
127c0644160STomasz Duszynski .id_table = ms5611_id,
128*7cf15f42SUwe Kleine-König .probe = ms5611_i2c_probe,
129c0644160STomasz Duszynski };
130c0644160STomasz Duszynski module_i2c_driver(ms5611_driver);
131c0644160STomasz Duszynski
132c0644160STomasz Duszynski MODULE_AUTHOR("Tomasz Duszynski <tduszyns@gmail.com>");
133c0644160STomasz Duszynski MODULE_DESCRIPTION("MS5611 i2c driver");
134c0644160STomasz Duszynski MODULE_LICENSE("GPL v2");
1351980d4a1SJonathan Cameron MODULE_IMPORT_NS(IIO_MS5611);
136