From 3e57ad907caa55bab8ba52ef87ddbc5130aede2c Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sat, 7 Aug 2021 07:24:11 -0600 Subject: [PATCH] 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 --- arch/sandbox/dts/sandbox.dtsi | 13 +++++++++++++ arch/sandbox/include/asm/irq.h | 20 ++++++++++++++++++++ drivers/misc/Makefile | 2 +- drivers/misc/irq-uclass.c | 10 ++++++++-- drivers/misc/irq_sandbox.c | 15 +++------------ drivers/misc/irq_sandbox_test.c | 22 ++++++++++++++++++++++ include/irq.h | 29 +++++++++++++++++++++++++++++ test/dm/of_platdata.c | 26 ++++++++++++++++++++++---- tools/dtoc/dtb_platdata.py | 1 + 9 files changed, 119 insertions(+), 19 deletions(-) create mode 100644 arch/sandbox/include/asm/irq.h create mode 100644 drivers/misc/irq_sandbox_test.c diff --git a/arch/sandbox/dts/sandbox.dtsi b/arch/sandbox/dts/sandbox.dtsi index 6cf5f14cd1..1fc9c9bdfc 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 0000000000..f73fec74f5 --- /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 b64cd2a4de..c16a77c34c 100644 --- a/drivers/misc/Makefile +++ b/drivers/misc/Makefile @@ -42,7 +42,7 @@ obj-$(CONFIG_GDSYS_IOEP) += gdsys_ioep.o 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 3aa26f61d9..eb9f3b902f 100644 --- a/drivers/misc/irq-uclass.c +++ b/drivers/misc/irq-uclass.c @@ -64,8 +64,8 @@ int irq_read_and_clear(struct irq *irq) } #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 @@ int irq_get_by_driver_info(struct udevice *dev, 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 1f7e62e661..8b5573fcad 100644 --- a/drivers/misc/irq_sandbox.c +++ b/drivers/misc/irq_sandbox.c @@ -9,19 +9,9 @@ #include #include #include +#include #include -/** - * 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 @@ static const struct udevice_id sandbox_irq_ids[] = { { } }; -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() }; diff --git a/drivers/misc/irq_sandbox_test.c b/drivers/misc/irq_sandbox_test.c new file mode 100644 index 0000000000..95c45c24ed --- /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 +#include +#include +#include + +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 8527e4dd79..a0965e4420 100644 --- a/include/irq.h +++ b/include/irq.h @@ -200,6 +200,35 @@ int irq_restore_polarities(struct udevice *dev); */ 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 c4a2d11410..082989021d 100644 --- a/test/dm/of_platdata.c +++ b/test/dm/of_platdata.c @@ -4,6 +4,7 @@ #include #include #include +#include #include #include #include @@ -28,11 +29,9 @@ static int dm_test_of_plat_props(struct unit_test_state *uts) 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 @@ static int dm_test_of_plat_clk(struct unit_test_state *uts) 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 869c92b49b..3bb5c680f2 100644 --- a/tools/dtoc/dtb_platdata.py +++ b/tools/dtoc/dtb_platdata.py @@ -62,6 +62,7 @@ VAL_PREFIX = 'dtv_' # a phandle property. PHANDLE_PROPS = { 'clocks': '#clock-cells', + 'interrupts-extended': '#interrupt-cells', 'gpios': '#gpio-cells', 'sandbox,emul': '#emul-cells', } -- 2.39.5