[PATCH 3/3] iio: light: veml6030: add support for veml7700

From: Javier Carrasco
Date: Mon Oct 07 2024 - 16:37:51 EST


The veml7700 contains the same sensor as the veml6030 in a different
package with no interrupt line and no pin to select the I2C address.

To handle the lack of the interrupt line and profit from the existing
support for the veml6030, add a specific iio_chan_spec with no
(num_)event_spec(s), and register the device's info from the
veml6030_info_no_irq struct.

Signed-off-by: Javier Carrasco <javier.carrasco.cruz@xxxxxxxxx>
---
drivers/iio/light/veml6030.c | 108 ++++++++++++++++++++++++++++++++++++-------
1 file changed, 91 insertions(+), 17 deletions(-)

diff --git a/drivers/iio/light/veml6030.c b/drivers/iio/light/veml6030.c
index ca0379945b1c..173c85a05a8d 100644
--- a/drivers/iio/light/veml6030.c
+++ b/drivers/iio/light/veml6030.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0+
/*
- * VEML6030 and VMEL6035 Ambient Light Sensors
+ * VEML6030, VMEL6035 and VEML7700 Ambient Light Sensors
*
* Copyright (c) 2019, Rishi Gupta <gupt21@xxxxxxxxx>
*
@@ -11,6 +11,10 @@
* VEML6035:
* Datasheet: https://www.vishay.com/docs/84889/veml6035.pdf
* Appnote-84944: https://www.vishay.com/docs/84944/designingveml6035.pdf
+ *
+ * VEML7700:
+ * Datasheet: https://www.vishay.com/docs/84286/veml7700.pdf
+ * Appnote-84323: https://www.vishay.com/docs/84323/designingveml7700.pdf
*/

#include <linux/bitfield.h>
@@ -56,7 +60,10 @@ struct veml603x_chip {
const char *name;
const int(*scale_vals)[][2];
const int num_scale_vals;
+ const struct iio_chan_spec *channels;
+ const int num_channels;
int (*hw_init)(struct iio_dev *indio_dev, struct device *dev);
+ int (*set_info)(struct iio_dev *indio_dev);
int (*set_als_gain)(struct iio_dev *indio_dev, int val, int val2);
int (*get_als_gain)(struct iio_dev *indio_dev, int *val, int *val2);
};
@@ -250,6 +257,30 @@ static const struct iio_chan_spec veml6030_channels[] = {
},
};

+static const struct iio_chan_spec veml7700_channels[] = {
+ {
+ .type = IIO_LIGHT,
+ .channel = CH_ALS,
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+ BIT(IIO_CHAN_INFO_PROCESSED) |
+ BIT(IIO_CHAN_INFO_INT_TIME) |
+ BIT(IIO_CHAN_INFO_SCALE),
+ .info_mask_shared_by_all_available = BIT(IIO_CHAN_INFO_INT_TIME) |
+ BIT(IIO_CHAN_INFO_SCALE),
+ },
+ {
+ .type = IIO_INTENSITY,
+ .channel = CH_WHITE,
+ .modified = 1,
+ .channel2 = IIO_MOD_LIGHT_BOTH,
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+ BIT(IIO_CHAN_INFO_INT_TIME) |
+ BIT(IIO_CHAN_INFO_SCALE),
+ .info_mask_shared_by_all_available = BIT(IIO_CHAN_INFO_INT_TIME) |
+ BIT(IIO_CHAN_INFO_SCALE),
+ },
+};
+
static const struct regmap_config veml6030_regmap_config = {
.name = "veml6030_regmap",
.reg_bits = 8,
@@ -862,6 +893,37 @@ static irqreturn_t veml6030_event_handler(int irq, void *private)
return IRQ_HANDLED;
}

