Skip to content

Commit f8410e6

Browse files
Saravana KannanMarc Zyngier
authored andcommitted
irqchip: Add IRQCHIP_PLATFORM_DRIVER_BEGIN/END and IRQCHIP_MATCH helper macros
Compiling an irqchip driver as a platform driver needs to bunch of things to be done right: - Making sure the parent domain is initialized first - Making sure the device can't be unbound from sysfs - Disallowing module unload if it's built as a module - Finding the parent node - Etc. Instead of trying to make sure all future irqchip platform drivers get this right, provide boilerplate macros that take care of all of this. An example use would look something like this. Where acme_foo_init and acme_bar_init are similar to what would be passed to IRQCHIP_DECLARE. IRQCHIP_PLATFORM_DRIVER_BEGIN(acme_irq) IRQCHIP_MATCH("acme,foo", acme_foo_init) IRQCHIP_MATCH("acme,bar", acme_bar_init) IRQCHIP_PLATFORM_DRIVER_END(acme_irq) Signed-off-by: Saravana Kannan <[email protected]> Signed-off-by: Marc Zyngier <[email protected]> Cc: John Stultz <[email protected]> Link: https://lore.kernel.org/r/[email protected]
1 parent b7640d7 commit f8410e6

File tree

2 files changed

+52
-0
lines changed

2 files changed

+52
-0
lines changed

drivers/irqchip/irqchip.c

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,10 @@
1010

1111
#include <linux/acpi.h>
1212
#include <linux/init.h>
13+
#include <linux/of_device.h>
1314
#include <linux/of_irq.h>
1415
#include <linux/irqchip.h>
16+
#include <linux/platform_device.h>
1517

1618
/*
1719
* This special of_device_id is the sentinel at the end of the
@@ -29,3 +31,30 @@ void __init irqchip_init(void)
2931
of_irq_init(__irqchip_of_table);
3032
acpi_probe_device_table(irqchip);
3133
}
34+
35+
int platform_irqchip_probe(struct platform_device *pdev)
36+
{
37+
struct device_node *np = pdev->dev.of_node;
38+
struct device_node *par_np = of_irq_find_parent(np);
39+
of_irq_init_cb_t irq_init_cb = of_device_get_match_data(&pdev->dev);
40+
41+
if (!irq_init_cb)
42+
return -EINVAL;
43+
44+
if (par_np == np)
45+
par_np = NULL;
46+
47+
/*
48+
* If there's a parent interrupt controller and none of the parent irq
49+
* domains have been registered, that means the parent interrupt
50+
* controller has not been initialized yet. it's not time for this
51+
* interrupt controller to initialize. So, defer probe of this
52+
* interrupt controller. The actual initialization callback of this
53+
* interrupt controller can check for specific domains as necessary.
54+
*/
55+
if (par_np && !irq_find_matching_host(np, DOMAIN_BUS_ANY))
56+
return -EPROBE_DEFER;
57+
58+
return irq_init_cb(np, par_np);
59+
}
60+
EXPORT_SYMBOL_GPL(platform_irqchip_probe);

include/linux/irqchip.h

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
#include <linux/acpi.h>
1515
#include <linux/of.h>
16+
#include <linux/platform_device.h>
1617

1718
/*
1819
* This macro must be used by the different irqchip drivers to declare
@@ -26,6 +27,28 @@
2627
*/
2728
#define IRQCHIP_DECLARE(name, compat, fn) OF_DECLARE_2(irqchip, name, compat, fn)
2829

30+
extern int platform_irqchip_probe(struct platform_device *pdev);
31+
32+
#define IRQCHIP_PLATFORM_DRIVER_BEGIN(drv_name) \
33+
static const struct of_device_id drv_name##_irqchip_match_table[] = {
34+
35+
#define IRQCHIP_MATCH(compat, fn) { .compatible = compat, .data = fn },
36+
37+
#define IRQCHIP_PLATFORM_DRIVER_END(drv_name) \
38+
{}, \
39+
}; \
40+
MODULE_DEVICE_TABLE(of, drv_name##_irqchip_match_table); \
41+
static struct platform_driver drv_name##_driver = { \
42+
.probe = platform_irqchip_probe, \
43+
.driver = { \
44+
.name = #drv_name, \
45+
.owner = THIS_MODULE, \
46+
.of_match_table = drv_name##_irqchip_match_table, \
47+
.suppress_bind_attrs = true, \
48+
}, \
49+
}; \
50+
builtin_platform_driver(drv_name##_driver)
51+
2952
/*
3053
* This macro must be used by the different irqchip drivers to declare
3154
* the association between their version and their initialization function.

0 commit comments

Comments
 (0)