1f6e916b8SThomas Petazzoni /* 2f6e916b8SThomas Petazzoni * Copyright (C) 2012 Thomas Petazzoni 3f6e916b8SThomas Petazzoni * 4f6e916b8SThomas Petazzoni * Thomas Petazzoni <thomas.petazzoni@free-electrons.com> 5f6e916b8SThomas Petazzoni * 6f6e916b8SThomas Petazzoni * This file is licensed under the terms of the GNU General Public 7f6e916b8SThomas Petazzoni * License version 2. This program is licensed "as is" without any 8f6e916b8SThomas Petazzoni * warranty of any kind, whether express or implied. 9f6e916b8SThomas Petazzoni */ 10f6e916b8SThomas Petazzoni 1146e589a3SMarc Zyngier #include <linux/acpi.h> 12f6e916b8SThomas Petazzoni #include <linux/init.h> 13*ee076750SRob Herring #include <linux/of.h> 14f6e916b8SThomas Petazzoni #include <linux/of_irq.h> 15559ba4b1SStephen Boyd #include <linux/irqchip.h> 16f8410e62SSaravana Kannan #include <linux/platform_device.h> 17f6e916b8SThomas Petazzoni 18f6e916b8SThomas Petazzoni /* 19f6e916b8SThomas Petazzoni * This special of_device_id is the sentinel at the end of the 20f6e916b8SThomas Petazzoni * of_device_id[] array of all irqchips. It is automatically placed at 21f6e916b8SThomas Petazzoni * the end of the array by the linker, thanks to being part of a 22f6e916b8SThomas Petazzoni * special section. 23f6e916b8SThomas Petazzoni */ 24f6e916b8SThomas Petazzoni static const struct of_device_id 2533def849SJoe Perches irqchip_of_match_end __used __section("__irqchip_of_table_end"); 26f6e916b8SThomas Petazzoni 27735e0da7SRob Herring extern struct of_device_id __irqchip_of_table[]; 28f6e916b8SThomas Petazzoni irqchip_init(void)29f6e916b8SThomas Petazzonivoid __init irqchip_init(void) 30f6e916b8SThomas Petazzoni { 31735e0da7SRob Herring of_irq_init(__irqchip_of_table); 3246e589a3SMarc Zyngier acpi_probe_device_table(irqchip); 33f6e916b8SThomas Petazzoni } 34f8410e62SSaravana Kannan platform_irqchip_probe(struct platform_device * pdev)35f8410e62SSaravana Kannanint platform_irqchip_probe(struct platform_device *pdev) 36f8410e62SSaravana Kannan { 37f8410e62SSaravana Kannan struct device_node *np = pdev->dev.of_node; 38f8410e62SSaravana Kannan struct device_node *par_np = of_irq_find_parent(np); 39f8410e62SSaravana Kannan of_irq_init_cb_t irq_init_cb = of_device_get_match_data(&pdev->dev); 40f8410e62SSaravana Kannan 416caa5a2bSMiaoqian Lin if (!irq_init_cb) { 426caa5a2bSMiaoqian Lin of_node_put(par_np); 43f8410e62SSaravana Kannan return -EINVAL; 446caa5a2bSMiaoqian Lin } 45f8410e62SSaravana Kannan 46f8410e62SSaravana Kannan if (par_np == np) 47f8410e62SSaravana Kannan par_np = NULL; 48f8410e62SSaravana Kannan 49f8410e62SSaravana Kannan /* 50f8410e62SSaravana Kannan * If there's a parent interrupt controller and none of the parent irq 51f8410e62SSaravana Kannan * domains have been registered, that means the parent interrupt 52f8410e62SSaravana Kannan * controller has not been initialized yet. it's not time for this 53f8410e62SSaravana Kannan * interrupt controller to initialize. So, defer probe of this 54f8410e62SSaravana Kannan * interrupt controller. The actual initialization callback of this 55f8410e62SSaravana Kannan * interrupt controller can check for specific domains as necessary. 56f8410e62SSaravana Kannan */ 576caa5a2bSMiaoqian Lin if (par_np && !irq_find_matching_host(par_np, DOMAIN_BUS_ANY)) { 586caa5a2bSMiaoqian Lin of_node_put(par_np); 59f8410e62SSaravana Kannan return -EPROBE_DEFER; 606caa5a2bSMiaoqian Lin } 61f8410e62SSaravana Kannan 62f8410e62SSaravana Kannan return irq_init_cb(np, par_np); 63f8410e62SSaravana Kannan } 64f8410e62SSaravana Kannan EXPORT_SYMBOL_GPL(platform_irqchip_probe); 65