+static int veml6030_set_info(struct iio_dev *indio_dev)
+{
+ struct veml6030_data *data = iio_priv(indio_dev);
+ struct i2c_client *client = data->client;
+ int ret;
+
+ if (client->irq) {
+ ret = devm_request_threaded_irq(&client->dev, client->irq,
+ NULL, veml6030_event_handler,
+ IRQF_TRIGGER_LOW | IRQF_ONESHOT,
+ indio_dev->name, indio_dev);
+ if (ret < 0)
+ return dev_err_probe(&client->dev, ret,
+ "irq %d request failed\n",
+ client->irq);
+
+ indio_dev->info = &veml6030_info;
+ } else {
+ indio_dev->info = &veml6030_info_no_irq;
+ }
+
+ return 0;
+}
+
+static int veml7700_set_info(struct iio_dev *indio_dev)
+{
+ indio_dev->info = &veml6030_info_no_irq;
+
+ return 0;
+}
+
/*
* Set ALS gain to 1/8, integration time to 100 ms, PSM to mode 2,
* persistence to 1 x integration time and the threshold
@@ -1007,24 +1069,13 @@ static int veml6030_probe(struct i2c_client *client)
return -EINVAL;

indio_dev->name = data->chip->name;
- indio_dev->channels = veml6030_channels;
- indio_dev->num_channels = ARRAY_SIZE(veml6030_channels);
+ indio_dev->channels = data->chip->channels;
+ indio_dev->num_channels = data->chip->num_channels;
indio_dev->modes = INDIO_DIRECT_MODE;

- if (client->irq) {
- ret = devm_request_threaded_irq(&client->dev, client->irq,
- NULL, veml6030_event_handler,
- IRQF_TRIGGER_LOW | IRQF_ONESHOT,
- indio_dev->name, indio_dev);
- if (ret < 0)
- return dev_err_probe(&client->dev, ret,
- "irq %d request failed\n",
- client->irq);
-
- indio_dev->info = &veml6030_info;
- } else {
- indio_dev->info = &veml6030_info_no_irq;
- }
+ ret = data->chip->set_info(indio_dev);
+ if (ret < 0)
+ return ret;

ret = data->chip->hw_init(indio_dev, &client->dev);
if (ret < 0)
@@ -1066,7 +1117,10 @@ static const struct veml603x_chip veml6030_chip = {
.name = "veml6030",
.scale_vals = &veml6030_scale_vals,
.num_scale_vals = ARRAY_SIZE(veml6030_scale_vals),
+ .channels = veml6030_channels,
+ .num_channels = ARRAY_SIZE(veml6030_channels),
.hw_init = veml6030_hw_init,
+ .set_info = veml6030_set_info,
.set_als_gain = veml6030_set_als_gain,
.get_als_gain = veml6030_get_als_gain,
};
@@ -1075,11 +1129,26 @@ static const struct veml603x_chip veml6035_chip = {
.name = "veml6035",
.scale_vals = &veml6035_scale_vals,
.num_scale_vals = ARRAY_SIZE(veml6035_scale_vals),
+ .channels = veml6030_channels,
+ .num_channels = ARRAY_SIZE(veml6030_channels),
.hw_init = veml6035_hw_init,
+ .set_info = veml6030_set_info,
.set_als_gain = veml6035_set_als_gain,
.get_als_gain = veml6035_get_als_gain,
};

+static const struct veml603x_chip veml7700_chip = {
+ .name = "veml7700",
+ .scale_vals = &veml6030_scale_vals,
+ .num_scale_vals = ARRAY_SIZE(veml6030_scale_vals),
+ .channels = veml7700_channels,
+ .num_channels = ARRAY_SIZE(veml7700_channels),
+ .hw_init = veml6030_hw_init,
+ .set_info = veml7700_set_info,
+ .set_als_gain = veml6030_set_als_gain,
+ .get_als_gain = veml6030_get_als_gain,
+};
+
static const struct of_device_id veml6030_of_match[] = {
{
.compatible = "vishay,veml6030",
@@ -1089,6 +1158,10 @@ static const struct of_device_id veml6030_of_match[] = {
.compatible = "vishay,veml6035",
.data = &veml6035_chip,
},
+ {
+ .compatible = "vishay,veml7700",
+ .data = &veml7700_chip,
+ },
{ }
};
MODULE_DEVICE_TABLE(of, veml6030_of_match);
@@ -1096,6 +1169,7 @@ MODULE_DEVICE_TABLE(of, veml6030_of_match);
static const struct i2c_device_id veml6030_id[] = {
{ "veml6030", (kernel_ulong_t)&veml6030_chip},
{ "veml6035", (kernel_ulong_t)&veml6035_chip},
+ { "veml7700", (kernel_ulong_t)&veml7700_chip},
{ }
};
MODULE_DEVICE_TABLE(i2c, veml6030_id);

--
2.43.0