|
@@ -53,12 +53,13 @@ typedef void (*irq_preflow_handler_t)(struct irq_data *data);
|
|
* Bits which can be modified via irq_set/clear/modify_status_flags()
|
|
* Bits which can be modified via irq_set/clear/modify_status_flags()
|
|
* IRQ_LEVEL - Interrupt is level type. Will be also
|
|
* IRQ_LEVEL - Interrupt is level type. Will be also
|
|
* updated in the code when the above trigger
|
|
* updated in the code when the above trigger
|
|
- * bits are modified via set_irq_type()
|
|
|
|
|
|
+ * bits are modified via irq_set_irq_type()
|
|
* IRQ_PER_CPU - Mark an interrupt PER_CPU. Will protect
|
|
* IRQ_PER_CPU - Mark an interrupt PER_CPU. Will protect
|
|
* it from affinity setting
|
|
* it from affinity setting
|
|
* IRQ_NOPROBE - Interrupt cannot be probed by autoprobing
|
|
* IRQ_NOPROBE - Interrupt cannot be probed by autoprobing
|
|
* IRQ_NOREQUEST - Interrupt cannot be requested via
|
|
* IRQ_NOREQUEST - Interrupt cannot be requested via
|
|
* request_irq()
|
|
* request_irq()
|
|
|
|
+ * IRQ_NOTHREAD - Interrupt cannot be threaded
|
|
* IRQ_NOAUTOEN - Interrupt is not automatically enabled in
|
|
* IRQ_NOAUTOEN - Interrupt is not automatically enabled in
|
|
* request/setup_irq()
|
|
* request/setup_irq()
|
|
* IRQ_NO_BALANCING - Interrupt cannot be balanced (affinity set)
|
|
* IRQ_NO_BALANCING - Interrupt cannot be balanced (affinity set)
|
|
@@ -85,6 +86,7 @@ enum {
|
|
IRQ_NO_BALANCING = (1 << 13),
|
|
IRQ_NO_BALANCING = (1 << 13),
|
|
IRQ_MOVE_PCNTXT = (1 << 14),
|
|
IRQ_MOVE_PCNTXT = (1 << 14),
|
|
IRQ_NESTED_THREAD = (1 << 15),
|
|
IRQ_NESTED_THREAD = (1 << 15),
|
|
|
|
+ IRQ_NOTHREAD = (1 << 16),
|
|
};
|
|
};
|
|
|
|
|
|
#define IRQF_MODIFY_MASK \
|
|
#define IRQF_MODIFY_MASK \
|
|
@@ -261,23 +263,6 @@ static inline void irqd_clr_chained_irq_inprogress(struct irq_data *d)
|
|
* struct irq_chip - hardware interrupt chip descriptor
|
|
* struct irq_chip - hardware interrupt chip descriptor
|
|
*
|
|
*
|
|
* @name: name for /proc/interrupts
|
|
* @name: name for /proc/interrupts
|
|
- * @startup: deprecated, replaced by irq_startup
|
|
|
|
- * @shutdown: deprecated, replaced by irq_shutdown
|
|
|
|
- * @enable: deprecated, replaced by irq_enable
|
|
|
|
- * @disable: deprecated, replaced by irq_disable
|
|
|
|
- * @ack: deprecated, replaced by irq_ack
|
|
|
|
- * @mask: deprecated, replaced by irq_mask
|
|
|
|
- * @mask_ack: deprecated, replaced by irq_mask_ack
|
|
|
|
- * @unmask: deprecated, replaced by irq_unmask
|
|
|
|
- * @eoi: deprecated, replaced by irq_eoi
|
|
|
|
- * @end: deprecated, will go away with __do_IRQ()
|
|
|
|
- * @set_affinity: deprecated, replaced by irq_set_affinity
|
|
|
|
- * @retrigger: deprecated, replaced by irq_retrigger
|
|
|
|
- * @set_type: deprecated, replaced by irq_set_type
|
|
|
|
- * @set_wake: deprecated, replaced by irq_wake
|
|
|
|
- * @bus_lock: deprecated, replaced by irq_bus_lock
|
|
|
|
- * @bus_sync_unlock: deprecated, replaced by irq_bus_sync_unlock
|
|
|
|
- *
|
|
|
|
* @irq_startup: start up the interrupt (defaults to ->enable if NULL)
|
|
* @irq_startup: start up the interrupt (defaults to ->enable if NULL)
|
|
* @irq_shutdown: shut down the interrupt (defaults to ->disable if NULL)
|
|
* @irq_shutdown: shut down the interrupt (defaults to ->disable if NULL)
|
|
* @irq_enable: enable the interrupt (defaults to chip->unmask if NULL)
|
|
* @irq_enable: enable the interrupt (defaults to chip->unmask if NULL)
|
|
@@ -295,6 +280,9 @@ static inline void irqd_clr_chained_irq_inprogress(struct irq_data *d)
|
|
* @irq_bus_sync_unlock:function to sync and unlock slow bus (i2c) chips
|
|
* @irq_bus_sync_unlock:function to sync and unlock slow bus (i2c) chips
|
|
* @irq_cpu_online: configure an interrupt source for a secondary CPU
|
|
* @irq_cpu_online: configure an interrupt source for a secondary CPU
|
|
* @irq_cpu_offline: un-configure an interrupt source for a secondary CPU
|
|
* @irq_cpu_offline: un-configure an interrupt source for a secondary CPU
|
|
|
|
+ * @irq_suspend: function called from core code on suspend once per chip
|
|
|
|
+ * @irq_resume: function called from core code on resume once per chip
|
|
|
|
+ * @irq_pm_shutdown: function called from core code on shutdown once per chip
|
|
* @irq_print_chip: optional to print special chip info in show_interrupts
|
|
* @irq_print_chip: optional to print special chip info in show_interrupts
|
|
* @flags: chip specific flags
|
|
* @flags: chip specific flags
|
|
*
|
|
*
|
|
@@ -324,6 +312,10 @@ struct irq_chip {
|
|
void (*irq_cpu_online)(struct irq_data *data);
|
|
void (*irq_cpu_online)(struct irq_data *data);
|
|
void (*irq_cpu_offline)(struct irq_data *data);
|
|
void (*irq_cpu_offline)(struct irq_data *data);
|
|
|
|
|
|
|
|
+ void (*irq_suspend)(struct irq_data *data);
|
|
|
|
+ void (*irq_resume)(struct irq_data *data);
|
|
|
|
+ void (*irq_pm_shutdown)(struct irq_data *data);
|
|
|
|
+
|
|
void (*irq_print_chip)(struct irq_data *data, struct seq_file *p);
|
|
void (*irq_print_chip)(struct irq_data *data, struct seq_file *p);
|
|
|
|
|
|
unsigned long flags;
|
|
unsigned long flags;
|
|
@@ -439,7 +431,7 @@ irq_set_handler(unsigned int irq, irq_flow_handler_t handle)
|
|
/*
|
|
/*
|
|
* Set a highlevel chained flow handler for a given IRQ.
|
|
* Set a highlevel chained flow handler for a given IRQ.
|
|
* (a chained handler is automatically enabled and set to
|
|
* (a chained handler is automatically enabled and set to
|
|
- * IRQ_NOREQUEST and IRQ_NOPROBE)
|
|
|
|
|
|
+ * IRQ_NOREQUEST, IRQ_NOPROBE, and IRQ_NOTHREAD)
|
|
*/
|
|
*/
|
|
static inline void
|
|
static inline void
|
|
irq_set_chained_handler(unsigned int irq, irq_flow_handler_t handle)
|
|
irq_set_chained_handler(unsigned int irq, irq_flow_handler_t handle)
|
|
@@ -469,6 +461,16 @@ static inline void irq_set_probe(unsigned int irq)
|
|
irq_modify_status(irq, IRQ_NOPROBE, 0);
|
|
irq_modify_status(irq, IRQ_NOPROBE, 0);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+static inline void irq_set_nothread(unsigned int irq)
|
|
|
|
+{
|
|
|
|
+ irq_modify_status(irq, 0, IRQ_NOTHREAD);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static inline void irq_set_thread(unsigned int irq)
|
|
|
|
+{
|
|
|
|
+ irq_modify_status(irq, IRQ_NOTHREAD, 0);
|
|
|
|
+}
|
|
|
|
+
|
|
static inline void irq_set_nested_thread(unsigned int irq, bool nest)
|
|
static inline void irq_set_nested_thread(unsigned int irq, bool nest)
|
|
{
|
|
{
|
|
if (nest)
|
|
if (nest)
|
|
@@ -573,6 +575,145 @@ static inline int irq_reserve_irq(unsigned int irq)
|
|
return irq_reserve_irqs(irq, 1);
|
|
return irq_reserve_irqs(irq, 1);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+#ifndef irq_reg_writel
|
|
|
|
+# define irq_reg_writel(val, addr) writel(val, addr)
|
|
|
|
+#endif
|
|
|
|
+#ifndef irq_reg_readl
|
|
|
|
+# define irq_reg_readl(addr) readl(addr)
|
|
|
|
+#endif
|
|
|
|
+
|
|
|
|
+/**
|
|
|
|
+ * struct irq_chip_regs - register offsets for struct irq_gci
|
|
|
|
+ * @enable: Enable register offset to reg_base
|
|
|
|
+ * @disable: Disable register offset to reg_base
|
|
|
|
+ * @mask: Mask register offset to reg_base
|
|
|
|
+ * @ack: Ack register offset to reg_base
|
|
|
|
+ * @eoi: Eoi register offset to reg_base
|
|
|
|
+ * @type: Type configuration register offset to reg_base
|
|
|
|
+ * @polarity: Polarity configuration register offset to reg_base
|
|
|
|
+ */
|
|
|
|
+struct irq_chip_regs {
|
|
|
|
+ unsigned long enable;
|
|
|
|
+ unsigned long disable;
|
|
|
|
+ unsigned long mask;
|
|
|
|
+ unsigned long ack;
|
|
|
|
+ unsigned long eoi;
|
|
|
|
+ unsigned long type;
|
|
|
|
+ unsigned long polarity;
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+/**
|
|
|
|
+ * struct irq_chip_type - Generic interrupt chip instance for a flow type
|
|
|
|
+ * @chip: The real interrupt chip which provides the callbacks
|
|
|
|
+ * @regs: Register offsets for this chip
|
|
|
|
+ * @handler: Flow handler associated with this chip
|
|
|
|
+ * @type: Chip can handle these flow types
|
|
|
|
+ *
|
|
|
|
+ * A irq_generic_chip can have several instances of irq_chip_type when
|
|
|
|
+ * it requires different functions and register offsets for different
|
|
|
|
+ * flow types.
|
|
|
|
+ */
|
|
|
|
+struct irq_chip_type {
|
|
|
|
+ struct irq_chip chip;
|
|
|
|
+ struct irq_chip_regs regs;
|
|
|
|
+ irq_flow_handler_t handler;
|
|
|
|
+ u32 type;
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+/**
|
|
|
|
+ * struct irq_chip_generic - Generic irq chip data structure
|
|
|
|
+ * @lock: Lock to protect register and cache data access
|
|
|
|
+ * @reg_base: Register base address (virtual)
|
|
|
|
+ * @irq_base: Interrupt base nr for this chip
|
|
|
|
+ * @irq_cnt: Number of interrupts handled by this chip
|
|
|
|
+ * @mask_cache: Cached mask register
|
|
|
|
+ * @type_cache: Cached type register
|
|
|
|
+ * @polarity_cache: Cached polarity register
|
|
|
|
+ * @wake_enabled: Interrupt can wakeup from suspend
|
|
|
|
+ * @wake_active: Interrupt is marked as an wakeup from suspend source
|
|
|
|
+ * @num_ct: Number of available irq_chip_type instances (usually 1)
|
|
|
|
+ * @private: Private data for non generic chip callbacks
|
|
|
|
+ * @list: List head for keeping track of instances
|
|
|
|
+ * @chip_types: Array of interrupt irq_chip_types
|
|
|
|
+ *
|
|
|
|
+ * Note, that irq_chip_generic can have multiple irq_chip_type
|
|
|
|
+ * implementations which can be associated to a particular irq line of
|
|
|
|
+ * an irq_chip_generic instance. That allows to share and protect
|
|
|
|
+ * state in an irq_chip_generic instance when we need to implement
|
|
|
|
+ * different flow mechanisms (level/edge) for it.
|
|
|
|
+ */
|
|
|
|
+struct irq_chip_generic {
|
|
|
|
+ raw_spinlock_t lock;
|
|
|
|
+ void __iomem *reg_base;
|
|
|
|
+ unsigned int irq_base;
|
|
|
|
+ unsigned int irq_cnt;
|
|
|
|
+ u32 mask_cache;
|
|
|
|
+ u32 type_cache;
|
|
|
|
+ u32 polarity_cache;
|
|
|
|
+ u32 wake_enabled;
|
|
|
|
+ u32 wake_active;
|
|
|
|
+ unsigned int num_ct;
|
|
|
|
+ void *private;
|
|
|
|
+ struct list_head list;
|
|
|
|
+ struct irq_chip_type chip_types[0];
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+/**
|
|
|
|
+ * enum irq_gc_flags - Initialization flags for generic irq chips
|
|
|
|
+ * @IRQ_GC_INIT_MASK_CACHE: Initialize the mask_cache by reading mask reg
|
|
|
|
+ * @IRQ_GC_INIT_NESTED_LOCK: Set the lock class of the irqs to nested for
|
|
|
|
+ * irq chips which need to call irq_set_wake() on
|
|
|
|
+ * the parent irq. Usually GPIO implementations
|
|
|
|
+ */
|
|
|
|
+enum irq_gc_flags {
|
|
|
|
+ IRQ_GC_INIT_MASK_CACHE = 1 << 0,
|
|
|
|
+ IRQ_GC_INIT_NESTED_LOCK = 1 << 1,
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+/* Generic chip callback functions */
|
|
|
|
+void irq_gc_noop(struct irq_data *d);
|
|
|
|
+void irq_gc_mask_disable_reg(struct irq_data *d);
|
|
|
|
+void irq_gc_mask_set_bit(struct irq_data *d);
|
|
|
|
+void irq_gc_mask_clr_bit(struct irq_data *d);
|
|
|
|
+void irq_gc_unmask_enable_reg(struct irq_data *d);
|
|
|
|
+void irq_gc_ack(struct irq_data *d);
|
|
|
|
+void irq_gc_mask_disable_reg_and_ack(struct irq_data *d);
|
|
|
|
+void irq_gc_eoi(struct irq_data *d);
|
|
|
|
+int irq_gc_set_wake(struct irq_data *d, unsigned int on);
|
|
|
|
+
|
|
|
|
+/* Setup functions for irq_chip_generic */
|
|
|
|
+struct irq_chip_generic *
|
|
|
|
+irq_alloc_generic_chip(const char *name, int nr_ct, unsigned int irq_base,
|
|
|
|
+ void __iomem *reg_base, irq_flow_handler_t handler);
|
|
|
|
+void irq_setup_generic_chip(struct irq_chip_generic *gc, u32 msk,
|
|
|
|
+ enum irq_gc_flags flags, unsigned int clr,
|
|
|
|
+ unsigned int set);
|
|
|
|
+int irq_setup_alt_chip(struct irq_data *d, unsigned int type);
|
|
|
|
+void irq_remove_generic_chip(struct irq_chip_generic *gc, u32 msk,
|
|
|
|
+ unsigned int clr, unsigned int set);
|
|
|
|
+
|
|
|
|
+static inline struct irq_chip_type *irq_data_get_chip_type(struct irq_data *d)
|
|
|
|
+{
|
|
|
|
+ return container_of(d->chip, struct irq_chip_type, chip);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+#define IRQ_MSK(n) (u32)((n) < 32 ? ((1 << (n)) - 1) : UINT_MAX)
|
|
|
|
+
|
|
|
|
+#ifdef CONFIG_SMP
|
|
|
|
+static inline void irq_gc_lock(struct irq_chip_generic *gc)
|
|
|
|
+{
|
|
|
|
+ raw_spin_lock(&gc->lock);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static inline void irq_gc_unlock(struct irq_chip_generic *gc)
|
|
|
|
+{
|
|
|
|
+ raw_spin_unlock(&gc->lock);
|
|
|
|
+}
|
|
|
|
+#else
|
|
|
|
+static inline void irq_gc_lock(struct irq_chip_generic *gc) { }
|
|
|
|
+static inline void irq_gc_unlock(struct irq_chip_generic *gc) { }
|
|
|
|
+#endif
|
|
|
|
+
|
|
#endif /* CONFIG_GENERIC_HARDIRQS */
|
|
#endif /* CONFIG_GENERIC_HARDIRQS */
|
|
|
|
|
|
#endif /* !CONFIG_S390 */
|
|
#endif /* !CONFIG_S390 */
|