Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  *  GT641xx IRQ routines.
0004  *
0005  *  Copyright (C) 2007  Yoichi Yuasa <yuasa@linux-mips.org>
0006  */
0007 #include <linux/hardirq.h>
0008 #include <linux/init.h>
0009 #include <linux/irq.h>
0010 #include <linux/spinlock.h>
0011 #include <linux/types.h>
0012 
0013 #include <asm/gt64120.h>
0014 
0015 #define GT641XX_IRQ_TO_BIT(irq) (1U << (irq - GT641XX_IRQ_BASE))
0016 
0017 static DEFINE_RAW_SPINLOCK(gt641xx_irq_lock);
0018 
0019 static void ack_gt641xx_irq(struct irq_data *d)
0020 {
0021     unsigned long flags;
0022     u32 cause;
0023 
0024     raw_spin_lock_irqsave(&gt641xx_irq_lock, flags);
0025     cause = GT_READ(GT_INTRCAUSE_OFS);
0026     cause &= ~GT641XX_IRQ_TO_BIT(d->irq);
0027     GT_WRITE(GT_INTRCAUSE_OFS, cause);
0028     raw_spin_unlock_irqrestore(&gt641xx_irq_lock, flags);
0029 }
0030 
0031 static void mask_gt641xx_irq(struct irq_data *d)
0032 {
0033     unsigned long flags;
0034     u32 mask;
0035 
0036     raw_spin_lock_irqsave(&gt641xx_irq_lock, flags);
0037     mask = GT_READ(GT_INTRMASK_OFS);
0038     mask &= ~GT641XX_IRQ_TO_BIT(d->irq);
0039     GT_WRITE(GT_INTRMASK_OFS, mask);
0040     raw_spin_unlock_irqrestore(&gt641xx_irq_lock, flags);
0041 }
0042 
0043 static void mask_ack_gt641xx_irq(struct irq_data *d)
0044 {
0045     unsigned long flags;
0046     u32 cause, mask;
0047 
0048     raw_spin_lock_irqsave(&gt641xx_irq_lock, flags);
0049     mask = GT_READ(GT_INTRMASK_OFS);
0050     mask &= ~GT641XX_IRQ_TO_BIT(d->irq);
0051     GT_WRITE(GT_INTRMASK_OFS, mask);
0052 
0053     cause = GT_READ(GT_INTRCAUSE_OFS);
0054     cause &= ~GT641XX_IRQ_TO_BIT(d->irq);
0055     GT_WRITE(GT_INTRCAUSE_OFS, cause);
0056     raw_spin_unlock_irqrestore(&gt641xx_irq_lock, flags);
0057 }
0058 
0059 static void unmask_gt641xx_irq(struct irq_data *d)
0060 {
0061     unsigned long flags;
0062     u32 mask;
0063 
0064     raw_spin_lock_irqsave(&gt641xx_irq_lock, flags);
0065     mask = GT_READ(GT_INTRMASK_OFS);
0066     mask |= GT641XX_IRQ_TO_BIT(d->irq);
0067     GT_WRITE(GT_INTRMASK_OFS, mask);
0068     raw_spin_unlock_irqrestore(&gt641xx_irq_lock, flags);
0069 }
0070 
0071 static struct irq_chip gt641xx_irq_chip = {
0072     .name       = "GT641xx",
0073     .irq_ack    = ack_gt641xx_irq,
0074     .irq_mask   = mask_gt641xx_irq,
0075     .irq_mask_ack   = mask_ack_gt641xx_irq,
0076     .irq_unmask = unmask_gt641xx_irq,
0077 };
0078 
0079 void gt641xx_irq_dispatch(void)
0080 {
0081     u32 cause, mask;
0082     int i;
0083 
0084     cause = GT_READ(GT_INTRCAUSE_OFS);
0085     mask = GT_READ(GT_INTRMASK_OFS);
0086     cause &= mask;
0087 
0088     /*
0089      * bit0 : logical or of all the interrupt bits.
0090      * bit30: logical or of bits[29:26,20:1].
0091      * bit31: logical or of bits[25:1].
0092      */
0093     for (i = 1; i < 30; i++) {
0094         if (cause & (1U << i)) {
0095             do_IRQ(GT641XX_IRQ_BASE + i);
0096             return;
0097         }
0098     }
0099 
0100     atomic_inc(&irq_err_count);
0101 }
0102 
0103 void __init gt641xx_irq_init(void)
0104 {
0105     int i;
0106 
0107     GT_WRITE(GT_INTRMASK_OFS, 0);
0108     GT_WRITE(GT_INTRCAUSE_OFS, 0);
0109 
0110     /*
0111      * bit0 : logical or of all the interrupt bits.
0112      * bit30: logical or of bits[29:26,20:1].
0113      * bit31: logical or of bits[25:1].
0114      */
0115     for (i = 1; i < 30; i++)
0116         irq_set_chip_and_handler(GT641XX_IRQ_BASE + i,
0117                      &gt641xx_irq_chip, handle_level_irq);
0118 }