From: Marek Vasut <marex@denx.de>
To: Matti Vaittinen <mazziesaccount@gmail.com>, linux-iio@vger.kernel.org
Cc: Alexander Stein <alexander.stein@ew.tq-group.com>,
Andre Werner <andre.werner@systec-electronic.com>,
Andy Shevchenko <andriy.shevchenko@linux.intel.com>,
Bjorn Helgaas <bhelgaas@google.com>,
Conor Dooley <conor+dt@kernel.org>,
Fabio Estevam <festevam@denx.de>,
Guenter Roeck <linux@roeck-us.net>,
Jonathan Cameron <jic23@kernel.org>,
Krzysztof Kozlowski <krzysztof.kozlowski+dt@linaro.org>,
Lars-Peter Clausen <lars@metafoo.de>,
Luca Ceresoli <luca.ceresoli@bootlin.com>,
Mark Brown <broonie@kernel.org>,
Naresh Solanki <naresh.solanki@9elements.com>,
Patrick Rudolph <patrick.rudolph@9elements.com>,
Rob Herring <robh+dt@kernel.org>,
Stefan Windfeldt-Prytz <stefan.windfeldt-prytz@axis.com>,
Vincent Tremblay <vincent@vtremblay.dev>,
devicetree@vger.kernel.org
Subject: Re: [PATCH v4 2/2] iio: light: isl76682: Add ISL76682 driver
Date: Thu, 23 Nov 2023 01:26:19 +0100 [thread overview]
Message-ID: <cd21c72f-d9ff-471d-a08d-9b67bf180950@denx.de> (raw)
In-Reply-To: <8b865546-0e51-45ff-ab76-8189afaa9ad5@gmail.com>
On 11/22/23 13:17, Matti Vaittinen wrote:
> On 11/21/23 05:10, Marek Vasut wrote:
>> The ISL76682 is very basic ALS which only supports ALS or IR mode
>> in four ranges, 1k/4k/16k/64k LUX. There is no IRQ support or any
>> other fancy functionality.
>>
>> Signed-off-by: Marek Vasut <marex@denx.de>
>> ---
>> Cc: Alexander Stein <alexander.stein@ew.tq-group.com>
>> Cc: Andre Werner <andre.werner@systec-electronic.com>
>> Cc: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
>> Cc: Bjorn Helgaas <bhelgaas@google.com>
>> Cc: Conor Dooley <conor+dt@kernel.org>
>> Cc: Fabio Estevam <festevam@denx.de>
>> Cc: Guenter Roeck <linux@roeck-us.net>
>> Cc: Jonathan Cameron <jic23@kernel.org>
>> Cc: Krzysztof Kozlowski <krzysztof.kozlowski+dt@linaro.org>
>> Cc: Lars-Peter Clausen <lars@metafoo.de>
>> Cc: Luca Ceresoli <luca.ceresoli@bootlin.com>
>> Cc: Mark Brown <broonie@kernel.org>
>> Cc: Matti Vaittinen <mazziesaccount@gmail.com>
>> Cc: Naresh Solanki <naresh.solanki@9elements.com>
>> Cc: Patrick Rudolph <patrick.rudolph@9elements.com>
>> Cc: Rob Herring <robh+dt@kernel.org>
>> Cc: Stefan Windfeldt-Prytz <stefan.windfeldt-prytz@axis.com>
>> Cc: Vincent Tremblay <vincent@vtremblay.dev>
>> Cc: devicetree@vger.kernel.org
>> Cc: linux-iio@vger.kernel.org
>> ---
>> V2: - Overhaul the driver
>> - Cache the entire 8-bit command register instead of parts of it
>> and build up and rewrite the entire register if necessary
>> - Fix illumination scale, add intensity scale, add integration time
>> V3: - Limit the read data to 16bit ADC range
>> - Update Kconfig description
>> - Update macros, drop bitshifts
>> - Switch over to table lookup for lux ranges
>> - Switch over to .read_avail instead of attributes
>> - Use guard where applicable
>> - Drop remove function in favor of reset action
>> V4: - Address feedback from Andy
>> - Add missing includes
>> - Change ISL76682_ADC_MAX to BIT(16) - 1
>> - Drop initial ret assignment in isl76682_read_raw()
>> - Move return -EINVAL to default: switch-case branch
>> - Use switch-case consistenly instead of if/else
>> - Drop trailing commas
>> - Add comment to isl76682_clear_configure_reg on command zeroing
>> on failure
>> - Drop i2c_set_clientdata
>> - Update devm_regmap_init_i2c return value handling
>> ---
>> drivers/iio/light/Kconfig | 15 ++
>> drivers/iio/light/Makefile | 1 +
>> drivers/iio/light/isl76682.c | 364 +++++++++++++++++++++++++++++++++++
>> 3 files changed, 380 insertions(+)
>> create mode 100644 drivers/iio/light/isl76682.c
>>
>> diff --git a/drivers/iio/light/Kconfig b/drivers/iio/light/Kconfig
>> index 45edba797e4c7..9e8cdc091556d 100644
>> --- a/drivers/iio/light/Kconfig
>> +++ b/drivers/iio/light/Kconfig
>> @@ -252,6 +252,21 @@ config ISL29125
>> To compile this driver as a module, choose M here: the module
>> will be
>> called isl29125.
>> +config ISL76682
>> + tristate "Intersil ISL76682 Light Sensor"
>> + depends on I2C
>> + select REGMAP_I2C
>> + help
>> + Say Y here if you want to build a driver for the Intersil ISL76682
>> + Ambient Light Sensor and IR Intensity sensor. This driver provides
>> + the readouts via standard IIO sysfs and device interface. Both ALS
>> + illuminance and IR illuminance are provided raw with separate
>> scale
>> + setting which can be configured via sysfs, the default scale is
>> 1000
>> + lux, other options are 4000/16000/64000 lux.
>> +
>> + To compile this driver as a module, choose M here: the module
>> will be
>> + called isl76682.
>> +
>> config HID_SENSOR_ALS
>> depends on HID_SENSOR_HUB
>> select IIO_BUFFER
>> diff --git a/drivers/iio/light/Makefile b/drivers/iio/light/Makefile
>> index c0db4c4c36ec9..09fa585f3109f 100644
>> --- a/drivers/iio/light/Makefile
>> +++ b/drivers/iio/light/Makefile
>> @@ -28,6 +28,7 @@ obj-$(CONFIG_IQS621_ALS) += iqs621-als.o
>> obj-$(CONFIG_SENSORS_ISL29018) += isl29018.o
>> obj-$(CONFIG_SENSORS_ISL29028) += isl29028.o
>> obj-$(CONFIG_ISL29125) += isl29125.o
>> +obj-$(CONFIG_ISL76682) += isl76682.o
>> obj-$(CONFIG_JSA1212) += jsa1212.o
>> obj-$(CONFIG_SENSORS_LM3533) += lm3533-als.o
>> obj-$(CONFIG_LTR501) += ltr501.o
>> diff --git a/drivers/iio/light/isl76682.c b/drivers/iio/light/isl76682.c
>> new file mode 100644
>> index 0000000000000..7f0ccd0d37539
>> --- /dev/null
>> +++ b/drivers/iio/light/isl76682.c
>> @@ -0,0 +1,364 @@
>> +// SPDX-License-Identifier: GPL-2.0-only
>> +/*
>> + * IIO driver for the light sensor ISL76682.
>> + * ISL76682 is Ambient Light Sensor
>> + *
>> + * Copyright (c) 2023 Marek Vasut <marex@denx.de>
>> + */
>> +
>> +#include <linux/array_size.h>
>> +#include <linux/bits.h>
>> +#include <linux/cleanup.h>
>> +#include <linux/delay.h>
>> +#include <linux/err.h>
>> +#include <linux/i2c.h>
>> +#include <linux/module.h>
>> +#include <linux/mutex.h>
>> +#include <linux/regmap.h>
>> +#include <linux/types.h>
>> +
>> +#include <linux/iio/iio.h>
>> +
>> +#define ISL76682_REG_COMMAND 0x00
>> +
>> +#define ISL76682_COMMAND_EN BIT(7)
>> +#define ISL76682_COMMAND_MODE_CONTINUOUS BIT(6)
>> +#define ISL76682_COMMAND_LIGHT_IR BIT(5)
>> +
>> +#define ISL76682_COMMAND_RANGE_LUX_1K 0x0
>> +#define ISL76682_COMMAND_RANGE_LUX_4K 0x1
>> +#define ISL76682_COMMAND_RANGE_LUX_16K 0x2
>> +#define ISL76682_COMMAND_RANGE_LUX_64K 0x3
>> +#define ISL76682_COMMAND_RANGE_LUX_MASK GENMASK(1, 0)
>> +
>> +#define ISL76682_REG_ALSIR_L 0x01
>> +
>> +#define ISL76682_REG_ALSIR_U 0x02
>> +
>> +#define ISL76682_NUM_REGS (ISL76682_REG_ALSIR_U + 1)
>> +
>> +#define ISL76682_CONV_TIME_MS 100
>> +#define ISL76682_INT_TIME_US 90000
>> +
>> +#define ISL76682_ADC_MAX (BIT(16) - 1)
>> +
>> +struct isl76682_chip {
>> + /*
>> + * Lock to synchronize access to device command register
>> + * and the content of range variable below.
>> + */
>> + struct mutex lock;
>> + struct regmap *regmap;
>> + u8 range;
>> + u8 command;
>> +};
>> +
>> +struct isl76682_range {
>> + u8 range;
>> + u32 als;
>> + u32 ir;
>> +};
>> +
>> +static struct isl76682_range isl76682_range_table[] = {
>> + { ISL76682_COMMAND_RANGE_LUX_1K, 15000, 10500 },
>> + { ISL76682_COMMAND_RANGE_LUX_4K, 60000, 42000 },
>> + { ISL76682_COMMAND_RANGE_LUX_16K, 240000, 168000 },
>> + { ISL76682_COMMAND_RANGE_LUX_64K, 960000, 673000 }
>> +};
>> +
>> +static int isl76682_get(struct isl76682_chip *chip, bool mode_ir, int
>> *data)
>> +{
>> + u8 command;
>> + int ret;
>> +
>> + command = ISL76682_COMMAND_EN | ISL76682_COMMAND_MODE_CONTINUOUS |
>> + chip->range;
>> +
>> + if (mode_ir)
>> + command |= ISL76682_COMMAND_LIGHT_IR;
>> +
>> + if (command != chip->command) {
>> + ret = regmap_write(chip->regmap, ISL76682_REG_COMMAND, command);
>> + if (ret)
>> + return ret;
>> +
>> + /* Need to wait for conversion time if ALS/IR mode enabled */
>> + msleep(ISL76682_CONV_TIME_MS);
>> +
>> + chip->command = command;
>> + }
>> +
>> + ret = regmap_bulk_read(chip->regmap, ISL76682_REG_ALSIR_L, data, 2);
>> + *data &= ISL76682_ADC_MAX;
>> + return ret;
>> +}
>> +
>> +static int isl76682_write_raw(struct iio_dev *indio_dev,
>> + struct iio_chan_spec const *chan,
>> + int val, int val2, long mask)
>> +{
>> + struct isl76682_chip *chip = iio_priv(indio_dev);
>> + int i;
>> +
>> + if (chan->type != IIO_LIGHT && chan->type != IIO_INTENSITY)
>> + return -EINVAL;
>> +
>> + if (mask != IIO_CHAN_INFO_SCALE)
>> + return -EINVAL;
>> +
>> + if (val != 0)
>> + return -EINVAL;
>> +
>> + for (i = 0; i < ARRAY_SIZE(isl76682_range_table); i++) {
>> + if (chan->type == IIO_LIGHT) {
>> + if (val2 != isl76682_range_table[i].als)
>> + continue;
>> + } else if (chan->type == IIO_INTENSITY) {
>> + if (val2 != isl76682_range_table[i].ir)
>> + continue;
>> + }
>
> I like this table-based look-up for write (and read) of scales. Looking
> at this I see an analogy to some of the regulator stuff, like for
> example the ramp-up values. What I do very much like in the regulator
> subsystem is the drivers/regulator/helpers.c
>
> I wonder if similar approach would be usable in IIO as well? I mean,
> providing readily written iio_regmap_read/write_raw_<functionality>()
> and iio_available_*() helpers for the simple devices where we just have
> value-register mapping? I mean, driver would just populate something like:
>
> struct iio_scale_desc {
> int *scale_val_table;
> int *scale_val2_table;
> int num_scales;
You'd also need type here (fractional, int+micro, ...), right ?
> int scale_reg_addr;
> int scale_reg_mask;
> };
>
> and call helper like
> int iio_regmap_read_raw_scale(struct iio_dev *idev,
> struct iio_scale_desc *sd, int *val,
> int *val2)"
> provided by IIO framework.
>
> Similar helper for writing new scales and getting available scales.
>
> Later this could be expanded by allowing specifying the type of provided
> values (in the example case, IIO_VAL_INT_PLUS_x - but maybe this would
> be extensible (and worth) to support also the other options?)
>
> I know it's a bit much to be done in the context of this series. Hence I
> am definitely not insisting this to be done here! OTOH, the embedded
> Linux is not in EU next year so maybe Marek would forgive me before we
> meet next time :pondering:
toffee-- forgive++ , hehehe , no worries.
> Anyways - does this sound like a sensible thing to do? I guess it could
> help simplifying some drivers a little.
The only thing I would wonder about is, should such a thing go into
regmap so it can be reused cross-subsystem instead of making this iio
specific ?
> Oh. Only after writing of this I noticed the range is written in HW only
> together with the 'start' command. I guess this is how the IC operates -
The IC is just simple, a few bits in command register to control it and
nothing fancy, so it is just easier to write the 8 bits at a time
instead of doing RMW .
> you need to write all configs together with starting the measurement? Or
> is that just an optimization to avoid extra writes? If it's the first,
> then a suggested iio_regmap_*() -helper wouldn't work here. I might've
> added a comment explaining why range is written in isl76682_get() and
> not here to the isl76682_get().
It is just easier and cheaper to write it all at once instead of RMW .
It also isn't like RMW would win anything here, rather the opposite.
> Anyways - this driver looks good to me. (What a long way of saying that).
>
> Reviewed-by: Matti Vaittinen <mazziesaccount@gmail.com>
Thanks !
next prev parent reply other threads:[~2023-11-23 0:26 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-11-21 3:10 [PATCH v4 1/2] dt-bindings: iio: light: isl76682: Document ISL76682 Marek Vasut
2023-11-21 3:10 ` [PATCH v4 2/2] iio: light: isl76682: Add ISL76682 driver Marek Vasut
2023-11-21 18:09 ` Andy Shevchenko
2023-11-22 0:06 ` Marek Vasut
2023-11-22 12:17 ` Matti Vaittinen
2023-11-23 0:26 ` Marek Vasut [this message]
2023-11-23 7:24 ` Matti Vaittinen
2023-12-15 12:06 ` Matti Vaittinen
2023-12-17 13:06 ` Jonathan Cameron
2023-12-18 9:36 ` Matti Vaittinen
2023-11-25 18:06 ` 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=cd21c72f-d9ff-471d-a08d-9b67bf180950@denx.de \
--to=marex@denx.de \
--cc=alexander.stein@ew.tq-group.com \
--cc=andre.werner@systec-electronic.com \
--cc=andriy.shevchenko@linux.intel.com \
--cc=bhelgaas@google.com \
--cc=broonie@kernel.org \
--cc=conor+dt@kernel.org \
--cc=devicetree@vger.kernel.org \
--cc=festevam@denx.de \
--cc=jic23@kernel.org \
--cc=krzysztof.kozlowski+dt@linaro.org \
--cc=lars@metafoo.de \
--cc=linux-iio@vger.kernel.org \
--cc=linux@roeck-us.net \
--cc=luca.ceresoli@bootlin.com \
--cc=mazziesaccount@gmail.com \
--cc=naresh.solanki@9elements.com \
--cc=patrick.rudolph@9elements.com \
--cc=robh+dt@kernel.org \
--cc=stefan.windfeldt-prytz@axis.com \
--cc=vincent@vtremblay.dev \
/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 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).