1098 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * mlx90635.c - Melexis MLX90635 contactless IR temperature sensor4 *5 * Copyright (c) 2023 Melexis <cmo@melexis.com>6 *7 * Driver for the Melexis MLX90635 I2C 16-bit IR thermopile sensor8 */9#include <linux/bitfield.h>10#include <linux/delay.h>11#include <linux/device.h>12#include <linux/err.h>13#include <linux/gpio/consumer.h>14#include <linux/i2c.h>15#include <linux/iopoll.h>16#include <linux/jiffies.h>17#include <linux/kernel.h>18#include <linux/limits.h>19#include <linux/mod_devicetable.h>20#include <linux/module.h>21#include <linux/math64.h>22#include <linux/pm_runtime.h>23#include <linux/regmap.h>24#include <linux/regulator/consumer.h>25 26#include <linux/iio/iio.h>27 28/* Memory sections addresses */29#define MLX90635_ADDR_RAM 0x0000 /* Start address of ram */30#define MLX90635_ADDR_EEPROM 0x0018 /* Start address of user eeprom */31 32/* EEPROM addresses - used at startup */33#define MLX90635_EE_I2C_CFG 0x0018 /* I2C address register initial value */34#define MLX90635_EE_CTRL1 0x001A /* Control register1 initial value */35#define MLX90635_EE_CTRL2 0x001C /* Control register2 initial value */36 37#define MLX90635_EE_Ha 0x001E /* Ha customer calib value reg 16bit */38#define MLX90635_EE_Hb 0x0020 /* Hb customer calib value reg 16bit */39#define MLX90635_EE_Fa 0x0026 /* Fa calibration register 32bit */40#define MLX90635_EE_FASCALE 0x002A /* Scaling coefficient for Fa register 16bit */41#define MLX90635_EE_Ga 0x002C /* Ga calibration register 16bit */42#define MLX90635_EE_Fb 0x002E /* Fb calibration register 16bit */43#define MLX90635_EE_Ea 0x0030 /* Ea calibration register 32bit */44#define MLX90635_EE_Eb 0x0034 /* Eb calibration register 32bit */45#define MLX90635_EE_P_G 0x0038 /* P_G calibration register 16bit */46#define MLX90635_EE_P_O 0x003A /* P_O calibration register 16bit */47#define MLX90635_EE_Aa 0x003C /* Aa calibration register 16bit */48#define MLX90635_EE_VERSION 0x003E /* Version bits 4:7 and 12:15 */49#define MLX90635_EE_Gb 0x0040 /* Gb calibration register 16bit */50 51/* Device status register - volatile */52#define MLX90635_REG_STATUS 0x000053#define MLX90635_STAT_BUSY BIT(6) /* Device busy indicator */54#define MLX90635_STAT_BRST BIT(5) /* Brown out reset indicator */55#define MLX90635_STAT_CYCLE_POS GENMASK(4, 2) /* Data position */56#define MLX90635_STAT_END_CONV BIT(1) /* End of conversion indicator */57#define MLX90635_STAT_DATA_RDY BIT(0) /* Data ready indicator */58 59/* EEPROM control register address - volatile */60#define MLX90635_REG_EE 0x000C61#define MLX90635_EE_ACTIVE BIT(4) /* Power-on EEPROM */62#define MLX90635_EE_BUSY_MASK BIT(15)63 64#define MLX90635_REG_CMD 0x0010 /* Command register address */65 66/* Control register1 address - volatile */67#define MLX90635_REG_CTRL1 0x001468#define MLX90635_CTRL1_REFRESH_RATE_MASK GENMASK(2, 0)69#define MLX90635_CTRL1_RES_CTRL_MASK GENMASK(4, 3)70#define MLX90635_CTRL1_TABLE_MASK BIT(15) /* Table select */71 72/* Control register2 address - volatile */73#define MLX90635_REG_CTRL2 0x001674#define MLX90635_CTRL2_BURST_CNT_MASK GENMASK(10, 6) /* Burst count */75#define MLX90635_CTRL2_MODE_MASK GENMASK(12, 11) /* Power mode */76#define MLX90635_CTRL2_SOB_MASK BIT(15)77 78/* PowerModes statuses */79#define MLX90635_PWR_STATUS_HALT 080#define MLX90635_PWR_STATUS_SLEEP_STEP 181#define MLX90635_PWR_STATUS_STEP 282#define MLX90635_PWR_STATUS_CONTINUOUS 383 84/* Measurement data addresses */85#define MLX90635_RESULT_1 0x000286#define MLX90635_RESULT_2 0x000487#define MLX90635_RESULT_3 0x000688#define MLX90635_RESULT_4 0x000889#define MLX90635_RESULT_5 0x000A90 91/* Timings (ms) */92#define MLX90635_TIMING_RST_MIN 200 /* Minimum time after addressed reset command */93#define MLX90635_TIMING_RST_MAX 250 /* Maximum time after addressed reset command */94#define MLX90635_TIMING_POLLING 10000 /* Time between bit polling*/95#define MLX90635_TIMING_EE_ACTIVE_MIN 100 /* Minimum time after activating the EEPROM for read */96#define MLX90635_TIMING_EE_ACTIVE_MAX 150 /* Maximum time after activating the EEPROM for read */97 98/* Magic constants */99#define MLX90635_ID_DSPv1 0x01 /* EEPROM DSP version */100#define MLX90635_RESET_CMD 0x0006 /* Reset sensor (address or global) */101#define MLX90635_MAX_MEAS_NUM 31 /* Maximum number of measurements in list */102#define MLX90635_PTAT_DIV 12 /* Used to divide the PTAT value in pre-processing */103#define MLX90635_IR_DIV 24 /* Used to divide the IR value in pre-processing */104#define MLX90635_SLEEP_DELAY_MS 6000 /* Autosleep delay */105#define MLX90635_MEAS_MAX_TIME 2000 /* Max measurement time in ms for the lowest refresh rate */106#define MLX90635_READ_RETRIES 100 /* Number of read retries before quitting with timeout error */107#define MLX90635_VERSION_MASK (GENMASK(15, 12) | GENMASK(7, 4))108#define MLX90635_DSP_VERSION(reg) (((reg & GENMASK(14, 12)) >> 9) | ((reg & GENMASK(6, 4)) >> 4))109#define MLX90635_DSP_FIXED BIT(15)110 111 112/**113 * struct mlx90635_data - private data for the MLX90635 device114 * @client: I2C client of the device115 * @lock: Internal mutex because multiple reads are needed for single triggered116 * measurement to ensure data consistency117 * @regmap: Regmap of the device registers118 * @regmap_ee: Regmap of the device EEPROM which can be cached119 * @emissivity: Object emissivity from 0 to 1000 where 1000 = 1120 * @regulator: Regulator of the device121 * @powerstatus: Current POWER status of the device122 * @interaction_ts: Timestamp of the last temperature read that is used123 * for power management in jiffies124 */125struct mlx90635_data {126 struct i2c_client *client;127 struct mutex lock;128 struct regmap *regmap;129 struct regmap *regmap_ee;130 u16 emissivity;131 struct regulator *regulator;132 int powerstatus;133 unsigned long interaction_ts;134};135 136static const struct regmap_range mlx90635_volatile_reg_range[] = {137 regmap_reg_range(MLX90635_REG_STATUS, MLX90635_REG_STATUS),138 regmap_reg_range(MLX90635_RESULT_1, MLX90635_RESULT_5),139 regmap_reg_range(MLX90635_REG_EE, MLX90635_REG_EE),140 regmap_reg_range(MLX90635_REG_CMD, MLX90635_REG_CMD),141 regmap_reg_range(MLX90635_REG_CTRL1, MLX90635_REG_CTRL2),142};143 144static const struct regmap_access_table mlx90635_volatile_regs_tbl = {145 .yes_ranges = mlx90635_volatile_reg_range,146 .n_yes_ranges = ARRAY_SIZE(mlx90635_volatile_reg_range),147};148 149static const struct regmap_range mlx90635_read_reg_range[] = {150 regmap_reg_range(MLX90635_REG_STATUS, MLX90635_REG_STATUS),151 regmap_reg_range(MLX90635_RESULT_1, MLX90635_RESULT_5),152 regmap_reg_range(MLX90635_REG_EE, MLX90635_REG_EE),153 regmap_reg_range(MLX90635_REG_CMD, MLX90635_REG_CMD),154 regmap_reg_range(MLX90635_REG_CTRL1, MLX90635_REG_CTRL2),155};156 157static const struct regmap_access_table mlx90635_readable_regs_tbl = {158 .yes_ranges = mlx90635_read_reg_range,159 .n_yes_ranges = ARRAY_SIZE(mlx90635_read_reg_range),160};161 162static const struct regmap_range mlx90635_no_write_reg_range[] = {163 regmap_reg_range(MLX90635_RESULT_1, MLX90635_RESULT_5),164};165 166static const struct regmap_access_table mlx90635_writeable_regs_tbl = {167 .no_ranges = mlx90635_no_write_reg_range,168 .n_no_ranges = ARRAY_SIZE(mlx90635_no_write_reg_range),169};170 171static const struct regmap_config mlx90635_regmap = {172 .name = "mlx90635-registers",173 .reg_stride = 1,174 .reg_bits = 16,175 .val_bits = 16,176 177 .volatile_table = &mlx90635_volatile_regs_tbl,178 .rd_table = &mlx90635_readable_regs_tbl,179 .wr_table = &mlx90635_writeable_regs_tbl,180 181 .use_single_read = true,182 .use_single_write = true,183 .can_multi_write = false,184 .reg_format_endian = REGMAP_ENDIAN_BIG,185 .val_format_endian = REGMAP_ENDIAN_BIG,186 .cache_type = REGCACHE_RBTREE,187};188 189static const struct regmap_range mlx90635_read_ee_range[] = {190 regmap_reg_range(MLX90635_EE_I2C_CFG, MLX90635_EE_CTRL2),191 regmap_reg_range(MLX90635_EE_Ha, MLX90635_EE_Gb),192};193 194static const struct regmap_access_table mlx90635_readable_ees_tbl = {195 .yes_ranges = mlx90635_read_ee_range,196 .n_yes_ranges = ARRAY_SIZE(mlx90635_read_ee_range),197};198 199static const struct regmap_range mlx90635_no_write_ee_range[] = {200 regmap_reg_range(MLX90635_ADDR_EEPROM, MLX90635_EE_Gb),201};202 203static const struct regmap_access_table mlx90635_writeable_ees_tbl = {204 .no_ranges = mlx90635_no_write_ee_range,205 .n_no_ranges = ARRAY_SIZE(mlx90635_no_write_ee_range),206};207 208static const struct regmap_config mlx90635_regmap_ee = {209 .name = "mlx90635-eeprom",210 .reg_stride = 1,211 .reg_bits = 16,212 .val_bits = 16,213 214 .volatile_table = NULL,215 .rd_table = &mlx90635_readable_ees_tbl,216 .wr_table = &mlx90635_writeable_ees_tbl,217 218 .use_single_read = true,219 .use_single_write = true,220 .can_multi_write = false,221 .reg_format_endian = REGMAP_ENDIAN_BIG,222 .val_format_endian = REGMAP_ENDIAN_BIG,223 .cache_type = REGCACHE_RBTREE,224};225 226/**227 * mlx90635_reset_delay() - Give the mlx90635 some time to reset properly228 * If this is not done, the following I2C command(s) will not be accepted.229 */230static void mlx90635_reset_delay(void)231{232 usleep_range(MLX90635_TIMING_RST_MIN, MLX90635_TIMING_RST_MAX);233}234 235static int mlx90635_pwr_sleep_step(struct mlx90635_data *data)236{237 int ret;238 239 if (data->powerstatus == MLX90635_PWR_STATUS_SLEEP_STEP)240 return 0;241 242 ret = regmap_write_bits(data->regmap, MLX90635_REG_CTRL2, MLX90635_CTRL2_MODE_MASK,243 FIELD_PREP(MLX90635_CTRL2_MODE_MASK, MLX90635_PWR_STATUS_SLEEP_STEP));244 if (ret < 0)245 return ret;246 247 data->powerstatus = MLX90635_PWR_STATUS_SLEEP_STEP;248 return 0;249}250 251static int mlx90635_pwr_continuous(struct mlx90635_data *data)252{253 int ret;254 255 if (data->powerstatus == MLX90635_PWR_STATUS_CONTINUOUS)256 return 0;257 258 ret = regmap_write_bits(data->regmap, MLX90635_REG_CTRL2, MLX90635_CTRL2_MODE_MASK,259 FIELD_PREP(MLX90635_CTRL2_MODE_MASK, MLX90635_PWR_STATUS_CONTINUOUS));260 if (ret < 0)261 return ret;262 263 data->powerstatus = MLX90635_PWR_STATUS_CONTINUOUS;264 return 0;265}266 267static int mlx90635_read_ee_register(struct regmap *regmap, u16 reg_lsb,268 s32 *reg_value)269{270 unsigned int read;271 u32 value;272 int ret;273 274 ret = regmap_read(regmap, reg_lsb + 2, &read);275 if (ret < 0)276 return ret;277 278 value = read;279 280 ret = regmap_read(regmap, reg_lsb, &read);281 if (ret < 0)282 return ret;283 284 *reg_value = (read << 16) | (value & 0xffff);285 286 return 0;287}288 289static int mlx90635_read_ee_ambient(struct regmap *regmap, s16 *PG, s16 *PO, s16 *Gb)290{291 unsigned int read_tmp;292 int ret;293 294 ret = regmap_read(regmap, MLX90635_EE_P_O, &read_tmp);295 if (ret < 0)296 return ret;297 *PO = (s16)read_tmp;298 299 ret = regmap_read(regmap, MLX90635_EE_P_G, &read_tmp);300 if (ret < 0)301 return ret;302 *PG = (s16)read_tmp;303 304 ret = regmap_read(regmap, MLX90635_EE_Gb, &read_tmp);305 if (ret < 0)306 return ret;307 *Gb = (u16)read_tmp;308 309 return 0;310}311 312static int mlx90635_read_ee_object(struct regmap *regmap, u32 *Ea, u32 *Eb, u32 *Fa, s16 *Fb,313 s16 *Ga, s16 *Gb, s16 *Ha, s16 *Hb, u16 *Fa_scale)314{315 unsigned int read_tmp;316 int ret;317 318 ret = mlx90635_read_ee_register(regmap, MLX90635_EE_Ea, Ea);319 if (ret < 0)320 return ret;321 322 ret = mlx90635_read_ee_register(regmap, MLX90635_EE_Eb, Eb);323 if (ret < 0)324 return ret;325 326 ret = mlx90635_read_ee_register(regmap, MLX90635_EE_Fa, Fa);327 if (ret < 0)328 return ret;329 330 ret = regmap_read(regmap, MLX90635_EE_Ha, &read_tmp);331 if (ret < 0)332 return ret;333 *Ha = (s16)read_tmp;334 335 ret = regmap_read(regmap, MLX90635_EE_Hb, &read_tmp);336 if (ret < 0)337 return ret;338 *Hb = (s16)read_tmp;339 340 ret = regmap_read(regmap, MLX90635_EE_Ga, &read_tmp);341 if (ret < 0)342 return ret;343 *Ga = (s16)read_tmp;344 345 ret = regmap_read(regmap, MLX90635_EE_Gb, &read_tmp);346 if (ret < 0)347 return ret;348 *Gb = (s16)read_tmp;349 350 ret = regmap_read(regmap, MLX90635_EE_Fb, &read_tmp);351 if (ret < 0)352 return ret;353 *Fb = (s16)read_tmp;354 355 ret = regmap_read(regmap, MLX90635_EE_FASCALE, &read_tmp);356 if (ret < 0)357 return ret;358 *Fa_scale = (u16)read_tmp;359 360 return 0;361}362 363static int mlx90635_calculate_dataset_ready_time(struct mlx90635_data *data, int *refresh_time)364{365 unsigned int reg;366 int ret;367 368 ret = regmap_read(data->regmap, MLX90635_REG_CTRL1, ®);369 if (ret < 0)370 return ret;371 372 *refresh_time = 2 * (MLX90635_MEAS_MAX_TIME >> FIELD_GET(MLX90635_CTRL1_REFRESH_RATE_MASK, reg)) + 80;373 374 return 0;375}376 377static int mlx90635_perform_measurement_burst(struct mlx90635_data *data)378{379 unsigned int reg_status;380 int refresh_time;381 int ret;382 383 ret = regmap_write_bits(data->regmap, MLX90635_REG_STATUS,384 MLX90635_STAT_END_CONV, MLX90635_STAT_END_CONV);385 if (ret < 0)386 return ret;387 388 ret = mlx90635_calculate_dataset_ready_time(data, &refresh_time);389 if (ret < 0)390 return ret;391 392 ret = regmap_write_bits(data->regmap, MLX90635_REG_CTRL2,393 FIELD_PREP(MLX90635_CTRL2_SOB_MASK, 1),394 FIELD_PREP(MLX90635_CTRL2_SOB_MASK, 1));395 if (ret < 0)396 return ret;397 398 msleep(refresh_time); /* Wait minimum time for dataset to be ready */399 400 ret = regmap_read_poll_timeout(data->regmap, MLX90635_REG_STATUS, reg_status,401 (!(reg_status & MLX90635_STAT_END_CONV)) == 0,402 MLX90635_TIMING_POLLING, MLX90635_READ_RETRIES * 10000);403 if (ret < 0) {404 dev_err(&data->client->dev, "data not ready");405 return -ETIMEDOUT;406 }407 408 return 0;409}410 411static int mlx90635_read_ambient_raw(struct regmap *regmap,412 s16 *ambient_new_raw, s16 *ambient_old_raw)413{414 unsigned int read_tmp;415 int ret;416 417 ret = regmap_read(regmap, MLX90635_RESULT_2, &read_tmp);418 if (ret < 0)419 return ret;420 *ambient_new_raw = (s16)read_tmp;421 422 ret = regmap_read(regmap, MLX90635_RESULT_3, &read_tmp);423 if (ret < 0)424 return ret;425 *ambient_old_raw = (s16)read_tmp;426 427 return 0;428}429 430static int mlx90635_read_object_raw(struct regmap *regmap, s16 *object_raw)431{432 unsigned int read_tmp;433 s16 read;434 int ret;435 436 ret = regmap_read(regmap, MLX90635_RESULT_1, &read_tmp);437 if (ret < 0)438 return ret;439 440 read = (s16)read_tmp;441 442 ret = regmap_read(regmap, MLX90635_RESULT_4, &read_tmp);443 if (ret < 0)444 return ret;445 *object_raw = (read - (s16)read_tmp) / 2;446 447 return 0;448}449 450static int mlx90635_read_all_channel(struct mlx90635_data *data,451 s16 *ambient_new_raw, s16 *ambient_old_raw,452 s16 *object_raw)453{454 int ret;455 456 mutex_lock(&data->lock);457 if (data->powerstatus == MLX90635_PWR_STATUS_SLEEP_STEP) {458 /* Trigger measurement in Sleep Step mode */459 ret = mlx90635_perform_measurement_burst(data);460 if (ret < 0)461 goto read_unlock;462 }463 464 ret = mlx90635_read_ambient_raw(data->regmap, ambient_new_raw,465 ambient_old_raw);466 if (ret < 0)467 goto read_unlock;468 469 ret = mlx90635_read_object_raw(data->regmap, object_raw);470read_unlock:471 mutex_unlock(&data->lock);472 return ret;473}474 475static s64 mlx90635_preprocess_temp_amb(s16 ambient_new_raw,476 s16 ambient_old_raw, s16 Gb)477{478 s64 VR_Ta, kGb, tmp;479 480 kGb = ((s64)Gb * 1000LL) >> 10ULL;481 VR_Ta = (s64)ambient_old_raw * 1000000LL +482 kGb * div64_s64(((s64)ambient_new_raw * 1000LL),483 (MLX90635_PTAT_DIV));484 tmp = div64_s64(485 div64_s64(((s64)ambient_new_raw * 1000000000000LL),486 (MLX90635_PTAT_DIV)), VR_Ta);487 return div64_s64(tmp << 19ULL, 1000LL);488}489 490static s64 mlx90635_preprocess_temp_obj(s16 object_raw,491 s16 ambient_new_raw,492 s16 ambient_old_raw, s16 Gb)493{494 s64 VR_IR, kGb, tmp;495 496 kGb = ((s64)Gb * 1000LL) >> 10ULL;497 VR_IR = (s64)ambient_old_raw * 1000000LL +498 kGb * (div64_s64((s64)ambient_new_raw * 1000LL,499 MLX90635_PTAT_DIV));500 tmp = div64_s64(501 div64_s64((s64)(object_raw * 1000000LL),502 MLX90635_IR_DIV) * 1000000LL,503 VR_IR);504 return div64_s64((tmp << 19ULL), 1000LL);505}506 507static s32 mlx90635_calc_temp_ambient(s16 ambient_new_raw, s16 ambient_old_raw,508 u16 P_G, u16 P_O, s16 Gb)509{510 s64 kPG, kPO, AMB;511 512 AMB = mlx90635_preprocess_temp_amb(ambient_new_raw, ambient_old_raw,513 Gb);514 kPG = ((s64)P_G * 1000000LL) >> 9ULL;515 kPO = AMB - (((s64)P_O * 1000LL) >> 1ULL);516 517 return 30 * 1000LL + div64_s64(kPO * 1000000LL, kPG);518}519 520static s32 mlx90635_calc_temp_object_iteration(s32 prev_object_temp, s64 object,521 s64 TAdut, s64 TAdut4, s16 Ga,522 u32 Fa, u16 Fa_scale, s16 Fb,523 s16 Ha, s16 Hb, u16 emissivity)524{525 s64 calcedGa, calcedGb, calcedFa, Alpha_corr;526 s64 Ha_customer, Hb_customer;527 528 Ha_customer = ((s64)Ha * 1000000LL) >> 14ULL;529 Hb_customer = ((s64)Hb * 100) >> 10ULL;530 531 calcedGa = ((s64)((s64)Ga * (prev_object_temp - 35 * 1000LL)532 * 1000LL)) >> 24LL;533 calcedGb = ((s64)(Fb * (TAdut - 30 * 1000000LL))) >> 24LL;534 535 Alpha_corr = ((s64)((s64)Fa * Ha_customer * 10000LL) >> Fa_scale);536 Alpha_corr *= ((s64)(1 * 1000000LL + calcedGa + calcedGb));537 538 Alpha_corr = div64_s64(Alpha_corr, 1000LL);539 Alpha_corr *= emissivity;540 Alpha_corr = div64_s64(Alpha_corr, 100LL);541 calcedFa = div64_s64((s64)object * 100000000000LL, Alpha_corr);542 543 return (int_sqrt64(int_sqrt64(calcedFa * 100000000LL + TAdut4))544 - 27315 - Hb_customer) * 10;545}546 547static s64 mlx90635_calc_ta4(s64 TAdut, s64 scale)548{549 return (div64_s64(TAdut, scale) + 27315) *550 (div64_s64(TAdut, scale) + 27315) *551 (div64_s64(TAdut, scale) + 27315) *552 (div64_s64(TAdut, scale) + 27315);553}554 555static s32 mlx90635_calc_temp_object(s64 object, s64 ambient, u32 Ea, u32 Eb,556 s16 Ga, u32 Fa, u16 Fa_scale, s16 Fb, s16 Ha, s16 Hb,557 u16 tmp_emi)558{559 s64 kTA, kTA0, TAdut, TAdut4;560 s64 temp = 35000;561 s8 i;562 563 kTA = (Ea * 1000LL) >> 16LL;564 kTA0 = (Eb * 1000LL) >> 8LL;565 TAdut = div64_s64(((ambient - kTA0) * 1000000LL), kTA) + 30 * 1000000LL;566 TAdut4 = mlx90635_calc_ta4(TAdut, 10000LL);567 568 /* Iterations of calculation as described in datasheet */569 for (i = 0; i < 5; ++i) {570 temp = mlx90635_calc_temp_object_iteration(temp, object, TAdut, TAdut4,571 Ga, Fa, Fa_scale, Fb, Ha, Hb,572 tmp_emi);573 }574 return temp;575}576 577static int mlx90635_calc_object(struct mlx90635_data *data, int *val)578{579 s16 ambient_new_raw, ambient_old_raw, object_raw;580 s16 Fb, Ga, Gb, Ha, Hb;581 s64 object, ambient;582 u32 Ea, Eb, Fa;583 u16 Fa_scale;584 int ret;585 586 ret = mlx90635_read_ee_object(data->regmap_ee, &Ea, &Eb, &Fa, &Fb, &Ga, &Gb, &Ha, &Hb, &Fa_scale);587 if (ret < 0)588 return ret;589 590 ret = mlx90635_read_all_channel(data,591 &ambient_new_raw, &ambient_old_raw,592 &object_raw);593 if (ret < 0)594 return ret;595 596 ambient = mlx90635_preprocess_temp_amb(ambient_new_raw,597 ambient_old_raw, Gb);598 object = mlx90635_preprocess_temp_obj(object_raw,599 ambient_new_raw,600 ambient_old_raw, Gb);601 602 *val = mlx90635_calc_temp_object(object, ambient, Ea, Eb, Ga, Fa, Fa_scale, Fb,603 Ha, Hb, data->emissivity);604 return 0;605}606 607static int mlx90635_calc_ambient(struct mlx90635_data *data, int *val)608{609 s16 ambient_new_raw, ambient_old_raw;610 s16 PG, PO, Gb;611 int ret;612 613 ret = mlx90635_read_ee_ambient(data->regmap_ee, &PG, &PO, &Gb);614 if (ret < 0)615 return ret;616 617 mutex_lock(&data->lock);618 if (data->powerstatus == MLX90635_PWR_STATUS_SLEEP_STEP) {619 ret = mlx90635_perform_measurement_burst(data);620 if (ret < 0)621 goto read_ambient_unlock;622 }623 624 ret = mlx90635_read_ambient_raw(data->regmap, &ambient_new_raw,625 &ambient_old_raw);626read_ambient_unlock:627 mutex_unlock(&data->lock);628 if (ret < 0)629 return ret;630 631 *val = mlx90635_calc_temp_ambient(ambient_new_raw, ambient_old_raw,632 PG, PO, Gb);633 return ret;634}635 636static int mlx90635_get_refresh_rate(struct mlx90635_data *data,637 unsigned int *refresh_rate)638{639 unsigned int reg;640 int ret;641 642 ret = regmap_read(data->regmap, MLX90635_REG_CTRL1, ®);643 if (ret < 0)644 return ret;645 646 *refresh_rate = FIELD_GET(MLX90635_CTRL1_REFRESH_RATE_MASK, reg);647 648 return 0;649}650 651static const struct {652 int val;653 int val2;654} mlx90635_freqs[] = {655 { 0, 200000 },656 { 0, 500000 },657 { 0, 900000 },658 { 1, 700000 },659 { 3, 0 },660 { 4, 800000 },661 { 6, 900000 },662 { 8, 900000 }663};664 665/**666 * mlx90635_pm_interaction_wakeup() - Measure time between user interactions to change powermode667 * @data: pointer to mlx90635_data object containing interaction_ts information668 *669 * Switch to continuous mode when interaction is faster than MLX90635_MEAS_MAX_TIME. Update the670 * interaction_ts for each function call with the jiffies to enable measurement between function671 * calls. Initial value of the interaction_ts needs to be set before this function call.672 */673static int mlx90635_pm_interaction_wakeup(struct mlx90635_data *data)674{675 unsigned long now;676 int ret;677 678 now = jiffies;679 if (time_in_range(now, data->interaction_ts,680 data->interaction_ts +681 msecs_to_jiffies(MLX90635_MEAS_MAX_TIME + 100))) {682 ret = mlx90635_pwr_continuous(data);683 if (ret < 0)684 return ret;685 }686 687 data->interaction_ts = now;688 689 return 0;690}691 692static int mlx90635_read_raw(struct iio_dev *indio_dev,693 struct iio_chan_spec const *channel, int *val,694 int *val2, long mask)695{696 struct mlx90635_data *data = iio_priv(indio_dev);697 int ret;698 int cr;699 700 pm_runtime_get_sync(&data->client->dev);701 ret = mlx90635_pm_interaction_wakeup(data);702 if (ret < 0)703 goto mlx90635_read_raw_pm;704 705 switch (mask) {706 case IIO_CHAN_INFO_PROCESSED:707 switch (channel->channel2) {708 case IIO_MOD_TEMP_AMBIENT:709 ret = mlx90635_calc_ambient(data, val);710 if (ret < 0)711 goto mlx90635_read_raw_pm;712 713 ret = IIO_VAL_INT;714 break;715 case IIO_MOD_TEMP_OBJECT:716 ret = mlx90635_calc_object(data, val);717 if (ret < 0)718 goto mlx90635_read_raw_pm;719 720 ret = IIO_VAL_INT;721 break;722 default:723 ret = -EINVAL;724 break;725 }726 break;727 case IIO_CHAN_INFO_CALIBEMISSIVITY:728 if (data->emissivity == 1000) {729 *val = 1;730 *val2 = 0;731 } else {732 *val = 0;733 *val2 = data->emissivity * 1000;734 }735 ret = IIO_VAL_INT_PLUS_MICRO;736 break;737 case IIO_CHAN_INFO_SAMP_FREQ:738 ret = mlx90635_get_refresh_rate(data, &cr);739 if (ret < 0)740 goto mlx90635_read_raw_pm;741 742 *val = mlx90635_freqs[cr].val;743 *val2 = mlx90635_freqs[cr].val2;744 ret = IIO_VAL_INT_PLUS_MICRO;745 break;746 default:747 ret = -EINVAL;748 break;749 }750 751mlx90635_read_raw_pm:752 pm_runtime_mark_last_busy(&data->client->dev);753 pm_runtime_put_autosuspend(&data->client->dev);754 return ret;755}756 757static int mlx90635_write_raw(struct iio_dev *indio_dev,758 struct iio_chan_spec const *channel, int val,759 int val2, long mask)760{761 struct mlx90635_data *data = iio_priv(indio_dev);762 int ret;763 int i;764 765 switch (mask) {766 case IIO_CHAN_INFO_CALIBEMISSIVITY:767 /* Confirm we are within 0 and 1.0 */768 if (val < 0 || val2 < 0 || val > 1 ||769 (val == 1 && val2 != 0))770 return -EINVAL;771 data->emissivity = val * 1000 + val2 / 1000;772 return 0;773 case IIO_CHAN_INFO_SAMP_FREQ:774 for (i = 0; i < ARRAY_SIZE(mlx90635_freqs); i++) {775 if (val == mlx90635_freqs[i].val &&776 val2 == mlx90635_freqs[i].val2)777 break;778 }779 if (i == ARRAY_SIZE(mlx90635_freqs))780 return -EINVAL;781 782 ret = regmap_write_bits(data->regmap, MLX90635_REG_CTRL1,783 MLX90635_CTRL1_REFRESH_RATE_MASK, i);784 785 return ret;786 default:787 return -EINVAL;788 }789}790 791static int mlx90635_read_avail(struct iio_dev *indio_dev,792 struct iio_chan_spec const *chan,793 const int **vals, int *type, int *length,794 long mask)795{796 switch (mask) {797 case IIO_CHAN_INFO_SAMP_FREQ:798 *vals = (int *)mlx90635_freqs;799 *type = IIO_VAL_INT_PLUS_MICRO;800 *length = 2 * ARRAY_SIZE(mlx90635_freqs);801 return IIO_AVAIL_LIST;802 default:803 return -EINVAL;804 }805}806 807static const struct iio_chan_spec mlx90635_channels[] = {808 {809 .type = IIO_TEMP,810 .modified = 1,811 .channel2 = IIO_MOD_TEMP_AMBIENT,812 .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED),813 .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ),814 .info_mask_shared_by_all_available = BIT(IIO_CHAN_INFO_SAMP_FREQ),815 },816 {817 .type = IIO_TEMP,818 .modified = 1,819 .channel2 = IIO_MOD_TEMP_OBJECT,820 .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED) |821 BIT(IIO_CHAN_INFO_CALIBEMISSIVITY),822 .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ),823 .info_mask_shared_by_all_available = BIT(IIO_CHAN_INFO_SAMP_FREQ),824 },825};826 827static const struct iio_info mlx90635_info = {828 .read_raw = mlx90635_read_raw,829 .write_raw = mlx90635_write_raw,830 .read_avail = mlx90635_read_avail,831};832 833static void mlx90635_sleep(void *_data)834{835 struct mlx90635_data *data = _data;836 837 mlx90635_pwr_sleep_step(data);838}839 840static int mlx90635_suspend(struct mlx90635_data *data)841{842 return mlx90635_pwr_sleep_step(data);843}844 845static int mlx90635_wakeup(struct mlx90635_data *data)846{847 s16 Fb, Ga, Gb, Ha, Hb, PG, PO;848 unsigned int dsp_version;849 u32 Ea, Eb, Fa;850 u16 Fa_scale;851 int ret;852 853 regcache_cache_bypass(data->regmap_ee, false);854 regcache_cache_only(data->regmap_ee, false);855 regcache_cache_only(data->regmap, false);856 857 ret = mlx90635_pwr_continuous(data);858 if (ret < 0) {859 dev_err(&data->client->dev, "Switch to continuous mode failed\n");860 return ret;861 }862 ret = regmap_write_bits(data->regmap, MLX90635_REG_EE,863 MLX90635_EE_ACTIVE, MLX90635_EE_ACTIVE);864 if (ret < 0) {865 dev_err(&data->client->dev, "Powering EEPROM failed\n");866 return ret;867 }868 usleep_range(MLX90635_TIMING_EE_ACTIVE_MIN, MLX90635_TIMING_EE_ACTIVE_MAX);869 870 regcache_mark_dirty(data->regmap_ee);871 872 ret = regcache_sync(data->regmap_ee);873 if (ret < 0) {874 dev_err(&data->client->dev,875 "Failed to sync cache: %d\n", ret);876 return ret;877 }878 879 ret = mlx90635_read_ee_ambient(data->regmap_ee, &PG, &PO, &Gb);880 if (ret < 0) {881 dev_err(&data->client->dev,882 "Failed to read to cache Ambient coefficients EEPROM region: %d\n", ret);883 return ret;884 }885 886 ret = mlx90635_read_ee_object(data->regmap_ee, &Ea, &Eb, &Fa, &Fb, &Ga, &Gb, &Ha, &Hb, &Fa_scale);887 if (ret < 0) {888 dev_err(&data->client->dev,889 "Failed to read to cache Object coefficients EEPROM region: %d\n", ret);890 return ret;891 }892 893 ret = regmap_read(data->regmap_ee, MLX90635_EE_VERSION, &dsp_version);894 if (ret < 0) {895 dev_err(&data->client->dev,896 "Failed to read to cache of EEPROM version: %d\n", ret);897 return ret;898 }899 900 regcache_cache_only(data->regmap_ee, true);901 902 return ret;903}904 905static void mlx90635_disable_regulator(void *_data)906{907 struct mlx90635_data *data = _data;908 int ret;909 910 ret = regulator_disable(data->regulator);911 if (ret < 0)912 dev_err(regmap_get_device(data->regmap),913 "Failed to disable power regulator: %d\n", ret);914}915 916static int mlx90635_enable_regulator(struct mlx90635_data *data)917{918 int ret;919 920 ret = regulator_enable(data->regulator);921 if (ret < 0) {922 dev_err(regmap_get_device(data->regmap), "Failed to enable power regulator!\n");923 return ret;924 }925 926 mlx90635_reset_delay();927 928 return ret;929}930 931static int mlx90635_probe(struct i2c_client *client)932{933 struct mlx90635_data *mlx90635;934 struct iio_dev *indio_dev;935 unsigned int dsp_version;936 struct regmap *regmap;937 struct regmap *regmap_ee;938 int ret;939 940 indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*mlx90635));941 if (!indio_dev)942 return dev_err_probe(&client->dev, -ENOMEM, "failed to allocate device\n");943 944 regmap = devm_regmap_init_i2c(client, &mlx90635_regmap);945 if (IS_ERR(regmap))946 return dev_err_probe(&client->dev, PTR_ERR(regmap),947 "failed to allocate regmap\n");948 949 regmap_ee = devm_regmap_init_i2c(client, &mlx90635_regmap_ee);950 if (IS_ERR(regmap_ee))951 return dev_err_probe(&client->dev, PTR_ERR(regmap_ee),952 "failed to allocate EEPROM regmap\n");953 954 mlx90635 = iio_priv(indio_dev);955 i2c_set_clientdata(client, indio_dev);956 mlx90635->client = client;957 mlx90635->regmap = regmap;958 mlx90635->regmap_ee = regmap_ee;959 mlx90635->powerstatus = MLX90635_PWR_STATUS_SLEEP_STEP;960 961 mutex_init(&mlx90635->lock);962 indio_dev->name = "mlx90635";963 indio_dev->modes = INDIO_DIRECT_MODE;964 indio_dev->info = &mlx90635_info;965 indio_dev->channels = mlx90635_channels;966 indio_dev->num_channels = ARRAY_SIZE(mlx90635_channels);967 968 mlx90635->regulator = devm_regulator_get(&client->dev, "vdd");969 if (IS_ERR(mlx90635->regulator))970 return dev_err_probe(&client->dev, PTR_ERR(mlx90635->regulator),971 "failed to get vdd regulator");972 973 ret = mlx90635_enable_regulator(mlx90635);974 if (ret < 0)975 return ret;976 977 ret = devm_add_action_or_reset(&client->dev, mlx90635_disable_regulator,978 mlx90635);979 if (ret < 0)980 return dev_err_probe(&client->dev, ret,981 "failed to setup regulator cleanup action\n");982 983 ret = mlx90635_wakeup(mlx90635);984 if (ret < 0)985 return dev_err_probe(&client->dev, ret, "wakeup failed\n");986 987 ret = devm_add_action_or_reset(&client->dev, mlx90635_sleep, mlx90635);988 if (ret < 0)989 return dev_err_probe(&client->dev, ret,990 "failed to setup low power cleanup\n");991 992 ret = regmap_read(mlx90635->regmap_ee, MLX90635_EE_VERSION, &dsp_version);993 if (ret < 0)994 return dev_err_probe(&client->dev, ret, "read of version failed\n");995 996 dsp_version = dsp_version & MLX90635_VERSION_MASK;997 998 if (FIELD_GET(MLX90635_DSP_FIXED, dsp_version)) {999 if (MLX90635_DSP_VERSION(dsp_version) == MLX90635_ID_DSPv1) {1000 dev_dbg(&client->dev,1001 "Detected DSP v1 calibration %x\n", dsp_version);1002 } else {1003 dev_dbg(&client->dev,1004 "Detected Unknown EEPROM calibration %lx\n",1005 MLX90635_DSP_VERSION(dsp_version));1006 }1007 } else {1008 return dev_err_probe(&client->dev, -EPROTONOSUPPORT,1009 "Wrong fixed top bit %x (expected 0x8X0X)\n",1010 dsp_version);1011 }1012 1013 mlx90635->emissivity = 1000;1014 mlx90635->interaction_ts = jiffies; /* Set initial value */1015 1016 pm_runtime_get_noresume(&client->dev);1017 pm_runtime_set_active(&client->dev);1018 1019 ret = devm_pm_runtime_enable(&client->dev);1020 if (ret)1021 return dev_err_probe(&client->dev, ret,1022 "failed to enable powermanagement\n");1023 1024 pm_runtime_set_autosuspend_delay(&client->dev, MLX90635_SLEEP_DELAY_MS);1025 pm_runtime_use_autosuspend(&client->dev);1026 pm_runtime_put_autosuspend(&client->dev);1027 1028 return devm_iio_device_register(&client->dev, indio_dev);1029}1030 1031static const struct i2c_device_id mlx90635_id[] = {1032 { "mlx90635" },1033 { }1034};1035MODULE_DEVICE_TABLE(i2c, mlx90635_id);1036 1037static const struct of_device_id mlx90635_of_match[] = {1038 { .compatible = "melexis,mlx90635" },1039 { }1040};1041MODULE_DEVICE_TABLE(of, mlx90635_of_match);1042 1043static int mlx90635_pm_suspend(struct device *dev)1044{1045 struct mlx90635_data *data = iio_priv(dev_get_drvdata(dev));1046 int ret;1047 1048 ret = mlx90635_suspend(data);1049 if (ret < 0)1050 return ret;1051 1052 ret = regulator_disable(data->regulator);1053 if (ret < 0)1054 dev_err(regmap_get_device(data->regmap),1055 "Failed to disable power regulator: %d\n", ret);1056 1057 return ret;1058}1059 1060static int mlx90635_pm_resume(struct device *dev)1061{1062 struct mlx90635_data *data = iio_priv(dev_get_drvdata(dev));1063 int ret;1064 1065 ret = mlx90635_enable_regulator(data);1066 if (ret < 0)1067 return ret;1068 1069 return mlx90635_wakeup(data);1070}1071 1072static int mlx90635_pm_runtime_suspend(struct device *dev)1073{1074 struct mlx90635_data *data = iio_priv(dev_get_drvdata(dev));1075 1076 return mlx90635_pwr_sleep_step(data);1077}1078 1079static const struct dev_pm_ops mlx90635_pm_ops = {1080 SYSTEM_SLEEP_PM_OPS(mlx90635_pm_suspend, mlx90635_pm_resume)1081 RUNTIME_PM_OPS(mlx90635_pm_runtime_suspend, NULL, NULL)1082};1083 1084static struct i2c_driver mlx90635_driver = {1085 .driver = {1086 .name = "mlx90635",1087 .of_match_table = mlx90635_of_match,1088 .pm = pm_ptr(&mlx90635_pm_ops),1089 },1090 .probe = mlx90635_probe,1091 .id_table = mlx90635_id,1092};1093module_i2c_driver(mlx90635_driver);1094 1095MODULE_AUTHOR("Crt Mori <cmo@melexis.com>");1096MODULE_DESCRIPTION("Melexis MLX90635 contactless Infra Red temperature sensor driver");1097MODULE_LICENSE("GPL");1098