Re: [PATCH v2 3/3] iio: Add Vishay VEML6070 UV A light sensor driver

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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@xxxxxxxxxx>
> 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@xxxxxxxxxx>
>> + *
>> + * 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@xxxxxxxxxx>");
>> +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@xxxxxxxxxxxxxxx
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 

--
To unsubscribe from this list: send the line "unsubscribe linux-iio" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Input]     [Linux Kernel]     [Linux SCSI]     [X.org]

  Powered by Linux