* [PATCH v2 0/3] Add IIO veml6070 driver and UV light support
@ 2016-03-20 15:20 Peter Meerwald-Stadler
2016-03-20 15:20 ` [PATCH v2 1/3] iio: Add modifier for UV light Peter Meerwald-Stadler
` (2 more replies)
0 siblings, 3 replies; 7+ messages in thread
From: Peter Meerwald-Stadler @ 2016-03-20 15:20 UTC (permalink / raw)
To: Jonathan Cameron; +Cc: linux-iio
v2 adds a new IIO channel type IIO_UVINDEX (suggested by Jonathan)
Peter Meerwald-Stadler (3):
iio: Add modifier for UV light
iio: Add channel for UV index
iio: Add Vishay VEML6070 UV A light sensor driver
Documentation/ABI/testing/sysfs-bus-iio | 13 +-
drivers/iio/industrialio-core.c | 2 +
drivers/iio/light/Kconfig | 10 ++
drivers/iio/light/Makefile | 1 +
drivers/iio/light/veml6070.c | 218 ++++++++++++++++++++++++++++++++
include/uapi/linux/iio/types.h | 2 +
tools/iio/iio_event_monitor.c | 4 +
7 files changed, 249 insertions(+), 1 deletion(-)
create mode 100644 drivers/iio/light/veml6070.c
--
1.9.1
^ permalink raw reply [flat|nested] 7+ messages in thread* [PATCH v2 1/3] iio: Add modifier for UV light 2016-03-20 15:20 [PATCH v2 0/3] Add IIO veml6070 driver and UV light support Peter Meerwald-Stadler @ 2016-03-20 15:20 ` Peter Meerwald-Stadler 2016-03-28 15:36 ` Jonathan Cameron 2016-03-20 15:20 ` [PATCH v2 2/3] iio: Add channel for UV index Peter Meerwald-Stadler 2016-03-20 15:20 ` [PATCH v2 3/3] iio: Add Vishay VEML6070 UV A light sensor driver Peter Meerwald-Stadler 2 siblings, 1 reply; 7+ messages in thread From: Peter Meerwald-Stadler @ 2016-03-20 15:20 UTC (permalink / raw) To: Jonathan Cameron; +Cc: linux-iio, Peter Meerwald-Stadler Signed-off-by: Peter Meerwald-Stadler <pmeerw@pmeerw.net> --- Documentation/ABI/testing/sysfs-bus-iio | 4 +++- drivers/iio/industrialio-core.c | 1 + include/uapi/linux/iio/types.h | 1 + tools/iio/iio_event_monitor.c | 2 ++ 4 files changed, 7 insertions(+), 1 deletion(-) diff --git a/Documentation/ABI/testing/sysfs-bus-iio b/Documentation/ABI/testing/sysfs-bus-iio index 17a9210..6fb9180 100644 --- a/Documentation/ABI/testing/sysfs-bus-iio +++ b/Documentation/ABI/testing/sysfs-bus-iio @@ -1255,12 +1255,14 @@ Description: What: /sys/.../iio:deviceX/in_intensityY_raw What: /sys/.../iio:deviceX/in_intensityY_ir_raw What: /sys/.../iio:deviceX/in_intensityY_both_raw +What: /sys/.../iio:deviceX/in_intensityY_uv_raw KernelVersion: 3.4 Contact: linux-iio@vger.kernel.org Description: Unit-less light intensity. Modifiers both and ir indicate that measurements contains visible and infrared light - components or just infrared light, respectively. + components or just infrared light, respectively. Modifier uv indicates + that measurements contain ultraviolet light components. What: /sys/.../iio:deviceX/in_intensity_red_integration_time What: /sys/.../iio:deviceX/in_intensity_green_integration_time diff --git a/drivers/iio/industrialio-core.c b/drivers/iio/industrialio-core.c index 2e768bc..88353ae 100644 --- a/drivers/iio/industrialio-core.c +++ b/drivers/iio/industrialio-core.c @@ -101,6 +101,7 @@ static const char * const iio_modifier_names[] = { [IIO_MOD_LIGHT_RED] = "red", [IIO_MOD_LIGHT_GREEN] = "green", [IIO_MOD_LIGHT_BLUE] = "blue", + [IIO_MOD_LIGHT_UV] = "uv", [IIO_MOD_QUATERNION] = "quaternion", [IIO_MOD_TEMP_AMBIENT] = "ambient", [IIO_MOD_TEMP_OBJECT] = "object", diff --git a/include/uapi/linux/iio/types.h b/include/uapi/linux/iio/types.h index c077617..9337ece 100644 --- a/include/uapi/linux/iio/types.h +++ b/include/uapi/linux/iio/types.h @@ -77,6 +77,7 @@ enum iio_modifier { IIO_MOD_Q, IIO_MOD_CO2, IIO_MOD_VOC, + IIO_MOD_LIGHT_UV, }; enum iio_event_type { diff --git a/tools/iio/iio_event_monitor.c b/tools/iio/iio_event_monitor.c index 90980f5..8d7d979 100644 --- a/tools/iio/iio_event_monitor.c +++ b/tools/iio/iio_event_monitor.c @@ -93,6 +93,7 @@ static const char * const iio_modifier_names[] = { [IIO_MOD_LIGHT_RED] = "red", [IIO_MOD_LIGHT_GREEN] = "green", [IIO_MOD_LIGHT_BLUE] = "blue", + [IIO_MOD_LIGHT_UV] = "uv", [IIO_MOD_QUATERNION] = "quaternion", [IIO_MOD_TEMP_AMBIENT] = "ambient", [IIO_MOD_TEMP_OBJECT] = "object", @@ -172,6 +173,7 @@ static bool event_is_known(struct iio_event_data *event) case IIO_MOD_LIGHT_RED: case IIO_MOD_LIGHT_GREEN: case IIO_MOD_LIGHT_BLUE: + case IIO_MOD_LIGHT_UV: case IIO_MOD_QUATERNION: case IIO_MOD_TEMP_AMBIENT: case IIO_MOD_TEMP_OBJECT: -- 1.9.1 ^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [PATCH v2 1/3] iio: Add modifier for UV light 2016-03-20 15:20 ` [PATCH v2 1/3] iio: Add modifier for UV light Peter Meerwald-Stadler @ 2016-03-28 15:36 ` Jonathan Cameron 0 siblings, 0 replies; 7+ messages in thread From: Jonathan Cameron @ 2016-03-28 15:36 UTC (permalink / raw) To: Peter Meerwald-Stadler; +Cc: linux-iio On 20/03/16 15:20, Peter Meerwald-Stadler wrote: > Signed-off-by: Peter Meerwald-Stadler <pmeerw@pmeerw.net> Applied. > --- > Documentation/ABI/testing/sysfs-bus-iio | 4 +++- > drivers/iio/industrialio-core.c | 1 + > include/uapi/linux/iio/types.h | 1 + > tools/iio/iio_event_monitor.c | 2 ++ > 4 files changed, 7 insertions(+), 1 deletion(-) > > diff --git a/Documentation/ABI/testing/sysfs-bus-iio b/Documentation/ABI/testing/sysfs-bus-iio > index 17a9210..6fb9180 100644 > --- a/Documentation/ABI/testing/sysfs-bus-iio > +++ b/Documentation/ABI/testing/sysfs-bus-iio > @@ -1255,12 +1255,14 @@ Description: > What: /sys/.../iio:deviceX/in_intensityY_raw > What: /sys/.../iio:deviceX/in_intensityY_ir_raw > What: /sys/.../iio:deviceX/in_intensityY_both_raw > +What: /sys/.../iio:deviceX/in_intensityY_uv_raw > KernelVersion: 3.4 > Contact: linux-iio@vger.kernel.org > Description: > Unit-less light intensity. Modifiers both and ir indicate > that measurements contains visible and infrared light > - components or just infrared light, respectively. > + components or just infrared light, respectively. Modifier uv indicates > + that measurements contain ultraviolet light components. > > What: /sys/.../iio:deviceX/in_intensity_red_integration_time > What: /sys/.../iio:deviceX/in_intensity_green_integration_time > diff --git a/drivers/iio/industrialio-core.c b/drivers/iio/industrialio-core.c > index 2e768bc..88353ae 100644 > --- a/drivers/iio/industrialio-core.c > +++ b/drivers/iio/industrialio-core.c > @@ -101,6 +101,7 @@ static const char * const iio_modifier_names[] = { > [IIO_MOD_LIGHT_RED] = "red", > [IIO_MOD_LIGHT_GREEN] = "green", > [IIO_MOD_LIGHT_BLUE] = "blue", > + [IIO_MOD_LIGHT_UV] = "uv", > [IIO_MOD_QUATERNION] = "quaternion", > [IIO_MOD_TEMP_AMBIENT] = "ambient", > [IIO_MOD_TEMP_OBJECT] = "object", > diff --git a/include/uapi/linux/iio/types.h b/include/uapi/linux/iio/types.h > index c077617..9337ece 100644 > --- a/include/uapi/linux/iio/types.h > +++ b/include/uapi/linux/iio/types.h > @@ -77,6 +77,7 @@ enum iio_modifier { > IIO_MOD_Q, > IIO_MOD_CO2, > IIO_MOD_VOC, > + IIO_MOD_LIGHT_UV, > }; > > enum iio_event_type { > diff --git a/tools/iio/iio_event_monitor.c b/tools/iio/iio_event_monitor.c > index 90980f5..8d7d979 100644 > --- a/tools/iio/iio_event_monitor.c > +++ b/tools/iio/iio_event_monitor.c > @@ -93,6 +93,7 @@ static const char * const iio_modifier_names[] = { > [IIO_MOD_LIGHT_RED] = "red", > [IIO_MOD_LIGHT_GREEN] = "green", > [IIO_MOD_LIGHT_BLUE] = "blue", > + [IIO_MOD_LIGHT_UV] = "uv", > [IIO_MOD_QUATERNION] = "quaternion", > [IIO_MOD_TEMP_AMBIENT] = "ambient", > [IIO_MOD_TEMP_OBJECT] = "object", > @@ -172,6 +173,7 @@ static bool event_is_known(struct iio_event_data *event) > case IIO_MOD_LIGHT_RED: > case IIO_MOD_LIGHT_GREEN: > case IIO_MOD_LIGHT_BLUE: > + case IIO_MOD_LIGHT_UV: > case IIO_MOD_QUATERNION: > case IIO_MOD_TEMP_AMBIENT: > case IIO_MOD_TEMP_OBJECT: > ^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH v2 2/3] iio: Add channel for UV index 2016-03-20 15:20 [PATCH v2 0/3] Add IIO veml6070 driver and UV light support Peter Meerwald-Stadler 2016-03-20 15:20 ` [PATCH v2 1/3] iio: Add modifier for UV light Peter Meerwald-Stadler @ 2016-03-20 15:20 ` Peter Meerwald-Stadler 2016-03-20 15:20 ` [PATCH v2 3/3] iio: Add Vishay VEML6070 UV A light sensor driver Peter Meerwald-Stadler 2 siblings, 0 replies; 7+ messages in thread From: Peter Meerwald-Stadler @ 2016-03-20 15:20 UTC (permalink / raw) To: Jonathan Cameron; +Cc: linux-iio, Peter Meerwald-Stadler UV index indicating strength of sunburn-producing ultraviolet (UV) radiation Signed-off-by: Peter Meerwald-Stadler <pmeerw@pmeerw.net> --- Documentation/ABI/testing/sysfs-bus-iio | 9 +++++++++ drivers/iio/industrialio-core.c | 1 + include/uapi/linux/iio/types.h | 1 + tools/iio/iio_event_monitor.c | 2 ++ 4 files changed, 13 insertions(+) diff --git a/Documentation/ABI/testing/sysfs-bus-iio b/Documentation/ABI/testing/sysfs-bus-iio index 6fb9180..f155eff 100644 --- a/Documentation/ABI/testing/sysfs-bus-iio +++ b/Documentation/ABI/testing/sysfs-bus-iio @@ -1264,6 +1264,15 @@ Description: components or just infrared light, respectively. Modifier uv indicates that measurements contain ultraviolet light components. +What: /sys/.../iio:deviceX/in_uvindex_input +KernelVersion: 4.6 +Contact: linux-iio@vger.kernel.org +Description: + UV light intensity index measuring the human skin's response to + different wavelength of sunlight weighted according to the + standardised CIE Erythemal Action Spectrum. UV index values range + from 0 (low) to >=11 (extreme). + What: /sys/.../iio:deviceX/in_intensity_red_integration_time What: /sys/.../iio:deviceX/in_intensity_green_integration_time What: /sys/.../iio:deviceX/in_intensity_blue_integration_time diff --git a/drivers/iio/industrialio-core.c b/drivers/iio/industrialio-core.c index 88353ae..190a593 100644 --- a/drivers/iio/industrialio-core.c +++ b/drivers/iio/industrialio-core.c @@ -79,6 +79,7 @@ static const char * const iio_chan_type_name_spec[] = { [IIO_CONCENTRATION] = "concentration", [IIO_RESISTANCE] = "resistance", [IIO_PH] = "ph", + [IIO_UVINDEX] = "uvindex", }; static const char * const iio_modifier_names[] = { diff --git a/include/uapi/linux/iio/types.h b/include/uapi/linux/iio/types.h index 9337ece..b0916fc 100644 --- a/include/uapi/linux/iio/types.h +++ b/include/uapi/linux/iio/types.h @@ -38,6 +38,7 @@ enum iio_chan_type { IIO_CONCENTRATION, IIO_RESISTANCE, IIO_PH, + IIO_UVINDEX, }; enum iio_modifier { diff --git a/tools/iio/iio_event_monitor.c b/tools/iio/iio_event_monitor.c index 8d7d979..d9b7e0f 100644 --- a/tools/iio/iio_event_monitor.c +++ b/tools/iio/iio_event_monitor.c @@ -56,6 +56,7 @@ static const char * const iio_chan_type_name_spec[] = { [IIO_CONCENTRATION] = "concentration", [IIO_RESISTANCE] = "resistance", [IIO_PH] = "ph", + [IIO_UVINDEX] = "uvindex", }; static const char * const iio_ev_type_text[] = { @@ -147,6 +148,7 @@ static bool event_is_known(struct iio_event_data *event) case IIO_CONCENTRATION: case IIO_RESISTANCE: case IIO_PH: + case IIO_UVINDEX: break; default: return false; -- 1.9.1 ^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH v2 3/3] iio: Add Vishay VEML6070 UV A light sensor driver 2016-03-20 15:20 [PATCH v2 0/3] Add IIO veml6070 driver and UV light support Peter Meerwald-Stadler 2016-03-20 15:20 ` [PATCH v2 1/3] iio: Add modifier for UV light Peter Meerwald-Stadler 2016-03-20 15:20 ` [PATCH v2 2/3] iio: Add channel for UV index Peter Meerwald-Stadler @ 2016-03-20 15:20 ` Peter Meerwald-Stadler 2016-03-28 16:02 ` Jonathan Cameron 2 siblings, 1 reply; 7+ messages in thread From: Peter Meerwald-Stadler @ 2016-03-20 15:20 UTC (permalink / raw) To: Jonathan Cameron; +Cc: linux-iio, Peter Meerwald-Stadler ultraviolet (UV) light sensor with I2C interface with a peak sensitivity at 355 nm strangely, chip uses two addresses 0x38 and 0x39 for LSB and MSB data, resp. datasheet: http://www.vishay.com/docs/84277/veml6070.pdf Signed-off-by: Peter Meerwald-Stadler <pmeerw@pmeerw.net> --- drivers/iio/light/Kconfig | 10 ++ drivers/iio/light/Makefile | 1 + drivers/iio/light/veml6070.c | 218 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 229 insertions(+) create mode 100644 drivers/iio/light/veml6070.c diff --git a/drivers/iio/light/Kconfig b/drivers/iio/light/Kconfig index cfd3df8..d2fe64e 100644 --- a/drivers/iio/light/Kconfig +++ b/drivers/iio/light/Kconfig @@ -320,4 +320,14 @@ config VCNL4000 To compile this driver as a module, choose M here: the module will be called vcnl4000. +config VEML6070 + tristate "VEML6070 UV A light sensor" + depends on I2C + help + Say Y here if you want to build a driver for the Vishay VEML6070 UV A + light sensor. + + To compile this driver as a module, choose M here: the + module will be called veml6070. + endmenu diff --git a/drivers/iio/light/Makefile b/drivers/iio/light/Makefile index b2c3105..a447c62 100644 --- a/drivers/iio/light/Makefile +++ b/drivers/iio/light/Makefile @@ -30,3 +30,4 @@ obj-$(CONFIG_TCS3472) += tcs3472.o obj-$(CONFIG_TSL4531) += tsl4531.o obj-$(CONFIG_US5182D) += us5182d.o obj-$(CONFIG_VCNL4000) += vcnl4000.o +obj-$(CONFIG_VEML6070) += veml6070.o diff --git a/drivers/iio/light/veml6070.c b/drivers/iio/light/veml6070.c new file mode 100644 index 0000000..bc1c4cb --- /dev/null +++ b/drivers/iio/light/veml6070.c @@ -0,0 +1,218 @@ +/* + * veml6070.c - Support for Vishay VEML6070 UV A light sensor + * + * Copyright 2016 Peter Meerwald-Stadler <pmeerw@pmeerw.net> + * + * This file is subject to the terms and conditions of version 2 of + * the GNU General Public License. See the file COPYING in the main + * directory of this archive for more details. + * + * IIO driver for VEML6070 (7-bit I2C slave addresses 0x38 and 0x39) + * + * TODO: integration time, ACK signal + */ + +#include <linux/module.h> +#include <linux/i2c.h> +#include <linux/mutex.h> +#include <linux/err.h> +#include <linux/delay.h> + +#include <linux/iio/iio.h> +#include <linux/iio/sysfs.h> + +#define VEML6070_DRV_NAME "veml6070" + +#define VEML6070_ADDR_CONFIG_DATA_MSB 0x38 /* read: MSB data, write: config */ +#define VEML6070_ADDR_DATA_LSB 0x39 /* LSB data */ + +#define VEML6070_COMMAND_ACK BIT(5) /* raise interrupt when over threshold */ +#define VEML6070_COMMAND_IT GENMASK(3, 2) /* bit mask integration time */ +#define VEML6070_COMMAND_RSRVD BIT(1) /* reserved, set to 1 */ +#define VEML6070_COMMAND_SD BIT(0) /* shutdown mode when set */ + +#define VEML6070_IT_10 0x04 /* integration time 1x */ + +struct veml6070_data { + struct i2c_client *client1; + struct i2c_client *client2; + u8 config; + struct mutex lock; +}; + +static int veml6070_read(struct veml6070_data *data) +{ + int ret; + u8 msb, lsb; + + mutex_lock(&data->lock); + + /* disable shutdown */ + ret = i2c_smbus_write_byte(data->client1, + data->config & ~VEML6070_COMMAND_SD); + if (ret < 0) + goto out; + + msleep(125 + 10); /* measurement takes up to 125 ms for IT 1x */ + + ret = i2c_smbus_read_byte(data->client2); /* read MSB, address 0x39 */ + if (ret < 0) + goto out; + msb = ret; + + ret = i2c_smbus_read_byte(data->client1); /* read LSB, address 0x38 */ + if (ret < 0) + goto out; + lsb = ret; + + /* shutdown again */ + ret = i2c_smbus_write_byte(data->client1, data->config); + if (ret < 0) + goto out; + + ret = (msb << 8) | lsb; + +out: + mutex_unlock(&data->lock); + return ret; +} + +static const struct iio_chan_spec veml6070_channels[] = { + { + .type = IIO_INTENSITY, + .modified = 1, + .channel2 = IIO_MOD_LIGHT_UV, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), + }, + { + .type = IIO_UVINDEX, + .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED), + } +}; + +static int veml6070_to_uv_index(unsigned val) +{ + /* + * conversion of raw UV intensity values to UV index depends on + * integration time (IT) and value of the resistor connected to + * the RSET pin (default: 270 KOhm) + */ + unsigned uvi[11] = { + 187, 373, 560, /* low */ + 746, 933, 1120, /* moderate */ + 1308, 1494, /* high */ + 1681, 1868, 2054}; /* very high */ + int i; + + for (i = 0; i < ARRAY_SIZE(uvi); i++) + if (val <= uvi[i]) + return i; + + return 11; /* extreme */ +} + +static int veml6070_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, int *val2, long mask) +{ + struct veml6070_data *data = iio_priv(indio_dev); + int ret; + + switch (mask) { + case IIO_CHAN_INFO_RAW: + case IIO_CHAN_INFO_PROCESSED: + ret = veml6070_read(data); + if (ret < 0) + return ret; + if (mask == IIO_CHAN_INFO_PROCESSED) + *val = veml6070_to_uv_index(ret); + else + *val = ret; + return IIO_VAL_INT; + default: + return -EINVAL; + } +} + +static const struct iio_info veml6070_info = { + .read_raw = veml6070_read_raw, + .driver_module = THIS_MODULE, +}; + +static int veml6070_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct veml6070_data *data; + struct iio_dev *indio_dev; + int ret; + + indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); + if (!indio_dev) + return -ENOMEM; + + data = iio_priv(indio_dev); + i2c_set_clientdata(client, indio_dev); + data->client1 = client; + mutex_init(&data->lock); + + indio_dev->dev.parent = &client->dev; + indio_dev->info = &veml6070_info; + indio_dev->channels = veml6070_channels; + indio_dev->num_channels = ARRAY_SIZE(veml6070_channels); + indio_dev->name = VEML6070_DRV_NAME; + indio_dev->modes = INDIO_DIRECT_MODE; + + data->client2 = i2c_new_dummy(client->adapter, VEML6070_ADDR_DATA_LSB); + if (!data->client2) { + dev_err(&client->dev, "i2c device for second chip address failed\n"); + return -ENODEV; + } + + data->config = VEML6070_IT_10 | VEML6070_COMMAND_RSRVD | + VEML6070_COMMAND_SD; + ret = i2c_smbus_write_byte(data->client1, data->config); + if (ret < 0) + goto fail; + + ret = iio_device_register(indio_dev); + if (ret < 0) + goto fail; + + return ret; + +fail: + i2c_unregister_device(data->client2); + return ret; +} + +static int veml6070_remove(struct i2c_client *client) +{ + struct iio_dev *indio_dev = i2c_get_clientdata(client); + struct veml6070_data *data = iio_priv(indio_dev); + + iio_device_unregister(indio_dev); + i2c_unregister_device(data->client2); + + return 0; +} + +static const struct i2c_device_id veml6070_id[] = { + { "veml6070", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, veml6070_id); + +static struct i2c_driver veml6070_driver = { + .driver = { + .name = VEML6070_DRV_NAME, + }, + .probe = veml6070_probe, + .remove = veml6070_remove, + .id_table = veml6070_id, +}; + +module_i2c_driver(veml6070_driver); + +MODULE_AUTHOR("Peter Meerwald-Stadler <pmeerw@pmeerw.net>"); +MODULE_DESCRIPTION("Vishay VEML6070 UV A light sensor driver"); +MODULE_LICENSE("GPL"); -- 1.9.1 ^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [PATCH v2 3/3] iio: Add Vishay VEML6070 UV A light sensor driver 2016-03-20 15:20 ` [PATCH v2 3/3] iio: Add Vishay VEML6070 UV A light sensor driver Peter Meerwald-Stadler @ 2016-03-28 16:02 ` Jonathan Cameron 2016-04-18 18:50 ` Jonathan Cameron 0 siblings, 1 reply; 7+ messages in thread From: Jonathan Cameron @ 2016-03-28 16:02 UTC (permalink / raw) To: Peter Meerwald-Stadler; +Cc: linux-iio On 20/03/16 15:20, Peter Meerwald-Stadler wrote: > ultraviolet (UV) light sensor with I2C interface with a peak > sensitivity at 355 nm > > strangely, chip uses two addresses 0x38 and 0x39 for LSB and > MSB data, resp. > > datasheet: http://www.vishay.com/docs/84277/veml6070.pdf > > Signed-off-by: Peter Meerwald-Stadler <pmeerw@pmeerw.net> Looks good. Applied to the togreg branch of iio.git - initially pushed out as testing for the autobuilders to play with it. Jonathan > --- > drivers/iio/light/Kconfig | 10 ++ > drivers/iio/light/Makefile | 1 + > drivers/iio/light/veml6070.c | 218 +++++++++++++++++++++++++++++++++++++++++++ > 3 files changed, 229 insertions(+) > create mode 100644 drivers/iio/light/veml6070.c > > diff --git a/drivers/iio/light/Kconfig b/drivers/iio/light/Kconfig > index cfd3df8..d2fe64e 100644 > --- a/drivers/iio/light/Kconfig > +++ b/drivers/iio/light/Kconfig > @@ -320,4 +320,14 @@ config VCNL4000 > To compile this driver as a module, choose M here: the > module will be called vcnl4000. > > +config VEML6070 > + tristate "VEML6070 UV A light sensor" > + depends on I2C > + help > + Say Y here if you want to build a driver for the Vishay VEML6070 UV A > + light sensor. > + > + To compile this driver as a module, choose M here: the > + module will be called veml6070. > + > endmenu > diff --git a/drivers/iio/light/Makefile b/drivers/iio/light/Makefile > index b2c3105..a447c62 100644 > --- a/drivers/iio/light/Makefile > +++ b/drivers/iio/light/Makefile > @@ -30,3 +30,4 @@ obj-$(CONFIG_TCS3472) += tcs3472.o > obj-$(CONFIG_TSL4531) += tsl4531.o > obj-$(CONFIG_US5182D) += us5182d.o > obj-$(CONFIG_VCNL4000) += vcnl4000.o > +obj-$(CONFIG_VEML6070) += veml6070.o > diff --git a/drivers/iio/light/veml6070.c b/drivers/iio/light/veml6070.c > new file mode 100644 > index 0000000..bc1c4cb > --- /dev/null > +++ b/drivers/iio/light/veml6070.c > @@ -0,0 +1,218 @@ > +/* > + * veml6070.c - Support for Vishay VEML6070 UV A light sensor > + * > + * Copyright 2016 Peter Meerwald-Stadler <pmeerw@pmeerw.net> > + * > + * This file is subject to the terms and conditions of version 2 of > + * the GNU General Public License. See the file COPYING in the main > + * directory of this archive for more details. > + * > + * IIO driver for VEML6070 (7-bit I2C slave addresses 0x38 and 0x39) > + * > + * TODO: integration time, ACK signal > + */ > + > +#include <linux/module.h> > +#include <linux/i2c.h> > +#include <linux/mutex.h> > +#include <linux/err.h> > +#include <linux/delay.h> > + > +#include <linux/iio/iio.h> > +#include <linux/iio/sysfs.h> > + > +#define VEML6070_DRV_NAME "veml6070" > + > +#define VEML6070_ADDR_CONFIG_DATA_MSB 0x38 /* read: MSB data, write: config */ > +#define VEML6070_ADDR_DATA_LSB 0x39 /* LSB data */ > + > +#define VEML6070_COMMAND_ACK BIT(5) /* raise interrupt when over threshold */ > +#define VEML6070_COMMAND_IT GENMASK(3, 2) /* bit mask integration time */ > +#define VEML6070_COMMAND_RSRVD BIT(1) /* reserved, set to 1 */ > +#define VEML6070_COMMAND_SD BIT(0) /* shutdown mode when set */ > + > +#define VEML6070_IT_10 0x04 /* integration time 1x */ > + > +struct veml6070_data { > + struct i2c_client *client1; > + struct i2c_client *client2; > + u8 config; > + struct mutex lock; > +}; > + > +static int veml6070_read(struct veml6070_data *data) > +{ > + int ret; > + u8 msb, lsb; > + > + mutex_lock(&data->lock); > + > + /* disable shutdown */ > + ret = i2c_smbus_write_byte(data->client1, > + data->config & ~VEML6070_COMMAND_SD); > + if (ret < 0) > + goto out; > + > + msleep(125 + 10); /* measurement takes up to 125 ms for IT 1x */ > + > + ret = i2c_smbus_read_byte(data->client2); /* read MSB, address 0x39 */ > + if (ret < 0) > + goto out; > + msb = ret; > + > + ret = i2c_smbus_read_byte(data->client1); /* read LSB, address 0x38 */ > + if (ret < 0) > + goto out; > + lsb = ret; > + > + /* shutdown again */ > + ret = i2c_smbus_write_byte(data->client1, data->config); > + if (ret < 0) > + goto out; > + > + ret = (msb << 8) | lsb; > + > +out: > + mutex_unlock(&data->lock); > + return ret; > +} > + > +static const struct iio_chan_spec veml6070_channels[] = { > + { > + .type = IIO_INTENSITY, > + .modified = 1, > + .channel2 = IIO_MOD_LIGHT_UV, > + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), > + }, > + { > + .type = IIO_UVINDEX, > + .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED), > + } > +}; > + > +static int veml6070_to_uv_index(unsigned val) > +{ > + /* > + * conversion of raw UV intensity values to UV index depends on > + * integration time (IT) and value of the resistor connected to > + * the RSET pin (default: 270 KOhm) > + */ > + unsigned uvi[11] = { > + 187, 373, 560, /* low */ > + 746, 933, 1120, /* moderate */ > + 1308, 1494, /* high */ > + 1681, 1868, 2054}; /* very high */ > + int i; > + > + for (i = 0; i < ARRAY_SIZE(uvi); i++) > + if (val <= uvi[i]) > + return i; > + > + return 11; /* extreme */ > +} > + > +static int veml6070_read_raw(struct iio_dev *indio_dev, > + struct iio_chan_spec const *chan, > + int *val, int *val2, long mask) > +{ > + struct veml6070_data *data = iio_priv(indio_dev); > + int ret; > + > + switch (mask) { > + case IIO_CHAN_INFO_RAW: > + case IIO_CHAN_INFO_PROCESSED: > + ret = veml6070_read(data); > + if (ret < 0) > + return ret; > + if (mask == IIO_CHAN_INFO_PROCESSED) > + *val = veml6070_to_uv_index(ret); > + else > + *val = ret; > + return IIO_VAL_INT; > + default: > + return -EINVAL; > + } > +} > + > +static const struct iio_info veml6070_info = { > + .read_raw = veml6070_read_raw, > + .driver_module = THIS_MODULE, > +}; > + > +static int veml6070_probe(struct i2c_client *client, > + const struct i2c_device_id *id) > +{ > + struct veml6070_data *data; > + struct iio_dev *indio_dev; > + int ret; > + > + indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); > + if (!indio_dev) > + return -ENOMEM; > + > + data = iio_priv(indio_dev); > + i2c_set_clientdata(client, indio_dev); > + data->client1 = client; > + mutex_init(&data->lock); > + > + indio_dev->dev.parent = &client->dev; > + indio_dev->info = &veml6070_info; > + indio_dev->channels = veml6070_channels; > + indio_dev->num_channels = ARRAY_SIZE(veml6070_channels); > + indio_dev->name = VEML6070_DRV_NAME; > + indio_dev->modes = INDIO_DIRECT_MODE; > + > + data->client2 = i2c_new_dummy(client->adapter, VEML6070_ADDR_DATA_LSB); > + if (!data->client2) { > + dev_err(&client->dev, "i2c device for second chip address failed\n"); > + return -ENODEV; > + } > + > + data->config = VEML6070_IT_10 | VEML6070_COMMAND_RSRVD | > + VEML6070_COMMAND_SD; > + ret = i2c_smbus_write_byte(data->client1, data->config); > + if (ret < 0) > + goto fail; > + > + ret = iio_device_register(indio_dev); > + if (ret < 0) > + goto fail; > + > + return ret; > + > +fail: > + i2c_unregister_device(data->client2); > + return ret; > +} > + > +static int veml6070_remove(struct i2c_client *client) > +{ > + struct iio_dev *indio_dev = i2c_get_clientdata(client); > + struct veml6070_data *data = iio_priv(indio_dev); > + > + iio_device_unregister(indio_dev); > + i2c_unregister_device(data->client2); > + > + return 0; > +} > + > +static const struct i2c_device_id veml6070_id[] = { > + { "veml6070", 0 }, > + { } > +}; > +MODULE_DEVICE_TABLE(i2c, veml6070_id); > + > +static struct i2c_driver veml6070_driver = { > + .driver = { > + .name = VEML6070_DRV_NAME, > + }, > + .probe = veml6070_probe, > + .remove = veml6070_remove, > + .id_table = veml6070_id, > +}; > + > +module_i2c_driver(veml6070_driver); > + > +MODULE_AUTHOR("Peter Meerwald-Stadler <pmeerw@pmeerw.net>"); > +MODULE_DESCRIPTION("Vishay VEML6070 UV A light sensor driver"); > +MODULE_LICENSE("GPL"); > ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH v2 3/3] iio: Add Vishay VEML6070 UV A light sensor driver 2016-03-28 16:02 ` Jonathan Cameron @ 2016-04-18 18:50 ` Jonathan Cameron 0 siblings, 0 replies; 7+ messages in thread From: Jonathan Cameron @ 2016-04-18 18:50 UTC (permalink / raw) To: Peter Meerwald-Stadler; +Cc: linux-iio On 28/03/16 17:02, Jonathan Cameron wrote: > On 20/03/16 15:20, Peter Meerwald-Stadler wrote: >> ultraviolet (UV) light sensor with I2C interface with a peak >> sensitivity at 355 nm >> >> strangely, chip uses two addresses 0x38 and 0x39 for LSB and >> MSB data, resp. >> >> datasheet: http://www.vishay.com/docs/84277/veml6070.pdf >> >> Signed-off-by: Peter Meerwald-Stadler <pmeerw@pmeerw.net> > Looks good. > > Applied to the togreg branch of iio.git - initially pushed out as testing > for the autobuilders to play with it. Except that apparently I didn't. Odd. Now applied and pushed out for the autobuilders to play with it. Thanks for poking me Peter! I am regularly incompetent and never mind someone pointing out I've mysteriously dropped their patches! (just in case anyone was wondering) Jonathan > > Jonathan >> --- >> drivers/iio/light/Kconfig | 10 ++ >> drivers/iio/light/Makefile | 1 + >> drivers/iio/light/veml6070.c | 218 +++++++++++++++++++++++++++++++++++++++++++ >> 3 files changed, 229 insertions(+) >> create mode 100644 drivers/iio/light/veml6070.c >> >> diff --git a/drivers/iio/light/Kconfig b/drivers/iio/light/Kconfig >> index cfd3df8..d2fe64e 100644 >> --- a/drivers/iio/light/Kconfig >> +++ b/drivers/iio/light/Kconfig >> @@ -320,4 +320,14 @@ config VCNL4000 >> To compile this driver as a module, choose M here: the >> module will be called vcnl4000. >> >> +config VEML6070 >> + tristate "VEML6070 UV A light sensor" >> + depends on I2C >> + help >> + Say Y here if you want to build a driver for the Vishay VEML6070 UV A >> + light sensor. >> + >> + To compile this driver as a module, choose M here: the >> + module will be called veml6070. >> + >> endmenu >> diff --git a/drivers/iio/light/Makefile b/drivers/iio/light/Makefile >> index b2c3105..a447c62 100644 >> --- a/drivers/iio/light/Makefile >> +++ b/drivers/iio/light/Makefile >> @@ -30,3 +30,4 @@ obj-$(CONFIG_TCS3472) += tcs3472.o >> obj-$(CONFIG_TSL4531) += tsl4531.o >> obj-$(CONFIG_US5182D) += us5182d.o >> obj-$(CONFIG_VCNL4000) += vcnl4000.o >> +obj-$(CONFIG_VEML6070) += veml6070.o >> diff --git a/drivers/iio/light/veml6070.c b/drivers/iio/light/veml6070.c >> new file mode 100644 >> index 0000000..bc1c4cb >> --- /dev/null >> +++ b/drivers/iio/light/veml6070.c >> @@ -0,0 +1,218 @@ >> +/* >> + * veml6070.c - Support for Vishay VEML6070 UV A light sensor >> + * >> + * Copyright 2016 Peter Meerwald-Stadler <pmeerw@pmeerw.net> >> + * >> + * This file is subject to the terms and conditions of version 2 of >> + * the GNU General Public License. See the file COPYING in the main >> + * directory of this archive for more details. >> + * >> + * IIO driver for VEML6070 (7-bit I2C slave addresses 0x38 and 0x39) >> + * >> + * TODO: integration time, ACK signal >> + */ >> + >> +#include <linux/module.h> >> +#include <linux/i2c.h> >> +#include <linux/mutex.h> >> +#include <linux/err.h> >> +#include <linux/delay.h> >> + >> +#include <linux/iio/iio.h> >> +#include <linux/iio/sysfs.h> >> + >> +#define VEML6070_DRV_NAME "veml6070" >> + >> +#define VEML6070_ADDR_CONFIG_DATA_MSB 0x38 /* read: MSB data, write: config */ >> +#define VEML6070_ADDR_DATA_LSB 0x39 /* LSB data */ >> + >> +#define VEML6070_COMMAND_ACK BIT(5) /* raise interrupt when over threshold */ >> +#define VEML6070_COMMAND_IT GENMASK(3, 2) /* bit mask integration time */ >> +#define VEML6070_COMMAND_RSRVD BIT(1) /* reserved, set to 1 */ >> +#define VEML6070_COMMAND_SD BIT(0) /* shutdown mode when set */ >> + >> +#define VEML6070_IT_10 0x04 /* integration time 1x */ >> + >> +struct veml6070_data { >> + struct i2c_client *client1; >> + struct i2c_client *client2; >> + u8 config; >> + struct mutex lock; >> +}; >> + >> +static int veml6070_read(struct veml6070_data *data) >> +{ >> + int ret; >> + u8 msb, lsb; >> + >> + mutex_lock(&data->lock); >> + >> + /* disable shutdown */ >> + ret = i2c_smbus_write_byte(data->client1, >> + data->config & ~VEML6070_COMMAND_SD); >> + if (ret < 0) >> + goto out; >> + >> + msleep(125 + 10); /* measurement takes up to 125 ms for IT 1x */ >> + >> + ret = i2c_smbus_read_byte(data->client2); /* read MSB, address 0x39 */ >> + if (ret < 0) >> + goto out; >> + msb = ret; >> + >> + ret = i2c_smbus_read_byte(data->client1); /* read LSB, address 0x38 */ >> + if (ret < 0) >> + goto out; >> + lsb = ret; >> + >> + /* shutdown again */ >> + ret = i2c_smbus_write_byte(data->client1, data->config); >> + if (ret < 0) >> + goto out; >> + >> + ret = (msb << 8) | lsb; >> + >> +out: >> + mutex_unlock(&data->lock); >> + return ret; >> +} >> + >> +static const struct iio_chan_spec veml6070_channels[] = { >> + { >> + .type = IIO_INTENSITY, >> + .modified = 1, >> + .channel2 = IIO_MOD_LIGHT_UV, >> + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), >> + }, >> + { >> + .type = IIO_UVINDEX, >> + .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED), >> + } >> +}; >> + >> +static int veml6070_to_uv_index(unsigned val) >> +{ >> + /* >> + * conversion of raw UV intensity values to UV index depends on >> + * integration time (IT) and value of the resistor connected to >> + * the RSET pin (default: 270 KOhm) >> + */ >> + unsigned uvi[11] = { >> + 187, 373, 560, /* low */ >> + 746, 933, 1120, /* moderate */ >> + 1308, 1494, /* high */ >> + 1681, 1868, 2054}; /* very high */ >> + int i; >> + >> + for (i = 0; i < ARRAY_SIZE(uvi); i++) >> + if (val <= uvi[i]) >> + return i; >> + >> + return 11; /* extreme */ >> +} >> + >> +static int veml6070_read_raw(struct iio_dev *indio_dev, >> + struct iio_chan_spec const *chan, >> + int *val, int *val2, long mask) >> +{ >> + struct veml6070_data *data = iio_priv(indio_dev); >> + int ret; >> + >> + switch (mask) { >> + case IIO_CHAN_INFO_RAW: >> + case IIO_CHAN_INFO_PROCESSED: >> + ret = veml6070_read(data); >> + if (ret < 0) >> + return ret; >> + if (mask == IIO_CHAN_INFO_PROCESSED) >> + *val = veml6070_to_uv_index(ret); >> + else >> + *val = ret; >> + return IIO_VAL_INT; >> + default: >> + return -EINVAL; >> + } >> +} >> + >> +static const struct iio_info veml6070_info = { >> + .read_raw = veml6070_read_raw, >> + .driver_module = THIS_MODULE, >> +}; >> + >> +static int veml6070_probe(struct i2c_client *client, >> + const struct i2c_device_id *id) >> +{ >> + struct veml6070_data *data; >> + struct iio_dev *indio_dev; >> + int ret; >> + >> + indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); >> + if (!indio_dev) >> + return -ENOMEM; >> + >> + data = iio_priv(indio_dev); >> + i2c_set_clientdata(client, indio_dev); >> + data->client1 = client; >> + mutex_init(&data->lock); >> + >> + indio_dev->dev.parent = &client->dev; >> + indio_dev->info = &veml6070_info; >> + indio_dev->channels = veml6070_channels; >> + indio_dev->num_channels = ARRAY_SIZE(veml6070_channels); >> + indio_dev->name = VEML6070_DRV_NAME; >> + indio_dev->modes = INDIO_DIRECT_MODE; >> + >> + data->client2 = i2c_new_dummy(client->adapter, VEML6070_ADDR_DATA_LSB); >> + if (!data->client2) { >> + dev_err(&client->dev, "i2c device for second chip address failed\n"); >> + return -ENODEV; >> + } >> + >> + data->config = VEML6070_IT_10 | VEML6070_COMMAND_RSRVD | >> + VEML6070_COMMAND_SD; >> + ret = i2c_smbus_write_byte(data->client1, data->config); >> + if (ret < 0) >> + goto fail; >> + >> + ret = iio_device_register(indio_dev); >> + if (ret < 0) >> + goto fail; >> + >> + return ret; >> + >> +fail: >> + i2c_unregister_device(data->client2); >> + return ret; >> +} >> + >> +static int veml6070_remove(struct i2c_client *client) >> +{ >> + struct iio_dev *indio_dev = i2c_get_clientdata(client); >> + struct veml6070_data *data = iio_priv(indio_dev); >> + >> + iio_device_unregister(indio_dev); >> + i2c_unregister_device(data->client2); >> + >> + return 0; >> +} >> + >> +static const struct i2c_device_id veml6070_id[] = { >> + { "veml6070", 0 }, >> + { } >> +}; >> +MODULE_DEVICE_TABLE(i2c, veml6070_id); >> + >> +static struct i2c_driver veml6070_driver = { >> + .driver = { >> + .name = VEML6070_DRV_NAME, >> + }, >> + .probe = veml6070_probe, >> + .remove = veml6070_remove, >> + .id_table = veml6070_id, >> +}; >> + >> +module_i2c_driver(veml6070_driver); >> + >> +MODULE_AUTHOR("Peter Meerwald-Stadler <pmeerw@pmeerw.net>"); >> +MODULE_DESCRIPTION("Vishay VEML6070 UV A light sensor driver"); >> +MODULE_LICENSE("GPL"); >> > > -- > To unsubscribe from this list: send the line "unsubscribe linux-iio" in > the body of a message to majordomo@vger.kernel.org > More majordomo info at http://vger.kernel.org/majordomo-info.html > ^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2016-04-18 18:50 UTC | newest] Thread overview: 7+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2016-03-20 15:20 [PATCH v2 0/3] Add IIO veml6070 driver and UV light support Peter Meerwald-Stadler 2016-03-20 15:20 ` [PATCH v2 1/3] iio: Add modifier for UV light Peter Meerwald-Stadler 2016-03-28 15:36 ` Jonathan Cameron 2016-03-20 15:20 ` [PATCH v2 2/3] iio: Add channel for UV index Peter Meerwald-Stadler 2016-03-20 15:20 ` [PATCH v2 3/3] iio: Add Vishay VEML6070 UV A light sensor driver Peter Meerwald-Stadler 2016-03-28 16:02 ` Jonathan Cameron 2016-04-18 18:50 ` Jonathan Cameron
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).