* [PATCH v2 1/4] iio: light: ltr501: Switch to read_avail() op from manual attribute registration
2026-11-06 9:19 [PATCH v2 0/4] iio: light: ltr501: Add LTR-659PS-01 prox sensor support Svyatoslav Ryhel
@ 2026-11-06 9:19 ` Svyatoslav Ryhel
2026-11-07 3:20 ` Jonathan Cameron
2026-11-06 9:19 ` [PATCH v2 2/4] iio: light: ltr501: Switch to modern match mechanism Svyatoslav Ryhel
` (2 subsequent siblings)
3 siblings, 1 reply; 13+ messages in thread
From: Svyatoslav Ryhel @ 2026-11-06 9:19 UTC (permalink / raw)
To: Jonathan Cameron, David Lechner, Nuno Sá,
Andy Shevchenko, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Esben Haabendal, Kuppuswamy Sathyanarayanan, Svyatoslav Ryhel,
Uwe Kleine-König (The Capable Hub),
Pan Chuang, Hemanth Selam, Antoniu Miclaus, Nikita Travkin
Cc: linux-iio, devicetree, linux-kernel
Switch to the read_avail() operation from manual attribute group
registration. This eliminates the need for per-chip attribute_group
structures and related ltr501_chip_info iio_info entries.
Signed-off-by: Svyatoslav Ryhel <clamor95@gmail.com>
---
drivers/iio/light/ltr501.c | 153 +++++++++++++------------------------
1 file changed, 52 insertions(+), 101 deletions(-)
diff --git a/drivers/iio/light/ltr501.c b/drivers/iio/light/ltr501.c
index 302be2fc314c5..cc5d7af44d77c 100644
--- a/drivers/iio/light/ltr501.c
+++ b/drivers/iio/light/ltr501.c
@@ -133,6 +133,22 @@ static const struct ltr501_gain ltr559_ps_gain_tbl[] = {
{0, 15624},
};
+static const int int_time_avail[] = {
+ 0, 50000,
+ 0, 100000,
+ 0, 200000,
+ 0, 400000
+};
+
+static const int samp_freq_avail[] = {
+ 20, 0,
+ 10, 0,
+ 5, 0,
+ 2, 0,
+ 1, 0,
+ 0, 500000
+};
+
struct ltr501_chip_info {
u8 partid;
const struct ltr501_gain *als_gain;
@@ -145,8 +161,6 @@ struct ltr501_chip_info {
bool no_irq_support;
struct iio_chan_spec const *channels;
const int no_channels;
- const struct iio_info *info;
- const struct iio_info *info_no_irq;
};
struct ltr501_data {
@@ -590,6 +604,7 @@ static const struct iio_event_spec ltr501_pxs_event_spec[] = {
.channel2 = (_mod), \
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
.info_mask_shared_by_type = (_shared), \
+ .info_mask_shared_by_all_available = (_shared), \
.scan_index = (_idx), \
.scan_type = { \
.sign = 'u', \
@@ -1111,111 +1126,56 @@ static int ltr501_write_event_config(struct iio_dev *indio_dev,
return -EINVAL;
}
-static ssize_t ltr501_show_proximity_scale_avail(struct device *dev,
- struct device_attribute *attr,
- char *buf)
+static int ltr501_read_avail(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ const int **vals, int *type, int *length, long mask)
{
- struct ltr501_data *data = iio_priv(dev_to_iio_dev(dev));
+ struct ltr501_data *data = iio_priv(indio_dev);
const struct ltr501_chip_info *info = data->chip_info;
- ssize_t len = 0;
- int i;
-
- for (i = 0; i < info->ps_gain_tbl_size; i++) {
- if (info->ps_gain[i].scale == LTR501_RESERVED_GAIN)
- continue;
- len += scnprintf(buf + len, PAGE_SIZE - len, "%d.%06d ",
- info->ps_gain[i].scale,
- info->ps_gain[i].uscale);
- }
- buf[len - 1] = '\n';
+ switch (mask) {
+ case IIO_CHAN_INFO_SCALE:
+ if (chan->type == IIO_INTENSITY) {
+ *length = info->als_gain_tbl_size * 2;
+ *vals = (const int *)info->als_gain;
+ } else {
+ *length = info->ps_gain_tbl_size * 2;
+ *vals = (const int *)info->ps_gain;
+ }
+ *type = IIO_VAL_INT_PLUS_MICRO;
+ return IIO_AVAIL_LIST;
- return len;
-}
+ case IIO_CHAN_INFO_INT_TIME:
+ *vals = int_time_avail;
+ *type = IIO_VAL_INT_PLUS_MICRO;
+ *length = ARRAY_SIZE(int_time_avail);
+ return IIO_AVAIL_LIST;
-static ssize_t ltr501_show_intensity_scale_avail(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- struct ltr501_data *data = iio_priv(dev_to_iio_dev(dev));
- const struct ltr501_chip_info *info = data->chip_info;
- ssize_t len = 0;
- int i;
+ case IIO_CHAN_INFO_SAMP_FREQ:
+ *vals = samp_freq_avail;
+ *type = IIO_VAL_INT_PLUS_MICRO;
+ *length = ARRAY_SIZE(samp_freq_avail);
+ return IIO_AVAIL_LIST;
- for (i = 0; i < info->als_gain_tbl_size; i++) {
- if (info->als_gain[i].scale == LTR501_RESERVED_GAIN)
- continue;
- len += scnprintf(buf + len, PAGE_SIZE - len, "%d.%06d ",
- info->als_gain[i].scale,
- info->als_gain[i].uscale);
+ default:
+ return -EINVAL;
}
-
- buf[len - 1] = '\n';
-
- return len;
}
-static IIO_CONST_ATTR_INT_TIME_AVAIL("0.05 0.1 0.2 0.4");
-static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("20 10 5 2 1 0.5");
-
-static IIO_DEVICE_ATTR(in_proximity_scale_available, S_IRUGO,
- ltr501_show_proximity_scale_avail, NULL, 0);
-static IIO_DEVICE_ATTR(in_intensity_scale_available, S_IRUGO,
- ltr501_show_intensity_scale_avail, NULL, 0);
-
-static struct attribute *ltr501_attributes[] = {
- &iio_dev_attr_in_proximity_scale_available.dev_attr.attr,
- &iio_dev_attr_in_intensity_scale_available.dev_attr.attr,
- &iio_const_attr_integration_time_available.dev_attr.attr,
- &iio_const_attr_sampling_frequency_available.dev_attr.attr,
- NULL
-};
-
-static struct attribute *ltr301_attributes[] = {
- &iio_dev_attr_in_intensity_scale_available.dev_attr.attr,
- &iio_const_attr_integration_time_available.dev_attr.attr,
- &iio_const_attr_sampling_frequency_available.dev_attr.attr,
- NULL
-};
-
-static const struct attribute_group ltr501_attribute_group = {
- .attrs = ltr501_attributes,
-};
-
-static const struct attribute_group ltr301_attribute_group = {
- .attrs = ltr301_attributes,
-};
-
static const struct iio_info ltr501_info_no_irq = {
.read_raw = ltr501_read_raw,
.write_raw = ltr501_write_raw,
- .attrs = <r501_attribute_group,
+ .read_avail = ltr501_read_avail,
};
static const struct iio_info ltr501_info = {
.read_raw = ltr501_read_raw,
.write_raw = ltr501_write_raw,
- .attrs = <r501_attribute_group,
- .read_event_value = <r501_read_event,
- .write_event_value = <r501_write_event,
- .read_event_config = <r501_read_event_config,
- .write_event_config = <r501_write_event_config,
-};
-
-static const struct iio_info ltr301_info_no_irq = {
- .read_raw = ltr501_read_raw,
- .write_raw = ltr501_write_raw,
- .attrs = <r301_attribute_group,
-};
-
-static const struct iio_info ltr301_info = {
- .read_raw = ltr501_read_raw,
- .write_raw = ltr501_write_raw,
- .attrs = <r301_attribute_group,
- .read_event_value = <r501_read_event,
- .write_event_value = <r501_write_event,
- .read_event_config = <r501_read_event_config,
- .write_event_config = <r501_write_event_config,
+ .read_avail = ltr501_read_avail,
+ .read_event_value = <r501_read_event,
+ .write_event_value = <r501_write_event,
+ .read_event_config = <r501_read_event_config,
+ .write_event_config = <r501_write_event_config,
};
static const struct ltr501_chip_info ltr501_chip_info_tbl[] = {
@@ -1226,8 +1186,6 @@ static const struct ltr501_chip_info ltr501_chip_info_tbl[] = {
.als_mode_active = BIT(0) | BIT(1),
.als_gain_mask = BIT(3),
.als_gain_shift = 3,
- .info = <r301_info,
- .info_no_irq = <r301_info_no_irq,
.channels = ltr301_channels,
.no_channels = ARRAY_SIZE(ltr301_channels),
},
@@ -1238,8 +1196,6 @@ static const struct ltr501_chip_info ltr501_chip_info_tbl[] = {
.als_mode_active = BIT(0),
.als_gain_mask = BIT(2) | BIT(3) | BIT(4),
.als_gain_shift = 2,
- .info = <r301_info,
- .info_no_irq = <r301_info_no_irq,
.channels = ltr301_channels,
.no_channels = ARRAY_SIZE(ltr301_channels),
},
@@ -1251,7 +1207,6 @@ static const struct ltr501_chip_info ltr501_chip_info_tbl[] = {
.als_gain_mask = BIT(2) | BIT(3) | BIT(4),
.als_gain_shift = 2,
.no_irq_support = true,
- .info_no_irq = <r301_info_no_irq,
.channels = ltr301_channels,
.no_channels = ARRAY_SIZE(ltr301_channels),
},
@@ -1264,8 +1219,6 @@ static const struct ltr501_chip_info ltr501_chip_info_tbl[] = {
.als_mode_active = BIT(0) | BIT(1),
.als_gain_mask = BIT(3),
.als_gain_shift = 3,
- .info = <r501_info,
- .info_no_irq = <r501_info_no_irq,
.channels = ltr501_channels,
.no_channels = ARRAY_SIZE(ltr501_channels),
},
@@ -1278,8 +1231,6 @@ static const struct ltr501_chip_info ltr501_chip_info_tbl[] = {
.als_mode_active = BIT(0),
.als_gain_mask = BIT(2) | BIT(3) | BIT(4),
.als_gain_shift = 2,
- .info = <r501_info,
- .info_no_irq = <r501_info_no_irq,
.channels = ltr501_channels,
.no_channels = ARRAY_SIZE(ltr501_channels),
},
@@ -1548,7 +1499,7 @@ static int ltr501_probe(struct i2c_client *client)
&data->near_level))
data->near_level = 0;
- indio_dev->info = data->chip_info->info;
+ indio_dev->info = <r501_info;
indio_dev->channels = data->chip_info->channels;
indio_dev->num_channels = data->chip_info->no_channels;
indio_dev->name = name;
@@ -1573,7 +1524,7 @@ static int ltr501_probe(struct i2c_client *client)
if (ret)
goto powerdown_on_error;
} else {
- indio_dev->info = data->chip_info->info_no_irq;
+ indio_dev->info = <r501_info_no_irq;
}
ret = iio_triggered_buffer_setup(indio_dev, NULL,
--
2.53.0
^ permalink raw reply [flat|nested] 13+ messages in thread* Re: [PATCH v2 1/4] iio: light: ltr501: Switch to read_avail() op from manual attribute registration
2026-11-06 9:19 ` [PATCH v2 1/4] iio: light: ltr501: Switch to read_avail() op from manual attribute registration Svyatoslav Ryhel
@ 2026-11-07 3:20 ` Jonathan Cameron
2026-11-07 10:10 ` Svyatoslav Ryhel
0 siblings, 1 reply; 13+ messages in thread
From: Jonathan Cameron @ 2026-11-07 3:20 UTC (permalink / raw)
To: Svyatoslav Ryhel
Cc: David Lechner, Nuno Sá,
Andy Shevchenko, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Esben Haabendal, Kuppuswamy Sathyanarayanan,
Uwe Kleine-König (The Capable Hub),
Pan Chuang, Hemanth Selam, Antoniu Miclaus, Nikita Travkin,
linux-iio, devicetree, linux-kernel
On Fri, 6 Nov 2026 11:19:40 +0200
Svyatoslav Ryhel <clamor95@gmail.com> wrote:
> Switch to the read_avail() operation from manual attribute group
> registration. This eliminates the need for per-chip attribute_group
> structures and related ltr501_chip_info iio_info entries.
>
> Signed-off-by: Svyatoslav Ryhel <clamor95@gmail.com>
Given you were quick off the mark on sashiko on v1, I guess
you already saw:
https://sashiko.dev/#/patchset/20261106091943.35783-1-clamor95%40gmail.com
It seems correct that you'll only get one attribute where there were two
before. I suspect it's as simple as the mask should be set of
shared_by_type_available not shared_by_all for scale and shared_by_all
for only sampling frequency and integration time.
The current code is odd in having per type sampling_freq and integration
time as both apply to the light channel as well I think. Not vital
to fix that though so I'd just split the mask to make it work for both
as it does today.
The current way the two Intensity channels is done is very odd.
The .info_mask_shared_by_type should be the same for both of them
(only one set of attrs will be created).
Ideally fix that as a precursor patch (don't label it as a fix
though as it's just a code consistency thing rather than actually
resulting in a change.)
> ---
> drivers/iio/light/ltr501.c | 153 +++++++++++++------------------------
> 1 file changed, 52 insertions(+), 101 deletions(-)
>
> static const struct iio_info ltr501_info = {
> .read_raw = ltr501_read_raw,
> .write_raw = ltr501_write_raw,
> - .attrs = <r501_attribute_group,
> - .read_event_value = <r501_read_event,
> - .write_event_value = <r501_write_event,
> - .read_event_config = <r501_read_event_config,
> - .write_event_config = <r501_write_event_config,
> -};
> -
> -static const struct iio_info ltr301_info_no_irq = {
> - .read_raw = ltr501_read_raw,
> - .write_raw = ltr501_write_raw,
> - .attrs = <r301_attribute_group,
> -};
> -
> -static const struct iio_info ltr301_info = {
> - .read_raw = ltr501_read_raw,
> - .write_raw = ltr501_write_raw,
> - .attrs = <r301_attribute_group,
> - .read_event_value = <r501_read_event,
> - .write_event_value = <r501_write_event,
> - .read_event_config = <r501_read_event_config,
> - .write_event_config = <r501_write_event_config,
> + .read_avail = ltr501_read_avail,
> + .read_event_value = <r501_read_event,
> + .write_event_value = <r501_write_event,
> + .read_event_config = <r501_read_event_config,
> + .write_event_config = <r501_write_event_config,
I'd prefer a precursor patch tidying up the indent as that should make
the diff on this patch easier to read.
> };
^ permalink raw reply [flat|nested] 13+ messages in thread* Re: [PATCH v2 1/4] iio: light: ltr501: Switch to read_avail() op from manual attribute registration
2026-11-07 3:20 ` Jonathan Cameron
@ 2026-11-07 10:10 ` Svyatoslav Ryhel
2026-11-07 10:59 ` Joshua Crofts
0 siblings, 1 reply; 13+ messages in thread
From: Svyatoslav Ryhel @ 2026-11-07 10:10 UTC (permalink / raw)
To: Jonathan Cameron
Cc: David Lechner, Nuno Sá,
Andy Shevchenko, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Esben Haabendal, Kuppuswamy Sathyanarayanan,
Uwe Kleine-König (The Capable Hub),
Pan Chuang, Hemanth Selam, Antoniu Miclaus, Nikita Travkin,
linux-iio, devicetree, linux-kernel
сб, 7 лист. 2026 р. о 05:20 Jonathan Cameron <jic23@kernel.org> пише:
>
> On Fri, 6 Nov 2026 11:19:40 +0200
> Svyatoslav Ryhel <clamor95@gmail.com> wrote:
>
> > Switch to the read_avail() operation from manual attribute group
> > registration. This eliminates the need for per-chip attribute_group
> > structures and related ltr501_chip_info iio_info entries.
> >
> > Signed-off-by: Svyatoslav Ryhel <clamor95@gmail.com>
> Given you were quick off the mark on sashiko on v1, I guess
> you already saw:
> https://sashiko.dev/#/patchset/20261106091943.35783-1-clamor95%40gmail.com
>
> It seems correct that you'll only get one attribute where there were two
> before. I suspect it's as simple as the mask should be set of
> shared_by_type_available not shared_by_all for scale and shared_by_all
> for only sampling frequency and integration time.
>
> The current code is odd in having per type sampling_freq and integration
> time as both apply to the light channel as well I think. Not vital
> to fix that though so I'd just split the mask to make it work for both
> as it does today.
>
- .info_mask_shared_by_all_available = (_shared), \
+ .info_mask_shared_by_type_available = (_avail_type), \
+ .info_mask_shared_by_all_available = (_avail_all), \
...
static const struct iio_chan_spec ltr501_channels[] = {
LTR501_LIGHT_CHANNEL(),
- LTR501_INTENSITY_CHANNEL(0, LTR501_ALS_DATA0, IIO_MOD_LIGHT_BOTH, 0,
+ LTR501_INTENSITY_CHANNEL(0, LTR501_ALS_DATA0,
IIO_MOD_LIGHT_BOTH, 0, 0, 0,
ltr501_als_event_spec,
ARRAY_SIZE(ltr501_als_event_spec)),
LTR501_INTENSITY_CHANNEL(1, LTR501_ALS_DATA1, IIO_MOD_LIGHT_IR,
BIT(IIO_CHAN_INFO_SCALE) |
BIT(IIO_CHAN_INFO_INT_TIME) |
BIT(IIO_CHAN_INFO_SAMP_FREQ),
- NULL, 0),
+ BIT(IIO_CHAN_INFO_SCALE),
+ BIT(IIO_CHAN_INFO_INT_TIME) |
+ BIT(IIO_CHAN_INFO_SAMP_FREQ), NULL, 0),
{
.type = IIO_PROXIMITY,
.address = LTR501_PS_DATA,
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
BIT(IIO_CHAN_INFO_SCALE),
+ .info_mask_separate_available = BIT(IIO_CHAN_INFO_SCALE),
.scan_index = 2,
.scan_type = {
IIO_CHAN_INFO_SCALE is by type and IIO_CHAN_INFO_INT_TIME and
IIO_CHAN_INFO_SAMP_FREQ by all
> The current way the two Intensity channels is done is very odd.
> The .info_mask_shared_by_type should be the same for both of them
> (only one set of attrs will be created).
> Ideally fix that as a precursor patch (don't label it as a fix
> though as it's just a code consistency thing rather than actually
> resulting in a change.)
>
No more precursor patches! I am just a random contributor, not a
driver author, not a subsystem maintainer, not even a random code
janitor. Stop using me for random unrelated fixes!
>
> > ---
> > drivers/iio/light/ltr501.c | 153 +++++++++++++------------------------
> > 1 file changed, 52 insertions(+), 101 deletions(-)
> >
>
> > static const struct iio_info ltr501_info = {
> > .read_raw = ltr501_read_raw,
> > .write_raw = ltr501_write_raw,
> > - .attrs = <r501_attribute_group,
> > - .read_event_value = <r501_read_event,
> > - .write_event_value = <r501_write_event,
> > - .read_event_config = <r501_read_event_config,
> > - .write_event_config = <r501_write_event_config,
> > -};
> > -
> > -static const struct iio_info ltr301_info_no_irq = {
> > - .read_raw = ltr501_read_raw,
> > - .write_raw = ltr501_write_raw,
> > - .attrs = <r301_attribute_group,
> > -};
> > -
> > -static const struct iio_info ltr301_info = {
> > - .read_raw = ltr501_read_raw,
> > - .write_raw = ltr501_write_raw,
> > - .attrs = <r301_attribute_group,
> > - .read_event_value = <r501_read_event,
> > - .write_event_value = <r501_write_event,
> > - .read_event_config = <r501_read_event_config,
> > - .write_event_config = <r501_write_event_config,
> > + .read_avail = ltr501_read_avail,
> > + .read_event_value = <r501_read_event,
> > + .write_event_value = <r501_write_event,
> > + .read_event_config = <r501_read_event_config,
> > + .write_event_config = <r501_write_event_config,
>
> I'd prefer a precursor patch tidying up the indent as that should make
> the diff on this patch easier to read.
>
NO, either this, or I can drop alignment adjustment and you can fix it
on your own whenever you like.
>
> > };
>
^ permalink raw reply [flat|nested] 13+ messages in thread* Re: [PATCH v2 1/4] iio: light: ltr501: Switch to read_avail() op from manual attribute registration
2026-11-07 10:10 ` Svyatoslav Ryhel
@ 2026-11-07 10:59 ` Joshua Crofts
0 siblings, 0 replies; 13+ messages in thread
From: Joshua Crofts @ 2026-11-07 10:59 UTC (permalink / raw)
To: Svyatoslav Ryhel
Cc: Jonathan Cameron, David Lechner, Nuno Sá,
Andy Shevchenko, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Esben Haabendal, Kuppuswamy Sathyanarayanan,
Uwe Kleine-König (The Capable Hub),
Pan Chuang, Hemanth Selam, Antoniu Miclaus, Nikita Travkin,
linux-iio, devicetree, linux-kernel
On Sat, 7 Nov 2026 12:10:06 +0200
Svyatoslav Ryhel <clamor95@gmail.com> wrote:
...
> IIO_CHAN_INFO_SCALE is by type and IIO_CHAN_INFO_INT_TIME and
> IIO_CHAN_INFO_SAMP_FREQ by all
>
> > The current way the two Intensity channels is done is very odd.
> > The .info_mask_shared_by_type should be the same for both of them
> > (only one set of attrs will be created).
> > Ideally fix that as a precursor patch (don't label it as a fix
> > though as it's just a code consistency thing rather than actually
> > resulting in a change.)
> >
>
> No more precursor patches! I am just a random contributor, not a
> driver author, not a subsystem maintainer, not even a random code
> janitor. Stop using me for random unrelated fixes!
It's not an attempt to use you as a janitor; reviewers often suggest
cleanups in the adjacent code so that no new patches are built on
inconsistent code patterns.
Nevertheless, it's only a suggestion, so it's no problem if you don't
have the time or just want to focus on adding new functionality.
--
Kind regards,
Joshua Crofts
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH v2 2/4] iio: light: ltr501: Switch to modern match mechanism
2026-11-06 9:19 [PATCH v2 0/4] iio: light: ltr501: Add LTR-659PS-01 prox sensor support Svyatoslav Ryhel
2026-11-06 9:19 ` [PATCH v2 1/4] iio: light: ltr501: Switch to read_avail() op from manual attribute registration Svyatoslav Ryhel
@ 2026-11-06 9:19 ` Svyatoslav Ryhel
2026-11-07 3:30 ` Jonathan Cameron
2026-11-06 9:19 ` [PATCH v2 3/4] dt-bindings: iio: light: ltr501: Document LTR659 proximity sensor Svyatoslav Ryhel
2026-11-06 9:19 ` [PATCH v2 4/4] iio: light: ltr501: Add support for the LTR-659PS-01 " Svyatoslav Ryhel
3 siblings, 1 reply; 13+ messages in thread
From: Svyatoslav Ryhel @ 2026-11-06 9:19 UTC (permalink / raw)
To: Jonathan Cameron, David Lechner, Nuno Sá,
Andy Shevchenko, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Esben Haabendal, Kuppuswamy Sathyanarayanan, Svyatoslav Ryhel,
Uwe Kleine-König (The Capable Hub),
Pan Chuang, Hemanth Selam, Antoniu Miclaus, Nikita Travkin
Cc: linux-iio, devicetree, linux-kernel
Remove the chip enum, break the chip list structure into individual
elements, and pass each element using i2c_get_match_data().
Signed-off-by: Svyatoslav Ryhel <clamor95@gmail.com>
---
drivers/iio/light/ltr501.c | 165 +++++++++++++++++--------------------
1 file changed, 74 insertions(+), 91 deletions(-)
diff --git a/drivers/iio/light/ltr501.c b/drivers/iio/light/ltr501.c
index cc5d7af44d77c..d5ce6468a229b 100644
--- a/drivers/iio/light/ltr501.c
+++ b/drivers/iio/light/ltr501.c
@@ -90,14 +90,6 @@ struct ltr501_samp_table {
#define LTR501_RESERVED_GAIN -1
-enum {
- ltr301,
- ltr303,
- ltr329,
- ltr501,
- ltr559,
-};
-
struct ltr501_gain {
int scale;
int uscale;
@@ -1178,62 +1170,64 @@ static const struct iio_info ltr501_info = {
.write_event_config = <r501_write_event_config,
};
-static const struct ltr501_chip_info ltr501_chip_info_tbl[] = {
- [ltr301] = {
- .partid = 0x08,
- .als_gain = ltr501_als_gain_tbl,
- .als_gain_tbl_size = ARRAY_SIZE(ltr501_als_gain_tbl),
- .als_mode_active = BIT(0) | BIT(1),
- .als_gain_mask = BIT(3),
- .als_gain_shift = 3,
- .channels = ltr301_channels,
- .no_channels = ARRAY_SIZE(ltr301_channels),
- },
- [ltr303] = {
- .partid = 0x0A,
- .als_gain = ltr559_als_gain_tbl,
- .als_gain_tbl_size = ARRAY_SIZE(ltr559_als_gain_tbl),
- .als_mode_active = BIT(0),
- .als_gain_mask = BIT(2) | BIT(3) | BIT(4),
- .als_gain_shift = 2,
- .channels = ltr301_channels,
- .no_channels = ARRAY_SIZE(ltr301_channels),
- },
- [ltr329] = {
- .partid = 0x0A,
- .als_gain = ltr559_als_gain_tbl,
- .als_gain_tbl_size = ARRAY_SIZE(ltr559_als_gain_tbl),
- .als_mode_active = BIT(0),
- .als_gain_mask = BIT(2) | BIT(3) | BIT(4),
- .als_gain_shift = 2,
- .no_irq_support = true,
- .channels = ltr301_channels,
- .no_channels = ARRAY_SIZE(ltr301_channels),
- },
- [ltr501] = {
- .partid = 0x08,
- .als_gain = ltr501_als_gain_tbl,
- .als_gain_tbl_size = ARRAY_SIZE(ltr501_als_gain_tbl),
- .ps_gain = ltr501_ps_gain_tbl,
- .ps_gain_tbl_size = ARRAY_SIZE(ltr501_ps_gain_tbl),
- .als_mode_active = BIT(0) | BIT(1),
- .als_gain_mask = BIT(3),
- .als_gain_shift = 3,
- .channels = ltr501_channels,
- .no_channels = ARRAY_SIZE(ltr501_channels),
- },
- [ltr559] = {
- .partid = 0x09,
- .als_gain = ltr559_als_gain_tbl,
- .als_gain_tbl_size = ARRAY_SIZE(ltr559_als_gain_tbl),
- .ps_gain = ltr559_ps_gain_tbl,
- .ps_gain_tbl_size = ARRAY_SIZE(ltr559_ps_gain_tbl),
- .als_mode_active = BIT(0),
- .als_gain_mask = BIT(2) | BIT(3) | BIT(4),
- .als_gain_shift = 2,
- .channels = ltr501_channels,
- .no_channels = ARRAY_SIZE(ltr501_channels),
- },
+static const struct ltr501_chip_info ltr301_chip_info_tbl = {
+ .partid = 0x08,
+ .als_gain = ltr501_als_gain_tbl,
+ .als_gain_tbl_size = ARRAY_SIZE(ltr501_als_gain_tbl),
+ .als_mode_active = BIT(0) | BIT(1),
+ .als_gain_mask = BIT(3),
+ .als_gain_shift = 3,
+ .channels = ltr301_channels,
+ .no_channels = ARRAY_SIZE(ltr301_channels),
+};
+
+static const struct ltr501_chip_info ltr303_chip_info_tbl = {
+ .partid = 0x0A,
+ .als_gain = ltr559_als_gain_tbl,
+ .als_gain_tbl_size = ARRAY_SIZE(ltr559_als_gain_tbl),
+ .als_mode_active = BIT(0),
+ .als_gain_mask = BIT(2) | BIT(3) | BIT(4),
+ .als_gain_shift = 2,
+ .channels = ltr301_channels,
+ .no_channels = ARRAY_SIZE(ltr301_channels),
+};
+
+static const struct ltr501_chip_info ltr329_chip_info_tbl = {
+ .partid = 0x0A,
+ .als_gain = ltr559_als_gain_tbl,
+ .als_gain_tbl_size = ARRAY_SIZE(ltr559_als_gain_tbl),
+ .als_mode_active = BIT(0),
+ .als_gain_mask = BIT(2) | BIT(3) | BIT(4),
+ .als_gain_shift = 2,
+ .no_irq_support = true,
+ .channels = ltr301_channels,
+ .no_channels = ARRAY_SIZE(ltr301_channels),
+};
+
+static const struct ltr501_chip_info ltr501_chip_info_tbl = {
+ .partid = 0x08,
+ .als_gain = ltr501_als_gain_tbl,
+ .als_gain_tbl_size = ARRAY_SIZE(ltr501_als_gain_tbl),
+ .ps_gain = ltr501_ps_gain_tbl,
+ .ps_gain_tbl_size = ARRAY_SIZE(ltr501_ps_gain_tbl),
+ .als_mode_active = BIT(0) | BIT(1),
+ .als_gain_mask = BIT(3),
+ .als_gain_shift = 3,
+ .channels = ltr501_channels,
+ .no_channels = ARRAY_SIZE(ltr501_channels),
+};
+
+static const struct ltr501_chip_info ltr559_chip_info_tbl = {
+ .partid = 0x09,
+ .als_gain = ltr559_als_gain_tbl,
+ .als_gain_tbl_size = ARRAY_SIZE(ltr559_als_gain_tbl),
+ .ps_gain = ltr559_ps_gain_tbl,
+ .ps_gain_tbl_size = ARRAY_SIZE(ltr559_ps_gain_tbl),
+ .als_mode_active = BIT(0),
+ .als_gain_mask = BIT(2) | BIT(3) | BIT(4),
+ .als_gain_shift = 2,
+ .channels = ltr501_channels,
+ .no_channels = ARRAY_SIZE(ltr501_channels),
};
static int ltr501_write_contr(struct ltr501_data *data, u8 als_val, u8 ps_val)
@@ -1393,14 +1387,11 @@ static int ltr501_powerdown(struct ltr501_data *data)
static int ltr501_probe(struct i2c_client *client)
{
- const struct i2c_device_id *id = i2c_client_get_device_id(client);
static const char * const regulator_names[] = { "vdd", "vddio" };
struct ltr501_data *data;
struct iio_dev *indio_dev;
struct regmap *regmap;
- const void *ddata = NULL;
- int partid, chip_idx;
- const char *name;
+ int partid;
int ret;
indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
@@ -1480,18 +1471,10 @@ static int ltr501_probe(struct i2c_client *client)
if (ret < 0)
return ret;
- if (id) {
- name = id->name;
- chip_idx = id->driver_data;
- } else {
- name = iio_get_acpi_device_name_and_data(&client->dev, &ddata);
- chip_idx = (intptr_t)ddata;
- }
- if (!name)
+ data->chip_info = i2c_get_match_data(client);
+ if (!data->chip_info)
return -ENODEV;
- data->chip_info = <r501_chip_info_tbl[chip_idx];
-
if ((partid >> 4) != data->chip_info->partid)
return -ENODEV;
@@ -1502,7 +1485,7 @@ static int ltr501_probe(struct i2c_client *client)
indio_dev->info = <r501_info;
indio_dev->channels = data->chip_info->channels;
indio_dev->num_channels = data->chip_info->no_channels;
- indio_dev->name = name;
+ indio_dev->name = client->name;
indio_dev->modes = INDIO_DIRECT_MODE;
ret = ltr501_init(data);
@@ -1573,29 +1556,29 @@ static int ltr501_resume(struct device *dev)
static DEFINE_SIMPLE_DEV_PM_OPS(ltr501_pm_ops, ltr501_suspend, ltr501_resume);
static const struct acpi_device_id ltr_acpi_match[] = {
- { "LTER0301", ltr301 },
+ { "LTER0301", .driver_data = (kernel_ulong_t)<r301_chip_info_tbl },
/* https://www.catalog.update.microsoft.com/Search.aspx?q=lter0303 */
- { "LTER0303", ltr303 },
+ { "LTER0303", .driver_data = (kernel_ulong_t)<r303_chip_info_tbl },
{ }
};
MODULE_DEVICE_TABLE(acpi, ltr_acpi_match);
static const struct i2c_device_id ltr501_id[] = {
- { .name = "ltr301", .driver_data = ltr301 },
- { .name = "ltr303", .driver_data = ltr303 },
- { .name = "ltr329", .driver_data = ltr329 },
- { .name = "ltr501", .driver_data = ltr501 },
- { .name = "ltr559", .driver_data = ltr559 },
+ { .name = "ltr301", .driver_data = (kernel_ulong_t)<r301_chip_info_tbl },
+ { .name = "ltr303", .driver_data = (kernel_ulong_t)<r303_chip_info_tbl },
+ { .name = "ltr329", .driver_data = (kernel_ulong_t)<r329_chip_info_tbl },
+ { .name = "ltr501", .driver_data = (kernel_ulong_t)<r501_chip_info_tbl },
+ { .name = "ltr559", .driver_data = (kernel_ulong_t)<r559_chip_info_tbl },
{ }
};
MODULE_DEVICE_TABLE(i2c, ltr501_id);
static const struct of_device_id ltr501_of_match[] = {
- { .compatible = "liteon,ltr301", },
- { .compatible = "liteon,ltr303", },
- { .compatible = "liteon,ltr329", },
- { .compatible = "liteon,ltr501", },
- { .compatible = "liteon,ltr559", },
+ { .compatible = "liteon,ltr301", .data = <r301_chip_info_tbl },
+ { .compatible = "liteon,ltr303", .data = <r303_chip_info_tbl },
+ { .compatible = "liteon,ltr329", .data = <r329_chip_info_tbl },
+ { .compatible = "liteon,ltr501", .data = <r501_chip_info_tbl },
+ { .compatible = "liteon,ltr559", .data = <r559_chip_info_tbl },
{ }
};
MODULE_DEVICE_TABLE(of, ltr501_of_match);
--
2.53.0
^ permalink raw reply [flat|nested] 13+ messages in thread* Re: [PATCH v2 2/4] iio: light: ltr501: Switch to modern match mechanism
2026-11-06 9:19 ` [PATCH v2 2/4] iio: light: ltr501: Switch to modern match mechanism Svyatoslav Ryhel
@ 2026-11-07 3:30 ` Jonathan Cameron
2026-11-07 10:13 ` Svyatoslav Ryhel
0 siblings, 1 reply; 13+ messages in thread
From: Jonathan Cameron @ 2026-11-07 3:30 UTC (permalink / raw)
To: Svyatoslav Ryhel
Cc: David Lechner, Nuno Sá,
Andy Shevchenko, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Esben Haabendal, Kuppuswamy Sathyanarayanan,
Uwe Kleine-König (The Capable Hub),
Pan Chuang, Hemanth Selam, Antoniu Miclaus, Nikita Travkin,
linux-iio, devicetree, linux-kernel
On Fri, 6 Nov 2026 11:19:41 +0200
Svyatoslav Ryhel <clamor95@gmail.com> wrote:
> Remove the chip enum, break the chip list structure into individual
> elements, and pass each element using i2c_get_match_data().
Sashiko calls out that for ACPI this results in an ABI change.
The original code did the ABI wrong but that unfortunately doesn't
mean we can change this one as it is an artefact of a time when
we weren't so careful about those names.
So you'll need to put special handling back in for the ACPI parts
and that name. Some other things in the existing code noted inline
that would be nice to clean up whilst you are here.
>
> Signed-off-by: Svyatoslav Ryhel <clamor95@gmail.com>
> ---
> drivers/iio/light/ltr501.c | 165 +++++++++++++++++--------------------
> 1 file changed, 74 insertions(+), 91 deletions(-)
>
> diff --git a/drivers/iio/light/ltr501.c b/drivers/iio/light/ltr501.c
> index cc5d7af44d77c..d5ce6468a229b 100644
> --- a/drivers/iio/light/ltr501.c
> +++ b/drivers/iio/light/ltr501.c
> +static const struct ltr501_chip_info ltr301_chip_info_tbl = {
> + .partid = 0x08,
> + .als_gain = ltr501_als_gain_tbl,
> + .als_gain_tbl_size = ARRAY_SIZE(ltr501_als_gain_tbl),
> + .als_mode_active = BIT(0) | BIT(1),
> + .als_gain_mask = BIT(3),
> + .als_gain_shift = 3,
> + .channels = ltr301_channels,
> + .no_channels = ARRAY_SIZE(ltr301_channels),
> +};
> +
> +static const struct ltr501_chip_info ltr303_chip_info_tbl = {
> + .partid = 0x0A,
> + .als_gain = ltr559_als_gain_tbl,
> + .als_gain_tbl_size = ARRAY_SIZE(ltr559_als_gain_tbl),
> + .als_mode_active = BIT(0),
> + .als_gain_mask = BIT(2) | BIT(3) | BIT(4),
> + .als_gain_shift = 2,
> + .channels = ltr301_channels,
> + .no_channels = ARRAY_SIZE(ltr301_channels),
> +};
> +
> +static const struct ltr501_chip_info ltr329_chip_info_tbl = {
> + .partid = 0x0A,
> + .als_gain = ltr559_als_gain_tbl,
> + .als_gain_tbl_size = ARRAY_SIZE(ltr559_als_gain_tbl),
> + .als_mode_active = BIT(0),
> + .als_gain_mask = BIT(2) | BIT(3) | BIT(4),
As below. Same for all the others. That would be a separate
cleanup patch though -> perhaps do it with getting rid of
the als_gain_shift.
> + .als_gain_shift = 2,
> + .no_irq_support = true,
> + .channels = ltr301_channels,
> + .no_channels = ARRAY_SIZE(ltr301_channels),
> +};
> +
> +static const struct ltr501_chip_info ltr501_chip_info_tbl = {
> + .partid = 0x08,
> + .als_gain = ltr501_als_gain_tbl,
> + .als_gain_tbl_size = ARRAY_SIZE(ltr501_als_gain_tbl),
> + .ps_gain = ltr501_ps_gain_tbl,
> + .ps_gain_tbl_size = ARRAY_SIZE(ltr501_ps_gain_tbl),
> + .als_mode_active = BIT(0) | BIT(1),
As below
> + .als_gain_mask = BIT(3),
> + .als_gain_shift = 3,
> + .channels = ltr501_channels,
> + .no_channels = ARRAY_SIZE(ltr501_channels),
> +};
> +
> +static const struct ltr501_chip_info ltr559_chip_info_tbl = {
> + .partid = 0x09,
> + .als_gain = ltr559_als_gain_tbl,
> + .als_gain_tbl_size = ARRAY_SIZE(ltr559_als_gain_tbl),
> + .ps_gain = ltr559_ps_gain_tbl,
> + .ps_gain_tbl_size = ARRAY_SIZE(ltr559_ps_gain_tbl),
> + .als_mode_active = BIT(0),
> + .als_gain_mask = BIT(2) | BIT(3) | BIT(4),
Is it really 3 separate bits, or GENMASK(4, 2) to
represent a 3 bit shift?
Whilst you are touching the driver can we get rid of the
separate shift by using field_prep() field_get() using
just the mask?
> + .als_gain_shift = 2,
> + .channels = ltr501_channels,
> + .no_channels = ARRAY_SIZE(ltr501_channels),
> };
>
> static int ltr501_write_contr(struct ltr501_data *data, u8 als_val, u8 ps_val)
> @@ -1393,14 +1387,11 @@ static int ltr501_powerdown(struct ltr501_data *data)
>
> static int ltr501_probe(struct i2c_client *client)
> {
> - const struct i2c_device_id *id = i2c_client_get_device_id(client);
> static const char * const regulator_names[] = { "vdd", "vddio" };
> struct ltr501_data *data;
> struct iio_dev *indio_dev;
> struct regmap *regmap;
> - const void *ddata = NULL;
> - int partid, chip_idx;
> - const char *name;
> + int partid;
> int ret;
>
> indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
> @@ -1480,18 +1471,10 @@ static int ltr501_probe(struct i2c_client *client)
> if (ret < 0)
> return ret;
>
> - if (id) {
> - name = id->name;
> - chip_idx = id->driver_data;
> - } else {
> - name = iio_get_acpi_device_name_and_data(&client->dev, &ddata);
> - chip_idx = (intptr_t)ddata;
> - }
> - if (!name)
> + data->chip_info = i2c_get_match_data(client);
> + if (!data->chip_info)
> return -ENODEV;
As above. Unfortunately at this point we'll still need to
do some special handling to match the existing indio_dev->name.
>
> - data->chip_info = <r501_chip_info_tbl[chip_idx];
> -
> if ((partid >> 4) != data->chip_info->partid)
> return -ENODEV;
>
> @@ -1502,7 +1485,7 @@ static int ltr501_probe(struct i2c_client *client)
> indio_dev->info = <r501_info;
> indio_dev->channels = data->chip_info->channels;
> indio_dev->num_channels = data->chip_info->no_channels;
> - indio_dev->name = name;
> + indio_dev->name = client->name;
> indio_dev->modes = INDIO_DIRECT_MODE;
>
^ permalink raw reply [flat|nested] 13+ messages in thread* Re: [PATCH v2 2/4] iio: light: ltr501: Switch to modern match mechanism
2026-11-07 3:30 ` Jonathan Cameron
@ 2026-11-07 10:13 ` Svyatoslav Ryhel
0 siblings, 0 replies; 13+ messages in thread
From: Svyatoslav Ryhel @ 2026-11-07 10:13 UTC (permalink / raw)
To: Jonathan Cameron
Cc: David Lechner, Nuno Sá,
Andy Shevchenko, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Esben Haabendal, Kuppuswamy Sathyanarayanan,
Uwe Kleine-König (The Capable Hub),
Pan Chuang, Hemanth Selam, Antoniu Miclaus, Nikita Travkin,
linux-iio, devicetree, linux-kernel
сб, 7 лист. 2026 р. о 05:30 Jonathan Cameron <jic23@kernel.org> пише:
>
> On Fri, 6 Nov 2026 11:19:41 +0200
> Svyatoslav Ryhel <clamor95@gmail.com> wrote:
>
> > Remove the chip enum, break the chip list structure into individual
> > elements, and pass each element using i2c_get_match_data().
>
> Sashiko calls out that for ACPI this results in an ABI change.
> The original code did the ABI wrong but that unfortunately doesn't
> mean we can change this one as it is an artefact of a time when
> we weren't so careful about those names.
>
> So you'll need to put special handling back in for the ACPI parts
> and that name. Some other things in the existing code noted inline
> that would be nice to clean up whilst you are here.
>
> >
> > Signed-off-by: Svyatoslav Ryhel <clamor95@gmail.com>
> > ---
> > drivers/iio/light/ltr501.c | 165 +++++++++++++++++--------------------
> > 1 file changed, 74 insertions(+), 91 deletions(-)
> >
> > diff --git a/drivers/iio/light/ltr501.c b/drivers/iio/light/ltr501.c
> > index cc5d7af44d77c..d5ce6468a229b 100644
> > --- a/drivers/iio/light/ltr501.c
> > +++ b/drivers/iio/light/ltr501.c
>
> > +static const struct ltr501_chip_info ltr301_chip_info_tbl = {
> > + .partid = 0x08,
> > + .als_gain = ltr501_als_gain_tbl,
> > + .als_gain_tbl_size = ARRAY_SIZE(ltr501_als_gain_tbl),
> > + .als_mode_active = BIT(0) | BIT(1),
> > + .als_gain_mask = BIT(3),
> > + .als_gain_shift = 3,
> > + .channels = ltr301_channels,
> > + .no_channels = ARRAY_SIZE(ltr301_channels),
> > +};
> > +
> > +static const struct ltr501_chip_info ltr303_chip_info_tbl = {
> > + .partid = 0x0A,
> > + .als_gain = ltr559_als_gain_tbl,
> > + .als_gain_tbl_size = ARRAY_SIZE(ltr559_als_gain_tbl),
> > + .als_mode_active = BIT(0),
> > + .als_gain_mask = BIT(2) | BIT(3) | BIT(4),
> > + .als_gain_shift = 2,
> > + .channels = ltr301_channels,
> > + .no_channels = ARRAY_SIZE(ltr301_channels),
> > +};
> > +
> > +static const struct ltr501_chip_info ltr329_chip_info_tbl = {
> > + .partid = 0x0A,
> > + .als_gain = ltr559_als_gain_tbl,
> > + .als_gain_tbl_size = ARRAY_SIZE(ltr559_als_gain_tbl),
> > + .als_mode_active = BIT(0),
> > + .als_gain_mask = BIT(2) | BIT(3) | BIT(4),
>
> As below. Same for all the others. That would be a separate
> cleanup patch though -> perhaps do it with getting rid of
> the als_gain_shift.
>
This is all out of scope of my series. I am not a code janitor!
> > + .als_gain_shift = 2,
> > + .no_irq_support = true,
> > + .channels = ltr301_channels,
> > + .no_channels = ARRAY_SIZE(ltr301_channels),
> > +};
> > +
> > +static const struct ltr501_chip_info ltr501_chip_info_tbl = {
> > + .partid = 0x08,
> > + .als_gain = ltr501_als_gain_tbl,
> > + .als_gain_tbl_size = ARRAY_SIZE(ltr501_als_gain_tbl),
> > + .ps_gain = ltr501_ps_gain_tbl,
> > + .ps_gain_tbl_size = ARRAY_SIZE(ltr501_ps_gain_tbl),
> > + .als_mode_active = BIT(0) | BIT(1),
> As below
> > + .als_gain_mask = BIT(3),
> > + .als_gain_shift = 3,
> > + .channels = ltr501_channels,
> > + .no_channels = ARRAY_SIZE(ltr501_channels),
> > +};
> > +
> > +static const struct ltr501_chip_info ltr559_chip_info_tbl = {
> > + .partid = 0x09,
> > + .als_gain = ltr559_als_gain_tbl,
> > + .als_gain_tbl_size = ARRAY_SIZE(ltr559_als_gain_tbl),
> > + .ps_gain = ltr559_ps_gain_tbl,
> > + .ps_gain_tbl_size = ARRAY_SIZE(ltr559_ps_gain_tbl),
> > + .als_mode_active = BIT(0),
> > + .als_gain_mask = BIT(2) | BIT(3) | BIT(4),
> Is it really 3 separate bits, or GENMASK(4, 2) to
> represent a 3 bit shift?
>
> Whilst you are touching the driver can we get rid of the
> separate shift by using field_prep() field_get() using
> just the mask?
>
> > + .als_gain_shift = 2,
> > + .channels = ltr501_channels,
> > + .no_channels = ARRAY_SIZE(ltr501_channels),
> > };
> >
> > static int ltr501_write_contr(struct ltr501_data *data, u8 als_val, u8 ps_val)
> > @@ -1393,14 +1387,11 @@ static int ltr501_powerdown(struct ltr501_data *data)
> >
> > static int ltr501_probe(struct i2c_client *client)
> > {
> > - const struct i2c_device_id *id = i2c_client_get_device_id(client);
> > static const char * const regulator_names[] = { "vdd", "vddio" };
> > struct ltr501_data *data;
> > struct iio_dev *indio_dev;
> > struct regmap *regmap;
> > - const void *ddata = NULL;
> > - int partid, chip_idx;
> > - const char *name;
> > + int partid;
> > int ret;
> >
> > indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
> > @@ -1480,18 +1471,10 @@ static int ltr501_probe(struct i2c_client *client)
> > if (ret < 0)
> > return ret;
> >
> > - if (id) {
> > - name = id->name;
> > - chip_idx = id->driver_data;
> > - } else {
> > - name = iio_get_acpi_device_name_and_data(&client->dev, &ddata);
> > - chip_idx = (intptr_t)ddata;
> > - }
> > - if (!name)
> > + data->chip_info = i2c_get_match_data(client);
> > + if (!data->chip_info)
> > return -ENODEV;
>
> As above. Unfortunately at this point we'll still need to
> do some special handling to match the existing indio_dev->name.
>
const struct i2c_device_id *id = i2c_client_get_device_id(client);
...
indio_dev->name = id ? id->name :
iio_get_acpi_device_name_and_data(&client->dev, NULL);
Will this be acceptible?
> >
> > - data->chip_info = <r501_chip_info_tbl[chip_idx];
> > -
> > if ((partid >> 4) != data->chip_info->partid)
> > return -ENODEV;
> >
> > @@ -1502,7 +1485,7 @@ static int ltr501_probe(struct i2c_client *client)
> > indio_dev->info = <r501_info;
> > indio_dev->channels = data->chip_info->channels;
> > indio_dev->num_channels = data->chip_info->no_channels;
> > - indio_dev->name = name;
> > + indio_dev->name = client->name;
> > indio_dev->modes = INDIO_DIRECT_MODE;
> >
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH v2 3/4] dt-bindings: iio: light: ltr501: Document LTR659 proximity sensor
2026-11-06 9:19 [PATCH v2 0/4] iio: light: ltr501: Add LTR-659PS-01 prox sensor support Svyatoslav Ryhel
2026-11-06 9:19 ` [PATCH v2 1/4] iio: light: ltr501: Switch to read_avail() op from manual attribute registration Svyatoslav Ryhel
2026-11-06 9:19 ` [PATCH v2 2/4] iio: light: ltr501: Switch to modern match mechanism Svyatoslav Ryhel
@ 2026-11-06 9:19 ` Svyatoslav Ryhel
2026-11-06 17:31 ` Conor Dooley
2026-11-06 9:19 ` [PATCH v2 4/4] iio: light: ltr501: Add support for the LTR-659PS-01 " Svyatoslav Ryhel
3 siblings, 1 reply; 13+ messages in thread
From: Svyatoslav Ryhel @ 2026-11-06 9:19 UTC (permalink / raw)
To: Jonathan Cameron, David Lechner, Nuno Sá,
Andy Shevchenko, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Esben Haabendal, Kuppuswamy Sathyanarayanan, Svyatoslav Ryhel,
Uwe Kleine-König (The Capable Hub),
Pan Chuang, Hemanth Selam, Antoniu Miclaus, Nikita Travkin
Cc: linux-iio, devicetree, linux-kernel
The LTR-659PS-01 is a proximity sensor similar to the LTR-559ALS-01, but
without ambient light sensing support.
Signed-off-by: Svyatoslav Ryhel <clamor95@gmail.com>
---
Documentation/devicetree/bindings/iio/light/liteon,ltr501.yaml | 1 +
1 file changed, 1 insertion(+)
diff --git a/Documentation/devicetree/bindings/iio/light/liteon,ltr501.yaml b/Documentation/devicetree/bindings/iio/light/liteon,ltr501.yaml
index 20abd7da080d6..85ac3b540c206 100644
--- a/Documentation/devicetree/bindings/iio/light/liteon,ltr501.yaml
+++ b/Documentation/devicetree/bindings/iio/light/liteon,ltr501.yaml
@@ -17,6 +17,7 @@ properties:
- liteon,ltr329
- liteon,ltr501
- liteon,ltr559
+ - liteon,ltr659
reg:
maxItems: 1
--
2.53.0
^ permalink raw reply [flat|nested] 13+ messages in thread* Re: [PATCH v2 3/4] dt-bindings: iio: light: ltr501: Document LTR659 proximity sensor
2026-11-06 9:19 ` [PATCH v2 3/4] dt-bindings: iio: light: ltr501: Document LTR659 proximity sensor Svyatoslav Ryhel
@ 2026-11-06 17:31 ` Conor Dooley
0 siblings, 0 replies; 13+ messages in thread
From: Conor Dooley @ 2026-11-06 17:31 UTC (permalink / raw)
To: Svyatoslav Ryhel
Cc: Jonathan Cameron, David Lechner, Nuno Sá,
Andy Shevchenko, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Esben Haabendal, Kuppuswamy Sathyanarayanan,
Uwe Kleine-König (The Capable Hub),
Pan Chuang, Hemanth Selam, Antoniu Miclaus, Nikita Travkin,
linux-iio, devicetree, linux-kernel
[-- Attachment #1: Type: text/plain, Size: 75 bytes --]
Acked-by: Conor Dooley <conor.dooley@microchip.com>
pw-bot: not-applicable
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH v2 4/4] iio: light: ltr501: Add support for the LTR-659PS-01 proximity sensor
2026-11-06 9:19 [PATCH v2 0/4] iio: light: ltr501: Add LTR-659PS-01 prox sensor support Svyatoslav Ryhel
` (2 preceding siblings ...)
2026-11-06 9:19 ` [PATCH v2 3/4] dt-bindings: iio: light: ltr501: Document LTR659 proximity sensor Svyatoslav Ryhel
@ 2026-11-06 9:19 ` Svyatoslav Ryhel
2026-11-07 3:33 ` Jonathan Cameron
3 siblings, 1 reply; 13+ messages in thread
From: Svyatoslav Ryhel @ 2026-11-06 9:19 UTC (permalink / raw)
To: Jonathan Cameron, David Lechner, Nuno Sá,
Andy Shevchenko, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Esben Haabendal, Kuppuswamy Sathyanarayanan, Svyatoslav Ryhel,
Uwe Kleine-König (The Capable Hub),
Pan Chuang, Hemanth Selam, Antoniu Miclaus, Nikita Travkin
Cc: linux-iio, devicetree, linux-kernel
Add support for the Lite-On LTR-659PS-01 proximity sensor. This device is
nearly identical to the LTR-559ALS-01, but omits all elements related to
ambient light sensing.
Add a no_als_support flag, similar to how no_irq_support is used, to
isolate ALS register access for the LTR-659PS-01, since ALS registers are
marked as reserved and interactions with them are discouraged.
The ltr501_trigger_handler relied on the scan index to identify channels.
This approach is fragile regarding channel status flags and can break if
the index is not strictly set. Switch to checking the channel type
instead.
Signed-off-by: Svyatoslav Ryhel <clamor95@gmail.com>
---
drivers/iio/light/ltr501.c | 73 +++++++++++++++++++++++++++++++-------
1 file changed, 61 insertions(+), 12 deletions(-)
diff --git a/drivers/iio/light/ltr501.c b/drivers/iio/light/ltr501.c
index d5ce6468a229b..e7762115df913 100644
--- a/drivers/iio/light/ltr501.c
+++ b/drivers/iio/light/ltr501.c
@@ -151,6 +151,7 @@ struct ltr501_chip_info {
u8 als_gain_mask;
u8 als_gain_shift;
bool no_irq_support;
+ bool no_als_support;
struct iio_chan_spec const *channels;
const int no_channels;
};
@@ -192,6 +193,11 @@ static bool ltr501_has_irq_support(const struct ltr501_chip_info *info)
return !info->no_irq_support;
}
+static bool ltr501_has_als_support(const struct ltr501_chip_info *info)
+{
+ return !info->no_als_support;
+}
+
static int ltr501_match_samp_freq(const struct ltr501_samp_table *tab,
int len, int val, int val2)
{
@@ -656,6 +662,29 @@ static const struct iio_chan_spec ltr301_channels[] = {
IIO_CHAN_SOFT_TIMESTAMP(2),
};
+static const struct iio_chan_spec ltr659_channels[] = {
+ {
+ .type = IIO_PROXIMITY,
+ .address = LTR501_PS_DATA,
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+ BIT(IIO_CHAN_INFO_SCALE) |
+ BIT(IIO_CHAN_INFO_SAMP_FREQ),
+ .info_mask_separate_available = BIT(IIO_CHAN_INFO_SCALE) |
+ BIT(IIO_CHAN_INFO_SAMP_FREQ),
+ .scan_index = 0,
+ .scan_type = {
+ .sign = 'u',
+ .realbits = 11,
+ .storagebits = 16,
+ .endianness = IIO_CPU,
+ },
+ .event_spec = ltr501_pxs_event_spec,
+ .num_event_specs = ARRAY_SIZE(ltr501_pxs_event_spec),
+ .ext_info = ltr501_ext_info,
+ },
+ IIO_CHAN_SOFT_TIMESTAMP(1),
+};
+
static int ltr501_read_info_raw(struct ltr501_data *data,
struct iio_chan_spec const *chan,
int *val)
@@ -1230,13 +1259,24 @@ static const struct ltr501_chip_info ltr559_chip_info_tbl = {
.no_channels = ARRAY_SIZE(ltr501_channels),
};
+static const struct ltr501_chip_info ltr659_chip_info_tbl = {
+ .partid = 0x09,
+ .ps_gain = ltr559_ps_gain_tbl,
+ .ps_gain_tbl_size = ARRAY_SIZE(ltr559_ps_gain_tbl),
+ .no_als_support = true,
+ .channels = ltr659_channels,
+ .no_channels = ARRAY_SIZE(ltr659_channels),
+};
+
static int ltr501_write_contr(struct ltr501_data *data, u8 als_val, u8 ps_val)
{
int ret;
- ret = regmap_write(data->regmap, LTR501_ALS_CONTR, als_val);
- if (ret < 0)
- return ret;
+ if (ltr501_has_als_support(data->chip_info)) {
+ ret = regmap_write(data->regmap, LTR501_ALS_CONTR, als_val);
+ if (ret < 0)
+ return ret;
+ }
return regmap_write(data->regmap, LTR501_PS_CONTR, ps_val);
}
@@ -1251,16 +1291,21 @@ static irqreturn_t ltr501_trigger_handler(int irq, void *p)
aligned_s64 ts;
} scan = { };
__le16 als_buf[2];
+ unsigned int i;
u8 mask = 0;
int j = 0;
int ret, psdata;
/* figure out which data needs to be ready */
- if (test_bit(0, indio_dev->active_scan_mask) ||
- test_bit(1, indio_dev->active_scan_mask))
- mask |= LTR501_STATUS_ALS_RDY;
- if (test_bit(2, indio_dev->active_scan_mask))
- mask |= LTR501_STATUS_PS_RDY;
+ for_each_set_bit(i, indio_dev->active_scan_mask, indio_dev->num_channels) {
+ const struct iio_chan_spec *chan = &indio_dev->channels[i];
+
+ if (chan->type == IIO_INTENSITY)
+ mask |= LTR501_STATUS_ALS_RDY;
+
+ if (chan->type == IIO_PROXIMITY)
+ mask |= LTR501_STATUS_PS_RDY;
+ }
ret = ltr501_drdy(data, mask);
if (ret < 0)
@@ -1328,11 +1373,13 @@ static int ltr501_init(struct ltr501_data *data)
{
int ret, status;
- ret = regmap_read(data->regmap, LTR501_ALS_CONTR, &status);
- if (ret < 0)
- return ret;
+ if (ltr501_has_als_support(data->chip_info)) {
+ ret = regmap_read(data->regmap, LTR501_ALS_CONTR, &status);
+ if (ret < 0)
+ return ret;
- data->als_contr = status | data->chip_info->als_mode_active;
+ data->als_contr = status | data->chip_info->als_mode_active;
+ }
ret = regmap_read(data->regmap, LTR501_PS_CONTR, &status);
if (ret < 0)
@@ -1569,6 +1616,7 @@ static const struct i2c_device_id ltr501_id[] = {
{ .name = "ltr329", .driver_data = (kernel_ulong_t)<r329_chip_info_tbl },
{ .name = "ltr501", .driver_data = (kernel_ulong_t)<r501_chip_info_tbl },
{ .name = "ltr559", .driver_data = (kernel_ulong_t)<r559_chip_info_tbl },
+ { .name = "ltr659", .driver_data = (kernel_ulong_t)<r659_chip_info_tbl },
{ }
};
MODULE_DEVICE_TABLE(i2c, ltr501_id);
@@ -1579,6 +1627,7 @@ static const struct of_device_id ltr501_of_match[] = {
{ .compatible = "liteon,ltr329", .data = <r329_chip_info_tbl },
{ .compatible = "liteon,ltr501", .data = <r501_chip_info_tbl },
{ .compatible = "liteon,ltr559", .data = <r559_chip_info_tbl },
+ { .compatible = "liteon,ltr659", .data = <r659_chip_info_tbl },
{ }
};
MODULE_DEVICE_TABLE(of, ltr501_of_match);
--
2.53.0
^ permalink raw reply [flat|nested] 13+ messages in thread* Re: [PATCH v2 4/4] iio: light: ltr501: Add support for the LTR-659PS-01 proximity sensor
2026-11-06 9:19 ` [PATCH v2 4/4] iio: light: ltr501: Add support for the LTR-659PS-01 " Svyatoslav Ryhel
@ 2026-11-07 3:33 ` Jonathan Cameron
2026-11-07 10:15 ` Svyatoslav Ryhel
0 siblings, 1 reply; 13+ messages in thread
From: Jonathan Cameron @ 2026-11-07 3:33 UTC (permalink / raw)
To: Svyatoslav Ryhel
Cc: David Lechner, Nuno Sá,
Andy Shevchenko, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Esben Haabendal, Kuppuswamy Sathyanarayanan,
Uwe Kleine-König (The Capable Hub),
Pan Chuang, Hemanth Selam, Antoniu Miclaus, Nikita Travkin,
linux-iio, devicetree, linux-kernel
On Fri, 6 Nov 2026 11:19:43 +0200
Svyatoslav Ryhel <clamor95@gmail.com> wrote:
> Add support for the Lite-On LTR-659PS-01 proximity sensor. This device is
> nearly identical to the LTR-559ALS-01, but omits all elements related to
> ambient light sensing.
>
> Add a no_als_support flag, similar to how no_irq_support is used, to
> isolate ALS register access for the LTR-659PS-01, since ALS registers are
> marked as reserved and interactions with them are discouraged.
>
> The ltr501_trigger_handler relied on the scan index to identify channels.
> This approach is fragile regarding channel status flags and can break if
> the index is not strictly set. Switch to checking the channel type
> instead.
>
> Signed-off-by: Svyatoslav Ryhel <clamor95@gmail.com>
> ---
> drivers/iio/light/ltr501.c | 73 +++++++++++++++++++++++++++++++-------
> 1 file changed, 61 insertions(+), 12 deletions(-)
>
> diff --git a/drivers/iio/light/ltr501.c b/drivers/iio/light/ltr501.c
> index d5ce6468a229b..e7762115df913 100644
> --- a/drivers/iio/light/ltr501.c
> +++ b/drivers/iio/light/ltr501.c
> @@ -151,6 +151,7 @@ struct ltr501_chip_info {
> u8 als_gain_mask;
> u8 als_gain_shift;
> bool no_irq_support;
> + bool no_als_support;
> struct iio_chan_spec const *channels;
> const int no_channels;
> };
> @@ -192,6 +193,11 @@ static bool ltr501_has_irq_support(const struct ltr501_chip_info *info)
> return !info->no_irq_support;
> }
>
> +static bool ltr501_has_als_support(const struct ltr501_chip_info *info)
Is the helper bring enough value? The !info->no_als_support
where this is used seems clear enough to me.
> +{
> + return !info->no_als_support;
> +}
> +
> static int ltr501_match_samp_freq(const struct ltr501_samp_table *tab,
> int len, int val, int val2)
> {
> @@ -656,6 +662,29 @@ static const struct iio_chan_spec ltr301_channels[] = {
> IIO_CHAN_SOFT_TIMESTAMP(2),
> };
>
> +static const struct iio_chan_spec ltr659_channels[] = {
> + {
> + .type = IIO_PROXIMITY,
> + .address = LTR501_PS_DATA,
> + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
> + BIT(IIO_CHAN_INFO_SCALE) |
> + BIT(IIO_CHAN_INFO_SAMP_FREQ),
> + .info_mask_separate_available = BIT(IIO_CHAN_INFO_SCALE) |
> + BIT(IIO_CHAN_INFO_SAMP_FREQ),
The sampling frequency applies to both channels here. I'd just make that
info_mask_shared_by_all
> + .scan_index = 0,
> + .scan_type = {
> + .sign = 'u',
> + .realbits = 11,
> + .storagebits = 16,
> + .endianness = IIO_CPU,
> + },
> + .event_spec = ltr501_pxs_event_spec,
> + .num_event_specs = ARRAY_SIZE(ltr501_pxs_event_spec),
> + .ext_info = ltr501_ext_info,
> + },
> + IIO_CHAN_SOFT_TIMESTAMP(1),
> +};
^ permalink raw reply [flat|nested] 13+ messages in thread* Re: [PATCH v2 4/4] iio: light: ltr501: Add support for the LTR-659PS-01 proximity sensor
2026-11-07 3:33 ` Jonathan Cameron
@ 2026-11-07 10:15 ` Svyatoslav Ryhel
0 siblings, 0 replies; 13+ messages in thread
From: Svyatoslav Ryhel @ 2026-11-07 10:15 UTC (permalink / raw)
To: Jonathan Cameron
Cc: David Lechner, Nuno Sá,
Andy Shevchenko, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Esben Haabendal, Kuppuswamy Sathyanarayanan,
Uwe Kleine-König (The Capable Hub),
Pan Chuang, Hemanth Selam, Antoniu Miclaus, Nikita Travkin,
linux-iio, devicetree, linux-kernel
сб, 7 лист. 2026 р. о 05:33 Jonathan Cameron <jic23@kernel.org> пише:
>
> On Fri, 6 Nov 2026 11:19:43 +0200
> Svyatoslav Ryhel <clamor95@gmail.com> wrote:
>
> > Add support for the Lite-On LTR-659PS-01 proximity sensor. This device is
> > nearly identical to the LTR-559ALS-01, but omits all elements related to
> > ambient light sensing.
> >
> > Add a no_als_support flag, similar to how no_irq_support is used, to
> > isolate ALS register access for the LTR-659PS-01, since ALS registers are
> > marked as reserved and interactions with them are discouraged.
> >
> > The ltr501_trigger_handler relied on the scan index to identify channels.
> > This approach is fragile regarding channel status flags and can break if
> > the index is not strictly set. Switch to checking the channel type
> > instead.
> >
> > Signed-off-by: Svyatoslav Ryhel <clamor95@gmail.com>
> > ---
> > drivers/iio/light/ltr501.c | 73 +++++++++++++++++++++++++++++++-------
> > 1 file changed, 61 insertions(+), 12 deletions(-)
> >
> > diff --git a/drivers/iio/light/ltr501.c b/drivers/iio/light/ltr501.c
> > index d5ce6468a229b..e7762115df913 100644
> > --- a/drivers/iio/light/ltr501.c
> > +++ b/drivers/iio/light/ltr501.c
> > @@ -151,6 +151,7 @@ struct ltr501_chip_info {
> > u8 als_gain_mask;
> > u8 als_gain_shift;
> > bool no_irq_support;
> > + bool no_als_support;
> > struct iio_chan_spec const *channels;
> > const int no_channels;
> > };
> > @@ -192,6 +193,11 @@ static bool ltr501_has_irq_support(const struct ltr501_chip_info *info)
> > return !info->no_irq_support;
> > }
> >
> > +static bool ltr501_has_als_support(const struct ltr501_chip_info *info)
>
> Is the helper bring enough value? The !info->no_als_support
> where this is used seems clear enough to me.
>
Noted, if you are fine with !info->no_als_support I have no objections.
> > +{
> > + return !info->no_als_support;
> > +}
> > +
> > static int ltr501_match_samp_freq(const struct ltr501_samp_table *tab,
> > int len, int val, int val2)
> > {
> > @@ -656,6 +662,29 @@ static const struct iio_chan_spec ltr301_channels[] = {
> > IIO_CHAN_SOFT_TIMESTAMP(2),
> > };
> >
> > +static const struct iio_chan_spec ltr659_channels[] = {
> > + {
> > + .type = IIO_PROXIMITY,
> > + .address = LTR501_PS_DATA,
> > + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
> > + BIT(IIO_CHAN_INFO_SCALE) |
> > + BIT(IIO_CHAN_INFO_SAMP_FREQ),
> > + .info_mask_separate_available = BIT(IIO_CHAN_INFO_SCALE) |
> > + BIT(IIO_CHAN_INFO_SAMP_FREQ),
>
> The sampling frequency applies to both channels here. I'd just make that
> info_mask_shared_by_all
>
so IIO_CHAN_INFO_SCALE is separate
and IIO_CHAN_INFO_SAMP_FREQ is shared_by_all
Noted.
> > + .scan_index = 0,
> > + .scan_type = {
> > + .sign = 'u',
> > + .realbits = 11,
> > + .storagebits = 16,
> > + .endianness = IIO_CPU,
> > + },
> > + .event_spec = ltr501_pxs_event_spec,
> > + .num_event_specs = ARRAY_SIZE(ltr501_pxs_event_spec),
> > + .ext_info = ltr501_ext_info,
> > + },
> > + IIO_CHAN_SOFT_TIMESTAMP(1),
> > +};
>
^ permalink raw reply [flat|nested] 13+ messages in thread