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>
This commit is contained in:
Simon Glass 2021-08-07 07:24:11 -06:00
parent f521be6083
commit 3e57ad907c
9 changed files with 119 additions and 19 deletions

View file

@ -124,6 +124,19 @@
#sound-dai-cells = <1>; #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 { lcd {
u-boot,dm-pre-proper; u-boot,dm-pre-proper;
compatible = "sandbox,lcd-sdl"; compatible = "sandbox,lcd-sdl";

View file

@ -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 */

View file

@ -42,7 +42,7 @@ obj-$(CONFIG_GDSYS_IOEP) += gdsys_ioep.o
obj-$(CONFIG_GDSYS_RXAUI_CTRL) += gdsys_rxaui_ctrl.o obj-$(CONFIG_GDSYS_RXAUI_CTRL) += gdsys_rxaui_ctrl.o
obj-$(CONFIG_GDSYS_SOC) += gdsys_soc.o obj-$(CONFIG_GDSYS_SOC) += gdsys_soc.o
obj-$(CONFIG_IRQ) += irq-uclass.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_$(SPL_)I2C_EEPROM) += i2c_eeprom.o
obj-$(CONFIG_IHS_FPGA) += ihs_fpga.o obj-$(CONFIG_IHS_FPGA) += ihs_fpga.o
obj-$(CONFIG_IMX8) += imx8/ obj-$(CONFIG_IMX8) += imx8/

View file

@ -64,8 +64,8 @@ int irq_read_and_clear(struct irq *irq)
} }
#if CONFIG_IS_ENABLED(OF_PLATDATA) #if CONFIG_IS_ENABLED(OF_PLATDATA)
int irq_get_by_driver_info(struct udevice *dev, int irq_get_by_phandle(struct udevice *dev, const struct phandle_2_arg *cells,
struct phandle_1_arg *cells, struct irq *irq) struct irq *irq)
{ {
int ret; int ret;
@ -74,6 +74,12 @@ int irq_get_by_driver_info(struct udevice *dev,
return ret; return ret;
irq->id = cells->arg[0]; 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; return 0;
} }
#else #else

View file

@ -9,19 +9,9 @@
#include <dm.h> #include <dm.h>
#include <irq.h> #include <irq.h>
#include <acpi/acpi_device.h> #include <acpi/acpi_device.h>
#include <asm/irq.h>
#include <asm/test.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) static int sandbox_set_polarity(struct udevice *dev, uint irq, bool active_low)
{ {
if (irq > 10) 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", .name = "sandbox_irq",
.id = UCLASS_IRQ, .id = UCLASS_IRQ,
.of_match = sandbox_irq_ids, .of_match = sandbox_irq_ids,
.ops = &sandbox_irq_ops, .ops = &sandbox_irq_ops,
.priv_auto = sizeof(struct sandbox_irq_priv), .priv_auto = sizeof(struct sandbox_irq_priv),
DM_HEADER(<asm/irq.h>)
}; };

View file

@ -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,
};

View file

@ -200,6 +200,35 @@ int irq_restore_polarities(struct udevice *dev);
*/ */
int irq_read_and_clear(struct irq *irq); 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. * irq_get_by_index - Get/request an irq by integer index.
* *

View file

@ -4,6 +4,7 @@
#include <clk.h> #include <clk.h>
#include <dm.h> #include <dm.h>
#include <dt-structs.h> #include <dt-structs.h>
#include <irq.h>
#include <dm/test.h> #include <dm/test.h>
#include <test/test.h> #include <test/test.h>
#include <test/ut.h> #include <test/ut.h>
@ -28,11 +29,9 @@ static int dm_test_of_plat_props(struct unit_test_state *uts)
struct udevice *dev; struct udevice *dev;
int i; int i;
/* Skip the clock */ ut_assertok(uclass_get_device_by_name(UCLASS_MISC, "sandbox_spl_test",
ut_assertok(uclass_first_device_err(UCLASS_MISC, &dev)); &dev));
ut_asserteq_str("sandbox_clk_test", dev->name);
ut_assertok(uclass_next_device_err(&dev));
plat = dev_get_plat(dev); plat = dev_get_plat(dev);
ut_assert(plat->boolval); ut_assert(plat->boolval);
ut_asserteq(1, plat->intval); ut_asserteq(1, plat->intval);
@ -241,3 +240,22 @@ static int dm_test_of_plat_clk(struct unit_test_state *uts)
return 0; return 0;
} }
DM_TEST(dm_test_of_plat_clk, UT_TESTF_SCAN_PDATA); 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);

View file

@ -62,6 +62,7 @@ VAL_PREFIX = 'dtv_'
# a phandle property. # a phandle property.
PHANDLE_PROPS = { PHANDLE_PROPS = {
'clocks': '#clock-cells', 'clocks': '#clock-cells',
'interrupts-extended': '#interrupt-cells',
'gpios': '#gpio-cells', 'gpios': '#gpio-cells',
'sandbox,emul': '#emul-cells', 'sandbox,emul': '#emul-cells',
} }