drivers/iio/light/ltr390.c | 53 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+)
Add support for debugfs_reg_access through the driver's iio_info structure
to enable low-level register read/write access for debugging.
Signed-off-by: Akshay Jindal <akshayaj.lkd@gmail.com>
---
Changes since v2:
================
- merged the regmap_range of LTR390_UP_THRESH with LTR390_LOW_THRESH.
Changes since v1:
=================
- Replaced _[0|1|2] macros with a respective common parameterized macro.
- Retained base macros to avoid churn.
- Swapped regmap_write with regmap_read to avoid negate operator.
- Simplified debugfs function by directly returning return value of
regmap_[read|write].
- Replaced [readable|writeable]_reg with regmap ranges by using
[rd|wr]_table property of regmap_config.
- Updated the testing details with v2 changes.
Testing details (done for v2):
==============================
-> Tested on Raspberrypi 4B. Follow for more details.
akshayajpi@raspberrypi:~ $ uname -r
6.12.35-v8+
akshayajpi@raspberrypi:~ $ uname -a
Linux raspberrypi 6.12.35-v8+ #5 SMP PREEMPT Tue Jul 15 17:38:06 IST 2025 aarch64 GNU/Linux
-> Sensor Detection, overlaying of device tree and Driver loading
akshayajpi@raspberrypi:~ $ i2cdetect -y 1
0 1 2 3 4 5 6 7 8 9 a b c d e f
00: -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: -- -- -- 53 -- -- -- -- -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: -- -- -- -- -- -- -- --
akshayajpi@raspberrypi:~ $ sudo dtoverlay i2c-sensor ltr390
akshayajpi@raspberrypi:~ $ lsmod|grep ltr390
ltr390 16384 0
industrialio 110592 1 ltr390
regmap_i2c 12288 1 ltr390
1. Disable sensor via debugfs, verify from i2cget and debugfs.
akshayajpi@raspberrypi:/sys/kernel/debug/iio/iio:device0 $ echo 0x0 | sudo tee direct_reg_access
0x0
akshayajpi@raspberrypi:/sys/kernel/debug/iio/iio:device0 $ cat direct_reg_access
0x2
akshayajpi@raspberrypi:/sys/kernel/debug/iio/iio:device0 $ echo 0x0 0x0 | sudo tee direct_reg_access
0x0 0x0
akshayajpi@raspberrypi:/sys/kernel/debug/iio/iio:device0 $ cat direct_reg_access
0x0
akshayajpi@raspberrypi:/sys/kernel/debug/iio/iio:device0 $ i2cget -f -y 1 0x53 0x0
0x00
2. Disable sensor via debugfs and read data status via debugfs.
akshayajpi@raspberrypi:/sys/kernel/debug/iio/iio:device0 $ cat /sys/bus/iio/devices/iio\:device0/in_illuminance_raw
603
akshayajpi@raspberrypi:/sys/kernel/debug/iio/iio:device0 $ cat /sys/bus/iio/devices/iio\:device0/in_illuminance_raw
603
akshayajpi@raspberrypi:/sys/kernel/debug/iio/iio:device0 $ cat /sys/bus/iio/devices/iio\:device0/in_illuminance_raw
603
akshayajpi@raspberrypi:/sys/kernel/debug/iio/iio:device0 $ i2cget -f -y 1 0x53 0x7
0x28
akshayajpi@raspberrypi:/sys/kernel/debug/iio/iio:device0 $ i2cget -f -y 1 0x53 0x7
0x00
akshayajpi@raspberrypi:/sys/kernel/debug/iio/iio:device0 $ echo 0x7 | sudo tee direct_reg_access
0x7
akshayajpi@raspberrypi:/sys/kernel/debug/iio/iio:device0 $ cat direct_reg_access
0x0
3. Re-enable sensor via debugfs and read data status via debugfs.
akshayajpi@raspberrypi:/sys/kernel/debug/iio/iio:device0 $ echo 0x0 0x2 | sudo tee direct_reg_access
0x0 0x2
akshayajpi@raspberrypi:/sys/kernel/debug/iio/iio:device0 $ cat direct_reg_access
0x2
akshayajpi@raspberrypi:/sys/kernel/debug/iio/iio:device0 $ cat /sys/bus/iio/devices/iio\:device0/in_illuminance_raw
608
akshayajpi@raspberrypi:/sys/kernel/debug/iio/iio:device0 $ cat /sys/bus/iio/devices/iio\:device0/in_illuminance_raw
614
akshayajpi@raspberrypi:/sys/kernel/debug/iio/iio:device0 $ cat /sys/bus/iio/devices/iio\:device0/in_illuminance_raw
601
akshayajpi@raspberrypi:/sys/kernel/debug/iio/iio:device0 $ echo 0x7 | sudo tee direct_reg_access
0x7
akshayajpi@raspberrypi:/sys/kernel/debug/iio/iio:device0 $ cat direct_reg_access
0x8
4. Enable interrupts via sysfs and verify via debugfs.
akshayajpi@raspberrypi:/sys/kernel/debug/iio/iio:device0 $ echo 1 | sudo tee /sys/bus/iio/devices/iio\:device0/events/in_illuminance_thresh_either_en
1
akshayajpi@raspberrypi:/sys/kernel/debug/iio/iio:device0 $ i2cget -f -y 1 0x53 0x19
0x14
akshayajpi@raspberrypi:/sys/kernel/debug/iio/iio:device0 $ echo 0x19 | sudo tee direct_reg_access
0x19
akshayajpi@raspberrypi:/sys/kernel/debug/iio/iio:device0 $ cat direct_reg_access
0x14
5. Write falling threshold via debugfs, verify the threshold written via sysfs.
akshayajpi@raspberrypi:/sys/kernel/debug/iio/iio:device0 $ echo 0x24 0x32 | sudo tee direct_reg_access
0x24 0x32
akshayajpi@raspberrypi:/sys/kernel/debug/iio/iio:device0 $ cat direct_reg_access
0x32
akshayajpi@raspberrypi:/sys/kernel/debug/iio/iio:device0 $ echo 0x25 0x0 | sudo tee direct_reg_access
0x25 0x0
akshayajpi@raspberrypi:/sys/kernel/debug/iio/iio:device0 $ cat direct_reg_access
0x0
akshayajpi@raspberrypi:/sys/kernel/debug/iio/iio:device0 $ echo 0x26 0x0 | sudo tee direct_reg_access
0x26 0x0
akshayajpi@raspberrypi:/sys/kernel/debug/iio/iio:device0 $ cat direct_reg_access
0x0
akshayajpi@raspberrypi:/sys/kernel/debug/iio/iio:device0 $ cat /sys/bus/iio/devices/iio\:device0/events/in_illuminance_thresh_falling_value
50
final value = 0x0 << 16 | 0x0 << 8 | 0x32 = 50
6. Block light and verify interrupts getting generated.
-> Before blocking light
cat /proc/interrupts|grep ltr390
58: 0 0 0 0 pinctrl-bcm2835 4 Edge ltr390_thresh_event
->After blocking light
58: 63 0 0 0 pinctrl-bcm2835 4 Edge ltr390_thresh_event
7. write value to a non-writeable reg via debugfs.
-> LTR390_ALS_DATA_0|1|2 are non-writeable registers. Writing to them gives I/O error as expected.
akshayajpi@raspberrypi:/sys/kernel/debug/iio/iio:device0 $ echo 0xd 0x1 | sudo tee direct_reg_access
0xd 0x1
tee: direct_reg_access: Input/output error
akshayajpi@raspberrypi:/sys/kernel/debug/iio/iio:device0 $ echo 0xe 0x1 | sudo tee direct_reg_access
0xe 0x1
tee: direct_reg_access: Input/output error
akshayajpi@raspberrypi:/sys/kernel/debug/iio/iio:device0 $ echo 0xf 0x1 | sudo tee direct_reg_access
0xf 0x1
tee: direct_reg_access: Input/output error
8. read value from a non-readable reg via debugfs.
akshayajpi@raspberrypi:/sys/kernel/debug/iio/iio:device0 $ echo 0x2 |sudo tee direct_reg_access
0x2
akshayajpi@raspberrypi:/sys/kernel/debug/iio/iio:device0 $ cat direct_reg_access
cat: direct_reg_access: Input/output error
9. do simple raw reads from debugfs.
-> reading raw value via sysfs:
akshayajpi@raspberrypi:/sys/kernel/debug/iio/iio:device0 $ cat /sys/bus/iio/devices/iio\:device0/in_illuminance_raw
627
akshayajpi@raspberrypi:/sys/kernel/debug/iio/iio:device0 $ cat /sys/bus/iio/devices/iio\:device0/in_illuminance_raw
622
akshayajpi@raspberrypi:/sys/kernel/debug/iio/iio:device0 $ cat /sys/bus/iio/devices/iio\:device0/in_illuminance_raw
616
-> reading via debugfs (should be in the same ballpark of sysfs)
akshayajpi@raspberrypi:/sys/kernel/debug/iio/iio:device0 $ echo 0xd | sudo tee direct_reg_access
0xd
akshayajpi@raspberrypi:/sys/kernel/debug/iio/iio:device0 $ cat direct_reg_access
0xC7
akshayajpi@raspberrypi:/sys/kernel/debug/iio/iio:device0 $ echo 0xe | sudo tee direct_reg_access
0xe
akshayajpi@raspberrypi:/sys/kernel/debug/iio/iio:device0 $ cat direct_reg_access
0x2
akshayajpi@raspberrypi:/sys/kernel/debug/iio/iio:device0 $ echo 0xf | sudo tee direct_reg_access
0xf
akshayajpi@raspberrypi:/sys/kernel/debug/iio/iio:device0 $ cat direct_reg_access
0x0
final value = 0x0 << 16 | 0x2 << 8 | 0x70 = 624
10. Testing reads on registers beyond max_register.
akshayajpi@raspberrypi:/sys/kernel/debug/iio/iio:device0 $ echo 0x27 | sudo tee direct_reg_access
0x27
akshayajpi@raspberrypi:/sys/kernel/debug/iio/iio:device0 $ cat direct_reg_access
cat: direct_reg_access: Input/output error
akshayajpi@raspberrypi:/sys/kernel/debug/iio/iio:device0 $ echo 0x28 | sudo tee direct_reg_access
0x28
akshayajpi@raspberrypi:/sys/kernel/debug/iio/iio:device0 $ cat direct_reg_access
cat: direct_reg_access: Input/output error
drivers/iio/light/ltr390.c | 53 ++++++++++++++++++++++++++++++++++++++
1 file changed, 53 insertions(+)
diff --git a/drivers/iio/light/ltr390.c b/drivers/iio/light/ltr390.c
index ee59bbb8aa09..b1028d027e1b 100644
--- a/drivers/iio/light/ltr390.c
+++ b/drivers/iio/light/ltr390.c
@@ -38,12 +38,21 @@
#define LTR390_ALS_UVS_GAIN 0x05
#define LTR390_PART_ID 0x06
#define LTR390_MAIN_STATUS 0x07
+
#define LTR390_ALS_DATA 0x0D
+#define LTR390_ALS_DATA_BYTE(n) ((LTR390_ALS_DATA) + (n))
+
#define LTR390_UVS_DATA 0x10
+#define LTR390_UVS_DATA_BYTE(n) ((LTR390_UVS_DATA) + (n))
+
#define LTR390_INT_CFG 0x19
#define LTR390_INT_PST 0x1A
+
#define LTR390_THRESH_UP 0x21
+#define LTR390_THRESH_UP_BYTE(n) ((LTR390_THRESH_UP) + (n))
+
#define LTR390_THRESH_LOW 0x24
+#define LTR390_THRESH_LOW_BYTE(n) ((LTR390_THRESH_LOW) + (n))
#define LTR390_PART_NUMBER_ID 0xb
#define LTR390_ALS_UVS_GAIN_MASK GENMASK(2, 0)
@@ -98,11 +107,40 @@ struct ltr390_data {
int int_time_us;
};
+static const struct regmap_range ltr390_readable_reg_ranges[] = {
+ regmap_reg_range(LTR390_MAIN_CTRL, LTR390_MAIN_CTRL),
+ regmap_reg_range(LTR390_ALS_UVS_MEAS_RATE, LTR390_MAIN_STATUS),
+ regmap_reg_range(LTR390_ALS_DATA_BYTE(0), LTR390_ALS_DATA_BYTE(2)),
+ regmap_reg_range(LTR390_UVS_DATA_BYTE(0), LTR390_UVS_DATA_BYTE(2)),
+ regmap_reg_range(LTR390_INT_CFG, LTR390_INT_PST),
+ regmap_reg_range(LTR390_THRESH_UP_BYTE(0), LTR390_THRESH_LOW_BYTE(2)),
+};
+
+static const struct regmap_access_table ltr390_readable_reg_table = {
+ .yes_ranges = ltr390_readable_reg_ranges,
+ .n_yes_ranges = ARRAY_SIZE(ltr390_readable_reg_ranges),
+};
+
+static const struct regmap_range ltr390_writeable_reg_ranges[] = {
+ regmap_reg_range(LTR390_MAIN_CTRL, LTR390_MAIN_CTRL),
+ regmap_reg_range(LTR390_ALS_UVS_MEAS_RATE, LTR390_ALS_UVS_GAIN),
+ regmap_reg_range(LTR390_INT_CFG, LTR390_INT_PST),
+ regmap_reg_range(LTR390_THRESH_UP_BYTE(0), LTR390_THRESH_LOW_BYTE(2)),
+};
+
+static const struct regmap_access_table ltr390_writeable_reg_table = {
+ .yes_ranges = ltr390_writeable_reg_ranges,
+ .n_yes_ranges = ARRAY_SIZE(ltr390_writeable_reg_ranges),
+};
+
static const struct regmap_config ltr390_regmap_config = {
.name = "ltr390",
.reg_bits = 8,
.reg_stride = 1,
.val_bits = 8,
+ .max_register = LTR390_THRESH_LOW_BYTE(2),
+ .rd_table = <r390_readable_reg_table,
+ .wr_table = <r390_writeable_reg_table,
};
/* Sampling frequency is in mili Hz and mili Seconds */
@@ -586,6 +624,20 @@ static int ltr390_write_event_config(struct iio_dev *indio_dev,
}
}
+static int ltr390_debugfs_reg_access(struct iio_dev *indio_dev,
+ unsigned int reg, unsigned int writeval,
+ unsigned int *readval)
+{
+ struct ltr390_data *data = iio_priv(indio_dev);
+
+ guard(mutex)(&data->lock);
+
+ if (readval)
+ return regmap_read(data->regmap, reg, readval);
+
+ return regmap_write(data->regmap, reg, writeval);
+}
+
static const struct iio_info ltr390_info = {
.read_raw = ltr390_read_raw,
.write_raw = ltr390_write_raw,
@@ -594,6 +646,7 @@ static const struct iio_info ltr390_info = {
.read_event_config = ltr390_read_event_config,
.write_event_value = ltr390_write_event_value,
.write_event_config = ltr390_write_event_config,
+ .debugfs_reg_access = ltr390_debugfs_reg_access,
};
static irqreturn_t ltr390_interrupt_handler(int irq, void *private)
--
2.43.0
On Thu, 24 Jul 2025 20:09:39 +0530
Akshay Jindal <akshayaj.lkd@gmail.com> wrote:
> Add support for debugfs_reg_access through the driver's iio_info structure
> to enable low-level register read/write access for debugging.
>
> Signed-off-by: Akshay Jindal <akshayaj.lkd@gmail.com>
> drivers/iio/light/ltr390.c | 53 ++++++++++++++++++++++++++++++++++++++
> 1 file changed, 53 insertions(+)
>
> diff --git a/drivers/iio/light/ltr390.c b/drivers/iio/light/ltr390.c
> index ee59bbb8aa09..b1028d027e1b 100644
> --- a/drivers/iio/light/ltr390.c
> +++ b/drivers/iio/light/ltr390.c
> @@ -38,12 +38,21 @@
> #define LTR390_ALS_UVS_GAIN 0x05
> #define LTR390_PART_ID 0x06
> #define LTR390_MAIN_STATUS 0x07
> +
> #define LTR390_ALS_DATA 0x0D
> +#define LTR390_ALS_DATA_BYTE(n) ((LTR390_ALS_DATA) + (n))
(LTR390_ALS_DATA + (n))
etc There is no benefit in brackets around the bit that isn't a parameter
of the macro that I can see.
> +
> #define LTR390_UVS_DATA 0x10
> +#define LTR390_UVS_DATA_BYTE(n) ((LTR390_UVS_DATA) + (n))
> +
> #define LTR390_INT_CFG 0x19
> #define LTR390_INT_PST 0x1A
> +
> #define LTR390_THRESH_UP 0x21
> +#define LTR390_THRESH_UP_BYTE(n) ((LTR390_THRESH_UP) + (n))
> +
> #define LTR390_THRESH_LOW 0x24
> +#define LTR390_THRESH_LOW_BYTE(n) ((LTR390_THRESH_LOW) + (n))
>
> #define LTR390_PART_NUMBER_ID 0xb
> #define LTR390_ALS_UVS_GAIN_MASK GENMASK(2, 0)
> @@ -98,11 +107,40 @@ struct ltr390_data {
> int int_time_us;
> };
>
> +static const struct regmap_range ltr390_readable_reg_ranges[] = {
> + regmap_reg_range(LTR390_MAIN_CTRL, LTR390_MAIN_CTRL),
> + regmap_reg_range(LTR390_ALS_UVS_MEAS_RATE, LTR390_MAIN_STATUS),
> + regmap_reg_range(LTR390_ALS_DATA_BYTE(0), LTR390_ALS_DATA_BYTE(2)),
> + regmap_reg_range(LTR390_UVS_DATA_BYTE(0), LTR390_UVS_DATA_BYTE(2)),
If we are doing maximum length ranges can we not combine the two above?
Looks to be 0xd,0xe,0xf,0x10,0x11 and 0x012, so a continuous range similar
to the thresholds below.
> + regmap_reg_range(LTR390_INT_CFG, LTR390_INT_PST),
> + regmap_reg_range(LTR390_THRESH_UP_BYTE(0), LTR390_THRESH_LOW_BYTE(2)),
> +};
Thanks,
Jonathan
On Mon, Jul 28, 2025 at 7:23 PM Jonathan Cameron <jic23@kernel.org> wrote:
>
> On Thu, 24 Jul 2025 20:09:39 +0530
> Akshay Jindal <akshayaj.lkd@gmail.com> wrote:
>
> > Add support for debugfs_reg_access through the driver's iio_info structure
> > to enable low-level register read/write access for debugging.
> >
> > Signed-off-by: Akshay Jindal <akshayaj.lkd@gmail.com>
>
> > drivers/iio/light/ltr390.c | 53 ++++++++++++++++++++++++++++++++++++++
> > 1 file changed, 53 insertions(+)
> >
> > diff --git a/drivers/iio/light/ltr390.c b/drivers/iio/light/ltr390.c
> > index ee59bbb8aa09..b1028d027e1b 100644
> > --- a/drivers/iio/light/ltr390.c
> > +++ b/drivers/iio/light/ltr390.c
> > @@ -38,12 +38,21 @@
> > #define LTR390_ALS_UVS_GAIN 0x05
> > #define LTR390_PART_ID 0x06
> > #define LTR390_MAIN_STATUS 0x07
> > +
> > #define LTR390_ALS_DATA 0x0D
> > +#define LTR390_ALS_DATA_BYTE(n) ((LTR390_ALS_DATA) + (n))
> (LTR390_ALS_DATA + (n))
>
> etc There is no benefit in brackets around the bit that isn't a parameter
> of the macro that I can see.
Fixed.
>
> > +
> > #define LTR390_UVS_DATA 0x10
> > +#define LTR390_UVS_DATA_BYTE(n) ((LTR390_UVS_DATA) + (n))
> > +
> > #define LTR390_INT_CFG 0x19
> > #define LTR390_INT_PST 0x1A
> > +
> > #define LTR390_THRESH_UP 0x21
> > +#define LTR390_THRESH_UP_BYTE(n) ((LTR390_THRESH_UP) + (n))
> > +
> > #define LTR390_THRESH_LOW 0x24
> > +#define LTR390_THRESH_LOW_BYTE(n) ((LTR390_THRESH_LOW) + (n))
> >
> > #define LTR390_PART_NUMBER_ID 0xb
> > #define LTR390_ALS_UVS_GAIN_MASK GENMASK(2, 0)
> > @@ -98,11 +107,40 @@ struct ltr390_data {
> > int int_time_us;
> > };
> >
> > +static const struct regmap_range ltr390_readable_reg_ranges[] = {
> > + regmap_reg_range(LTR390_MAIN_CTRL, LTR390_MAIN_CTRL),
> > + regmap_reg_range(LTR390_ALS_UVS_MEAS_RATE, LTR390_MAIN_STATUS),
> > + regmap_reg_range(LTR390_ALS_DATA_BYTE(0), LTR390_ALS_DATA_BYTE(2)),
> > + regmap_reg_range(LTR390_UVS_DATA_BYTE(0), LTR390_UVS_DATA_BYTE(2)),
>
> If we are doing maximum length ranges can we not combine the two above?
> Looks to be 0xd,0xe,0xf,0x10,0x11 and 0x012, so a continuous range similar
> to the thresholds below.
>
Done the changes.
> > + regmap_reg_range(LTR390_INT_CFG, LTR390_INT_PST),
> > + regmap_reg_range(LTR390_THRESH_UP_BYTE(0), LTR390_THRESH_LOW_BYTE(2)),
> > +};
>
> Thanks,
>
> Jonathan
>
Thanks for the review. Floated a v4 with the changes.
Thanks,
Akshay
On 7/24/25 08:39, Akshay Jindal wrote:
> Add support for debugfs_reg_access through the driver's iio_info structure
> to enable low-level register read/write access for debugging.
>
> Signed-off-by: Akshay Jindal <akshayaj.lkd@gmail.com>
> ---
>
> Changes since v2:
> ================
> - merged the regmap_range of LTR390_UP_THRESH with LTR390_LOW_THRESH.
>
> Changes since v1:
> =================
> - Replaced _[0|1|2] macros with a respective common parameterized macro.
> - Retained base macros to avoid churn.
> - Swapped regmap_write with regmap_read to avoid negate operator.
> - Simplified debugfs function by directly returning return value of
> regmap_[read|write].
> - Replaced [readable|writeable]_reg with regmap ranges by using
> [rd|wr]_table property of regmap_config.
> - Updated the testing details with v2 changes.
>
> Testing details (done for v2):
> ==============================
> -> Tested on Raspberrypi 4B. Follow for more details.
This is way too much testing information. Summarize what you tested
instead. It makes it easier to see the results as a summary.
>
> akshayajpi@raspberrypi:~ $ uname -r
> 6.12.35-v8+
> akshayajpi@raspberrypi:~ $ uname -a
> Linux raspberrypi 6.12.35-v8+ #5 SMP PREEMPT Tue Jul 15 17:38:06 IST 2025 aarch64 GNU/Linux
>
> -> Sensor Detection, overlaying of device tree and Driver loading
> akshayajpi@raspberrypi:~ $ i2cdetect -y 1
> 0 1 2 3 4 5 6 7 8 9 a b c d e f
> 00: -- -- -- -- -- -- -- --
> 10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
> 20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
> 30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
> 40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
> 50: -- -- -- 53 -- -- -- -- -- -- -- -- -- -- -- --
> 60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
> 70: -- -- -- -- -- -- -- --
>
> akshayajpi@raspberrypi:~ $ sudo dtoverlay i2c-sensor ltr390
> akshayajpi@raspberrypi:~ $ lsmod|grep ltr390
> ltr390 16384 0
> industrialio 110592 1 ltr390
> regmap_i2c 12288 1 ltr390
>
>
> 1. Disable sensor via debugfs, verify from i2cget and debugfs.
> akshayajpi@raspberrypi:/sys/kernel/debug/iio/iio:device0 $ echo 0x0 | sudo tee direct_reg_access
> 0x0
> akshayajpi@raspberrypi:/sys/kernel/debug/iio/iio:device0 $ cat direct_reg_access
> 0x2
> akshayajpi@raspberrypi:/sys/kernel/debug/iio/iio:device0 $ echo 0x0 0x0 | sudo tee direct_reg_access
> 0x0 0x0
> akshayajpi@raspberrypi:/sys/kernel/debug/iio/iio:device0 $ cat direct_reg_access
> 0x0
> akshayajpi@raspberrypi:/sys/kernel/debug/iio/iio:device0 $ i2cget -f -y 1 0x53 0x0
> 0x00
>
> 2. Disable sensor via debugfs and read data status via debugfs.
> akshayajpi@raspberrypi:/sys/kernel/debug/iio/iio:device0 $ cat /sys/bus/iio/devices/iio\:device0/in_illuminance_raw
> 603
> akshayajpi@raspberrypi:/sys/kernel/debug/iio/iio:device0 $ cat /sys/bus/iio/devices/iio\:device0/in_illuminance_raw
> 603
> akshayajpi@raspberrypi:/sys/kernel/debug/iio/iio:device0 $ cat /sys/bus/iio/devices/iio\:device0/in_illuminance_raw
> 603
> akshayajpi@raspberrypi:/sys/kernel/debug/iio/iio:device0 $ i2cget -f -y 1 0x53 0x7
> 0x28
> akshayajpi@raspberrypi:/sys/kernel/debug/iio/iio:device0 $ i2cget -f -y 1 0x53 0x7
> 0x00
> akshayajpi@raspberrypi:/sys/kernel/debug/iio/iio:device0 $ echo 0x7 | sudo tee direct_reg_access
> 0x7
> akshayajpi@raspberrypi:/sys/kernel/debug/iio/iio:device0 $ cat direct_reg_access
> 0x0
>
> 3. Re-enable sensor via debugfs and read data status via debugfs.
> akshayajpi@raspberrypi:/sys/kernel/debug/iio/iio:device0 $ echo 0x0 0x2 | sudo tee direct_reg_access
> 0x0 0x2
> akshayajpi@raspberrypi:/sys/kernel/debug/iio/iio:device0 $ cat direct_reg_access
> 0x2
> akshayajpi@raspberrypi:/sys/kernel/debug/iio/iio:device0 $ cat /sys/bus/iio/devices/iio\:device0/in_illuminance_raw
> 608
> akshayajpi@raspberrypi:/sys/kernel/debug/iio/iio:device0 $ cat /sys/bus/iio/devices/iio\:device0/in_illuminance_raw
> 614
> akshayajpi@raspberrypi:/sys/kernel/debug/iio/iio:device0 $ cat /sys/bus/iio/devices/iio\:device0/in_illuminance_raw
> 601
> akshayajpi@raspberrypi:/sys/kernel/debug/iio/iio:device0 $ echo 0x7 | sudo tee direct_reg_access
> 0x7
> akshayajpi@raspberrypi:/sys/kernel/debug/iio/iio:device0 $ cat direct_reg_access
> 0x8
>
> 4. Enable interrupts via sysfs and verify via debugfs.
> akshayajpi@raspberrypi:/sys/kernel/debug/iio/iio:device0 $ echo 1 | sudo tee /sys/bus/iio/devices/iio\:device0/events/in_illuminance_thresh_either_en
> 1
> akshayajpi@raspberrypi:/sys/kernel/debug/iio/iio:device0 $ i2cget -f -y 1 0x53 0x19
> 0x14
> akshayajpi@raspberrypi:/sys/kernel/debug/iio/iio:device0 $ echo 0x19 | sudo tee direct_reg_access
> 0x19
> akshayajpi@raspberrypi:/sys/kernel/debug/iio/iio:device0 $ cat direct_reg_access
> 0x14
>
> 5. Write falling threshold via debugfs, verify the threshold written via sysfs.
> akshayajpi@raspberrypi:/sys/kernel/debug/iio/iio:device0 $ echo 0x24 0x32 | sudo tee direct_reg_access
> 0x24 0x32
> akshayajpi@raspberrypi:/sys/kernel/debug/iio/iio:device0 $ cat direct_reg_access
> 0x32
> akshayajpi@raspberrypi:/sys/kernel/debug/iio/iio:device0 $ echo 0x25 0x0 | sudo tee direct_reg_access
> 0x25 0x0
> akshayajpi@raspberrypi:/sys/kernel/debug/iio/iio:device0 $ cat direct_reg_access
> 0x0
> akshayajpi@raspberrypi:/sys/kernel/debug/iio/iio:device0 $ echo 0x26 0x0 | sudo tee direct_reg_access
> 0x26 0x0
> akshayajpi@raspberrypi:/sys/kernel/debug/iio/iio:device0 $ cat direct_reg_access
> 0x0
> akshayajpi@raspberrypi:/sys/kernel/debug/iio/iio:device0 $ cat /sys/bus/iio/devices/iio\:device0/events/in_illuminance_thresh_falling_value
> 50
> final value = 0x0 << 16 | 0x0 << 8 | 0x32 = 50
>
> 6. Block light and verify interrupts getting generated.
> -> Before blocking light
> cat /proc/interrupts|grep ltr390
> 58: 0 0 0 0 pinctrl-bcm2835 4 Edge ltr390_thresh_event
>
> ->After blocking light
> 58: 63 0 0 0 pinctrl-bcm2835 4 Edge ltr390_thresh_event
>
> 7. write value to a non-writeable reg via debugfs.
> -> LTR390_ALS_DATA_0|1|2 are non-writeable registers. Writing to them gives I/O error as expected.
> akshayajpi@raspberrypi:/sys/kernel/debug/iio/iio:device0 $ echo 0xd 0x1 | sudo tee direct_reg_access
> 0xd 0x1
> tee: direct_reg_access: Input/output error
> akshayajpi@raspberrypi:/sys/kernel/debug/iio/iio:device0 $ echo 0xe 0x1 | sudo tee direct_reg_access
> 0xe 0x1
> tee: direct_reg_access: Input/output error
> akshayajpi@raspberrypi:/sys/kernel/debug/iio/iio:device0 $ echo 0xf 0x1 | sudo tee direct_reg_access
> 0xf 0x1
> tee: direct_reg_access: Input/output error
>
> 8. read value from a non-readable reg via debugfs.
> akshayajpi@raspberrypi:/sys/kernel/debug/iio/iio:device0 $ echo 0x2 |sudo tee direct_reg_access
> 0x2
> akshayajpi@raspberrypi:/sys/kernel/debug/iio/iio:device0 $ cat direct_reg_access
> cat: direct_reg_access: Input/output error
>
> 9. do simple raw reads from debugfs.
> -> reading raw value via sysfs:
> akshayajpi@raspberrypi:/sys/kernel/debug/iio/iio:device0 $ cat /sys/bus/iio/devices/iio\:device0/in_illuminance_raw
> 627
> akshayajpi@raspberrypi:/sys/kernel/debug/iio/iio:device0 $ cat /sys/bus/iio/devices/iio\:device0/in_illuminance_raw
> 622
> akshayajpi@raspberrypi:/sys/kernel/debug/iio/iio:device0 $ cat /sys/bus/iio/devices/iio\:device0/in_illuminance_raw
> 616
>
> -> reading via debugfs (should be in the same ballpark of sysfs)
> akshayajpi@raspberrypi:/sys/kernel/debug/iio/iio:device0 $ echo 0xd | sudo tee direct_reg_access
> 0xd
> akshayajpi@raspberrypi:/sys/kernel/debug/iio/iio:device0 $ cat direct_reg_access
> 0xC7
> akshayajpi@raspberrypi:/sys/kernel/debug/iio/iio:device0 $ echo 0xe | sudo tee direct_reg_access
> 0xe
> akshayajpi@raspberrypi:/sys/kernel/debug/iio/iio:device0 $ cat direct_reg_access
> 0x2
> akshayajpi@raspberrypi:/sys/kernel/debug/iio/iio:device0 $ echo 0xf | sudo tee direct_reg_access
> 0xf
> akshayajpi@raspberrypi:/sys/kernel/debug/iio/iio:device0 $ cat direct_reg_access
> 0x0
> final value = 0x0 << 16 | 0x2 << 8 | 0x70 = 624
>
> 10. Testing reads on registers beyond max_register.
> akshayajpi@raspberrypi:/sys/kernel/debug/iio/iio:device0 $ echo 0x27 | sudo tee direct_reg_access
> 0x27
> akshayajpi@raspberrypi:/sys/kernel/debug/iio/iio:device0 $ cat direct_reg_access
> cat: direct_reg_access: Input/output error
> akshayajpi@raspberrypi:/sys/kernel/debug/iio/iio:device0 $ echo 0x28 | sudo tee direct_reg_access
> 0x28
> akshayajpi@raspberrypi:/sys/kernel/debug/iio/iio:device0 $ cat direct_reg_access
> cat: direct_reg_access: Input/output error
>
> drivers/iio/light/ltr390.c | 53 ++++++++++++++++++++++++++++++++++++++
> 1 file changed, 53 insertions(+)
>
> diff --git a/drivers/iio/light/ltr390.c b/drivers/iio/light/ltr390.c
> index ee59bbb8aa09..b1028d027e1b 100644
> --- a/drivers/iio/light/ltr390.c
> +++ b/drivers/iio/light/ltr390.c
> @@ -38,12 +38,21 @@
> #define LTR390_ALS_UVS_GAIN 0x05
> #define LTR390_PART_ID 0x06
> #define LTR390_MAIN_STATUS 0x07
> +
> #define LTR390_ALS_DATA 0x0D
> +#define LTR390_ALS_DATA_BYTE(n) ((LTR390_ALS_DATA) + (n))
> +
> #define LTR390_UVS_DATA 0x10
> +#define LTR390_UVS_DATA_BYTE(n) ((LTR390_UVS_DATA) + (n))
> +
> #define LTR390_INT_CFG 0x19
> #define LTR390_INT_PST 0x1A
> +
> #define LTR390_THRESH_UP 0x21
> +#define LTR390_THRESH_UP_BYTE(n) ((LTR390_THRESH_UP) + (n))
> +
> #define LTR390_THRESH_LOW 0x24
> +#define LTR390_THRESH_LOW_BYTE(n) ((LTR390_THRESH_LOW) + (n))
>
> #define LTR390_PART_NUMBER_ID 0xb
> #define LTR390_ALS_UVS_GAIN_MASK GENMASK(2, 0)
> @@ -98,11 +107,40 @@ struct ltr390_data {
> int int_time_us;
> };
>
> +static const struct regmap_range ltr390_readable_reg_ranges[] = {
> + regmap_reg_range(LTR390_MAIN_CTRL, LTR390_MAIN_CTRL),
> + regmap_reg_range(LTR390_ALS_UVS_MEAS_RATE, LTR390_MAIN_STATUS),
> + regmap_reg_range(LTR390_ALS_DATA_BYTE(0), LTR390_ALS_DATA_BYTE(2)),
> + regmap_reg_range(LTR390_UVS_DATA_BYTE(0), LTR390_UVS_DATA_BYTE(2)),
> + regmap_reg_range(LTR390_INT_CFG, LTR390_INT_PST),
> + regmap_reg_range(LTR390_THRESH_UP_BYTE(0), LTR390_THRESH_LOW_BYTE(2)),
> +};
> +
> +static const struct regmap_access_table ltr390_readable_reg_table = {
> + .yes_ranges = ltr390_readable_reg_ranges,
> + .n_yes_ranges = ARRAY_SIZE(ltr390_readable_reg_ranges),
> +};
> +
> +static const struct regmap_range ltr390_writeable_reg_ranges[] = {
> + regmap_reg_range(LTR390_MAIN_CTRL, LTR390_MAIN_CTRL),
> + regmap_reg_range(LTR390_ALS_UVS_MEAS_RATE, LTR390_ALS_UVS_GAIN),
> + regmap_reg_range(LTR390_INT_CFG, LTR390_INT_PST),
> + regmap_reg_range(LTR390_THRESH_UP_BYTE(0), LTR390_THRESH_LOW_BYTE(2)),
> +};
> +
> +static const struct regmap_access_table ltr390_writeable_reg_table = {
> + .yes_ranges = ltr390_writeable_reg_ranges,
> + .n_yes_ranges = ARRAY_SIZE(ltr390_writeable_reg_ranges),
> +};
> +
> static const struct regmap_config ltr390_regmap_config = {
> .name = "ltr390",
> .reg_bits = 8,
> .reg_stride = 1,
> .val_bits = 8,
> + .max_register = LTR390_THRESH_LOW_BYTE(2),
> + .rd_table = <r390_readable_reg_table,
> + .wr_table = <r390_writeable_reg_table,
> };
>
> /* Sampling frequency is in mili Hz and mili Seconds */
> @@ -586,6 +624,20 @@ static int ltr390_write_event_config(struct iio_dev *indio_dev,
> }
> }
>
> +static int ltr390_debugfs_reg_access(struct iio_dev *indio_dev,
> + unsigned int reg, unsigned int writeval,
> + unsigned int *readval)
> +{
> + struct ltr390_data *data = iio_priv(indio_dev);
> +
> + guard(mutex)(&data->lock);
> +
> + if (readval)
> + return regmap_read(data->regmap, reg, readval);
> +
> + return regmap_write(data->regmap, reg, writeval);
> +}
> +
> static const struct iio_info ltr390_info = {
> .read_raw = ltr390_read_raw,
> .write_raw = ltr390_write_raw,
> @@ -594,6 +646,7 @@ static const struct iio_info ltr390_info = {
> .read_event_config = ltr390_read_event_config,
> .write_event_value = ltr390_write_event_value,
> .write_event_config = ltr390_write_event_config,
> + .debugfs_reg_access = ltr390_debugfs_reg_access,
> };
>
> static irqreturn_t ltr390_interrupt_handler(int irq, void *private)
thanks,
-- Shuah
On Fri, Jul 25, 2025 at 3:29 AM Shuah Khan <skhan@linuxfoundation.org> wrote: > > On 7/24/25 08:39, Akshay Jindal wrote: > > Testing details (done for v2): > > ============================== > > -> Tested on Raspberrypi 4B. Follow for more details. > > This is way too much testing information. Summarize what you tested > instead. It makes it easier to see the results as a summary. > Thanks Shuah for pointing this out. Will make sure summarized testing information in the upcoming version/patches. On 7/24/25 08:39, Akshay Jindal wrote: > > Add support for debugfs_reg_access through the driver's iio_info structure > to enable low-level register read/write access for debugging. > > Signed-off-by: Akshay Jindal <akshayaj.lkd@gmail.com> > --- > > Changes since v2: > ================ > - merged the regmap_range of LTR390_UP_THRESH with LTR390_LOW_THRESH. > > Changes since v1: > ================= > - Replaced _[0|1|2] macros with a respective common parameterized macro. > - Retained base macros to avoid churn. > - Swapped regmap_write with regmap_read to avoid negate operator. > - Simplified debugfs function by directly returning return value of > regmap_[read|write]. > - Replaced [readable|writeable]_reg with regmap ranges by using > [rd|wr]_table property of regmap_config. > - Updated the testing details with v2 changes. Dear Maintainers, Is there any feedback on the v3 patch? Thanks, Akshay
© 2016 - 2025 Red Hat, Inc.