Thomas Petazzoni | f6e916b | 2012-11-20 23:00:52 +0100 | [diff] [blame] | 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 | |
Marc Zyngier | 46e589a | 2015-09-28 15:49:13 +0100 | [diff] [blame] | 11 | #include <linux/acpi.h> |
Thomas Petazzoni | f6e916b | 2012-11-20 23:00:52 +0100 | [diff] [blame] | 12 | #include <linux/init.h> |
Saravana Kannan | f8410e6 | 2020-07-17 17:06:34 -0700 | [diff] [blame] | 13 | #include <linux/of_device.h> |
Thomas Petazzoni | f6e916b | 2012-11-20 23:00:52 +0100 | [diff] [blame] | 14 | #include <linux/of_irq.h> |
Stephen Boyd | 559ba4b | 2014-03-04 17:01:21 -0800 | [diff] [blame] | 15 | #include <linux/irqchip.h> |
Saravana Kannan | f8410e6 | 2020-07-17 17:06:34 -0700 | [diff] [blame] | 16 | #include <linux/platform_device.h> |
Thomas Petazzoni | f6e916b | 2012-11-20 23:00:52 +0100 | [diff] [blame] | 17 | |
Thomas Petazzoni | f6e916b | 2012-11-20 23:00:52 +0100 | [diff] [blame] | 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 |
Joe Perches | 33def84 | 2020-10-21 19:36:07 -0700 | [diff] [blame] | 25 | irqchip_of_match_end __used __section("__irqchip_of_table_end"); |
Thomas Petazzoni | f6e916b | 2012-11-20 23:00:52 +0100 | [diff] [blame] | 26 | |
Rob Herring | 735e0da | 2014-03-24 16:06:42 -0500 | [diff] [blame] | 27 | extern struct of_device_id __irqchip_of_table[]; |
Thomas Petazzoni | f6e916b | 2012-11-20 23:00:52 +0100 | [diff] [blame] | 28 | |
| 29 | void __init irqchip_init(void) |
| 30 | { |
Rob Herring | 735e0da | 2014-03-24 16:06:42 -0500 | [diff] [blame] | 31 | of_irq_init(__irqchip_of_table); |
Marc Zyngier | 46e589a | 2015-09-28 15:49:13 +0100 | [diff] [blame] | 32 | acpi_probe_device_table(irqchip); |
Thomas Petazzoni | f6e916b | 2012-11-20 23:00:52 +0100 | [diff] [blame] | 33 | } |
Saravana Kannan | f8410e6 | 2020-07-17 17:06:34 -0700 | [diff] [blame] | 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 | */ |
Marc Zyngier | 7828a3e | 2020-08-06 10:57:45 +0100 | [diff] [blame] | 55 | if (par_np && !irq_find_matching_host(par_np, DOMAIN_BUS_ANY)) |
Saravana Kannan | f8410e6 | 2020-07-17 17:06:34 -0700 | [diff] [blame] | 56 | return -EPROBE_DEFER; |
| 57 | |
| 58 | return irq_init_cb(np, par_np); |
| 59 | } |
| 60 | EXPORT_SYMBOL_GPL(platform_irqchip_probe); |