Skip to contentSkip to conversation

dt-bindings: mfd: mxs-lradc: Fix interrupt order

PATCH In review Fabio Estevam 4 participants 6 messages Nov 10 – Nov 11

Subsystems (7)
lore
Share & tools
lore

Fabio Estevam

author reviewer
#0 lore raw

PATCH v2 1/2 dt-bindings: mfd: mxs-lradc: Fix interrupt order

The interrupt descriptions added during the conversion to YAML do not match the ICOLL source numbers used by the existing DTS files.

For i.MX23, Table 5-1 of the reference manual maps source 36 to touch detection and sources 37 through 44 to channels 0 through 7. imx23.dtsi lists these sources in that order.

For i.MX28, Table 5-1 maps source 10 to touch detection, sources 14 and 15 to the threshold interrupts, sources 16 through 23 to channels 0 through 7, and sources 24 and 25 to buttons 0 and 1. imx28.dtsi also lists these sources in that order.

Reorder the schema descriptions to match the hardware documentation and the existing DT ABI.

Fixes 009528b5aa13 ("dt-bindings: mfd: convert mxs-lradc bindings to json-schema")

---
Changes since v1:
- Newly introduced.

 Documentation/devicetree/bindings/mfd/mxs-lradc.yaml | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)
Documentation/devicetree/bindings/mfd/mxs-lradc.yaml +4 -4
index 782b2f4005a0..755029880677 100644
@@ -87,13 +87,13 @@ then:
   properties:
     interrupts:
       items:
+        - description: touchscreen
         - description: channel 0
         - description: channel 1
         - description: channel 2
         - description: channel 3
         - description: channel 4
         - description: channel 5
-        - description: touchscreen
         - description: channel 6
         - description: channel 7
     fsl,lradc-touchscreen-wires:
@@ -102,6 +102,7 @@ else:
   properties:
     interrupts:
       items:
+        - description: touchscreen
         - description: threshold 0
         - description: threshold 1
         - description: channel 0
@@ -110,11 +111,10 @@ else:
         - description: channel 3
         - description: channel 4
         - description: channel 5
-        - description: button 0
-        - description: button 1
-        - description: touchscreen
         - description: channel 6
         - description: channel 7
+        - description: button 0
+        - description: button 1
 
 additionalProperties: false
 
Signature · 1 line
2.43.0
author reviewer
#1 lore raw

PATCH v2 2/2 mfd: mxs-lradc: Pass parent IRQs to child drivers

The MFD driver stores raw DT interrupt indices in IRQ resources but registers its child devices without an IRQ domain or IRQ base. The child drivers consequently receive the indices as if they were mapped Linux IRQ numbers. IRQ index 0 triggers the platform_get_irq_byname() warning:

0 is an invalid IRQ number

The children then try to recover the indices from their resources and map them against the parent OF node. Besides duplicating IRQ names in the parent and children, this relies on invalid platform IRQ resources and fails when IRQ 0 is rejected.

Resolve the interrupts with platform_get_irq() in the MFD parent and store the mapped IRQs in the shared LRADC data. Drop the child IRQ resources and duplicated name arrays, and have both child drivers request the mapped IRQs directly. Use the MFD memory base support to translate a single relative memory resource shared by both cells.

Tested on an i.MX28 EVK. The mxs-lradc-ts driver probes successfully, touch events are reported, and the touch-detect and LRADC channel 7 interrupt counters increase as expected.

---
Changes since v1:
- Rework the IRQ handling as suggested by Lee Jones:
- Replace the per-probe resource copying and mutation with parent-owned

    mapped IRQ arrays;

- Remove the static IRQ resources and duplicated IRQ-name arrays;
- Resolve IRQs in the MFD parent using platform_get_irq();
- Have the child drivers request the mapped IRQs directly;
- Collapse the per-SoC MFD cell arrays into a single const array;
- Pass the parent memory resource through the MFD mem_base argument.
- Add a preceding DT binding patch correcting the documented interrupt order

This is a long-standing bug that I reported in 2020:
https://lore.kernel.org/linux-input/CAOMZO5CgTzo6GuXptD4mFTN=UsJJqpkixDW1Q64gqZGrij8+uQ@mail.gmail.com/

This patch touches MFD, IIO, and Input. Since the IRQ mapping is moved into the MFD parent, I suggest merging it through the MFD tree, with acks from the IIO and Input maintainers.

The full backtrace:

