Lines Matching +full:irq +full:- +full:device

1 // SPDX-License-Identifier: GPL-2.0+
3 * Derived from arch/i386/kernel/irq.c
6 * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
8 * Copyright (C) 1996-2001 Cort Dougan
12 * This file contains the code used to make IRQ descriptions in the
13 * device tree to actual irq numbers on an interrupt controller
19 #include <linux/device.h>
31 * irq_of_parse_and_map - Parse and map an interrupt into linux virq space
32 * @dev: Device node of the device whose interrupt is to be mapped
50 * of_irq_find_parent - Given a device node, find its interrupt parent node
51 * @child: pointer to device node
65 if (of_property_read_u32(child, "interrupt-parent", &parent)) { in of_irq_find_parent()
75 } while (p && of_get_property(p, "#interrupt-cells", NULL) == NULL); in of_irq_find_parent()
82 * These interrupt controllers abuse interrupt-map for unspeakable
85 * non-sensical interrupt-map that is better left ignored.
92 "CBEA,platform-spider-pic",
93 "sti,platform-spider-pic",
94 "realtek,rtl-intc",
95 "fsl,ls1021a-extirq",
96 "fsl,ls1043a-extirq",
97 "fsl,ls1088a-extirq",
98 "renesas,rza1-irqc",
114 len--; in of_irq_parse_imap_parent()
118 pr_debug(" -> imap parent not found !\n"); in of_irq_parse_imap_parent()
122 /* Get #interrupt-cells and #address-cells of new parent */ in of_irq_parse_imap_parent()
123 if (of_property_read_u32(np, "#interrupt-cells", in of_irq_parse_imap_parent()
125 pr_debug(" -> parent lacks #interrupt-cells!\n"); in of_irq_parse_imap_parent()
129 if (of_property_read_u32(np, "#address-cells", in of_irq_parse_imap_parent()
133 pr_debug(" -> intsize=%d, addrsize=%d\n", in of_irq_parse_imap_parent()
143 pr_debug(" -> imaplen=%d\n", len); in of_irq_parse_imap_parent()
147 out_irq->np = np; in of_irq_parse_imap_parent()
149 out_irq->args[i] = be32_to_cpup(imap - intsize + i); in of_irq_parse_imap_parent()
150 out_irq->args_count = intsize; in of_irq_parse_imap_parent()
156 * of_irq_parse_raw - Low level interrupt tree parsing
157 * @addr: address specifier (start of "reg" property of the device) in be32 format
160 * This function is a low-level interrupt tree walking function. It
162 * properties, for example when resolving PCI interrupts when no device
164 * input, walks the tree looking for any interrupt-map properties, translates
174 const __be32 *tmp, dummy_imask[] = { [0 ... (MAX_PHANDLE_ARGS - 1)] = cpu_to_be32(~0) }; in of_irq_parse_raw()
176 int i, rc = -EINVAL; in of_irq_parse_raw()
182 ipar = of_node_get(out_irq->np); in of_irq_parse_raw()
184 /* First get the #interrupt-cells property of the current cursor in of_irq_parse_raw()
185 * that tells us how to interpret the passed-in intspec. If there in of_irq_parse_raw()
189 if (!of_property_read_u32(ipar, "#interrupt-cells", &intsize)) in of_irq_parse_raw()
196 pr_debug(" -> no parent found !\n"); in of_irq_parse_raw()
202 if (out_irq->args_count != intsize) in of_irq_parse_raw()
205 /* Look for this #address-cells. We have to implement the old linux in of_irq_parse_raw()
206 * trick of looking for the parent here as some device-trees rely on it in of_irq_parse_raw()
210 tmp = of_get_property(old, "#address-cells", NULL); in of_irq_parse_raw()
219 pr_debug(" -> addrsize=%d\n", addrsize); in of_irq_parse_raw()
223 rc = -EFAULT; in of_irq_parse_raw()
227 /* Precalculate the match array - this simplifies match loop */ in of_irq_parse_raw()
231 initial_match_array[addrsize + i] = cpu_to_be32(out_irq->args[i]); in of_irq_parse_raw()
239 * Now check if cursor is an interrupt-controller and in of_irq_parse_raw()
241 * interrupt-map which takes precedence except on one in of_irq_parse_raw()
243 * interrupt-map themselves for $reason. in of_irq_parse_raw()
245 bool intc = of_property_read_bool(ipar, "interrupt-controller"); in of_irq_parse_raw()
247 imap = of_get_property(ipar, "interrupt-map", &imaplen); in of_irq_parse_raw()
250 pr_debug(" -> got it !\n"); in of_irq_parse_raw()
255 * interrupt-map parsing does not work without a reg in of_irq_parse_raw()
256 * property when #address-cells != 0 in of_irq_parse_raw()
259 pr_debug(" -> no reg passed in when needed !\n"); in of_irq_parse_raw()
265 pr_debug(" -> no map, getting parent\n"); in of_irq_parse_raw()
272 imask = of_get_property(ipar, "interrupt-map-mask", NULL); in of_irq_parse_raw()
276 /* Parse interrupt-map */ in of_irq_parse_raw()
281 for (i = 0; i < (addrsize + intsize); i++, imaplen--) in of_irq_parse_raw()
284 pr_debug(" -> match=%d (imaplen=%d)\n", match, imaplen); in of_irq_parse_raw()
291 match &= of_device_is_available(out_irq->np); in of_irq_parse_raw()
295 of_node_put(out_irq->np); in of_irq_parse_raw()
296 imaplen -= imap - oldimap; in of_irq_parse_raw()
297 pr_debug(" -> imaplen=%d\n", imaplen); in of_irq_parse_raw()
303 * Successfully parsed an interrupt-map translation; copy new in of_irq_parse_raw()
308 newpar = out_irq->np; in of_irq_parse_raw()
309 intsize = out_irq->args_count; in of_irq_parse_raw()
310 addrsize = (imap - match_array) - intsize; in of_irq_parse_raw()
313 pr_debug("%pOF interrupt-map entry to self\n", ipar); in of_irq_parse_raw()
319 pr_debug(" -> new parent: %pOF\n", newpar); in of_irq_parse_raw()
324 rc = -ENOENT; /* No interrupt-map found */ in of_irq_parse_raw()
334 * of_irq_parse_one - Resolve an interrupt for a device
335 * @device: the device whose interrupt is to be resolved
341 * interrupt specifier that can be used to retrieve a Linux IRQ number.
343 int of_irq_parse_one(struct device_node *device, int index, struct of_phandle_args *out_irq) in of_irq_parse_one() argument
351 pr_debug("of_irq_parse_one: dev=%pOF, index=%d\n", device, index); in of_irq_parse_one()
355 return of_irq_parse_oldworld(device, index, out_irq); in of_irq_parse_one()
359 addr = of_get_property(device, "reg", &addr_len); in of_irq_parse_one()
361 /* Prevent out-of-bounds read in case of longer interrupt parent address size */ in of_irq_parse_one()
367 /* Try the new-style interrupts-extended first */ in of_irq_parse_one()
368 res = of_parse_phandle_with_args(device, "interrupts-extended", in of_irq_parse_one()
369 "#interrupt-cells", index, out_irq); in of_irq_parse_one()
374 p = of_irq_find_parent(device); in of_irq_parse_one()
376 return -EINVAL; in of_irq_parse_one()
379 if (of_property_read_u32(p, "#interrupt-cells", &intsize)) { in of_irq_parse_one()
380 res = -EINVAL; in of_irq_parse_one()
386 /* Copy intspec into irq structure */ in of_irq_parse_one()
387 out_irq->np = p; in of_irq_parse_one()
388 out_irq->args_count = intsize; in of_irq_parse_one()
390 res = of_property_read_u32_index(device, "interrupts", in of_irq_parse_one()
392 out_irq->args + i); in of_irq_parse_one()
397 pr_debug(" intspec=%d\n", *out_irq->args); in of_irq_parse_one()
400 /* Check if there are any interrupt-map translations to process */ in of_irq_parse_one()
409 * of_irq_to_resource - Decode a node's IRQ and return it as a resource
410 * @dev: pointer to device tree node
411 * @index: zero-based index of the irq
416 int irq = of_irq_get(dev, index); in of_irq_to_resource() local
418 if (irq < 0) in of_irq_to_resource()
419 return irq; in of_irq_to_resource()
422 * resource and the irq are valid. */ in of_irq_to_resource()
423 if (r && irq) { in of_irq_to_resource()
428 * Get optional "interrupt-names" property to add a name in of_irq_to_resource()
431 of_property_read_string_index(dev, "interrupt-names", index, in of_irq_to_resource()
434 *r = DEFINE_RES_IRQ_NAMED(irq, name ?: of_node_full_name(dev)); in of_irq_to_resource()
435 r->flags |= irq_get_trigger_type(irq); in of_irq_to_resource()
438 return irq; in of_irq_to_resource()
443 * of_irq_get - Decode a node's IRQ and return it as a Linux IRQ number
444 * @dev: pointer to device tree node
445 * @index: zero-based index of the IRQ
447 * Return: Linux IRQ number on success, or 0 on the IRQ mapping failure, or
448 * -EPROBE_DEFER if the IRQ domain is not yet created, or error code in case
463 rc = -EPROBE_DEFER; in of_irq_get()
476 * of_irq_get_byname - Decode a node's IRQ and return it as a Linux IRQ number
477 * @dev: pointer to device tree node
478 * @name: IRQ name
480 * Return: Linux IRQ number on success, or 0 on the IRQ mapping failure, or
481 * -EPROBE_DEFER if the IRQ domain is not yet created, or error code in case
489 return -EINVAL; in of_irq_get_byname()
491 index = of_property_match_string(dev, "interrupt-names", name); in of_irq_get_byname()
500 * of_irq_count - Count the number of IRQs a node uses
501 * @dev: pointer to device tree node
505 struct of_phandle_args irq; in of_irq_count() local
508 while (of_irq_parse_one(dev, nr, &irq) == 0) in of_irq_count()
515 * of_irq_to_resource_table - Fill in resource table with node's IRQ info
516 * @dev: pointer to device tree node
543 * of_irq_init - Scan and init matching interrupt controllers in DT
546 * This function scans the device tree for matching interrupt controller nodes,
560 if (!of_property_read_bool(np, "interrupt-controller") || in of_irq_init()
564 if (WARN(!match->data, "of_irq_init: no init function for %s\n", in of_irq_init()
565 match->compatible)) in of_irq_init()
570 * pointer, interrupt-parent device_node etc. in of_irq_init()
578 desc->irq_init_cb = match->data; in of_irq_init()
579 desc->dev = of_node_get(np); in of_irq_init()
581 * interrupts-extended can reference multiple parent domains. in of_irq_init()
583 * are the same distance away from the root irq controller. in of_irq_init()
585 desc->interrupt_parent = of_parse_phandle(np, "interrupts-extended", 0); in of_irq_init()
586 if (!desc->interrupt_parent) in of_irq_init()
587 desc->interrupt_parent = of_irq_find_parent(np); in of_irq_init()
588 if (desc->interrupt_parent == np) { in of_irq_init()
589 of_node_put(desc->interrupt_parent); in of_irq_init()
590 desc->interrupt_parent = NULL; in of_irq_init()
592 list_add_tail(&desc->list, &intc_desc_list); in of_irq_init()
596 * The root irq controller is the one without an interrupt-parent. in of_irq_init()
609 if (desc->interrupt_parent != parent) in of_irq_init()
612 list_del(&desc->list); in of_irq_init()
614 of_node_set_flag(desc->dev, OF_POPULATED); in of_irq_init()
617 desc->dev, in of_irq_init()
618 desc->dev, desc->interrupt_parent); in of_irq_init()
619 ret = desc->irq_init_cb(desc->dev, in of_irq_init()
620 desc->interrupt_parent); in of_irq_init()
623 __func__, desc->dev, desc->dev, in of_irq_init()
624 desc->interrupt_parent); in of_irq_init()
625 of_node_clear_flag(desc->dev, OF_POPULATED); in of_irq_init()
634 list_add_tail(&desc->list, &intc_parent_list); in of_irq_init()
644 list_del(&desc->list); in of_irq_init()
645 parent = desc->dev; in of_irq_init()
650 list_del(&desc->list); in of_irq_init()
655 list_del(&desc->list); in of_irq_init()
656 of_node_put(desc->dev); in of_irq_init()
661 static u32 __of_msi_map_id(struct device *dev, struct device_node **np, in __of_msi_map_id()
664 struct device *parent_dev; in __of_msi_map_id()
668 * Walk up the device parent links looking for one with a in __of_msi_map_id()
669 * "msi-map" property. in __of_msi_map_id()
671 for (parent_dev = dev; parent_dev; parent_dev = parent_dev->parent) in __of_msi_map_id()
672 if (!of_map_id(parent_dev->of_node, id_in, "msi-map", in __of_msi_map_id()
673 "msi-map-mask", np, &id_out)) in __of_msi_map_id()
679 * of_msi_map_id - Map a MSI ID for a device.
680 * @dev: device for which the mapping is to be done.
681 * @msi_np: device node of the expected msi controller.
682 * @id_in: unmapped MSI ID for the device.
684 * Walk up the device hierarchy looking for devices with a "msi-map"
689 u32 of_msi_map_id(struct device *dev, struct device_node *msi_np, u32 id_in) in of_msi_map_id()
695 * of_msi_map_get_device_domain - Use msi-map to find the relevant MSI domain
696 * @dev: device for which the mapping is to be done.
697 * @id: Device ID.
700 * Walk up the device hierarchy looking for devices with a "msi-map"
703 * Returns: the MSI domain for this device (or NULL on failure)
705 struct irq_domain *of_msi_map_get_device_domain(struct device *dev, u32 id, in of_msi_map_get_device_domain()
715 * of_msi_get_domain - Use msi-parent to find the relevant MSI domain
716 * @dev: device for which the domain is requested
717 * @np: device node for @dev
720 * Parse the msi-parent property and returns the corresponding MSI domain.
722 * Returns: the MSI domain for this device (or NULL on failure).
724 struct irq_domain *of_msi_get_domain(struct device *dev, in of_msi_get_domain()
732 of_for_each_phandle(&it, err, np, "msi-parent", "#msi-cells", 0) { in of_msi_get_domain()
743 * of_msi_configure - Set the msi_domain field of a device
744 * @dev: device structure to associate with an MSI irq domain
745 * @np: device node for that device
747 void of_msi_configure(struct device *dev, const struct device_node *np) in of_msi_configure()