* [PATCH v3 1/4] iio: light: ltr501: Switch to read_avail() op from manual attribute registration
2026-11-08 9:42 [PATCH v3 0/4] iio: light: ltr501: Add LTR-659PS-01 prox sensor support Svyatoslav Ryhel
@ 2026-11-08 9:42 ` Svyatoslav Ryhel
2026-11-08 9:42 ` [PATCH v3 2/4] iio: light: ltr501: Switch to modern match mechanism Svyatoslav Ryhel
` (2 subsequent siblings)
3 siblings, 0 replies; 5+ messages in thread
From: Svyatoslav Ryhel @ 2026-11-08 9:42 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.
Adjust LTR501_INTENSITY_CHANNEL to account for the new
info_mask_*_available layout, allowing the removal of _shared since all
intensity channels share the same layout of available entries.
Signed-off-by: Svyatoslav Ryhel <clamor95@gmail.com>
---
drivers/iio/light/ltr501.c | 192 +++++++++++++++----------------------
1 file changed, 76 insertions(+), 116 deletions(-)
diff --git a/drivers/iio/light/ltr501.c b/drivers/iio/light/ltr501.c
index 302be2fc314c5..1ddd0dfd55ea2 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 {
@@ -582,14 +596,18 @@ static const struct iio_event_spec ltr501_pxs_event_spec[] = {
},
};
-#define LTR501_INTENSITY_CHANNEL(_idx, _addr, _mod, _shared, \
- _evspec, _evsize) { \
+#define LTR501_INTENSITY_CHANNEL(_idx, _addr, _mod, _evspec, _evsize) { \
.type = IIO_INTENSITY, \
.modified = 1, \
.address = (_addr), \
.channel2 = (_mod), \
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
- .info_mask_shared_by_type = (_shared), \
+ .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \
+ BIT(IIO_CHAN_INFO_INT_TIME) | \
+ BIT(IIO_CHAN_INFO_SAMP_FREQ), \
+ .info_mask_shared_by_type_available = BIT(IIO_CHAN_INFO_SCALE), \
+ .info_mask_shared_by_all_available = BIT(IIO_CHAN_INFO_INT_TIME) | \
+ BIT(IIO_CHAN_INFO_SAMP_FREQ), \
.scan_index = (_idx), \
.scan_type = { \
.sign = 'u', \
@@ -609,19 +627,18 @@ static const struct iio_event_spec ltr501_pxs_event_spec[] = {
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,
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),
+ LTR501_INTENSITY_CHANNEL(1, LTR501_ALS_DATA1, IIO_MOD_LIGHT_IR, 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),
+ .info_mask_shared_by_all_available = BIT(IIO_CHAN_INFO_INT_TIME) |
+ BIT(IIO_CHAN_INFO_SAMP_FREQ),
.scan_index = 2,
.scan_type = {
.sign = 'u',
@@ -638,14 +655,10 @@ static const struct iio_chan_spec ltr501_channels[] = {
static const struct iio_chan_spec ltr301_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,
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),
+ LTR501_INTENSITY_CHANNEL(1, LTR501_ALS_DATA1, IIO_MOD_LIGHT_IR, NULL, 0),
IIO_CHAN_SOFT_TIMESTAMP(2),
};
@@ -1111,111 +1124,67 @@ 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) {
+ int valid_als_gains[ARRAY_SIZE(ltr559_als_gain_tbl) * 2];
+ int j = 0;
+
+ for (int i = 0; i < info->als_gain_tbl_size; i++) {
+ if (info->als_gain[i].scale == LTR501_RESERVED_GAIN)
+ continue;
+
+ valid_als_gains[j++] = info->als_gain[i].scale;
+ valid_als_gains[j++] = info->als_gain[i].uscale;
+ }
+
+ *length = j;
+ *vals = (const int *)valid_als_gains;
+ } 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 +1195,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 +1205,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 +1216,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 +1228,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 +1240,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 +1508,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 +1533,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] 5+ messages in thread* [PATCH v3 2/4] iio: light: ltr501: Switch to modern match mechanism
2026-11-08 9:42 [PATCH v3 0/4] iio: light: ltr501: Add LTR-659PS-01 prox sensor support Svyatoslav Ryhel
2026-11-08 9:42 ` [PATCH v3 1/4] iio: light: ltr501: Switch to read_avail() op from manual attribute registration Svyatoslav Ryhel
@ 2026-11-08 9:42 ` Svyatoslav Ryhel
2026-11-08 9:42 ` [PATCH v3 3/4] dt-bindings: iio: light: ltr501: Document LTR659 proximity sensor Svyatoslav Ryhel
2026-11-08 9:42 ` [PATCH v3 4/4] iio: light: ltr501: Add support for the LTR-659PS-01 " Svyatoslav Ryhel
3 siblings, 0 replies; 5+ messages in thread
From: Svyatoslav Ryhel @ 2026-11-08 9:42 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().
Preserve the iio_dev name configuration and replace the
iio_get_acpi_device_name_and_data() call with a simple dev_name(), since
the former is just a wrapper for the latter in this use case.
Signed-off-by: Svyatoslav Ryhel <clamor95@gmail.com>
---
drivers/iio/light/ltr501.c | 164 +++++++++++++++++--------------------
1 file changed, 74 insertions(+), 90 deletions(-)
diff --git a/drivers/iio/light/ltr501.c b/drivers/iio/light/ltr501.c
index 1ddd0dfd55ea2..ca6c8cffb4001 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;
@@ -1187,62 +1179,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)
@@ -1407,9 +1401,7 @@ static int ltr501_probe(struct i2c_client *client)
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));
@@ -1489,18 +1481,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;
@@ -1511,7 +1495,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 = id ? id->name : dev_name(&client->dev);
indio_dev->modes = INDIO_DIRECT_MODE;
ret = ltr501_init(data);
@@ -1582,29 +1566,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] 5+ messages in thread* [PATCH v3 3/4] dt-bindings: iio: light: ltr501: Document LTR659 proximity sensor
2026-11-08 9:42 [PATCH v3 0/4] iio: light: ltr501: Add LTR-659PS-01 prox sensor support Svyatoslav Ryhel
2026-11-08 9:42 ` [PATCH v3 1/4] iio: light: ltr501: Switch to read_avail() op from manual attribute registration Svyatoslav Ryhel
2026-11-08 9:42 ` [PATCH v3 2/4] iio: light: ltr501: Switch to modern match mechanism Svyatoslav Ryhel
@ 2026-11-08 9:42 ` Svyatoslav Ryhel
2026-11-08 9:42 ` [PATCH v3 4/4] iio: light: ltr501: Add support for the LTR-659PS-01 " Svyatoslav Ryhel
3 siblings, 0 replies; 5+ messages in thread
From: Svyatoslav Ryhel @ 2026-11-08 9:42 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.
Acked-by: Conor Dooley <conor.dooley@microchip.com>
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] 5+ messages in thread* [PATCH v3 4/4] iio: light: ltr501: Add support for the LTR-659PS-01 proximity sensor
2026-11-08 9:42 [PATCH v3 0/4] iio: light: ltr501: Add LTR-659PS-01 prox sensor support Svyatoslav Ryhel
` (2 preceding siblings ...)
2026-11-08 9:42 ` [PATCH v3 3/4] dt-bindings: iio: light: ltr501: Document LTR659 proximity sensor Svyatoslav Ryhel
@ 2026-11-08 9:42 ` Svyatoslav Ryhel
3 siblings, 0 replies; 5+ messages in thread
From: Svyatoslav Ryhel @ 2026-11-08 9:42 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 | 76 ++++++++++++++++++++++++++++++--------
1 file changed, 61 insertions(+), 15 deletions(-)
diff --git a/drivers/iio/light/ltr501.c b/drivers/iio/light/ltr501.c
index ca6c8cffb4001..b97b8da98e86c 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;
};
@@ -654,6 +655,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),
+ .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ),
+ .info_mask_separate_available = BIT(IIO_CHAN_INFO_SCALE),
+ .info_mask_shared_by_all_available = 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)
@@ -1239,13 +1263,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 (!data->chip_info->no_als_support) {
+ 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);
}
@@ -1260,16 +1295,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 = iio_find_channel_from_si(indio_dev, 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)
@@ -1337,11 +1377,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 (!data->chip_info->no_als_support) {
+ 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)
@@ -1350,9 +1392,11 @@ static int ltr501_init(struct ltr501_data *data)
data->ps_contr = status | LTR501_CONTR_ACTIVE;
if (ltr501_has_irq_support(data->chip_info)) {
- ret = ltr501_read_intr_prst(data, IIO_INTENSITY, &data->als_period);
- if (ret < 0)
- return ret;
+ if (!data->chip_info->no_als_support) {
+ ret = ltr501_read_intr_prst(data, IIO_INTENSITY, &data->als_period);
+ if (ret < 0)
+ return ret;
+ }
ret = ltr501_read_intr_prst(data, IIO_PROXIMITY, &data->ps_period);
if (ret < 0)
@@ -1579,6 +1623,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);
@@ -1589,6 +1634,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] 5+ messages in thread