From: Jonathan Cameron <jic23@kernel.org>
To: Peter Meerwald-Stadler <pmeerw@pmeerw.net>
Cc: linux-iio@vger.kernel.org
Subject: Re: [PATCH v2 3/3] iio: Add Vishay VEML6070 UV A light sensor driver
Date: Mon, 28 Mar 2016 17:02:29 +0100 [thread overview]
Message-ID: <56F95595.4040607@kernel.org> (raw)
In-Reply-To: <1458487224-3872-4-git-send-email-pmeerw@pmeerw.net>
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");
>
next prev parent reply other threads:[~2016-03-28 16:02 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
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 [this message]
2016-04-18 18:50 ` Jonathan Cameron
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=56F95595.4040607@kernel.org \
--to=jic23@kernel.org \
--cc=linux-iio@vger.kernel.org \
--cc=pmeerw@pmeerw.net \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.