^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * mlx90632.c - Melexis MLX90632 contactless IR temperature sensor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (c) 2017 Melexis <cmo@melexis.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Driver for the Melexis MLX90632 I2C 16-bit IR thermopile sensor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/err.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/gpio/consumer.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/i2c.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/iopoll.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/limits.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/math64.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/of.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/pm_runtime.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/regmap.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <linux/iio/iio.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <linux/iio/sysfs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) /* Memory sections addresses */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #define MLX90632_ADDR_RAM 0x4000 /* Start address of ram */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #define MLX90632_ADDR_EEPROM 0x2480 /* Start address of user eeprom */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) /* EEPROM addresses - used at startup */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #define MLX90632_EE_CTRL 0x24d4 /* Control register initial value */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #define MLX90632_EE_I2C_ADDR 0x24d5 /* I2C address register initial value */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #define MLX90632_EE_VERSION 0x240b /* EEPROM version reg address */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #define MLX90632_EE_P_R 0x240c /* P_R calibration register 32bit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #define MLX90632_EE_P_G 0x240e /* P_G calibration register 32bit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #define MLX90632_EE_P_T 0x2410 /* P_T calibration register 32bit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #define MLX90632_EE_P_O 0x2412 /* P_O calibration register 32bit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #define MLX90632_EE_Aa 0x2414 /* Aa calibration register 32bit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #define MLX90632_EE_Ab 0x2416 /* Ab calibration register 32bit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #define MLX90632_EE_Ba 0x2418 /* Ba calibration register 32bit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) #define MLX90632_EE_Bb 0x241a /* Bb calibration register 32bit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) #define MLX90632_EE_Ca 0x241c /* Ca calibration register 32bit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) #define MLX90632_EE_Cb 0x241e /* Cb calibration register 32bit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) #define MLX90632_EE_Da 0x2420 /* Da calibration register 32bit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) #define MLX90632_EE_Db 0x2422 /* Db calibration register 32bit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) #define MLX90632_EE_Ea 0x2424 /* Ea calibration register 32bit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) #define MLX90632_EE_Eb 0x2426 /* Eb calibration register 32bit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) #define MLX90632_EE_Fa 0x2428 /* Fa calibration register 32bit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) #define MLX90632_EE_Fb 0x242a /* Fb calibration register 32bit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) #define MLX90632_EE_Ga 0x242c /* Ga calibration register 32bit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) #define MLX90632_EE_Gb 0x242e /* Gb calibration register 16bit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) #define MLX90632_EE_Ka 0x242f /* Ka calibration register 16bit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) #define MLX90632_EE_Ha 0x2481 /* Ha customer calib value reg 16bit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) #define MLX90632_EE_Hb 0x2482 /* Hb customer calib value reg 16bit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) /* Register addresses - volatile */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) #define MLX90632_REG_I2C_ADDR 0x3000 /* Chip I2C address register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) /* Control register address - volatile */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) #define MLX90632_REG_CONTROL 0x3001 /* Control Register address */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) #define MLX90632_CFG_PWR_MASK GENMASK(2, 1) /* PowerMode Mask */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) #define MLX90632_CFG_MTYP_MASK GENMASK(8, 4) /* Meas select Mask */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) /* PowerModes statuses */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) #define MLX90632_PWR_STATUS(ctrl_val) (ctrl_val << 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) #define MLX90632_PWR_STATUS_HALT MLX90632_PWR_STATUS(0) /* hold */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) #define MLX90632_PWR_STATUS_SLEEP_STEP MLX90632_PWR_STATUS(1) /* sleep step*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) #define MLX90632_PWR_STATUS_STEP MLX90632_PWR_STATUS(2) /* step */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) #define MLX90632_PWR_STATUS_CONTINUOUS MLX90632_PWR_STATUS(3) /* continuous*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) /* Measurement types */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) #define MLX90632_MTYP_MEDICAL 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) #define MLX90632_MTYP_EXTENDED 17
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) /* Measurement type select*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) #define MLX90632_MTYP_STATUS(ctrl_val) (ctrl_val << 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) #define MLX90632_MTYP_STATUS_MEDICAL MLX90632_MTYP_STATUS(MLX90632_MTYP_MEDICAL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) #define MLX90632_MTYP_STATUS_EXTENDED MLX90632_MTYP_STATUS(MLX90632_MTYP_EXTENDED)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) /* I2C command register - volatile */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) #define MLX90632_REG_I2C_CMD 0x3005 /* I2C command Register address */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) /* Device status register - volatile */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) #define MLX90632_REG_STATUS 0x3fff /* Device status register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) #define MLX90632_STAT_BUSY BIT(10) /* Device busy indicator */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) #define MLX90632_STAT_EE_BUSY BIT(9) /* EEPROM busy indicator */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) #define MLX90632_STAT_BRST BIT(8) /* Brown out reset indicator */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) #define MLX90632_STAT_CYCLE_POS GENMASK(6, 2) /* Data position */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) #define MLX90632_STAT_DATA_RDY BIT(0) /* Data ready indicator */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) /* RAM_MEAS address-es for each channel */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) #define MLX90632_RAM_1(meas_num) (MLX90632_ADDR_RAM + 3 * meas_num)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) #define MLX90632_RAM_2(meas_num) (MLX90632_ADDR_RAM + 3 * meas_num + 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) #define MLX90632_RAM_3(meas_num) (MLX90632_ADDR_RAM + 3 * meas_num + 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) /* Name important RAM_MEAS channels */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) #define MLX90632_RAM_DSP5_EXTENDED_AMBIENT_1 MLX90632_RAM_3(17)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) #define MLX90632_RAM_DSP5_EXTENDED_AMBIENT_2 MLX90632_RAM_3(18)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) #define MLX90632_RAM_DSP5_EXTENDED_OBJECT_1 MLX90632_RAM_1(17)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) #define MLX90632_RAM_DSP5_EXTENDED_OBJECT_2 MLX90632_RAM_2(17)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) #define MLX90632_RAM_DSP5_EXTENDED_OBJECT_3 MLX90632_RAM_1(18)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) #define MLX90632_RAM_DSP5_EXTENDED_OBJECT_4 MLX90632_RAM_2(18)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) #define MLX90632_RAM_DSP5_EXTENDED_OBJECT_5 MLX90632_RAM_1(19)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) #define MLX90632_RAM_DSP5_EXTENDED_OBJECT_6 MLX90632_RAM_2(19)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) /* Magic constants */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) #define MLX90632_ID_MEDICAL 0x0105 /* EEPROM DSPv5 Medical device id */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) #define MLX90632_ID_CONSUMER 0x0205 /* EEPROM DSPv5 Consumer device id */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) #define MLX90632_ID_EXTENDED 0x0505 /* EEPROM DSPv5 Extended range device id */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) #define MLX90632_ID_MASK GENMASK(14, 0) /* DSP version and device ID in EE_VERSION */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) #define MLX90632_DSP_VERSION 5 /* DSP version */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) #define MLX90632_DSP_MASK GENMASK(7, 0) /* DSP version in EE_VERSION */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) #define MLX90632_RESET_CMD 0x0006 /* Reset sensor (address or global) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) #define MLX90632_REF_12 12LL /* ResCtrlRef value of Ch 1 or Ch 2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) #define MLX90632_REF_3 12LL /* ResCtrlRef value of Channel 3 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) #define MLX90632_MAX_MEAS_NUM 31 /* Maximum measurements in list */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) #define MLX90632_SLEEP_DELAY_MS 3000 /* Autosleep delay */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) #define MLX90632_EXTENDED_LIMIT 27000 /* Extended mode raw value limit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) * struct mlx90632_data - private data for the MLX90632 device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) * @client: I2C client of the device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) * @lock: Internal mutex for multiple reads for single measurement
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) * @regmap: Regmap of the device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) * @emissivity: Object emissivity from 0 to 1000 where 1000 = 1.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) * @mtyp: Measurement type physical sensor configuration for extended range
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) * calculations
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) * @object_ambient_temperature: Ambient temperature at object (might differ of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) * the ambient temperature of sensor.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) struct mlx90632_data {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) struct i2c_client *client;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) struct mutex lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) struct regmap *regmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) u16 emissivity;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) u8 mtyp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) u32 object_ambient_temperature;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) static const struct regmap_range mlx90632_volatile_reg_range[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) regmap_reg_range(MLX90632_REG_I2C_ADDR, MLX90632_REG_CONTROL),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) regmap_reg_range(MLX90632_REG_I2C_CMD, MLX90632_REG_I2C_CMD),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) regmap_reg_range(MLX90632_REG_STATUS, MLX90632_REG_STATUS),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) regmap_reg_range(MLX90632_RAM_1(0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) MLX90632_RAM_3(MLX90632_MAX_MEAS_NUM)),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) static const struct regmap_access_table mlx90632_volatile_regs_tbl = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) .yes_ranges = mlx90632_volatile_reg_range,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) .n_yes_ranges = ARRAY_SIZE(mlx90632_volatile_reg_range),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) static const struct regmap_range mlx90632_read_reg_range[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) regmap_reg_range(MLX90632_EE_VERSION, MLX90632_EE_Ka),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) regmap_reg_range(MLX90632_EE_CTRL, MLX90632_EE_I2C_ADDR),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) regmap_reg_range(MLX90632_EE_Ha, MLX90632_EE_Hb),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) regmap_reg_range(MLX90632_REG_I2C_ADDR, MLX90632_REG_CONTROL),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) regmap_reg_range(MLX90632_REG_I2C_CMD, MLX90632_REG_I2C_CMD),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) regmap_reg_range(MLX90632_REG_STATUS, MLX90632_REG_STATUS),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) regmap_reg_range(MLX90632_RAM_1(0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) MLX90632_RAM_3(MLX90632_MAX_MEAS_NUM)),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) static const struct regmap_access_table mlx90632_readable_regs_tbl = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) .yes_ranges = mlx90632_read_reg_range,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) .n_yes_ranges = ARRAY_SIZE(mlx90632_read_reg_range),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) static const struct regmap_range mlx90632_no_write_reg_range[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) regmap_reg_range(MLX90632_EE_VERSION, MLX90632_EE_Ka),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) regmap_reg_range(MLX90632_RAM_1(0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) MLX90632_RAM_3(MLX90632_MAX_MEAS_NUM)),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) static const struct regmap_access_table mlx90632_writeable_regs_tbl = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) .no_ranges = mlx90632_no_write_reg_range,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) .n_no_ranges = ARRAY_SIZE(mlx90632_no_write_reg_range),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) static const struct regmap_config mlx90632_regmap = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) .reg_bits = 16,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) .val_bits = 16,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) .volatile_table = &mlx90632_volatile_regs_tbl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) .rd_table = &mlx90632_readable_regs_tbl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) .wr_table = &mlx90632_writeable_regs_tbl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) .use_single_read = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) .use_single_write = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) .reg_format_endian = REGMAP_ENDIAN_BIG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) .val_format_endian = REGMAP_ENDIAN_BIG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) .cache_type = REGCACHE_RBTREE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) static s32 mlx90632_pwr_set_sleep_step(struct regmap *regmap)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) return regmap_update_bits(regmap, MLX90632_REG_CONTROL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) MLX90632_CFG_PWR_MASK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) MLX90632_PWR_STATUS_SLEEP_STEP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) static s32 mlx90632_pwr_continuous(struct regmap *regmap)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) return regmap_update_bits(regmap, MLX90632_REG_CONTROL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) MLX90632_CFG_PWR_MASK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) MLX90632_PWR_STATUS_CONTINUOUS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) * mlx90632_perform_measurement() - Trigger and retrieve current measurement cycle
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) * @data: pointer to mlx90632_data object containing regmap information
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) * Perform a measurement and return latest measurement cycle position reported
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) * by sensor. This is a blocking function for 500ms, as that is default sensor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) * refresh rate.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) static int mlx90632_perform_measurement(struct mlx90632_data *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) unsigned int reg_status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) ret = regmap_update_bits(data->regmap, MLX90632_REG_STATUS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) MLX90632_STAT_DATA_RDY, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) ret = regmap_read_poll_timeout(data->regmap, MLX90632_REG_STATUS, reg_status,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) !(reg_status & MLX90632_STAT_DATA_RDY), 10000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) 100 * 10000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) dev_err(&data->client->dev, "data not ready");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) return -ETIMEDOUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) return (reg_status & MLX90632_STAT_CYCLE_POS) >> 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) static int mlx90632_set_meas_type(struct regmap *regmap, u8 type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) if ((type != MLX90632_MTYP_MEDICAL) && (type != MLX90632_MTYP_EXTENDED))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) ret = regmap_write(regmap, MLX90632_REG_I2C_CMD, MLX90632_RESET_CMD);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) * Give the mlx90632 some time to reset properly before sending a new I2C command
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) * if this is not done, the following I2C command(s) will not be accepted.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) usleep_range(150, 200);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) ret = regmap_write_bits(regmap, MLX90632_REG_CONTROL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) (MLX90632_CFG_MTYP_MASK | MLX90632_CFG_PWR_MASK),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) (MLX90632_MTYP_STATUS(type) | MLX90632_PWR_STATUS_HALT));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) return mlx90632_pwr_continuous(regmap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) static int mlx90632_channel_new_select(int perform_ret, uint8_t *channel_new,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) uint8_t *channel_old)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) switch (perform_ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) case 1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) *channel_new = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) *channel_old = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) case 2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) *channel_new = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) *channel_old = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) static int mlx90632_read_ambient_raw(struct regmap *regmap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) s16 *ambient_new_raw, s16 *ambient_old_raw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) unsigned int read_tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) ret = regmap_read(regmap, MLX90632_RAM_3(1), &read_tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) *ambient_new_raw = (s16)read_tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) ret = regmap_read(regmap, MLX90632_RAM_3(2), &read_tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) *ambient_old_raw = (s16)read_tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) static int mlx90632_read_object_raw(struct regmap *regmap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) int perform_measurement_ret,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) s16 *object_new_raw, s16 *object_old_raw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) unsigned int read_tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) s16 read;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) u8 channel = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) u8 channel_old = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) ret = mlx90632_channel_new_select(perform_measurement_ret, &channel,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) &channel_old);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) if (ret != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) ret = regmap_read(regmap, MLX90632_RAM_2(channel), &read_tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) read = (s16)read_tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) ret = regmap_read(regmap, MLX90632_RAM_1(channel), &read_tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) *object_new_raw = (read + (s16)read_tmp) / 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) ret = regmap_read(regmap, MLX90632_RAM_2(channel_old), &read_tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) read = (s16)read_tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) ret = regmap_read(regmap, MLX90632_RAM_1(channel_old), &read_tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) *object_old_raw = (read + (s16)read_tmp) / 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) static int mlx90632_read_all_channel(struct mlx90632_data *data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) s16 *ambient_new_raw, s16 *ambient_old_raw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) s16 *object_new_raw, s16 *object_old_raw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) s32 ret, measurement;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) mutex_lock(&data->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) measurement = mlx90632_perform_measurement(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) if (measurement < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) ret = measurement;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) goto read_unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) ret = mlx90632_read_ambient_raw(data->regmap, ambient_new_raw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) ambient_old_raw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) goto read_unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) ret = mlx90632_read_object_raw(data->regmap, measurement,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) object_new_raw, object_old_raw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) read_unlock:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) mutex_unlock(&data->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) static int mlx90632_read_ambient_raw_extended(struct regmap *regmap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) s16 *ambient_new_raw, s16 *ambient_old_raw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) unsigned int read_tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) ret = regmap_read(regmap, MLX90632_RAM_DSP5_EXTENDED_AMBIENT_1, &read_tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) *ambient_new_raw = (s16)read_tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) ret = regmap_read(regmap, MLX90632_RAM_DSP5_EXTENDED_AMBIENT_2, &read_tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) *ambient_old_raw = (s16)read_tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) static int mlx90632_read_object_raw_extended(struct regmap *regmap, s16 *object_new_raw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) unsigned int read_tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) s32 read;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) ret = regmap_read(regmap, MLX90632_RAM_DSP5_EXTENDED_OBJECT_1, &read_tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) read = (s16)read_tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) ret = regmap_read(regmap, MLX90632_RAM_DSP5_EXTENDED_OBJECT_2, &read_tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) read = read - (s16)read_tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) ret = regmap_read(regmap, MLX90632_RAM_DSP5_EXTENDED_OBJECT_3, &read_tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) read = read - (s16)read_tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) ret = regmap_read(regmap, MLX90632_RAM_DSP5_EXTENDED_OBJECT_4, &read_tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) read = (read + (s16)read_tmp) / 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) ret = regmap_read(regmap, MLX90632_RAM_DSP5_EXTENDED_OBJECT_5, &read_tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) read = read + (s16)read_tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) ret = regmap_read(regmap, MLX90632_RAM_DSP5_EXTENDED_OBJECT_6, &read_tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) read = read + (s16)read_tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) if (read > S16_MAX || read < S16_MIN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) return -ERANGE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) *object_new_raw = read;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) static int mlx90632_read_all_channel_extended(struct mlx90632_data *data, s16 *object_new_raw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) s16 *ambient_new_raw, s16 *ambient_old_raw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) s32 ret, meas;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) mutex_lock(&data->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) ret = mlx90632_set_meas_type(data->regmap, MLX90632_MTYP_EXTENDED);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) goto read_unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) ret = read_poll_timeout(mlx90632_perform_measurement, meas, meas == 19,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) 50000, 800000, false, data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) if (ret != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) goto read_unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) ret = mlx90632_read_object_raw_extended(data->regmap, object_new_raw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) goto read_unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) ret = mlx90632_read_ambient_raw_extended(data->regmap, ambient_new_raw, ambient_old_raw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) read_unlock:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) (void) mlx90632_set_meas_type(data->regmap, MLX90632_MTYP_MEDICAL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) mutex_unlock(&data->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) static int mlx90632_read_ee_register(struct regmap *regmap, u16 reg_lsb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) s32 *reg_value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) s32 ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) unsigned int read;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) u32 value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) ret = regmap_read(regmap, reg_lsb, &read);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) value = read;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) ret = regmap_read(regmap, reg_lsb + 1, &read);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) *reg_value = (read << 16) | (value & 0xffff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) static s64 mlx90632_preprocess_temp_amb(s16 ambient_new_raw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) s16 ambient_old_raw, s16 Gb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) s64 VR_Ta, kGb, tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) kGb = ((s64)Gb * 1000LL) >> 10ULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) VR_Ta = (s64)ambient_old_raw * 1000000LL +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) kGb * div64_s64(((s64)ambient_new_raw * 1000LL),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) (MLX90632_REF_3));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) tmp = div64_s64(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) div64_s64(((s64)ambient_new_raw * 1000000000000LL),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) (MLX90632_REF_3)), VR_Ta);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) return div64_s64(tmp << 19ULL, 1000LL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) static s64 mlx90632_preprocess_temp_obj(s16 object_new_raw, s16 object_old_raw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) s16 ambient_new_raw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) s16 ambient_old_raw, s16 Ka)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) s64 VR_IR, kKa, tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) kKa = ((s64)Ka * 1000LL) >> 10ULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) VR_IR = (s64)ambient_old_raw * 1000000LL +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) kKa * div64_s64(((s64)ambient_new_raw * 1000LL),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) (MLX90632_REF_3));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) tmp = div64_s64(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) div64_s64(((s64)((object_new_raw + object_old_raw) / 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) * 1000000000000LL), (MLX90632_REF_12)),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) VR_IR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) return div64_s64((tmp << 19ULL), 1000LL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) static s64 mlx90632_preprocess_temp_obj_extended(s16 object_new_raw, s16 ambient_new_raw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) s16 ambient_old_raw, s16 Ka)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) s64 VR_IR, kKa, tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) kKa = ((s64)Ka * 1000LL) >> 10ULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) VR_IR = (s64)ambient_old_raw * 1000000LL +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) kKa * div64_s64((s64)ambient_new_raw * 1000LL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) MLX90632_REF_3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) tmp = div64_s64(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) div64_s64((s64) object_new_raw * 1000000000000LL, MLX90632_REF_12),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) VR_IR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) return div64_s64(tmp << 19ULL, 1000LL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) static s32 mlx90632_calc_temp_ambient(s16 ambient_new_raw, s16 ambient_old_raw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) s32 P_T, s32 P_R, s32 P_G, s32 P_O, s16 Gb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) s64 Asub, Bsub, Ablock, Bblock, Cblock, AMB, sum;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) AMB = mlx90632_preprocess_temp_amb(ambient_new_raw, ambient_old_raw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) Gb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) Asub = ((s64)P_T * 10000000000LL) >> 44ULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) Bsub = AMB - (((s64)P_R * 1000LL) >> 8ULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) Ablock = Asub * (Bsub * Bsub);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) Bblock = (div64_s64(Bsub * 10000000LL, P_G)) << 20ULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) Cblock = ((s64)P_O * 10000000000LL) >> 8ULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) sum = div64_s64(Ablock, 1000000LL) + Bblock + Cblock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) return div64_s64(sum, 10000000LL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) static s32 mlx90632_calc_temp_object_iteration(s32 prev_object_temp, s64 object,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) s64 TAdut, s64 TAdut4, s32 Fa, s32 Fb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) s32 Ga, s16 Ha, s16 Hb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) u16 emissivity)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) s64 calcedKsTO, calcedKsTA, ir_Alpha, Alpha_corr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) s64 Ha_customer, Hb_customer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) Ha_customer = ((s64)Ha * 1000000LL) >> 14ULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) Hb_customer = ((s64)Hb * 100) >> 10ULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) calcedKsTO = ((s64)((s64)Ga * (prev_object_temp - 25 * 1000LL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) * 1000LL)) >> 36LL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) calcedKsTA = ((s64)(Fb * (TAdut - 25 * 1000000LL))) >> 36LL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) Alpha_corr = div64_s64((((s64)(Fa * 10000000000LL) >> 46LL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) * Ha_customer), 1000LL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) Alpha_corr *= ((s64)(1 * 1000000LL + calcedKsTO + calcedKsTA));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) Alpha_corr = emissivity * div64_s64(Alpha_corr, 100000LL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) Alpha_corr = div64_s64(Alpha_corr, 1000LL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) ir_Alpha = div64_s64((s64)object * 10000000LL, Alpha_corr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) return (int_sqrt64(int_sqrt64(ir_Alpha * 1000000000000LL + TAdut4))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) - 27315 - Hb_customer) * 10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) static s64 mlx90632_calc_ta4(s64 TAdut, s64 scale)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) return (div64_s64(TAdut, scale) + 27315) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) (div64_s64(TAdut, scale) + 27315) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) (div64_s64(TAdut, scale) + 27315) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) (div64_s64(TAdut, scale) + 27315);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) static s32 mlx90632_calc_temp_object(s64 object, s64 ambient, s32 Ea, s32 Eb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) s32 Fa, s32 Fb, s32 Ga, s16 Ha, s16 Hb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) u16 tmp_emi)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) s64 kTA, kTA0, TAdut, TAdut4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) s64 temp = 25000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) s8 i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) kTA = (Ea * 1000LL) >> 16LL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) kTA0 = (Eb * 1000LL) >> 8LL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) TAdut = div64_s64(((ambient - kTA0) * 1000000LL), kTA) + 25 * 1000000LL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) TAdut4 = mlx90632_calc_ta4(TAdut, 10000LL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) /* Iterations of calculation as described in datasheet */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) for (i = 0; i < 5; ++i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) temp = mlx90632_calc_temp_object_iteration(temp, object, TAdut, TAdut4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) Fa, Fb, Ga, Ha, Hb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) tmp_emi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) return temp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) static s32 mlx90632_calc_temp_object_extended(s64 object, s64 ambient, s64 reflected,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) s32 Ea, s32 Eb, s32 Fa, s32 Fb, s32 Ga,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) s16 Ha, s16 Hb, u16 tmp_emi)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) s64 kTA, kTA0, TAdut, TAdut4, Tr4, TaTr4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) s64 temp = 25000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) s8 i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) kTA = (Ea * 1000LL) >> 16LL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) kTA0 = (Eb * 1000LL) >> 8LL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) TAdut = div64_s64((ambient - kTA0) * 1000000LL, kTA) + 25 * 1000000LL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) Tr4 = mlx90632_calc_ta4(reflected, 10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) TAdut4 = mlx90632_calc_ta4(TAdut, 10000LL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) TaTr4 = Tr4 - div64_s64(Tr4 - TAdut4, tmp_emi) * 1000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) /* Iterations of calculation as described in datasheet */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) for (i = 0; i < 5; ++i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) temp = mlx90632_calc_temp_object_iteration(temp, object, TAdut, TaTr4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) Fa / 2, Fb, Ga, Ha, Hb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) tmp_emi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) return temp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) static int mlx90632_calc_object_dsp105(struct mlx90632_data *data, int *val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) s32 ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) s32 Ea, Eb, Fa, Fb, Ga;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) unsigned int read_tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) s16 Ha, Hb, Gb, Ka;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) s16 ambient_new_raw, ambient_old_raw, object_new_raw, object_old_raw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) s64 object, ambient;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) ret = mlx90632_read_ee_register(data->regmap, MLX90632_EE_Ea, &Ea);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) ret = mlx90632_read_ee_register(data->regmap, MLX90632_EE_Eb, &Eb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) ret = mlx90632_read_ee_register(data->regmap, MLX90632_EE_Fa, &Fa);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) ret = mlx90632_read_ee_register(data->regmap, MLX90632_EE_Fb, &Fb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) ret = mlx90632_read_ee_register(data->regmap, MLX90632_EE_Ga, &Ga);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) ret = regmap_read(data->regmap, MLX90632_EE_Ha, &read_tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) Ha = (s16)read_tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) ret = regmap_read(data->regmap, MLX90632_EE_Hb, &read_tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) Hb = (s16)read_tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) ret = regmap_read(data->regmap, MLX90632_EE_Gb, &read_tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) Gb = (s16)read_tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) ret = regmap_read(data->regmap, MLX90632_EE_Ka, &read_tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) Ka = (s16)read_tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) ret = mlx90632_read_all_channel(data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) &ambient_new_raw, &ambient_old_raw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) &object_new_raw, &object_old_raw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) if (object_new_raw > MLX90632_EXTENDED_LIMIT &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) data->mtyp == MLX90632_MTYP_EXTENDED) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) ret = mlx90632_read_all_channel_extended(data, &object_new_raw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) &ambient_new_raw, &ambient_old_raw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) /* Use extended mode calculations */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) ambient = mlx90632_preprocess_temp_amb(ambient_new_raw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) ambient_old_raw, Gb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) object = mlx90632_preprocess_temp_obj_extended(object_new_raw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) ambient_new_raw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) ambient_old_raw, Ka);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) *val = mlx90632_calc_temp_object_extended(object, ambient,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) data->object_ambient_temperature,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) Ea, Eb, Fa, Fb, Ga,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) Ha, Hb, data->emissivity);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) ambient = mlx90632_preprocess_temp_amb(ambient_new_raw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) ambient_old_raw, Gb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) object = mlx90632_preprocess_temp_obj(object_new_raw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) object_old_raw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) ambient_new_raw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) ambient_old_raw, Ka);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) *val = mlx90632_calc_temp_object(object, ambient, Ea, Eb, Fa, Fb, Ga,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) Ha, Hb, data->emissivity);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) static int mlx90632_calc_ambient_dsp105(struct mlx90632_data *data, int *val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) s32 ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) unsigned int read_tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) s32 PT, PR, PG, PO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) s16 Gb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) s16 ambient_new_raw, ambient_old_raw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) ret = mlx90632_read_ee_register(data->regmap, MLX90632_EE_P_R, &PR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) ret = mlx90632_read_ee_register(data->regmap, MLX90632_EE_P_G, &PG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) ret = mlx90632_read_ee_register(data->regmap, MLX90632_EE_P_T, &PT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) ret = mlx90632_read_ee_register(data->regmap, MLX90632_EE_P_O, &PO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) ret = regmap_read(data->regmap, MLX90632_EE_Gb, &read_tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) Gb = (s16)read_tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) ret = mlx90632_read_ambient_raw(data->regmap, &ambient_new_raw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) &ambient_old_raw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) *val = mlx90632_calc_temp_ambient(ambient_new_raw, ambient_old_raw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) PT, PR, PG, PO, Gb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) static int mlx90632_read_raw(struct iio_dev *indio_dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) struct iio_chan_spec const *channel, int *val,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) int *val2, long mask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) struct mlx90632_data *data = iio_priv(indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) switch (mask) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) case IIO_CHAN_INFO_PROCESSED:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) switch (channel->channel2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) case IIO_MOD_TEMP_AMBIENT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) ret = mlx90632_calc_ambient_dsp105(data, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) return IIO_VAL_INT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) case IIO_MOD_TEMP_OBJECT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) ret = mlx90632_calc_object_dsp105(data, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) return IIO_VAL_INT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) case IIO_CHAN_INFO_CALIBEMISSIVITY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) if (data->emissivity == 1000) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) *val = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) *val2 = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) *val = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) *val2 = data->emissivity * 1000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) return IIO_VAL_INT_PLUS_MICRO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) case IIO_CHAN_INFO_CALIBAMBIENT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) *val = data->object_ambient_temperature;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) return IIO_VAL_INT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) static int mlx90632_write_raw(struct iio_dev *indio_dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) struct iio_chan_spec const *channel, int val,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) int val2, long mask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) struct mlx90632_data *data = iio_priv(indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) switch (mask) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) case IIO_CHAN_INFO_CALIBEMISSIVITY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) /* Confirm we are within 0 and 1.0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) if (val < 0 || val2 < 0 || val > 1 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) (val == 1 && val2 != 0))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) data->emissivity = val * 1000 + val2 / 1000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) case IIO_CHAN_INFO_CALIBAMBIENT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) data->object_ambient_temperature = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) static const struct iio_chan_spec mlx90632_channels[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) .type = IIO_TEMP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) .modified = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) .channel2 = IIO_MOD_TEMP_AMBIENT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) .type = IIO_TEMP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) .modified = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) .channel2 = IIO_MOD_TEMP_OBJECT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) BIT(IIO_CHAN_INFO_CALIBEMISSIVITY) | BIT(IIO_CHAN_INFO_CALIBAMBIENT),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) static const struct iio_info mlx90632_info = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) .read_raw = mlx90632_read_raw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) .write_raw = mlx90632_write_raw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) static int mlx90632_sleep(struct mlx90632_data *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) regcache_mark_dirty(data->regmap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) dev_dbg(&data->client->dev, "Requesting sleep");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) return mlx90632_pwr_set_sleep_step(data->regmap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) static int mlx90632_wakeup(struct mlx90632_data *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) ret = regcache_sync(data->regmap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) dev_err(&data->client->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) "Failed to sync regmap registers: %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) dev_dbg(&data->client->dev, "Requesting wake-up\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) return mlx90632_pwr_continuous(data->regmap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) static int mlx90632_probe(struct i2c_client *client,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) const struct i2c_device_id *id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) struct iio_dev *indio_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) struct mlx90632_data *mlx90632;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) struct regmap *regmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) unsigned int read;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*mlx90632));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) if (!indio_dev) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) dev_err(&client->dev, "Failed to allocate device\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) regmap = devm_regmap_init_i2c(client, &mlx90632_regmap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) if (IS_ERR(regmap)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) ret = PTR_ERR(regmap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) dev_err(&client->dev, "Failed to allocate regmap: %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) mlx90632 = iio_priv(indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) i2c_set_clientdata(client, indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) mlx90632->client = client;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) mlx90632->regmap = regmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) mlx90632->mtyp = MLX90632_MTYP_MEDICAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) mutex_init(&mlx90632->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) indio_dev->name = id->name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) indio_dev->modes = INDIO_DIRECT_MODE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) indio_dev->info = &mlx90632_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) indio_dev->channels = mlx90632_channels;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) indio_dev->num_channels = ARRAY_SIZE(mlx90632_channels);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) ret = mlx90632_wakeup(mlx90632);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) dev_err(&client->dev, "Wakeup failed: %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) ret = regmap_read(mlx90632->regmap, MLX90632_EE_VERSION, &read);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) dev_err(&client->dev, "read of version failed: %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) read = read & MLX90632_ID_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) if (read == MLX90632_ID_MEDICAL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) dev_dbg(&client->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) "Detected Medical EEPROM calibration %x\n", read);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) } else if (read == MLX90632_ID_CONSUMER) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) dev_dbg(&client->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) "Detected Consumer EEPROM calibration %x\n", read);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) } else if (read == MLX90632_ID_EXTENDED) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) dev_dbg(&client->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) "Detected Extended range EEPROM calibration %x\n", read);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) mlx90632->mtyp = MLX90632_MTYP_EXTENDED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) } else if ((read & MLX90632_DSP_MASK) == MLX90632_DSP_VERSION) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) dev_dbg(&client->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) "Detected Unknown EEPROM calibration %x\n", read);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) dev_err(&client->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) "Wrong DSP version %x (expected %x)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) read, MLX90632_DSP_VERSION);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) return -EPROTONOSUPPORT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) mlx90632->emissivity = 1000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) mlx90632->object_ambient_temperature = 25000; /* 25 degrees milliCelsius */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) pm_runtime_disable(&client->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) ret = pm_runtime_set_active(&client->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) mlx90632_sleep(mlx90632);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) pm_runtime_enable(&client->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) pm_runtime_set_autosuspend_delay(&client->dev, MLX90632_SLEEP_DELAY_MS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) pm_runtime_use_autosuspend(&client->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) return iio_device_register(indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) static int mlx90632_remove(struct i2c_client *client)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) struct iio_dev *indio_dev = i2c_get_clientdata(client);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) struct mlx90632_data *data = iio_priv(indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) iio_device_unregister(indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) pm_runtime_disable(&client->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) pm_runtime_set_suspended(&client->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) pm_runtime_put_noidle(&client->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) mlx90632_sleep(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) static const struct i2c_device_id mlx90632_id[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) { "mlx90632", 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) { }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) MODULE_DEVICE_TABLE(i2c, mlx90632_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) static const struct of_device_id mlx90632_of_match[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) { .compatible = "melexis,mlx90632" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) { }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) MODULE_DEVICE_TABLE(of, mlx90632_of_match);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) static int __maybe_unused mlx90632_pm_suspend(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) struct mlx90632_data *data = iio_priv(indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) return mlx90632_sleep(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) static int __maybe_unused mlx90632_pm_resume(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) struct mlx90632_data *data = iio_priv(indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) return mlx90632_wakeup(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) static UNIVERSAL_DEV_PM_OPS(mlx90632_pm_ops, mlx90632_pm_suspend,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) mlx90632_pm_resume, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) static struct i2c_driver mlx90632_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) .name = "mlx90632",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) .of_match_table = mlx90632_of_match,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) .pm = &mlx90632_pm_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) .probe = mlx90632_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) .remove = mlx90632_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) .id_table = mlx90632_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) module_i2c_driver(mlx90632_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) MODULE_AUTHOR("Crt Mori <cmo@melexis.com>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) MODULE_DESCRIPTION("Melexis MLX90632 contactless Infra Red temperature sensor driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) MODULE_LICENSE("GPL v2");