[   10.540505] WARNING: drivers/base/platform.c:492 at __platform_get_irq_byname+0xb4/0xcc, CPU#0: swapper/0/1
[   10.555516] 0 is an invalid IRQ number
[   10.559627] Modules linked in:
[   10.562849] CPU: 0 UID: 0 PID: 1 Comm: swapper/0 Not tainted 7.3.0-rc7-next-20261016-00003-g36062817a968 #17 VOLUNTARY
[   10.573732] Hardware name: Freescale MXS (Device Tree)
[   10.578934] Call trace:
[   10.578992]  unwind_backtrace from show_stack+0x10/0x14
[   10.586955]  show_stack from dump_stack_lvl+0x48/0x64
[   10.592170]  dump_stack_lvl from __warn+0x8c/0x190
[   10.597114]  __warn from warn_slowpath_fmt+0x94/0xcc
[   10.602232]  warn_slowpath_fmt from __platform_get_irq_byname+0xb4/0xcc
[   10.609027]  __platform_get_irq_byname from platform_get_irq_byname+0x10/0x30
[   10.616337]  platform_get_irq_byname from mxs_lradc_ts_probe+0x18c/0x378
[   10.623247]  mxs_lradc_ts_probe from platform_probe+0x58/0x90
[   10.629174]  platform_probe from really_probe+0xc4/0x2cc
[   10.634649]  really_probe from __driver_probe_device+0xa0/0x1e0
[   10.640721]  __driver_probe_device from driver_probe_device+0x30/0xc0
[   10.647315]  driver_probe_device from __driver_attach+0x94/0x158
[   10.653466]  __driver_attach from bus_for_each_dev+0x7c/0xd0
[   10.659280]  bus_for_each_dev from bus_add_driver+0x158/0x1fc
[   10.665169]  bus_add_driver from driver_register+0x7c/0x114
[   10.670901]  driver_register from do_one_initcall+0x60/0x294
[   10.676721]  do_one_initcall from kernel_init_freeable+0x19c/0x24c
[   10.683073]  kernel_init_freeable from kernel_init+0x14/0x10c
[   10.688997]  kernel_init from ret_from_fork+0x14/0x38
[   10.694200] Exception stack(0xc8819fb0 to 0xc8819ff8)
[   10.699335] 9fa0:                                     00000000 00000000 00000000 00000000
[   10.707591] 9fc0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
[   10.715843] 9fe0: 00000000 00000000 00000000 00000000 00000013 00000000
[   10.723117] irq event stamp: 146363
[   10.726729] hardirqs last  enabled at (146367): [<c00adbd8>] __nbcon_atomic_flush_pending_con+0x120/0x1c0
[   10.736770] hardirqs last disabled at (146372): [<c0008f38>] __irq_svc+0x58/0xb0
[   10.744618] softirqs last  enabled at (146362): [<c0032c20>] __irq_exit_rcu+0x148/0x1d4
[   10.753153] softirqs last disabled at (146385): [<c0032c20>] __irq_exit_rcu+0x148/0x1d4
[   10.761603] ---[ end trace 0000000000000000 ]---
[   10.766374] mxs-lradc-ts mxs-lradc-ts: error -EINVAL: IRQ mxs-lradc-touchscreen not found
[   10.766456] mxs-lradc-ts mxs-lradc-ts: probe with driver mxs-lradc-ts failed with error -22
 drivers/iio/adc/mxs-lradc-adc.c          |  43 +-----
 drivers/input/touchscreen/mxs-lradc-ts.c |  24 +---
 drivers/mfd/mxs-lradc.c                  | 172 ++++++++++++-----------
 include/linux/mfd/mxs-lradc.h            |  10 ++
 4 files changed, 107 insertions(+), 142 deletions(-)
drivers/iio/adc/mxs-lradc-adc.c +5 -38
index dda5182a5076..1222997649f4 100644
@@ -17,7 +17,6 @@
 #include <linux/mfd/core.h>
 #include <linux/mfd/mxs-lradc.h>
 #include <linux/module.h>
-#include <linux/of_irq.h>
 #include <linux/platform_device.h>
 #include <linux/sysfs.h>
 
@@ -39,28 +38,6 @@
 
 #define VREF_MV_BASE 1850
 
