Ejemplo n.º 1
0
void request_event_sources_irqs(struct device_node *np,
				irq_handler_t handler,
				const char *name)
{
	int i, index, count = 0;
	struct of_phandle_args oirq;
	unsigned int virqs[16];

	/* First try to do a proper OF tree parsing */
	for (index = 0; of_irq_parse_one(np, index, &oirq) == 0;
	     index++) {
		if (count > 15)
			break;
		virqs[count] = irq_create_of_mapping(&oirq);
		if (virqs[count] == NO_IRQ) {
			pr_err("event-sources: Unable to allocate "
			       "interrupt number for %s\n",
			       np->full_name);
			WARN_ON(1);
		} else {
			count++;
		}
	}

	/* Now request them */
	for (i = 0; i < count; i++) {
		if (request_irq(virqs[i], handler, 0, name, NULL)) {
			pr_err("event-sources: Unable to request interrupt "
			       "%d for %s\n", virqs[i], np->full_name);
			WARN_ON(1);
			return;
		}
	}
}
/**
 * irq_of_parse_and_map - Parse and map an interrupt into linux virq space
 * @dev: Device node of the device whose interrupt is to be mapped
 * @index: Index of the interrupt to map
 *
 * This function is a wrapper that chains of_irq_parse_one() and
 * irq_create_of_mapping() to make things easier to callers
 */
unsigned int irq_of_parse_and_map(struct device_node *dev, int index)
{
	struct of_phandle_args oirq;

	if (of_irq_parse_one(dev, index, &oirq))
		return 0;

	return irq_create_of_mapping(&oirq);
}
/**
 * of_irq_count - Count the number of IRQs a node uses
 * @dev: pointer to device tree node
 */
int of_irq_count(struct device_node *dev)
{
	struct of_phandle_args irq;
	int nr = 0;

	while (of_irq_parse_one(dev, nr, &irq) == 0)
		nr++;

	return nr;
}
Ejemplo n.º 4
0
Archivo: irq.c Proyecto: raoy1990/linux
/**
 * of_irq_get - Decode a node's IRQ and return it as a Linux irq number
 * @dev: pointer to device tree node
 * @index: zero-based index of the irq
 *
 * Returns Linux irq number on success, or -EPROBE_DEFER if the irq domain
 * is not yet created.
 *
 */
int of_irq_get(struct device_node *dev, int index)
{
	int rc;
	struct of_phandle_args oirq;
	struct irq_domain *domain;

	rc = of_irq_parse_one(dev, index, &oirq);
	if (rc)
		return rc;

	domain = irq_find_host(oirq.np);
	if (!domain)
		return -EPROBE_DEFER;

	return irq_create_of_mapping(&oirq);
}
Ejemplo n.º 5
0
static int mpic_msi_reserve_u3_hwirqs(struct mpic *mpic)
{
	irq_hw_number_t hwirq;
	const struct irq_domain_ops *ops = mpic->irqhost->ops;
	struct device_node *np;
	int flags, index, i;
	struct of_phandle_args oirq;

	pr_debug("mpic: found U3, guessing msi allocator setup\n");

	/* Reserve source numbers we know are reserved in the HW.
	 *
	 * This is a bit of a mix of U3 and U4 reserves but that's going
	 * to work fine, we have plenty enugh numbers left so let's just
	 * mark anything we don't like reserved.
	 */
	for (i = 0;   i < 8;   i++)
		msi_bitmap_reserve_hwirq(&mpic->msi_bitmap, i);

	for (i = 42;  i < 46;  i++)
		msi_bitmap_reserve_hwirq(&mpic->msi_bitmap, i);

	for (i = 100; i < 105; i++)
		msi_bitmap_reserve_hwirq(&mpic->msi_bitmap, i);

	for (i = 124; i < mpic->num_sources; i++)
		msi_bitmap_reserve_hwirq(&mpic->msi_bitmap, i);


	np = NULL;
	while ((np = of_find_all_nodes(np))) {
		pr_debug("mpic: mapping hwirqs for %s\n", np->full_name);

		index = 0;
		while (of_irq_parse_one(np, index++, &oirq) == 0) {
			ops->xlate(mpic->irqhost, NULL, oirq.args,
						oirq.args_count, &hwirq, &flags);
			msi_bitmap_reserve_hwirq(&mpic->msi_bitmap, hwirq);
		}
	}

	return 0;
}
Ejemplo n.º 6
0
void request_event_sources_irqs(struct device_node *np,
				irq_handler_t handler,
				const char *name)
{
	int i, index, count = 0;
	struct of_phandle_args oirq;
	const u32 *opicprop;
	unsigned int opicplen;
	unsigned int virqs[16];

	/* Check for obsolete "open-pic-interrupt" property. If present, then
	 * map those interrupts using the default interrupt host and default
	 * trigger
	 */
	opicprop = of_get_property(np, "open-pic-interrupt", &opicplen);
	if (opicprop) {
		opicplen /= sizeof(u32);
		for (i = 0; i < opicplen; i++) {
			if (count > 15)
				break;
			virqs[count] = irq_create_mapping(NULL, *(opicprop++));
			if (virqs[count] == NO_IRQ) {
				pr_err("event-sources: Unable to allocate "
				       "interrupt number for %s\n",
				       np->full_name);
				WARN_ON(1);
			}
			else
				count++;

		}
	}
	/* Else use normal interrupt tree parsing */
	else {
		/* First try to do a proper OF tree parsing */
		for (index = 0; of_irq_parse_one(np, index, &oirq) == 0;
		     index++) {
			if (count > 15)
				break;
			virqs[count] = irq_create_of_mapping(&oirq);
			if (virqs[count] == NO_IRQ) {
				pr_err("event-sources: Unable to allocate "
				       "interrupt number for %s\n",
				       np->full_name);
				WARN_ON(1);
			}
			else
				count++;
		}
	}

	/* Now request them */
	for (i = 0; i < count; i++) {
		if (request_irq(virqs[i], handler, 0, name, NULL)) {
			pr_err("event-sources: Unable to request interrupt "
			       "%d for %s\n", virqs[i], np->full_name);
			WARN_ON(1);
			return;
		}
	}
}
Ejemplo n.º 7
0
/**
 * of_irq_parse_pci - Resolve the interrupt for a PCI device
 * @pdev:       the device whose interrupt is to be resolved
 * @out_irq:    structure of_irq filled by this function
 *
 * This function resolves the PCI interrupt for a given PCI device. If a
 * device-node exists for a given pci_dev, it will use normal OF tree
 * walking. If not, it will implement standard swizzling and walk up the
 * PCI tree until an device-node is found, at which point it will finish
 * resolving using the OF tree walking.
 */
