Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 08a543ad authored by Grant Likely's avatar Grant Likely
Browse files

irq: add irq_domain translation infrastructure



This patch adds irq_domain infrastructure for translating from
hardware irq numbers to linux irqs.  This is particularly important
for architectures adding device tree support because the current
implementation (excluding PowerPC and SPARC) cannot handle
translation for more than a single interrupt controller.  irq_domain
supports device tree translation for any number of interrupt
controllers.

This patch converts x86, Microblaze, ARM and MIPS to use irq_domain
for device tree irq translation.  x86 is untested beyond compiling it,
irq_domain is enabled for MIPS and Microblaze, but the old behaviour is
preserved until the core code is modified to actually register an
irq_domain yet.  On ARM it works and is required for much of the new
ARM device tree board support.

PowerPC has /not/ been converted to use this new infrastructure.  It
is still missing some features before it can replace the virq
infrastructure already in powerpc (see documentation on
irq_domain_map/unmap for details).  Followup patches will add the
missing pieces and migrate PowerPC to use irq_domain.

SPARC has its own method of managing interrupts from the device tree
and is unaffected by this change.

Acked-by: default avatarRalf Baechle <ralf@linux-mips.org>
Signed-off-by: default avatarGrant Likely <grant.likely@secretlab.ca>
parent 5fd1a2ed
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -1682,6 +1682,7 @@ config USE_OF
	bool "Flattened Device Tree support"
	select OF
	select OF_EARLY_FLATTREE
	select IRQ_DOMAIN
	help
	  Include support for flattened device tree machine descriptions.

+0 −5
Original line number Diff line number Diff line
@@ -16,11 +16,6 @@
#include <asm/setup.h>
#include <asm/irq.h>

static inline void irq_dispose_mapping(unsigned int virq)
{
	return;
}

extern struct machine_desc *setup_machine_fdt(unsigned int dt_phys);
extern void arm_dt_memblock_reserve(void);

+0 −14
Original line number Diff line number Diff line
@@ -132,17 +132,3 @@ struct machine_desc * __init setup_machine_fdt(unsigned int dt_phys)

	return mdesc_best;
}

/**
 * irq_create_of_mapping - Hook to resolve OF irq specifier into a Linux irq#
 *
 * Currently the mapping mechanism is trivial; simple flat hwirq numbers are
 * mapped 1:1 onto Linux irq numbers.  Cascaded irq controllers are not
 * supported.
 */
unsigned int irq_create_of_mapping(struct device_node *controller,
				   const u32 *intspec, unsigned int intsize)
{
	return intspec[0];
}
EXPORT_SYMBOL_GPL(irq_create_of_mapping);
+6 −0
Original line number Diff line number Diff line
@@ -108,14 +108,18 @@ enum {
};

struct msi_desc;
struct irq_domain;

/**
 * struct irq_data - per irq and irq chip data passed down to chip functions
 * @irq:		interrupt number
 * @hwirq:		hardware interrupt number, local to the interrupt domain
 * @node:		node index useful for balancing
 * @state_use_accessors: status information for irq chip functions.
 *			Use accessor functions to deal with it
 * @chip:		low level interrupt hardware access
 * @domain:		Interrupt translation domain; responsible for mapping
 *			between hwirq number and linux irq number.
 * @handler_data:	per-IRQ data for the irq_chip methods
 * @chip_data:		platform-specific per-chip private data for the chip
 *			methods, to allow shared chip implementations
@@ -128,9 +132,11 @@ struct msi_desc;
 */
struct irq_data {
	unsigned int		irq;
	unsigned long		hwirq;
	unsigned int		node;
	unsigned int		state_use_accessors;
	struct irq_chip		*chip;
	struct irq_domain	*domain;
	void			*handler_data;
	void			*chip_data;
	struct msi_desc		*msi_desc;
+81 −0
Original line number Diff line number Diff line
/*
 * irq_domain - IRQ translation domains
 *
 * Translation infrastructure between hw and linux irq numbers.  This is
 * helpful for interrupt controllers to implement mapping between hardware
 * irq numbers and the Linux irq number space.
 *
 * irq_domains also have a hook for translating device tree interrupt
 * representation into a hardware irq number that can be mapped back to a
 * Linux irq number without any extra platform support code.
 *
 * irq_domain is expected to be embedded in an interrupt controller's private
 * data structure.
 */
#ifndef _LINUX_IRQDOMAIN_H
#define _LINUX_IRQDOMAIN_H

#include <linux/irq.h>

#ifdef CONFIG_IRQ_DOMAIN
struct device_node;
struct irq_domain;

/**
 * struct irq_domain_ops - Methods for irq_domain objects
 * @to_irq: (optional) given a local hardware irq number, return the linux
 *          irq number.  If to_irq is not implemented, then the irq_domain
 *          will use this translation: irq = (domain->irq_base + hwirq)
 * @dt_translate: Given a device tree node and interrupt specifier, decode
 *                the hardware irq number and linux irq type value.
 */
struct irq_domain_ops {
	unsigned int (*to_irq)(struct irq_domain *d, unsigned long hwirq);

#ifdef CONFIG_OF
	int (*dt_translate)(struct irq_domain *d, struct device_node *node,
			    const u32 *intspec, unsigned int intsize,
			    unsigned long *out_hwirq, unsigned int *out_type);
#endif /* CONFIG_OF */
};

/**
 * struct irq_domain - Hardware interrupt number translation object
 * @list: Element in global irq_domain list.
 * @irq_base: Start of irq_desc range assigned to the irq_domain.  The creator
 *            of the irq_domain is responsible for allocating the array of
 *            irq_desc structures.
 * @nr_irq: Number of irqs managed by the irq domain
 * @ops: pointer to irq_domain methods
 * @priv: private data pointer for use by owner.  Not touched by irq_domain
 *        core code.
 * @of_node: (optional) Pointer to device tree nodes associated with the
 *           irq_domain.  Used when decoding device tree interrupt specifiers.
 */
struct irq_domain {
	struct list_head list;
	unsigned int irq_base;
	unsigned int nr_irq;
	const struct irq_domain_ops *ops;
	void *priv;
	struct device_node *of_node;
};

/**
 * irq_domain_to_irq() - Translate from a hardware irq to a linux irq number
 *
 * Returns the linux irq number associated with a hardware irq.  By default,
 * the mapping is irq == domain->irq_base + hwirq, but this mapping can
 * be overridden if the irq_domain implements a .to_irq() hook.
 */
static inline unsigned int irq_domain_to_irq(struct irq_domain *d,
					     unsigned long hwirq)
{
	return d->ops->to_irq ? d->ops->to_irq(d, hwirq) : d->irq_base + hwirq;
}

extern void irq_domain_add(struct irq_domain *domain);
extern void irq_domain_del(struct irq_domain *domain);
#endif /* CONFIG_IRQ_DOMAIN */

#endif /* _LINUX_IRQDOMAIN_H */
Loading