-static const char *mx23_lradc_adc_irq_names[] = {
-	"mxs-lradc-channel0",
-	"mxs-lradc-channel1",
-	"mxs-lradc-channel2",
-	"mxs-lradc-channel3",
-	"mxs-lradc-channel4",
-	"mxs-lradc-channel5",
-};
-
-static const char *mx28_lradc_adc_irq_names[] = {
-	"mxs-lradc-thresh0",
-	"mxs-lradc-thresh1",
-	"mxs-lradc-channel0",
-	"mxs-lradc-channel1",
-	"mxs-lradc-channel2",
-	"mxs-lradc-channel3",
-	"mxs-lradc-channel4",
-	"mxs-lradc-channel5",
-	"mxs-lradc-button0",
-	"mxs-lradc-button1",
-};
-
 static const u32 mxs_lradc_adc_vref_mv[][LRADC_MAX_TOTAL_CHANS] = {
 	[IMX23_LRADC] = {
 		VREF_MV_BASE,		/* CH0 */
@@ -691,9 +668,8 @@ static int mxs_lradc_adc_probe(struct platform_device *pdev)
 	struct mxs_lradc_adc *adc;
 	struct iio_dev *iio;
 	struct resource *iores;
-	int ret, irq, virq, i, s, n;
+	int ret, i, s;
 	u64 scale_uv;
-	const char **irq_name;
 
 	/* Allocate the IIO device. */
 	iio = devm_iio_device_alloc(dev, sizeof(*adc));
@@ -725,28 +701,19 @@ static int mxs_lradc_adc_probe(struct platform_device *pdev)
 	if (lradc->soc == IMX23_LRADC) {
 		iio->channels = mx23_lradc_chan_spec;
 		iio->num_channels = ARRAY_SIZE(mx23_lradc_chan_spec);
-		irq_name = mx23_lradc_adc_irq_names;
-		n = ARRAY_SIZE(mx23_lradc_adc_irq_names);
 	} else {
 		iio->channels = mx28_lradc_chan_spec;
 		iio->num_channels = ARRAY_SIZE(mx28_lradc_chan_spec);
-		irq_name = mx28_lradc_adc_irq_names;
-		n = ARRAY_SIZE(mx28_lradc_adc_irq_names);
 	}
 
 	ret = stmp_reset_block(adc->base);
 	if (ret)
 		return ret;
 
-	for (i = 0; i < n; i++) {
-		irq = platform_get_irq_byname(pdev, irq_name[i]);
-		if (irq < 0)
-			return irq;
-
-		virq = irq_of_parse_and_map(dev->parent->of_node, irq);
-
-		ret = devm_request_irq(dev, virq, mxs_lradc_adc_handle_irq,
-				       0, irq_name[i], iio);
+	for (i = 0; i < lradc->num_adc_irqs; i++) {
+		ret = devm_request_irq(dev, lradc->adc_irq[i],
+				       mxs_lradc_adc_handle_irq, 0,
+				       dev_name(dev), iio);
 		if (ret)
 			return ret;
 	}
drivers/input/touchscreen/mxs-lradc-ts.c +5 -19
index 2970d9eb9c2b..998206cab3e7 100644
@@ -18,15 +18,8 @@
 #include <linux/mfd/core.h>
 #include <linux/mfd/mxs-lradc.h>
 #include <linux/of.h>
-#include <linux/of_irq.h>
 #include <linux/platform_device.h>
 
-static const char * const mxs_lradc_ts_irq_names[] = {
-	"mxs-lradc-touchscreen",
-	"mxs-lradc-channel6",
-	"mxs-lradc-channel7",
-};
-
 /*
  * Touchscreen handling
  */
@@ -605,7 +598,7 @@ static int mxs_lradc_ts_probe(struct platform_device *pdev)
 	struct device_node *node = dev->parent->of_node;
 	struct mxs_lradc *lradc = dev_get_drvdata(dev->parent);
 	struct mxs_lradc_ts *ts;
-	int ret, irq, virq, i;
+	int ret, i;
 	u32 ts_wires = 0, adapt;
 
 	ts = devm_kzalloc_obj(dev, *ts);
@@ -668,19 +661,12 @@ static int mxs_lradc_ts_probe(struct platform_device *pdev)
 		return ret;
 
 	mxs_lradc_ts_hw_init(ts);
+	mxs_lradc_ts_stop(ts);
 
-	for (i = 0; i < 3; i++) {
-		irq = platform_get_irq_byname(pdev, mxs_lradc_ts_irq_names[i]);
-		if (irq < 0)
-			return irq;
-
-		virq = irq_of_parse_and_map(node, irq);
-
-		mxs_lradc_ts_stop(ts);
-
-		ret = devm_request_irq(dev, virq,
+	for (i = 0; i < ARRAY_SIZE(lradc->ts_irq); i++) {
+		ret = devm_request_irq(dev, lradc->ts_irq[i],
 				       mxs_lradc_ts_handle_irq,
-				       0, mxs_lradc_ts_irq_names[i], ts);
+				       0, dev_name(dev), ts);
 		if (ret)
 			return ret;
 	}
drivers/mfd/mxs-lradc.c +87 -85

228 lines not on this page · raw message

include/linux/mfd/mxs-lradc.h +10 -0
index ada3d81ee277..d36951f03da2 100644
@@ -19,6 +19,9 @@
 #define LRADC_MAX_MAPPED_CHANS	8
 #define LRADC_MAX_TOTAL_CHANS	16
 
+#define MXS_LRADC_MAX_ADC_IRQS	10
+#define MXS_LRADC_NUM_TS_IRQS	3
+
 #define LRADC_DELAY_TIMER_HZ	2000
 
 #define LRADC_CTRL0				0x00
@@ -153,6 +156,9 @@ enum mxs_lradc_ts_wires {
  * @buffer_vchans: channels that can be used during buffered capture
  * @touchscreen_wire: touchscreen type (4-wire or 5-wire)
  * @use_touchbutton: button state (on or off)
+ * @num_adc_irqs: number of ADC interrupts
+ * @adc_irq: ADC interrupts
+ * @ts_irq: touchscreen interrupts
  */
 struct mxs_lradc {
 	enum mxs_lradc_id	soc;
@@ -161,6 +167,10 @@ struct mxs_lradc {
 
 	enum mxs_lradc_ts_wires	touchscreen_wire;
 	bool			use_touchbutton;
+
+	unsigned int		num_adc_irqs;
+	int			adc_irq[MXS_LRADC_MAX_ADC_IRQS];
+	int			ts_irq[MXS_LRADC_NUM_TS_IRQS];
 };
 
 static inline u32 mxs_lradc_irq_mask(struct mxs_lradc *lradc)
Signature · 1 line
2.43.0
#2 lore raw

Re: [PATCH v2 2/2] mfd: mxs-lradc: Pass parent IRQs to child drivers

Thank you for your contribution! Sashiko AI review found 1 potential issue to consider: - [Low] mfd: mxs-lradc: Fixes trailer cites driver-core warning commit --

Thank you for your contribution! Sashiko AI review found 1 potential issue to consider:
- [Low] mfd: mxs-lradc: Fixes trailer cites driver-core warning commit --

commit fbb3c430756f909de04d8f2ea7a88e5473612cd3
Author: Fabio Estevam <[email protected]>

Quoted 24 lines

mfd: mxs-lradc: Pass parent IRQs to child drivers

The MFD driver stores raw DT interrupt indices in IRQ resources but registers its child devices without an IRQ domain or IRQ base. The child drivers consequently receive the indices as if they were mapped Linux IRQ numbers. IRQ index 0 triggers the platform_get_irq_byname() warning:

0 is an invalid IRQ number

The children then try to recover the indices from their resources and map them against the parent OF node. Besides duplicating IRQ names in the parent and children, this relies on invalid platform IRQ resources and fails when IRQ 0 is rejected.

Resolve the interrupts with platform_get_irq() in the MFD parent and store the mapped IRQs in the shared LRADC data. Drop the child IRQ resources and duplicated name arrays, and have both child drivers request the mapped IRQs directly. Use the MFD memory base support to translate a single relative memory resource shared by both cells.

Tested on an i.MX28 EVK. The mxs-lradc-ts driver probes successfully, touch events are reported, and the touch-detect and LRADC channel 7 interrupt counters increase as expected.

Quoted 5 lines

[Severity: Low]
Commit a85a6c86c25b ("driver core: platform: Clarify that IRQ 0 is invalid") only added a warning in the platform driver core when an IORESOURCE_IRQ resource has start == 0. The unmapped DT interrupt indices in the MFD cell resources and the irq_of_parse_and_map() workaround in the child drivers were introduced when the driver was split in ead25133e935 ("mfd: mxs-lradc: Add support for mxs-lradc"), 6dd112b9f85e ("iio: adc:
mxs-lradc: Add support for ADC driver"), and d81ca730e3e4 ("input:
touchscreen: mxs-lradc: Add support for touchscreen").

Should the Fixes: tag reference those commits instead?

Signature · 1 line
Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=2
#3 lore raw

Re: [PATCH v2 2/2] mfd: mxs-lradc: Pass parent IRQs to child drivers

In reply to Fabio Estevam
Quoted 18 lines · Fabio Estevam

The MFD driver stores raw DT interrupt indices in IRQ resources but registers its child devices without an IRQ domain or IRQ base. The child drivers consequently receive the indices as if they were mapped Linux IRQ numbers. IRQ index 0 triggers the platform_get_irq_byname() warning:

0 is an invalid IRQ number

The children then try to recover the indices from their resources and map them against the parent OF node. Besides duplicating IRQ names in the parent and children, this relies on invalid platform IRQ resources and fails when IRQ 0 is rejected.

Resolve the interrupts with platform_get_irq() in the MFD parent and store the mapped IRQs in the shared LRADC data. Drop the child IRQ resources and duplicated name arrays, and have both child drivers request the mapped IRQs directly. Use the MFD memory base support to translate a single relative memory resource shared by both cells.

Quoted 7 lines

Tested on an i.MX28 EVK. The mxs-lradc-ts driver probes successfully, touch events are reported, and the touch-detect and LRADC channel 7 interrupt counters increase as expected.

He-he, this rings a bell! I have still a copy of the mbox of this thread locally to maybe (likely never) look into that. So, I am so glad to see this being eventually addressed!

Quoted 2 lines
Fixes a85a6c86c25b ("driver core: platform: Clarify that IRQ 0 is invalid")

...

drivers/input/touchscreen/mxs-lradc-ts.c static int mxs_lradc_ts_probe(struct platform_device *pdev) · line 602

Quoted 6 lines
drivers/input/touchscreen/mxs-lradc-ts.c +1 -1
 	struct device_node *node = dev->parent->of_node;
 	struct mxs_lradc *lradc = dev_get_drvdata(dev->parent);
 	struct mxs_lradc_ts *ts;
-	int ret, irq, virq, i;
+	int ret, i;
 	u32 ts_wires = 0, adapt;

Can we, while at it, kinda follow the reversed xmas tree order here?

...

drivers/mfd/mxs-lradc.c static int mxs_lradc_probe(struct platform_device *pdev) · line 164

Quoted 2 lines
drivers/mfd/mxs-lradc.c +1 -1
-	lradc->soc = (kernel_ulong_t)device_get_match_data(&pdev->dev);
+	data = device_get_match_data(dev);

Is this driver affected by driver_override case? If so, this has to be checked against NULL and return -ENODATA.

Quoted 1 line
drivers/mfd/mxs-lradc.c +1 -0
+	lradc->soc = data->soc;
Signature · 2 lines
With Best Regards,
Andy Shevchenko
#4 lore raw
In reply to Fabio Estevam
Sashiko has reviewed this patch and found no issues.
Quoted 12 lines

The interrupt descriptions added during the conversion to YAML do not match the ICOLL source numbers used by the existing DTS files.

For i.MX23, Table 5-1 of the reference manual maps source 36 to touch detection and sources 37 through 44 to channels 0 through 7. imx23.dtsi lists these sources in that order.

For i.MX28, Table 5-1 maps source 10 to touch detection, sources 14 and 15 to the threshold interrupts, sources 16 through 23 to channels 0 through 7, and sources 24 and 25 to buttons 0 and 1. imx28.dtsi also lists these sources in that order.

Quoted 5 lines

Reorder the schema descriptions to match the hardware documentation and the existing DT ABI.

Fixes 009528b5aa13 ("dt-bindings: mfd: convert mxs-lradc bindings to json-schema")

Sashiko has reviewed this patch and found no issues.

Signature · 1 line
Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=1
Acked-by on v2 1/2
#5 lore raw
In reply to Fabio Estevam
Quoted 12 lines · Fabio Estevam

The interrupt descriptions added during the conversion to YAML do not match the ICOLL source numbers used by the existing DTS files.

For i.MX23, Table 5-1 of the reference manual maps source 36 to touch detection and sources 37 through 44 to channels 0 through 7. imx23.dtsi lists these sources in that order.

For i.MX28, Table 5-1 maps source 10 to touch detection, sources 14 and 15 to the threshold interrupts, sources 16 through 23 to channels 0 through 7, and sources 24 and 25 to buttons 0 and 1. imx28.dtsi also lists these sources in that order.

Quoted 5 lines

Reorder the schema descriptions to match the hardware documentation and the existing DT ABI.

Fixes 009528b5aa13 ("dt-bindings: mfd: convert mxs-lradc bindings to json-schema")

Best regards,
Krzysztof