int of_irq_parse_pci(const struct pci_dev *pdev, struct of_phandle_args *out_irq)
{
	struct device_node *dn, *ppnode;
	struct pci_dev *ppdev;
	u32 lspec;
	__be32 lspec_be;
	__be32 laddr[3];
	u8 pin;
	int rc;

	/* Check if we have a device node, if yes, fallback to standard
	 * device tree parsing
	 */
	dn = pci_device_to_OF_node(pdev);
	if (dn) {
		rc = of_irq_parse_one(dn, 0, out_irq);
		if (!rc)
			return rc;
	}

	/* Ok, we don't, time to have fun. Let's start by building up an
	 * interrupt spec.  we assume #interrupt-cells is 1, which is standard
	 * for PCI. If you do different, then don't use that routine.
	 */
	rc = pci_read_config_byte(pdev, PCI_INTERRUPT_PIN, &pin);
	if (rc != 0)
		return rc;
	/* No pin, exit */
	if (pin == 0)
		return -ENODEV;

	/* Now we walk up the PCI tree */
	lspec = pin;
	for (;;) {
		/* Get the pci_dev of our parent */
		ppdev = pdev->bus->self;

		/* Ouch, it's a host bridge... */
		if (ppdev == NULL) {
			ppnode = pci_bus_to_OF_node(pdev->bus);

			/* No node for host bridge ? give up */
			if (ppnode == NULL)
				return -EINVAL;
		} else {
			/* We found a P2P bridge, check if it has a node */
			ppnode = pci_device_to_OF_node(ppdev);
		}

		/* Ok, we have found a parent with a device-node, hand over to
		 * the OF parsing code.
		 * We build a unit address from the linux device to be used for
		 * resolution. Note that we use the linux bus number which may
		 * not match your firmware bus numbering.
		 * Fortunately, in most cases, interrupt-map-mask doesn't
		 * include the bus number as part of the matching.
		 * You should still be careful about that though if you intend
		 * to rely on this function (you ship  a firmware that doesn't
		 * create device nodes for all PCI devices).
		 */
		if (ppnode)
			break;

		/* We can only get here if we hit a P2P bridge with no node,
		 * let's do standard swizzling and try again
		 */
		lspec = pci_swizzle_interrupt_pin(pdev, lspec);
		pdev = ppdev;
	}

	out_irq->np = ppnode;
	out_irq->args_count = 1;
	out_irq->args[0] = lspec;
	lspec_be = cpu_to_be32(lspec);
	laddr[0] = cpu_to_be32((pdev->bus->number << 16) | (pdev->devfn << 8));
	laddr[1] = laddr[2] = cpu_to_be32(0);
	return of_irq_parse_raw(laddr, out_irq);
}
Ejemplo n.º 8
0
static void __init of_selftest_parse_interrupts_extended(void)
{
	struct device_node *np;
	struct of_phandle_args args;
	int i, rc;

	np = of_find_node_by_path("/testcase-data/interrupts/interrupts-extended0");
	if (!np) {
		pr_err("missing testcase data\n");
		return;
	}

	for (i = 0; i < 7; i++) {
		bool passed = true;
		rc = of_irq_parse_one(np, i, &args);

		/* Test the values from tests-phandle.dtsi */
		switch (i) {
		case 0:
			passed &= !rc;
			passed &= (args.args_count == 1);
			passed &= (args.args[0] == 1);
			break;
		case 1:
			passed &= !rc;
			passed &= (args.args_count == 3);
			passed &= (args.args[0] == 2);
			passed &= (args.args[1] == 3);
			passed &= (args.args[2] == 4);
			break;
		case 2:
			passed &= !rc;
			passed &= (args.args_count == 2);
			passed &= (args.args[0] == 5);
			passed &= (args.args[1] == 6);
			break;
		case 3:
			passed &= !rc;
			passed &= (args.args_count == 1);
			passed &= (args.args[0] == 9);
			break;
		case 4:
			passed &= !rc;
			passed &= (args.args_count == 3);
			passed &= (args.args[0] == 10);
			passed &= (args.args[1] == 11);
			passed &= (args.args[2] == 12);
			break;
		case 5:
			passed &= !rc;
			passed &= (args.args_count == 2);
			passed &= (args.args[0] == 13);
			passed &= (args.args[1] == 14);
			break;
		case 6:
			passed &= !rc;
			passed &= (args.args_count == 1);
			passed &= (args.args[0] == 15);
			break;
		default:
			passed = false;
		}

		selftest(passed, "index %i - data error on node %s rc=%i\n",
			 i, args.np->full_name, rc);
	}
	of_node_put(np);
}
Ejemplo n.º 9
0
static int __init hidma_mgmt_of_populate_channels(struct device_node *np)
{
	struct platform_device *pdev_parent = of_find_device_by_node(np);
	struct platform_device_info pdevinfo;
	struct of_phandle_args out_irq;
	struct device_node *child;
	struct resource *res;
	const __be32 *cell;
	int ret = 0, size, i, num;
	u64 addr, addr_size;

	for_each_available_child_of_node(np, child) {
		struct resource *res_iter;
		struct platform_device *new_pdev;

		cell = of_get_property(child, "reg", &size);
		if (!cell) {
			ret = -EINVAL;
			goto out;
		}

		size /= sizeof(*cell);
		num = size /
			(of_n_addr_cells(child) + of_n_size_cells(child)) + 1;

		/* allocate a resource array */
		res = kcalloc(num, sizeof(*res), GFP_KERNEL);
		if (!res) {
			ret = -ENOMEM;
			goto out;
		}

		/* read each reg value */
		i = 0;
		res_iter = res;
		while (i < size) {
			addr = of_read_number(&cell[i],
					      of_n_addr_cells(child));
			i += of_n_addr_cells(child);

			addr_size = of_read_number(&cell[i],
						   of_n_size_cells(child));
			i += of_n_size_cells(child);

			res_iter->start = addr;
			res_iter->end = res_iter->start + addr_size - 1;
			res_iter->flags = IORESOURCE_MEM;
			res_iter++;
		}

		ret = of_irq_parse_one(child, 0, &out_irq);
		if (ret)
			goto out;

		res_iter->start = irq_create_of_mapping(&out_irq);
		res_iter->name = "hidma event irq";
		res_iter->flags = IORESOURCE_IRQ;

		memset(&pdevinfo, 0, sizeof(pdevinfo));
		pdevinfo.fwnode = &child->fwnode;
		pdevinfo.parent = pdev_parent ? &pdev_parent->dev : NULL;
		pdevinfo.name = child->name;
		pdevinfo.id = object_counter++;
		pdevinfo.res = res;
		pdevinfo.num_res = num;
		pdevinfo.data = NULL;
		pdevinfo.size_data = 0;
		pdevinfo.dma_mask = DMA_BIT_MASK(64);
		new_pdev = platform_device_register_full(&pdevinfo);
		if (IS_ERR(new_pdev)) {
			ret = PTR_ERR(new_pdev);
			goto out;
		}
		of_node_get(child);
		new_pdev->dev.of_node = child;
		of_dma_configure(&new_pdev->dev, child);
		/*
		 * It is assumed that calling of_msi_configure is safe on
		 * platforms with or without MSI support.
		 */
		of_msi_configure(&new_pdev->dev, child);
		of_node_put(child);
		kfree(res);
		res = NULL;
	}
out:
	kfree(res);

	return ret;
}