diff options
author | Thomas Gleixner <tglx@linutronix.de> | 2011-04-03 05:42:53 -0400 |
---|---|---|
committer | Thomas Gleixner <tglx@linutronix.de> | 2011-04-23 09:56:24 -0400 |
commit | 7d8280624797bbe2f5170bd3c85c75a8c9c74242 (patch) | |
tree | 8028581a9a51eeb3c168409b5645c68b7a32e7dd /include/linux/irq.h | |
parent | 7f1b1244e159a8490d7fb13667c6cb7e1e75046b (diff) |
genirq: Implement a generic interrupt chip
Implement a generic interrupt chip, which is configurable and is able
to handle the most common irq chip implementations.
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: linux-arm-kernel@lists.infradead.org
Tested-by: H Hartley Sweeten <hsweeten@visionengravers.com>
Tested-by: Tony Lindgren <tony@atomide.com>
Tested-by; Kevin Hilman <khilman@ti.com>
Diffstat (limited to 'include/linux/irq.h')
-rw-r--r-- | include/linux/irq.h | 135 |
1 files changed, 135 insertions, 0 deletions
diff --git a/include/linux/irq.h b/include/linux/irq.h index 39c23786c1db..2ba2f1216790 100644 --- a/include/linux/irq.h +++ b/include/linux/irq.h | |||
@@ -568,6 +568,141 @@ static inline int irq_reserve_irq(unsigned int irq) | |||
568 | return irq_reserve_irqs(irq, 1); | 568 | return irq_reserve_irqs(irq, 1); |
569 | } | 569 | } |
570 | 570 | ||
571 | #ifndef irq_reg_writel | ||
572 | # define irq_reg_writel(val, addr) writel(val, addr) | ||
573 | #endif | ||
574 | #ifndef irq_reg_readl | ||
575 | # define irq_reg_readl(addr) readl(addr) | ||
576 | #endif | ||
577 | |||
578 | /** | ||
579 | * struct irq_chip_regs - register offsets for struct irq_gci | ||
580 | * @enable: Enable register offset to reg_base | ||
581 | * @disable: Disable register offset to reg_base | ||
582 | * @mask: Mask register offset to reg_base | ||
583 | * @ack: Ack register offset to reg_base | ||
584 | * @eoi: Eoi register offset to reg_base | ||
585 | * @type: Type configuration register offset to reg_base | ||
586 | * @polarity: Polarity configuration register offset to reg_base | ||
587 | */ | ||
588 | struct irq_chip_regs { | ||
589 | unsigned long enable; | ||
590 | unsigned long disable; | ||
591 | unsigned long mask; | ||
592 | unsigned long ack; | ||
593 | unsigned long eoi; | ||
594 | unsigned long type; | ||
595 | unsigned long polarity; | ||
596 | }; | ||
597 | |||
598 | /** | ||
599 | * struct irq_chip_type - Generic interrupt chip instance for a flow type | ||
600 | * @chip: The real interrupt chip which provides the callbacks | ||
601 | * @regs: Register offsets for this chip | ||
602 | * @handler: Flow handler associated with this chip | ||
603 | * @type: Chip can handle these flow types | ||
604 | * | ||
605 | * A irq_generic_chip can have several instances of irq_chip_type when | ||
606 | * it requires different functions and register offsets for different | ||
607 | * flow types. | ||
608 | */ | ||
609 | struct irq_chip_type { | ||
610 | struct irq_chip chip; | ||
611 | struct irq_chip_regs regs; | ||
612 | irq_flow_handler_t handler; | ||
613 | u32 type; | ||
614 | }; | ||
615 | |||
616 | /** | ||
617 | * struct irq_chip_generic - Generic irq chip data structure | ||
618 | * @lock: Lock to protect register and cache data access | ||
619 | * @reg_base: Register base address (virtual) | ||
620 | * @irq_base: Interrupt base nr for this chip | ||
621 | * @irq_cnt: Number of interrupts handled by this chip | ||
622 | * @mask_cache: Cached mask register | ||
623 | * @type_cache: Cached type register | ||
624 | * @polarity_cache: Cached polarity register | ||
625 | * @wake_enabled: Interrupt can wakeup from suspend | ||
626 | * @wake_active: Interrupt is marked as an wakeup from suspend source | ||
627 | * @num_ct: Number of available irq_chip_type instances (usually 1) | ||
628 | * @private: Private data for non generic chip callbacks | ||
629 | * @chip_types: Array of interrupt irq_chip_types | ||
630 | * | ||
631 | * Note, that irq_chip_generic can have multiple irq_chip_type | ||
632 | * implementations which can be associated to a particular irq line of | ||
633 | * an irq_chip_generic instance. That allows to share and protect | ||
634 | * state in an irq_chip_generic instance when we need to implement | ||
635 | * different flow mechanisms (level/edge) for it. | ||
636 | */ | ||
637 | struct irq_chip_generic { | ||
638 | raw_spinlock_t lock; | ||
639 | void __iomem *reg_base; | ||
640 | unsigned int irq_base; | ||
641 | unsigned int irq_cnt; | ||
642 | u32 mask_cache; | ||
643 | u32 type_cache; | ||
644 | u32 polarity_cache; | ||
645 | u32 wake_enabled; | ||
646 | u32 wake_active; | ||
647 | unsigned int num_ct; | ||
648 | void *private; | ||
649 | struct irq_chip_type chip_types[0]; | ||
650 | }; | ||
651 | |||
652 | /** | ||
653 | * enum irq_gc_flags - Initialization flags for generic irq chips | ||
654 | * @IRQ_GC_INIT_MASK_CACHE: Initialize the mask_cache by reading mask reg | ||
655 | * @IRQ_GC_INIT_NESTED_LOCK: Set the lock class of the irqs to nested for | ||
656 | * irq chips which need to call irq_set_wake() on | ||
657 | * the parent irq. Usually GPIO implementations | ||
658 | */ | ||
659 | enum irq_gc_flags { | ||
660 | IRQ_GC_INIT_MASK_CACHE = 1 << 0, | ||
661 | IRQ_GC_INIT_NESTED_LOCK = 1 << 1, | ||
662 | }; | ||
663 | |||
664 | /* Generic chip callback functions */ | ||
665 | void irq_gc_noop(struct irq_data *d); | ||
666 | void irq_gc_mask_disable_reg(struct irq_data *d); | ||
667 | void irq_gc_mask_set_bit(struct irq_data *d); | ||
668 | void irq_gc_mask_clr_bit(struct irq_data *d); | ||
669 | void irq_gc_unmask_enable_reg(struct irq_data *d); | ||
670 | void irq_gc_ack(struct irq_data *d); | ||
671 | void irq_gc_mask_disable_reg_and_ack(struct irq_data *d); | ||
672 | void irq_gc_eoi(struct irq_data *d); | ||
673 | int irq_gc_set_wake(struct irq_data *d, unsigned int on); | ||
674 | |||
675 | /* Setup functions for irq_chip_generic */ | ||
676 | struct irq_chip_generic * | ||
677 | irq_alloc_generic_chip(const char *name, int nr_ct, unsigned int irq_base, | ||
678 | void __iomem *reg_base, irq_flow_handler_t handler); | ||
679 | void irq_setup_generic_chip(struct irq_chip_generic *gc, u32 msk, | ||
680 | enum irq_gc_flags flags, unsigned int clr, | ||
681 | unsigned int set); | ||
682 | int irq_setup_alt_chip(struct irq_data *d, unsigned int type); | ||
683 | |||
684 | static inline struct irq_chip_type *irq_data_get_chip_type(struct irq_data *d) | ||
685 | { | ||
686 | return container_of(d->chip, struct irq_chip_type, chip); | ||
687 | } | ||
688 | |||
689 | #define IRQ_MSK(n) (u32)((n) < 32 ? ((1 << (n)) - 1) : UINT_MAX) | ||
690 | |||
691 | #ifdef CONFIG_SMP | ||
692 | static inline void irq_gc_lock(struct irq_chip_generic *gc) | ||
693 | { | ||
694 | raw_spin_lock(&gc->lock); | ||
695 | } | ||
696 | |||
697 | static inline void irq_gc_unlock(struct irq_chip_generic *gc) | ||
698 | { | ||
699 | raw_spin_unlock(&gc->lock); | ||
700 | } | ||
701 | #else | ||
702 | static inline void irq_gc_lock(struct irq_chip_generic *gc) { } | ||
703 | static inline void irq_gc_unlock(struct irq_chip_generic *gc) { } | ||
704 | #endif | ||
705 | |||
571 | #endif /* CONFIG_GENERIC_HARDIRQS */ | 706 | #endif /* CONFIG_GENERIC_HARDIRQS */ |
572 | 707 | ||
573 | #endif /* !CONFIG_S390 */ | 708 | #endif /* !CONFIG_S390 */ |