xref: /openbmc/linux/include/linux/irq.h (revision 119f7373)
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)
675d4d8fc9SThomas Gleixner  * IRQ_MOVE_PCNTXT		- Interrupt can be migrated from process context
6892068d17SMika Westerberg  * IRQ_NESTED_THREAD		- Interrupt nests into another thread
6931d9d9b6SMarc Zyngier  * IRQ_PER_CPU_DEVID		- Dev_id is a per-cpu variable
70b39898cdSThomas Gleixner  * IRQ_IS_POLLED		- Always polled by another interrupt. Exclude
71b39898cdSThomas Gleixner  *				  it from the spurious interrupt detection
72b39898cdSThomas Gleixner  *				  mechanism and from core side polling.
73e9849777SThomas Gleixner  * IRQ_DISABLE_UNLAZY		- Disable lazy irq disable
7483cfac95SMarc Zyngier  * IRQ_HIDDEN			- Don't show up in /proc/interrupts
75c2b1063eSThomas Gleixner  * IRQ_NO_DEBUG			- Exclude from note_interrupt() debugging
761da177e4SLinus Torvalds  */
775d4d8fc9SThomas Gleixner enum {
785d4d8fc9SThomas Gleixner 	IRQ_TYPE_NONE		= 0x00000000,
795d4d8fc9SThomas Gleixner 	IRQ_TYPE_EDGE_RISING	= 0x00000001,
805d4d8fc9SThomas Gleixner 	IRQ_TYPE_EDGE_FALLING	= 0x00000002,
815d4d8fc9SThomas Gleixner 	IRQ_TYPE_EDGE_BOTH	= (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING),
825d4d8fc9SThomas Gleixner 	IRQ_TYPE_LEVEL_HIGH	= 0x00000004,
835d4d8fc9SThomas Gleixner 	IRQ_TYPE_LEVEL_LOW	= 0x00000008,
845d4d8fc9SThomas Gleixner 	IRQ_TYPE_LEVEL_MASK	= (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH),
855d4d8fc9SThomas Gleixner 	IRQ_TYPE_SENSE_MASK	= 0x0000000f,
863fca40c7SBenjamin Herrenschmidt 	IRQ_TYPE_DEFAULT	= IRQ_TYPE_SENSE_MASK,
87876dbd4cSThomas Gleixner 
885d4d8fc9SThomas Gleixner 	IRQ_TYPE_PROBE		= 0x00000010,
896e213616SThomas Gleixner 
905d4d8fc9SThomas Gleixner 	IRQ_LEVEL		= (1 <<  8),
915d4d8fc9SThomas Gleixner 	IRQ_PER_CPU		= (1 <<  9),
925d4d8fc9SThomas Gleixner 	IRQ_NOPROBE		= (1 << 10),
935d4d8fc9SThomas Gleixner 	IRQ_NOREQUEST		= (1 << 11),
945d4d8fc9SThomas Gleixner 	IRQ_NOAUTOEN		= (1 << 12),
955d4d8fc9SThomas Gleixner 	IRQ_NO_BALANCING	= (1 << 13),
965d4d8fc9SThomas Gleixner 	IRQ_MOVE_PCNTXT		= (1 << 14),
975d4d8fc9SThomas Gleixner 	IRQ_NESTED_THREAD	= (1 << 15),
987f1b1244SPaul Mundt 	IRQ_NOTHREAD		= (1 << 16),
9931d9d9b6SMarc Zyngier 	IRQ_PER_CPU_DEVID	= (1 << 17),
100b39898cdSThomas Gleixner 	IRQ_IS_POLLED		= (1 << 18),
101e9849777SThomas Gleixner 	IRQ_DISABLE_UNLAZY	= (1 << 19),
10283cfac95SMarc Zyngier 	IRQ_HIDDEN		= (1 << 20),
103c2b1063eSThomas Gleixner 	IRQ_NO_DEBUG		= (1 << 21),
1045d4d8fc9SThomas Gleixner };
105950f4427SThomas Gleixner 
10644247184SThomas Gleixner #define IRQF_MODIFY_MASK	\
10744247184SThomas Gleixner 	(IRQ_TYPE_SENSE_MASK | IRQ_NOPROBE | IRQ_NOREQUEST | \
108872434d6SThomas Gleixner 	 IRQ_NOAUTOEN | IRQ_MOVE_PCNTXT | IRQ_LEVEL | IRQ_NO_BALANCING | \
109b39898cdSThomas Gleixner 	 IRQ_PER_CPU | IRQ_NESTED_THREAD | IRQ_NOTHREAD | IRQ_PER_CPU_DEVID | \
11083cfac95SMarc Zyngier 	 IRQ_IS_POLLED | IRQ_DISABLE_UNLAZY | IRQ_HIDDEN)
11144247184SThomas Gleixner 
112950f4427SThomas Gleixner #define IRQ_NO_BALANCING_MASK	(IRQ_PER_CPU | IRQ_NO_BALANCING)
1131da177e4SLinus Torvalds 
1143b8249e7SThomas Gleixner /*
1153b8249e7SThomas Gleixner  * Return value for chip->irq_set_affinity()
1163b8249e7SThomas Gleixner  *
1179df872faSJiang Liu  * IRQ_SET_MASK_OK	- OK, core updates irq_common_data.affinity
1189df872faSJiang Liu  * IRQ_SET_MASK_NOCPY	- OK, chip did update irq_common_data.affinity
1192cb62547SJiang Liu  * IRQ_SET_MASK_OK_DONE	- Same as IRQ_SET_MASK_OK for core. Special code to
1202cb62547SJiang Liu  *			  support stacked irqchips, which indicates skipping
121a359f757SIngo Molnar  *			  all descendant irqchips.
1223b8249e7SThomas Gleixner  */
1233b8249e7SThomas Gleixner enum {
1243b8249e7SThomas Gleixner 	IRQ_SET_MASK_OK = 0,
1253b8249e7SThomas Gleixner 	IRQ_SET_MASK_OK_NOCOPY,
1262cb62547SJiang Liu 	IRQ_SET_MASK_OK_DONE,
1273b8249e7SThomas Gleixner };
1283b8249e7SThomas Gleixner 
1295b912c10SEric W. Biederman struct msi_desc;
13008a543adSGrant Likely struct irq_domain;
1316a6de9efSThomas Gleixner 
1328fee5c36SIngo Molnar /**
1330d0b4c86SJiang Liu  * struct irq_common_data - per irq data shared by all irqchips
1340d0b4c86SJiang Liu  * @state_use_accessors: status information for irq chip functions.
1350d0b4c86SJiang Liu  *			Use accessor functions to deal with it
136449e9caeSJiang Liu  * @node:		node index useful for balancing
137af7080e0SJiang Liu  * @handler_data:	per-IRQ data for the irq_chip methods
138955bfe59SQais Yousef  * @affinity:		IRQ affinity on SMP. If this is an IPI
139955bfe59SQais Yousef  *			related irq, then this is the mask of the
140955bfe59SQais Yousef  *			CPUs to which an IPI can be sent.
1410d3f5425SThomas Gleixner  * @effective_affinity:	The effective IRQ affinity on SMP as some irq
1420d3f5425SThomas Gleixner  *			chips do not allow multi CPU destinations.
1430d3f5425SThomas Gleixner  *			A subset of @affinity.
144b237721cSJiang Liu  * @msi_desc:		MSI descriptor
145f256c9a0SQais Yousef  * @ipi_offset:		Offset of first IPI target cpu in @affinity. Optional.
1460d0b4c86SJiang Liu  */
1470d0b4c86SJiang Liu struct irq_common_data {
148b354286eSBoqun Feng 	unsigned int		__private state_use_accessors;
149449e9caeSJiang Liu #ifdef CONFIG_NUMA
150449e9caeSJiang Liu 	unsigned int		node;
151449e9caeSJiang Liu #endif
152af7080e0SJiang Liu 	void			*handler_data;
153b237721cSJiang Liu 	struct msi_desc		*msi_desc;
154aa081358SSamuel Holland #ifdef CONFIG_SMP
1559df872faSJiang Liu 	cpumask_var_t		affinity;
156aa081358SSamuel Holland #endif
1570d3f5425SThomas Gleixner #ifdef CONFIG_GENERIC_IRQ_EFFECTIVE_AFF_MASK
1580d3f5425SThomas Gleixner 	cpumask_var_t		effective_affinity;
1590d3f5425SThomas Gleixner #endif
160f256c9a0SQais Yousef #ifdef CONFIG_GENERIC_IRQ_IPI
161f256c9a0SQais Yousef 	unsigned int		ipi_offset;
162f256c9a0SQais Yousef #endif
1630d0b4c86SJiang Liu };
1640d0b4c86SJiang Liu 
1650d0b4c86SJiang Liu /**
1660d0b4c86SJiang Liu  * struct irq_data - per irq chip data passed down to chip functions
167966dc736SThomas Gleixner  * @mask:		precomputed bitmask for accessing the chip registers
168ff7dcd44SThomas Gleixner  * @irq:		interrupt number
16908a543adSGrant Likely  * @hwirq:		hardware interrupt number, local to the interrupt domain
1700d0b4c86SJiang Liu  * @common:		point to data shared by all irqchips
171ff7dcd44SThomas Gleixner  * @chip:		low level interrupt hardware access
17208a543adSGrant Likely  * @domain:		Interrupt translation domain; responsible for mapping
17308a543adSGrant Likely  *			between hwirq number and linux irq number.
174f8264e34SJiang Liu  * @parent_data:	pointer to parent struct irq_data to support hierarchy
175f8264e34SJiang Liu  *			irq_domain
176ff7dcd44SThomas Gleixner  * @chip_data:		platform-specific per-chip private data for the chip
177ff7dcd44SThomas Gleixner  *			methods, to allow shared chip implementations
178ff7dcd44SThomas Gleixner  */
179ff7dcd44SThomas Gleixner struct irq_data {
180966dc736SThomas Gleixner 	u32			mask;
181ff7dcd44SThomas Gleixner 	unsigned int		irq;
18208a543adSGrant Likely 	unsigned long		hwirq;
1830d0b4c86SJiang Liu 	struct irq_common_data	*common;
184ff7dcd44SThomas Gleixner 	struct irq_chip		*chip;
18508a543adSGrant Likely 	struct irq_domain	*domain;
186f8264e34SJiang Liu #ifdef	CONFIG_IRQ_DOMAIN_HIERARCHY
187f8264e34SJiang Liu 	struct irq_data		*parent_data;
188f8264e34SJiang Liu #endif
189ff7dcd44SThomas Gleixner 	void			*chip_data;
190ff7dcd44SThomas Gleixner };
191ff7dcd44SThomas Gleixner 
192f230b6d5SThomas Gleixner /*
1930d0b4c86SJiang Liu  * Bit masks for irq_common_data.state_use_accessors
194f230b6d5SThomas Gleixner  *
195876dbd4cSThomas Gleixner  * IRQD_TRIGGER_MASK		- Mask for the trigger type bits
196f230b6d5SThomas Gleixner  * IRQD_SETAFFINITY_PENDING	- Affinity setting is pending
19708d85f3eSMarc Zyngier  * IRQD_ACTIVATED		- Interrupt has already been activated
198a005677bSThomas Gleixner  * IRQD_NO_BALANCING		- Balancing disabled for this IRQ
199a005677bSThomas Gleixner  * IRQD_PER_CPU			- Interrupt is per cpu
2002bdd1055SThomas Gleixner  * IRQD_AFFINITY_SET		- Interrupt affinity was set
201876dbd4cSThomas Gleixner  * IRQD_LEVEL			- Interrupt is level triggered
2027f94226fSThomas Gleixner  * IRQD_WAKEUP_STATE		- Interrupt is configured for wakeup
2037f94226fSThomas Gleixner  *				  from suspend
204551417afSPeter Xu  * IRQD_MOVE_PCNTXT		- Interrupt can be moved in process
205e1ef8241SThomas Gleixner  *				  context
20632f4125eSThomas Gleixner  * IRQD_IRQ_DISABLED		- Disabled state of the interrupt
20732f4125eSThomas Gleixner  * IRQD_IRQ_MASKED		- Masked state of the interrupt
20832f4125eSThomas Gleixner  * IRQD_IRQ_INPROGRESS		- In progress state of the interrupt
209b76f1674SThomas Gleixner  * IRQD_WAKEUP_ARMED		- Wakeup mode armed
210fc569712SThomas Gleixner  * IRQD_FORWARDED_TO_VCPU	- The interrupt is forwarded to a VCPU
2119c255583SThomas Gleixner  * IRQD_AFFINITY_MANAGED	- Affinity is auto-managed by the kernel
2121bb04016SThomas Gleixner  * IRQD_IRQ_STARTED		- Startup state of the interrupt
21354fdf6a0SThomas Gleixner  * IRQD_MANAGED_SHUTDOWN	- Interrupt was shutdown due to empty affinity
21454fdf6a0SThomas Gleixner  *				  mask. Applies only to affinity managed irqs.
215d52dd441SThomas Gleixner  * IRQD_SINGLE_TARGET		- IRQ allows only a single affinity target
2164f8413a3SMarc Zyngier  * IRQD_DEFAULT_TRIGGER_SET	- Expected trigger already been set
21769790ba9SThomas Gleixner  * IRQD_CAN_RESERVE		- Can use reservation mode
218c16816acSThomas Gleixner  * IRQD_HANDLE_ENFORCE_IRQCTX	- Enforce that handle_irq_*() is only invoked
219c16816acSThomas Gleixner  *				  from actual interrupt context.
220f0c7bacaSThomas Gleixner  * IRQD_AFFINITY_ON_ACTIVATE	- Affinity is set on activation. Don't call
221f0c7bacaSThomas Gleixner  *				  irq_chip::irq_set_affinity() when deactivated.
22290428a8eSMaulik Shah  * IRQD_IRQ_ENABLED_ON_SUSPEND	- Interrupt is enabled on suspend by irq pm if
22390428a8eSMaulik Shah  *				  irqchip have flag IRQCHIP_ENABLE_WAKEUP_ON_SUSPEND set.
2249c15eeb5SJames Gowans  * IRQD_RESEND_WHEN_IN_PROGRESS	- Interrupt may fire when already in progress in which
2259c15eeb5SJames Gowans  *				  case it must be resent at the next available opportunity.
226f230b6d5SThomas Gleixner  */
227f230b6d5SThomas Gleixner enum {
228876dbd4cSThomas Gleixner 	IRQD_TRIGGER_MASK		= 0xf,
2290cfb4a1aSMarc Zyngier 	IRQD_SETAFFINITY_PENDING	= BIT(8),
2300cfb4a1aSMarc Zyngier 	IRQD_ACTIVATED			= BIT(9),
2310cfb4a1aSMarc Zyngier 	IRQD_NO_BALANCING		= BIT(10),
2320cfb4a1aSMarc Zyngier 	IRQD_PER_CPU			= BIT(11),
2330cfb4a1aSMarc Zyngier 	IRQD_AFFINITY_SET		= BIT(12),
2340cfb4a1aSMarc Zyngier 	IRQD_LEVEL			= BIT(13),
2350cfb4a1aSMarc Zyngier 	IRQD_WAKEUP_STATE		= BIT(14),
2360cfb4a1aSMarc Zyngier 	IRQD_MOVE_PCNTXT		= BIT(15),
2370cfb4a1aSMarc Zyngier 	IRQD_IRQ_DISABLED		= BIT(16),
2380cfb4a1aSMarc Zyngier 	IRQD_IRQ_MASKED			= BIT(17),
2390cfb4a1aSMarc Zyngier 	IRQD_IRQ_INPROGRESS		= BIT(18),
2400cfb4a1aSMarc Zyngier 	IRQD_WAKEUP_ARMED		= BIT(19),
2410cfb4a1aSMarc Zyngier 	IRQD_FORWARDED_TO_VCPU		= BIT(20),
2420cfb4a1aSMarc Zyngier 	IRQD_AFFINITY_MANAGED		= BIT(21),
2430cfb4a1aSMarc Zyngier 	IRQD_IRQ_STARTED		= BIT(22),
2440cfb4a1aSMarc Zyngier 	IRQD_MANAGED_SHUTDOWN		= BIT(23),
2450cfb4a1aSMarc Zyngier 	IRQD_SINGLE_TARGET		= BIT(24),
2460cfb4a1aSMarc Zyngier 	IRQD_DEFAULT_TRIGGER_SET	= BIT(25),
2470cfb4a1aSMarc Zyngier 	IRQD_CAN_RESERVE		= BIT(26),
248*119f7373SKoichiro Den 	IRQD_HANDLE_ENFORCE_IRQCTX	= BIT(27),
249*119f7373SKoichiro Den 	IRQD_AFFINITY_ON_ACTIVATE	= BIT(28),
250*119f7373SKoichiro Den 	IRQD_IRQ_ENABLED_ON_SUSPEND	= BIT(29),
251*119f7373SKoichiro Den 	IRQD_RESEND_WHEN_IN_PROGRESS    = BIT(30),
252f230b6d5SThomas Gleixner };
253f230b6d5SThomas Gleixner 
254b354286eSBoqun Feng #define __irqd_to_state(d) ACCESS_PRIVATE((d)->common, state_use_accessors)
2550d0b4c86SJiang Liu 
irqd_is_setaffinity_pending(struct irq_data * d)256f230b6d5SThomas Gleixner static inline bool irqd_is_setaffinity_pending(struct irq_data *d)
257f230b6d5SThomas Gleixner {
2580d0b4c86SJiang Liu 	return __irqd_to_state(d) & IRQD_SETAFFINITY_PENDING;
259f230b6d5SThomas Gleixner }
260f230b6d5SThomas Gleixner 
irqd_is_per_cpu(struct irq_data * d)261a005677bSThomas Gleixner static inline bool irqd_is_per_cpu(struct irq_data *d)
262a005677bSThomas Gleixner {
2630d0b4c86SJiang Liu 	return __irqd_to_state(d) & IRQD_PER_CPU;
264a005677bSThomas Gleixner }
265a005677bSThomas Gleixner 
irqd_can_balance(struct irq_data * d)266a005677bSThomas Gleixner static inline bool irqd_can_balance(struct irq_data *d)
267a005677bSThomas Gleixner {
2680d0b4c86SJiang Liu 	return !(__irqd_to_state(d) & (IRQD_PER_CPU | IRQD_NO_BALANCING));
269a005677bSThomas Gleixner }
270a005677bSThomas Gleixner 
irqd_affinity_was_set(struct irq_data * d)2712bdd1055SThomas Gleixner static inline bool irqd_affinity_was_set(struct irq_data *d)
2722bdd1055SThomas Gleixner {
2730d0b4c86SJiang Liu 	return __irqd_to_state(d) & IRQD_AFFINITY_SET;
2742bdd1055SThomas Gleixner }
2752bdd1055SThomas Gleixner 
irqd_mark_affinity_was_set(struct irq_data * d)276ee38c04bSThomas Gleixner static inline void irqd_mark_affinity_was_set(struct irq_data *d)
277ee38c04bSThomas Gleixner {
2780d0b4c86SJiang Liu 	__irqd_to_state(d) |= IRQD_AFFINITY_SET;
279ee38c04bSThomas Gleixner }
280ee38c04bSThomas Gleixner 
irqd_trigger_type_was_set(struct irq_data * d)2814f8413a3SMarc Zyngier static inline bool irqd_trigger_type_was_set(struct irq_data *d)
2824f8413a3SMarc Zyngier {
2834f8413a3SMarc Zyngier 	return __irqd_to_state(d) & IRQD_DEFAULT_TRIGGER_SET;
2844f8413a3SMarc Zyngier }
2854f8413a3SMarc Zyngier 
irqd_get_trigger_type(struct irq_data * d)286876dbd4cSThomas Gleixner static inline u32 irqd_get_trigger_type(struct irq_data *d)
287876dbd4cSThomas Gleixner {
2880d0b4c86SJiang Liu 	return __irqd_to_state(d) & IRQD_TRIGGER_MASK;
289876dbd4cSThomas Gleixner }
290876dbd4cSThomas Gleixner 
291876dbd4cSThomas Gleixner /*
2924f8413a3SMarc Zyngier  * Must only be called inside irq_chip.irq_set_type() functions or
2934f8413a3SMarc Zyngier  * from the DT/ACPI setup code.
294876dbd4cSThomas Gleixner  */
irqd_set_trigger_type(struct irq_data * d,u32 type)295876dbd4cSThomas Gleixner static inline void irqd_set_trigger_type(struct irq_data *d, u32 type)
296876dbd4cSThomas Gleixner {
2970d0b4c86SJiang Liu 	__irqd_to_state(d) &= ~IRQD_TRIGGER_MASK;
2980d0b4c86SJiang Liu 	__irqd_to_state(d) |= type & IRQD_TRIGGER_MASK;
2994f8413a3SMarc Zyngier 	__irqd_to_state(d) |= IRQD_DEFAULT_TRIGGER_SET;
300876dbd4cSThomas Gleixner }
301876dbd4cSThomas Gleixner 
irqd_is_level_type(struct irq_data * d)302876dbd4cSThomas Gleixner static inline bool irqd_is_level_type(struct irq_data *d)
303876dbd4cSThomas Gleixner {
3040d0b4c86SJiang Liu 	return __irqd_to_state(d) & IRQD_LEVEL;
305876dbd4cSThomas Gleixner }
306876dbd4cSThomas Gleixner 
307d52dd441SThomas Gleixner /*
308d52dd441SThomas Gleixner  * Must only be called of irqchip.irq_set_affinity() or low level
309a359f757SIngo Molnar  * hierarchy domain allocation functions.
310d52dd441SThomas Gleixner  */
irqd_set_single_target(struct irq_data * d)311d52dd441SThomas Gleixner static inline void irqd_set_single_target(struct irq_data *d)
312d52dd441SThomas Gleixner {
313d52dd441SThomas Gleixner 	__irqd_to_state(d) |= IRQD_SINGLE_TARGET;
314d52dd441SThomas Gleixner }
315d52dd441SThomas Gleixner 
irqd_is_single_target(struct irq_data * d)316d52dd441SThomas Gleixner static inline bool irqd_is_single_target(struct irq_data *d)
317d52dd441SThomas Gleixner {
318d52dd441SThomas Gleixner 	return __irqd_to_state(d) & IRQD_SINGLE_TARGET;
319d52dd441SThomas Gleixner }
320d52dd441SThomas Gleixner 
irqd_set_handle_enforce_irqctx(struct irq_data * d)321c16816acSThomas Gleixner static inline void irqd_set_handle_enforce_irqctx(struct irq_data *d)
322c16816acSThomas Gleixner {
323c16816acSThomas Gleixner 	__irqd_to_state(d) |= IRQD_HANDLE_ENFORCE_IRQCTX;
324c16816acSThomas Gleixner }
325c16816acSThomas Gleixner 
irqd_is_handle_enforce_irqctx(struct irq_data * d)326c16816acSThomas Gleixner static inline bool irqd_is_handle_enforce_irqctx(struct irq_data *d)
327c16816acSThomas Gleixner {
328c16816acSThomas Gleixner 	return __irqd_to_state(d) & IRQD_HANDLE_ENFORCE_IRQCTX;
329c16816acSThomas Gleixner }
330c16816acSThomas Gleixner 
irqd_is_enabled_on_suspend(struct irq_data * d)33190428a8eSMaulik Shah static inline bool irqd_is_enabled_on_suspend(struct irq_data *d)
33290428a8eSMaulik Shah {
33390428a8eSMaulik Shah 	return __irqd_to_state(d) & IRQD_IRQ_ENABLED_ON_SUSPEND;
33490428a8eSMaulik Shah }
33590428a8eSMaulik Shah 
irqd_is_wakeup_set(struct irq_data * d)3367f94226fSThomas Gleixner static inline bool irqd_is_wakeup_set(struct irq_data *d)
3377f94226fSThomas Gleixner {
3380d0b4c86SJiang Liu 	return __irqd_to_state(d) & IRQD_WAKEUP_STATE;
3397f94226fSThomas Gleixner }
3407f94226fSThomas Gleixner 
irqd_can_move_in_process_context(struct irq_data * d)341e1ef8241SThomas Gleixner static inline bool irqd_can_move_in_process_context(struct irq_data *d)
342e1ef8241SThomas Gleixner {
3430d0b4c86SJiang Liu 	return __irqd_to_state(d) & IRQD_MOVE_PCNTXT;
344e1ef8241SThomas Gleixner }
345e1ef8241SThomas Gleixner 
irqd_irq_disabled(struct irq_data * d)346801a0e9aSThomas Gleixner static inline bool irqd_irq_disabled(struct irq_data *d)
347801a0e9aSThomas Gleixner {
3480d0b4c86SJiang Liu 	return __irqd_to_state(d) & IRQD_IRQ_DISABLED;
349801a0e9aSThomas Gleixner }
350801a0e9aSThomas Gleixner 
irqd_irq_masked(struct irq_data * d)35132f4125eSThomas Gleixner static inline bool irqd_irq_masked(struct irq_data *d)
35232f4125eSThomas Gleixner {
3530d0b4c86SJiang Liu 	return __irqd_to_state(d) & IRQD_IRQ_MASKED;
35432f4125eSThomas Gleixner }
35532f4125eSThomas Gleixner 
irqd_irq_inprogress(struct irq_data * d)35632f4125eSThomas Gleixner static inline bool irqd_irq_inprogress(struct irq_data *d)
35732f4125eSThomas Gleixner {
3580d0b4c86SJiang Liu 	return __irqd_to_state(d) & IRQD_IRQ_INPROGRESS;
35932f4125eSThomas Gleixner }
36032f4125eSThomas Gleixner 
irqd_is_wakeup_armed(struct irq_data * d)361b76f1674SThomas Gleixner static inline bool irqd_is_wakeup_armed(struct irq_data *d)
362b76f1674SThomas Gleixner {
3630d0b4c86SJiang Liu 	return __irqd_to_state(d) & IRQD_WAKEUP_ARMED;
364b76f1674SThomas Gleixner }
365b76f1674SThomas Gleixner 
irqd_is_forwarded_to_vcpu(struct irq_data * d)366fc569712SThomas Gleixner static inline bool irqd_is_forwarded_to_vcpu(struct irq_data *d)
367fc569712SThomas Gleixner {
368fc569712SThomas Gleixner 	return __irqd_to_state(d) & IRQD_FORWARDED_TO_VCPU;
369fc569712SThomas Gleixner }
370fc569712SThomas Gleixner 
irqd_set_forwarded_to_vcpu(struct irq_data * d)371fc569712SThomas Gleixner static inline void irqd_set_forwarded_to_vcpu(struct irq_data *d)
372fc569712SThomas Gleixner {
373fc569712SThomas Gleixner 	__irqd_to_state(d) |= IRQD_FORWARDED_TO_VCPU;
374fc569712SThomas Gleixner }
375fc569712SThomas Gleixner 
irqd_clr_forwarded_to_vcpu(struct irq_data * d)376fc569712SThomas Gleixner static inline void irqd_clr_forwarded_to_vcpu(struct irq_data *d)
377fc569712SThomas Gleixner {
378fc569712SThomas Gleixner 	__irqd_to_state(d) &= ~IRQD_FORWARDED_TO_VCPU;
379fc569712SThomas Gleixner }
380b76f1674SThomas Gleixner 
irqd_affinity_is_managed(struct irq_data * d)3819c255583SThomas Gleixner static inline bool irqd_affinity_is_managed(struct irq_data *d)
3829c255583SThomas Gleixner {
3839c255583SThomas Gleixner 	return __irqd_to_state(d) & IRQD_AFFINITY_MANAGED;
3849c255583SThomas Gleixner }
3859c255583SThomas Gleixner 
irqd_is_activated(struct irq_data * d)38608d85f3eSMarc Zyngier static inline bool irqd_is_activated(struct irq_data *d)
38708d85f3eSMarc Zyngier {
38808d85f3eSMarc Zyngier 	return __irqd_to_state(d) & IRQD_ACTIVATED;
38908d85f3eSMarc Zyngier }
39008d85f3eSMarc Zyngier 
irqd_set_activated(struct irq_data * d)39108d85f3eSMarc Zyngier static inline void irqd_set_activated(struct irq_data *d)
39208d85f3eSMarc Zyngier {
39308d85f3eSMarc Zyngier 	__irqd_to_state(d) |= IRQD_ACTIVATED;
39408d85f3eSMarc Zyngier }
39508d85f3eSMarc Zyngier 
irqd_clr_activated(struct irq_data * d)39608d85f3eSMarc Zyngier static inline void irqd_clr_activated(struct irq_data *d)
39708d85f3eSMarc Zyngier {
39808d85f3eSMarc Zyngier 	__irqd_to_state(d) &= ~IRQD_ACTIVATED;
39908d85f3eSMarc Zyngier }
40008d85f3eSMarc Zyngier 
irqd_is_started(struct irq_data * d)401201d7f47SThomas Gleixner static inline bool irqd_is_started(struct irq_data *d)
402201d7f47SThomas Gleixner {
403201d7f47SThomas Gleixner 	return __irqd_to_state(d) & IRQD_IRQ_STARTED;
404201d7f47SThomas Gleixner }
405201d7f47SThomas Gleixner 
irqd_is_managed_and_shutdown(struct irq_data * d)406761ea388SThomas Gleixner static inline bool irqd_is_managed_and_shutdown(struct irq_data *d)
40754fdf6a0SThomas Gleixner {
40854fdf6a0SThomas Gleixner 	return __irqd_to_state(d) & IRQD_MANAGED_SHUTDOWN;
40954fdf6a0SThomas Gleixner }
41054fdf6a0SThomas Gleixner 
irqd_set_can_reserve(struct irq_data * d)41169790ba9SThomas Gleixner static inline void irqd_set_can_reserve(struct irq_data *d)
41269790ba9SThomas Gleixner {
41369790ba9SThomas Gleixner 	__irqd_to_state(d) |= IRQD_CAN_RESERVE;
41469790ba9SThomas Gleixner }
41569790ba9SThomas Gleixner 
irqd_clr_can_reserve(struct irq_data * d)41669790ba9SThomas Gleixner static inline void irqd_clr_can_reserve(struct irq_data *d)
41769790ba9SThomas Gleixner {
41869790ba9SThomas Gleixner 	__irqd_to_state(d) &= ~IRQD_CAN_RESERVE;
41969790ba9SThomas Gleixner }
42069790ba9SThomas Gleixner 
irqd_can_reserve(struct irq_data * d)42169790ba9SThomas Gleixner static inline bool irqd_can_reserve(struct irq_data *d)
42269790ba9SThomas Gleixner {
42369790ba9SThomas Gleixner 	return __irqd_to_state(d) & IRQD_CAN_RESERVE;
42469790ba9SThomas Gleixner }
42569790ba9SThomas Gleixner 
irqd_set_affinity_on_activate(struct irq_data * d)426f0c7bacaSThomas Gleixner static inline void irqd_set_affinity_on_activate(struct irq_data *d)
427f0c7bacaSThomas Gleixner {
428f0c7bacaSThomas Gleixner 	__irqd_to_state(d) |= IRQD_AFFINITY_ON_ACTIVATE;
429f0c7bacaSThomas Gleixner }
430f0c7bacaSThomas Gleixner 
irqd_affinity_on_activate(struct irq_data * d)431f0c7bacaSThomas Gleixner static inline bool irqd_affinity_on_activate(struct irq_data *d)
432f0c7bacaSThomas Gleixner {
433f0c7bacaSThomas Gleixner 	return __irqd_to_state(d) & IRQD_AFFINITY_ON_ACTIVATE;
434f0c7bacaSThomas Gleixner }
435f0c7bacaSThomas Gleixner 
irqd_set_resend_when_in_progress(struct irq_data * d)4369c15eeb5SJames Gowans static inline void irqd_set_resend_when_in_progress(struct irq_data *d)
4379c15eeb5SJames Gowans {
4389c15eeb5SJames Gowans 	__irqd_to_state(d) |= IRQD_RESEND_WHEN_IN_PROGRESS;
4399c15eeb5SJames Gowans }
4409c15eeb5SJames Gowans 
irqd_needs_resend_when_in_progress(struct irq_data * d)4419c15eeb5SJames Gowans static inline bool irqd_needs_resend_when_in_progress(struct irq_data *d)
4429c15eeb5SJames Gowans {
4439c15eeb5SJames Gowans 	return __irqd_to_state(d) & IRQD_RESEND_WHEN_IN_PROGRESS;
4449c15eeb5SJames Gowans }
4459c15eeb5SJames Gowans 
446b354286eSBoqun Feng #undef __irqd_to_state
447b354286eSBoqun Feng 
irqd_to_hwirq(struct irq_data * d)448a699e4e4SGrant Likely static inline irq_hw_number_t irqd_to_hwirq(struct irq_data *d)
449a699e4e4SGrant Likely {
450a699e4e4SGrant Likely 	return d->hwirq;
451a699e4e4SGrant Likely }
452a699e4e4SGrant Likely 
453ff7dcd44SThomas Gleixner /**
4546a6de9efSThomas Gleixner  * struct irq_chip - hardware interrupt chip descriptor
4558fee5c36SIngo Molnar  *
4568fee5c36SIngo Molnar  * @name:		name for /proc/interrupts
457f8822657SThomas Gleixner  * @irq_startup:	start up the interrupt (defaults to ->enable if NULL)
458f8822657SThomas Gleixner  * @irq_shutdown:	shut down the interrupt (defaults to ->disable if NULL)
459f8822657SThomas Gleixner  * @irq_enable:		enable the interrupt (defaults to chip->unmask if NULL)
460f8822657SThomas Gleixner  * @irq_disable:	disable the interrupt
461f8822657SThomas Gleixner  * @irq_ack:		start of a new interrupt
462f8822657SThomas Gleixner  * @irq_mask:		mask an interrupt source
463f8822657SThomas Gleixner  * @irq_mask_ack:	ack and mask an interrupt source
464f8822657SThomas Gleixner  * @irq_unmask:		unmask an interrupt source
465f8822657SThomas Gleixner  * @irq_eoi:		end of interrupt
46683979133SThomas Gleixner  * @irq_set_affinity:	Set the CPU affinity on SMP machines. If the force
46783979133SThomas Gleixner  *			argument is true, it tells the driver to
46883979133SThomas Gleixner  *			unconditionally apply the affinity setting. Sanity
46983979133SThomas Gleixner  *			checks against the supplied affinity mask are not
47083979133SThomas Gleixner  *			required. This is used for CPU hotplug where the
47183979133SThomas Gleixner  *			target CPU is not yet set in the cpu_online_mask.
472f8822657SThomas Gleixner  * @irq_retrigger:	resend an IRQ to the CPU
473f8822657SThomas Gleixner  * @irq_set_type:	set the flow type (IRQ_TYPE_LEVEL/etc.) of an IRQ
474f8822657SThomas Gleixner  * @irq_set_wake:	enable/disable power-management wake-on of an IRQ
475f8822657SThomas Gleixner  * @irq_bus_lock:	function to lock access to slow bus (i2c) chips
476f8822657SThomas Gleixner  * @irq_bus_sync_unlock:function to sync and unlock slow bus (i2c) chips
4770fdb4b25SDavid Daney  * @irq_cpu_online:	configure an interrupt source for a secondary CPU
4780fdb4b25SDavid Daney  * @irq_cpu_offline:	un-configure an interrupt source for a secondary CPU
479be9b22b6SBrian Norris  * @irq_suspend:	function called from core code on suspend once per
480be9b22b6SBrian Norris  *			chip, when one or more interrupts are installed
481be9b22b6SBrian Norris  * @irq_resume:		function called from core code on resume once per chip,
482be9b22b6SBrian Norris  *			when one ore more interrupts are installed
483cfefd21eSThomas Gleixner  * @irq_pm_shutdown:	function called from core code on shutdown once per chip
484d0051816SThomas Gleixner  * @irq_calc_mask:	Optional function to set irq_data.mask for special cases
485ab7798ffSThomas Gleixner  * @irq_print_chip:	optional to print special chip info in show_interrupts
486c1bacbaeSThomas Gleixner  * @irq_request_resources:	optional to request resources before calling
487c1bacbaeSThomas Gleixner  *				any other callback related to this irq
488c1bacbaeSThomas Gleixner  * @irq_release_resources:	optional to release resources acquired with
489c1bacbaeSThomas Gleixner  *				irq_request_resources
490515085efSJiang Liu  * @irq_compose_msi_msg:	optional to compose message content for MSI
4919dde55b7SJiang Liu  * @irq_write_msi_msg:	optional to write message content for MSI
4921b7047edSMarc Zyngier  * @irq_get_irqchip_state:	return the internal state of an interrupt
4931b7047edSMarc Zyngier  * @irq_set_irqchip_state:	set the internal state of a interrupt
4940a4377deSJiang Liu  * @irq_set_vcpu_affinity:	optional to target a vCPU in a virtual machine
49534dc1ae1SQais Yousef  * @ipi_send_single:	send a single IPI to destination cpus
49634dc1ae1SQais Yousef  * @ipi_send_mask:	send an IPI to destination cpus in cpumask
497b525903cSJulien Thierry  * @irq_nmi_setup:	function called from core code before enabling an NMI
498b525903cSJulien Thierry  * @irq_nmi_teardown:	function called from core code after disabling an NMI
4992bff17adSThomas Gleixner  * @flags:		chip specific flags
5001da177e4SLinus Torvalds  */
5016a6de9efSThomas Gleixner struct irq_chip {
5026a6de9efSThomas Gleixner 	const char	*name;
503f8822657SThomas Gleixner 	unsigned int	(*irq_startup)(struct irq_data *data);
504f8822657SThomas Gleixner 	void		(*irq_shutdown)(struct irq_data *data);
505f8822657SThomas Gleixner 	void		(*irq_enable)(struct irq_data *data);
506f8822657SThomas Gleixner 	void		(*irq_disable)(struct irq_data *data);
507f8822657SThomas Gleixner 
508f8822657SThomas Gleixner 	void		(*irq_ack)(struct irq_data *data);
509f8822657SThomas Gleixner 	void		(*irq_mask)(struct irq_data *data);
510f8822657SThomas Gleixner 	void		(*irq_mask_ack)(struct irq_data *data);
511f8822657SThomas Gleixner 	void		(*irq_unmask)(struct irq_data *data);
512f8822657SThomas Gleixner 	void		(*irq_eoi)(struct irq_data *data);
513f8822657SThomas Gleixner 
514f8822657SThomas Gleixner 	int		(*irq_set_affinity)(struct irq_data *data, const struct cpumask *dest, bool force);
515f8822657SThomas Gleixner 	int		(*irq_retrigger)(struct irq_data *data);
516f8822657SThomas Gleixner 	int		(*irq_set_type)(struct irq_data *data, unsigned int flow_type);
517f8822657SThomas Gleixner 	int		(*irq_set_wake)(struct irq_data *data, unsigned int on);
518f8822657SThomas Gleixner 
519f8822657SThomas Gleixner 	void		(*irq_bus_lock)(struct irq_data *data);
520f8822657SThomas Gleixner 	void		(*irq_bus_sync_unlock)(struct irq_data *data);
521f8822657SThomas Gleixner 
5228d15a729SMarc Zyngier #ifdef CONFIG_DEPRECATED_IRQ_CPU_ONOFFLINE
5230fdb4b25SDavid Daney 	void		(*irq_cpu_online)(struct irq_data *data);
5240fdb4b25SDavid Daney 	void		(*irq_cpu_offline)(struct irq_data *data);
5258d15a729SMarc Zyngier #endif
526cfefd21eSThomas Gleixner 	void		(*irq_suspend)(struct irq_data *data);
527cfefd21eSThomas Gleixner 	void		(*irq_resume)(struct irq_data *data);
528cfefd21eSThomas Gleixner 	void		(*irq_pm_shutdown)(struct irq_data *data);
529cfefd21eSThomas Gleixner 
530d0051816SThomas Gleixner 	void		(*irq_calc_mask)(struct irq_data *data);
531d0051816SThomas Gleixner 
532ab7798ffSThomas Gleixner 	void		(*irq_print_chip)(struct irq_data *data, struct seq_file *p);
533c1bacbaeSThomas Gleixner 	int		(*irq_request_resources)(struct irq_data *data);
534c1bacbaeSThomas Gleixner 	void		(*irq_release_resources)(struct irq_data *data);
535ab7798ffSThomas Gleixner 
536515085efSJiang Liu 	void		(*irq_compose_msi_msg)(struct irq_data *data, struct msi_msg *msg);
5379dde55b7SJiang Liu 	void		(*irq_write_msi_msg)(struct irq_data *data, struct msi_msg *msg);
538515085efSJiang Liu 
5391b7047edSMarc Zyngier 	int		(*irq_get_irqchip_state)(struct irq_data *data, enum irqchip_irq_state which, bool *state);
5401b7047edSMarc Zyngier 	int		(*irq_set_irqchip_state)(struct irq_data *data, enum irqchip_irq_state which, bool state);
5411b7047edSMarc Zyngier 
5420a4377deSJiang Liu 	int		(*irq_set_vcpu_affinity)(struct irq_data *data, void *vcpu_info);
5430a4377deSJiang Liu 
54434dc1ae1SQais Yousef 	void		(*ipi_send_single)(struct irq_data *data, unsigned int cpu);
54534dc1ae1SQais Yousef 	void		(*ipi_send_mask)(struct irq_data *data, const struct cpumask *dest);
54634dc1ae1SQais Yousef 
547b525903cSJulien Thierry 	int		(*irq_nmi_setup)(struct irq_data *data);
548b525903cSJulien Thierry 	void		(*irq_nmi_teardown)(struct irq_data *data);
549b525903cSJulien Thierry 
5502bff17adSThomas Gleixner 	unsigned long	flags;
5511da177e4SLinus Torvalds };
5521da177e4SLinus Torvalds 
553d4d5e089SThomas Gleixner /*
554d4d5e089SThomas Gleixner  * irq_chip specific flags
555d4d5e089SThomas Gleixner  *
556d4d5e089SThomas Gleixner  * IRQCHIP_SET_TYPE_MASKED:           Mask before calling chip.irq_set_type()
55777694b40SThomas Gleixner  * IRQCHIP_EOI_IF_HANDLED:            Only issue irq_eoi() when irq was handled
558d209a699SThomas Gleixner  * IRQCHIP_MASK_ON_SUSPEND:           Mask non wake irqs in the suspend path
559b3d42232SThomas Gleixner  * IRQCHIP_ONOFFLINE_ENABLED:         Only call irq_on/off_line callbacks
560b3d42232SThomas Gleixner  *                                    when irq enabled
56160f96b41SSantosh Shilimkar  * IRQCHIP_SKIP_SET_WAKE:             Skip chip.irq_set_wake(), for this irq chip
5624f6e4f71SThomas Gleixner  * IRQCHIP_ONESHOT_SAFE:              One shot does not require mask/unmask
563328a4978SThomas Gleixner  * IRQCHIP_EOI_THREADED:              Chip requires eoi() on unmask in threaded mode
56490428a8eSMaulik Shah  * IRQCHIP_SUPPORTS_LEVEL_MSI:        Chip can provide two doorbells for Level MSIs
565b525903cSJulien Thierry  * IRQCHIP_SUPPORTS_NMI:              Chip can deliver NMIs, only for root irqchips
56690428a8eSMaulik Shah  * IRQCHIP_ENABLE_WAKEUP_ON_SUSPEND:  Invokes __enable_irq()/__disable_irq() for wake irqs
56790428a8eSMaulik Shah  *                                    in the suspend path if they are in disabled state
568826da771SThomas Gleixner  * IRQCHIP_AFFINITY_PRE_STARTUP:      Default affinity update before startup
5696c846d02SMarc Zyngier  * IRQCHIP_IMMUTABLE:		      Don't ever change anything in this chip
570d4d5e089SThomas Gleixner  */
571d4d5e089SThomas Gleixner enum {
572d4d5e089SThomas Gleixner 	IRQCHIP_SET_TYPE_MASKED			= (1 <<  0),
57377694b40SThomas Gleixner 	IRQCHIP_EOI_IF_HANDLED			= (1 <<  1),
574d209a699SThomas Gleixner 	IRQCHIP_MASK_ON_SUSPEND			= (1 <<  2),
575b3d42232SThomas Gleixner 	IRQCHIP_ONOFFLINE_ENABLED		= (1 <<  3),
57660f96b41SSantosh Shilimkar 	IRQCHIP_SKIP_SET_WAKE			= (1 <<  4),
577dc9b229aSThomas Gleixner 	IRQCHIP_ONESHOT_SAFE			= (1 <<  5),
578328a4978SThomas Gleixner 	IRQCHIP_EOI_THREADED			= (1 <<  6),
5796988e0e0SMarc Zyngier 	IRQCHIP_SUPPORTS_LEVEL_MSI		= (1 <<  7),
580b525903cSJulien Thierry 	IRQCHIP_SUPPORTS_NMI			= (1 <<  8),
58190428a8eSMaulik Shah 	IRQCHIP_ENABLE_WAKEUP_ON_SUSPEND	= (1 <<  9),
582826da771SThomas Gleixner 	IRQCHIP_AFFINITY_PRE_STARTUP		= (1 << 10),
5836c846d02SMarc Zyngier 	IRQCHIP_IMMUTABLE			= (1 << 11),
584d4d5e089SThomas Gleixner };
585d4d5e089SThomas Gleixner 
586e144710bSThomas Gleixner #include <linux/irqdesc.h>
587c6b7674fSThomas Gleixner 
58834ffdb72SIngo Molnar /*
58934ffdb72SIngo Molnar  * Pick up the arch-dependent methods:
59034ffdb72SIngo Molnar  */
59134ffdb72SIngo Molnar #include <asm/hw_irq.h>
5921da177e4SLinus Torvalds 
593b683de2bSThomas Gleixner #ifndef NR_IRQS_LEGACY
594b683de2bSThomas Gleixner # define NR_IRQS_LEGACY 0
595b683de2bSThomas Gleixner #endif
596b683de2bSThomas Gleixner 
5971318a481SThomas Gleixner #ifndef ARCH_IRQ_INIT_FLAGS
5981318a481SThomas Gleixner # define ARCH_IRQ_INIT_FLAGS	0
5991318a481SThomas Gleixner #endif
6001318a481SThomas Gleixner 
601c1594b77SThomas Gleixner #define IRQ_DEFAULT_INIT_FLAGS	ARCH_IRQ_INIT_FLAGS
6021318a481SThomas Gleixner 
603e144710bSThomas Gleixner struct irqaction;
60431d9d9b6SMarc Zyngier extern int setup_percpu_irq(unsigned int irq, struct irqaction *new);
60531d9d9b6SMarc Zyngier extern void remove_percpu_irq(unsigned int irq, struct irqaction *act);
6061da177e4SLinus Torvalds 
6078d15a729SMarc Zyngier #ifdef CONFIG_DEPRECATED_IRQ_CPU_ONOFFLINE
6080fdb4b25SDavid Daney extern void irq_cpu_online(void);
6090fdb4b25SDavid Daney extern void irq_cpu_offline(void);
6108d15a729SMarc Zyngier #endif
61101f8fa4fSThomas Gleixner extern int irq_set_affinity_locked(struct irq_data *data,
61201f8fa4fSThomas Gleixner 				   const struct cpumask *cpumask, bool force);
6130a4377deSJiang Liu extern int irq_set_vcpu_affinity(unsigned int irq, void *vcpu_info);
6140fdb4b25SDavid Daney 
615c5cb83bbSThomas Gleixner #if defined(CONFIG_SMP) && defined(CONFIG_GENERIC_IRQ_MIGRATION)
616f1e0bb0aSYang Yingliang extern void irq_migrate_all_off_this_cpu(void);
617c5cb83bbSThomas Gleixner extern int irq_affinity_online_cpu(unsigned int cpu);
618c5cb83bbSThomas Gleixner #else
619c5cb83bbSThomas Gleixner # define irq_affinity_online_cpu	NULL
620c5cb83bbSThomas Gleixner #endif
621f1e0bb0aSYang Yingliang 
6223a3856d0SThomas Gleixner #if defined(CONFIG_SMP) && defined(CONFIG_GENERIC_PENDING_IRQ)
623d340ebd6SThomas Gleixner void __irq_move_irq(struct irq_data *data);
irq_move_irq(struct irq_data * data)624d340ebd6SThomas Gleixner static inline void irq_move_irq(struct irq_data *data)
625d340ebd6SThomas Gleixner {
626d340ebd6SThomas Gleixner 	if (unlikely(irqd_is_setaffinity_pending(data)))
627d340ebd6SThomas Gleixner 		__irq_move_irq(data);
628d340ebd6SThomas Gleixner }
629a439520fSThomas Gleixner void irq_move_masked_irq(struct irq_data *data);
630f0383c24SThomas Gleixner void irq_force_complete_move(struct irq_desc *desc);
631e144710bSThomas Gleixner #else
irq_move_irq(struct irq_data * data)632a439520fSThomas Gleixner static inline void irq_move_irq(struct irq_data *data) { }
irq_move_masked_irq(struct irq_data * data)633a439520fSThomas Gleixner static inline void irq_move_masked_irq(struct irq_data *data) { }
irq_force_complete_move(struct irq_desc * desc)634f0383c24SThomas Gleixner static inline void irq_force_complete_move(struct irq_desc *desc) { }
635e144710bSThomas Gleixner #endif
63654d5d424SAshok Raj 
6371da177e4SLinus Torvalds extern int no_irq_affinity;
6381da177e4SLinus Torvalds 
639293a7a0aSThomas Gleixner #ifdef CONFIG_HARDIRQS_SW_RESEND
640293a7a0aSThomas Gleixner int irq_set_parent(int irq, int parent_irq);
641293a7a0aSThomas Gleixner #else
irq_set_parent(int irq,int parent_irq)642293a7a0aSThomas Gleixner static inline int irq_set_parent(int irq, int parent_irq)
643293a7a0aSThomas Gleixner {
644293a7a0aSThomas Gleixner 	return 0;
645293a7a0aSThomas Gleixner }
646293a7a0aSThomas Gleixner #endif
647293a7a0aSThomas Gleixner 
6482e60bbb6SIngo Molnar /*
6496a6de9efSThomas Gleixner  * Built-in IRQ handlers for various IRQ types,
650bebd04ccSKrzysztof Halasa  * callable via desc->handle_irq()
6516a6de9efSThomas Gleixner  */
652bd0b9ac4SThomas Gleixner extern void handle_level_irq(struct irq_desc *desc);
653bd0b9ac4SThomas Gleixner extern void handle_fasteoi_irq(struct irq_desc *desc);
654bd0b9ac4SThomas Gleixner extern void handle_edge_irq(struct irq_desc *desc);
655bd0b9ac4SThomas Gleixner extern void handle_edge_eoi_irq(struct irq_desc *desc);
656bd0b9ac4SThomas Gleixner extern void handle_simple_irq(struct irq_desc *desc);
657edd14cfeSKeith Busch extern void handle_untracked_irq(struct irq_desc *desc);
658bd0b9ac4SThomas Gleixner extern void handle_percpu_irq(struct irq_desc *desc);
659bd0b9ac4SThomas Gleixner extern void handle_percpu_devid_irq(struct irq_desc *desc);
660bd0b9ac4SThomas Gleixner extern void handle_bad_irq(struct irq_desc *desc);
66131b47cf7SMark Brown extern void handle_nested_irq(unsigned int irq);
6626a6de9efSThomas Gleixner 
6632dcf1fbcSJulien Thierry extern void handle_fasteoi_nmi(struct irq_desc *desc);
6642dcf1fbcSJulien Thierry extern void handle_percpu_devid_fasteoi_nmi(struct irq_desc *desc);
6652dcf1fbcSJulien Thierry 
666515085efSJiang Liu extern int irq_chip_compose_msi_msg(struct irq_data *data, struct msi_msg *msg);
667be45beb2SJon Hunter extern int irq_chip_pm_get(struct irq_data *data);
668be45beb2SJon Hunter extern int irq_chip_pm_put(struct irq_data *data);
66985f08c17SJiang Liu #ifdef	CONFIG_IRQ_DOMAIN_HIERARCHY
6707703b08cSDavid Daney extern void handle_fasteoi_ack_irq(struct irq_desc *desc);
6717703b08cSDavid Daney extern void handle_fasteoi_mask_irq(struct irq_desc *desc);
6724a169a95SMaulik Shah extern int irq_chip_set_parent_state(struct irq_data *data,
6734a169a95SMaulik Shah 				     enum irqchip_irq_state which,
6744a169a95SMaulik Shah 				     bool val);
6754a169a95SMaulik Shah extern int irq_chip_get_parent_state(struct irq_data *data,
6764a169a95SMaulik Shah 				     enum irqchip_irq_state which,
6774a169a95SMaulik Shah 				     bool *state);
6783cfeffc2SStefan Agner extern void irq_chip_enable_parent(struct irq_data *data);
6793cfeffc2SStefan Agner extern void irq_chip_disable_parent(struct irq_data *data);
68085f08c17SJiang Liu extern void irq_chip_ack_parent(struct irq_data *data);
68185f08c17SJiang Liu extern int irq_chip_retrigger_hierarchy(struct irq_data *data);
68256e8ababSYingjoe Chen extern void irq_chip_mask_parent(struct irq_data *data);
6835aa5bd56SLinus Walleij extern void irq_chip_mask_ack_parent(struct irq_data *data);
68456e8ababSYingjoe Chen extern void irq_chip_unmask_parent(struct irq_data *data);
68556e8ababSYingjoe Chen extern void irq_chip_eoi_parent(struct irq_data *data);
68656e8ababSYingjoe Chen extern int irq_chip_set_affinity_parent(struct irq_data *data,
68756e8ababSYingjoe Chen 					const struct cpumask *dest,
68856e8ababSYingjoe Chen 					bool force);
68908b55e2aSMarc Zyngier extern int irq_chip_set_wake_parent(struct irq_data *data, unsigned int on);
6900a4377deSJiang Liu extern int irq_chip_set_vcpu_affinity_parent(struct irq_data *data,
6910a4377deSJiang Liu 					     void *vcpu_info);
692b7560de1SGrygorii Strashko extern int irq_chip_set_type_parent(struct irq_data *data, unsigned int type);
6932bd1298aSLokesh Vutla extern int irq_chip_request_resources_parent(struct irq_data *data);
6942bd1298aSLokesh Vutla extern void irq_chip_release_resources_parent(struct irq_data *data);
69585f08c17SJiang Liu #endif
69685f08c17SJiang Liu 
6976a6de9efSThomas Gleixner /* Handling of unhandled and spurious interrupts: */
6980dcdbc97SJiang Liu extern void note_interrupt(struct irq_desc *desc, irqreturn_t action_ret);
6991da177e4SLinus Torvalds 
700a4633adcSThomas Gleixner 
7016a6de9efSThomas Gleixner /* Enable/disable irq debugging output: */
7026a6de9efSThomas Gleixner extern int noirqdebug_setup(char *str);
7031da177e4SLinus Torvalds 
7046a6de9efSThomas Gleixner /* Checks whether the interrupt can be requested by request_irq(): */
7056a6de9efSThomas Gleixner extern int can_request_irq(unsigned int irq, unsigned long irqflags);
7066a6de9efSThomas Gleixner 
707f8b5473fSThomas Gleixner /* Dummy irq-chip implementations: */
7086a6de9efSThomas Gleixner extern struct irq_chip no_irq_chip;
709f8b5473fSThomas Gleixner extern struct irq_chip dummy_irq_chip;
7106a6de9efSThomas Gleixner 
7116a6de9efSThomas Gleixner extern void
712393e1280SMarc Zyngier irq_set_chip_and_handler_name(unsigned int irq, const struct irq_chip *chip,
713a460e745SIngo Molnar 			      irq_flow_handler_t handle, const char *name);
714a460e745SIngo Molnar 
irq_set_chip_and_handler(unsigned int irq,const struct irq_chip * chip,irq_flow_handler_t handle)715393e1280SMarc Zyngier static inline void irq_set_chip_and_handler(unsigned int irq,
716393e1280SMarc Zyngier 					    const struct irq_chip *chip,
7173836ca08SThomas Gleixner 					    irq_flow_handler_t handle)
7183836ca08SThomas Gleixner {
7193836ca08SThomas Gleixner 	irq_set_chip_and_handler_name(irq, chip, handle, NULL);
7203836ca08SThomas Gleixner }
7213836ca08SThomas Gleixner 
72231d9d9b6SMarc Zyngier extern int irq_set_percpu_devid(unsigned int irq);
723222df54fSMarc Zyngier extern int irq_set_percpu_devid_partition(unsigned int irq,
724222df54fSMarc Zyngier 					  const struct cpumask *affinity);
725222df54fSMarc Zyngier extern int irq_get_percpu_devid_partition(unsigned int irq,
726222df54fSMarc Zyngier 					  struct cpumask *affinity);
72731d9d9b6SMarc Zyngier 
7286a6de9efSThomas Gleixner extern void
7293836ca08SThomas Gleixner __irq_set_handler(unsigned int irq, irq_flow_handler_t handle, int is_chained,
730a460e745SIngo Molnar 		  const char *name);
7316a6de9efSThomas Gleixner 
7326a6de9efSThomas Gleixner static inline void
irq_set_handler(unsigned int irq,irq_flow_handler_t handle)7333836ca08SThomas Gleixner irq_set_handler(unsigned int irq, irq_flow_handler_t handle)
7346a6de9efSThomas Gleixner {
7353836ca08SThomas Gleixner 	__irq_set_handler(irq, handle, 0, NULL);
7366a6de9efSThomas Gleixner }
7376a6de9efSThomas Gleixner 
7386a6de9efSThomas Gleixner /*
7396a6de9efSThomas Gleixner  * Set a highlevel chained flow handler for a given IRQ.
7406a6de9efSThomas Gleixner  * (a chained handler is automatically enabled and set to
7417f1b1244SPaul Mundt  *  IRQ_NOREQUEST, IRQ_NOPROBE, and IRQ_NOTHREAD)
7426a6de9efSThomas Gleixner  */
7436a6de9efSThomas Gleixner static inline void
irq_set_chained_handler(unsigned int irq,irq_flow_handler_t handle)7443836ca08SThomas Gleixner irq_set_chained_handler(unsigned int irq, irq_flow_handler_t handle)
7456a6de9efSThomas Gleixner {
7463836ca08SThomas Gleixner 	__irq_set_handler(irq, handle, 1, NULL);
7476a6de9efSThomas Gleixner }
7486a6de9efSThomas Gleixner 
7493b0f95beSRussell King /*
7503b0f95beSRussell King  * Set a highlevel chained flow handler and its data for a given IRQ.
7513b0f95beSRussell King  * (a chained handler is automatically enabled and set to
7523b0f95beSRussell King  *  IRQ_NOREQUEST, IRQ_NOPROBE, and IRQ_NOTHREAD)
7533b0f95beSRussell King  */
7543b0f95beSRussell King void
7553b0f95beSRussell King irq_set_chained_handler_and_data(unsigned int irq, irq_flow_handler_t handle,
7563b0f95beSRussell King 				 void *data);
7573b0f95beSRussell King 
75844247184SThomas Gleixner void irq_modify_status(unsigned int irq, unsigned long clr, unsigned long set);
75944247184SThomas Gleixner 
irq_set_status_flags(unsigned int irq,unsigned long set)76044247184SThomas Gleixner static inline void irq_set_status_flags(unsigned int irq, unsigned long set)
76144247184SThomas Gleixner {
76244247184SThomas Gleixner 	irq_modify_status(irq, 0, set);
76344247184SThomas Gleixner }
76444247184SThomas Gleixner 
irq_clear_status_flags(unsigned int irq,unsigned long clr)76544247184SThomas Gleixner static inline void irq_clear_status_flags(unsigned int irq, unsigned long clr)
76644247184SThomas Gleixner {
76744247184SThomas Gleixner 	irq_modify_status(irq, clr, 0);
76844247184SThomas Gleixner }
76944247184SThomas Gleixner 
irq_set_noprobe(unsigned int irq)770a0cd9ca2SThomas Gleixner static inline void irq_set_noprobe(unsigned int irq)
77144247184SThomas Gleixner {
77244247184SThomas Gleixner 	irq_modify_status(irq, 0, IRQ_NOPROBE);
77344247184SThomas Gleixner }
77444247184SThomas Gleixner 
irq_set_probe(unsigned int irq)775a0cd9ca2SThomas Gleixner static inline void irq_set_probe(unsigned int irq)
77644247184SThomas Gleixner {
77744247184SThomas Gleixner 	irq_modify_status(irq, IRQ_NOPROBE, 0);
77844247184SThomas Gleixner }
77946f4f8f6SRalf Baechle 
irq_set_nothread(unsigned int irq)7807f1b1244SPaul Mundt static inline void irq_set_nothread(unsigned int irq)
7817f1b1244SPaul Mundt {
7827f1b1244SPaul Mundt 	irq_modify_status(irq, 0, IRQ_NOTHREAD);
7837f1b1244SPaul Mundt }
7847f1b1244SPaul Mundt 
irq_set_thread(unsigned int irq)7857f1b1244SPaul Mundt static inline void irq_set_thread(unsigned int irq)
7867f1b1244SPaul Mundt {
7877f1b1244SPaul Mundt 	irq_modify_status(irq, IRQ_NOTHREAD, 0);
7887f1b1244SPaul Mundt }
7897f1b1244SPaul Mundt 
irq_set_nested_thread(unsigned int irq,bool nest)7906f91a52dSThomas Gleixner static inline void irq_set_nested_thread(unsigned int irq, bool nest)
7916f91a52dSThomas Gleixner {
7926f91a52dSThomas Gleixner 	if (nest)
7936f91a52dSThomas Gleixner 		irq_set_status_flags(irq, IRQ_NESTED_THREAD);
7946f91a52dSThomas Gleixner 	else
7956f91a52dSThomas Gleixner 		irq_clear_status_flags(irq, IRQ_NESTED_THREAD);
7966f91a52dSThomas Gleixner }
7976f91a52dSThomas Gleixner 
irq_set_percpu_devid_flags(unsigned int irq)79831d9d9b6SMarc Zyngier static inline void irq_set_percpu_devid_flags(unsigned int irq)
79931d9d9b6SMarc Zyngier {
80031d9d9b6SMarc Zyngier 	irq_set_status_flags(irq,
80131d9d9b6SMarc Zyngier 			     IRQ_NOAUTOEN | IRQ_PER_CPU | IRQ_NOTHREAD |
80231d9d9b6SMarc Zyngier 			     IRQ_NOPROBE | IRQ_PER_CPU_DEVID);
80331d9d9b6SMarc Zyngier }
80431d9d9b6SMarc Zyngier 
8053a16d713SEric W. Biederman /* Set/get chip/data for an IRQ: */
806393e1280SMarc Zyngier extern int irq_set_chip(unsigned int irq, const struct irq_chip *chip);
807a0cd9ca2SThomas Gleixner extern int irq_set_handler_data(unsigned int irq, void *data);
808a0cd9ca2SThomas Gleixner extern int irq_set_chip_data(unsigned int irq, void *data);
809a0cd9ca2SThomas Gleixner extern int irq_set_irq_type(unsigned int irq, unsigned int type);
810a0cd9ca2SThomas Gleixner extern int irq_set_msi_desc(unsigned int irq, struct msi_desc *entry);
81151906e77SAlexander Gordeev extern int irq_set_msi_desc_off(unsigned int irq_base, unsigned int irq_offset,
81251906e77SAlexander Gordeev 				struct msi_desc *entry);
813f303a6ddSThomas Gleixner extern struct irq_data *irq_get_irq_data(unsigned int irq);
814dd87eb3aSThomas Gleixner 
irq_get_chip(unsigned int irq)815a0cd9ca2SThomas Gleixner static inline struct irq_chip *irq_get_chip(unsigned int irq)
816f303a6ddSThomas Gleixner {
817f303a6ddSThomas Gleixner 	struct irq_data *d = irq_get_irq_data(irq);
818f303a6ddSThomas Gleixner 	return d ? d->chip : NULL;
819f303a6ddSThomas Gleixner }
820f303a6ddSThomas Gleixner 
irq_data_get_irq_chip(struct irq_data * d)821f303a6ddSThomas Gleixner static inline struct irq_chip *irq_data_get_irq_chip(struct irq_data *d)
822f303a6ddSThomas Gleixner {
823f303a6ddSThomas Gleixner 	return d->chip;
824f303a6ddSThomas Gleixner }
825f303a6ddSThomas Gleixner 
irq_get_chip_data(unsigned int irq)826a0cd9ca2SThomas Gleixner static inline void *irq_get_chip_data(unsigned int irq)
827f303a6ddSThomas Gleixner {
828f303a6ddSThomas Gleixner 	struct irq_data *d = irq_get_irq_data(irq);
829f303a6ddSThomas Gleixner 	return d ? d->chip_data : NULL;
830f303a6ddSThomas Gleixner }
831f303a6ddSThomas Gleixner 
irq_data_get_irq_chip_data(struct irq_data * d)832f303a6ddSThomas Gleixner static inline void *irq_data_get_irq_chip_data(struct irq_data *d)
833f303a6ddSThomas Gleixner {
834f303a6ddSThomas Gleixner 	return d->chip_data;
835f303a6ddSThomas Gleixner }
836f303a6ddSThomas Gleixner 
irq_get_handler_data(unsigned int irq)837a0cd9ca2SThomas Gleixner static inline void *irq_get_handler_data(unsigned int irq)
838f303a6ddSThomas Gleixner {
839f303a6ddSThomas Gleixner 	struct irq_data *d = irq_get_irq_data(irq);
840af7080e0SJiang Liu 	return d ? d->common->handler_data : NULL;
841f303a6ddSThomas Gleixner }
842f303a6ddSThomas Gleixner 
irq_data_get_irq_handler_data(struct irq_data * d)843a0cd9ca2SThomas Gleixner static inline void *irq_data_get_irq_handler_data(struct irq_data *d)
844f303a6ddSThomas Gleixner {
845af7080e0SJiang Liu 	return d->common->handler_data;
846f303a6ddSThomas Gleixner }
847f303a6ddSThomas Gleixner 
irq_get_msi_desc(unsigned int irq)848a0cd9ca2SThomas Gleixner static inline struct msi_desc *irq_get_msi_desc(unsigned int irq)
849f303a6ddSThomas Gleixner {
850f303a6ddSThomas Gleixner 	struct irq_data *d = irq_get_irq_data(irq);
851b237721cSJiang Liu 	return d ? d->common->msi_desc : NULL;
852f303a6ddSThomas Gleixner }
853f303a6ddSThomas Gleixner 
irq_data_get_msi_desc(struct irq_data * d)854c391f262SJiang Liu static inline struct msi_desc *irq_data_get_msi_desc(struct irq_data *d)
855f303a6ddSThomas Gleixner {
856b237721cSJiang Liu 	return d->common->msi_desc;
857f303a6ddSThomas Gleixner }
858f303a6ddSThomas Gleixner 
irq_get_trigger_type(unsigned int irq)8591f6236bfSJavier Martinez Canillas static inline u32 irq_get_trigger_type(unsigned int irq)
8601f6236bfSJavier Martinez Canillas {
8611f6236bfSJavier Martinez Canillas 	struct irq_data *d = irq_get_irq_data(irq);
8621f6236bfSJavier Martinez Canillas 	return d ? irqd_get_trigger_type(d) : 0;
8631f6236bfSJavier Martinez Canillas }
8641f6236bfSJavier Martinez Canillas 
irq_common_data_get_node(struct irq_common_data * d)865449e9caeSJiang Liu static inline int irq_common_data_get_node(struct irq_common_data *d)
866449e9caeSJiang Liu {
867449e9caeSJiang Liu #ifdef CONFIG_NUMA
868449e9caeSJiang Liu 	return d->node;
869449e9caeSJiang Liu #else
870449e9caeSJiang Liu 	return 0;
871449e9caeSJiang Liu #endif
872449e9caeSJiang Liu }
873449e9caeSJiang Liu 
irq_data_get_node(struct irq_data * d)8746783011bSJiang Liu static inline int irq_data_get_node(struct irq_data *d)
8756783011bSJiang Liu {
876449e9caeSJiang Liu 	return irq_common_data_get_node(d->common);
8776783011bSJiang Liu }
8786783011bSJiang Liu 
8794d0b8298SSamuel Holland static inline
irq_data_get_affinity_mask(struct irq_data * d)8804d0b8298SSamuel Holland const struct cpumask *irq_data_get_affinity_mask(struct irq_data *d)
881961343d7SSamuel Holland {
882aa081358SSamuel Holland #ifdef CONFIG_SMP
883961343d7SSamuel Holland 	return d->common->affinity;
884aa081358SSamuel Holland #else
885aa081358SSamuel Holland 	return cpumask_of(0);
886aa081358SSamuel Holland #endif
887961343d7SSamuel Holland }
888961343d7SSamuel Holland 
irq_data_update_affinity(struct irq_data * d,const struct cpumask * m)889073352e9SSamuel Holland static inline void irq_data_update_affinity(struct irq_data *d,
890073352e9SSamuel Holland 					    const struct cpumask *m)
891073352e9SSamuel Holland {
892aa081358SSamuel Holland #ifdef CONFIG_SMP
893073352e9SSamuel Holland 	cpumask_copy(d->common->affinity, m);
894aa081358SSamuel Holland #endif
895073352e9SSamuel Holland }
896073352e9SSamuel Holland 
irq_get_affinity_mask(int irq)8974d0b8298SSamuel Holland static inline const struct cpumask *irq_get_affinity_mask(int irq)
898c64301a2SJiang Liu {
899c64301a2SJiang Liu 	struct irq_data *d = irq_get_irq_data(irq);
900c64301a2SJiang Liu 
901961343d7SSamuel Holland 	return d ? irq_data_get_affinity_mask(d) : NULL;
902c64301a2SJiang Liu }
903c64301a2SJiang Liu 
9040d3f5425SThomas Gleixner #ifdef CONFIG_GENERIC_IRQ_EFFECTIVE_AFF_MASK
9050d3f5425SThomas Gleixner static inline
irq_data_get_effective_affinity_mask(struct irq_data * d)9064d0b8298SSamuel Holland const struct cpumask *irq_data_get_effective_affinity_mask(struct irq_data *d)
9070d3f5425SThomas Gleixner {
9080d3f5425SThomas Gleixner 	return d->common->effective_affinity;
9090d3f5425SThomas Gleixner }
irq_data_update_effective_affinity(struct irq_data * d,const struct cpumask * m)9100d3f5425SThomas Gleixner static inline void irq_data_update_effective_affinity(struct irq_data *d,
9110d3f5425SThomas Gleixner 						      const struct cpumask *m)
9120d3f5425SThomas Gleixner {
9130d3f5425SThomas Gleixner 	cpumask_copy(d->common->effective_affinity, m);
9140d3f5425SThomas Gleixner }
9150d3f5425SThomas Gleixner #else
irq_data_update_effective_affinity(struct irq_data * d,const struct cpumask * m)9160d3f5425SThomas Gleixner static inline void irq_data_update_effective_affinity(struct irq_data *d,
9170d3f5425SThomas Gleixner 						      const struct cpumask *m)
9180d3f5425SThomas Gleixner {
9190d3f5425SThomas Gleixner }
9200d3f5425SThomas Gleixner static inline
irq_data_get_effective_affinity_mask(struct irq_data * d)9214d0b8298SSamuel Holland const struct cpumask *irq_data_get_effective_affinity_mask(struct irq_data *d)
9220d3f5425SThomas Gleixner {
923961343d7SSamuel Holland 	return irq_data_get_affinity_mask(d);
9240d3f5425SThomas Gleixner }
9250d3f5425SThomas Gleixner #endif
9260d3f5425SThomas Gleixner 
9274d0b8298SSamuel Holland static inline
irq_get_effective_affinity_mask(unsigned int irq)9284d0b8298SSamuel Holland const struct cpumask *irq_get_effective_affinity_mask(unsigned int irq)
9293e238012SThomas Gleixner {
9303e238012SThomas Gleixner 	struct irq_data *d = irq_get_irq_data(irq);
9313e238012SThomas Gleixner 
9323e238012SThomas Gleixner 	return d ? irq_data_get_effective_affinity_mask(d) : NULL;
9333e238012SThomas Gleixner }
9343e238012SThomas Gleixner 
93562a08ae2SThomas Gleixner unsigned int arch_dynirq_lower_bound(unsigned int from);
93662a08ae2SThomas Gleixner 
937b6873807SSebastian Andrzej Siewior int __irq_alloc_descs(int irq, unsigned int from, unsigned int cnt, int node,
938bec04037SDou Liyang 		      struct module *owner,
939bec04037SDou Liyang 		      const struct irq_affinity_desc *affinity);
940b6873807SSebastian Andrzej Siewior 
9412b5e7730SBartosz Golaszewski int __devm_irq_alloc_descs(struct device *dev, int irq, unsigned int from,
9422b5e7730SBartosz Golaszewski 			   unsigned int cnt, int node, struct module *owner,
943bec04037SDou Liyang 			   const struct irq_affinity_desc *affinity);
9442b5e7730SBartosz Golaszewski 
945ec53cf23SPaul Gortmaker /* use macros to avoid needing export.h for THIS_MODULE */
946ec53cf23SPaul Gortmaker #define irq_alloc_descs(irq, from, cnt, node)	\
94706ee6d57SThomas Gleixner 	__irq_alloc_descs(irq, from, cnt, node, THIS_MODULE, NULL)
948ec53cf23SPaul Gortmaker 
949ec53cf23SPaul Gortmaker #define irq_alloc_desc(node)			\
9504c7bcb51SHans de Goede 	irq_alloc_descs(-1, 1, 1, node)
951ec53cf23SPaul Gortmaker 
952ec53cf23SPaul Gortmaker #define irq_alloc_desc_at(at, node)		\
953ec53cf23SPaul Gortmaker 	irq_alloc_descs(at, at, 1, node)
954ec53cf23SPaul Gortmaker 
955ec53cf23SPaul Gortmaker #define irq_alloc_desc_from(from, node)		\
956ec53cf23SPaul Gortmaker 	irq_alloc_descs(-1, from, 1, node)
957b6873807SSebastian Andrzej Siewior 
95851906e77SAlexander Gordeev #define irq_alloc_descs_from(from, cnt, node)	\
95951906e77SAlexander Gordeev 	irq_alloc_descs(-1, from, cnt, node)
96051906e77SAlexander Gordeev 
9612b5e7730SBartosz Golaszewski #define devm_irq_alloc_descs(dev, irq, from, cnt, node)		\
9622b5e7730SBartosz Golaszewski 	__devm_irq_alloc_descs(dev, irq, from, cnt, node, THIS_MODULE, NULL)
9632b5e7730SBartosz Golaszewski 
9642b5e7730SBartosz Golaszewski #define devm_irq_alloc_desc(dev, node)				\
9654c7bcb51SHans de Goede 	devm_irq_alloc_descs(dev, -1, 1, 1, node)
9662b5e7730SBartosz Golaszewski 
9672b5e7730SBartosz Golaszewski #define devm_irq_alloc_desc_at(dev, at, node)			\
9682b5e7730SBartosz Golaszewski 	devm_irq_alloc_descs(dev, at, at, 1, node)
9692b5e7730SBartosz Golaszewski 
9702b5e7730SBartosz Golaszewski #define devm_irq_alloc_desc_from(dev, from, node)		\
9712b5e7730SBartosz Golaszewski 	devm_irq_alloc_descs(dev, -1, from, 1, node)
9722b5e7730SBartosz Golaszewski 
9732b5e7730SBartosz Golaszewski #define devm_irq_alloc_descs_from(dev, from, cnt, node)		\
9742b5e7730SBartosz Golaszewski 	devm_irq_alloc_descs(dev, -1, from, cnt, node)
9752b5e7730SBartosz Golaszewski 
9761f5a5b87SThomas Gleixner void irq_free_descs(unsigned int irq, unsigned int cnt);
irq_free_desc(unsigned int irq)9771f5a5b87SThomas Gleixner static inline void irq_free_desc(unsigned int irq)
9781f5a5b87SThomas Gleixner {
9791f5a5b87SThomas Gleixner 	irq_free_descs(irq, 1);
9801f5a5b87SThomas Gleixner }
9811f5a5b87SThomas Gleixner 
982c940e01cSThomas Gleixner #ifdef CONFIG_GENERIC_IRQ_LEGACY
983c940e01cSThomas Gleixner void irq_init_desc(unsigned int irq);
984c940e01cSThomas Gleixner #endif
985c940e01cSThomas Gleixner 
9867d828062SThomas Gleixner /**
9877d828062SThomas Gleixner  * struct irq_chip_regs - register offsets for struct irq_gci
9887d828062SThomas Gleixner  * @enable:	Enable register offset to reg_base
9897d828062SThomas Gleixner  * @disable:	Disable register offset to reg_base
9907d828062SThomas Gleixner  * @mask:	Mask register offset to reg_base
9917d828062SThomas Gleixner  * @ack:	Ack register offset to reg_base
9927d828062SThomas Gleixner  * @eoi:	Eoi register offset to reg_base
9937d828062SThomas Gleixner  * @type:	Type configuration register offset to reg_base
9947d828062SThomas Gleixner  * @polarity:	Polarity configuration register offset to reg_base
9957d828062SThomas Gleixner  */
9967d828062SThomas Gleixner struct irq_chip_regs {
9977d828062SThomas Gleixner 	unsigned long		enable;
9987d828062SThomas Gleixner 	unsigned long		disable;
9997d828062SThomas Gleixner 	unsigned long		mask;
10007d828062SThomas Gleixner 	unsigned long		ack;
10017d828062SThomas Gleixner 	unsigned long		eoi;
10027d828062SThomas Gleixner 	unsigned long		type;
10037d828062SThomas Gleixner 	unsigned long		polarity;
10047d828062SThomas Gleixner };
10057d828062SThomas Gleixner 
10067d828062SThomas Gleixner /**
10077d828062SThomas Gleixner  * struct irq_chip_type - Generic interrupt chip instance for a flow type
10087d828062SThomas Gleixner  * @chip:		The real interrupt chip which provides the callbacks
10097d828062SThomas Gleixner  * @regs:		Register offsets for this chip
10107d828062SThomas Gleixner  * @handler:		Flow handler associated with this chip
10117d828062SThomas Gleixner  * @type:		Chip can handle these flow types
1012899f0e66SGerlando Falauto  * @mask_cache_priv:	Cached mask register private to the chip type
1013899f0e66SGerlando Falauto  * @mask_cache:		Pointer to cached mask register
10147d828062SThomas Gleixner  *
10157d828062SThomas Gleixner  * A irq_generic_chip can have several instances of irq_chip_type when
10167d828062SThomas Gleixner  * it requires different functions and register offsets for different
10177d828062SThomas Gleixner  * flow types.
10187d828062SThomas Gleixner  */
10197d828062SThomas Gleixner struct irq_chip_type {
10207d828062SThomas Gleixner 	struct irq_chip		chip;
10217d828062SThomas Gleixner 	struct irq_chip_regs	regs;
10227d828062SThomas Gleixner 	irq_flow_handler_t	handler;
10237d828062SThomas Gleixner 	u32			type;
1024899f0e66SGerlando Falauto 	u32			mask_cache_priv;
1025899f0e66SGerlando Falauto 	u32			*mask_cache;
10267d828062SThomas Gleixner };
10277d828062SThomas Gleixner 
10287d828062SThomas Gleixner /**
10297d828062SThomas Gleixner  * struct irq_chip_generic - Generic irq chip data structure
10307d828062SThomas Gleixner  * @lock:		Lock to protect register and cache data access
10317d828062SThomas Gleixner  * @reg_base:		Register base address (virtual)
10322b280376SKevin Cernekee  * @reg_readl:		Alternate I/O accessor (defaults to readl if NULL)
10332b280376SKevin Cernekee  * @reg_writel:		Alternate I/O accessor (defaults to writel if NULL)
1034be9b22b6SBrian Norris  * @suspend:		Function called from core code on suspend once per
1035be9b22b6SBrian Norris  *			chip; can be useful instead of irq_chip::suspend to
1036be9b22b6SBrian Norris  *			handle chip details even when no interrupts are in use
1037be9b22b6SBrian Norris  * @resume:		Function called from core code on resume once per chip;
1038be9b22b6SBrian Norris  *			can be useful instead of irq_chip::suspend to handle
1039be9b22b6SBrian Norris  *			chip details even when no interrupts are in use
10407d828062SThomas Gleixner  * @irq_base:		Interrupt base nr for this chip
10417d828062SThomas Gleixner  * @irq_cnt:		Number of interrupts handled by this chip
1042899f0e66SGerlando Falauto  * @mask_cache:		Cached mask register shared between all chip types
10437d828062SThomas Gleixner  * @type_cache:		Cached type register
10447d828062SThomas Gleixner  * @polarity_cache:	Cached polarity register
10457d828062SThomas Gleixner  * @wake_enabled:	Interrupt can wakeup from suspend
10467d828062SThomas Gleixner  * @wake_active:	Interrupt is marked as an wakeup from suspend source
10477d828062SThomas Gleixner  * @num_ct:		Number of available irq_chip_type instances (usually 1)
10487d828062SThomas Gleixner  * @private:		Private data for non generic chip callbacks
1049088f40b7SThomas Gleixner  * @installed:		bitfield to denote installed interrupts
1050e8bd834fSGrant Likely  * @unused:		bitfield to denote unused interrupts
1051088f40b7SThomas Gleixner  * @domain:		irq domain pointer
1052cfefd21eSThomas Gleixner  * @list:		List head for keeping track of instances
10537d828062SThomas Gleixner  * @chip_types:		Array of interrupt irq_chip_types
10547d828062SThomas Gleixner  *
10557d828062SThomas Gleixner  * Note, that irq_chip_generic can have multiple irq_chip_type
10567d828062SThomas Gleixner  * implementations which can be associated to a particular irq line of
10577d828062SThomas Gleixner  * an irq_chip_generic instance. That allows to share and protect
10587d828062SThomas Gleixner  * state in an irq_chip_generic instance when we need to implement
10597d828062SThomas Gleixner  * different flow mechanisms (level/edge) for it.
10607d828062SThomas Gleixner  */
10617d828062SThomas Gleixner struct irq_chip_generic {
10627d828062SThomas Gleixner 	raw_spinlock_t		lock;
10637d828062SThomas Gleixner 	void __iomem		*reg_base;
10642b280376SKevin Cernekee 	u32			(*reg_readl)(void __iomem *addr);
10652b280376SKevin Cernekee 	void			(*reg_writel)(u32 val, void __iomem *addr);
1066be9b22b6SBrian Norris 	void			(*suspend)(struct irq_chip_generic *gc);
1067be9b22b6SBrian Norris 	void			(*resume)(struct irq_chip_generic *gc);
10687d828062SThomas Gleixner 	unsigned int		irq_base;
10697d828062SThomas Gleixner 	unsigned int		irq_cnt;
10707d828062SThomas Gleixner 	u32			mask_cache;
10717d828062SThomas Gleixner 	u32			type_cache;
10727d828062SThomas Gleixner 	u32			polarity_cache;
10737d828062SThomas Gleixner 	u32			wake_enabled;
10747d828062SThomas Gleixner 	u32			wake_active;
10757d828062SThomas Gleixner 	unsigned int		num_ct;
10767d828062SThomas Gleixner 	void			*private;
1077088f40b7SThomas Gleixner 	unsigned long		installed;
1078e8bd834fSGrant Likely 	unsigned long		unused;
1079088f40b7SThomas Gleixner 	struct irq_domain	*domain;
1080cfefd21eSThomas Gleixner 	struct list_head	list;
10817856e9f1SGustavo A. R. Silva 	struct irq_chip_type	chip_types[];
10827d828062SThomas Gleixner };
10837d828062SThomas Gleixner 
10847d828062SThomas Gleixner /**
10857d828062SThomas Gleixner  * enum irq_gc_flags - Initialization flags for generic irq chips
10867d828062SThomas Gleixner  * @IRQ_GC_INIT_MASK_CACHE:	Initialize the mask_cache by reading mask reg
10877d828062SThomas Gleixner  * @IRQ_GC_INIT_NESTED_LOCK:	Set the lock class of the irqs to nested for
10887d828062SThomas Gleixner  *				irq chips which need to call irq_set_wake() on
10897d828062SThomas Gleixner  *				the parent irq. Usually GPIO implementations
1090af80b0feSGerlando Falauto  * @IRQ_GC_MASK_CACHE_PER_TYPE:	Mask cache is chip type private
1091966dc736SThomas Gleixner  * @IRQ_GC_NO_MASK:		Do not calculate irq_data->mask
1092b7905595SKevin Cernekee  * @IRQ_GC_BE_IO:		Use big-endian register accesses (default: LE)
10937d828062SThomas Gleixner  */
10947d828062SThomas Gleixner enum irq_gc_flags {
10957d828062SThomas Gleixner 	IRQ_GC_INIT_MASK_CACHE		= 1 << 0,
10967d828062SThomas Gleixner 	IRQ_GC_INIT_NESTED_LOCK		= 1 << 1,
1097af80b0feSGerlando Falauto 	IRQ_GC_MASK_CACHE_PER_TYPE	= 1 << 2,
1098966dc736SThomas Gleixner 	IRQ_GC_NO_MASK			= 1 << 3,
1099b7905595SKevin Cernekee 	IRQ_GC_BE_IO			= 1 << 4,
11007d828062SThomas Gleixner };
11017d828062SThomas Gleixner 
1102088f40b7SThomas Gleixner /*
1103088f40b7SThomas Gleixner  * struct irq_domain_chip_generic - Generic irq chip data structure for irq domains
1104088f40b7SThomas Gleixner  * @irqs_per_chip:	Number of interrupts per chip
1105088f40b7SThomas Gleixner  * @num_chips:		Number of chips
1106088f40b7SThomas Gleixner  * @irq_flags_to_set:	IRQ* flags to set on irq setup
1107088f40b7SThomas Gleixner  * @irq_flags_to_clear:	IRQ* flags to clear on irq setup
1108088f40b7SThomas Gleixner  * @gc_flags:		Generic chip specific setup flags
1109088f40b7SThomas Gleixner  * @gc:			Array of pointers to generic interrupt chips
1110088f40b7SThomas Gleixner  */
1111088f40b7SThomas Gleixner struct irq_domain_chip_generic {
1112088f40b7SThomas Gleixner 	unsigned int		irqs_per_chip;
1113088f40b7SThomas Gleixner 	unsigned int		num_chips;
1114088f40b7SThomas Gleixner 	unsigned int		irq_flags_to_clear;
1115088f40b7SThomas Gleixner 	unsigned int		irq_flags_to_set;
1116088f40b7SThomas Gleixner 	enum irq_gc_flags	gc_flags;
11177856e9f1SGustavo A. R. Silva 	struct irq_chip_generic	*gc[];
1118088f40b7SThomas Gleixner };
1119088f40b7SThomas Gleixner 
11207d828062SThomas Gleixner /* Generic chip callback functions */
11217d828062SThomas Gleixner void irq_gc_noop(struct irq_data *d);
11227d828062SThomas Gleixner void irq_gc_mask_disable_reg(struct irq_data *d);
11237d828062SThomas Gleixner void irq_gc_mask_set_bit(struct irq_data *d);
11247d828062SThomas Gleixner void irq_gc_mask_clr_bit(struct irq_data *d);
11257d828062SThomas Gleixner void irq_gc_unmask_enable_reg(struct irq_data *d);
1126659fb32dSSimon Guinot void irq_gc_ack_set_bit(struct irq_data *d);
1127659fb32dSSimon Guinot void irq_gc_ack_clr_bit(struct irq_data *d);
112820608924SDoug Berger void irq_gc_mask_disable_and_ack_set(struct irq_data *d);
11297d828062SThomas Gleixner void irq_gc_eoi(struct irq_data *d);
11307d828062SThomas Gleixner int irq_gc_set_wake(struct irq_data *d, unsigned int on);
11317d828062SThomas Gleixner 
11327d828062SThomas Gleixner /* Setup functions for irq_chip_generic */
1133a5152c8aSBoris BREZILLON int irq_map_generic_chip(struct irq_domain *d, unsigned int virq,
1134a5152c8aSBoris BREZILLON 			 irq_hw_number_t hw_irq);
1135d319a299SJianmin Lv void irq_unmap_generic_chip(struct irq_domain *d, unsigned int virq);
11367d828062SThomas Gleixner struct irq_chip_generic *
11377d828062SThomas Gleixner irq_alloc_generic_chip(const char *name, int nr_ct, unsigned int irq_base,
11387d828062SThomas Gleixner 		       void __iomem *reg_base, irq_flow_handler_t handler);
11397d828062SThomas Gleixner void irq_setup_generic_chip(struct irq_chip_generic *gc, u32 msk,
11407d828062SThomas Gleixner 			    enum irq_gc_flags flags, unsigned int clr,
11417d828062SThomas Gleixner 			    unsigned int set);
11427d828062SThomas Gleixner int irq_setup_alt_chip(struct irq_data *d, unsigned int type);
1143cfefd21eSThomas Gleixner void irq_remove_generic_chip(struct irq_chip_generic *gc, u32 msk,
1144cfefd21eSThomas Gleixner 			     unsigned int clr, unsigned int set);
11457d828062SThomas Gleixner 
11461c3e3630SBartosz Golaszewski struct irq_chip_generic *
11471c3e3630SBartosz Golaszewski devm_irq_alloc_generic_chip(struct device *dev, const char *name, int num_ct,
11481c3e3630SBartosz Golaszewski 			    unsigned int irq_base, void __iomem *reg_base,
11491c3e3630SBartosz Golaszewski 			    irq_flow_handler_t handler);
115030fd8fc5SBartosz Golaszewski int devm_irq_setup_generic_chip(struct device *dev, struct irq_chip_generic *gc,
115130fd8fc5SBartosz Golaszewski 				u32 msk, enum irq_gc_flags flags,
115230fd8fc5SBartosz Golaszewski 				unsigned int clr, unsigned int set);
11531c3e3630SBartosz Golaszewski 
1154088f40b7SThomas Gleixner struct irq_chip_generic *irq_get_domain_generic_chip(struct irq_domain *d, unsigned int hw_irq);
1155f88eecfeSSebastian Frias 
1156f88eecfeSSebastian Frias int __irq_alloc_domain_generic_chips(struct irq_domain *d, int irqs_per_chip,
1157088f40b7SThomas Gleixner 				     int num_ct, const char *name,
1158088f40b7SThomas Gleixner 				     irq_flow_handler_t handler,
1159088f40b7SThomas Gleixner 				     unsigned int clr, unsigned int set,
1160088f40b7SThomas Gleixner 				     enum irq_gc_flags flags);
1161088f40b7SThomas Gleixner 
1162f88eecfeSSebastian Frias #define irq_alloc_domain_generic_chips(d, irqs_per_chip, num_ct, name,	\
1163f88eecfeSSebastian Frias 				       handler,	clr, set, flags)	\
1164f88eecfeSSebastian Frias ({									\
1165f88eecfeSSebastian Frias 	MAYBE_BUILD_BUG_ON(irqs_per_chip > 32);				\
1166f88eecfeSSebastian Frias 	__irq_alloc_domain_generic_chips(d, irqs_per_chip, num_ct, name,\
1167f88eecfeSSebastian Frias 					 handler, clr, set, flags);	\
1168f88eecfeSSebastian Frias })
1169088f40b7SThomas Gleixner 
irq_free_generic_chip(struct irq_chip_generic * gc)1170707188f5SBartosz Golaszewski static inline void irq_free_generic_chip(struct irq_chip_generic *gc)
1171707188f5SBartosz Golaszewski {
1172707188f5SBartosz Golaszewski 	kfree(gc);
1173707188f5SBartosz Golaszewski }
1174707188f5SBartosz Golaszewski 
irq_destroy_generic_chip(struct irq_chip_generic * gc,u32 msk,unsigned int clr,unsigned int set)117532bb6cbbSBartosz Golaszewski static inline void irq_destroy_generic_chip(struct irq_chip_generic *gc,
117632bb6cbbSBartosz Golaszewski 					    u32 msk, unsigned int clr,
117732bb6cbbSBartosz Golaszewski 					    unsigned int set)
117832bb6cbbSBartosz Golaszewski {
117932bb6cbbSBartosz Golaszewski 	irq_remove_generic_chip(gc, msk, clr, set);
118032bb6cbbSBartosz Golaszewski 	irq_free_generic_chip(gc);
118132bb6cbbSBartosz Golaszewski }
118232bb6cbbSBartosz Golaszewski 
irq_data_get_chip_type(struct irq_data * d)11837d828062SThomas Gleixner static inline struct irq_chip_type *irq_data_get_chip_type(struct irq_data *d)
11847d828062SThomas Gleixner {
11857d828062SThomas Gleixner 	return container_of(d->chip, struct irq_chip_type, chip);
11867d828062SThomas Gleixner }
11877d828062SThomas Gleixner 
11887d828062SThomas Gleixner #define IRQ_MSK(n) (u32)((n) < 32 ? ((1 << (n)) - 1) : UINT_MAX)
11897d828062SThomas Gleixner 
11907d828062SThomas Gleixner #ifdef CONFIG_SMP
irq_gc_lock(struct irq_chip_generic * gc)11917d828062SThomas Gleixner static inline void irq_gc_lock(struct irq_chip_generic *gc)
11927d828062SThomas Gleixner {
11937d828062SThomas Gleixner 	raw_spin_lock(&gc->lock);
11947d828062SThomas Gleixner }
11957d828062SThomas Gleixner 
irq_gc_unlock(struct irq_chip_generic * gc)11967d828062SThomas Gleixner static inline void irq_gc_unlock(struct irq_chip_generic *gc)
11977d828062SThomas Gleixner {
11987d828062SThomas Gleixner 	raw_spin_unlock(&gc->lock);
11997d828062SThomas Gleixner }
12007d828062SThomas Gleixner #else
irq_gc_lock(struct irq_chip_generic * gc)12017d828062SThomas Gleixner static inline void irq_gc_lock(struct irq_chip_generic *gc) { }
irq_gc_unlock(struct irq_chip_generic * gc)12027d828062SThomas Gleixner static inline void irq_gc_unlock(struct irq_chip_generic *gc) { }
12037d828062SThomas Gleixner #endif
12047d828062SThomas Gleixner 
1205ebf9ff75SBoris Brezillon /*
1206ebf9ff75SBoris Brezillon  * The irqsave variants are for usage in non interrupt code. Do not use
1207ebf9ff75SBoris Brezillon  * them in irq_chip callbacks. Use irq_gc_lock() instead.
1208ebf9ff75SBoris Brezillon  */
1209ebf9ff75SBoris Brezillon #define irq_gc_lock_irqsave(gc, flags)	\
1210ebf9ff75SBoris Brezillon 	raw_spin_lock_irqsave(&(gc)->lock, flags)
1211ebf9ff75SBoris Brezillon 
1212ebf9ff75SBoris Brezillon #define irq_gc_unlock_irqrestore(gc, flags)	\
1213ebf9ff75SBoris Brezillon 	raw_spin_unlock_irqrestore(&(gc)->lock, flags)
1214ebf9ff75SBoris Brezillon 
irq_reg_writel(struct irq_chip_generic * gc,u32 val,int reg_offset)1215332fd7c4SKevin Cernekee static inline void irq_reg_writel(struct irq_chip_generic *gc,
1216332fd7c4SKevin Cernekee 				  u32 val, int reg_offset)
1217332fd7c4SKevin Cernekee {
12182b280376SKevin Cernekee 	if (gc->reg_writel)
12192b280376SKevin Cernekee 		gc->reg_writel(val, gc->reg_base + reg_offset);
12202b280376SKevin Cernekee 	else
1221332fd7c4SKevin Cernekee 		writel(val, gc->reg_base + reg_offset);
1222332fd7c4SKevin Cernekee }
1223332fd7c4SKevin Cernekee 
irq_reg_readl(struct irq_chip_generic * gc,int reg_offset)1224332fd7c4SKevin Cernekee static inline u32 irq_reg_readl(struct irq_chip_generic *gc,
1225332fd7c4SKevin Cernekee 				int reg_offset)
1226332fd7c4SKevin Cernekee {
12272b280376SKevin Cernekee 	if (gc->reg_readl)
12282b280376SKevin Cernekee 		return gc->reg_readl(gc->reg_base + reg_offset);
12292b280376SKevin Cernekee 	else
1230332fd7c4SKevin Cernekee 		return readl(gc->reg_base + reg_offset);
1231332fd7c4SKevin Cernekee }
1232332fd7c4SKevin Cernekee 
12332f75d9e1SThomas Gleixner struct irq_matrix;
12342f75d9e1SThomas Gleixner struct irq_matrix *irq_alloc_matrix(unsigned int matrix_bits,
12352f75d9e1SThomas Gleixner 				    unsigned int alloc_start,
12362f75d9e1SThomas Gleixner 				    unsigned int alloc_end);
12372f75d9e1SThomas Gleixner void irq_matrix_online(struct irq_matrix *m);
12382f75d9e1SThomas Gleixner void irq_matrix_offline(struct irq_matrix *m);
12392f75d9e1SThomas Gleixner void irq_matrix_assign_system(struct irq_matrix *m, unsigned int bit, bool replace);
12402f75d9e1SThomas Gleixner int irq_matrix_reserve_managed(struct irq_matrix *m, const struct cpumask *msk);
12412f75d9e1SThomas Gleixner void irq_matrix_remove_managed(struct irq_matrix *m, const struct cpumask *msk);
124276f99ae5SDou Liyang int irq_matrix_alloc_managed(struct irq_matrix *m, const struct cpumask *msk,
124376f99ae5SDou Liyang 				unsigned int *mapped_cpu);
12442f75d9e1SThomas Gleixner void irq_matrix_reserve(struct irq_matrix *m);
12452f75d9e1SThomas Gleixner void irq_matrix_remove_reserved(struct irq_matrix *m);
12462f75d9e1SThomas Gleixner int irq_matrix_alloc(struct irq_matrix *m, const struct cpumask *msk,
12472f75d9e1SThomas Gleixner 		     bool reserved, unsigned int *mapped_cpu);
12482f75d9e1SThomas Gleixner void irq_matrix_free(struct irq_matrix *m, unsigned int cpu,
12492f75d9e1SThomas Gleixner 		     unsigned int bit, bool managed);
12502f75d9e1SThomas Gleixner void irq_matrix_assign(struct irq_matrix *m, unsigned int bit);
12512f75d9e1SThomas Gleixner unsigned int irq_matrix_available(struct irq_matrix *m, bool cpudown);
12522f75d9e1SThomas Gleixner unsigned int irq_matrix_allocated(struct irq_matrix *m);
12532f75d9e1SThomas Gleixner unsigned int irq_matrix_reserved(struct irq_matrix *m);
12542f75d9e1SThomas Gleixner void irq_matrix_debug_show(struct seq_file *sf, struct irq_matrix *m, int ind);
12552f75d9e1SThomas Gleixner 
1256d17bf24eSQais Yousef /* Contrary to Linux irqs, for hardware irqs the irq number 0 is valid */
1257d17bf24eSQais Yousef #define INVALID_HWIRQ	(~0UL)
1258f9bce791SQais Yousef irq_hw_number_t ipi_get_hwirq(unsigned int irq, unsigned int cpu);
12593b8e29a8SQais Yousef int __ipi_send_single(struct irq_desc *desc, unsigned int cpu);
12603b8e29a8SQais Yousef int __ipi_send_mask(struct irq_desc *desc, const struct cpumask *dest);
12613b8e29a8SQais Yousef int ipi_send_single(unsigned int virq, unsigned int cpu);
12623b8e29a8SQais Yousef int ipi_send_mask(unsigned int virq, const struct cpumask *dest);
1263d17bf24eSQais Yousef 
1264835a486cSAnup Patel void ipi_mux_process(void);
1265835a486cSAnup Patel int ipi_mux_create(unsigned int nr_ipi, void (*mux_send)(unsigned int cpu));
1266835a486cSAnup Patel 
1267caacdbf4SPalmer Dabbelt #ifdef CONFIG_GENERIC_IRQ_MULTI_HANDLER
1268caacdbf4SPalmer Dabbelt /*
1269caacdbf4SPalmer Dabbelt  * Registers a generic IRQ handling function as the top-level IRQ handler in
1270caacdbf4SPalmer Dabbelt  * the system, which is generally the first C code called from an assembly
1271caacdbf4SPalmer Dabbelt  * architecture-specific interrupt handler.
1272caacdbf4SPalmer Dabbelt  *
1273caacdbf4SPalmer Dabbelt  * Returns 0 on success, or -EBUSY if an IRQ handler has already been
1274caacdbf4SPalmer Dabbelt  * registered.
1275caacdbf4SPalmer Dabbelt  */
1276caacdbf4SPalmer Dabbelt int __init set_handle_irq(void (*handle_irq)(struct pt_regs *));
1277caacdbf4SPalmer Dabbelt 
1278caacdbf4SPalmer Dabbelt /*
1279caacdbf4SPalmer Dabbelt  * Allows interrupt handlers to find the irqchip that's been registered as the
1280caacdbf4SPalmer Dabbelt  * top-level IRQ handler.
1281caacdbf4SPalmer Dabbelt  */
1282caacdbf4SPalmer Dabbelt extern void (*handle_arch_irq)(struct pt_regs *) __ro_after_init;
1283a1b09501SMark Rutland asmlinkage void generic_handle_arch_irq(struct pt_regs *regs);
1284ea0c80d1SZhen Lei #else
1285b0b8b689SMarc Zyngier #ifndef set_handle_irq
1286ea0c80d1SZhen Lei #define set_handle_irq(handle_irq)		\
1287ea0c80d1SZhen Lei 	do {					\
1288ea0c80d1SZhen Lei 		(void)handle_irq;		\
1289ea0c80d1SZhen Lei 		WARN_ON(1);			\
1290ea0c80d1SZhen Lei 	} while (0)
1291caacdbf4SPalmer Dabbelt #endif
1292b0b8b689SMarc Zyngier #endif
1293caacdbf4SPalmer Dabbelt 
129406fcb0c6SIngo Molnar #endif /* _LINUX_IRQ_H */
1295