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
29 /* EEPROM addresses - used at startup */
33 #define MLX90632_EE_P_R 0x240c /* P_R calibration register 32bit */
34 #define MLX90632_EE_P_G 0x240e /* P_G calibration register 32bit */
35 #define MLX90632_EE_P_T 0x2410 /* P_T calibration register 32bit */
36 #define MLX90632_EE_P_O 0x2412 /* P_O calibration register 32bit */
37 #define MLX90632_EE_Aa 0x2414 /* Aa calibration register 32bit */
38 #define MLX90632_EE_Ab 0x2416 /* Ab calibration register 32bit */
39 #define MLX90632_EE_Ba 0x2418 /* Ba calibration register 32bit */
40 #define MLX90632_EE_Bb 0x241a /* Bb calibration register 32bit */
41 #define MLX90632_EE_Ca 0x241c /* Ca calibration register 32bit */
42 #define MLX90632_EE_Cb 0x241e /* Cb calibration register 32bit */
43 #define MLX90632_EE_Da 0x2420 /* Da calibration register 32bit */
44 #define MLX90632_EE_Db 0x2422 /* Db calibration register 32bit */
45 #define MLX90632_EE_Ea 0x2424 /* Ea calibration register 32bit */
46 #define MLX90632_EE_Eb 0x2426 /* Eb calibration register 32bit */
47 #define MLX90632_EE_Fa 0x2428 /* Fa calibration register 32bit */
48 #define MLX90632_EE_Fb 0x242a /* Fb calibration register 32bit */
49 #define MLX90632_EE_Ga 0x242c /* Ga calibration register 32bit */
51 #define MLX90632_EE_Gb 0x242e /* Gb calibration register 16bit */
52 #define MLX90632_EE_Ka 0x242f /* Ka calibration register 16bit */
57 /* Register addresses - volatile */
60 /* Control register address - volatile */
81 /* I2C command register - volatile */
84 /* Device status register - volatile */
89 #define MLX90632_STAT_CYCLE_POS GENMASK(6, 2) /* Data position */
90 #define MLX90632_STAT_DATA_RDY BIT(0) /* Data ready indicator */
92 /* RAM_MEAS address-es for each channel */
122 * struct mlx90632_data - private data for the MLX90632 device
211 * mlx90632_perform_measurement() - Trigger and retrieve current measurement cycle
212 * @data: pointer to mlx90632_data object containing regmap information
218 static int mlx90632_perform_measurement(struct mlx90632_data *data) in mlx90632_perform_measurement() argument
223 ret = regmap_update_bits(data->regmap, MLX90632_REG_STATUS, in mlx90632_perform_measurement()
228 ret = regmap_read_poll_timeout(data->regmap, MLX90632_REG_STATUS, reg_status, in mlx90632_perform_measurement()
233 dev_err(&data->client->dev, "data not ready"); in mlx90632_perform_measurement()
234 return -ETIMEDOUT; in mlx90632_perform_measurement()
245 return -EINVAL; in mlx90632_set_meas_type()
279 return -EINVAL; in mlx90632_channel_new_select()
343 static int mlx90632_read_all_channel(struct mlx90632_data *data, in mlx90632_read_all_channel() argument
349 mutex_lock(&data->lock); in mlx90632_read_all_channel()
350 measurement = mlx90632_perform_measurement(data); in mlx90632_read_all_channel()
355 ret = mlx90632_read_ambient_raw(data->regmap, ambient_new_raw, in mlx90632_read_all_channel()
360 ret = mlx90632_read_object_raw(data->regmap, measurement, in mlx90632_read_all_channel()
363 mutex_unlock(&data->lock); in mlx90632_read_all_channel()
400 read = read - (s16)read_tmp; in mlx90632_read_object_raw_extended()
405 read = read - (s16)read_tmp; in mlx90632_read_object_raw_extended()
423 return -ERANGE; in mlx90632_read_object_raw_extended()
430 static int mlx90632_read_all_channel_extended(struct mlx90632_data *data, s16 *object_new_raw, in mlx90632_read_all_channel_extended() argument
435 mutex_lock(&data->lock); in mlx90632_read_all_channel_extended()
436 ret = mlx90632_set_meas_type(data->regmap, MLX90632_MTYP_EXTENDED); in mlx90632_read_all_channel_extended()
441 50000, 800000, false, data); in mlx90632_read_all_channel_extended()
445 ret = mlx90632_read_object_raw_extended(data->regmap, object_new_raw); in mlx90632_read_all_channel_extended()
449 ret = mlx90632_read_ambient_raw_extended(data->regmap, ambient_new_raw, ambient_old_raw); in mlx90632_read_all_channel_extended()
452 (void) mlx90632_set_meas_type(data->regmap, MLX90632_MTYP_MEDICAL); in mlx90632_read_all_channel_extended()
454 mutex_unlock(&data->lock); in mlx90632_read_all_channel_extended()
535 Bsub = AMB - (((s64)P_R * 1000LL) >> 8ULL); in mlx90632_calc_temp_ambient()
556 calcedKsTO = ((s64)((s64)Ga * (prev_object_temp - 25 * 1000LL) in mlx90632_calc_temp_object_iteration()
558 calcedKsTA = ((s64)(Fb * (TAdut - 25 * 1000000LL))) >> 36LL; in mlx90632_calc_temp_object_iteration()
567 - 27315 - Hb_customer) * 10; in mlx90632_calc_temp_object_iteration()
588 TAdut = div64_s64(((ambient - kTA0) * 1000000LL), kTA) + 25 * 1000000LL; in mlx90632_calc_temp_object()
610 TAdut = div64_s64((ambient - kTA0) * 1000000LL, kTA) + 25 * 1000000LL; in mlx90632_calc_temp_object_extended()
613 TaTr4 = Tr4 - div64_s64(Tr4 - TAdut4, tmp_emi) * 1000; in mlx90632_calc_temp_object_extended()
625 static int mlx90632_calc_object_dsp105(struct mlx90632_data *data, int *val) in mlx90632_calc_object_dsp105() argument
634 ret = mlx90632_read_ee_register(data->regmap, MLX90632_EE_Ea, &Ea); in mlx90632_calc_object_dsp105()
637 ret = mlx90632_read_ee_register(data->regmap, MLX90632_EE_Eb, &Eb); in mlx90632_calc_object_dsp105()
640 ret = mlx90632_read_ee_register(data->regmap, MLX90632_EE_Fa, &Fa); in mlx90632_calc_object_dsp105()
643 ret = mlx90632_read_ee_register(data->regmap, MLX90632_EE_Fb, &Fb); in mlx90632_calc_object_dsp105()
646 ret = mlx90632_read_ee_register(data->regmap, MLX90632_EE_Ga, &Ga); in mlx90632_calc_object_dsp105()
649 ret = regmap_read(data->regmap, MLX90632_EE_Ha, &read_tmp); in mlx90632_calc_object_dsp105()
653 ret = regmap_read(data->regmap, MLX90632_EE_Hb, &read_tmp); in mlx90632_calc_object_dsp105()
657 ret = regmap_read(data->regmap, MLX90632_EE_Gb, &read_tmp); in mlx90632_calc_object_dsp105()
661 ret = regmap_read(data->regmap, MLX90632_EE_Ka, &read_tmp); in mlx90632_calc_object_dsp105()
666 ret = mlx90632_read_all_channel(data, in mlx90632_calc_object_dsp105()
673 data->mtyp == MLX90632_MTYP_EXTENDED) { in mlx90632_calc_object_dsp105()
674 ret = mlx90632_read_all_channel_extended(data, &object_new_raw, in mlx90632_calc_object_dsp105()
686 data->object_ambient_temperature, in mlx90632_calc_object_dsp105()
688 Ha, Hb, data->emissivity); in mlx90632_calc_object_dsp105()
700 Ha, Hb, data->emissivity); in mlx90632_calc_object_dsp105()
704 static int mlx90632_calc_ambient_dsp105(struct mlx90632_data *data, int *val) in mlx90632_calc_ambient_dsp105() argument
712 ret = mlx90632_read_ee_register(data->regmap, MLX90632_EE_P_R, &PR); in mlx90632_calc_ambient_dsp105()
715 ret = mlx90632_read_ee_register(data->regmap, MLX90632_EE_P_G, &PG); in mlx90632_calc_ambient_dsp105()
718 ret = mlx90632_read_ee_register(data->regmap, MLX90632_EE_P_T, &PT); in mlx90632_calc_ambient_dsp105()
721 ret = mlx90632_read_ee_register(data->regmap, MLX90632_EE_P_O, &PO); in mlx90632_calc_ambient_dsp105()
724 ret = regmap_read(data->regmap, MLX90632_EE_Gb, &read_tmp); in mlx90632_calc_ambient_dsp105()
729 ret = mlx90632_read_ambient_raw(data->regmap, &ambient_new_raw, in mlx90632_calc_ambient_dsp105()
742 struct mlx90632_data *data = iio_priv(indio_dev); in mlx90632_read_raw() local
747 switch (channel->channel2) { in mlx90632_read_raw()
749 ret = mlx90632_calc_ambient_dsp105(data, val); in mlx90632_read_raw()
754 ret = mlx90632_calc_object_dsp105(data, val); in mlx90632_read_raw()
759 return -EINVAL; in mlx90632_read_raw()
762 if (data->emissivity == 1000) { in mlx90632_read_raw()
767 *val2 = data->emissivity * 1000; in mlx90632_read_raw()
771 *val = data->object_ambient_temperature; in mlx90632_read_raw()
774 return -EINVAL; in mlx90632_read_raw()
782 struct mlx90632_data *data = iio_priv(indio_dev); in mlx90632_write_raw() local
789 return -EINVAL; in mlx90632_write_raw()
790 data->emissivity = val * 1000 + val2 / 1000; in mlx90632_write_raw()
793 data->object_ambient_temperature = val; in mlx90632_write_raw()
796 return -EINVAL; in mlx90632_write_raw()
821 static int mlx90632_sleep(struct mlx90632_data *data) in mlx90632_sleep() argument
823 regcache_mark_dirty(data->regmap); in mlx90632_sleep()
825 dev_dbg(&data->client->dev, "Requesting sleep"); in mlx90632_sleep()
826 return mlx90632_pwr_set_sleep_step(data->regmap); in mlx90632_sleep()
829 static int mlx90632_wakeup(struct mlx90632_data *data) in mlx90632_wakeup() argument
833 ret = regcache_sync(data->regmap); in mlx90632_wakeup()
835 dev_err(&data->client->dev, in mlx90632_wakeup()
840 dev_dbg(&data->client->dev, "Requesting wake-up\n"); in mlx90632_wakeup()
841 return mlx90632_pwr_continuous(data->regmap); in mlx90632_wakeup()
853 indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*mlx90632)); in mlx90632_probe()
855 dev_err(&client->dev, "Failed to allocate device\n"); in mlx90632_probe()
856 return -ENOMEM; in mlx90632_probe()
862 dev_err(&client->dev, "Failed to allocate regmap: %d\n", ret); in mlx90632_probe()
868 mlx90632->client = client; in mlx90632_probe()
869 mlx90632->regmap = regmap; in mlx90632_probe()
870 mlx90632->mtyp = MLX90632_MTYP_MEDICAL; in mlx90632_probe()
872 mutex_init(&mlx90632->lock); in mlx90632_probe()
873 indio_dev->name = id->name; in mlx90632_probe()
874 indio_dev->modes = INDIO_DIRECT_MODE; in mlx90632_probe()
875 indio_dev->info = &mlx90632_info; in mlx90632_probe()
876 indio_dev->channels = mlx90632_channels; in mlx90632_probe()
877 indio_dev->num_channels = ARRAY_SIZE(mlx90632_channels); in mlx90632_probe()
881 dev_err(&client->dev, "Wakeup failed: %d\n", ret); in mlx90632_probe()
885 ret = regmap_read(mlx90632->regmap, MLX90632_EE_VERSION, &read); in mlx90632_probe()
887 dev_err(&client->dev, "read of version failed: %d\n", ret); in mlx90632_probe()
892 dev_dbg(&client->dev, in mlx90632_probe()
893 "Detected Medical EEPROM calibration %x\n", read); in mlx90632_probe()
895 dev_dbg(&client->dev, in mlx90632_probe()
896 "Detected Consumer EEPROM calibration %x\n", read); in mlx90632_probe()
898 dev_dbg(&client->dev, in mlx90632_probe()
899 "Detected Extended range EEPROM calibration %x\n", read); in mlx90632_probe()
900 mlx90632->mtyp = MLX90632_MTYP_EXTENDED; in mlx90632_probe()
902 dev_dbg(&client->dev, in mlx90632_probe()
903 "Detected Unknown EEPROM calibration %x\n", read); in mlx90632_probe()
905 dev_err(&client->dev, in mlx90632_probe()
908 return -EPROTONOSUPPORT; in mlx90632_probe()
911 mlx90632->emissivity = 1000; in mlx90632_probe()
912 mlx90632->object_ambient_temperature = 25000; /* 25 degrees milliCelsius */ in mlx90632_probe()
914 pm_runtime_disable(&client->dev); in mlx90632_probe()
915 ret = pm_runtime_set_active(&client->dev); in mlx90632_probe()
920 pm_runtime_enable(&client->dev); in mlx90632_probe()
921 pm_runtime_set_autosuspend_delay(&client->dev, MLX90632_SLEEP_DELAY_MS); in mlx90632_probe()
922 pm_runtime_use_autosuspend(&client->dev); in mlx90632_probe()
930 struct mlx90632_data *data = iio_priv(indio_dev); in mlx90632_remove() local
934 pm_runtime_disable(&client->dev); in mlx90632_remove()
935 pm_runtime_set_suspended(&client->dev); in mlx90632_remove()
936 pm_runtime_put_noidle(&client->dev); in mlx90632_remove()
938 mlx90632_sleep(data); in mlx90632_remove()
958 struct mlx90632_data *data = iio_priv(indio_dev); in mlx90632_pm_suspend() local
960 return mlx90632_sleep(data); in mlx90632_pm_suspend()
966 struct mlx90632_data *data = iio_priv(indio_dev); in mlx90632_pm_resume() local
968 return mlx90632_wakeup(data); in mlx90632_pm_resume()