Commit 7699e975 authored by Marek Vasut's avatar Marek Vasut Committed by Jonathan Cameron

iio: mlx90614: Add MLX90615 support

Add support for MLX90615 Infra Red Thermometer, which seems to be
the predecesor of MLX90614 . There are significant differences in
the register layout compared to MLX90614, but the functionality
of the device is virtually identical.

The following differences have been identified:
- RAM/EEPROM/SLEEP access opcodes are different
- RAM/EEPROM registers are at different offsets
- EEPROM emissivity and configuration registers are at different offsets
- EEPROM configuration register bits are shuffled around
- EEPROM emissivity settings are 14 bit on MLX90615 , 16 bit on MLX90614
- MLX90615 can only ever support one sensor, MLX90614 could support two
- FIR filter is set to fixed settings on MLX90615
- IIR filter coefficients are different

This patch fills in the MLX90615 specific description and quirk handling.

The IIR filter coefficients were provided by Melexis as follows:
0b0000 - Forbidden value
0b0001 - 100% - settling time = refresh rate = 205ms (around 5Hz)
0b0010 - 50% - settling time = 2050ms (around 0.5Hz)
0b0011 - 33% - settling time = 36900ms (around 0.3Hz)
0b0100 - 25% - settling time = 5125ms (around 0.2Hz)
0b0101 - 20% - settling time = 6355ms (around 0.15Hz)
0b0110 - 17% - settling time = 7790ms (around 0.13Hz)
0b0111 - 14% - settling time = 9225ms (around 0.1Hz)
Signed-off-by: default avatarMarek Vasut <marex@denx.de>
Acked-by: default avatarCrt Mori <cmo@melexis.com>
Link: https://lore.kernel.org/r/20230510102251.10118-6-marex@denx.deSigned-off-by: default avatarJonathan Cameron <Jonathan.Cameron@huawei.com>
parent 3d5ead23
// SPDX-License-Identifier: GPL-2.0-only // SPDX-License-Identifier: GPL-2.0-only
/* /*
* mlx90614.c - Support for Melexis MLX90614 contactless IR temperature sensor * mlx90614.c - Support for Melexis MLX90614/MLX90615 contactless IR temperature sensor
* *
* Copyright (c) 2014 Peter Meerwald <pmeerw@pmeerw.net> * Copyright (c) 2014 Peter Meerwald <pmeerw@pmeerw.net>
* Copyright (c) 2015 Essensium NV * Copyright (c) 2015 Essensium NV
* Copyright (c) 2015 Melexis * Copyright (c) 2015 Melexis
* *
* Driver for the Melexis MLX90614 I2C 16-bit IR thermopile sensor * Driver for the Melexis MLX90614/MLX90615 I2C 16-bit IR thermopile sensor
*
* MLX90614 - 17-bit ADC + MLX90302 DSP
* MLX90615 - 16-bit ADC + MLX90325 DSP
* *
* (7-bit I2C slave address 0x5a, 100KHz bus speed only!) * (7-bit I2C slave address 0x5a, 100KHz bus speed only!)
* *
...@@ -35,6 +38,10 @@ ...@@ -35,6 +38,10 @@
#define MLX90614_OP_EEPROM 0x20 #define MLX90614_OP_EEPROM 0x20
#define MLX90614_OP_SLEEP 0xff #define MLX90614_OP_SLEEP 0xff
#define MLX90615_OP_EEPROM 0x10
#define MLX90615_OP_RAM 0x20
#define MLX90615_OP_SLEEP 0xc6
/* Control bits in configuration register */ /* Control bits in configuration register */
#define MLX90614_CONFIG_IIR_SHIFT 0 /* IIR coefficient */ #define MLX90614_CONFIG_IIR_SHIFT 0 /* IIR coefficient */
#define MLX90614_CONFIG_IIR_MASK (0x7 << MLX90614_CONFIG_IIR_SHIFT) #define MLX90614_CONFIG_IIR_MASK (0x7 << MLX90614_CONFIG_IIR_SHIFT)
...@@ -43,11 +50,16 @@ ...@@ -43,11 +50,16 @@
#define MLX90614_CONFIG_FIR_SHIFT 8 /* FIR coefficient */ #define MLX90614_CONFIG_FIR_SHIFT 8 /* FIR coefficient */
#define MLX90614_CONFIG_FIR_MASK (0x7 << MLX90614_CONFIG_FIR_SHIFT) #define MLX90614_CONFIG_FIR_MASK (0x7 << MLX90614_CONFIG_FIR_SHIFT)
#define MLX90615_CONFIG_IIR_SHIFT 12 /* IIR coefficient */
#define MLX90615_CONFIG_IIR_MASK (0x7 << MLX90615_CONFIG_IIR_SHIFT)
/* Timings (in ms) */ /* Timings (in ms) */
#define MLX90614_TIMING_EEPROM 20 /* time for EEPROM write/erase to complete */ #define MLX90614_TIMING_EEPROM 20 /* time for EEPROM write/erase to complete */
#define MLX90614_TIMING_WAKEUP 34 /* time to hold SDA low for wake-up */ #define MLX90614_TIMING_WAKEUP 34 /* time to hold SDA low for wake-up */
#define MLX90614_TIMING_STARTUP 250 /* time before first data after wake-up */ #define MLX90614_TIMING_STARTUP 250 /* time before first data after wake-up */
#define MLX90615_TIMING_WAKEUP 22 /* time to hold SCL low for wake-up */
#define MLX90614_AUTOSLEEP_DELAY 5000 /* default autosleep delay */ #define MLX90614_AUTOSLEEP_DELAY 5000 /* default autosleep delay */
/* Magic constants */ /* Magic constants */
...@@ -305,8 +317,8 @@ static int mlx90614_read_raw(struct iio_dev *indio_dev, ...@@ -305,8 +317,8 @@ static int mlx90614_read_raw(struct iio_dev *indio_dev,
*val2 = ret * NSEC_PER_SEC / chip_info->emissivity_max; *val2 = ret * NSEC_PER_SEC / chip_info->emissivity_max;
} }
return IIO_VAL_INT_PLUS_NANO; return IIO_VAL_INT_PLUS_NANO;
case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY: /* IIR setting with /* IIR setting with FIR=1024 (MLX90614) or FIR=65536 (MLX90615) */
FIR = 1024 */ case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY:
ret = mlx90614_power_get(data, false); ret = mlx90614_power_get(data, false);
if (ret < 0) if (ret < 0)
return ret; return ret;
...@@ -664,14 +676,42 @@ static const struct mlx_chip_info mlx90614_chip_info = { ...@@ -664,14 +676,42 @@ static const struct mlx_chip_info mlx90614_chip_info = {
}, },
}; };
static const struct mlx_chip_info mlx90615_chip_info = {
.op_eeprom_emissivity = MLX90615_OP_EEPROM | 0x03,
.op_eeprom_config1 = MLX90615_OP_EEPROM | 0x02,
.op_ram_ta = MLX90615_OP_RAM | 0x06,
.op_ram_tobj1 = MLX90615_OP_RAM | 0x07,
.op_ram_tobj2 = MLX90615_OP_RAM | 0x08,
.op_sleep = MLX90615_OP_SLEEP,
.dual_channel = false,
.wakeup_delay_ms = MLX90615_TIMING_WAKEUP,
.emissivity_max = 16383,
.fir_config_mask = 0, /* MLX90615 FIR is fixed */
.iir_config_mask = MLX90615_CONFIG_IIR_MASK,
/* IIR value 0 is FORBIDDEN COMBINATION on MLX90615 */
.iir_valid_offset = 1,
.iir_values = { 500, 50, 30, 20, 15, 13, 10 },
.iir_freqs = {
{ 0, 100000 }, /* 14% ~= 0.10 Hz */
{ 0, 130000 }, /* 17% ~= 0.13 Hz */
{ 0, 150000 }, /* 20% ~= 0.15 Hz */
{ 0, 200000 }, /* 25% ~= 0.20 Hz */
{ 0, 300000 }, /* 33% ~= 0.30 Hz */
{ 0, 500000 }, /* 50% ~= 0.50 Hz */
{ 5, 000000 }, /* 100% ~= 5.00 Hz */
},
};
static const struct i2c_device_id mlx90614_id[] = { static const struct i2c_device_id mlx90614_id[] = {
{ "mlx90614", .driver_data = (kernel_ulong_t)&mlx90614_chip_info }, { "mlx90614", .driver_data = (kernel_ulong_t)&mlx90614_chip_info },
{ "mlx90615", .driver_data = (kernel_ulong_t)&mlx90615_chip_info },
{ } { }
}; };
MODULE_DEVICE_TABLE(i2c, mlx90614_id); MODULE_DEVICE_TABLE(i2c, mlx90614_id);
static const struct of_device_id mlx90614_of_match[] = { static const struct of_device_id mlx90614_of_match[] = {
{ .compatible = "melexis,mlx90614", .data = &mlx90614_chip_info }, { .compatible = "melexis,mlx90614", .data = &mlx90614_chip_info },
{ .compatible = "melexis,mlx90615", .data = &mlx90615_chip_info },
{ } { }
}; };
MODULE_DEVICE_TABLE(of, mlx90614_of_match); MODULE_DEVICE_TABLE(of, mlx90614_of_match);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment