From 2edc8afe0a631287b30e65046dce514d489b1d97 Mon Sep 17 00:00:00 2001 From: Javier Carrasco Date: Mon, 27 Nov 2023 18:34:28 +0100 Subject: [PATCH 1/7] iio: add modifiers for A and B ultraviolet light commit b89710bd215e650f0aaf8ffe7104413d46d44392 upstream. Currently there are only two modifiers for ultraviolet light: a generic one for any ultraviolet light (IIO_MOD_LIGHT_UV) and one for deep ultraviolet (IIO_MOD_LIGHT_DUV), which is also referred as ultraviolet C (UV-C) band and covers short-wave ultraviolet. There are still no modifiers for the long-wave and medium-wave ultraviolet bands. These two bands are the main components used to obtain the UV index on the Earth's surface. Add modifiers for the ultraviolet A (UV-A) and ultraviolet B (UV-B) bands. Signed-off-by: Javier Carrasco Link: https://lore.kernel.org/r/20231110-veml6075-v3-1-6ee46775b422@gmail.com Signed-off-by: Jonathan Cameron --- Documentation/ABI/testing/sysfs-bus-iio | 7 +++++-- drivers/iio/industrialio-core.c | 2 ++ include/uapi/linux/iio/types.h | 2 ++ tools/iio/iio_event_monitor.c | 2 ++ 4 files changed, 11 insertions(+), 2 deletions(-) diff --git a/Documentation/ABI/testing/sysfs-bus-iio b/Documentation/ABI/testing/sysfs-bus-iio index a2854dc9a83931..79bbc3be2fd276 100644 --- a/Documentation/ABI/testing/sysfs-bus-iio +++ b/Documentation/ABI/testing/sysfs-bus-iio @@ -1529,6 +1529,8 @@ 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 +What: /sys/.../iio:deviceX/in_intensityY_uva_raw +What: /sys/.../iio:deviceX/in_intensityY_uvb_raw What: /sys/.../iio:deviceX/in_intensityY_duv_raw KernelVersion: 3.4 Contact: linux-iio@vger.kernel.org @@ -1537,8 +1539,9 @@ Description: that measurements contain visible and infrared light components or just infrared light, respectively. Modifier uv indicates that measurements contain ultraviolet light - components. Modifier duv indicates that measurements - contain deep ultraviolet light components. + components. Modifiers uva, uvb and duv indicate that + measurements contain A, B or deep (C) ultraviolet light + components respectively. What: /sys/.../iio:deviceX/in_uvindex_input KernelVersion: 4.6 diff --git a/drivers/iio/industrialio-core.c b/drivers/iio/industrialio-core.c index 121bde49ccb7d4..6349f4c9d33b60 100644 --- a/drivers/iio/industrialio-core.c +++ b/drivers/iio/industrialio-core.c @@ -113,6 +113,8 @@ static const char * const iio_modifier_names[] = { [IIO_MOD_LIGHT_GREEN] = "green", [IIO_MOD_LIGHT_BLUE] = "blue", [IIO_MOD_LIGHT_UV] = "uv", + [IIO_MOD_LIGHT_UVA] = "uva", + [IIO_MOD_LIGHT_UVB] = "uvb", [IIO_MOD_LIGHT_DUV] = "duv", [IIO_MOD_QUATERNION] = "quaternion", [IIO_MOD_TEMP_AMBIENT] = "ambient", diff --git a/include/uapi/linux/iio/types.h b/include/uapi/linux/iio/types.h index c79f2f046a0be1..bd6da708f98638 100644 --- a/include/uapi/linux/iio/types.h +++ b/include/uapi/linux/iio/types.h @@ -87,6 +87,8 @@ enum iio_modifier { IIO_MOD_CO2, IIO_MOD_VOC, IIO_MOD_LIGHT_UV, + IIO_MOD_LIGHT_UVA, + IIO_MOD_LIGHT_UVB, IIO_MOD_LIGHT_DUV, IIO_MOD_PM1, IIO_MOD_PM2P5, diff --git a/tools/iio/iio_event_monitor.c b/tools/iio/iio_event_monitor.c index 0a5c2bb60030b9..79819c2e81f1e4 100644 --- a/tools/iio/iio_event_monitor.c +++ b/tools/iio/iio_event_monitor.c @@ -101,6 +101,8 @@ static const char * const iio_modifier_names[] = { [IIO_MOD_LIGHT_GREEN] = "green", [IIO_MOD_LIGHT_BLUE] = "blue", [IIO_MOD_LIGHT_UV] = "uv", + [IIO_MOD_LIGHT_UVA] = "uva", + [IIO_MOD_LIGHT_UVB] = "uvb", [IIO_MOD_LIGHT_DUV] = "duv", [IIO_MOD_QUATERNION] = "quaternion", [IIO_MOD_TEMP_AMBIENT] = "ambient", From e77e352f7091c05b1cb2fa8e28d125c36061f9f7 Mon Sep 17 00:00:00 2001 From: Javier Carrasco Date: Sat, 27 Jan 2024 21:02:08 +0100 Subject: [PATCH 2/7] iio: move LIGHT_UVA and LIGHT_UVB to the end of iio_modifier commit 6f6c72acddf4357fcc83593c20ef9064fb42db92 upstream. The new modifiers should have added to the end of the enum, so they do not affect the existing entries. No modifiers were added since then, so they can be moved safely to the end of the list. Move IIO_MOD_LIGHT_UVA and IIO_MOD_LIGHT_UVB to the end of iio_modifier. Fixes: b89710bd215e ("iio: add modifiers for A and B ultraviolet light") Suggested-by: Paul Cercueil Signed-off-by: Javier Carrasco Link: https://lore.kernel.org/r/20240127200208.185815-1-javier.carrasco.cruz@gmail.com Signed-off-by: Jonathan Cameron --- include/uapi/linux/iio/types.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/uapi/linux/iio/types.h b/include/uapi/linux/iio/types.h index bd6da708f98638..620f9fc590e28a 100644 --- a/include/uapi/linux/iio/types.h +++ b/include/uapi/linux/iio/types.h @@ -87,8 +87,6 @@ enum iio_modifier { IIO_MOD_CO2, IIO_MOD_VOC, IIO_MOD_LIGHT_UV, - IIO_MOD_LIGHT_UVA, - IIO_MOD_LIGHT_UVB, IIO_MOD_LIGHT_DUV, IIO_MOD_PM1, IIO_MOD_PM2P5, @@ -103,6 +101,8 @@ enum iio_modifier { IIO_MOD_PITCH, IIO_MOD_YAW, IIO_MOD_ROLL, + IIO_MOD_LIGHT_UVA, + IIO_MOD_LIGHT_UVB, }; enum iio_event_type { From 83355cffc09a4b553bd3141392528303d52af613 Mon Sep 17 00:00:00 2001 From: Javier Carrasco Date: Mon, 27 Nov 2023 18:34:30 +0100 Subject: [PATCH 3/7] iio: light: add VEML6075 UVA and UVB light sensor driver commit 3b82f43238aecd73464aeacc9c73407079511533 upstream. The Vishay VEMl6075 is a low power, 16-bit resolution UVA and UVB light sensor with I2C interface and noise compensation (visible and infrarred). Every UV channel generates an output signal measured in counts per integration period, where the integration time is configurable. This driver adds support for both UV channels and the ultraviolet index (UVI) inferred from them according to the device application note with open-air (no teflon) coefficients. Signed-off-by: Javier Carrasco Link: https://lore.kernel.org/r/20231110-veml6075-v3-3-6ee46775b422@gmail.com Signed-off-by: Jonathan Cameron --- MAINTAINERS | 6 + drivers/iio/light/Kconfig | 11 + drivers/iio/light/Makefile | 1 + drivers/iio/light/veml6075.c | 474 +++++++++++++++++++++++++++++++++++ 4 files changed, 492 insertions(+) create mode 100644 drivers/iio/light/veml6075.c diff --git a/MAINTAINERS b/MAINTAINERS index 6a6e2941c4976a..373ac561e60503 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -23054,6 +23054,12 @@ S: Maintained F: drivers/input/serio/userio.c F: include/uapi/linux/userio.h +VISHAY VEML6075 UVA AND UVB LIGHT SENSOR DRIVER +M: Javier Carrasco +S: Maintained +F: Documentation/devicetree/bindings/iio/light/vishay,veml6075.yaml +F: drivers/iio/light/veml6075.c + VISL VIRTUAL STATELESS DECODER DRIVER M: Daniel Almeida L: linux-media@vger.kernel.org diff --git a/drivers/iio/light/Kconfig b/drivers/iio/light/Kconfig index ddbd1838650ec8..6de3ad43d05194 100644 --- a/drivers/iio/light/Kconfig +++ b/drivers/iio/light/Kconfig @@ -639,6 +639,17 @@ config VEML6070 To compile this driver as a module, choose M here: the module will be called veml6070. +config VEML6075 + tristate "VEML6075 UVA and UVB light sensor" + select REGMAP_I2C + depends on I2C + help + Say Y here if you want to build a driver for the Vishay VEML6075 UVA + and UVB light sensor. + + To compile this driver as a module, choose M here: the + module will be called veml6075. + config VL6180 tristate "VL6180 ALS, range and proximity sensor" depends on I2C diff --git a/drivers/iio/light/Makefile b/drivers/iio/light/Makefile index c0db4c4c36ec9f..c8289e24e3f66a 100644 --- a/drivers/iio/light/Makefile +++ b/drivers/iio/light/Makefile @@ -60,5 +60,6 @@ obj-$(CONFIG_VCNL4000) += vcnl4000.o obj-$(CONFIG_VCNL4035) += vcnl4035.o obj-$(CONFIG_VEML6030) += veml6030.o obj-$(CONFIG_VEML6070) += veml6070.o +obj-$(CONFIG_VEML6075) += veml6075.o obj-$(CONFIG_VL6180) += vl6180.o obj-$(CONFIG_ZOPT2201) += zopt2201.o diff --git a/drivers/iio/light/veml6075.c b/drivers/iio/light/veml6075.c new file mode 100644 index 00000000000000..05d4c0e9015d6e --- /dev/null +++ b/drivers/iio/light/veml6075.c @@ -0,0 +1,474 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Vishay VEML6075 UVA and UVB light sensor + * + * Copyright 2023 Javier Carrasco + * + * 7-bit I2C slave, address 0x10 + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#define VEML6075_CMD_CONF 0x00 /* configuration register */ +#define VEML6075_CMD_UVA 0x07 /* UVA channel */ +#define VEML6075_CMD_UVB 0x09 /* UVB channel */ +#define VEML6075_CMD_COMP1 0x0A /* visible light compensation */ +#define VEML6075_CMD_COMP2 0x0B /* infrarred light compensation */ +#define VEML6075_CMD_ID 0x0C /* device ID */ + +#define VEML6075_CONF_IT GENMASK(6, 4) /* intregration time */ +#define VEML6075_CONF_HD BIT(3) /* dynamic setting */ +#define VEML6075_CONF_TRIG BIT(2) /* trigger */ +#define VEML6075_CONF_AF BIT(1) /* active force enable */ +#define VEML6075_CONF_SD BIT(0) /* shutdown */ + +#define VEML6075_IT_50_MS 0x00 +#define VEML6075_IT_100_MS 0x01 +#define VEML6075_IT_200_MS 0x02 +#define VEML6075_IT_400_MS 0x03 +#define VEML6075_IT_800_MS 0x04 + +#define VEML6075_AF_DISABLE 0x00 +#define VEML6075_AF_ENABLE 0x01 + +#define VEML6075_SD_DISABLE 0x00 +#define VEML6075_SD_ENABLE 0x01 + +/* Open-air coefficients and responsivity */ +#define VEML6075_A_COEF 2220 +#define VEML6075_B_COEF 1330 +#define VEML6075_C_COEF 2950 +#define VEML6075_D_COEF 1740 +#define VEML6075_UVA_RESP 1461 +#define VEML6075_UVB_RESP 2591 + +static const int veml6075_it_ms[] = { 50, 100, 200, 400, 800 }; + +struct veml6075_data { + struct i2c_client *client; + struct regmap *regmap; + /* + * prevent integration time modification and triggering + * measurements while a measurement is underway. + */ + struct mutex lock; +}; + +/* channel number */ +enum veml6075_chan { + CH_UVA, + CH_UVB, +}; + +static const struct iio_chan_spec veml6075_channels[] = { + { + .type = IIO_INTENSITY, + .channel = CH_UVA, + .modified = 1, + .channel2 = IIO_MOD_LIGHT_UVA, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | + BIT(IIO_CHAN_INFO_SCALE), + .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_INT_TIME), + .info_mask_shared_by_all_available = BIT(IIO_CHAN_INFO_INT_TIME), + }, + { + .type = IIO_INTENSITY, + .channel = CH_UVB, + .modified = 1, + .channel2 = IIO_MOD_LIGHT_UVB, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | + BIT(IIO_CHAN_INFO_SCALE), + .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_INT_TIME), + .info_mask_shared_by_all_available = BIT(IIO_CHAN_INFO_INT_TIME), + }, + { + .type = IIO_UVINDEX, + .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED), + .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_INT_TIME), + .info_mask_shared_by_all_available = BIT(IIO_CHAN_INFO_INT_TIME), + }, +}; + +static int veml6075_request_measurement(struct veml6075_data *data) +{ + int ret, conf, int_time; + + ret = regmap_read(data->regmap, VEML6075_CMD_CONF, &conf); + if (ret < 0) + return ret; + + /* disable shutdown and trigger measurement */ + ret = regmap_write(data->regmap, VEML6075_CMD_CONF, + (conf | VEML6075_CONF_TRIG) & ~VEML6075_CONF_SD); + if (ret < 0) + return ret; + + /* + * A measurement requires between 1.30 and 1.40 times the integration + * time for all possible configurations. Using a 1.50 factor simplifies + * operations and ensures reliability under all circumstances. + */ + int_time = veml6075_it_ms[FIELD_GET(VEML6075_CONF_IT, conf)]; + msleep(int_time + (int_time / 2)); + + /* shutdown again, data registers are still accessible */ + return regmap_update_bits(data->regmap, VEML6075_CMD_CONF, + VEML6075_CONF_SD, VEML6075_CONF_SD); +} + +static int veml6075_uva_comp(int raw_uva, int comp1, int comp2) +{ + int comp1a_c, comp2a_c, uva_comp; + + comp1a_c = (comp1 * VEML6075_A_COEF) / 1000U; + comp2a_c = (comp2 * VEML6075_B_COEF) / 1000U; + uva_comp = raw_uva - comp1a_c - comp2a_c; + + return clamp_val(uva_comp, 0, U16_MAX); +} + +static int veml6075_uvb_comp(int raw_uvb, int comp1, int comp2) +{ + int comp1b_c, comp2b_c, uvb_comp; + + comp1b_c = (comp1 * VEML6075_C_COEF) / 1000U; + comp2b_c = (comp2 * VEML6075_D_COEF) / 1000U; + uvb_comp = raw_uvb - comp1b_c - comp2b_c; + + return clamp_val(uvb_comp, 0, U16_MAX); +} + +static int veml6075_read_comp(struct veml6075_data *data, int *c1, int *c2) +{ + int ret; + + ret = regmap_read(data->regmap, VEML6075_CMD_COMP1, c1); + if (ret < 0) + return ret; + + return regmap_read(data->regmap, VEML6075_CMD_COMP2, c2); +} + +static int veml6075_read_uv_direct(struct veml6075_data *data, int chan, + int *val) +{ + int c1, c2, ret; + + guard(mutex)(&data->lock); + + ret = veml6075_request_measurement(data); + if (ret < 0) + return ret; + + ret = veml6075_read_comp(data, &c1, &c2); + if (ret < 0) + return ret; + + switch (chan) { + case CH_UVA: + ret = regmap_read(data->regmap, VEML6075_CMD_UVA, val); + if (ret < 0) + return ret; + + *val = veml6075_uva_comp(*val, c1, c2); + return IIO_VAL_INT; + case CH_UVB: + ret = regmap_read(data->regmap, VEML6075_CMD_UVB, val); + if (ret < 0) + return ret; + + *val = veml6075_uvb_comp(*val, c1, c2); + return IIO_VAL_INT; + default: + return -EINVAL; + } +} + +static int veml6075_read_int_time_index(struct veml6075_data *data) +{ + int ret, conf; + + ret = regmap_read(data->regmap, VEML6075_CMD_CONF, &conf); + if (ret < 0) + return ret; + + return FIELD_GET(VEML6075_CONF_IT, conf); +} + +static int veml6075_read_int_time_ms(struct veml6075_data *data, int *val) +{ + int int_index; + + guard(mutex)(&data->lock); + int_index = veml6075_read_int_time_index(data); + if (int_index < 0) + return int_index; + + *val = veml6075_it_ms[int_index]; + + return IIO_VAL_INT; +} + +static int veml6075_get_uvi_micro(struct veml6075_data *data, int uva_comp, + int uvb_comp) +{ + int uvia_micro = uva_comp * VEML6075_UVA_RESP; + int uvib_micro = uvb_comp * VEML6075_UVB_RESP; + int int_index; + + int_index = veml6075_read_int_time_index(data); + if (int_index < 0) + return int_index; + + switch (int_index) { + case VEML6075_IT_50_MS: + return uvia_micro + uvib_micro; + case VEML6075_IT_100_MS: + case VEML6075_IT_200_MS: + case VEML6075_IT_400_MS: + case VEML6075_IT_800_MS: + return (uvia_micro + uvib_micro) / (2 << int_index); + default: + return -EINVAL; + } +} + +static int veml6075_read_uvi(struct veml6075_data *data, int *val, int *val2) +{ + int ret, c1, c2, uva, uvb, uvi_micro; + + guard(mutex)(&data->lock); + + ret = veml6075_request_measurement(data); + if (ret < 0) + return ret; + + ret = veml6075_read_comp(data, &c1, &c2); + if (ret < 0) + return ret; + + ret = regmap_read(data->regmap, VEML6075_CMD_UVA, &uva); + if (ret < 0) + return ret; + + ret = regmap_read(data->regmap, VEML6075_CMD_UVB, &uvb); + if (ret < 0) + return ret; + + uvi_micro = veml6075_get_uvi_micro(data, veml6075_uva_comp(uva, c1, c2), + veml6075_uvb_comp(uvb, c1, c2)); + if (uvi_micro < 0) + return uvi_micro; + + *val = uvi_micro / MICRO; + *val2 = uvi_micro % MICRO; + + return IIO_VAL_INT_PLUS_MICRO; +} + +static int veml6075_read_responsivity(int chan, int *val, int *val2) +{ + /* scale = 1 / resp */ + switch (chan) { + case CH_UVA: + /* resp = 0.93 c/uW/cm2: scale = 1.75268817 */ + *val = 1; + *val2 = 75268817; + return IIO_VAL_INT_PLUS_NANO; + case CH_UVB: + /* resp = 2.1 c/uW/cm2: scale = 0.476190476 */ + *val = 0; + *val2 = 476190476; + return IIO_VAL_INT_PLUS_NANO; + default: + return -EINVAL; + } +} + +static int veml6075_read_avail(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + const int **vals, int *type, int *length, + long mask) +{ + switch (mask) { + case IIO_CHAN_INFO_INT_TIME: + *length = ARRAY_SIZE(veml6075_it_ms); + *vals = veml6075_it_ms; + *type = IIO_VAL_INT; + return IIO_AVAIL_LIST; + + default: + return -EINVAL; + } +} + +static int veml6075_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, int *val2, long mask) +{ + struct veml6075_data *data = iio_priv(indio_dev); + + switch (mask) { + case IIO_CHAN_INFO_RAW: + return veml6075_read_uv_direct(data, chan->channel, val); + case IIO_CHAN_INFO_PROCESSED: + return veml6075_read_uvi(data, val, val2); + case IIO_CHAN_INFO_INT_TIME: + return veml6075_read_int_time_ms(data, val); + case IIO_CHAN_INFO_SCALE: + return veml6075_read_responsivity(chan->channel, val, val2); + default: + return -EINVAL; + } +} + +static int veml6075_write_int_time_ms(struct veml6075_data *data, int val) +{ + int i = ARRAY_SIZE(veml6075_it_ms); + + guard(mutex)(&data->lock); + + while (i-- > 0) { + if (val == veml6075_it_ms[i]) + break; + } + if (i < 0) + return -EINVAL; + + return regmap_update_bits(data->regmap, VEML6075_CMD_CONF, + VEML6075_CONF_IT, + FIELD_PREP(VEML6075_CONF_IT, i)); +} + +static int veml6075_write_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int val, int val2, long mask) +{ + struct veml6075_data *data = iio_priv(indio_dev); + + switch (mask) { + case IIO_CHAN_INFO_INT_TIME: + return veml6075_write_int_time_ms(data, val); + default: + return -EINVAL; + } +} + +static const struct iio_info veml6075_info = { + .read_avail = veml6075_read_avail, + .read_raw = veml6075_read_raw, + .write_raw = veml6075_write_raw, +}; + +static bool veml6075_readable_reg(struct device *dev, unsigned int reg) +{ + switch (reg) { + case VEML6075_CMD_CONF: + case VEML6075_CMD_UVA: + case VEML6075_CMD_UVB: + case VEML6075_CMD_COMP1: + case VEML6075_CMD_COMP2: + case VEML6075_CMD_ID: + return true; + default: + return false; + } +} + +static bool veml6075_writable_reg(struct device *dev, unsigned int reg) +{ + switch (reg) { + case VEML6075_CMD_CONF: + return true; + default: + return false; + } +} + +static const struct regmap_config veml6075_regmap_config = { + .name = "veml6075", + .reg_bits = 8, + .val_bits = 16, + .max_register = VEML6075_CMD_ID, + .readable_reg = veml6075_readable_reg, + .writeable_reg = veml6075_writable_reg, + .val_format_endian = REGMAP_ENDIAN_LITTLE, +}; + +static int veml6075_probe(struct i2c_client *client) +{ + struct veml6075_data *data; + struct iio_dev *indio_dev; + struct regmap *regmap; + int config, ret; + + indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); + if (!indio_dev) + return -ENOMEM; + + regmap = devm_regmap_init_i2c(client, &veml6075_regmap_config); + if (IS_ERR(regmap)) + return PTR_ERR(regmap); + + data = iio_priv(indio_dev); + data->client = client; + data->regmap = regmap; + + mutex_init(&data->lock); + + indio_dev->name = "veml6075"; + indio_dev->info = &veml6075_info; + indio_dev->channels = veml6075_channels; + indio_dev->num_channels = ARRAY_SIZE(veml6075_channels); + indio_dev->modes = INDIO_DIRECT_MODE; + + ret = devm_regulator_get_enable(&client->dev, "vdd"); + if (ret < 0) + return ret; + + /* default: 100ms integration time, active force enable, shutdown */ + config = FIELD_PREP(VEML6075_CONF_IT, VEML6075_IT_100_MS) | + FIELD_PREP(VEML6075_CONF_AF, VEML6075_AF_ENABLE) | + FIELD_PREP(VEML6075_CONF_SD, VEML6075_SD_ENABLE); + ret = regmap_write(data->regmap, VEML6075_CMD_CONF, config); + if (ret < 0) + return ret; + + return devm_iio_device_register(&client->dev, indio_dev); +} + +static const struct i2c_device_id veml6075_id[] = { + { "veml6075" }, + { } +}; +MODULE_DEVICE_TABLE(i2c, veml6075_id); + +static const struct of_device_id veml6075_of_match[] = { + { .compatible = "vishay,veml6075" }, + {} +}; +MODULE_DEVICE_TABLE(of, veml6075_of_match); + +static struct i2c_driver veml6075_driver = { + .driver = { + .name = "veml6075", + .of_match_table = veml6075_of_match, + }, + .probe = veml6075_probe, + .id_table = veml6075_id, +}; + +module_i2c_driver(veml6075_driver); + +MODULE_AUTHOR("Javier Carrasco "); +MODULE_DESCRIPTION("Vishay VEML6075 UVA and UVB light sensor driver"); +MODULE_LICENSE("GPL"); From ead83686f1b4ed6f62cf7ca30e5acbc6107fdb5c Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Tue, 29 Oct 2024 16:38:41 +0000 Subject: [PATCH 4/7] configs: Back-port several sensors Add config settings for the HTS221, VEML6075 and AS73211 sensors. Link: https://github.com/raspberrypi/linux/issues/6446 Signed-off-by: Phil Elwell --- arch/arm/configs/bcm2709_defconfig | 3 +++ arch/arm/configs/bcm2711_defconfig | 3 +++ arch/arm/configs/bcmrpi_defconfig | 3 +++ arch/arm64/configs/bcm2711_defconfig | 3 +++ arch/arm64/configs/bcm2712_defconfig | 3 +++ arch/arm64/configs/bcmrpi3_defconfig | 3 +++ 6 files changed, 18 insertions(+) diff --git a/arch/arm/configs/bcm2709_defconfig b/arch/arm/configs/bcm2709_defconfig index ae4732a2224f41..f20d5d5a32d86e 100644 --- a/arch/arm/configs/bcm2709_defconfig +++ b/arch/arm/configs/bcm2709_defconfig @@ -1418,14 +1418,17 @@ CONFIG_SPS30_I2C=m CONFIG_MAX30102=m CONFIG_DHT11=m CONFIG_HDC100X=m +CONFIG_HTS221=m CONFIG_HTU21=m CONFIG_SI7020=m CONFIG_BOSCH_BNO055_I2C=m CONFIG_INV_MPU6050_I2C=m CONFIG_APDS9960=m +CONFIG_AS73211=m CONFIG_BH1750=m CONFIG_TSL4531=m CONFIG_VEML6070=m +CONFIG_VEML6075=m CONFIG_IIO_HRTIMER_TRIGGER=m CONFIG_IIO_INTERRUPT_TRIGGER=m CONFIG_IIO_SYSFS_TRIGGER=m diff --git a/arch/arm/configs/bcm2711_defconfig b/arch/arm/configs/bcm2711_defconfig index ec4974041a5a4f..61eae6b7c1d1ef 100644 --- a/arch/arm/configs/bcm2711_defconfig +++ b/arch/arm/configs/bcm2711_defconfig @@ -1450,14 +1450,17 @@ CONFIG_SPS30_I2C=m CONFIG_MAX30102=m CONFIG_DHT11=m CONFIG_HDC100X=m +CONFIG_HTS221=m CONFIG_HTU21=m CONFIG_SI7020=m CONFIG_BOSCH_BNO055_I2C=m CONFIG_INV_MPU6050_I2C=m CONFIG_APDS9960=m +CONFIG_AS73211=m CONFIG_BH1750=m CONFIG_TSL4531=m CONFIG_VEML6070=m +CONFIG_VEML6075=m CONFIG_IIO_HRTIMER_TRIGGER=m CONFIG_IIO_INTERRUPT_TRIGGER=m CONFIG_IIO_SYSFS_TRIGGER=m diff --git a/arch/arm/configs/bcmrpi_defconfig b/arch/arm/configs/bcmrpi_defconfig index 911266f06ab228..b315207fd9ecc6 100644 --- a/arch/arm/configs/bcmrpi_defconfig +++ b/arch/arm/configs/bcmrpi_defconfig @@ -1411,14 +1411,17 @@ CONFIG_SPS30_I2C=m CONFIG_MAX30102=m CONFIG_DHT11=m CONFIG_HDC100X=m +CONFIG_HTS221=m CONFIG_HTU21=m CONFIG_SI7020=m CONFIG_BOSCH_BNO055_I2C=m CONFIG_INV_MPU6050_I2C=m CONFIG_APDS9960=m +CONFIG_AS73211=m CONFIG_BH1750=m CONFIG_TSL4531=m CONFIG_VEML6070=m +CONFIG_VEML6075=m CONFIG_IIO_HRTIMER_TRIGGER=m CONFIG_IIO_INTERRUPT_TRIGGER=m CONFIG_IIO_SYSFS_TRIGGER=m diff --git a/arch/arm64/configs/bcm2711_defconfig b/arch/arm64/configs/bcm2711_defconfig index 845dc739da5f08..ff568bf766dab3 100644 --- a/arch/arm64/configs/bcm2711_defconfig +++ b/arch/arm64/configs/bcm2711_defconfig @@ -1505,14 +1505,17 @@ CONFIG_SPS30_I2C=m CONFIG_MAX30102=m CONFIG_DHT11=m CONFIG_HDC100X=m +CONFIG_HTS221=m CONFIG_HTU21=m CONFIG_SI7020=m CONFIG_BOSCH_BNO055_I2C=m CONFIG_INV_MPU6050_I2C=m CONFIG_APDS9960=m +CONFIG_AS73211=m CONFIG_BH1750=m CONFIG_TSL4531=m CONFIG_VEML6070=m +CONFIG_VEML6075=m CONFIG_IIO_HRTIMER_TRIGGER=m CONFIG_IIO_INTERRUPT_TRIGGER=m CONFIG_IIO_SYSFS_TRIGGER=m diff --git a/arch/arm64/configs/bcm2712_defconfig b/arch/arm64/configs/bcm2712_defconfig index 3bdf65c72b403b..438f6f12d5ddf7 100644 --- a/arch/arm64/configs/bcm2712_defconfig +++ b/arch/arm64/configs/bcm2712_defconfig @@ -1507,14 +1507,17 @@ CONFIG_SPS30_I2C=m CONFIG_MAX30102=m CONFIG_DHT11=m CONFIG_HDC100X=m +CONFIG_HTS221=m CONFIG_HTU21=m CONFIG_SI7020=m CONFIG_BOSCH_BNO055_I2C=m CONFIG_INV_MPU6050_I2C=m CONFIG_APDS9960=m +CONFIG_AS73211=m CONFIG_BH1750=m CONFIG_TSL4531=m CONFIG_VEML6070=m +CONFIG_VEML6075=m CONFIG_IIO_HRTIMER_TRIGGER=m CONFIG_IIO_INTERRUPT_TRIGGER=m CONFIG_IIO_SYSFS_TRIGGER=m diff --git a/arch/arm64/configs/bcmrpi3_defconfig b/arch/arm64/configs/bcmrpi3_defconfig index 7ab46c0502f33a..1fcd88808194de 100644 --- a/arch/arm64/configs/bcmrpi3_defconfig +++ b/arch/arm64/configs/bcmrpi3_defconfig @@ -1388,14 +1388,17 @@ CONFIG_SPS30_I2C=m CONFIG_MAX30102=m CONFIG_DHT11=m CONFIG_HDC100X=m +CONFIG_HTS221=m CONFIG_HTU21=m CONFIG_SI7020=m CONFIG_BOSCH_BNO055_I2C=m CONFIG_INV_MPU6050_I2C=m CONFIG_APDS9960=m +CONFIG_AS73211=m CONFIG_BH1750=m CONFIG_TSL4531=m CONFIG_VEML6070=m +CONFIG_VEML6075=m CONFIG_IIO_HRTIMER_TRIGGER=m CONFIG_IIO_INTERRUPT_TRIGGER=m CONFIG_IIO_SYSFS_TRIGGER=m From d751ed0bb46bc79bafe57e5f2213e561394f36e6 Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Tue, 29 Oct 2024 11:53:45 +0000 Subject: [PATCH 5/7] overlays: Back-port several sensors Extend the i2c-sensor overlay with support for the HTS221, VEML6075 and AS73211 sensors. Link: https://github.com/raspberrypi/linux/issues/6446 Signed-off-by: Phil Elwell --- arch/arm/boot/dts/overlays/README | 8 +++ .../boot/dts/overlays/i2c-sensor-common.dtsi | 58 ++++++++++++++++++- 2 files changed, 65 insertions(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/overlays/README b/arch/arm/boot/dts/overlays/README index f09b965d9ba571..7e1df2bd5e5cea 100644 --- a/arch/arm/boot/dts/overlays/README +++ b/arch/arm/boot/dts/overlays/README @@ -2386,6 +2386,8 @@ Params: addr Set the address for the ADT7410, BH1750, BME280, aht10 Select the Aosong AHT10 temperature and humidity sensor + as73211 Select the AMS AS73211 XYZ true color sensor + bh1750 Select the Rohm BH1750 ambient light sensor Valid addresses 0x23 or 0x5c, default 0x23 @@ -2421,6 +2423,9 @@ Params: addr Set the address for the ADT7410, BH1750, BME280, hdc100x Select the Texas Instruments HDC100x temp sensor Valid addresses 0x40-0x43, default 0x40 + hts221 Select the HTS221 temperature and humidity + sensor + htu21 Select the HTU21 temperature and humidity sensor ina238 Select the TI INA238 power monitor. Valid @@ -2519,6 +2524,9 @@ Params: addr Set the address for the ADT7410, BH1750, BME280, veml6070 Select the Vishay VEML6070 ultraviolet light sensor + veml6075 Select the Vishay VEML6075 UVA and UVB light + sensor + Name: i2c0 Info: Change i2c0 pin usage. Not all pin combinations are usable on all diff --git a/arch/arm/boot/dts/overlays/i2c-sensor-common.dtsi b/arch/arm/boot/dts/overlays/i2c-sensor-common.dtsi index f1662a0de40ac9..46eafe10ae8eeb 100755 --- a/arch/arm/boot/dts/overlays/i2c-sensor-common.dtsi +++ b/arch/arm/boot/dts/overlays/i2c-sensor-common.dtsi @@ -1,5 +1,6 @@ // Definitions for I2C based sensors using the Industrial IO or HWMON interface. #include +#include / { compatible = "brcm,bcm2835"; @@ -562,6 +563,56 @@ }; }; + fragment@37 { + target = <&i2cbus>; + __dormant__ { + #address-cells = <1>; + #size-cells = <0>; + status = "okay"; + + hts221: hts221@5f { + compatible = "st,hts221-humid", "st,hts221"; + reg = <0x5f>; + interrupt-parent = <&gpio>; + interrupts = <4 IRQ_TYPE_EDGE_RISING>; + pinctrl-0 = <&int_pins>; + pinctrl-names = "default"; + }; + }; + }; + + fragment@38 { + target = <&i2cbus>; + __dormant__ { + #address-cells = <1>; + #size-cells = <0>; + status = "okay"; + + veml6075: veml6075@10 { + compatible = "vishay,veml6075"; + reg = <0x10>; + }; + }; + }; + + fragment@39 { + target = <&i2cbus>; + __dormant__ { + #address-cells = <1>; + #size-cells = <0>; + status = "okay"; + + as73211: as73211@74 { + compatible = "ams,as73211"; + reg = <0x74>; + interrupt-parent = <&gpio>; + interrupts = <4 IRQ_TYPE_EDGE_RISING>; + pinctrl-0 = <&int_pins>; + pinctrl-names = "default"; + }; + }; + }; + fragment@99 { target = <&gpio>; __dormant__ { @@ -611,6 +662,9 @@ adt7410 = <0>,"+34"; ina238 = <0>,"+35"; shtc3 = <0>,"+36"; + hts221 = <0>,"+37+99"; + veml6075 = <0>,"+38"; + as73211 = <0>,"+39+99"; addr = <&bme280>,"reg:0", <&bmp280>,"reg:0", <&tmp102>,"reg:0", <&lm75>,"reg:0", <&hdc100x>,"reg:0", <&sht3x>,"reg:0", @@ -625,7 +679,9 @@ <&int_pins>, "reg:0", <&max30102>, "interrupts:0", <&mpu6050>, "interrupts:0", - <&mpu9250>, "interrupts:0"; + <&mpu9250>, "interrupts:0", + <&hts221>, "interrupts:0", + <&as73211>, "interrupts:0"; no_timeout = <&jc42>, "smbus-timeout-disable?"; reset_pin = <&bno055>,"reset-gpios:4", <0>,"+30"; shunt_resistor = <&ina238>,"shunt-resistor:0"; From 35af55d2c1503af5f4db9ce2690d08361d40a151 Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Tue, 29 Oct 2024 11:52:41 +0000 Subject: [PATCH 6/7] configs: Add TCS3472=m Enable support for the TCS3472 family of light sensors. Link: https://github.com/raspberrypi/linux/issues/6446 Signed-off-by: Phil Elwell --- arch/arm/configs/bcm2709_defconfig | 1 + arch/arm/configs/bcm2711_defconfig | 1 + arch/arm/configs/bcmrpi_defconfig | 1 + arch/arm64/configs/bcm2711_defconfig | 1 + arch/arm64/configs/bcm2712_defconfig | 1 + arch/arm64/configs/bcmrpi3_defconfig | 1 + 6 files changed, 6 insertions(+) diff --git a/arch/arm/configs/bcm2709_defconfig b/arch/arm/configs/bcm2709_defconfig index f20d5d5a32d86e..4a8635ac65e8dd 100644 --- a/arch/arm/configs/bcm2709_defconfig +++ b/arch/arm/configs/bcm2709_defconfig @@ -1426,6 +1426,7 @@ CONFIG_INV_MPU6050_I2C=m CONFIG_APDS9960=m CONFIG_AS73211=m CONFIG_BH1750=m +CONFIG_TCS3472=m CONFIG_TSL4531=m CONFIG_VEML6070=m CONFIG_VEML6075=m diff --git a/arch/arm/configs/bcm2711_defconfig b/arch/arm/configs/bcm2711_defconfig index 61eae6b7c1d1ef..94606f214cf17d 100644 --- a/arch/arm/configs/bcm2711_defconfig +++ b/arch/arm/configs/bcm2711_defconfig @@ -1458,6 +1458,7 @@ CONFIG_INV_MPU6050_I2C=m CONFIG_APDS9960=m CONFIG_AS73211=m CONFIG_BH1750=m +CONFIG_TCS3472=m CONFIG_TSL4531=m CONFIG_VEML6070=m CONFIG_VEML6075=m diff --git a/arch/arm/configs/bcmrpi_defconfig b/arch/arm/configs/bcmrpi_defconfig index b315207fd9ecc6..0eedab1737a763 100644 --- a/arch/arm/configs/bcmrpi_defconfig +++ b/arch/arm/configs/bcmrpi_defconfig @@ -1419,6 +1419,7 @@ CONFIG_INV_MPU6050_I2C=m CONFIG_APDS9960=m CONFIG_AS73211=m CONFIG_BH1750=m +CONFIG_TCS3472=m CONFIG_TSL4531=m CONFIG_VEML6070=m CONFIG_VEML6075=m diff --git a/arch/arm64/configs/bcm2711_defconfig b/arch/arm64/configs/bcm2711_defconfig index ff568bf766dab3..097a9c2bdb6278 100644 --- a/arch/arm64/configs/bcm2711_defconfig +++ b/arch/arm64/configs/bcm2711_defconfig @@ -1513,6 +1513,7 @@ CONFIG_INV_MPU6050_I2C=m CONFIG_APDS9960=m CONFIG_AS73211=m CONFIG_BH1750=m +CONFIG_TCS3472=m CONFIG_TSL4531=m CONFIG_VEML6070=m CONFIG_VEML6075=m diff --git a/arch/arm64/configs/bcm2712_defconfig b/arch/arm64/configs/bcm2712_defconfig index 438f6f12d5ddf7..ca7be52d5e42ee 100644 --- a/arch/arm64/configs/bcm2712_defconfig +++ b/arch/arm64/configs/bcm2712_defconfig @@ -1515,6 +1515,7 @@ CONFIG_INV_MPU6050_I2C=m CONFIG_APDS9960=m CONFIG_AS73211=m CONFIG_BH1750=m +CONFIG_TCS3472=m CONFIG_TSL4531=m CONFIG_VEML6070=m CONFIG_VEML6075=m diff --git a/arch/arm64/configs/bcmrpi3_defconfig b/arch/arm64/configs/bcmrpi3_defconfig index 1fcd88808194de..a8a9cb3d7c415b 100644 --- a/arch/arm64/configs/bcmrpi3_defconfig +++ b/arch/arm64/configs/bcmrpi3_defconfig @@ -1396,6 +1396,7 @@ CONFIG_INV_MPU6050_I2C=m CONFIG_APDS9960=m CONFIG_AS73211=m CONFIG_BH1750=m +CONFIG_TCS3472=m CONFIG_TSL4531=m CONFIG_VEML6070=m CONFIG_VEML6075=m From 29c71ae3468a6eb14027364afcc14961140234d6 Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Tue, 29 Oct 2024 11:53:45 +0000 Subject: [PATCH 7/7] overlays: Add TCS3472 and VEML6040 support Extend the i2c-sensor overlay with support for the VEML6040 and TCS3472 family of light sensors. Link: https://github.com/raspberrypi/linux/issues/6446 Signed-off-by: Phil Elwell --- arch/arm/boot/dts/overlays/README | 6 +++ .../boot/dts/overlays/i2c-sensor-common.dtsi | 38 ++++++++++++++++++- 2 files changed, 43 insertions(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/overlays/README b/arch/arm/boot/dts/overlays/README index 7e1df2bd5e5cea..78a93df0304bf5 100644 --- a/arch/arm/boot/dts/overlays/README +++ b/arch/arm/boot/dts/overlays/README @@ -2515,12 +2515,18 @@ Params: addr Set the address for the ADT7410, BH1750, BME280, sgp30 Select the Sensirion SGP30 VOC sensor. Fixed address 0x58. + tcs3472 Select the AMS TAOS TCS3472 family of RGBW light + sensors. + Valid addresses 0x48-0x4b, default 0x48 XXX + tmp102 Select the Texas Instruments TMP102 temp sensor Valid addresses 0x48-0x4b, default 0x48 tsl4531 Select the AMS TSL4531 digital ambient light sensor + veml6040 Select the Vishay VEML6040 RGBW light sensor + veml6070 Select the Vishay VEML6070 ultraviolet light sensor diff --git a/arch/arm/boot/dts/overlays/i2c-sensor-common.dtsi b/arch/arm/boot/dts/overlays/i2c-sensor-common.dtsi index 46eafe10ae8eeb..a04c435a8d80be 100755 --- a/arch/arm/boot/dts/overlays/i2c-sensor-common.dtsi +++ b/arch/arm/boot/dts/overlays/i2c-sensor-common.dtsi @@ -613,6 +613,39 @@ }; }; + fragment@40 { + target = <&i2cbus>; + __dormant__ { + #address-cells = <1>; + #size-cells = <0>; + status = "okay"; + + tcs3472: tcs3472@29 { + compatible = "amstaos,tcs3472"; + reg = <0x29>; + interrupt-parent = <&gpio>; + interrupts = <4 IRQ_TYPE_EDGE_RISING>; + pinctrl-0 = <&int_pins>; + pinctrl-names = "default"; + }; + }; + }; + + fragment@41 { + target = <&i2cbus>; + __dormant__ { + #address-cells = <1>; + #size-cells = <0>; + status = "okay"; + + veml6040: veml6040@10 { + compatible = "vishay,veml6040"; + reg = <0x10>; + status = "okay"; + }; + }; + }; + fragment@99 { target = <&gpio>; __dormant__ { @@ -665,6 +698,8 @@ hts221 = <0>,"+37+99"; veml6075 = <0>,"+38"; as73211 = <0>,"+39+99"; + tcs3472 = <0>,"+40+99"; + veml6040 = <0>,"+41"; addr = <&bme280>,"reg:0", <&bmp280>,"reg:0", <&tmp102>,"reg:0", <&lm75>,"reg:0", <&hdc100x>,"reg:0", <&sht3x>,"reg:0", @@ -681,7 +716,8 @@ <&mpu6050>, "interrupts:0", <&mpu9250>, "interrupts:0", <&hts221>, "interrupts:0", - <&as73211>, "interrupts:0"; + <&as73211>, "interrupts:0", + <&tcs3472>, "interrupts:0"; no_timeout = <&jc42>, "smbus-timeout-disable?"; reset_pin = <&bno055>,"reset-gpios:4", <0>,"+30"; shunt_resistor = <&ina238>,"shunt-resistor:0";