xref: /linux-6.15/include/linux/irq.h (revision e54b1b5e)
1b2441318SGreg Kroah-Hartman /* SPDX-License-Identifier: GPL-2.0 */
206fcb0c6SIngo Molnar #ifndef _LINUX_IRQ_H
306fcb0c6SIngo Molnar #define _LINUX_IRQ_H
41da177e4SLinus Torvalds 
51da177e4SLinus Torvalds /*
61da177e4SLinus Torvalds  * Please do not include this file in generic code.  There is currently
71da177e4SLinus Torvalds  * no requirement for any architecture to implement anything held
81da177e4SLinus Torvalds  * within this file.
91da177e4SLinus Torvalds  *
101da177e4SLinus Torvalds  * Thanks. --rmk
111da177e4SLinus Torvalds  */
121da177e4SLinus Torvalds 
131da177e4SLinus Torvalds #include <linux/cache.h>
141da177e4SLinus Torvalds #include <linux/spinlock.h>
151da177e4SLinus Torvalds #include <linux/cpumask.h>
1675ffc007SThomas Gleixner #include <linux/irqhandler.h>
17908dcecdSJan Beulich #include <linux/irqreturn.h>
18dd3a1db9SThomas Gleixner #include <linux/irqnr.h>
19503e5763SRalf Baechle #include <linux/topology.h>
20332fd7c4SKevin Cernekee #include <linux/io.h>
21707188f5SBartosz Golaszewski #include <linux/slab.h>
221da177e4SLinus Torvalds 
231da177e4SLinus Torvalds #include <asm/irq.h>
241da177e4SLinus Torvalds #include <asm/ptrace.h>
257d12e780SDavid Howells #include <asm/irq_regs.h>
261da177e4SLinus Torvalds 
27ab7798ffSThomas Gleixner struct seq_file;
28ec53cf23SPaul Gortmaker struct module;
29515085efSJiang Liu struct msi_msg;
30bec04037SDou Liyang struct irq_affinity_desc;
311b7047edSMarc Zyngier enum irqchip_irq_state;
3257a58a94SDavid Howells 
331da177e4SLinus Torvalds /*
341da177e4SLinus Torvalds  * IRQ line status.
356e213616SThomas Gleixner  *
365d4d8fc9SThomas Gleixner  * Bits 0-7 are the same as the IRQF_* bits in linux/interrupt.h
376e213616SThomas Gleixner  *
385d4d8fc9SThomas Gleixner  * IRQ_TYPE_NONE		- default, unspecified type
395d4d8fc9SThomas Gleixner  * IRQ_TYPE_EDGE_RISING		- rising edge triggered
405d4d8fc9SThomas Gleixner  * IRQ_TYPE_EDGE_FALLING	- falling edge triggered
415d4d8fc9SThomas Gleixner  * IRQ_TYPE_EDGE_BOTH		- rising and falling edge triggered
425d4d8fc9SThomas Gleixner  * IRQ_TYPE_LEVEL_HIGH		- high level triggered
435d4d8fc9SThomas Gleixner  * IRQ_TYPE_LEVEL_LOW		- low level triggered
445d4d8fc9SThomas Gleixner  * IRQ_TYPE_LEVEL_MASK		- Mask to filter out the level bits
455d4d8fc9SThomas Gleixner  * IRQ_TYPE_SENSE_MASK		- Mask for all the above bits
463fca40c7SBenjamin Herrenschmidt  * IRQ_TYPE_DEFAULT		- For use by some PICs to ask irq_set_type
473fca40c7SBenjamin Herrenschmidt  *				  to setup the HW to a sane default (used
483fca40c7SBenjamin Herrenschmidt  *                                by irqdomain map() callbacks to synchronize
493fca40c7SBenjamin Herrenschmidt  *                                the HW state and SW flags for a newly
503fca40c7SBenjamin Herrenschmidt  *                                allocated descriptor).
513fca40c7SBenjamin Herrenschmidt  *
525d4d8fc9SThomas Gleixner  * IRQ_TYPE_PROBE		- Special flag for probing in progress
535d4d8fc9SThomas Gleixner  *
545d4d8fc9SThomas Gleixner  * Bits which can be modified via irq_set/clear/modify_status_flags()
555d4d8fc9SThomas Gleixner  * IRQ_LEVEL			- Interrupt is level type. Will be also
565d4d8fc9SThomas Gleixner  *				  updated in the code when the above trigger
570911f124SGeert Uytterhoeven  *				  bits are modified via irq_set_irq_type()
585d4d8fc9SThomas Gleixner  * IRQ_PER_CPU			- Mark an interrupt PER_CPU. Will protect
595d4d8fc9SThomas Gleixner  *				  it from affinity setting
605d4d8fc9SThomas Gleixner  * IRQ_NOPROBE			- Interrupt cannot be probed by autoprobing
615d4d8fc9SThomas Gleixner  * IRQ_NOREQUEST		- Interrupt cannot be requested via
625d4d8fc9SThomas Gleixner  *				  request_irq()
637f1b1244SPaul Mundt  * IRQ_NOTHREAD			- Interrupt cannot be threaded
645d4d8fc9SThomas Gleixner  * IRQ_NOAUTOEN			- Interrupt is not automatically enabled in
655d4d8fc9SThomas Gleixner  *				  request/setup_irq()
665d4d8fc9SThomas Gleixner  * IRQ_NO_BALANCING		- Interrupt cannot be balanced (affinity set)
6792068d17SMika Westerberg  * IRQ_NESTED_THREAD		- Interrupt nests into another thread
6831d9d9b6SMarc Zyngier  * IRQ_PER_CPU_DEVID		- Dev_id is a per-cpu variable
69b39898cdSThomas Gleixner  * IRQ_IS_POLLED		- Always polled by another interrupt. Exclude
70b39898cdSThomas Gleixner  *				  it from the spurious interrupt detection
71b39898cdSThomas Gleixner  *				  mechanism and from core side polling.
72e9849777SThomas Gleixner  * IRQ_DISABLE_UNLAZY		- Disable lazy irq disable
7383cfac95SMarc Zyngier  * IRQ_HIDDEN			- Don't show up in /proc/interrupts
74c2b1063eSThomas Gleixner  * IRQ_NO_DEBUG			- Exclude from note_interrupt() debugging
751da177e4SLinus Torvalds  */
765d4d8fc9SThomas Gleixner enum {
775d4d8fc9SThomas Gleixner 	IRQ_TYPE_NONE		= 0x00000000,
785d4d8fc9SThomas Gleixner 	IRQ_TYPE_EDGE_RISING	= 0x00000001,
795d4d8fc9SThomas Gleixner 	IRQ_TYPE_EDGE_FALLING	= 0x00000002,
805d4d8fc9SThomas Gleixner 	IRQ_TYPE_EDGE_BOTH	= (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING),
815d4d8fc9SThomas Gleixner 	IRQ_TYPE_LEVEL_HIGH	= 0x00000004,
825d4d8fc9SThomas Gleixner 	IRQ_TYPE_LEVEL_LOW	= 0x00000008,
835d4d8fc9SThomas Gleixner 	IRQ_TYPE_LEVEL_MASK	= (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH),
845d4d8fc9SThomas Gleixner 	IRQ_TYPE_SENSE_MASK	= 0x0000000f,
853fca40c7SBenjamin Herrenschmidt 	IRQ_TYPE_DEFAULT	= IRQ_TYPE_SENSE_MASK,
86876dbd4cSThomas Gleixner 
875d4d8fc9SThomas Gleixner 	IRQ_TYPE_PROBE		= 0x00000010,
886e213616SThomas Gleixner 
895d4d8fc9SThomas Gleixner 	IRQ_LEVEL		= (1 <<  8),
905d4d8fc9SThomas Gleixner 	IRQ_PER_CPU		= (1 <<  9),
915d4d8fc9SThomas Gleixner 	IRQ_NOPROBE		= (1 << 10),
925d4d8fc9SThomas Gleixner 	IRQ_NOREQUEST		= (1 << 11),
935d4d8fc9SThomas Gleixner 	IRQ_NOAUTOEN		= (1 << 12),
945d4d8fc9SThomas Gleixner 	IRQ_NO_BALANCING	= (1 << 13),
955d4d8fc9SThomas Gleixner 	IRQ_NESTED_THREAD	= (1 << 15),
967f1b1244SPaul Mundt 	IRQ_NOTHREAD		= (1 << 16),
9731d9d9b6SMarc Zyngier 	IRQ_PER_CPU_DEVID	= (1 << 17),
98b39898cdSThomas Gleixner 	IRQ_IS_POLLED		= (1 << 18),
99e9849777SThomas Gleixner 	IRQ_DISABLE_UNLAZY	= (1 << 19),
10083cfac95SMarc Zyngier 	IRQ_HIDDEN		= (1 << 20),
101c2b1063eSThomas Gleixner 	IRQ_NO_DEBUG		= (1 << 21),
1025d4d8fc9SThomas Gleixner };
103950f4427SThomas Gleixner 
10444247184SThomas Gleixner #define IRQF_MODIFY_MASK	\
10544247184SThomas Gleixner 	(IRQ_TYPE_SENSE_MASK | IRQ_NOPROBE | IRQ_NOREQUEST | \
106f94a1824SThomas Gleixner 	 IRQ_NOAUTOEN | IRQ_LEVEL | IRQ_NO_BALANCING | \
107b39898cdSThomas Gleixner 	 IRQ_PER_CPU | IRQ_NESTED_THREAD | IRQ_NOTHREAD | IRQ_PER_CPU_DEVID | \
10883cfac95SMarc Zyngier 	 IRQ_IS_POLLED | IRQ_DISABLE_UNLAZY | IRQ_HIDDEN)
10944247184SThomas Gleixner 
110950f4427SThomas Gleixner #define IRQ_NO_BALANCING_MASK	(IRQ_PER_CPU | IRQ_NO_BALANCING)
1111da177e4SLinus Torvalds 
1123b8249e7SThomas Gleixner /*
1133b8249e7SThomas Gleixner  * Return value for chip->irq_set_affinity()
1143b8249e7SThomas Gleixner  *
1159df872faSJiang Liu  * IRQ_SET_MASK_OK	- OK, core updates irq_common_data.affinity
11663752ad1SAndy Shevchenko  * IRQ_SET_MASK_NOCOPY	- OK, chip did update irq_common_data.affinity
1172cb62547SJiang Liu  * IRQ_SET_MASK_OK_DONE	- Same as IRQ_SET_MASK_OK for core. Special code to
1182cb62547SJiang Liu  *			  support stacked irqchips, which indicates skipping
119a359f757SIngo Molnar  *			  all descendant irqchips.
1203b8249e7SThomas Gleixner  */
1213b8249e7SThomas Gleixner enum {
1223b8249e7SThomas Gleixner 	IRQ_SET_MASK_OK = 0,
1233b8249e7SThomas Gleixner 	IRQ_SET_MASK_OK_NOCOPY,
1242cb62547SJiang Liu 	IRQ_SET_MASK_OK_DONE,
1253b8249e7SThomas Gleixner };
1263b8249e7SThomas Gleixner 
1275b912c10SEric W. Biederman struct msi_desc;
12808a543adSGrant Likely struct irq_domain;
1296a6de9efSThomas Gleixner 
1308fee5c36SIngo Molnar /**
1310d0b4c86SJiang Liu  * struct irq_common_data - per irq data shared by all irqchips
1320d0b4c86SJiang Liu  * @state_use_accessors: status information for irq chip functions.
1330d0b4c86SJiang Liu  *			Use accessor functions to deal with it
134449e9caeSJiang Liu  * @node:		node index useful for balancing
135af7080e0SJiang Liu  * @handler_data:	per-IRQ data for the irq_chip methods
136955bfe59SQais Yousef  * @affinity:		IRQ affinity on SMP. If this is an IPI
137955bfe59SQais Yousef  *			related irq, then this is the mask of the
138955bfe59SQais Yousef  *			CPUs to which an IPI can be sent.
1390d3f5425SThomas Gleixner  * @effective_affinity:	The effective IRQ affinity on SMP as some irq
1400d3f5425SThomas Gleixner  *			chips do not allow multi CPU destinations.
1410d3f5425SThomas Gleixner  *			A subset of @affinity.
142b237721cSJiang Liu  * @msi_desc:		MSI descriptor
143f256c9a0SQais Yousef  * @ipi_offset:		Offset of first IPI target cpu in @affinity. Optional.
1440d0b4c86SJiang Liu  */
1450d0b4c86SJiang Liu struct irq_common_data {
146b354286eSBoqun Feng 	unsigned int		__private state_use_accessors;
147449e9caeSJiang Liu #ifdef CONFIG_NUMA
148449e9caeSJiang Liu 	unsigned int		node;
149449e9caeSJiang Liu #endif
150af7080e0SJiang Liu 	void			*handler_data;
151b237721cSJiang Liu 	struct msi_desc		*msi_desc;
152aa081358SSamuel Holland #ifdef CONFIG_SMP
1539df872faSJiang Liu 	cpumask_var_t		affinity;
154aa081358SSamuel Holland #endif
1550d3f5425SThomas Gleixner #ifdef CONFIG_GENERIC_IRQ_EFFECTIVE_AFF_MASK
1560d3f5425SThomas Gleixner 	cpumask_var_t		effective_affinity;
1570d3f5425SThomas Gleixner #endif
158f256c9a0SQais Yousef #ifdef CONFIG_GENERIC_IRQ_IPI
159f256c9a0SQais Yousef 	unsigned int		ipi_offset;
160f256c9a0SQais Yousef #endif
1610d0b4c86SJiang Liu };
1620d0b4c86SJiang Liu 
1630d0b4c86SJiang Liu /**
1640d0b4c86SJiang Liu  * struct irq_data - per irq chip data passed down to chip functions
165966dc736SThomas Gleixner  * @mask:		precomputed bitmask for accessing the chip registers
166ff7dcd44SThomas Gleixner  * @irq:		interrupt number
16708a543adSGrant Likely  * @hwirq:		hardware interrupt number, local to the interrupt domain
1680d0b4c86SJiang Liu  * @common:		point to data shared by all irqchips
169ff7dcd44SThomas Gleixner  * @chip:		low level interrupt hardware access
17008a543adSGrant Likely  * @domain:		Interrupt translation domain; responsible for mapping
17108a543adSGrant Likely  *			between hwirq number and linux irq number.
172f8264e34SJiang Liu  * @parent_data:	pointer to parent struct irq_data to support hierarchy
173f8264e34SJiang Liu  *			irq_domain
174ff7dcd44SThomas Gleixner  * @chip_data:		platform-specific per-chip private data for the chip
175ff7dcd44SThomas Gleixner  *			methods, to allow shared chip implementations
176ff7dcd44SThomas Gleixner  */
177ff7dcd44SThomas Gleixner struct irq_data {
178966dc736SThomas Gleixner 	u32			mask;
179ff7dcd44SThomas Gleixner 	unsigned int		irq;
180d22083a5SDawei Li 	irq_hw_number_t		hwirq;
1810d0b4c86SJiang Liu 	struct irq_common_data	*common;
182ff7dcd44SThomas Gleixner 	struct irq_chip		*chip;
18308a543adSGrant Likely 	struct irq_domain	*domain;
184f8264e34SJiang Liu #ifdef	CONFIG_IRQ_DOMAIN_HIERARCHY
185f8264e34SJiang Liu 	struct irq_data		*parent_data;
186f8264e34SJiang Liu #endif
187ff7dcd44SThomas Gleixner 	void			*chip_data;
188ff7dcd44SThomas Gleixner };
189ff7dcd44SThomas Gleixner 
190f230b6d5SThomas Gleixner /*
1910d0b4c86SJiang Liu  * Bit masks for irq_common_data.state_use_accessors
192f230b6d5SThomas Gleixner  *
193876dbd4cSThomas Gleixner  * IRQD_TRIGGER_MASK		- Mask for the trigger type bits
194f230b6d5SThomas Gleixner  * IRQD_SETAFFINITY_PENDING	- Affinity setting is pending
19508d85f3eSMarc Zyngier  * IRQD_ACTIVATED		- Interrupt has already been activated
196a005677bSThomas Gleixner  * IRQD_NO_BALANCING		- Balancing disabled for this IRQ
197a005677bSThomas Gleixner  * IRQD_PER_CPU			- Interrupt is per cpu
1982bdd1055SThomas Gleixner  * IRQD_AFFINITY_SET		- Interrupt affinity was set
199876dbd4cSThomas Gleixner  * IRQD_LEVEL			- Interrupt is level triggered
2007f94226fSThomas Gleixner  * IRQD_WAKEUP_STATE		- Interrupt is configured for wakeup
2017f94226fSThomas Gleixner  *				  from suspend
20232f4125eSThomas Gleixner  * IRQD_IRQ_DISABLED		- Disabled state of the interrupt
20332f4125eSThomas Gleixner  * IRQD_IRQ_MASKED		- Masked state of the interrupt
20432f4125eSThomas Gleixner  * IRQD_IRQ_INPROGRESS		- In progress state of the interrupt
205b76f1674SThomas Gleixner  * IRQD_WAKEUP_ARMED		- Wakeup mode armed
206fc569712SThomas Gleixner  * IRQD_FORWARDED_TO_VCPU	- The interrupt is forwarded to a VCPU
2079c255583SThomas Gleixner  * IRQD_AFFINITY_MANAGED	- Affinity is auto-managed by the kernel
2081bb04016SThomas Gleixner  * IRQD_IRQ_STARTED		- Startup state of the interrupt
20954fdf6a0SThomas Gleixner  * IRQD_MANAGED_SHUTDOWN	- Interrupt was shutdown due to empty affinity
21054fdf6a0SThomas Gleixner  *				  mask. Applies only to affinity managed irqs.
211d52dd441SThomas Gleixner  * IRQD_SINGLE_TARGET		- IRQ allows only a single affinity target
2124f8413a3SMarc Zyngier  * IRQD_DEFAULT_TRIGGER_SET	- Expected trigger already been set
21369790ba9SThomas Gleixner  * IRQD_CAN_RESERVE		- Can use reservation mode
214c16816acSThomas Gleixner  * IRQD_HANDLE_ENFORCE_IRQCTX	- Enforce that handle_irq_*() is only invoked
215c16816acSThomas Gleixner  *				  from actual interrupt context.
216f0c7bacaSThomas Gleixner  * IRQD_AFFINITY_ON_ACTIVATE	- Affinity is set on activation. Don't call
217f0c7bacaSThomas Gleixner  *				  irq_chip::irq_set_affinity() when deactivated.
21890428a8eSMaulik Shah  * IRQD_IRQ_ENABLED_ON_SUSPEND	- Interrupt is enabled on suspend by irq pm if
21990428a8eSMaulik Shah  *				  irqchip have flag IRQCHIP_ENABLE_WAKEUP_ON_SUSPEND set.
2209c15eeb5SJames Gowans  * IRQD_RESEND_WHEN_IN_PROGRESS	- Interrupt may fire when already in progress in which
2219c15eeb5SJames Gowans  *				  case it must be resent at the next available opportunity.
222f230b6d5SThomas Gleixner  */
223f230b6d5SThomas Gleixner enum {
224876dbd4cSThomas Gleixner 	IRQD_TRIGGER_MASK		= 0xf,
2250cfb4a1aSMarc Zyngier 	IRQD_SETAFFINITY_PENDING	= BIT(8),
2260cfb4a1aSMarc Zyngier 	IRQD_ACTIVATED			= BIT(9),
2270cfb4a1aSMarc Zyngier 	IRQD_NO_BALANCING		= BIT(10),
2280cfb4a1aSMarc Zyngier 	IRQD_PER_CPU			= BIT(11),
2290cfb4a1aSMarc Zyngier 	IRQD_AFFINITY_SET		= BIT(12),
2300cfb4a1aSMarc Zyngier 	IRQD_LEVEL			= BIT(13),
2310cfb4a1aSMarc Zyngier 	IRQD_WAKEUP_STATE		= BIT(14),
2320cfb4a1aSMarc Zyngier 	IRQD_IRQ_DISABLED		= BIT(16),
2330cfb4a1aSMarc Zyngier 	IRQD_IRQ_MASKED			= BIT(17),
2340cfb4a1aSMarc Zyngier 	IRQD_IRQ_INPROGRESS		= BIT(18),
2350cfb4a1aSMarc Zyngier 	IRQD_WAKEUP_ARMED		= BIT(19),
2360cfb4a1aSMarc Zyngier 	IRQD_FORWARDED_TO_VCPU		= BIT(20),
2370cfb4a1aSMarc Zyngier 	IRQD_AFFINITY_MANAGED		= BIT(21),
2380cfb4a1aSMarc Zyngier 	IRQD_IRQ_STARTED		= BIT(22),
2390cfb4a1aSMarc Zyngier 	IRQD_MANAGED_SHUTDOWN		= BIT(23),
2400cfb4a1aSMarc Zyngier 	IRQD_SINGLE_TARGET		= BIT(24),
2410cfb4a1aSMarc Zyngier 	IRQD_DEFAULT_TRIGGER_SET	= BIT(25),
2420cfb4a1aSMarc Zyngier 	IRQD_CAN_RESERVE		= BIT(26),
243b56ebe7cSKoichiro Den 	IRQD_HANDLE_ENFORCE_IRQCTX	= BIT(27),
244b56ebe7cSKoichiro Den 	IRQD_AFFINITY_ON_ACTIVATE	= BIT(28),
245b56ebe7cSKoichiro Den 	IRQD_IRQ_ENABLED_ON_SUSPEND	= BIT(29),
246b56ebe7cSKoichiro Den 	IRQD_RESEND_WHEN_IN_PROGRESS    = BIT(30),
247f230b6d5SThomas Gleixner };
248f230b6d5SThomas Gleixner 
249b354286eSBoqun Feng #define __irqd_to_state(d) ACCESS_PRIVATE((d)->common, state_use_accessors)
2500d0b4c86SJiang Liu 
irqd_is_setaffinity_pending(struct irq_data * d)251f230b6d5SThomas Gleixner static inline bool irqd_is_setaffinity_pending(struct irq_data *d)
252f230b6d5SThomas Gleixner {
2530d0b4c86SJiang Liu 	return __irqd_to_state(d) & IRQD_SETAFFINITY_PENDING;
254f230b6d5SThomas Gleixner }
255f230b6d5SThomas Gleixner 
irqd_is_per_cpu(struct irq_data * d)256a005677bSThomas Gleixner static inline bool irqd_is_per_cpu(struct irq_data *d)
257a005677bSThomas Gleixner {
2580d0b4c86SJiang Liu 	return __irqd_to_state(d) & IRQD_PER_CPU;
259a005677bSThomas Gleixner }
260a005677bSThomas Gleixner 
irqd_can_balance(struct irq_data * d)261a005677bSThomas Gleixner static inline bool irqd_can_balance(struct irq_data *d)
262a005677bSThomas Gleixner {
2630d0b4c86SJiang Liu 	return !(__irqd_to_state(d) & (IRQD_PER_CPU | IRQD_NO_BALANCING));
264a005677bSThomas Gleixner }
265a005677bSThomas Gleixner 
irqd_affinity_was_set(struct irq_data * d)2662bdd1055SThomas Gleixner static inline bool irqd_affinity_was_set(struct irq_data *d)
2672bdd1055SThomas Gleixner {
2680d0b4c86SJiang Liu 	return __irqd_to_state(d) & IRQD_AFFINITY_SET;
2692bdd1055SThomas Gleixner }
2702bdd1055SThomas Gleixner 
irqd_mark_affinity_was_set(struct irq_data * d)271ee38c04bSThomas Gleixner static inline void irqd_mark_affinity_was_set(struct irq_data *d)
272ee38c04bSThomas Gleixner {
2730d0b4c86SJiang Liu 	__irqd_to_state(d) |= IRQD_AFFINITY_SET;
274ee38c04bSThomas Gleixner }
275ee38c04bSThomas Gleixner 
irqd_trigger_type_was_set(struct irq_data * d)2764f8413a3SMarc Zyngier static inline bool irqd_trigger_type_was_set(struct irq_data *d)
2774f8413a3SMarc Zyngier {
2784f8413a3SMarc Zyngier 	return __irqd_to_state(d) & IRQD_DEFAULT_TRIGGER_SET;
2794f8413a3SMarc Zyngier }
2804f8413a3SMarc Zyngier 
irqd_get_trigger_type(struct irq_data * d)281876dbd4cSThomas Gleixner static inline u32 irqd_get_trigger_type(struct irq_data *d)
282876dbd4cSThomas Gleixner {
2830d0b4c86SJiang Liu 	return __irqd_to_state(d) & IRQD_TRIGGER_MASK;
284876dbd4cSThomas Gleixner }
285876dbd4cSThomas Gleixner 
286876dbd4cSThomas Gleixner /*
2874f8413a3SMarc Zyngier  * Must only be called inside irq_chip.irq_set_type() functions or
2884f8413a3SMarc Zyngier  * from the DT/ACPI setup code.
289876dbd4cSThomas Gleixner  */
irqd_set_trigger_type(struct irq_data * d,u32 type)290876dbd4cSThomas Gleixner static inline void irqd_set_trigger_type(struct irq_data *d, u32 type)
291876dbd4cSThomas Gleixner {
2920d0b4c86SJiang Liu 	__irqd_to_state(d) &= ~IRQD_TRIGGER_MASK;
2930d0b4c86SJiang Liu 	__irqd_to_state(d) |= type & IRQD_TRIGGER_MASK;
2944f8413a3SMarc Zyngier 	__irqd_to_state(d) |= IRQD_DEFAULT_TRIGGER_SET;
295876dbd4cSThomas Gleixner }
296876dbd4cSThomas Gleixner 
irqd_is_level_type(struct irq_data * d)297876dbd4cSThomas Gleixner static inline bool irqd_is_level_type(struct irq_data *d)
298876dbd4cSThomas Gleixner {
2990d0b4c86SJiang Liu 	return __irqd_to_state(d) & IRQD_LEVEL;
300876dbd4cSThomas Gleixner }
301876dbd4cSThomas Gleixner 
302d52dd441SThomas Gleixner /*
303d52dd441SThomas Gleixner  * Must only be called of irqchip.irq_set_affinity() or low level
304a359f757SIngo Molnar  * hierarchy domain allocation functions.
305d52dd441SThomas Gleixner  */
irqd_set_single_target(struct irq_data * d)306d52dd441SThomas Gleixner static inline void irqd_set_single_target(struct irq_data *d)
307d52dd441SThomas Gleixner {
308d52dd441SThomas Gleixner 	__irqd_to_state(d) |= IRQD_SINGLE_TARGET;
309d52dd441SThomas Gleixner }
310d52dd441SThomas Gleixner 
irqd_is_single_target(struct irq_data * d)311d52dd441SThomas Gleixner static inline bool irqd_is_single_target(struct irq_data *d)
312d52dd441SThomas Gleixner {
313d52dd441SThomas Gleixner 	return __irqd_to_state(d) & IRQD_SINGLE_TARGET;
314d52dd441SThomas Gleixner }
315d52dd441SThomas Gleixner 
irqd_set_handle_enforce_irqctx(struct irq_data * d)316c16816acSThomas Gleixner static inline void irqd_set_handle_enforce_irqctx(struct irq_data *d)
317c16816acSThomas Gleixner {
318c16816acSThomas Gleixner 	__irqd_to_state(d) |= IRQD_HANDLE_ENFORCE_IRQCTX;
319c16816acSThomas Gleixner }
320c16816acSThomas Gleixner 
irqd_is_handle_enforce_irqctx(struct irq_data * d)321c16816acSThomas Gleixner static inline bool irqd_is_handle_enforce_irqctx(struct irq_data *d)
322c16816acSThomas Gleixner {
323c16816acSThomas Gleixner 	return __irqd_to_state(d) & IRQD_HANDLE_ENFORCE_IRQCTX;
324c16816acSThomas Gleixner }
325c16816acSThomas Gleixner 
irqd_is_enabled_on_suspend(struct irq_data * d)32690428a8eSMaulik Shah static inline bool irqd_is_enabled_on_suspend(struct irq_data *d)
32790428a8eSMaulik Shah {
32890428a8eSMaulik Shah 	return __irqd_to_state(d) & IRQD_IRQ_ENABLED_ON_SUSPEND;
32990428a8eSMaulik Shah }
33090428a8eSMaulik Shah 
irqd_is_wakeup_set(struct irq_data * d)3317f94226fSThomas Gleixner static inline bool irqd_is_wakeup_set(struct irq_data *d)
3327f94226fSThomas Gleixner {
3330d0b4c86SJiang Liu 	return __irqd_to_state(d) & IRQD_WAKEUP_STATE;
3347f94226fSThomas Gleixner }
3357f94226fSThomas Gleixner 
irqd_irq_disabled(struct irq_data * d)336801a0e9aSThomas Gleixner static inline bool irqd_irq_disabled(struct irq_data *d)
337801a0e9aSThomas Gleixner {
3380d0b4c86SJiang Liu 	return __irqd_to_state(d) & IRQD_IRQ_DISABLED;
339801a0e9aSThomas Gleixner }
340801a0e9aSThomas Gleixner 
irqd_irq_masked(struct irq_data * d)34132f4125eSThomas Gleixner static inline bool irqd_irq_masked(struct irq_data *d)
34232f4125eSThomas Gleixner {
3430d0b4c86SJiang Liu 	return __irqd_to_state(d) & IRQD_IRQ_MASKED;
34432f4125eSThomas Gleixner }
34532f4125eSThomas Gleixner 
irqd_irq_inprogress(struct irq_data * d)34632f4125eSThomas Gleixner static inline bool irqd_irq_inprogress(struct irq_data *d)
34732f4125eSThomas Gleixner {
3480d0b4c86SJiang Liu 	return __irqd_to_state(d) & IRQD_IRQ_INPROGRESS;
34932f4125eSThomas Gleixner }
35032f4125eSThomas Gleixner 
irqd_is_wakeup_armed(struct irq_data * d)351b76f1674SThomas Gleixner static inline bool irqd_is_wakeup_armed(struct irq_data *d)
352b76f1674SThomas Gleixner {
3530d0b4c86SJiang Liu 	return __irqd_to_state(d) & IRQD_WAKEUP_ARMED;
354b76f1674SThomas Gleixner }
355b76f1674SThomas Gleixner 
irqd_is_forwarded_to_vcpu(struct irq_data * d)356fc569712SThomas Gleixner static inline bool irqd_is_forwarded_to_vcpu(struct irq_data *d)
357fc569712SThomas Gleixner {
358fc569712SThomas Gleixner 	return __irqd_to_state(d) & IRQD_FORWARDED_TO_VCPU;
359fc569712SThomas Gleixner }
360fc569712SThomas Gleixner 
irqd_set_forwarded_to_vcpu(struct irq_data * d)361fc569712SThomas Gleixner static inline void irqd_set_forwarded_to_vcpu(struct irq_data *d)
362fc569712SThomas Gleixner {
363fc569712SThomas Gleixner 	__irqd_to_state(d) |= IRQD_FORWARDED_TO_VCPU;
364fc569712SThomas Gleixner }
365fc569712SThomas Gleixner 
irqd_clr_forwarded_to_vcpu(struct irq_data * d)366fc569712SThomas Gleixner static inline void irqd_clr_forwarded_to_vcpu(struct irq_data *d)
367fc569712SThomas Gleixner {
368fc569712SThomas Gleixner 	__irqd_to_state(d) &= ~IRQD_FORWARDED_TO_VCPU;
369fc569712SThomas Gleixner }
370b76f1674SThomas Gleixner 
irqd_affinity_is_managed(struct irq_data * d)3719c255583SThomas Gleixner static inline bool irqd_affinity_is_managed(struct irq_data *d)
3729c255583SThomas Gleixner {
3739c255583SThomas Gleixner 	return __irqd_to_state(d) & IRQD_AFFINITY_MANAGED;
3749c255583SThomas Gleixner }
3759c255583SThomas Gleixner 
irqd_is_activated(struct irq_data * d)37608d85f3eSMarc Zyngier static inline bool irqd_is_activated(struct irq_data *d)
37708d85f3eSMarc Zyngier {
37808d85f3eSMarc Zyngier 	return __irqd_to_state(d) & IRQD_ACTIVATED;
37908d85f3eSMarc Zyngier }
38008d85f3eSMarc Zyngier 
irqd_set_activated(struct irq_data * d)38108d85f3eSMarc Zyngier static inline void irqd_set_activated(struct irq_data *d)
38208d85f3eSMarc Zyngier {
38308d85f3eSMarc Zyngier 	__irqd_to_state(d) |= IRQD_ACTIVATED;
38408d85f3eSMarc Zyngier }
38508d85f3eSMarc Zyngier 
irqd_clr_activated(struct irq_data * d)38608d85f3eSMarc Zyngier static inline void irqd_clr_activated(struct irq_data *d)
38708d85f3eSMarc Zyngier {
38808d85f3eSMarc Zyngier 	__irqd_to_state(d) &= ~IRQD_ACTIVATED;
38908d85f3eSMarc Zyngier }
39008d85f3eSMarc Zyngier 
irqd_is_started(struct irq_data * d)391201d7f47SThomas Gleixner static inline bool irqd_is_started(struct irq_data *d)
392201d7f47SThomas Gleixner {
393201d7f47SThomas Gleixner 	return __irqd_to_state(d) & IRQD_IRQ_STARTED;
394201d7f47SThomas Gleixner }
395201d7f47SThomas Gleixner 
irqd_is_managed_and_shutdown(struct irq_data * d)396761ea388SThomas Gleixner static inline bool irqd_is_managed_and_shutdown(struct irq_data *d)
39754fdf6a0SThomas Gleixner {
39854fdf6a0SThomas Gleixner 	return __irqd_to_state(d) & IRQD_MANAGED_SHUTDOWN;
39954fdf6a0SThomas Gleixner }
40054fdf6a0SThomas Gleixner 
irqd_set_can_reserve(struct irq_data * d)40169790ba9SThomas Gleixner static inline void irqd_set_can_reserve(struct irq_data *d)
40269790ba9SThomas Gleixner {
40369790ba9SThomas Gleixner 	__irqd_to_state(d) |= IRQD_CAN_RESERVE;
40469790ba9SThomas Gleixner }
40569790ba9SThomas Gleixner 
irqd_clr_can_reserve(struct irq_data * d)40669790ba9SThomas Gleixner static inline void irqd_clr_can_reserve(struct irq_data *d)
40769790ba9SThomas Gleixner {
40869790ba9SThomas Gleixner 	__irqd_to_state(d) &= ~IRQD_CAN_RESERVE;
40969790ba9SThomas Gleixner }
41069790ba9SThomas Gleixner 
irqd_can_reserve(struct irq_data * d)41169790ba9SThomas Gleixner static inline bool irqd_can_reserve(struct irq_data *d)
41269790ba9SThomas Gleixner {
41369790ba9SThomas Gleixner 	return __irqd_to_state(d) & IRQD_CAN_RESERVE;
41469790ba9SThomas Gleixner }
41569790ba9SThomas Gleixner 
irqd_set_affinity_on_activate(struct irq_data * d)416f0c7bacaSThomas Gleixner static inline void irqd_set_affinity_on_activate(struct irq_data *d)
417f0c7bacaSThomas Gleixner {
418f0c7bacaSThomas Gleixner 	__irqd_to_state(d) |= IRQD_AFFINITY_ON_ACTIVATE;
419f0c7bacaSThomas Gleixner }
420f0c7bacaSThomas Gleixner 
irqd_affinity_on_activate(struct irq_data * d)421f0c7bacaSThomas Gleixner static inline bool irqd_affinity_on_activate(struct irq_data *d)
422f0c7bacaSThomas Gleixner {
423f0c7bacaSThomas Gleixner 	return __irqd_to_state(d) & IRQD_AFFINITY_ON_ACTIVATE;
424f0c7bacaSThomas Gleixner }
425f0c7bacaSThomas Gleixner 
irqd_set_resend_when_in_progress(struct irq_data * d)4269c15eeb5SJames Gowans static inline void irqd_set_resend_when_in_progress(struct irq_data *d)
4279c15eeb5SJames Gowans {
4289c15eeb5SJames Gowans 	__irqd_to_state(d) |= IRQD_RESEND_WHEN_IN_PROGRESS;
4299c15eeb5SJames Gowans }
4309c15eeb5SJames Gowans 
irqd_needs_resend_when_in_progress(struct irq_data * d)4319c15eeb5SJames Gowans static inline bool irqd_needs_resend_when_in_progress(struct irq_data *d)
4329c15eeb5SJames Gowans {
4339c15eeb5SJames Gowans 	return __irqd_to_state(d) & IRQD_RESEND_WHEN_IN_PROGRESS;
4349c15eeb5SJames Gowans }
4359c15eeb5SJames Gowans 
436b354286eSBoqun Feng #undef __irqd_to_state
437b354286eSBoqun Feng 
irqd_to_hwirq(struct irq_data * d)438a699e4e4SGrant Likely static inline irq_hw_number_t irqd_to_hwirq(struct irq_data *d)
439a699e4e4SGrant Likely {
440a699e4e4SGrant Likely 	return d->hwirq;
441a699e4e4SGrant Likely }
442a699e4e4SGrant Likely 
443ff7dcd44SThomas Gleixner /**
4446a6de9efSThomas Gleixner  * struct irq_chip - hardware interrupt chip descriptor
4458fee5c36SIngo Molnar  *
4468fee5c36SIngo Molnar  * @name:		name for /proc/interrupts
447f8822657SThomas Gleixner  * @irq_startup:	start up the interrupt (defaults to ->enable if NULL)
448f8822657SThomas Gleixner  * @irq_shutdown:	shut down the interrupt (defaults to ->disable if NULL)
449f8822657SThomas Gleixner  * @irq_enable:		enable the interrupt (defaults to chip->unmask if NULL)
450f8822657SThomas Gleixner  * @irq_disable:	disable the interrupt
451f8822657SThomas Gleixner  * @irq_ack:		start of a new interrupt
452f8822657SThomas Gleixner  * @irq_mask:		mask an interrupt source
453f8822657SThomas Gleixner  * @irq_mask_ack:	ack and mask an interrupt source
454f8822657SThomas Gleixner  * @irq_unmask:		unmask an interrupt source
455f8822657SThomas Gleixner  * @irq_eoi:		end of interrupt
45683979133SThomas Gleixner  * @irq_set_affinity:	Set the CPU affinity on SMP machines. If the force
45783979133SThomas Gleixner  *			argument is true, it tells the driver to
45883979133SThomas Gleixner  *			unconditionally apply the affinity setting. Sanity
45983979133SThomas Gleixner  *			checks against the supplied affinity mask are not
46083979133SThomas Gleixner  *			required. This is used for CPU hotplug where the
46183979133SThomas Gleixner  *			target CPU is not yet set in the cpu_online_mask.
462f8822657SThomas Gleixner  * @irq_retrigger:	resend an IRQ to the CPU
463f8822657SThomas Gleixner  * @irq_set_type:	set the flow type (IRQ_TYPE_LEVEL/etc.) of an IRQ
464f8822657SThomas Gleixner  * @irq_set_wake:	enable/disable power-management wake-on of an IRQ
465f8822657SThomas Gleixner  * @irq_bus_lock:	function to lock access to slow bus (i2c) chips
466f8822657SThomas Gleixner  * @irq_bus_sync_unlock:function to sync and unlock slow bus (i2c) chips
4670fdb4b25SDavid Daney  * @irq_cpu_online:	configure an interrupt source for a secondary CPU
4680fdb4b25SDavid Daney  * @irq_cpu_offline:	un-configure an interrupt source for a secondary CPU
469be9b22b6SBrian Norris  * @irq_suspend:	function called from core code on suspend once per
470be9b22b6SBrian Norris  *			chip, when one or more interrupts are installed
471be9b22b6SBrian Norris  * @irq_resume:		function called from core code on resume once per chip,
472be9b22b6SBrian Norris  *			when one ore more interrupts are installed
473cfefd21eSThomas Gleixner  * @irq_pm_shutdown:	function called from core code on shutdown once per chip
474d0051816SThomas Gleixner  * @irq_calc_mask:	Optional function to set irq_data.mask for special cases
475ab7798ffSThomas Gleixner  * @irq_print_chip:	optional to print special chip info in show_interrupts
476c1bacbaeSThomas Gleixner  * @irq_request_resources:	optional to request resources before calling
477c1bacbaeSThomas Gleixner  *				any other callback related to this irq
478c1bacbaeSThomas Gleixner  * @irq_release_resources:	optional to release resources acquired with
479c1bacbaeSThomas Gleixner  *				irq_request_resources
480515085efSJiang Liu  * @irq_compose_msi_msg:	optional to compose message content for MSI
4819dde55b7SJiang Liu  * @irq_write_msi_msg:	optional to write message content for MSI
4821b7047edSMarc Zyngier  * @irq_get_irqchip_state:	return the internal state of an interrupt
4831b7047edSMarc Zyngier  * @irq_set_irqchip_state:	set the internal state of a interrupt
4840a4377deSJiang Liu  * @irq_set_vcpu_affinity:	optional to target a vCPU in a virtual machine
48534dc1ae1SQais Yousef  * @ipi_send_single:	send a single IPI to destination cpus
48634dc1ae1SQais Yousef  * @ipi_send_mask:	send an IPI to destination cpus in cpumask
487b525903cSJulien Thierry  * @irq_nmi_setup:	function called from core code before enabling an NMI
488b525903cSJulien Thierry  * @irq_nmi_teardown:	function called from core code after disabling an NMI
489751dc837SThomas Gleixner  * @irq_force_complete_move:	optional function to force complete pending irq move
4902bff17adSThomas Gleixner  * @flags:		chip specific flags
4911da177e4SLinus Torvalds  */
4926a6de9efSThomas Gleixner struct irq_chip {
4936a6de9efSThomas Gleixner 	const char	*name;
494f8822657SThomas Gleixner 	unsigned int	(*irq_startup)(struct irq_data *data);
495f8822657SThomas Gleixner 	void		(*irq_shutdown)(struct irq_data *data);
496f8822657SThomas Gleixner 	void		(*irq_enable)(struct irq_data *data);
497f8822657SThomas Gleixner 	void		(*irq_disable)(struct irq_data *data);
498f8822657SThomas Gleixner 
499f8822657SThomas Gleixner 	void		(*irq_ack)(struct irq_data *data);
500f8822657SThomas Gleixner 	void		(*irq_mask)(struct irq_data *data);
501f8822657SThomas Gleixner 	void		(*irq_mask_ack)(struct irq_data *data);
502f8822657SThomas Gleixner 	void		(*irq_unmask)(struct irq_data *data);
503f8822657SThomas Gleixner 	void		(*irq_eoi)(struct irq_data *data);
504f8822657SThomas Gleixner 
505f8822657SThomas Gleixner 	int		(*irq_set_affinity)(struct irq_data *data, const struct cpumask *dest, bool force);
506f8822657SThomas Gleixner 	int		(*irq_retrigger)(struct irq_data *data);
507f8822657SThomas Gleixner 	int		(*irq_set_type)(struct irq_data *data, unsigned int flow_type);
508f8822657SThomas Gleixner 	int		(*irq_set_wake)(struct irq_data *data, unsigned int on);
509f8822657SThomas Gleixner 
510f8822657SThomas Gleixner 	void		(*irq_bus_lock)(struct irq_data *data);
511f8822657SThomas Gleixner 	void		(*irq_bus_sync_unlock)(struct irq_data *data);
512f8822657SThomas Gleixner 
5138d15a729SMarc Zyngier #ifdef CONFIG_DEPRECATED_IRQ_CPU_ONOFFLINE
5140fdb4b25SDavid Daney 	void		(*irq_cpu_online)(struct irq_data *data);
5150fdb4b25SDavid Daney 	void		(*irq_cpu_offline)(struct irq_data *data);
5168d15a729SMarc Zyngier #endif
517cfefd21eSThomas Gleixner 	void		(*irq_suspend)(struct irq_data *data);
518cfefd21eSThomas Gleixner 	void		(*irq_resume)(struct irq_data *data);
519cfefd21eSThomas Gleixner 	void		(*irq_pm_shutdown)(struct irq_data *data);
520cfefd21eSThomas Gleixner 
521d0051816SThomas Gleixner 	void		(*irq_calc_mask)(struct irq_data *data);
522d0051816SThomas Gleixner 
523ab7798ffSThomas Gleixner 	void		(*irq_print_chip)(struct irq_data *data, struct seq_file *p);
524c1bacbaeSThomas Gleixner 	int		(*irq_request_resources)(struct irq_data *data);
525c1bacbaeSThomas Gleixner 	void		(*irq_release_resources)(struct irq_data *data);
526ab7798ffSThomas Gleixner 
527515085efSJiang Liu 	void		(*irq_compose_msi_msg)(struct irq_data *data, struct msi_msg *msg);
5289dde55b7SJiang Liu 	void		(*irq_write_msi_msg)(struct irq_data *data, struct msi_msg *msg);
529515085efSJiang Liu 
5301b7047edSMarc Zyngier 	int		(*irq_get_irqchip_state)(struct irq_data *data, enum irqchip_irq_state which, bool *state);
5311b7047edSMarc Zyngier 	int		(*irq_set_irqchip_state)(struct irq_data *data, enum irqchip_irq_state which, bool state);
5321b7047edSMarc Zyngier 
5330a4377deSJiang Liu 	int		(*irq_set_vcpu_affinity)(struct irq_data *data, void *vcpu_info);
5340a4377deSJiang Liu 
53534dc1ae1SQais Yousef 	void		(*ipi_send_single)(struct irq_data *data, unsigned int cpu);
53634dc1ae1SQais Yousef 	void		(*ipi_send_mask)(struct irq_data *data, const struct cpumask *dest);
53734dc1ae1SQais Yousef 
538b525903cSJulien Thierry 	int		(*irq_nmi_setup)(struct irq_data *data);
539b525903cSJulien Thierry 	void		(*irq_nmi_teardown)(struct irq_data *data);
540b525903cSJulien Thierry 
541751dc837SThomas Gleixner 	void		(*irq_force_complete_move)(struct irq_data *data);
542751dc837SThomas Gleixner 
5432bff17adSThomas Gleixner 	unsigned long	flags;
5441da177e4SLinus Torvalds };
5451da177e4SLinus Torvalds 
546d4d5e089SThomas Gleixner /*
547d4d5e089SThomas Gleixner  * irq_chip specific flags
548d4d5e089SThomas Gleixner  *
549d4d5e089SThomas Gleixner  * IRQCHIP_SET_TYPE_MASKED:           Mask before calling chip.irq_set_type()
55077694b40SThomas Gleixner  * IRQCHIP_EOI_IF_HANDLED:            Only issue irq_eoi() when irq was handled
551d209a699SThomas Gleixner  * IRQCHIP_MASK_ON_SUSPEND:           Mask non wake irqs in the suspend path
552b3d42232SThomas Gleixner  * IRQCHIP_ONOFFLINE_ENABLED:         Only call irq_on/off_line callbacks
553b3d42232SThomas Gleixner  *                                    when irq enabled
55460f96b41SSantosh Shilimkar  * IRQCHIP_SKIP_SET_WAKE:             Skip chip.irq_set_wake(), for this irq chip
5554f6e4f71SThomas Gleixner  * IRQCHIP_ONESHOT_SAFE:              One shot does not require mask/unmask
556328a4978SThomas Gleixner  * IRQCHIP_EOI_THREADED:              Chip requires eoi() on unmask in threaded mode
55790428a8eSMaulik Shah  * IRQCHIP_SUPPORTS_LEVEL_MSI:        Chip can provide two doorbells for Level MSIs
558b525903cSJulien Thierry  * IRQCHIP_SUPPORTS_NMI:              Chip can deliver NMIs, only for root irqchips
55990428a8eSMaulik Shah  * IRQCHIP_ENABLE_WAKEUP_ON_SUSPEND:  Invokes __enable_irq()/__disable_irq() for wake irqs
56090428a8eSMaulik Shah  *                                    in the suspend path if they are in disabled state
561826da771SThomas Gleixner  * IRQCHIP_AFFINITY_PRE_STARTUP:      Default affinity update before startup
5626c846d02SMarc Zyngier  * IRQCHIP_IMMUTABLE:		      Don't ever change anything in this chip
563a648eb3aSThomas Gleixner  * IRQCHIP_MOVE_DEFERRED:	      Move the interrupt in actual interrupt context
564d4d5e089SThomas Gleixner  */
565d4d5e089SThomas Gleixner enum {
566d4d5e089SThomas Gleixner 	IRQCHIP_SET_TYPE_MASKED			= (1 <<  0),
56777694b40SThomas Gleixner 	IRQCHIP_EOI_IF_HANDLED			= (1 <<  1),
568d209a699SThomas Gleixner 	IRQCHIP_MASK_ON_SUSPEND			= (1 <<  2),
569b3d42232SThomas Gleixner 	IRQCHIP_ONOFFLINE_ENABLED		= (1 <<  3),
57060f96b41SSantosh Shilimkar 	IRQCHIP_SKIP_SET_WAKE			= (1 <<  4),
571dc9b229aSThomas Gleixner 	IRQCHIP_ONESHOT_SAFE			= (1 <<  5),
572328a4978SThomas Gleixner 	IRQCHIP_EOI_THREADED			= (1 <<  6),
5736988e0e0SMarc Zyngier 	IRQCHIP_SUPPORTS_LEVEL_MSI		= (1 <<  7),
574b525903cSJulien Thierry 	IRQCHIP_SUPPORTS_NMI			= (1 <<  8),
57590428a8eSMaulik Shah 	IRQCHIP_ENABLE_WAKEUP_ON_SUSPEND	= (1 <<  9),
576826da771SThomas Gleixner 	IRQCHIP_AFFINITY_PRE_STARTUP		= (1 << 10),
5776c846d02SMarc Zyngier 	IRQCHIP_IMMUTABLE			= (1 << 11),
578a648eb3aSThomas Gleixner 	IRQCHIP_MOVE_DEFERRED			= (1 << 12),
579d4d5e089SThomas Gleixner };
580d4d5e089SThomas Gleixner 
581e144710bSThomas Gleixner #include <linux/irqdesc.h>
582c6b7674fSThomas Gleixner 
58334ffdb72SIngo Molnar /*
58434ffdb72SIngo Molnar  * Pick up the arch-dependent methods:
58534ffdb72SIngo Molnar  */
58634ffdb72SIngo Molnar #include <asm/hw_irq.h>
5871da177e4SLinus Torvalds 
588b683de2bSThomas Gleixner #ifndef NR_IRQS_LEGACY
589b683de2bSThomas Gleixner # define NR_IRQS_LEGACY 0
590b683de2bSThomas Gleixner #endif
591b683de2bSThomas Gleixner 
5921318a481SThomas Gleixner #ifndef ARCH_IRQ_INIT_FLAGS
5931318a481SThomas Gleixner # define ARCH_IRQ_INIT_FLAGS	0
5941318a481SThomas Gleixner #endif
5951318a481SThomas Gleixner 
596c1594b77SThomas Gleixner #define IRQ_DEFAULT_INIT_FLAGS	ARCH_IRQ_INIT_FLAGS
5971318a481SThomas Gleixner 
598e144710bSThomas Gleixner struct irqaction;
59931d9d9b6SMarc Zyngier extern int setup_percpu_irq(unsigned int irq, struct irqaction *new);
60031d9d9b6SMarc Zyngier extern void remove_percpu_irq(unsigned int irq, struct irqaction *act);
6011da177e4SLinus Torvalds 
6028d15a729SMarc Zyngier #ifdef CONFIG_DEPRECATED_IRQ_CPU_ONOFFLINE
6030fdb4b25SDavid Daney extern void irq_cpu_online(void);
6040fdb4b25SDavid Daney extern void irq_cpu_offline(void);
6058d15a729SMarc Zyngier #endif
60601f8fa4fSThomas Gleixner extern int irq_set_affinity_locked(struct irq_data *data,
60701f8fa4fSThomas Gleixner 				   const struct cpumask *cpumask, bool force);
6080a4377deSJiang Liu extern int irq_set_vcpu_affinity(unsigned int irq, void *vcpu_info);
6090fdb4b25SDavid Daney 
610c5cb83bbSThomas Gleixner #if defined(CONFIG_SMP) && defined(CONFIG_GENERIC_IRQ_MIGRATION)
611f1e0bb0aSYang Yingliang extern void irq_migrate_all_off_this_cpu(void);
612c5cb83bbSThomas Gleixner extern int irq_affinity_online_cpu(unsigned int cpu);
613c5cb83bbSThomas Gleixner #else
614c5cb83bbSThomas Gleixner # define irq_affinity_online_cpu	NULL
615c5cb83bbSThomas Gleixner #endif
616f1e0bb0aSYang Yingliang 
6173a3856d0SThomas Gleixner #if defined(CONFIG_SMP) && defined(CONFIG_GENERIC_PENDING_IRQ)
618*e54b1b5eSAnup Patel bool irq_can_move_in_process_context(struct irq_data *data);
619d340ebd6SThomas Gleixner void __irq_move_irq(struct irq_data *data);
irq_move_irq(struct irq_data * data)620d340ebd6SThomas Gleixner static inline void irq_move_irq(struct irq_data *data)
621d340ebd6SThomas Gleixner {
622d340ebd6SThomas Gleixner 	if (unlikely(irqd_is_setaffinity_pending(data)))
623d340ebd6SThomas Gleixner 		__irq_move_irq(data);
624d340ebd6SThomas Gleixner }
625a439520fSThomas Gleixner void irq_move_masked_irq(struct irq_data *data);
626e144710bSThomas Gleixner #else
irq_can_move_in_process_context(struct irq_data * data)627*e54b1b5eSAnup Patel static inline bool irq_can_move_in_process_context(struct irq_data *data) { return true; }
irq_move_irq(struct irq_data * data)628a439520fSThomas Gleixner static inline void irq_move_irq(struct irq_data *data) { }
irq_move_masked_irq(struct irq_data * data)629a439520fSThomas Gleixner static inline void irq_move_masked_irq(struct irq_data *data) { }
630e144710bSThomas Gleixner #endif
63154d5d424SAshok Raj 
6321da177e4SLinus Torvalds extern int no_irq_affinity;
6331da177e4SLinus Torvalds 
634293a7a0aSThomas Gleixner #ifdef CONFIG_HARDIRQS_SW_RESEND
635293a7a0aSThomas Gleixner int irq_set_parent(int irq, int parent_irq);
636293a7a0aSThomas Gleixner #else
irq_set_parent(int irq,int parent_irq)637293a7a0aSThomas Gleixner static inline int irq_set_parent(int irq, int parent_irq)
638293a7a0aSThomas Gleixner {
639293a7a0aSThomas Gleixner 	return 0;
640293a7a0aSThomas Gleixner }
641293a7a0aSThomas Gleixner #endif
642293a7a0aSThomas Gleixner 
6432e60bbb6SIngo Molnar /*
6446a6de9efSThomas Gleixner  * Built-in IRQ handlers for various IRQ types,
645bebd04ccSKrzysztof Halasa  * callable via desc->handle_irq()
6466a6de9efSThomas Gleixner  */
647bd0b9ac4SThomas Gleixner extern void handle_level_irq(struct irq_desc *desc);
648bd0b9ac4SThomas Gleixner extern void handle_fasteoi_irq(struct irq_desc *desc);
649bd0b9ac4SThomas Gleixner extern void handle_edge_irq(struct irq_desc *desc);
650bd0b9ac4SThomas Gleixner extern void handle_edge_eoi_irq(struct irq_desc *desc);
651bd0b9ac4SThomas Gleixner extern void handle_simple_irq(struct irq_desc *desc);
652edd14cfeSKeith Busch extern void handle_untracked_irq(struct irq_desc *desc);
653bd0b9ac4SThomas Gleixner extern void handle_percpu_irq(struct irq_desc *desc);
654bd0b9ac4SThomas Gleixner extern void handle_percpu_devid_irq(struct irq_desc *desc);
655bd0b9ac4SThomas Gleixner extern void handle_bad_irq(struct irq_desc *desc);
65631b47cf7SMark Brown extern void handle_nested_irq(unsigned int irq);
6576a6de9efSThomas Gleixner 
6582dcf1fbcSJulien Thierry extern void handle_fasteoi_nmi(struct irq_desc *desc);
6592dcf1fbcSJulien Thierry extern void handle_percpu_devid_fasteoi_nmi(struct irq_desc *desc);
6602dcf1fbcSJulien Thierry 
661515085efSJiang Liu extern int irq_chip_compose_msi_msg(struct irq_data *data, struct msi_msg *msg);
662be45beb2SJon Hunter extern int irq_chip_pm_get(struct irq_data *data);
663be45beb2SJon Hunter extern int irq_chip_pm_put(struct irq_data *data);
66485f08c17SJiang Liu #ifdef	CONFIG_IRQ_DOMAIN_HIERARCHY
6657703b08cSDavid Daney extern void handle_fasteoi_ack_irq(struct irq_desc *desc);
6667703b08cSDavid Daney extern void handle_fasteoi_mask_irq(struct irq_desc *desc);
6674a169a95SMaulik Shah extern int irq_chip_set_parent_state(struct irq_data *data,
6684a169a95SMaulik Shah 				     enum irqchip_irq_state which,
6694a169a95SMaulik Shah 				     bool val);
6704a169a95SMaulik Shah extern int irq_chip_get_parent_state(struct irq_data *data,
6714a169a95SMaulik Shah 				     enum irqchip_irq_state which,
6724a169a95SMaulik Shah 				     bool *state);
6733cfeffc2SStefan Agner extern void irq_chip_enable_parent(struct irq_data *data);
6743cfeffc2SStefan Agner extern void irq_chip_disable_parent(struct irq_data *data);
67585f08c17SJiang Liu extern void irq_chip_ack_parent(struct irq_data *data);
67685f08c17SJiang Liu extern int irq_chip_retrigger_hierarchy(struct irq_data *data);
67756e8ababSYingjoe Chen extern void irq_chip_mask_parent(struct irq_data *data);
6785aa5bd56SLinus Walleij extern void irq_chip_mask_ack_parent(struct irq_data *data);
67956e8ababSYingjoe Chen extern void irq_chip_unmask_parent(struct irq_data *data);
68056e8ababSYingjoe Chen extern void irq_chip_eoi_parent(struct irq_data *data);
68156e8ababSYingjoe Chen extern int irq_chip_set_affinity_parent(struct irq_data *data,
68256e8ababSYingjoe Chen 					const struct cpumask *dest,
68356e8ababSYingjoe Chen 					bool force);
68408b55e2aSMarc Zyngier extern int irq_chip_set_wake_parent(struct irq_data *data, unsigned int on);
6850a4377deSJiang Liu extern int irq_chip_set_vcpu_affinity_parent(struct irq_data *data,
6860a4377deSJiang Liu 					     void *vcpu_info);
687b7560de1SGrygorii Strashko extern int irq_chip_set_type_parent(struct irq_data *data, unsigned int type);
6882bd1298aSLokesh Vutla extern int irq_chip_request_resources_parent(struct irq_data *data);
6892bd1298aSLokesh Vutla extern void irq_chip_release_resources_parent(struct irq_data *data);
69085f08c17SJiang Liu #endif
69185f08c17SJiang Liu 
692bad6722eSEliav Farber /* Disable or mask interrupts during a kernel kexec */
693bad6722eSEliav Farber extern void machine_kexec_mask_interrupts(void);
694bad6722eSEliav Farber 
6956a6de9efSThomas Gleixner /* Handling of unhandled and spurious interrupts: */
6960dcdbc97SJiang Liu extern void note_interrupt(struct irq_desc *desc, irqreturn_t action_ret);
6971da177e4SLinus Torvalds 
698a4633adcSThomas Gleixner 
6996a6de9efSThomas Gleixner /* Enable/disable irq debugging output: */
7006a6de9efSThomas Gleixner extern int noirqdebug_setup(char *str);
7011da177e4SLinus Torvalds 
7026a6de9efSThomas Gleixner /* Checks whether the interrupt can be requested by request_irq(): */
7036a6de9efSThomas Gleixner extern int can_request_irq(unsigned int irq, unsigned long irqflags);
7046a6de9efSThomas Gleixner 
705f8b5473fSThomas Gleixner /* Dummy irq-chip implementations: */
7066a6de9efSThomas Gleixner extern struct irq_chip no_irq_chip;
707f8b5473fSThomas Gleixner extern struct irq_chip dummy_irq_chip;
7086a6de9efSThomas Gleixner 
7096a6de9efSThomas Gleixner extern void
710393e1280SMarc Zyngier irq_set_chip_and_handler_name(unsigned int irq, const struct irq_chip *chip,
711a460e745SIngo Molnar 			      irq_flow_handler_t handle, const char *name);
712a460e745SIngo Molnar 
irq_set_chip_and_handler(unsigned int irq,const struct irq_chip * chip,irq_flow_handler_t handle)713393e1280SMarc Zyngier static inline void irq_set_chip_and_handler(unsigned int irq,
714393e1280SMarc Zyngier 					    const struct irq_chip *chip,
7153836ca08SThomas Gleixner 					    irq_flow_handler_t handle)
7163836ca08SThomas Gleixner {
7173836ca08SThomas Gleixner 	irq_set_chip_and_handler_name(irq, chip, handle, NULL);
7183836ca08SThomas Gleixner }
7193836ca08SThomas Gleixner 
72031d9d9b6SMarc Zyngier extern int irq_set_percpu_devid(unsigned int irq);
721222df54fSMarc Zyngier extern int irq_set_percpu_devid_partition(unsigned int irq,
722222df54fSMarc Zyngier 					  const struct cpumask *affinity);
723222df54fSMarc Zyngier extern int irq_get_percpu_devid_partition(unsigned int irq,
724222df54fSMarc Zyngier 					  struct cpumask *affinity);
72531d9d9b6SMarc Zyngier 
7266a6de9efSThomas Gleixner extern void
7273836ca08SThomas Gleixner __irq_set_handler(unsigned int irq, irq_flow_handler_t handle, int is_chained,
728a460e745SIngo Molnar 		  const char *name);
7296a6de9efSThomas Gleixner 
7306a6de9efSThomas Gleixner static inline void
irq_set_handler(unsigned int irq,irq_flow_handler_t handle)7313836ca08SThomas Gleixner irq_set_handler(unsigned int irq, irq_flow_handler_t handle)
7326a6de9efSThomas Gleixner {
7333836ca08SThomas Gleixner 	__irq_set_handler(irq, handle, 0, NULL);
7346a6de9efSThomas Gleixner }
7356a6de9efSThomas Gleixner 
7366a6de9efSThomas Gleixner /*
7376a6de9efSThomas Gleixner  * Set a highlevel chained flow handler for a given IRQ.
7386a6de9efSThomas Gleixner  * (a chained handler is automatically enabled and set to
7397f1b1244SPaul Mundt  *  IRQ_NOREQUEST, IRQ_NOPROBE, and IRQ_NOTHREAD)
7406a6de9efSThomas Gleixner  */
7416a6de9efSThomas Gleixner static inline void
irq_set_chained_handler(unsigned int irq,irq_flow_handler_t handle)7423836ca08SThomas Gleixner irq_set_chained_handler(unsigned int irq, irq_flow_handler_t handle)
7436a6de9efSThomas Gleixner {
7443836ca08SThomas Gleixner 	__irq_set_handler(irq, handle, 1, NULL);
7456a6de9efSThomas Gleixner }
7466a6de9efSThomas Gleixner 
7473b0f95beSRussell King /*
7483b0f95beSRussell King  * Set a highlevel chained flow handler and its data for a given IRQ.
7493b0f95beSRussell King  * (a chained handler is automatically enabled and set to
7503b0f95beSRussell King  *  IRQ_NOREQUEST, IRQ_NOPROBE, and IRQ_NOTHREAD)
7513b0f95beSRussell King  */
7523b0f95beSRussell King void
7533b0f95beSRussell King irq_set_chained_handler_and_data(unsigned int irq, irq_flow_handler_t handle,
7543b0f95beSRussell King 				 void *data);
7553b0f95beSRussell King 
75644247184SThomas Gleixner void irq_modify_status(unsigned int irq, unsigned long clr, unsigned long set);
75744247184SThomas Gleixner 
irq_set_status_flags(unsigned int irq,unsigned long set)75844247184SThomas Gleixner static inline void irq_set_status_flags(unsigned int irq, unsigned long set)
75944247184SThomas Gleixner {
76044247184SThomas Gleixner 	irq_modify_status(irq, 0, set);
76144247184SThomas Gleixner }
76244247184SThomas Gleixner 
irq_clear_status_flags(unsigned int irq,unsigned long clr)76344247184SThomas Gleixner static inline void irq_clear_status_flags(unsigned int irq, unsigned long clr)
76444247184SThomas Gleixner {
76544247184SThomas Gleixner 	irq_modify_status(irq, clr, 0);
76644247184SThomas Gleixner }
76744247184SThomas Gleixner 
irq_set_noprobe(unsigned int irq)768a0cd9ca2SThomas Gleixner static inline void irq_set_noprobe(unsigned int irq)
76944247184SThomas Gleixner {
77044247184SThomas Gleixner 	irq_modify_status(irq, 0, IRQ_NOPROBE);
77144247184SThomas Gleixner }
77244247184SThomas Gleixner 
irq_set_probe(unsigned int irq)773a0cd9ca2SThomas Gleixner static inline void irq_set_probe(unsigned int irq)
77444247184SThomas Gleixner {
77544247184SThomas Gleixner 	irq_modify_status(irq, IRQ_NOPROBE, 0);
77644247184SThomas Gleixner }
77746f4f8f6SRalf Baechle 
irq_set_nothread(unsigned int irq)7787f1b1244SPaul Mundt static inline void irq_set_nothread(unsigned int irq)
7797f1b1244SPaul Mundt {
7807f1b1244SPaul Mundt 	irq_modify_status(irq, 0, IRQ_NOTHREAD);
7817f1b1244SPaul Mundt }
7827f1b1244SPaul Mundt 
irq_set_thread(unsigned int irq)7837f1b1244SPaul Mundt static inline void irq_set_thread(unsigned int irq)
7847f1b1244SPaul Mundt {
7857f1b1244SPaul Mundt 	irq_modify_status(irq, IRQ_NOTHREAD, 0);
7867f1b1244SPaul Mundt }
7877f1b1244SPaul Mundt 
irq_set_nested_thread(unsigned int irq,bool nest)7886f91a52dSThomas Gleixner static inline void irq_set_nested_thread(unsigned int irq, bool nest)
7896f91a52dSThomas Gleixner {
7906f91a52dSThomas Gleixner 	if (nest)
7916f91a52dSThomas Gleixner 		irq_set_status_flags(irq, IRQ_NESTED_THREAD);
7926f91a52dSThomas Gleixner 	else
7936f91a52dSThomas Gleixner 		irq_clear_status_flags(irq, IRQ_NESTED_THREAD);
7946f91a52dSThomas Gleixner }
7956f91a52dSThomas Gleixner 
irq_set_percpu_devid_flags(unsigned int irq)79631d9d9b6SMarc Zyngier static inline void irq_set_percpu_devid_flags(unsigned int irq)
79731d9d9b6SMarc Zyngier {
79831d9d9b6SMarc Zyngier 	irq_set_status_flags(irq,
79931d9d9b6SMarc Zyngier 			     IRQ_NOAUTOEN | IRQ_PER_CPU | IRQ_NOTHREAD |
80031d9d9b6SMarc Zyngier 			     IRQ_NOPROBE | IRQ_PER_CPU_DEVID);
80131d9d9b6SMarc Zyngier }
80231d9d9b6SMarc Zyngier 
8033a16d713SEric W. Biederman /* Set/get chip/data for an IRQ: */
804393e1280SMarc Zyngier extern int irq_set_chip(unsigned int irq, const struct irq_chip *chip);
805a0cd9ca2SThomas Gleixner extern int irq_set_handler_data(unsigned int irq, void *data);
806a0cd9ca2SThomas Gleixner extern int irq_set_chip_data(unsigned int irq, void *data);
807a0cd9ca2SThomas Gleixner extern int irq_set_irq_type(unsigned int irq, unsigned int type);
808a0cd9ca2SThomas Gleixner extern int irq_set_msi_desc(unsigned int irq, struct msi_desc *entry);
80951906e77SAlexander Gordeev extern int irq_set_msi_desc_off(unsigned int irq_base, unsigned int irq_offset,
81051906e77SAlexander Gordeev 				struct msi_desc *entry);
811f303a6ddSThomas Gleixner extern struct irq_data *irq_get_irq_data(unsigned int irq);
812dd87eb3aSThomas Gleixner 
irq_get_chip(unsigned int irq)813a0cd9ca2SThomas Gleixner static inline struct irq_chip *irq_get_chip(unsigned int irq)
814f303a6ddSThomas Gleixner {
815f303a6ddSThomas Gleixner 	struct irq_data *d = irq_get_irq_data(irq);
816f303a6ddSThomas Gleixner 	return d ? d->chip : NULL;
817f303a6ddSThomas Gleixner }
818f303a6ddSThomas Gleixner 
irq_data_get_irq_chip(struct irq_data * d)819f303a6ddSThomas Gleixner static inline struct irq_chip *irq_data_get_irq_chip(struct irq_data *d)
820f303a6ddSThomas Gleixner {
821f303a6ddSThomas Gleixner 	return d->chip;
822f303a6ddSThomas Gleixner }
823f303a6ddSThomas Gleixner 
irq_get_chip_data(unsigned int irq)824a0cd9ca2SThomas Gleixner static inline void *irq_get_chip_data(unsigned int irq)
825f303a6ddSThomas Gleixner {
826f303a6ddSThomas Gleixner 	struct irq_data *d = irq_get_irq_data(irq);
827f303a6ddSThomas Gleixner 	return d ? d->chip_data : NULL;
828f303a6ddSThomas Gleixner }
829f303a6ddSThomas Gleixner 
irq_data_get_irq_chip_data(struct irq_data * d)830f303a6ddSThomas Gleixner static inline void *irq_data_get_irq_chip_data(struct irq_data *d)
831f303a6ddSThomas Gleixner {
832f303a6ddSThomas Gleixner 	return d->chip_data;
833f303a6ddSThomas Gleixner }
834f303a6ddSThomas Gleixner 
irq_get_handler_data(unsigned int irq)835a0cd9ca2SThomas Gleixner static inline void *irq_get_handler_data(unsigned int irq)
836f303a6ddSThomas Gleixner {
837f303a6ddSThomas Gleixner 	struct irq_data *d = irq_get_irq_data(irq);
838af7080e0SJiang Liu 	return d ? d->common->handler_data : NULL;
839f303a6ddSThomas Gleixner }
840f303a6ddSThomas Gleixner 
irq_data_get_irq_handler_data(struct irq_data * d)841a0cd9ca2SThomas Gleixner static inline void *irq_data_get_irq_handler_data(struct irq_data *d)
842f303a6ddSThomas Gleixner {
843af7080e0SJiang Liu 	return d->common->handler_data;
844f303a6ddSThomas Gleixner }
845f303a6ddSThomas Gleixner 
irq_get_msi_desc(unsigned int irq)846a0cd9ca2SThomas Gleixner static inline struct msi_desc *irq_get_msi_desc(unsigned int irq)
847f303a6ddSThomas Gleixner {
848f303a6ddSThomas Gleixner 	struct irq_data *d = irq_get_irq_data(irq);
849b237721cSJiang Liu 	return d ? d->common->msi_desc : NULL;
850f303a6ddSThomas Gleixner }
851f303a6ddSThomas Gleixner 
irq_data_get_msi_desc(struct irq_data * d)852c391f262SJiang Liu static inline struct msi_desc *irq_data_get_msi_desc(struct irq_data *d)
853f303a6ddSThomas Gleixner {
854b237721cSJiang Liu 	return d->common->msi_desc;
855f303a6ddSThomas Gleixner }
856f303a6ddSThomas Gleixner 
irq_get_trigger_type(unsigned int irq)8571f6236bfSJavier Martinez Canillas static inline u32 irq_get_trigger_type(unsigned int irq)
8581f6236bfSJavier Martinez Canillas {
8591f6236bfSJavier Martinez Canillas 	struct irq_data *d = irq_get_irq_data(irq);
8601f6236bfSJavier Martinez Canillas 	return d ? irqd_get_trigger_type(d) : 0;
8611f6236bfSJavier Martinez Canillas }
8621f6236bfSJavier Martinez Canillas 
irq_common_data_get_node(struct irq_common_data * d)863449e9caeSJiang Liu static inline int irq_common_data_get_node(struct irq_common_data *d)
864449e9caeSJiang Liu {
865449e9caeSJiang Liu #ifdef CONFIG_NUMA
866449e9caeSJiang Liu 	return d->node;
867449e9caeSJiang Liu #else
868449e9caeSJiang Liu 	return 0;
869449e9caeSJiang Liu #endif
870449e9caeSJiang Liu }
871449e9caeSJiang Liu 
irq_data_get_node(struct irq_data * d)8726783011bSJiang Liu static inline int irq_data_get_node(struct irq_data *d)
8736783011bSJiang Liu {
874449e9caeSJiang Liu 	return irq_common_data_get_node(d->common);
8756783011bSJiang Liu }
8766783011bSJiang Liu 
8774d0b8298SSamuel Holland static inline
irq_data_get_affinity_mask(struct irq_data * d)8784d0b8298SSamuel Holland const struct cpumask *irq_data_get_affinity_mask(struct irq_data *d)
879961343d7SSamuel Holland {
880aa081358SSamuel Holland #ifdef CONFIG_SMP
881961343d7SSamuel Holland 	return d->common->affinity;
882aa081358SSamuel Holland #else
883aa081358SSamuel Holland 	return cpumask_of(0);
884aa081358SSamuel Holland #endif
885961343d7SSamuel Holland }
886961343d7SSamuel Holland 
irq_data_update_affinity(struct irq_data * d,const struct cpumask * m)887073352e9SSamuel Holland static inline void irq_data_update_affinity(struct irq_data *d,
888073352e9SSamuel Holland 					    const struct cpumask *m)
889073352e9SSamuel Holland {
890aa081358SSamuel Holland #ifdef CONFIG_SMP
891073352e9SSamuel Holland 	cpumask_copy(d->common->affinity, m);
892aa081358SSamuel Holland #endif
893073352e9SSamuel Holland }
894073352e9SSamuel Holland 
irq_get_affinity_mask(int irq)8954d0b8298SSamuel Holland static inline const struct cpumask *irq_get_affinity_mask(int irq)
896c64301a2SJiang Liu {
897c64301a2SJiang Liu 	struct irq_data *d = irq_get_irq_data(irq);
898c64301a2SJiang Liu 
899961343d7SSamuel Holland 	return d ? irq_data_get_affinity_mask(d) : NULL;
900c64301a2SJiang Liu }
901c64301a2SJiang Liu 
9020d3f5425SThomas Gleixner #ifdef CONFIG_GENERIC_IRQ_EFFECTIVE_AFF_MASK
9030d3f5425SThomas Gleixner static inline
irq_data_get_effective_affinity_mask(struct irq_data * d)9044d0b8298SSamuel Holland const struct cpumask *irq_data_get_effective_affinity_mask(struct irq_data *d)
9050d3f5425SThomas Gleixner {
9060d3f5425SThomas Gleixner 	return d->common->effective_affinity;
9070d3f5425SThomas Gleixner }
irq_data_update_effective_affinity(struct irq_data * d,const struct cpumask * m)9080d3f5425SThomas Gleixner static inline void irq_data_update_effective_affinity(struct irq_data *d,
9090d3f5425SThomas Gleixner 						      const struct cpumask *m)
9100d3f5425SThomas Gleixner {
9110d3f5425SThomas Gleixner 	cpumask_copy(d->common->effective_affinity, m);
9120d3f5425SThomas Gleixner }
9130d3f5425SThomas Gleixner #else
irq_data_update_effective_affinity(struct irq_data * d,const struct cpumask * m)9140d3f5425SThomas Gleixner static inline void irq_data_update_effective_affinity(struct irq_data *d,
9150d3f5425SThomas Gleixner 						      const struct cpumask *m)
9160d3f5425SThomas Gleixner {
9170d3f5425SThomas Gleixner }
9180d3f5425SThomas Gleixner static inline
irq_data_get_effective_affinity_mask(struct irq_data * d)9194d0b8298SSamuel Holland const struct cpumask *irq_data_get_effective_affinity_mask(struct irq_data *d)
9200d3f5425SThomas Gleixner {
921961343d7SSamuel Holland 	return irq_data_get_affinity_mask(d);
9220d3f5425SThomas Gleixner }
9230d3f5425SThomas Gleixner #endif
9240d3f5425SThomas Gleixner 
9254d0b8298SSamuel Holland static inline
irq_get_effective_affinity_mask(unsigned int irq)9264d0b8298SSamuel Holland const struct cpumask *irq_get_effective_affinity_mask(unsigned int irq)
9273e238012SThomas Gleixner {
9283e238012SThomas Gleixner 	struct irq_data *d = irq_get_irq_data(irq);
9293e238012SThomas Gleixner 
9303e238012SThomas Gleixner 	return d ? irq_data_get_effective_affinity_mask(d) : NULL;
9313e238012SThomas Gleixner }
9323e238012SThomas Gleixner 
93362a08ae2SThomas Gleixner unsigned int arch_dynirq_lower_bound(unsigned int from);
93462a08ae2SThomas Gleixner 
935b6873807SSebastian Andrzej Siewior int __irq_alloc_descs(int irq, unsigned int from, unsigned int cnt, int node,
936bec04037SDou Liyang 		      struct module *owner,
937bec04037SDou Liyang 		      const struct irq_affinity_desc *affinity);
938b6873807SSebastian Andrzej Siewior 
9392b5e7730SBartosz Golaszewski int __devm_irq_alloc_descs(struct device *dev, int irq, unsigned int from,
9402b5e7730SBartosz Golaszewski 			   unsigned int cnt, int node, struct module *owner,
941bec04037SDou Liyang 			   const struct irq_affinity_desc *affinity);
9422b5e7730SBartosz Golaszewski 
943ec53cf23SPaul Gortmaker /* use macros to avoid needing export.h for THIS_MODULE */
944ec53cf23SPaul Gortmaker #define irq_alloc_descs(irq, from, cnt, node)	\
94506ee6d57SThomas Gleixner 	__irq_alloc_descs(irq, from, cnt, node, THIS_MODULE, NULL)
946ec53cf23SPaul Gortmaker 
947ec53cf23SPaul Gortmaker #define irq_alloc_desc(node)			\
9484c7bcb51SHans de Goede 	irq_alloc_descs(-1, 1, 1, node)
949ec53cf23SPaul Gortmaker 
950ec53cf23SPaul Gortmaker #define irq_alloc_desc_at(at, node)		\
951ec53cf23SPaul Gortmaker 	irq_alloc_descs(at, at, 1, node)
952ec53cf23SPaul Gortmaker 
953ec53cf23SPaul Gortmaker #define irq_alloc_desc_from(from, node)		\
954ec53cf23SPaul Gortmaker 	irq_alloc_descs(-1, from, 1, node)
955b6873807SSebastian Andrzej Siewior 
95651906e77SAlexander Gordeev #define irq_alloc_descs_from(from, cnt, node)	\
95751906e77SAlexander Gordeev 	irq_alloc_descs(-1, from, cnt, node)
95851906e77SAlexander Gordeev 
9592b5e7730SBartosz Golaszewski #define devm_irq_alloc_descs(dev, irq, from, cnt, node)		\
9602b5e7730SBartosz Golaszewski 	__devm_irq_alloc_descs(dev, irq, from, cnt, node, THIS_MODULE, NULL)
9612b5e7730SBartosz Golaszewski 
9622b5e7730SBartosz Golaszewski #define devm_irq_alloc_desc(dev, node)				\
9634c7bcb51SHans de Goede 	devm_irq_alloc_descs(dev, -1, 1, 1, node)
9642b5e7730SBartosz Golaszewski 
9652b5e7730SBartosz Golaszewski #define devm_irq_alloc_desc_at(dev, at, node)			\
9662b5e7730SBartosz Golaszewski 	devm_irq_alloc_descs(dev, at, at, 1, node)
9672b5e7730SBartosz Golaszewski 
9682b5e7730SBartosz Golaszewski #define devm_irq_alloc_desc_from(dev, from, node)		\
9692b5e7730SBartosz Golaszewski 	devm_irq_alloc_descs(dev, -1, from, 1, node)
9702b5e7730SBartosz Golaszewski 
9712b5e7730SBartosz Golaszewski #define devm_irq_alloc_descs_from(dev, from, cnt, node)		\
9722b5e7730SBartosz Golaszewski 	devm_irq_alloc_descs(dev, -1, from, cnt, node)
9732b5e7730SBartosz Golaszewski 
9741f5a5b87SThomas Gleixner void irq_free_descs(unsigned int irq, unsigned int cnt);
irq_free_desc(unsigned int irq)9751f5a5b87SThomas Gleixner static inline void irq_free_desc(unsigned int irq)
9761f5a5b87SThomas Gleixner {
9771f5a5b87SThomas Gleixner 	irq_free_descs(irq, 1);
9781f5a5b87SThomas Gleixner }
9791f5a5b87SThomas Gleixner 
980c940e01cSThomas Gleixner #ifdef CONFIG_GENERIC_IRQ_LEGACY
981c940e01cSThomas Gleixner void irq_init_desc(unsigned int irq);
982c940e01cSThomas Gleixner #endif
983c940e01cSThomas Gleixner 
9847d828062SThomas Gleixner /**
9857d828062SThomas Gleixner  * struct irq_chip_regs - register offsets for struct irq_gci
9867d828062SThomas Gleixner  * @enable:	Enable register offset to reg_base
9877d828062SThomas Gleixner  * @disable:	Disable register offset to reg_base
9887d828062SThomas Gleixner  * @mask:	Mask register offset to reg_base
9897d828062SThomas Gleixner  * @ack:	Ack register offset to reg_base
9907d828062SThomas Gleixner  * @eoi:	Eoi register offset to reg_base
9917d828062SThomas Gleixner  * @type:	Type configuration register offset to reg_base
9927d828062SThomas Gleixner  */
9937d828062SThomas Gleixner struct irq_chip_regs {
9947d828062SThomas Gleixner 	unsigned long		enable;
9957d828062SThomas Gleixner 	unsigned long		disable;
9967d828062SThomas Gleixner 	unsigned long		mask;
9977d828062SThomas Gleixner 	unsigned long		ack;
9987d828062SThomas Gleixner 	unsigned long		eoi;
9997d828062SThomas Gleixner 	unsigned long		type;
10007d828062SThomas Gleixner };
10017d828062SThomas Gleixner 
10027d828062SThomas Gleixner /**
10037d828062SThomas Gleixner  * struct irq_chip_type - Generic interrupt chip instance for a flow type
10047d828062SThomas Gleixner  * @chip:		The real interrupt chip which provides the callbacks
10057d828062SThomas Gleixner  * @regs:		Register offsets for this chip
10067d828062SThomas Gleixner  * @handler:		Flow handler associated with this chip
10077d828062SThomas Gleixner  * @type:		Chip can handle these flow types
1008899f0e66SGerlando Falauto  * @mask_cache_priv:	Cached mask register private to the chip type
1009899f0e66SGerlando Falauto  * @mask_cache:		Pointer to cached mask register
10107d828062SThomas Gleixner  *
10117d828062SThomas Gleixner  * A irq_generic_chip can have several instances of irq_chip_type when
10127d828062SThomas Gleixner  * it requires different functions and register offsets for different
10137d828062SThomas Gleixner  * flow types.
10147d828062SThomas Gleixner  */
10157d828062SThomas Gleixner struct irq_chip_type {
10167d828062SThomas Gleixner 	struct irq_chip		chip;
10177d828062SThomas Gleixner 	struct irq_chip_regs	regs;
10187d828062SThomas Gleixner 	irq_flow_handler_t	handler;
10197d828062SThomas Gleixner 	u32			type;
1020899f0e66SGerlando Falauto 	u32			mask_cache_priv;
1021899f0e66SGerlando Falauto 	u32			*mask_cache;
10227d828062SThomas Gleixner };
10237d828062SThomas Gleixner 
10247d828062SThomas Gleixner /**
10257d828062SThomas Gleixner  * struct irq_chip_generic - Generic irq chip data structure
10267d828062SThomas Gleixner  * @lock:		Lock to protect register and cache data access
10277d828062SThomas Gleixner  * @reg_base:		Register base address (virtual)
10282b280376SKevin Cernekee  * @reg_readl:		Alternate I/O accessor (defaults to readl if NULL)
10292b280376SKevin Cernekee  * @reg_writel:		Alternate I/O accessor (defaults to writel if NULL)
1030be9b22b6SBrian Norris  * @suspend:		Function called from core code on suspend once per
1031be9b22b6SBrian Norris  *			chip; can be useful instead of irq_chip::suspend to
1032be9b22b6SBrian Norris  *			handle chip details even when no interrupts are in use
1033be9b22b6SBrian Norris  * @resume:		Function called from core code on resume once per chip;
1034be9b22b6SBrian Norris  *			can be useful instead of irq_chip::suspend to handle
1035be9b22b6SBrian Norris  *			chip details even when no interrupts are in use
10367d828062SThomas Gleixner  * @irq_base:		Interrupt base nr for this chip
10377d828062SThomas Gleixner  * @irq_cnt:		Number of interrupts handled by this chip
1038899f0e66SGerlando Falauto  * @mask_cache:		Cached mask register shared between all chip types
10397d828062SThomas Gleixner  * @wake_enabled:	Interrupt can wakeup from suspend
10407d828062SThomas Gleixner  * @wake_active:	Interrupt is marked as an wakeup from suspend source
10417d828062SThomas Gleixner  * @num_ct:		Number of available irq_chip_type instances (usually 1)
10427d828062SThomas Gleixner  * @private:		Private data for non generic chip callbacks
1043088f40b7SThomas Gleixner  * @installed:		bitfield to denote installed interrupts
1044e8bd834fSGrant Likely  * @unused:		bitfield to denote unused interrupts
1045088f40b7SThomas Gleixner  * @domain:		irq domain pointer
1046cfefd21eSThomas Gleixner  * @list:		List head for keeping track of instances
10477d828062SThomas Gleixner  * @chip_types:		Array of interrupt irq_chip_types
10487d828062SThomas Gleixner  *
10497d828062SThomas Gleixner  * Note, that irq_chip_generic can have multiple irq_chip_type
10507d828062SThomas Gleixner  * implementations which can be associated to a particular irq line of
10517d828062SThomas Gleixner  * an irq_chip_generic instance. That allows to share and protect
10527d828062SThomas Gleixner  * state in an irq_chip_generic instance when we need to implement
10537d828062SThomas Gleixner  * different flow mechanisms (level/edge) for it.
10547d828062SThomas Gleixner  */
10557d828062SThomas Gleixner struct irq_chip_generic {
10567d828062SThomas Gleixner 	raw_spinlock_t		lock;
10577d828062SThomas Gleixner 	void __iomem		*reg_base;
10582b280376SKevin Cernekee 	u32			(*reg_readl)(void __iomem *addr);
10592b280376SKevin Cernekee 	void			(*reg_writel)(u32 val, void __iomem *addr);
1060be9b22b6SBrian Norris 	void			(*suspend)(struct irq_chip_generic *gc);
1061be9b22b6SBrian Norris 	void			(*resume)(struct irq_chip_generic *gc);
10627d828062SThomas Gleixner 	unsigned int		irq_base;
10637d828062SThomas Gleixner 	unsigned int		irq_cnt;
10647d828062SThomas Gleixner 	u32			mask_cache;
10657d828062SThomas Gleixner 	u32			wake_enabled;
10667d828062SThomas Gleixner 	u32			wake_active;
10677d828062SThomas Gleixner 	unsigned int		num_ct;
10687d828062SThomas Gleixner 	void			*private;
1069088f40b7SThomas Gleixner 	unsigned long		installed;
1070e8bd834fSGrant Likely 	unsigned long		unused;
1071088f40b7SThomas Gleixner 	struct irq_domain	*domain;
1072cfefd21eSThomas Gleixner 	struct list_head	list;
10737856e9f1SGustavo A. R. Silva 	struct irq_chip_type	chip_types[];
10747d828062SThomas Gleixner };
10757d828062SThomas Gleixner 
10767d828062SThomas Gleixner /**
10777d828062SThomas Gleixner  * enum irq_gc_flags - Initialization flags for generic irq chips
10787d828062SThomas Gleixner  * @IRQ_GC_INIT_MASK_CACHE:	Initialize the mask_cache by reading mask reg
10797d828062SThomas Gleixner  * @IRQ_GC_INIT_NESTED_LOCK:	Set the lock class of the irqs to nested for
10807d828062SThomas Gleixner  *				irq chips which need to call irq_set_wake() on
10817d828062SThomas Gleixner  *				the parent irq. Usually GPIO implementations
1082af80b0feSGerlando Falauto  * @IRQ_GC_MASK_CACHE_PER_TYPE:	Mask cache is chip type private
1083966dc736SThomas Gleixner  * @IRQ_GC_NO_MASK:		Do not calculate irq_data->mask
1084b7905595SKevin Cernekee  * @IRQ_GC_BE_IO:		Use big-endian register accesses (default: LE)
10857d828062SThomas Gleixner  */
10867d828062SThomas Gleixner enum irq_gc_flags {
10877d828062SThomas Gleixner 	IRQ_GC_INIT_MASK_CACHE		= 1 << 0,
10887d828062SThomas Gleixner 	IRQ_GC_INIT_NESTED_LOCK		= 1 << 1,
1089af80b0feSGerlando Falauto 	IRQ_GC_MASK_CACHE_PER_TYPE	= 1 << 2,
1090966dc736SThomas Gleixner 	IRQ_GC_NO_MASK			= 1 << 3,
1091b7905595SKevin Cernekee 	IRQ_GC_BE_IO			= 1 << 4,
10927d828062SThomas Gleixner };
10937d828062SThomas Gleixner 
1094088f40b7SThomas Gleixner /*
1095088f40b7SThomas Gleixner  * struct irq_domain_chip_generic - Generic irq chip data structure for irq domains
1096088f40b7SThomas Gleixner  * @irqs_per_chip:	Number of interrupts per chip
1097088f40b7SThomas Gleixner  * @num_chips:		Number of chips
1098088f40b7SThomas Gleixner  * @irq_flags_to_set:	IRQ* flags to set on irq setup
1099088f40b7SThomas Gleixner  * @irq_flags_to_clear:	IRQ* flags to clear on irq setup
1100088f40b7SThomas Gleixner  * @gc_flags:		Generic chip specific setup flags
1101fea922eeSHerve Codina  * @exit:		Function called on each chip when they are destroyed.
1102088f40b7SThomas Gleixner  * @gc:			Array of pointers to generic interrupt chips
1103088f40b7SThomas Gleixner  */
1104088f40b7SThomas Gleixner struct irq_domain_chip_generic {
1105088f40b7SThomas Gleixner 	unsigned int		irqs_per_chip;
1106088f40b7SThomas Gleixner 	unsigned int		num_chips;
1107088f40b7SThomas Gleixner 	unsigned int		irq_flags_to_clear;
1108088f40b7SThomas Gleixner 	unsigned int		irq_flags_to_set;
1109088f40b7SThomas Gleixner 	enum irq_gc_flags	gc_flags;
1110fea922eeSHerve Codina 	void			(*exit)(struct irq_chip_generic *gc);
11117856e9f1SGustavo A. R. Silva 	struct irq_chip_generic	*gc[];
1112088f40b7SThomas Gleixner };
1113088f40b7SThomas Gleixner 
1114e25f553aSHerve Codina /**
1115e25f553aSHerve Codina  * struct irq_domain_chip_generic_info - Generic chip information structure
1116e25f553aSHerve Codina  * @name:		Name of the generic interrupt chip
1117e25f553aSHerve Codina  * @handler:		Interrupt handler used by the generic interrupt chip
1118e25f553aSHerve Codina  * @irqs_per_chip:	Number of interrupts each chip handles (max 32)
1119e25f553aSHerve Codina  * @num_ct:		Number of irq_chip_type instances associated with each
1120e25f553aSHerve Codina  *			chip
1121e25f553aSHerve Codina  * @irq_flags_to_clear:	IRQ_* bits to clear in the mapping function
1122e25f553aSHerve Codina  * @irq_flags_to_set:	IRQ_* bits to set in the mapping function
1123e25f553aSHerve Codina  * @gc_flags:		Generic chip specific setup flags
1124fea922eeSHerve Codina  * @init:		Function called on each chip when they are created.
1125fea922eeSHerve Codina  *			Allow to do some additional chip initialisation.
1126fea922eeSHerve Codina  * @exit:		Function called on each chip when they are destroyed.
1127fea922eeSHerve Codina  *			Allow to do some chip cleanup operation.
1128e25f553aSHerve Codina  */
1129e25f553aSHerve Codina struct irq_domain_chip_generic_info {
1130e25f553aSHerve Codina 	const char		*name;
1131e25f553aSHerve Codina 	irq_flow_handler_t	handler;
1132e25f553aSHerve Codina 	unsigned int		irqs_per_chip;
1133e25f553aSHerve Codina 	unsigned int		num_ct;
1134e25f553aSHerve Codina 	unsigned int		irq_flags_to_clear;
1135e25f553aSHerve Codina 	unsigned int		irq_flags_to_set;
1136e25f553aSHerve Codina 	enum irq_gc_flags	gc_flags;
1137fea922eeSHerve Codina 	int			(*init)(struct irq_chip_generic *gc);
1138fea922eeSHerve Codina 	void			(*exit)(struct irq_chip_generic *gc);
1139e25f553aSHerve Codina };
1140e25f553aSHerve Codina 
11417d828062SThomas Gleixner /* Generic chip callback functions */
11427d828062SThomas Gleixner void irq_gc_noop(struct irq_data *d);
11437d828062SThomas Gleixner void irq_gc_mask_disable_reg(struct irq_data *d);
11447d828062SThomas Gleixner void irq_gc_mask_set_bit(struct irq_data *d);
11457d828062SThomas Gleixner void irq_gc_mask_clr_bit(struct irq_data *d);
11467d828062SThomas Gleixner void irq_gc_unmask_enable_reg(struct irq_data *d);
1147659fb32dSSimon Guinot void irq_gc_ack_set_bit(struct irq_data *d);
1148659fb32dSSimon Guinot void irq_gc_ack_clr_bit(struct irq_data *d);
114920608924SDoug Berger void irq_gc_mask_disable_and_ack_set(struct irq_data *d);
11507d828062SThomas Gleixner void irq_gc_eoi(struct irq_data *d);
11517d828062SThomas Gleixner int irq_gc_set_wake(struct irq_data *d, unsigned int on);
11527d828062SThomas Gleixner 
11537d828062SThomas Gleixner /* Setup functions for irq_chip_generic */
1154a5152c8aSBoris BREZILLON int irq_map_generic_chip(struct irq_domain *d, unsigned int virq,
1155a5152c8aSBoris BREZILLON 			 irq_hw_number_t hw_irq);
1156d319a299SJianmin Lv void irq_unmap_generic_chip(struct irq_domain *d, unsigned int virq);
11577d828062SThomas Gleixner struct irq_chip_generic *
11587d828062SThomas Gleixner irq_alloc_generic_chip(const char *name, int nr_ct, unsigned int irq_base,
11597d828062SThomas Gleixner 		       void __iomem *reg_base, irq_flow_handler_t handler);
11607d828062SThomas Gleixner void irq_setup_generic_chip(struct irq_chip_generic *gc, u32 msk,
11617d828062SThomas Gleixner 			    enum irq_gc_flags flags, unsigned int clr,
11627d828062SThomas Gleixner 			    unsigned int set);
11637d828062SThomas Gleixner int irq_setup_alt_chip(struct irq_data *d, unsigned int type);
1164cfefd21eSThomas Gleixner void irq_remove_generic_chip(struct irq_chip_generic *gc, u32 msk,
1165cfefd21eSThomas Gleixner 			     unsigned int clr, unsigned int set);
11667d828062SThomas Gleixner 
11671c3e3630SBartosz Golaszewski struct irq_chip_generic *
11681c3e3630SBartosz Golaszewski devm_irq_alloc_generic_chip(struct device *dev, const char *name, int num_ct,
11691c3e3630SBartosz Golaszewski 			    unsigned int irq_base, void __iomem *reg_base,
11701c3e3630SBartosz Golaszewski 			    irq_flow_handler_t handler);
117130fd8fc5SBartosz Golaszewski int devm_irq_setup_generic_chip(struct device *dev, struct irq_chip_generic *gc,
117230fd8fc5SBartosz Golaszewski 				u32 msk, enum irq_gc_flags flags,
117330fd8fc5SBartosz Golaszewski 				unsigned int clr, unsigned int set);
11741c3e3630SBartosz Golaszewski 
1175088f40b7SThomas Gleixner struct irq_chip_generic *irq_get_domain_generic_chip(struct irq_domain *d, unsigned int hw_irq);
1176f88eecfeSSebastian Frias 
11778cb2dbf9SThomas Gleixner #ifdef CONFIG_GENERIC_IRQ_CHIP
1178e25f553aSHerve Codina int irq_domain_alloc_generic_chips(struct irq_domain *d,
1179e25f553aSHerve Codina 				   const struct irq_domain_chip_generic_info *info);
1180e25f553aSHerve Codina void irq_domain_remove_generic_chips(struct irq_domain *d);
11818cb2dbf9SThomas Gleixner #else
11828cb2dbf9SThomas Gleixner static inline int
irq_domain_alloc_generic_chips(struct irq_domain * d,const struct irq_domain_chip_generic_info * info)11838cb2dbf9SThomas Gleixner irq_domain_alloc_generic_chips(struct irq_domain *d,
11848cb2dbf9SThomas Gleixner 			       const struct irq_domain_chip_generic_info *info)
11858cb2dbf9SThomas Gleixner {
11868cb2dbf9SThomas Gleixner 	return -EINVAL;
11878cb2dbf9SThomas Gleixner }
irq_domain_remove_generic_chips(struct irq_domain * d)11888cb2dbf9SThomas Gleixner static inline void irq_domain_remove_generic_chips(struct irq_domain *d) { }
11898cb2dbf9SThomas Gleixner #endif /* CONFIG_GENERIC_IRQ_CHIP */
1190e25f553aSHerve Codina 
1191f88eecfeSSebastian Frias int __irq_alloc_domain_generic_chips(struct irq_domain *d, int irqs_per_chip,
1192088f40b7SThomas Gleixner 				     int num_ct, const char *name,
1193088f40b7SThomas Gleixner 				     irq_flow_handler_t handler,
1194088f40b7SThomas Gleixner 				     unsigned int clr, unsigned int set,
1195088f40b7SThomas Gleixner 				     enum irq_gc_flags flags);
1196088f40b7SThomas Gleixner 
1197f88eecfeSSebastian Frias #define irq_alloc_domain_generic_chips(d, irqs_per_chip, num_ct, name,	\
1198f88eecfeSSebastian Frias 				       handler,	clr, set, flags)	\
1199f88eecfeSSebastian Frias ({									\
1200f88eecfeSSebastian Frias 	MAYBE_BUILD_BUG_ON(irqs_per_chip > 32);				\
1201f88eecfeSSebastian Frias 	__irq_alloc_domain_generic_chips(d, irqs_per_chip, num_ct, name,\
1202f88eecfeSSebastian Frias 					 handler, clr, set, flags);	\
1203f88eecfeSSebastian Frias })
1204088f40b7SThomas Gleixner 
irq_free_generic_chip(struct irq_chip_generic * gc)1205707188f5SBartosz Golaszewski static inline void irq_free_generic_chip(struct irq_chip_generic *gc)
1206707188f5SBartosz Golaszewski {
1207707188f5SBartosz Golaszewski 	kfree(gc);
1208707188f5SBartosz Golaszewski }
1209707188f5SBartosz Golaszewski 
irq_destroy_generic_chip(struct irq_chip_generic * gc,u32 msk,unsigned int clr,unsigned int set)121032bb6cbbSBartosz Golaszewski static inline void irq_destroy_generic_chip(struct irq_chip_generic *gc,
121132bb6cbbSBartosz Golaszewski 					    u32 msk, unsigned int clr,
121232bb6cbbSBartosz Golaszewski 					    unsigned int set)
121332bb6cbbSBartosz Golaszewski {
121432bb6cbbSBartosz Golaszewski 	irq_remove_generic_chip(gc, msk, clr, set);
121532bb6cbbSBartosz Golaszewski 	irq_free_generic_chip(gc);
121632bb6cbbSBartosz Golaszewski }
121732bb6cbbSBartosz Golaszewski 
irq_data_get_chip_type(struct irq_data * d)12187d828062SThomas Gleixner static inline struct irq_chip_type *irq_data_get_chip_type(struct irq_data *d)
12197d828062SThomas Gleixner {
12207d828062SThomas Gleixner 	return container_of(d->chip, struct irq_chip_type, chip);
12217d828062SThomas Gleixner }
12227d828062SThomas Gleixner 
12237d828062SThomas Gleixner #define IRQ_MSK(n) (u32)((n) < 32 ? ((1 << (n)) - 1) : UINT_MAX)
12247d828062SThomas Gleixner 
12257d828062SThomas Gleixner #ifdef CONFIG_SMP
irq_gc_lock(struct irq_chip_generic * gc)12267d828062SThomas Gleixner static inline void irq_gc_lock(struct irq_chip_generic *gc)
12277d828062SThomas Gleixner {
12287d828062SThomas Gleixner 	raw_spin_lock(&gc->lock);
12297d828062SThomas Gleixner }
12307d828062SThomas Gleixner 
irq_gc_unlock(struct irq_chip_generic * gc)12317d828062SThomas Gleixner static inline void irq_gc_unlock(struct irq_chip_generic *gc)
12327d828062SThomas Gleixner {
12337d828062SThomas Gleixner 	raw_spin_unlock(&gc->lock);
12347d828062SThomas Gleixner }
12357d828062SThomas Gleixner #else
irq_gc_lock(struct irq_chip_generic * gc)12367d828062SThomas Gleixner static inline void irq_gc_lock(struct irq_chip_generic *gc) { }
irq_gc_unlock(struct irq_chip_generic * gc)12377d828062SThomas Gleixner static inline void irq_gc_unlock(struct irq_chip_generic *gc) { }
12387d828062SThomas Gleixner #endif
12397d828062SThomas Gleixner 
1240ebf9ff75SBoris Brezillon /*
1241ebf9ff75SBoris Brezillon  * The irqsave variants are for usage in non interrupt code. Do not use
1242ebf9ff75SBoris Brezillon  * them in irq_chip callbacks. Use irq_gc_lock() instead.
1243ebf9ff75SBoris Brezillon  */
1244ebf9ff75SBoris Brezillon #define irq_gc_lock_irqsave(gc, flags)	\
1245ebf9ff75SBoris Brezillon 	raw_spin_lock_irqsave(&(gc)->lock, flags)
1246ebf9ff75SBoris Brezillon 
1247ebf9ff75SBoris Brezillon #define irq_gc_unlock_irqrestore(gc, flags)	\
1248ebf9ff75SBoris Brezillon 	raw_spin_unlock_irqrestore(&(gc)->lock, flags)
1249ebf9ff75SBoris Brezillon 
irq_reg_writel(struct irq_chip_generic * gc,u32 val,int reg_offset)1250332fd7c4SKevin Cernekee static inline void irq_reg_writel(struct irq_chip_generic *gc,
1251332fd7c4SKevin Cernekee 				  u32 val, int reg_offset)
1252332fd7c4SKevin Cernekee {
12532b280376SKevin Cernekee 	if (gc->reg_writel)
12542b280376SKevin Cernekee 		gc->reg_writel(val, gc->reg_base + reg_offset);
12552b280376SKevin Cernekee 	else
1256332fd7c4SKevin Cernekee 		writel(val, gc->reg_base + reg_offset);
1257332fd7c4SKevin Cernekee }
1258332fd7c4SKevin Cernekee 
irq_reg_readl(struct irq_chip_generic * gc,int reg_offset)1259332fd7c4SKevin Cernekee static inline u32 irq_reg_readl(struct irq_chip_generic *gc,
1260332fd7c4SKevin Cernekee 				int reg_offset)
1261332fd7c4SKevin Cernekee {
12622b280376SKevin Cernekee 	if (gc->reg_readl)
12632b280376SKevin Cernekee 		return gc->reg_readl(gc->reg_base + reg_offset);
12642b280376SKevin Cernekee 	else
1265332fd7c4SKevin Cernekee 		return readl(gc->reg_base + reg_offset);
1266332fd7c4SKevin Cernekee }
1267332fd7c4SKevin Cernekee 
12682f75d9e1SThomas Gleixner struct irq_matrix;
12692f75d9e1SThomas Gleixner struct irq_matrix *irq_alloc_matrix(unsigned int matrix_bits,
12702f75d9e1SThomas Gleixner 				    unsigned int alloc_start,
12712f75d9e1SThomas Gleixner 				    unsigned int alloc_end);
12722f75d9e1SThomas Gleixner void irq_matrix_online(struct irq_matrix *m);
12732f75d9e1SThomas Gleixner void irq_matrix_offline(struct irq_matrix *m);
12742f75d9e1SThomas Gleixner void irq_matrix_assign_system(struct irq_matrix *m, unsigned int bit, bool replace);
12752f75d9e1SThomas Gleixner int irq_matrix_reserve_managed(struct irq_matrix *m, const struct cpumask *msk);
12762f75d9e1SThomas Gleixner void irq_matrix_remove_managed(struct irq_matrix *m, const struct cpumask *msk);
127776f99ae5SDou Liyang int irq_matrix_alloc_managed(struct irq_matrix *m, const struct cpumask *msk,
127876f99ae5SDou Liyang 				unsigned int *mapped_cpu);
12792f75d9e1SThomas Gleixner void irq_matrix_reserve(struct irq_matrix *m);
12802f75d9e1SThomas Gleixner void irq_matrix_remove_reserved(struct irq_matrix *m);
12812f75d9e1SThomas Gleixner int irq_matrix_alloc(struct irq_matrix *m, const struct cpumask *msk,
12822f75d9e1SThomas Gleixner 		     bool reserved, unsigned int *mapped_cpu);
12832f75d9e1SThomas Gleixner void irq_matrix_free(struct irq_matrix *m, unsigned int cpu,
12842f75d9e1SThomas Gleixner 		     unsigned int bit, bool managed);
12852f75d9e1SThomas Gleixner void irq_matrix_assign(struct irq_matrix *m, unsigned int bit);
12862f75d9e1SThomas Gleixner unsigned int irq_matrix_available(struct irq_matrix *m, bool cpudown);
12872f75d9e1SThomas Gleixner unsigned int irq_matrix_allocated(struct irq_matrix *m);
12882f75d9e1SThomas Gleixner unsigned int irq_matrix_reserved(struct irq_matrix *m);
12892f75d9e1SThomas Gleixner void irq_matrix_debug_show(struct seq_file *sf, struct irq_matrix *m, int ind);
12902f75d9e1SThomas Gleixner 
1291d17bf24eSQais Yousef /* Contrary to Linux irqs, for hardware irqs the irq number 0 is valid */
1292d17bf24eSQais Yousef #define INVALID_HWIRQ	(~0UL)
1293f9bce791SQais Yousef irq_hw_number_t ipi_get_hwirq(unsigned int irq, unsigned int cpu);
12943b8e29a8SQais Yousef int __ipi_send_single(struct irq_desc *desc, unsigned int cpu);
12953b8e29a8SQais Yousef int __ipi_send_mask(struct irq_desc *desc, const struct cpumask *dest);
12963b8e29a8SQais Yousef int ipi_send_single(unsigned int virq, unsigned int cpu);
12973b8e29a8SQais Yousef int ipi_send_mask(unsigned int virq, const struct cpumask *dest);
1298d17bf24eSQais Yousef 
1299835a486cSAnup Patel void ipi_mux_process(void);
1300835a486cSAnup Patel int ipi_mux_create(unsigned int nr_ipi, void (*mux_send)(unsigned int cpu));
1301835a486cSAnup Patel 
1302caacdbf4SPalmer Dabbelt #ifdef CONFIG_GENERIC_IRQ_MULTI_HANDLER
1303caacdbf4SPalmer Dabbelt /*
1304caacdbf4SPalmer Dabbelt  * Registers a generic IRQ handling function as the top-level IRQ handler in
1305caacdbf4SPalmer Dabbelt  * the system, which is generally the first C code called from an assembly
1306caacdbf4SPalmer Dabbelt  * architecture-specific interrupt handler.
1307caacdbf4SPalmer Dabbelt  *
1308caacdbf4SPalmer Dabbelt  * Returns 0 on success, or -EBUSY if an IRQ handler has already been
1309caacdbf4SPalmer Dabbelt  * registered.
1310caacdbf4SPalmer Dabbelt  */
1311caacdbf4SPalmer Dabbelt int __init set_handle_irq(void (*handle_irq)(struct pt_regs *));
1312caacdbf4SPalmer Dabbelt 
1313caacdbf4SPalmer Dabbelt /*
1314caacdbf4SPalmer Dabbelt  * Allows interrupt handlers to find the irqchip that's been registered as the
1315caacdbf4SPalmer Dabbelt  * top-level IRQ handler.
1316caacdbf4SPalmer Dabbelt  */
1317caacdbf4SPalmer Dabbelt extern void (*handle_arch_irq)(struct pt_regs *) __ro_after_init;
1318a1b09501SMark Rutland asmlinkage void generic_handle_arch_irq(struct pt_regs *regs);
1319ea0c80d1SZhen Lei #else
1320b0b8b689SMarc Zyngier #ifndef set_handle_irq
1321ea0c80d1SZhen Lei #define set_handle_irq(handle_irq)		\
1322ea0c80d1SZhen Lei 	do {					\
1323ea0c80d1SZhen Lei 		(void)handle_irq;		\
1324ea0c80d1SZhen Lei 		WARN_ON(1);			\
1325ea0c80d1SZhen Lei 	} while (0)
1326caacdbf4SPalmer Dabbelt #endif
1327b0b8b689SMarc Zyngier #endif
1328caacdbf4SPalmer Dabbelt 
132906fcb0c6SIngo Molnar #endif /* _LINUX_IRQ_H */
1330