Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Measurements Specialties driver common i2c functions
0004  *
0005  * Copyright (c) 2015 Measurement-Specialties
0006  */
0007 
0008 #include <linux/module.h>
0009 #include <linux/iio/iio.h>
0010 #include <linux/device.h>
0011 #include <linux/delay.h>
0012 
0013 #include "ms_sensors_i2c.h"
0014 
0015 /* Conversion times in us */
0016 static const u16 ms_sensors_ht_t_conversion_time[] = { 50000, 25000,
0017                                13000, 7000 };
0018 static const u16 ms_sensors_ht_h_conversion_time[] = { 16000, 3000,
0019                                5000, 8000 };
0020 static const u16 ms_sensors_tp_conversion_time[] = { 500, 1100, 2100,
0021                              4100, 8220, 16440 };
0022 
0023 #define MS_SENSORS_SERIAL_READ_MSB      0xFA0F
0024 #define MS_SENSORS_SERIAL_READ_LSB      0xFCC9
0025 #define MS_SENSORS_CONFIG_REG_WRITE     0xE6
0026 #define MS_SENSORS_CONFIG_REG_READ      0xE7
0027 #define MS_SENSORS_HT_T_CONVERSION_START    0xF3
0028 #define MS_SENSORS_HT_H_CONVERSION_START    0xF5
0029 
0030 #define MS_SENSORS_TP_PROM_READ         0xA0
0031 #define MS_SENSORS_TP_T_CONVERSION_START    0x50
0032 #define MS_SENSORS_TP_P_CONVERSION_START    0x40
0033 #define MS_SENSORS_TP_ADC_READ          0x00
0034 
0035 #define MS_SENSORS_NO_READ_CMD          0xFF
0036 
0037 /**
0038  * ms_sensors_reset() - Reset function
0039  * @cli:    pointer to device client
0040  * @cmd:    reset cmd. Depends on device in use
0041  * @delay:  usleep minimal delay after reset command is issued
0042  *
0043  * Generic I2C reset function for Measurement Specialties devices.
0044  *
0045  * Return: 0 on success, negative errno otherwise.
0046  */
0047 int ms_sensors_reset(void *cli, u8 cmd, unsigned int delay)
0048 {
0049     int ret;
0050     struct i2c_client *client = cli;
0051 
0052     ret = i2c_smbus_write_byte(client, cmd);
0053     if (ret) {
0054         dev_err(&client->dev, "Failed to reset device\n");
0055         return ret;
0056     }
0057     usleep_range(delay, delay + 1000);
0058 
0059     return 0;
0060 }
0061 EXPORT_SYMBOL_NS(ms_sensors_reset, IIO_MEAS_SPEC_SENSORS);
0062 
0063 /**
0064  * ms_sensors_read_prom_word() - PROM word read function
0065  * @cli:    pointer to device client
0066  * @cmd:    PROM read cmd. Depends on device and prom id
0067  * @word:   pointer to word destination value
0068  *
0069  * Generic i2c prom word read function for Measurement Specialties devices.
0070  *
0071  * Return: 0 on success, negative errno otherwise.
0072  */
0073 int ms_sensors_read_prom_word(void *cli, int cmd, u16 *word)
0074 {
0075     int ret;
0076     struct i2c_client *client = cli;
0077 
0078     ret = i2c_smbus_read_word_swapped(client, cmd);
0079     if (ret < 0) {
0080         dev_err(&client->dev, "Failed to read prom word\n");
0081         return ret;
0082     }
0083     *word = ret;
0084 
0085     return 0;
0086 }
0087 EXPORT_SYMBOL_NS(ms_sensors_read_prom_word, IIO_MEAS_SPEC_SENSORS);
0088 
0089 /**
0090  * ms_sensors_convert_and_read() - ADC conversion & read function
0091  * @cli:    pointer to device client
0092  * @conv:   ADC conversion command. Depends on device in use
0093  * @rd:     ADC read command. Depends on device in use
0094  * @delay:  usleep minimal delay after conversion command is issued
0095  * @adc:    pointer to ADC destination value
0096  *
0097  * Generic ADC conversion & read function for Measurement Specialties
0098  * devices.
0099  * The function will issue conversion command, sleep appopriate delay, and
0100  * issue command to read ADC.
0101  *
0102  * Return: 0 on success, negative errno otherwise.
0103  */
0104 int ms_sensors_convert_and_read(void *cli, u8 conv, u8 rd,
0105                 unsigned int delay, u32 *adc)
0106 {
0107     int ret;
0108     __be32 buf = 0;
0109     struct i2c_client *client = cli;
0110 
0111     /* Trigger conversion */
0112     ret = i2c_smbus_write_byte(client, conv);
0113     if (ret)
0114         goto err;
0115     usleep_range(delay, delay + 1000);
0116 
0117     /* Retrieve ADC value */
0118     if (rd != MS_SENSORS_NO_READ_CMD)
0119         ret = i2c_smbus_read_i2c_block_data(client, rd, 3, (u8 *)&buf);
0120     else
0121         ret = i2c_master_recv(client, (u8 *)&buf, 3);
0122     if (ret < 0)
0123         goto err;
0124 
0125     dev_dbg(&client->dev, "ADC raw value : %x\n", be32_to_cpu(buf) >> 8);
0126     *adc = be32_to_cpu(buf) >> 8;
0127 
0128     return 0;
0129 err:
0130     dev_err(&client->dev, "Unable to make sensor adc conversion\n");
0131     return ret;
0132 }
0133 EXPORT_SYMBOL_NS(ms_sensors_convert_and_read, IIO_MEAS_SPEC_SENSORS);
0134 
0135 /**
0136  * ms_sensors_crc_valid() - CRC check function
0137  * @value:  input and CRC compare value
0138  *
0139  * Cyclic Redundancy Check function used in TSYS02D, HTU21, MS8607.
0140  * This function performs a x^8 + x^5 + x^4 + 1 polynomial CRC.
0141  * The argument contains CRC value in LSB byte while the bytes 1 and 2
0142  * are used for CRC computation.
0143  *
0144  * Return: 1 if CRC is valid, 0 otherwise.
0145  */
0146 static bool ms_sensors_crc_valid(u32 value)
0147 {
0148     u32 polynom = 0x988000; /* x^8 + x^5 + x^4 + 1 */
0149     u32 msb = 0x800000;
0150     u32 mask = 0xFF8000;
0151     u32 result = value & 0xFFFF00;
0152     u8 crc = value & 0xFF;
0153 
0154     while (msb != 0x80) {
0155         if (result & msb)
0156             result = ((result ^ polynom) & mask)
0157                 | (result & ~mask);
0158         msb >>= 1;
0159         mask >>= 1;
0160         polynom >>= 1;
0161     }
0162 
0163     return result == crc;
0164 }
0165 
0166 /**
0167  * ms_sensors_read_serial() - Serial number read function
0168  * @client: pointer to i2c client
0169  * @sn:     pointer to 64-bits destination value
0170  *
0171  * Generic i2c serial number read function for Measurement Specialties devices.
0172  * This function is used for TSYS02d, HTU21, MS8607 chipset.
0173  * Refer to datasheet:
0174  *  http://www.meas-spec.com/downloads/HTU2X_Serial_Number_Reading.pdf
0175  *
0176  * Sensor raw MSB serial number format is the following :
0177  *  [ SNB3, CRC, SNB2, CRC, SNB1, CRC, SNB0, CRC]
0178  * Sensor raw LSB serial number format is the following :
0179  *  [ X, X, SNC1, SNC0, CRC, SNA1, SNA0, CRC]
0180  * The resulting serial number is following :
0181  *  [ SNA1, SNA0, SNB3, SNB2, SNB1, SNB0, SNC1, SNC0]
0182  *
0183  * Return: 0 on success, negative errno otherwise.
0184  */
0185 int ms_sensors_read_serial(struct i2c_client *client, u64 *sn)
0186 {
0187     u8 i;
0188     __be64 rcv_buf = 0;
0189     u64 rcv_val;
0190     __be16 send_buf;
0191     int ret;
0192 
0193     struct i2c_msg msg[2] = {
0194         {
0195          .addr = client->addr,
0196          .flags = client->flags,
0197          .len = 2,
0198          .buf = (__u8 *)&send_buf,
0199          },
0200         {
0201          .addr = client->addr,
0202          .flags = client->flags | I2C_M_RD,
0203          .buf = (__u8 *)&rcv_buf,
0204          },
0205     };
0206 
0207     /* Read MSB part of serial number */
0208     send_buf = cpu_to_be16(MS_SENSORS_SERIAL_READ_MSB);
0209     msg[1].len = 8;
0210     ret = i2c_transfer(client->adapter, msg, 2);
0211     if (ret < 0) {
0212         dev_err(&client->dev, "Unable to read device serial number");
0213         return ret;
0214     }
0215 
0216     rcv_val = be64_to_cpu(rcv_buf);
0217     dev_dbg(&client->dev, "Serial MSB raw : %llx\n", rcv_val);
0218 
0219     for (i = 0; i < 64; i += 16) {
0220         if (!ms_sensors_crc_valid((rcv_val >> i) & 0xFFFF))
0221             return -ENODEV;
0222     }
0223 
0224     *sn = (((rcv_val >> 32) & 0xFF000000) |
0225            ((rcv_val >> 24) & 0x00FF0000) |
0226            ((rcv_val >> 16) & 0x0000FF00) |
0227            ((rcv_val >> 8) & 0x000000FF)) << 16;
0228 
0229     /* Read LSB part of serial number */
0230     send_buf = cpu_to_be16(MS_SENSORS_SERIAL_READ_LSB);
0231     msg[1].len = 6;
0232     rcv_buf = 0;
0233     ret = i2c_transfer(client->adapter, msg, 2);
0234     if (ret < 0) {
0235         dev_err(&client->dev, "Unable to read device serial number");
0236         return ret;
0237     }
0238 
0239     rcv_val = be64_to_cpu(rcv_buf) >> 16;
0240     dev_dbg(&client->dev, "Serial MSB raw : %llx\n", rcv_val);
0241 
0242     for (i = 0; i < 48; i += 24) {
0243         if (!ms_sensors_crc_valid((rcv_val >> i) & 0xFFFFFF))
0244             return -ENODEV;
0245     }
0246 
0247     *sn |= (rcv_val & 0xFFFF00) << 40 | (rcv_val >> 32);
0248 
0249     return 0;
0250 }
0251 EXPORT_SYMBOL_NS(ms_sensors_read_serial, IIO_MEAS_SPEC_SENSORS);
0252 
0253 static int ms_sensors_read_config_reg(struct i2c_client *client,
0254                       u8 *config_reg)
0255 {
0256     int ret;
0257 
0258     ret = i2c_smbus_write_byte(client, MS_SENSORS_CONFIG_REG_READ);
0259     if (ret) {
0260         dev_err(&client->dev, "Unable to read config register");
0261         return ret;
0262     }
0263 
0264     ret = i2c_master_recv(client, config_reg, 1);
0265     if (ret < 0) {
0266         dev_err(&client->dev, "Unable to read config register");
0267         return ret;
0268     }
0269     dev_dbg(&client->dev, "Config register :%x\n", *config_reg);
0270 
0271     return 0;
0272 }
0273 
0274 /**
0275  * ms_sensors_write_resolution() - Set resolution function
0276  * @dev_data:   pointer to temperature/humidity device data
0277  * @i:      resolution index to set
0278  *
0279  * This function will program the appropriate resolution based on the index
0280  * provided when user space will set samp_freq channel.
0281  * This function is used for TSYS02D, HTU21 and MS8607 chipsets.
0282  *
0283  * Return: 0 on success, negative errno otherwise.
0284  */
0285 ssize_t ms_sensors_write_resolution(struct ms_ht_dev *dev_data,
0286                     u8 i)
0287 {
0288     u8 config_reg;
0289     int ret;
0290 
0291     ret = ms_sensors_read_config_reg(dev_data->client, &config_reg);
0292     if (ret)
0293         return ret;
0294 
0295     config_reg &= 0x7E;
0296     config_reg |= ((i & 1) << 7) + ((i & 2) >> 1);
0297 
0298     return i2c_smbus_write_byte_data(dev_data->client,
0299                      MS_SENSORS_CONFIG_REG_WRITE,
0300                      config_reg);
0301 }
0302 EXPORT_SYMBOL_NS(ms_sensors_write_resolution, IIO_MEAS_SPEC_SENSORS);
0303 
0304 /**
0305  * ms_sensors_show_battery_low() - Show device battery low indicator
0306  * @dev_data:   pointer to temperature/humidity device data
0307  * @buf:    pointer to char buffer to write result
0308  *
0309  * This function will read battery indicator value in the device and
0310  * return 1 if the device voltage is below 2.25V.
0311  * This function is used for TSYS02D, HTU21 and MS8607 chipsets.
0312  *
0313  * Return: length of sprintf on success, negative errno otherwise.
0314  */
0315 ssize_t ms_sensors_show_battery_low(struct ms_ht_dev *dev_data,
0316                     char *buf)
0317 {
0318     int ret;
0319     u8 config_reg;
0320 
0321     mutex_lock(&dev_data->lock);
0322     ret = ms_sensors_read_config_reg(dev_data->client, &config_reg);
0323     mutex_unlock(&dev_data->lock);
0324     if (ret)
0325         return ret;
0326 
0327     return sysfs_emit(buf, "%d\n", (config_reg & 0x40) >> 6);
0328 }
0329 EXPORT_SYMBOL_NS(ms_sensors_show_battery_low, IIO_MEAS_SPEC_SENSORS);
0330 
0331 /**
0332  * ms_sensors_show_heater() - Show device heater
0333  * @dev_data:   pointer to temperature/humidity device data
0334  * @buf:    pointer to char buffer to write result
0335  *
0336  * This function will read heater enable value in the device and
0337  * return 1 if the heater is enabled.
0338  * This function is used for HTU21 and MS8607 chipsets.
0339  *
0340  * Return: length of sprintf on success, negative errno otherwise.
0341  */
0342 ssize_t ms_sensors_show_heater(struct ms_ht_dev *dev_data,
0343                    char *buf)
0344 {
0345     u8 config_reg;
0346     int ret;
0347 
0348     mutex_lock(&dev_data->lock);
0349     ret = ms_sensors_read_config_reg(dev_data->client, &config_reg);
0350     mutex_unlock(&dev_data->lock);
0351     if (ret)
0352         return ret;
0353 
0354     return sysfs_emit(buf, "%d\n", (config_reg & 0x4) >> 2);
0355 }
0356 EXPORT_SYMBOL_NS(ms_sensors_show_heater, IIO_MEAS_SPEC_SENSORS);
0357 
0358 /**
0359  * ms_sensors_write_heater() - Write device heater
0360  * @dev_data:   pointer to temperature/humidity device data
0361  * @buf:    pointer to char buffer from user space
0362  * @len:    length of buf
0363  *
0364  * This function will write 1 or 0 value in the device
0365  * to enable or disable heater.
0366  * This function is used for HTU21 and MS8607 chipsets.
0367  *
0368  * Return: length of buffer, negative errno otherwise.
0369  */
0370 ssize_t ms_sensors_write_heater(struct ms_ht_dev *dev_data,
0371                 const char *buf, size_t len)
0372 {
0373     u8 val, config_reg;
0374     int ret;
0375 
0376     ret = kstrtou8(buf, 10, &val);
0377     if (ret)
0378         return ret;
0379 
0380     if (val > 1)
0381         return -EINVAL;
0382 
0383     mutex_lock(&dev_data->lock);
0384     ret = ms_sensors_read_config_reg(dev_data->client, &config_reg);
0385     if (ret) {
0386         mutex_unlock(&dev_data->lock);
0387         return ret;
0388     }
0389 
0390     config_reg &= 0xFB;
0391     config_reg |= val << 2;
0392 
0393     ret = i2c_smbus_write_byte_data(dev_data->client,
0394                     MS_SENSORS_CONFIG_REG_WRITE,
0395                     config_reg);
0396     mutex_unlock(&dev_data->lock);
0397     if (ret) {
0398         dev_err(&dev_data->client->dev, "Unable to write config register\n");
0399         return ret;
0400     }
0401 
0402     return len;
0403 }
0404 EXPORT_SYMBOL_NS(ms_sensors_write_heater, IIO_MEAS_SPEC_SENSORS);
0405 
0406 /**
0407  * ms_sensors_ht_read_temperature() - Read temperature
0408  * @dev_data:   pointer to temperature/humidity device data
0409  * @temperature:pointer to temperature destination value
0410  *
0411  * This function will get temperature ADC value from the device,
0412  * check the CRC and compute the temperature value.
0413  * This function is used for TSYS02D, HTU21 and MS8607 chipsets.
0414  *
0415  * Return: 0 on success, negative errno otherwise.
0416  */
0417 int ms_sensors_ht_read_temperature(struct ms_ht_dev *dev_data,
0418                    s32 *temperature)
0419 {
0420     int ret;
0421     u32 adc;
0422     u16 delay;
0423 
0424     mutex_lock(&dev_data->lock);
0425     delay = ms_sensors_ht_t_conversion_time[dev_data->res_index];
0426     ret = ms_sensors_convert_and_read(dev_data->client,
0427                       MS_SENSORS_HT_T_CONVERSION_START,
0428                       MS_SENSORS_NO_READ_CMD,
0429                       delay, &adc);
0430     mutex_unlock(&dev_data->lock);
0431     if (ret)
0432         return ret;
0433 
0434     if (!ms_sensors_crc_valid(adc)) {
0435         dev_err(&dev_data->client->dev,
0436             "Temperature read crc check error\n");
0437         return -ENODEV;
0438     }
0439 
0440     /* Temperature algorithm */
0441     *temperature = (((s64)(adc >> 8) * 175720) >> 16) - 46850;
0442 
0443     return 0;
0444 }
0445 EXPORT_SYMBOL_NS(ms_sensors_ht_read_temperature, IIO_MEAS_SPEC_SENSORS);
0446 
0447 /**
0448  * ms_sensors_ht_read_humidity() - Read humidity
0449  * @dev_data:   pointer to temperature/humidity device data
0450  * @humidity:   pointer to humidity destination value
0451  *
0452  * This function will get humidity ADC value from the device,
0453  * check the CRC and compute the temperature value.
0454  * This function is used for HTU21 and MS8607 chipsets.
0455  *
0456  * Return: 0 on success, negative errno otherwise.
0457  */
0458 int ms_sensors_ht_read_humidity(struct ms_ht_dev *dev_data,
0459                 u32 *humidity)
0460 {
0461     int ret;
0462     u32 adc;
0463     u16 delay;
0464 
0465     mutex_lock(&dev_data->lock);
0466     delay = ms_sensors_ht_h_conversion_time[dev_data->res_index];
0467     ret = ms_sensors_convert_and_read(dev_data->client,
0468                       MS_SENSORS_HT_H_CONVERSION_START,
0469                       MS_SENSORS_NO_READ_CMD,
0470                       delay, &adc);
0471     mutex_unlock(&dev_data->lock);
0472     if (ret)
0473         return ret;
0474 
0475     if (!ms_sensors_crc_valid(adc)) {
0476         dev_err(&dev_data->client->dev,
0477             "Humidity read crc check error\n");
0478         return -ENODEV;
0479     }
0480 
0481     /* Humidity algorithm */
0482     *humidity = (((s32)(adc >> 8) * 12500) >> 16) * 10 - 6000;
0483     if (*humidity >= 100000)
0484         *humidity = 100000;
0485 
0486     return 0;
0487 }
0488 EXPORT_SYMBOL_NS(ms_sensors_ht_read_humidity, IIO_MEAS_SPEC_SENSORS);
0489 
0490 /**
0491  * ms_sensors_tp_crc4() - Calculate PROM CRC for
0492  *     Temperature and pressure devices.
0493  *     This function is only used when reading PROM coefficients
0494  *
0495  * @prom:   pointer to PROM coefficients array
0496  *
0497  * Return: CRC.
0498  */
0499 static u8 ms_sensors_tp_crc4(u16 *prom)
0500 {
0501     unsigned int cnt, n_bit;
0502     u16 n_rem = 0x0000;
0503 
0504     for (cnt = 0; cnt < MS_SENSORS_TP_PROM_WORDS_NB * 2; cnt++) {
0505         if (cnt % 2 == 1)
0506             n_rem ^= prom[cnt >> 1] & 0x00FF;
0507         else
0508             n_rem ^= prom[cnt >> 1] >> 8;
0509 
0510         for (n_bit = 8; n_bit > 0; n_bit--) {
0511             if (n_rem & 0x8000)
0512                 n_rem = (n_rem << 1) ^ 0x3000;
0513             else
0514                 n_rem <<= 1;
0515         }
0516     }
0517 
0518     return n_rem >> 12;
0519 }
0520 
0521 /**
0522  * ms_sensors_tp_crc_valid_112() - CRC check function for
0523  *     Temperature and pressure devices for 112bit PROM.
0524  *     This function is only used when reading PROM coefficients
0525  *
0526  * @prom:   pointer to PROM coefficients array
0527  *
0528  * Return: True if CRC is ok.
0529  */
0530 static bool ms_sensors_tp_crc_valid_112(u16 *prom)
0531 {
0532     u16 w0 = prom[0], crc_read = (w0 & 0xF000) >> 12;
0533     u8 crc;
0534 
0535     prom[0] &= 0x0FFF;      /* Clear the CRC computation part */
0536     prom[MS_SENSORS_TP_PROM_WORDS_NB - 1] = 0;
0537 
0538     crc = ms_sensors_tp_crc4(prom);
0539 
0540     prom[0] = w0;
0541 
0542     return crc == crc_read;
0543 }
0544 
0545 /**
0546  * ms_sensors_tp_crc_valid_128() - CRC check function for
0547  *     Temperature and pressure devices for 128bit PROM.
0548  *     This function is only used when reading PROM coefficients
0549  *
0550  * @prom:   pointer to PROM coefficients array
0551  *
0552  * Return: True if CRC is ok.
0553  */
0554 static bool ms_sensors_tp_crc_valid_128(u16 *prom)
0555 {
0556     u16 w7 = prom[7], crc_read = w7 & 0x000F;
0557     u8 crc;
0558 
0559     prom[7] &= 0xFF00;      /* Clear the CRC and LSB part */
0560 
0561     crc = ms_sensors_tp_crc4(prom);
0562 
0563     prom[7] = w7;
0564 
0565     return crc == crc_read;
0566 }
0567 
0568 /**
0569  * ms_sensors_tp_read_prom() - prom coeff read function
0570  * @dev_data:   pointer to temperature/pressure device data
0571  *
0572  * This function will read prom coefficients and check CRC.
0573  * This function is used for MS5637 and MS8607 chipsets.
0574  *
0575  * Return: 0 on success, negative errno otherwise.
0576  */
0577 int ms_sensors_tp_read_prom(struct ms_tp_dev *dev_data)
0578 {
0579     int i, ret;
0580     bool valid;
0581 
0582     for (i = 0; i < dev_data->hw->prom_len; i++) {
0583         ret = ms_sensors_read_prom_word(
0584             dev_data->client,
0585             MS_SENSORS_TP_PROM_READ + (i << 1),
0586             &dev_data->prom[i]);
0587 
0588         if (ret)
0589             return ret;
0590     }
0591 
0592     if (dev_data->hw->prom_len == 8)
0593         valid = ms_sensors_tp_crc_valid_128(dev_data->prom);
0594     else
0595         valid = ms_sensors_tp_crc_valid_112(dev_data->prom);
0596 
0597     if (!valid) {
0598         dev_err(&dev_data->client->dev,
0599             "Calibration coefficients crc check error\n");
0600         return -ENODEV;
0601     }
0602 
0603     return 0;
0604 }
0605 EXPORT_SYMBOL_NS(ms_sensors_tp_read_prom, IIO_MEAS_SPEC_SENSORS);
0606 
0607 /**
0608  * ms_sensors_read_temp_and_pressure() - read temp and pressure
0609  * @dev_data:   pointer to temperature/pressure device data
0610  * @temperature:pointer to temperature destination value
0611  * @pressure:   pointer to pressure destination value
0612  *
0613  * This function will read ADC and compute pressure and temperature value.
0614  * This function is used for MS5637 and MS8607 chipsets.
0615  *
0616  * Return: 0 on success, negative errno otherwise.
0617  */
0618 int ms_sensors_read_temp_and_pressure(struct ms_tp_dev *dev_data,
0619                       int *temperature,
0620                       unsigned int *pressure)
0621 {
0622     int ret;
0623     u32 t_adc, p_adc;
0624     s32 dt, temp;
0625     s64 off, sens, t2, off2, sens2;
0626     u16 *prom = dev_data->prom, delay;
0627 
0628     mutex_lock(&dev_data->lock);
0629     delay = ms_sensors_tp_conversion_time[dev_data->res_index];
0630 
0631     ret = ms_sensors_convert_and_read(
0632                     dev_data->client,
0633                     MS_SENSORS_TP_T_CONVERSION_START +
0634                         dev_data->res_index * 2,
0635                     MS_SENSORS_TP_ADC_READ,
0636                     delay, &t_adc);
0637     if (ret) {
0638         mutex_unlock(&dev_data->lock);
0639         return ret;
0640     }
0641 
0642     ret = ms_sensors_convert_and_read(
0643                     dev_data->client,
0644                     MS_SENSORS_TP_P_CONVERSION_START +
0645                         dev_data->res_index * 2,
0646                     MS_SENSORS_TP_ADC_READ,
0647                     delay, &p_adc);
0648     mutex_unlock(&dev_data->lock);
0649     if (ret)
0650         return ret;
0651 
0652     dt = (s32)t_adc - (prom[5] << 8);
0653 
0654     /* Actual temperature = 2000 + dT * TEMPSENS */
0655     temp = 2000 + (((s64)dt * prom[6]) >> 23);
0656 
0657     /* Second order temperature compensation */
0658     if (temp < 2000) {
0659         s64 tmp = (s64)temp - 2000;
0660 
0661         t2 = (3 * ((s64)dt * (s64)dt)) >> 33;
0662         off2 = (61 * tmp * tmp) >> 4;
0663         sens2 = (29 * tmp * tmp) >> 4;
0664 
0665         if (temp < -1500) {
0666             s64 tmp = (s64)temp + 1500;
0667 
0668             off2 += 17 * tmp * tmp;
0669             sens2 += 9 * tmp * tmp;
0670         }
0671     } else {
0672         t2 = (5 * ((s64)dt * (s64)dt)) >> 38;
0673         off2 = 0;
0674         sens2 = 0;
0675     }
0676 
0677     /* OFF = OFF_T1 + TCO * dT */
0678     off = (((s64)prom[2]) << 17) + ((((s64)prom[4]) * (s64)dt) >> 6);
0679     off -= off2;
0680 
0681     /* Sensitivity at actual temperature = SENS_T1 + TCS * dT */
0682     sens = (((s64)prom[1]) << 16) + (((s64)prom[3] * dt) >> 7);
0683     sens -= sens2;
0684 
0685     /* Temperature compensated pressure = D1 * SENS - OFF */
0686     *temperature = (temp - t2) * 10;
0687     *pressure = (u32)(((((s64)p_adc * sens) >> 21) - off) >> 15);
0688 
0689     return 0;
0690 }
0691 EXPORT_SYMBOL_NS(ms_sensors_read_temp_and_pressure, IIO_MEAS_SPEC_SENSORS);
0692 
0693 MODULE_DESCRIPTION("Measurement-Specialties common i2c driver");
0694 MODULE_AUTHOR("William Markezana <william.markezana@meas-spec.com>");
0695 MODULE_AUTHOR("Ludovic Tancerel <ludovic.tancerel@maplehightech.com>");
0696 MODULE_LICENSE("GPL v2");
0697