2 * veml6070.c - Support for Vishay VEML6070 UV A light sensor
4 * Copyright 2016 Peter Meerwald-Stadler <pmeerw@pmeerw.net>
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.
10 * IIO driver for VEML6070 (7-bit I2C slave addresses 0x38 and 0x39)
12 * TODO: integration time, ACK signal
15 #include <linux/module.h>
16 #include <linux/i2c.h>
17 #include <linux/mutex.h>
18 #include <linux/err.h>
19 #include <linux/delay.h>
21 #include <linux/iio/iio.h>
22 #include <linux/iio/sysfs.h>
24 #define VEML6070_DRV_NAME "veml6070"
26 #define VEML6070_ADDR_CONFIG_DATA_MSB 0x38 /* read: MSB data, write: config */
27 #define VEML6070_ADDR_DATA_LSB 0x39 /* LSB data */
29 #define VEML6070_COMMAND_ACK BIT(5) /* raise interrupt when over threshold */
30 #define VEML6070_COMMAND_IT GENMASK(3, 2) /* bit mask integration time */
31 #define VEML6070_COMMAND_RSRVD BIT(1) /* reserved, set to 1 */
32 #define VEML6070_COMMAND_SD BIT(0) /* shutdown mode when set */
34 #define VEML6070_IT_10 0x04 /* integration time 1x */
36 struct veml6070_data
{
37 struct i2c_client
*client1
;
38 struct i2c_client
*client2
;
43 static int veml6070_read(struct veml6070_data
*data
)
48 mutex_lock(&data
->lock
);
50 /* disable shutdown */
51 ret
= i2c_smbus_write_byte(data
->client1
,
52 data
->config
& ~VEML6070_COMMAND_SD
);
56 msleep(125 + 10); /* measurement takes up to 125 ms for IT 1x */
58 ret
= i2c_smbus_read_byte(data
->client2
); /* read MSB, address 0x39 */
63 ret
= i2c_smbus_read_byte(data
->client1
); /* read LSB, address 0x38 */
69 ret
= i2c_smbus_write_byte(data
->client1
, data
->config
);
73 ret
= (msb
<< 8) | lsb
;
76 mutex_unlock(&data
->lock
);
80 static const struct iio_chan_spec veml6070_channels
[] = {
82 .type
= IIO_INTENSITY
,
84 .channel2
= IIO_MOD_LIGHT_UV
,
85 .info_mask_separate
= BIT(IIO_CHAN_INFO_RAW
),
89 .info_mask_separate
= BIT(IIO_CHAN_INFO_PROCESSED
),
93 static int veml6070_to_uv_index(unsigned val
)
96 * conversion of raw UV intensity values to UV index depends on
97 * integration time (IT) and value of the resistor connected to
98 * the RSET pin (default: 270 KOhm)
101 187, 373, 560, /* low */
102 746, 933, 1120, /* moderate */
103 1308, 1494, /* high */
104 1681, 1868, 2054}; /* very high */
107 for (i
= 0; i
< ARRAY_SIZE(uvi
); i
++)
111 return 11; /* extreme */
114 static int veml6070_read_raw(struct iio_dev
*indio_dev
,
115 struct iio_chan_spec
const *chan
,
116 int *val
, int *val2
, long mask
)
118 struct veml6070_data
*data
= iio_priv(indio_dev
);
122 case IIO_CHAN_INFO_RAW
:
123 case IIO_CHAN_INFO_PROCESSED
:
124 ret
= veml6070_read(data
);
127 if (mask
== IIO_CHAN_INFO_PROCESSED
)
128 *val
= veml6070_to_uv_index(ret
);
137 static const struct iio_info veml6070_info
= {
138 .read_raw
= veml6070_read_raw
,
141 static int veml6070_probe(struct i2c_client
*client
,
142 const struct i2c_device_id
*id
)
144 struct veml6070_data
*data
;
145 struct iio_dev
*indio_dev
;
148 indio_dev
= devm_iio_device_alloc(&client
->dev
, sizeof(*data
));
152 data
= iio_priv(indio_dev
);
153 i2c_set_clientdata(client
, indio_dev
);
154 data
->client1
= client
;
155 mutex_init(&data
->lock
);
157 indio_dev
->dev
.parent
= &client
->dev
;
158 indio_dev
->info
= &veml6070_info
;
159 indio_dev
->channels
= veml6070_channels
;
160 indio_dev
->num_channels
= ARRAY_SIZE(veml6070_channels
);
161 indio_dev
->name
= VEML6070_DRV_NAME
;
162 indio_dev
->modes
= INDIO_DIRECT_MODE
;
164 data
->client2
= i2c_new_dummy(client
->adapter
, VEML6070_ADDR_DATA_LSB
);
165 if (!data
->client2
) {
166 dev_err(&client
->dev
, "i2c device for second chip address failed\n");
170 data
->config
= VEML6070_IT_10
| VEML6070_COMMAND_RSRVD
|
172 ret
= i2c_smbus_write_byte(data
->client1
, data
->config
);
176 ret
= iio_device_register(indio_dev
);
183 i2c_unregister_device(data
->client2
);
187 static int veml6070_remove(struct i2c_client
*client
)
189 struct iio_dev
*indio_dev
= i2c_get_clientdata(client
);
190 struct veml6070_data
*data
= iio_priv(indio_dev
);
192 iio_device_unregister(indio_dev
);
193 i2c_unregister_device(data
->client2
);
198 static const struct i2c_device_id veml6070_id
[] = {
202 MODULE_DEVICE_TABLE(i2c
, veml6070_id
);
204 static struct i2c_driver veml6070_driver
= {
206 .name
= VEML6070_DRV_NAME
,
208 .probe
= veml6070_probe
,
209 .remove
= veml6070_remove
,
210 .id_table
= veml6070_id
,
213 module_i2c_driver(veml6070_driver
);
215 MODULE_AUTHOR("Peter Meerwald-Stadler <pmeerw@pmeerw.net>");
216 MODULE_DESCRIPTION("Vishay VEML6070 UV A light sensor driver");
217 MODULE_LICENSE("GPL");