diff options
author | Peter Meerwald <pmeerw@pmeerw.net> | 2014-02-05 11:57:00 -0500 |
---|---|---|
committer | Jonathan Cameron <jic23@kernel.org> | 2014-05-03 06:38:13 -0400 |
commit | 474fe212e669b6c1698982041028f7727c879970 (patch) | |
tree | 5e3c5606c8d759914630c31abba98fe6993177d7 /drivers/iio/temperature | |
parent | 888c9c7366cef902531f27f6aa5fb787c86810d4 (diff) |
iio: Add Melexis mlx90614 contact-less infrared temperature sensor driver
I2C-controlled sensor measures ambient and object temperatuer
see
http://www.melexis.com/Infrared-Thermometer-Sensors/Infrared-Thermometer-Sensors/MLX90614-615.aspx
Signed-off-by: Peter Meerwald <pmeerw@pmeerw.net>
Signed-off-by: Jonathan Cameron <jic23@kernel.org>
Diffstat (limited to 'drivers/iio/temperature')
-rw-r--r-- | drivers/iio/temperature/Kconfig | 10 | ||||
-rw-r--r-- | drivers/iio/temperature/Makefile | 1 | ||||
-rw-r--r-- | drivers/iio/temperature/mlx90614.c | 150 |
3 files changed, 161 insertions, 0 deletions
diff --git a/drivers/iio/temperature/Kconfig b/drivers/iio/temperature/Kconfig index 372f8fb3085f..21feaa4661b4 100644 --- a/drivers/iio/temperature/Kconfig +++ b/drivers/iio/temperature/Kconfig | |||
@@ -3,6 +3,16 @@ | |||
3 | # | 3 | # |
4 | menu "Temperature sensors" | 4 | menu "Temperature sensors" |
5 | 5 | ||
6 | config MLX90614 | ||
7 | tristate "MLX90614 contact-less infrared sensor" | ||
8 | depends on I2C | ||
9 | help | ||
10 | If you say yes here you get support for the Melexis | ||
11 | MLX90614 contact-less infrared sensor connected with I2C. | ||
12 | |||
13 | This driver can also be built as a module. If so, the module will | ||
14 | be called mlx90614. | ||
15 | |||
6 | config TMP006 | 16 | config TMP006 |
7 | tristate "TMP006 infrared thermopile sensor" | 17 | tristate "TMP006 infrared thermopile sensor" |
8 | depends on I2C | 18 | depends on I2C |
diff --git a/drivers/iio/temperature/Makefile b/drivers/iio/temperature/Makefile index 24d7b602db3e..40710a81158e 100644 --- a/drivers/iio/temperature/Makefile +++ b/drivers/iio/temperature/Makefile | |||
@@ -2,4 +2,5 @@ | |||
2 | # Makefile for industrial I/O temperature drivers | 2 | # Makefile for industrial I/O temperature drivers |
3 | # | 3 | # |
4 | 4 | ||
5 | obj-$(CONFIG_MLX90614) += mlx90614.o | ||
5 | obj-$(CONFIG_TMP006) += tmp006.o | 6 | obj-$(CONFIG_TMP006) += tmp006.o |
diff --git a/drivers/iio/temperature/mlx90614.c b/drivers/iio/temperature/mlx90614.c new file mode 100644 index 000000000000..c8b6ac8b2d69 --- /dev/null +++ b/drivers/iio/temperature/mlx90614.c | |||
@@ -0,0 +1,150 @@ | |||
1 | /* | ||
2 | * mlx90614.c - Support for Melexis MLX90614 contactless IR temperature sensor | ||
3 | * | ||
4 | * Copyright (c) 2014 Peter Meerwald <pmeerw@pmeerw.net> | ||
5 | * | ||
6 | * This file is subject to the terms and conditions of version 2 of | ||
7 | * the GNU General Public License. See the file COPYING in the main | ||
8 | * directory of this archive for more details. | ||
9 | * | ||
10 | * Driver for the Melexis MLX90614 I2C 16-bit IR thermopile sensor | ||
11 | * | ||
12 | * (7-bit I2C slave address 0x5a, 100KHz bus speed only!) | ||
13 | * | ||
14 | * TODO: sleep mode, configuration EEPROM | ||
15 | */ | ||
16 | |||
17 | #include <linux/err.h> | ||
18 | #include <linux/i2c.h> | ||
19 | #include <linux/module.h> | ||
20 | |||
21 | #include <linux/iio/iio.h> | ||
22 | |||
23 | #define MLX90614_OP_RAM 0x00 | ||
24 | |||
25 | /* RAM offsets with 16-bit data, MSB first */ | ||
26 | #define MLX90614_TA 0x06 /* ambient temperature */ | ||
27 | #define MLX90614_TOBJ1 0x07 /* object temperature */ | ||
28 | |||
29 | struct mlx90614_data { | ||
30 | struct i2c_client *client; | ||
31 | }; | ||
32 | |||
33 | static int mlx90614_read_raw(struct iio_dev *indio_dev, | ||
34 | struct iio_chan_spec const *channel, int *val, | ||
35 | int *val2, long mask) | ||
36 | { | ||
37 | struct mlx90614_data *data = iio_priv(indio_dev); | ||
38 | s32 ret; | ||
39 | |||
40 | switch (mask) { | ||
41 | case IIO_CHAN_INFO_RAW: /* 0.02K / LSB */ | ||
42 | switch (channel->channel2) { | ||
43 | case IIO_MOD_TEMP_AMBIENT: | ||
44 | ret = i2c_smbus_read_word_data(data->client, | ||
45 | MLX90614_OP_RAM | MLX90614_TA); | ||
46 | if (ret < 0) | ||
47 | return ret; | ||
48 | break; | ||
49 | case IIO_MOD_TEMP_OBJECT: | ||
50 | ret = i2c_smbus_read_word_data(data->client, | ||
51 | MLX90614_OP_RAM | MLX90614_TOBJ1); | ||
52 | if (ret < 0) | ||
53 | return ret; | ||
54 | break; | ||
55 | default: | ||
56 | return -EINVAL; | ||
57 | } | ||
58 | *val = ret; | ||
59 | return IIO_VAL_INT; | ||
60 | case IIO_CHAN_INFO_OFFSET: | ||
61 | *val = 13657; | ||
62 | *val2 = 500000; | ||
63 | return IIO_VAL_INT_PLUS_MICRO; | ||
64 | case IIO_CHAN_INFO_SCALE: | ||
65 | *val = 20; | ||
66 | return IIO_VAL_INT; | ||
67 | default: | ||
68 | return -EINVAL; | ||
69 | } | ||
70 | } | ||
71 | |||
72 | static const struct iio_chan_spec mlx90614_channels[] = { | ||
73 | { | ||
74 | .type = IIO_TEMP, | ||
75 | .modified = 1, | ||
76 | .channel2 = IIO_MOD_TEMP_AMBIENT, | ||
77 | .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), | ||
78 | .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_OFFSET) | | ||
79 | BIT(IIO_CHAN_INFO_SCALE), | ||
80 | }, | ||
81 | { | ||
82 | .type = IIO_TEMP, | ||
83 | .modified = 1, | ||
84 | .channel2 = IIO_MOD_TEMP_OBJECT, | ||
85 | .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), | ||
86 | .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_OFFSET) | | ||
87 | BIT(IIO_CHAN_INFO_SCALE), | ||
88 | }, | ||
89 | }; | ||
90 | |||
91 | static const struct iio_info mlx90614_info = { | ||
92 | .read_raw = mlx90614_read_raw, | ||
93 | .driver_module = THIS_MODULE, | ||
94 | }; | ||
95 | |||
96 | static int mlx90614_probe(struct i2c_client *client, | ||
97 | const struct i2c_device_id *id) | ||
98 | { | ||
99 | struct iio_dev *indio_dev; | ||
100 | struct mlx90614_data *data; | ||
101 | |||
102 | if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_WORD_DATA)) | ||
103 | return -ENODEV; | ||
104 | |||
105 | indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); | ||
106 | if (!indio_dev) | ||
107 | return -ENOMEM; | ||
108 | |||
109 | data = iio_priv(indio_dev); | ||
110 | i2c_set_clientdata(client, indio_dev); | ||
111 | data->client = client; | ||
112 | |||
113 | indio_dev->dev.parent = &client->dev; | ||
114 | indio_dev->name = id->name; | ||
115 | indio_dev->modes = INDIO_DIRECT_MODE; | ||
116 | indio_dev->info = &mlx90614_info; | ||
117 | |||
118 | indio_dev->channels = mlx90614_channels; | ||
119 | indio_dev->num_channels = ARRAY_SIZE(mlx90614_channels); | ||
120 | |||
121 | return iio_device_register(indio_dev); | ||
122 | } | ||
123 | |||
124 | static int mlx90614_remove(struct i2c_client *client) | ||
125 | { | ||
126 | iio_device_unregister(i2c_get_clientdata(client)); | ||
127 | |||
128 | return 0; | ||
129 | } | ||
130 | |||
131 | static const struct i2c_device_id mlx90614_id[] = { | ||
132 | { "mlx90614", 0 }, | ||
133 | { } | ||
134 | }; | ||
135 | MODULE_DEVICE_TABLE(i2c, mlx90614_id); | ||
136 | |||
137 | static struct i2c_driver mlx90614_driver = { | ||
138 | .driver = { | ||
139 | .name = "mlx90614", | ||
140 | .owner = THIS_MODULE, | ||
141 | }, | ||
142 | .probe = mlx90614_probe, | ||
143 | .remove = mlx90614_remove, | ||
144 | .id_table = mlx90614_id, | ||
145 | }; | ||
146 | module_i2c_driver(mlx90614_driver); | ||
147 | |||
148 | MODULE_AUTHOR("Peter Meerwald <pmeerw@pmeerw.net>"); | ||
149 | MODULE_DESCRIPTION("Melexis MLX90614 contactless IR temperature sensor driver"); | ||
150 | MODULE_LICENSE("GPL"); | ||