xref: /linux/drivers/iio/pressure/sdp500.c (revision 6ddb86d93cc08c00eccc1a14980f7260e4fbe2bc)
1*6ddb86d9SPetar Stoykov // SPDX-License-Identifier: GPL-2.0-only
2*6ddb86d9SPetar Stoykov /*
3*6ddb86d9SPetar Stoykov  * Driver for Sensirion sdp500 and sdp510 pressure sensors
4*6ddb86d9SPetar Stoykov  *
5*6ddb86d9SPetar Stoykov  * Datasheet: https://sensirion.com/resource/datasheet/sdp600
6*6ddb86d9SPetar Stoykov  */
7*6ddb86d9SPetar Stoykov 
8*6ddb86d9SPetar Stoykov #include <linux/i2c.h>
9*6ddb86d9SPetar Stoykov #include <linux/crc8.h>
10*6ddb86d9SPetar Stoykov #include <linux/iio/iio.h>
11*6ddb86d9SPetar Stoykov #include <linux/mod_devicetable.h>
12*6ddb86d9SPetar Stoykov #include <linux/regulator/consumer.h>
13*6ddb86d9SPetar Stoykov #include <asm/unaligned.h>
14*6ddb86d9SPetar Stoykov 
15*6ddb86d9SPetar Stoykov #define SDP500_CRC8_POLYNOMIAL  0x31   /* x8+x5+x4+1 (normalized to 0x31) */
16*6ddb86d9SPetar Stoykov #define SDP500_READ_SIZE        3
17*6ddb86d9SPetar Stoykov 
18*6ddb86d9SPetar Stoykov #define SDP500_I2C_START_MEAS 0xF1
19*6ddb86d9SPetar Stoykov 
20*6ddb86d9SPetar Stoykov struct sdp500_data {
21*6ddb86d9SPetar Stoykov 	struct device *dev;
22*6ddb86d9SPetar Stoykov };
23*6ddb86d9SPetar Stoykov 
24*6ddb86d9SPetar Stoykov DECLARE_CRC8_TABLE(sdp500_crc8_table);
25*6ddb86d9SPetar Stoykov 
26*6ddb86d9SPetar Stoykov static int sdp500_start_measurement(struct sdp500_data *data)
27*6ddb86d9SPetar Stoykov {
28*6ddb86d9SPetar Stoykov 	struct i2c_client *client = to_i2c_client(data->dev);
29*6ddb86d9SPetar Stoykov 
30*6ddb86d9SPetar Stoykov 	return i2c_smbus_write_byte(client, SDP500_I2C_START_MEAS);
31*6ddb86d9SPetar Stoykov }
32*6ddb86d9SPetar Stoykov 
33*6ddb86d9SPetar Stoykov static const struct iio_chan_spec sdp500_channels[] = {
34*6ddb86d9SPetar Stoykov 	{
35*6ddb86d9SPetar Stoykov 		.type = IIO_PRESSURE,
36*6ddb86d9SPetar Stoykov 		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
37*6ddb86d9SPetar Stoykov 			BIT(IIO_CHAN_INFO_SCALE),
38*6ddb86d9SPetar Stoykov 	},
39*6ddb86d9SPetar Stoykov };
40*6ddb86d9SPetar Stoykov 
41*6ddb86d9SPetar Stoykov static int sdp500_read_raw(struct iio_dev *indio_dev,
42*6ddb86d9SPetar Stoykov 			  struct iio_chan_spec const *chan,
43*6ddb86d9SPetar Stoykov 			  int *val, int *val2, long mask)
44*6ddb86d9SPetar Stoykov {
45*6ddb86d9SPetar Stoykov 	int ret;
46*6ddb86d9SPetar Stoykov 	u8 rxbuf[SDP500_READ_SIZE];
47*6ddb86d9SPetar Stoykov 	u8 received_crc, calculated_crc;
48*6ddb86d9SPetar Stoykov 	struct sdp500_data *data = iio_priv(indio_dev);
49*6ddb86d9SPetar Stoykov 	struct i2c_client *client = to_i2c_client(data->dev);
50*6ddb86d9SPetar Stoykov 
51*6ddb86d9SPetar Stoykov 	switch (mask) {
52*6ddb86d9SPetar Stoykov 	case IIO_CHAN_INFO_RAW:
53*6ddb86d9SPetar Stoykov 		ret = i2c_master_recv(client, rxbuf, SDP500_READ_SIZE);
54*6ddb86d9SPetar Stoykov 		if (ret < 0) {
55*6ddb86d9SPetar Stoykov 			dev_err(data->dev, "Failed to receive data");
56*6ddb86d9SPetar Stoykov 			return ret;
57*6ddb86d9SPetar Stoykov 		}
58*6ddb86d9SPetar Stoykov 		if (ret != SDP500_READ_SIZE) {
59*6ddb86d9SPetar Stoykov 			dev_err(data->dev, "Data is received wrongly");
60*6ddb86d9SPetar Stoykov 			return -EIO;
61*6ddb86d9SPetar Stoykov 		}
62*6ddb86d9SPetar Stoykov 
63*6ddb86d9SPetar Stoykov 		received_crc = rxbuf[2];
64*6ddb86d9SPetar Stoykov 		calculated_crc = crc8(sdp500_crc8_table, rxbuf,
65*6ddb86d9SPetar Stoykov 				      sizeof(rxbuf) - 1, 0x00);
66*6ddb86d9SPetar Stoykov 		if (received_crc != calculated_crc) {
67*6ddb86d9SPetar Stoykov 			dev_err(data->dev,
68*6ddb86d9SPetar Stoykov 				"calculated crc = 0x%.2X, received 0x%.2X",
69*6ddb86d9SPetar Stoykov 				calculated_crc, received_crc);
70*6ddb86d9SPetar Stoykov 			return -EIO;
71*6ddb86d9SPetar Stoykov 		}
72*6ddb86d9SPetar Stoykov 
73*6ddb86d9SPetar Stoykov 		*val = get_unaligned_be16(rxbuf);
74*6ddb86d9SPetar Stoykov 		return IIO_VAL_INT;
75*6ddb86d9SPetar Stoykov 	case IIO_CHAN_INFO_SCALE:
76*6ddb86d9SPetar Stoykov 		*val = 1;
77*6ddb86d9SPetar Stoykov 		*val2 = 60;
78*6ddb86d9SPetar Stoykov 
79*6ddb86d9SPetar Stoykov 		return IIO_VAL_FRACTIONAL;
80*6ddb86d9SPetar Stoykov 	default:
81*6ddb86d9SPetar Stoykov 		return -EINVAL;
82*6ddb86d9SPetar Stoykov 	}
83*6ddb86d9SPetar Stoykov }
84*6ddb86d9SPetar Stoykov 
85*6ddb86d9SPetar Stoykov static const struct iio_info sdp500_info = {
86*6ddb86d9SPetar Stoykov 	.read_raw = &sdp500_read_raw,
87*6ddb86d9SPetar Stoykov };
88*6ddb86d9SPetar Stoykov 
89*6ddb86d9SPetar Stoykov static int sdp500_probe(struct i2c_client *client)
90*6ddb86d9SPetar Stoykov {
91*6ddb86d9SPetar Stoykov 	struct iio_dev *indio_dev;
92*6ddb86d9SPetar Stoykov 	struct sdp500_data *data;
93*6ddb86d9SPetar Stoykov 	struct device *dev = &client->dev;
94*6ddb86d9SPetar Stoykov 	int ret;
95*6ddb86d9SPetar Stoykov 	u8 rxbuf[SDP500_READ_SIZE];
96*6ddb86d9SPetar Stoykov 
97*6ddb86d9SPetar Stoykov 	ret = devm_regulator_get_enable(dev, "vdd");
98*6ddb86d9SPetar Stoykov 	if (ret)
99*6ddb86d9SPetar Stoykov 		return dev_err_probe(dev, ret,
100*6ddb86d9SPetar Stoykov 			"Failed to get and enable regulator\n");
101*6ddb86d9SPetar Stoykov 
102*6ddb86d9SPetar Stoykov 	indio_dev = devm_iio_device_alloc(dev, sizeof(*data));
103*6ddb86d9SPetar Stoykov 	if (!indio_dev)
104*6ddb86d9SPetar Stoykov 		return -ENOMEM;
105*6ddb86d9SPetar Stoykov 
106*6ddb86d9SPetar Stoykov 	/* has to be done before the first i2c communication */
107*6ddb86d9SPetar Stoykov 	crc8_populate_msb(sdp500_crc8_table, SDP500_CRC8_POLYNOMIAL);
108*6ddb86d9SPetar Stoykov 
109*6ddb86d9SPetar Stoykov 	data = iio_priv(indio_dev);
110*6ddb86d9SPetar Stoykov 	data->dev = dev;
111*6ddb86d9SPetar Stoykov 
112*6ddb86d9SPetar Stoykov 	indio_dev->name = "sdp500";
113*6ddb86d9SPetar Stoykov 	indio_dev->channels = sdp500_channels;
114*6ddb86d9SPetar Stoykov 	indio_dev->info = &sdp500_info;
115*6ddb86d9SPetar Stoykov 	indio_dev->modes = INDIO_DIRECT_MODE;
116*6ddb86d9SPetar Stoykov 	indio_dev->num_channels = ARRAY_SIZE(sdp500_channels);
117*6ddb86d9SPetar Stoykov 
118*6ddb86d9SPetar Stoykov 	ret = sdp500_start_measurement(data);
119*6ddb86d9SPetar Stoykov 	if (ret)
120*6ddb86d9SPetar Stoykov 		return dev_err_probe(dev, ret, "Failed to start measurement");
121*6ddb86d9SPetar Stoykov 
122*6ddb86d9SPetar Stoykov 	/* First measurement is not correct, read it out to get rid of it */
123*6ddb86d9SPetar Stoykov 	i2c_master_recv(client, rxbuf, SDP500_READ_SIZE);
124*6ddb86d9SPetar Stoykov 
125*6ddb86d9SPetar Stoykov 	ret = devm_iio_device_register(dev, indio_dev);
126*6ddb86d9SPetar Stoykov 	if (ret)
127*6ddb86d9SPetar Stoykov 		return dev_err_probe(dev, ret, "Failed to register indio_dev");
128*6ddb86d9SPetar Stoykov 
129*6ddb86d9SPetar Stoykov 	return 0;
130*6ddb86d9SPetar Stoykov }
131*6ddb86d9SPetar Stoykov 
132*6ddb86d9SPetar Stoykov static const struct i2c_device_id sdp500_id[] = {
133*6ddb86d9SPetar Stoykov 	{ "sdp500" },
134*6ddb86d9SPetar Stoykov 	{ }
135*6ddb86d9SPetar Stoykov };
136*6ddb86d9SPetar Stoykov MODULE_DEVICE_TABLE(i2c, sdp500_id);
137*6ddb86d9SPetar Stoykov 
138*6ddb86d9SPetar Stoykov static const struct of_device_id sdp500_of_match[] = {
139*6ddb86d9SPetar Stoykov 	{ .compatible = "sensirion,sdp500" },
140*6ddb86d9SPetar Stoykov 	{ }
141*6ddb86d9SPetar Stoykov };
142*6ddb86d9SPetar Stoykov MODULE_DEVICE_TABLE(of, sdp500_of_match);
143*6ddb86d9SPetar Stoykov 
144*6ddb86d9SPetar Stoykov static struct i2c_driver sdp500_driver = {
145*6ddb86d9SPetar Stoykov 	.driver = {
146*6ddb86d9SPetar Stoykov 		.name = "sensirion,sdp500",
147*6ddb86d9SPetar Stoykov 		.of_match_table = sdp500_of_match,
148*6ddb86d9SPetar Stoykov 	},
149*6ddb86d9SPetar Stoykov 	.probe = sdp500_probe,
150*6ddb86d9SPetar Stoykov 	.id_table = sdp500_id,
151*6ddb86d9SPetar Stoykov };
152*6ddb86d9SPetar Stoykov module_i2c_driver(sdp500_driver);
153*6ddb86d9SPetar Stoykov 
154*6ddb86d9SPetar Stoykov MODULE_AUTHOR("Thomas Sioutas <thomas.sioutas@prodrive-technologies.com>");
155*6ddb86d9SPetar Stoykov MODULE_DESCRIPTION("Driver for Sensirion SDP500 differential pressure sensor");
156*6ddb86d9SPetar Stoykov MODULE_LICENSE("GPL");
157