2 * mlx90614.c - Support for Melexis MLX90614 contactless IR temperature sensor
4 * Copyright (c) 2014 Peter Meerwald <pmeerw@pmeerw.net>
5 * Copyright (c) 2015 Essensium NV
7 * This file is subject to the terms and conditions of version 2 of
8 * the GNU General Public License. See the file COPYING in the main
9 * directory of this archive for more details.
11 * Driver for the Melexis MLX90614 I2C 16-bit IR thermopile sensor
13 * (7-bit I2C slave address 0x5a, 100KHz bus speed only!)
15 * TODO: sleep mode, configuration EEPROM
18 #include <linux/err.h>
19 #include <linux/i2c.h>
20 #include <linux/module.h>
22 #include <linux/iio/iio.h>
24 #define MLX90614_OP_RAM 0x00
25 #define MLX90614_OP_EEPROM 0x20
26 #define MLX90614_OP_SLEEP 0xff
28 /* RAM offsets with 16-bit data, MSB first */
29 #define MLX90614_RAW1 (MLX90614_OP_RAM | 0x04) /* raw data IR channel 1 */
30 #define MLX90614_RAW2 (MLX90614_OP_RAM | 0x05) /* raw data IR channel 2 */
31 #define MLX90614_TA (MLX90614_OP_RAM | 0x06) /* ambient temperature */
32 #define MLX90614_TOBJ1 (MLX90614_OP_RAM | 0x07) /* object 1 temperature */
33 #define MLX90614_TOBJ2 (MLX90614_OP_RAM | 0x08) /* object 2 temperature */
35 /* EEPROM offsets with 16-bit data, MSB first */
36 #define MLX90614_EMISSIVITY (MLX90614_OP_EEPROM | 0x04) /* emissivity correction coefficient */
37 #define MLX90614_CONFIG (MLX90614_OP_EEPROM | 0x05) /* configuration register */
39 /* Control bits in configuration register */
40 #define MLX90614_CONFIG_IIR_SHIFT 0 /* IIR coefficient */
41 #define MLX90614_CONFIG_IIR_MASK (0x7 << MLX90614_CONFIG_IIR_SHIFT)
42 #define MLX90614_CONFIG_DUAL_SHIFT 6 /* single (0) or dual (1) IR sensor */
43 #define MLX90614_CONFIG_DUAL_MASK (1 << MLX90614_CONFIG_DUAL_SHIFT)
44 #define MLX90614_CONFIG_FIR_SHIFT 8 /* FIR coefficient */
45 #define MLX90614_CONFIG_FIR_MASK (0x7 << MLX90614_CONFIG_FIR_SHIFT)
46 #define MLX90614_CONFIG_GAIN_SHIFT 11 /* gain */
47 #define MLX90614_CONFIG_GAIN_MASK (0x7 << MLX90614_CONFIG_GAIN_SHIFT)
50 #define MLX90614_TIMING_EEPROM 20 /* time for EEPROM write/erase to complete */
51 #define MLX90614_TIMING_WAKEUP 34 /* time to hold SDA low for wake-up */
52 #define MLX90614_TIMING_STARTUP 250 /* time before first data after wake-up */
54 struct mlx90614_data
{
55 struct i2c_client
*client
;
58 static int mlx90614_read_raw(struct iio_dev
*indio_dev
,
59 struct iio_chan_spec
const *channel
, int *val
,
62 struct mlx90614_data
*data
= iio_priv(indio_dev
);
67 case IIO_CHAN_INFO_RAW
: /* 0.02K / LSB */
68 switch (channel
->channel2
) {
69 case IIO_MOD_TEMP_AMBIENT
:
72 case IIO_MOD_TEMP_OBJECT
:
73 switch (channel
->channel
) {
88 ret
= i2c_smbus_read_word_data(data
->client
, cmd
);
93 case IIO_CHAN_INFO_OFFSET
:
96 return IIO_VAL_INT_PLUS_MICRO
;
97 case IIO_CHAN_INFO_SCALE
:
105 static const struct iio_chan_spec mlx90614_channels
[] = {
109 .channel2
= IIO_MOD_TEMP_AMBIENT
,
110 .info_mask_separate
= BIT(IIO_CHAN_INFO_RAW
),
111 .info_mask_shared_by_type
= BIT(IIO_CHAN_INFO_OFFSET
) |
112 BIT(IIO_CHAN_INFO_SCALE
),
117 .channel2
= IIO_MOD_TEMP_OBJECT
,
118 .info_mask_separate
= BIT(IIO_CHAN_INFO_RAW
),
119 .info_mask_shared_by_type
= BIT(IIO_CHAN_INFO_OFFSET
) |
120 BIT(IIO_CHAN_INFO_SCALE
),
127 .channel2
= IIO_MOD_TEMP_OBJECT
,
128 .info_mask_separate
= BIT(IIO_CHAN_INFO_RAW
),
129 .info_mask_shared_by_type
= BIT(IIO_CHAN_INFO_OFFSET
) |
130 BIT(IIO_CHAN_INFO_SCALE
),
134 static const struct iio_info mlx90614_info
= {
135 .read_raw
= mlx90614_read_raw
,
136 .driver_module
= THIS_MODULE
,
139 /* Return 0 for single sensor, 1 for dual sensor, <0 on error. */
140 static int mlx90614_probe_num_ir_sensors(struct i2c_client
*client
)
144 ret
= i2c_smbus_read_word_data(client
, MLX90614_CONFIG
);
149 return (ret
& MLX90614_CONFIG_DUAL_MASK
) ? 1 : 0;
152 static int mlx90614_probe(struct i2c_client
*client
,
153 const struct i2c_device_id
*id
)
155 struct iio_dev
*indio_dev
;
156 struct mlx90614_data
*data
;
159 if (!i2c_check_functionality(client
->adapter
, I2C_FUNC_SMBUS_WORD_DATA
))
162 indio_dev
= devm_iio_device_alloc(&client
->dev
, sizeof(*data
));
166 data
= iio_priv(indio_dev
);
167 i2c_set_clientdata(client
, indio_dev
);
168 data
->client
= client
;
170 indio_dev
->dev
.parent
= &client
->dev
;
171 indio_dev
->name
= id
->name
;
172 indio_dev
->modes
= INDIO_DIRECT_MODE
;
173 indio_dev
->info
= &mlx90614_info
;
175 ret
= mlx90614_probe_num_ir_sensors(client
);
178 dev_dbg(&client
->dev
, "Found single sensor");
179 indio_dev
->channels
= mlx90614_channels
;
180 indio_dev
->num_channels
= 2;
183 dev_dbg(&client
->dev
, "Found dual sensor");
184 indio_dev
->channels
= mlx90614_channels
;
185 indio_dev
->num_channels
= 3;
191 return iio_device_register(indio_dev
);
194 static int mlx90614_remove(struct i2c_client
*client
)
196 iio_device_unregister(i2c_get_clientdata(client
));
201 static const struct i2c_device_id mlx90614_id
[] = {
205 MODULE_DEVICE_TABLE(i2c
, mlx90614_id
);
207 static struct i2c_driver mlx90614_driver
= {
210 .owner
= THIS_MODULE
,
212 .probe
= mlx90614_probe
,
213 .remove
= mlx90614_remove
,
214 .id_table
= mlx90614_id
,
216 module_i2c_driver(mlx90614_driver
);
218 MODULE_AUTHOR("Peter Meerwald <pmeerw@pmeerw.net>");
219 MODULE_AUTHOR("Vianney le Clément de Saint-Marcq <vianney.leclement@essensium.com>");
220 MODULE_DESCRIPTION("Melexis MLX90614 contactless IR temperature sensor driver");
221 MODULE_LICENSE("GPL");