1 | /* |
---|---|
2 | * Copyright (C) 2012 Thomas Petazzoni |
3 | * |
4 | * Thomas Petazzoni <thomas.petazzoni@free-electrons.com> |
5 | * |
6 | * This file is licensed under the terms of the GNU General Public |
7 | * License version 2. This program is licensed "as is" without any |
8 | * warranty of any kind, whether express or implied. |
9 | */ |
10 | |
11 | #include <linux/acpi.h> |
12 | #include <linux/init.h> |
13 | #include <linux/of.h> |
14 | #include <linux/of_irq.h> |
15 | #include <linux/irqchip.h> |
16 | #include <linux/platform_device.h> |
17 | |
18 | /* |
19 | * This special of_device_id is the sentinel at the end of the |
20 | * of_device_id[] array of all irqchips. It is automatically placed at |
21 | * the end of the array by the linker, thanks to being part of a |
22 | * special section. |
23 | */ |
24 | static const struct of_device_id |
25 | irqchip_of_match_end __used __section("__irqchip_of_table_end"); |
26 | |
27 | extern struct of_device_id __irqchip_of_table[]; |
28 | |
29 | void __init irqchip_init(void) |
30 | { |
31 | of_irq_init(matches: __irqchip_of_table); |
32 | acpi_probe_device_table(irqchip); |
33 | } |
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(child: np); |
39 | of_irq_init_cb_t irq_init_cb = of_device_get_match_data(dev: &pdev->dev); |
40 | |
41 | if (!irq_init_cb) { |
42 | of_node_put(node: par_np); |
43 | return -EINVAL; |
44 | } |
45 | |
46 | if (par_np == np) |
47 | par_np = NULL; |
48 | |
49 | /* |
50 | * If there's a parent interrupt controller and none of the parent irq |
51 | * domains have been registered, that means the parent interrupt |
52 | * controller has not been initialized yet. it's not time for this |
53 | * interrupt controller to initialize. So, defer probe of this |
54 | * interrupt controller. The actual initialization callback of this |
55 | * interrupt controller can check for specific domains as necessary. |
56 | */ |
57 | if (par_np && !irq_find_matching_host(node: par_np, bus_token: DOMAIN_BUS_ANY)) { |
58 | of_node_put(node: par_np); |
59 | return -EPROBE_DEFER; |
60 | } |
61 | |
62 | return irq_init_cb(np, par_np); |
63 | } |
64 | EXPORT_SYMBOL_GPL(platform_irqchip_probe); |
65 |