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