Lines Matching +full:calibration +full:- +full:data

1 // SPDX-License-Identifier: GPL-2.0
3 * mlx90632.c - Melexis MLX90632 contactless IR temperature sensor
7 * Driver for the Melexis MLX90632 I2C 16-bit IR thermopile sensor
33 /* EEPROM addresses - used at startup */
37 #define MLX90632_EE_P_R 0x240c /* P_R calibration register 32bit */
38 #define MLX90632_EE_P_G 0x240e /* P_G calibration register 32bit */
39 #define MLX90632_EE_P_T 0x2410 /* P_T calibration register 32bit */
40 #define MLX90632_EE_P_O 0x2412 /* P_O calibration register 32bit */
41 #define MLX90632_EE_Aa 0x2414 /* Aa calibration register 32bit */
42 #define MLX90632_EE_Ab 0x2416 /* Ab calibration register 32bit */
43 #define MLX90632_EE_Ba 0x2418 /* Ba calibration register 32bit */
44 #define MLX90632_EE_Bb 0x241a /* Bb calibration register 32bit */
45 #define MLX90632_EE_Ca 0x241c /* Ca calibration register 32bit */
46 #define MLX90632_EE_Cb 0x241e /* Cb calibration register 32bit */
47 #define MLX90632_EE_Da 0x2420 /* Da calibration register 32bit */
48 #define MLX90632_EE_Db 0x2422 /* Db calibration register 32bit */
49 #define MLX90632_EE_Ea 0x2424 /* Ea calibration register 32bit */
50 #define MLX90632_EE_Eb 0x2426 /* Eb calibration register 32bit */
51 #define MLX90632_EE_Fa 0x2428 /* Fa calibration register 32bit */
52 #define MLX90632_EE_Fb 0x242a /* Fb calibration register 32bit */
53 #define MLX90632_EE_Ga 0x242c /* Ga calibration register 32bit */
55 #define MLX90632_EE_Gb 0x242e /* Gb calibration register 16bit */
56 #define MLX90632_EE_Ka 0x242f /* Ka calibration register 16bit */
67 /* Register addresses - volatile */
70 /* Control register address - volatile */
97 /* I2C command register - volatile */
100 /* Device status register - volatile */
105 #define MLX90632_STAT_CYCLE_POS GENMASK(6, 2) /* Data position */
106 #define MLX90632_STAT_DATA_RDY BIT(0) /* Data ready indicator */
108 /* RAM_MEAS address-es for each channel */
139 * struct mlx90632_data - private data for the MLX90632 device
224 struct mlx90632_data *data = in mlx90632_pwr_set_sleep_step() local
228 if (data->powerstatus == MLX90632_PWR_STATUS_SLEEP_STEP) in mlx90632_pwr_set_sleep_step()
236 data->powerstatus = MLX90632_PWR_STATUS_SLEEP_STEP; in mlx90632_pwr_set_sleep_step()
242 struct mlx90632_data *data = in mlx90632_pwr_continuous() local
246 if (data->powerstatus == MLX90632_PWR_STATUS_CONTINUOUS) in mlx90632_pwr_continuous()
254 data->powerstatus = MLX90632_PWR_STATUS_CONTINUOUS; in mlx90632_pwr_continuous()
259 * mlx90632_reset_delay() - Give the mlx90632 some time to reset properly
279 static int mlx90632_calculate_dataset_ready_time(struct mlx90632_data *data) in mlx90632_calculate_dataset_ready_time() argument
284 if (data->mtyp == MLX90632_MTYP_MEDICAL) { in mlx90632_calculate_dataset_ready_time()
285 ret = mlx90632_get_measurement_time(data->regmap, in mlx90632_calculate_dataset_ready_time()
292 ret = mlx90632_get_measurement_time(data->regmap, in mlx90632_calculate_dataset_ready_time()
299 ret = mlx90632_get_measurement_time(data->regmap, in mlx90632_calculate_dataset_ready_time()
306 ret = mlx90632_get_measurement_time(data->regmap, in mlx90632_calculate_dataset_ready_time()
313 ret = mlx90632_get_measurement_time(data->regmap, in mlx90632_calculate_dataset_ready_time()
325 * mlx90632_perform_measurement() - Trigger and retrieve current measurement cycle
326 * @data: pointer to mlx90632_data object containing regmap information
332 static int mlx90632_perform_measurement(struct mlx90632_data *data) in mlx90632_perform_measurement() argument
337 ret = regmap_clear_bits(data->regmap, MLX90632_REG_STATUS, in mlx90632_perform_measurement()
342 ret = regmap_read_poll_timeout(data->regmap, MLX90632_REG_STATUS, reg_status, in mlx90632_perform_measurement()
347 dev_err(&data->client->dev, "data not ready"); in mlx90632_perform_measurement()
348 return -ETIMEDOUT; in mlx90632_perform_measurement()
355 * mlx90632_perform_measurement_burst() - Trigger and retrieve current measurement
357 * @data: pointer to mlx90632_data object containing regmap information
363 static int mlx90632_perform_measurement_burst(struct mlx90632_data *data) in mlx90632_perform_measurement_burst() argument
368 ret = regmap_write_bits(data->regmap, MLX90632_REG_CONTROL, in mlx90632_perform_measurement_burst()
373 ret = mlx90632_calculate_dataset_ready_time(data); in mlx90632_perform_measurement_burst()
379 ret = regmap_read_poll_timeout(data->regmap, MLX90632_REG_STATUS, in mlx90632_perform_measurement_burst()
384 dev_err(&data->client->dev, "data not ready"); in mlx90632_perform_measurement_burst()
385 return -ETIMEDOUT; in mlx90632_perform_measurement_burst()
391 static int mlx90632_set_meas_type(struct mlx90632_data *data, u8 type) in mlx90632_set_meas_type() argument
396 if (data->mtyp == type) in mlx90632_set_meas_type()
399 current_powerstatus = data->powerstatus; in mlx90632_set_meas_type()
400 ret = mlx90632_pwr_continuous(data->regmap); in mlx90632_set_meas_type()
404 ret = regmap_write(data->regmap, MLX90632_REG_I2C_CMD, MLX90632_RESET_CMD); in mlx90632_set_meas_type()
410 ret = regmap_update_bits(data->regmap, MLX90632_REG_CONTROL, in mlx90632_set_meas_type()
416 data->mtyp = type; in mlx90632_set_meas_type()
417 data->powerstatus = MLX90632_PWR_STATUS_HALT; in mlx90632_set_meas_type()
420 return mlx90632_pwr_set_sleep_step(data->regmap); in mlx90632_set_meas_type()
422 return mlx90632_pwr_continuous(data->regmap); in mlx90632_set_meas_type()
438 return -ECHRNG; in mlx90632_channel_new_select()
502 static int mlx90632_read_all_channel(struct mlx90632_data *data, in mlx90632_read_all_channel() argument
509 mutex_lock(&data->lock); in mlx90632_read_all_channel()
510 ret = mlx90632_set_meas_type(data, MLX90632_MTYP_MEDICAL); in mlx90632_read_all_channel()
514 switch (data->powerstatus) { in mlx90632_read_all_channel()
516 ret = mlx90632_perform_measurement(data); in mlx90632_read_all_channel()
522 ret = mlx90632_perform_measurement_burst(data); in mlx90632_read_all_channel()
528 ret = -EOPNOTSUPP; in mlx90632_read_all_channel()
534 ret = mlx90632_read_ambient_raw(data->regmap, ambient_new_raw, in mlx90632_read_all_channel()
539 ret = mlx90632_read_object_raw(data->regmap, measurement, in mlx90632_read_all_channel()
542 mutex_unlock(&data->lock); in mlx90632_read_all_channel()
579 read = read - (s16)read_tmp; in mlx90632_read_object_raw_extended()
584 read = read - (s16)read_tmp; in mlx90632_read_object_raw_extended()
602 return -ERANGE; in mlx90632_read_object_raw_extended()
609 static int mlx90632_read_all_channel_extended(struct mlx90632_data *data, s16 *object_new_raw, in mlx90632_read_all_channel_extended() argument
614 mutex_lock(&data->lock); in mlx90632_read_all_channel_extended()
615 ret = mlx90632_set_meas_type(data, MLX90632_MTYP_EXTENDED); in mlx90632_read_all_channel_extended()
619 switch (data->powerstatus) { in mlx90632_read_all_channel_extended()
622 50000, 800000, false, data); in mlx90632_read_all_channel_extended()
627 ret = mlx90632_perform_measurement_burst(data); in mlx90632_read_all_channel_extended()
632 ret = -EOPNOTSUPP; in mlx90632_read_all_channel_extended()
636 ret = mlx90632_read_object_raw_extended(data->regmap, object_new_raw); in mlx90632_read_all_channel_extended()
640 ret = mlx90632_read_ambient_raw_extended(data->regmap, ambient_new_raw, ambient_old_raw); in mlx90632_read_all_channel_extended()
643 mutex_unlock(&data->lock); in mlx90632_read_all_channel_extended()
724 Bsub = AMB - (((s64)P_R * 1000LL) >> 8ULL); in mlx90632_calc_temp_ambient()
745 calcedKsTO = ((s64)((s64)Ga * (prev_object_temp - 25 * 1000LL) in mlx90632_calc_temp_object_iteration()
747 calcedKsTA = ((s64)(Fb * (TAdut - 25 * 1000000LL))) >> 36LL; in mlx90632_calc_temp_object_iteration()
756 - 27315 - Hb_customer) * 10; in mlx90632_calc_temp_object_iteration()
777 TAdut = div64_s64(((ambient - kTA0) * 1000000LL), kTA) + 25 * 1000000LL; in mlx90632_calc_temp_object()
799 TAdut = div64_s64((ambient - kTA0) * 1000000LL, kTA) + 25 * 1000000LL; in mlx90632_calc_temp_object_extended()
802 TaTr4 = Tr4 - div64_s64(Tr4 - TAdut4, tmp_emi) * 1000; in mlx90632_calc_temp_object_extended()
814 static int mlx90632_calc_object_dsp105(struct mlx90632_data *data, int *val) in mlx90632_calc_object_dsp105() argument
823 ret = mlx90632_read_ee_register(data->regmap, MLX90632_EE_Ea, &Ea); in mlx90632_calc_object_dsp105()
826 ret = mlx90632_read_ee_register(data->regmap, MLX90632_EE_Eb, &Eb); in mlx90632_calc_object_dsp105()
829 ret = mlx90632_read_ee_register(data->regmap, MLX90632_EE_Fa, &Fa); in mlx90632_calc_object_dsp105()
832 ret = mlx90632_read_ee_register(data->regmap, MLX90632_EE_Fb, &Fb); in mlx90632_calc_object_dsp105()
835 ret = mlx90632_read_ee_register(data->regmap, MLX90632_EE_Ga, &Ga); in mlx90632_calc_object_dsp105()
838 ret = regmap_read(data->regmap, MLX90632_EE_Ha, &read_tmp); in mlx90632_calc_object_dsp105()
842 ret = regmap_read(data->regmap, MLX90632_EE_Hb, &read_tmp); in mlx90632_calc_object_dsp105()
846 ret = regmap_read(data->regmap, MLX90632_EE_Gb, &read_tmp); in mlx90632_calc_object_dsp105()
850 ret = regmap_read(data->regmap, MLX90632_EE_Ka, &read_tmp); in mlx90632_calc_object_dsp105()
855 ret = mlx90632_read_all_channel(data, in mlx90632_calc_object_dsp105()
862 data->mtyp == MLX90632_MTYP_EXTENDED) { in mlx90632_calc_object_dsp105()
863 ret = mlx90632_read_all_channel_extended(data, &object_new_raw, in mlx90632_calc_object_dsp105()
875 data->object_ambient_temperature, in mlx90632_calc_object_dsp105()
877 Ha, Hb, data->emissivity); in mlx90632_calc_object_dsp105()
889 Ha, Hb, data->emissivity); in mlx90632_calc_object_dsp105()
893 static int mlx90632_calc_ambient_dsp105(struct mlx90632_data *data, int *val) in mlx90632_calc_ambient_dsp105() argument
901 ret = mlx90632_read_ee_register(data->regmap, MLX90632_EE_P_R, &PR); in mlx90632_calc_ambient_dsp105()
904 ret = mlx90632_read_ee_register(data->regmap, MLX90632_EE_P_G, &PG); in mlx90632_calc_ambient_dsp105()
907 ret = mlx90632_read_ee_register(data->regmap, MLX90632_EE_P_T, &PT); in mlx90632_calc_ambient_dsp105()
910 ret = mlx90632_read_ee_register(data->regmap, MLX90632_EE_P_O, &PO); in mlx90632_calc_ambient_dsp105()
913 ret = regmap_read(data->regmap, MLX90632_EE_Gb, &read_tmp); in mlx90632_calc_ambient_dsp105()
918 ret = mlx90632_read_ambient_raw(data->regmap, &ambient_new_raw, in mlx90632_calc_ambient_dsp105()
927 static int mlx90632_get_refresh_rate(struct mlx90632_data *data, in mlx90632_get_refresh_rate() argument
933 ret = regmap_read(data->regmap, MLX90632_EE_MEDICAL_MEAS1, &meas1); in mlx90632_get_refresh_rate()
954 * mlx90632_pm_interraction_wakeup() - Measure time between user interactions to change powermode
955 * @data: pointer to mlx90632_data object containing interaction_ts information
961 static int mlx90632_pm_interraction_wakeup(struct mlx90632_data *data) in mlx90632_pm_interraction_wakeup() argument
967 if (time_in_range(now, data->interaction_ts, in mlx90632_pm_interraction_wakeup()
968 data->interaction_ts + in mlx90632_pm_interraction_wakeup()
970 if (data->powerstatus == MLX90632_PWR_STATUS_SLEEP_STEP) { in mlx90632_pm_interraction_wakeup()
971 ret = mlx90632_pwr_continuous(data->regmap); in mlx90632_pm_interraction_wakeup()
977 data->interaction_ts = now; in mlx90632_pm_interraction_wakeup()
986 struct mlx90632_data *data = iio_priv(indio_dev); in mlx90632_read_raw() local
990 pm_runtime_get_sync(&data->client->dev); in mlx90632_read_raw()
991 ret = mlx90632_pm_interraction_wakeup(data); in mlx90632_read_raw()
997 switch (channel->channel2) { in mlx90632_read_raw()
999 ret = mlx90632_calc_ambient_dsp105(data, val); in mlx90632_read_raw()
1006 ret = mlx90632_calc_object_dsp105(data, val); in mlx90632_read_raw()
1013 ret = -EINVAL; in mlx90632_read_raw()
1018 if (data->emissivity == 1000) { in mlx90632_read_raw()
1023 *val2 = data->emissivity * 1000; in mlx90632_read_raw()
1028 *val = data->object_ambient_temperature; in mlx90632_read_raw()
1032 ret = mlx90632_get_refresh_rate(data, &cr); in mlx90632_read_raw()
1041 ret = -EINVAL; in mlx90632_read_raw()
1046 pm_runtime_mark_last_busy(&data->client->dev); in mlx90632_read_raw()
1047 pm_runtime_put_autosuspend(&data->client->dev); in mlx90632_read_raw()
1055 struct mlx90632_data *data = iio_priv(indio_dev); in mlx90632_write_raw() local
1062 return -EINVAL; in mlx90632_write_raw()
1063 data->emissivity = val * 1000 + val2 / 1000; in mlx90632_write_raw()
1066 data->object_ambient_temperature = val; in mlx90632_write_raw()
1069 return -EINVAL; in mlx90632_write_raw()
1085 return -EINVAL; in mlx90632_read_avail()
1117 struct mlx90632_data *data = _data; in mlx90632_sleep() local
1119 mlx90632_pwr_set_sleep_step(data->regmap); in mlx90632_sleep()
1122 static int mlx90632_suspend(struct mlx90632_data *data) in mlx90632_suspend() argument
1124 regcache_mark_dirty(data->regmap); in mlx90632_suspend()
1126 dev_dbg(&data->client->dev, "Requesting suspend"); in mlx90632_suspend()
1127 return mlx90632_pwr_set_sleep_step(data->regmap); in mlx90632_suspend()
1130 static int mlx90632_wakeup(struct mlx90632_data *data) in mlx90632_wakeup() argument
1134 ret = regcache_sync(data->regmap); in mlx90632_wakeup()
1136 dev_err(&data->client->dev, in mlx90632_wakeup()
1141 dev_dbg(&data->client->dev, "Requesting wake-up\n"); in mlx90632_wakeup()
1142 return mlx90632_pwr_continuous(data->regmap); in mlx90632_wakeup()
1147 struct mlx90632_data *data = _data; in mlx90632_disable_regulator() local
1150 ret = regulator_disable(data->regulator); in mlx90632_disable_regulator()
1152 dev_err(regmap_get_device(data->regmap), in mlx90632_disable_regulator()
1156 static int mlx90632_enable_regulator(struct mlx90632_data *data) in mlx90632_enable_regulator() argument
1160 ret = regulator_enable(data->regulator); in mlx90632_enable_regulator()
1162 dev_err(regmap_get_device(data->regmap), "Failed to enable power regulator!\n"); in mlx90632_enable_regulator()
1180 indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*mlx90632)); in mlx90632_probe()
1182 dev_err(&client->dev, "Failed to allocate device\n"); in mlx90632_probe()
1183 return -ENOMEM; in mlx90632_probe()
1189 dev_err(&client->dev, "Failed to allocate regmap: %d\n", ret); in mlx90632_probe()
1195 mlx90632->client = client; in mlx90632_probe()
1196 mlx90632->regmap = regmap; in mlx90632_probe()
1197 mlx90632->mtyp = MLX90632_MTYP_MEDICAL; in mlx90632_probe()
1198 mlx90632->powerstatus = MLX90632_PWR_STATUS_HALT; in mlx90632_probe()
1200 mutex_init(&mlx90632->lock); in mlx90632_probe()
1201 indio_dev->name = id->name; in mlx90632_probe()
1202 indio_dev->modes = INDIO_DIRECT_MODE; in mlx90632_probe()
1203 indio_dev->info = &mlx90632_info; in mlx90632_probe()
1204 indio_dev->channels = mlx90632_channels; in mlx90632_probe()
1205 indio_dev->num_channels = ARRAY_SIZE(mlx90632_channels); in mlx90632_probe()
1207 mlx90632->regulator = devm_regulator_get(&client->dev, "vdd"); in mlx90632_probe()
1208 if (IS_ERR(mlx90632->regulator)) in mlx90632_probe()
1209 return dev_err_probe(&client->dev, PTR_ERR(mlx90632->regulator), in mlx90632_probe()
1216 ret = devm_add_action_or_reset(&client->dev, mlx90632_disable_regulator, in mlx90632_probe()
1219 dev_err(&client->dev, "Failed to setup regulator cleanup action %d\n", in mlx90632_probe()
1226 dev_err(&client->dev, "Wakeup failed: %d\n", ret); in mlx90632_probe()
1230 ret = devm_add_action_or_reset(&client->dev, mlx90632_sleep, mlx90632); in mlx90632_probe()
1232 dev_err(&client->dev, "Failed to setup low power cleanup action %d\n", in mlx90632_probe()
1237 ret = regmap_read(mlx90632->regmap, MLX90632_EE_VERSION, &read); in mlx90632_probe()
1239 dev_err(&client->dev, "read of version failed: %d\n", ret); in mlx90632_probe()
1244 dev_dbg(&client->dev, in mlx90632_probe()
1245 "Detected Medical EEPROM calibration %x\n", read); in mlx90632_probe()
1247 dev_dbg(&client->dev, in mlx90632_probe()
1248 "Detected Consumer EEPROM calibration %x\n", read); in mlx90632_probe()
1250 dev_dbg(&client->dev, in mlx90632_probe()
1251 "Detected Extended range EEPROM calibration %x\n", read); in mlx90632_probe()
1252 mlx90632->mtyp = MLX90632_MTYP_EXTENDED; in mlx90632_probe()
1254 dev_dbg(&client->dev, in mlx90632_probe()
1255 "Detected Unknown EEPROM calibration %x\n", read); in mlx90632_probe()
1257 dev_err(&client->dev, in mlx90632_probe()
1260 return -EPROTONOSUPPORT; in mlx90632_probe()
1263 mlx90632->emissivity = 1000; in mlx90632_probe()
1264 mlx90632->object_ambient_temperature = 25000; /* 25 degrees milliCelsius */ in mlx90632_probe()
1265 mlx90632->interaction_ts = jiffies; /* Set initial value */ in mlx90632_probe()
1267 pm_runtime_get_noresume(&client->dev); in mlx90632_probe()
1268 pm_runtime_set_active(&client->dev); in mlx90632_probe()
1270 ret = devm_pm_runtime_enable(&client->dev); in mlx90632_probe()
1274 pm_runtime_set_autosuspend_delay(&client->dev, MLX90632_SLEEP_DELAY_MS); in mlx90632_probe()
1275 pm_runtime_use_autosuspend(&client->dev); in mlx90632_probe()
1276 pm_runtime_put_autosuspend(&client->dev); in mlx90632_probe()
1278 return devm_iio_device_register(&client->dev, indio_dev); in mlx90632_probe()
1295 struct mlx90632_data *data = iio_priv(dev_get_drvdata(dev)); in mlx90632_pm_suspend() local
1298 ret = mlx90632_suspend(data); in mlx90632_pm_suspend()
1302 ret = regulator_disable(data->regulator); in mlx90632_pm_suspend()
1304 dev_err(regmap_get_device(data->regmap), in mlx90632_pm_suspend()
1312 struct mlx90632_data *data = iio_priv(dev_get_drvdata(dev)); in mlx90632_pm_resume() local
1315 ret = mlx90632_enable_regulator(data); in mlx90632_pm_resume()
1319 return mlx90632_wakeup(data); in mlx90632_pm_resume()
1324 struct mlx90632_data *data = iio_priv(dev_get_drvdata(dev)); in mlx90632_pm_runtime_suspend() local
1326 return mlx90632_pwr_set_sleep_step(data->regmap); in mlx90632_pm_runtime_suspend()