irq: Tidy up of-platdata irq support
This function is available but not exported. More generally it does not
really work as intended.
Reimplement it and add a sandbox test too.
Signed-off-by: Simon Glass <sjg@chromium.org>
diff --git a/arch/sandbox/dts/sandbox.dtsi b/arch/sandbox/dts/sandbox.dtsi
index 6cf5f14..1fc9c9b 100644
--- a/arch/sandbox/dts/sandbox.dtsi
+++ b/arch/sandbox/dts/sandbox.dtsi
@@ -124,6 +124,19 @@
#sound-dai-cells = <1>;
};
+ irq_sandbox: irq-sbox {
+ u-boot,dm-spl;
+ compatible = "sandbox,irq";
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ irq-test {
+ u-boot,dm-spl;
+ compatible = "sandbox,irq-test";
+ interrupts-extended = <&irq_sandbox 3 0>;
+ };
+
lcd {
u-boot,dm-pre-proper;
compatible = "sandbox,lcd-sdl";
diff --git a/arch/sandbox/include/asm/irq.h b/arch/sandbox/include/asm/irq.h
new file mode 100644
index 0000000..f73fec7
--- /dev/null
+++ b/arch/sandbox/include/asm/irq.h
@@ -0,0 +1,20 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright 2021 Google LLC
+ */
+
+#ifndef __SANDBOX_IRQ_H
+#define __SANDBOX_IRQ_H
+
+/**
+ * struct sandbox_irq_priv - private data for this driver
+ *
+ * @count: Counts the number calls to the read_and_clear() method
+ * @pending: true if an interrupt is pending, else false
+ */
+struct sandbox_irq_priv {
+ int count;
+ bool pending;
+};
+
+#endif /* __SANDBOX_IRQ_H */
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index b64cd2a..c16a77c 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -42,7 +42,7 @@
obj-$(CONFIG_GDSYS_RXAUI_CTRL) += gdsys_rxaui_ctrl.o
obj-$(CONFIG_GDSYS_SOC) += gdsys_soc.o
obj-$(CONFIG_IRQ) += irq-uclass.o
-obj-$(CONFIG_SANDBOX) += irq_sandbox.o
+obj-$(CONFIG_SANDBOX) += irq_sandbox.o irq_sandbox_test.o
obj-$(CONFIG_$(SPL_)I2C_EEPROM) += i2c_eeprom.o
obj-$(CONFIG_IHS_FPGA) += ihs_fpga.o
obj-$(CONFIG_IMX8) += imx8/
diff --git a/drivers/misc/irq-uclass.c b/drivers/misc/irq-uclass.c
index 3aa26f6..eb9f3b9 100644
--- a/drivers/misc/irq-uclass.c
+++ b/drivers/misc/irq-uclass.c
@@ -64,8 +64,8 @@
}
#if CONFIG_IS_ENABLED(OF_PLATDATA)
-int irq_get_by_driver_info(struct udevice *dev,
- struct phandle_1_arg *cells, struct irq *irq)
+int irq_get_by_phandle(struct udevice *dev, const struct phandle_2_arg *cells,
+ struct irq *irq)
{
int ret;
@@ -74,6 +74,12 @@
return ret;
irq->id = cells->arg[0];
+ /*
+ * Note: we could call irq_of_xlate_default() here to do this properly.
+ * For now, this is good enough for existing cases.
+ */
+ irq->flags = cells->arg[1];
+
return 0;
}
#else
diff --git a/drivers/misc/irq_sandbox.c b/drivers/misc/irq_sandbox.c
index 1f7e62e..8b5573f 100644
--- a/drivers/misc/irq_sandbox.c
+++ b/drivers/misc/irq_sandbox.c
@@ -9,19 +9,9 @@
#include <dm.h>
#include <irq.h>
#include <acpi/acpi_device.h>
+#include <asm/irq.h>
#include <asm/test.h>
-/**
- * struct sandbox_irq_priv - private data for this driver
- *
- * @count: Counts the number calls to the read_and_clear() method
- * @pending: true if an interrupt is pending, else false
- */
-struct sandbox_irq_priv {
- int count;
- bool pending;
-};
-
static int sandbox_set_polarity(struct udevice *dev, uint irq, bool active_low)
{
if (irq > 10)
@@ -103,10 +93,11 @@
{ }
};
-U_BOOT_DRIVER(sandbox_irq_drv) = {
+U_BOOT_DRIVER(sandbox_irq) = {
.name = "sandbox_irq",
.id = UCLASS_IRQ,
.of_match = sandbox_irq_ids,
.ops = &sandbox_irq_ops,
.priv_auto = sizeof(struct sandbox_irq_priv),
+ DM_HEADER(<asm/irq.h>)
};
diff --git a/drivers/misc/irq_sandbox_test.c b/drivers/misc/irq_sandbox_test.c
new file mode 100644
index 0000000..95c45c2
--- /dev/null
+++ b/drivers/misc/irq_sandbox_test.c
@@ -0,0 +1,22 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Sandbox driver for testing interrupts with of-platdata
+ *
+ * Copyright 2021 Google LLC
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <irq.h>
+#include <asm/irq.h>
+
+static const struct udevice_id sandbox_irq_test_ids[] = {
+ { .compatible = "sandbox,irq-test" },
+ { }
+};
+
+U_BOOT_DRIVER(sandbox_irq_test) = {
+ .name = "sandbox_irq_test",
+ .id = UCLASS_MISC,
+ .of_match = sandbox_irq_test_ids,
+};
diff --git a/include/irq.h b/include/irq.h
index 8527e4d..a0965e4 100644
--- a/include/irq.h
+++ b/include/irq.h
@@ -200,6 +200,35 @@
*/
int irq_read_and_clear(struct irq *irq);
+struct phandle_2_arg;
+/**
+ * irq_get_by_phandle() - Get an irq by its phandle information (of-platadata)
+ *
+ * This function is used when of-platdata is enabled.
+ *
+ * This looks up an irq using the phandle info. With dtoc, each phandle in the
+ * 'interrupts-extended ' property is transformed into an idx representing the
+ * device. For example:
+ *
+ * interrupts-extended = <&acpi_gpe 0x3c 0>;
+ *
+ * might result in:
+ *
+ * .interrupts_extended = {6, {0x3c, 0}},},
+ *
+ * indicating that the irq is udevice idx 6 in dt-plat.c with a arguments of
+ * 0x3c and 0.This function can return a valid irq given the above
+ * information. In this example it would return an irq containing the
+ * 'acpi_gpe' device and the irq ID 0x3c.
+ *
+ * @dev: Device containing the phandle
+ * @cells: Phandle info
+ * @irq: A pointer to a irq struct to initialise
+ * @return 0 if OK, or a negative error code
+ */
+int irq_get_by_phandle(struct udevice *dev, const struct phandle_2_arg *cells,
+ struct irq *irq);
+
/**
* irq_get_by_index - Get/request an irq by integer index.
*
diff --git a/test/dm/of_platdata.c b/test/dm/of_platdata.c
index c4a2d11..0829890 100644
--- a/test/dm/of_platdata.c
+++ b/test/dm/of_platdata.c
@@ -4,6 +4,7 @@
#include <clk.h>
#include <dm.h>
#include <dt-structs.h>
+#include <irq.h>
#include <dm/test.h>
#include <test/test.h>
#include <test/ut.h>
@@ -28,11 +29,9 @@
struct udevice *dev;
int i;
- /* Skip the clock */
- ut_assertok(uclass_first_device_err(UCLASS_MISC, &dev));
- ut_asserteq_str("sandbox_clk_test", dev->name);
+ ut_assertok(uclass_get_device_by_name(UCLASS_MISC, "sandbox_spl_test",
+ &dev));
- ut_assertok(uclass_next_device_err(&dev));
plat = dev_get_plat(dev);
ut_assert(plat->boolval);
ut_asserteq(1, plat->intval);
@@ -241,3 +240,22 @@
return 0;
}
DM_TEST(dm_test_of_plat_clk, UT_TESTF_SCAN_PDATA);
+
+/* Test irqs with of-platdata */
+static int dm_test_of_plat_irq(struct unit_test_state *uts)
+{
+ struct dtd_sandbox_irq_test *plat;
+ struct udevice *dev;
+ struct irq irq;
+
+ ut_assertok(uclass_get_device_by_name(UCLASS_MISC, "sandbox_irq_test",
+ &dev));
+ plat = dev_get_plat(dev);
+
+ ut_assertok(irq_get_by_phandle(dev, &plat->interrupts_extended[0],
+ &irq));
+ ut_asserteq_str("sandbox_irq", irq.dev->name);
+
+ return 0;
+}
+DM_TEST(dm_test_of_plat_irq, UT_TESTF_SCAN_PDATA);
diff --git a/tools/dtoc/dtb_platdata.py b/tools/dtoc/dtb_platdata.py
index 869c92b..3bb5c68 100644
--- a/tools/dtoc/dtb_platdata.py
+++ b/tools/dtoc/dtb_platdata.py
@@ -62,6 +62,7 @@
# a phandle property.
PHANDLE_PROPS = {
'clocks': '#clock-cells',
+ 'interrupts-extended': '#interrupt-cells',
'gpios': '#gpio-cells',
'sandbox,emul': '#emul-cells',
}