root/arch/mips/txx9/generic/irq_tx4939.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. tx4939_irq_unmask
  2. tx4939_irq_mask
  3. tx4939_irq_mask_ack
  4. tx4939_irq_set_type
  5. tx4939_irq_set_pri
  6. tx4939_irq_init
  7. tx4939_irq

   1 /*
   2  * TX4939 irq routines
   3  * Based on linux/arch/mips/kernel/irq_txx9.c,
   4  *          and RBTX49xx patch from CELF patch archive.
   5  *
   6  * Copyright 2001, 2003-2005 MontaVista Software Inc.
   7  * Author: MontaVista Software, Inc.
   8  *         ahennessy@mvista.com
   9  *         source@mvista.com
  10  * Copyright (C) 2000-2001,2005-2007 Toshiba Corporation
  11  *
  12  * This file is subject to the terms and conditions of the GNU General Public
  13  * License.  See the file "COPYING" in the main directory of this archive
  14  * for more details.
  15  */
  16 /*
  17  * TX4939 defines 64 IRQs.
  18  * Similer to irq_txx9.c but different register layouts.
  19  */
  20 #include <linux/init.h>
  21 #include <linux/interrupt.h>
  22 #include <linux/irq.h>
  23 #include <linux/types.h>
  24 #include <asm/irq_cpu.h>
  25 #include <asm/txx9irq.h>
  26 #include <asm/txx9/tx4939.h>
  27 
  28 /* IRCER : Int. Control Enable */
  29 #define TXx9_IRCER_ICE  0x00000001
  30 
  31 /* IRCR : Int. Control */
  32 #define TXx9_IRCR_LOW   0x00000000
  33 #define TXx9_IRCR_HIGH  0x00000001
  34 #define TXx9_IRCR_DOWN  0x00000002
  35 #define TXx9_IRCR_UP    0x00000003
  36 #define TXx9_IRCR_EDGE(cr)      ((cr) & 0x00000002)
  37 
  38 /* IRSCR : Int. Status Control */
  39 #define TXx9_IRSCR_EIClrE       0x00000100
  40 #define TXx9_IRSCR_EIClr_MASK   0x0000000f
  41 
  42 /* IRCSR : Int. Current Status */
  43 #define TXx9_IRCSR_IF   0x00010000
  44 
  45 #define irc_dlevel      0
  46 #define irc_elevel      1
  47 
  48 static struct {
  49         unsigned char level;
  50         unsigned char mode;
  51 } tx4939irq[TX4939_NUM_IR] __read_mostly;
  52 
  53 static void tx4939_irq_unmask(struct irq_data *d)
  54 {
  55         unsigned int irq_nr = d->irq - TXX9_IRQ_BASE;
  56         u32 __iomem *lvlp;
  57         int ofs;
  58         if (irq_nr < 32) {
  59                 irq_nr--;
  60                 lvlp = &tx4939_ircptr->lvl[(irq_nr % 16) / 2].r;
  61         } else {
  62                 irq_nr -= 32;
  63                 lvlp = &tx4939_ircptr->lvl[8 + (irq_nr % 16) / 2].r;
  64         }
  65         ofs = (irq_nr & 16) + (irq_nr & 1) * 8;
  66         __raw_writel((__raw_readl(lvlp) & ~(0xff << ofs))
  67                      | (tx4939irq[irq_nr].level << ofs),
  68                      lvlp);
  69 }
  70 
  71 static inline void tx4939_irq_mask(struct irq_data *d)
  72 {
  73         unsigned int irq_nr = d->irq - TXX9_IRQ_BASE;
  74         u32 __iomem *lvlp;
  75         int ofs;
  76         if (irq_nr < 32) {
  77                 irq_nr--;
  78                 lvlp = &tx4939_ircptr->lvl[(irq_nr % 16) / 2].r;
  79         } else {
  80                 irq_nr -= 32;
  81                 lvlp = &tx4939_ircptr->lvl[8 + (irq_nr % 16) / 2].r;
  82         }
  83         ofs = (irq_nr & 16) + (irq_nr & 1) * 8;
  84         __raw_writel((__raw_readl(lvlp) & ~(0xff << ofs))
  85                      | (irc_dlevel << ofs),
  86                      lvlp);
  87         mmiowb();
  88 }
  89 
  90 static void tx4939_irq_mask_ack(struct irq_data *d)
  91 {
  92         unsigned int irq_nr = d->irq - TXX9_IRQ_BASE;
  93 
  94         tx4939_irq_mask(d);
  95         if (TXx9_IRCR_EDGE(tx4939irq[irq_nr].mode)) {
  96                 irq_nr--;
  97                 /* clear edge detection */
  98                 __raw_writel((TXx9_IRSCR_EIClrE | (irq_nr & 0xf))
  99                              << (irq_nr & 0x10),
 100                              &tx4939_ircptr->edc.r);
 101         }
 102 }
 103 
 104 static int tx4939_irq_set_type(struct irq_data *d, unsigned int flow_type)
 105 {
 106         unsigned int irq_nr = d->irq - TXX9_IRQ_BASE;
 107         u32 cr;
 108         u32 __iomem *crp;
 109         int ofs;
 110         int mode;
 111 
 112         if (flow_type & IRQF_TRIGGER_PROBE)
 113                 return 0;
 114         switch (flow_type & IRQF_TRIGGER_MASK) {
 115         case IRQF_TRIGGER_RISING:
 116                 mode = TXx9_IRCR_UP;
 117                 break;
 118         case IRQF_TRIGGER_FALLING:
 119                 mode = TXx9_IRCR_DOWN;
 120                 break;
 121         case IRQF_TRIGGER_HIGH:
 122                 mode = TXx9_IRCR_HIGH;
 123                 break;
 124         case IRQF_TRIGGER_LOW:
 125                 mode = TXx9_IRCR_LOW;
 126                 break;
 127         default:
 128                 return -EINVAL;
 129         }
 130         if (irq_nr < 32) {
 131                 irq_nr--;
 132                 crp = &tx4939_ircptr->dm[(irq_nr & 8) >> 3].r;
 133         } else {
 134                 irq_nr -= 32;
 135                 crp = &tx4939_ircptr->dm2[((irq_nr & 8) >> 3)].r;
 136         }
 137         ofs = (((irq_nr & 16) >> 1) | (irq_nr & (8 - 1))) * 2;
 138         cr = __raw_readl(crp);
 139         cr &= ~(0x3 << ofs);
 140         cr |= (mode & 0x3) << ofs;
 141         __raw_writel(cr, crp);
 142         tx4939irq[irq_nr].mode = mode;
 143         return 0;
 144 }
 145 
 146 static struct irq_chip tx4939_irq_chip = {
 147         .name           = "TX4939",
 148         .irq_ack        = tx4939_irq_mask_ack,
 149         .irq_mask       = tx4939_irq_mask,
 150         .irq_mask_ack   = tx4939_irq_mask_ack,
 151         .irq_unmask     = tx4939_irq_unmask,
 152         .irq_set_type   = tx4939_irq_set_type,
 153 };
 154 
 155 static int tx4939_irq_set_pri(int irc_irq, int new_pri)
 156 {
 157         int old_pri;
 158 
 159         if ((unsigned int)irc_irq >= TX4939_NUM_IR)
 160                 return 0;
 161         old_pri = tx4939irq[irc_irq].level;
 162         tx4939irq[irc_irq].level = new_pri;
 163         return old_pri;
 164 }
 165 
 166 void __init tx4939_irq_init(void)
 167 {
 168         int i;
 169 
 170         mips_cpu_irq_init();
 171         /* disable interrupt control */
 172         __raw_writel(0, &tx4939_ircptr->den.r);
 173         __raw_writel(0, &tx4939_ircptr->maskint.r);
 174         __raw_writel(0, &tx4939_ircptr->maskext.r);
 175         /* irq_base + 0 is not used */
 176         for (i = 1; i < TX4939_NUM_IR; i++) {
 177                 tx4939irq[i].level = 4; /* middle level */
 178                 tx4939irq[i].mode = TXx9_IRCR_LOW;
 179                 irq_set_chip_and_handler(TXX9_IRQ_BASE + i, &tx4939_irq_chip,
 180                                          handle_level_irq);
 181         }
 182 
 183         /* mask all IRC interrupts */
 184         __raw_writel(0, &tx4939_ircptr->msk.r);
 185         for (i = 0; i < 16; i++)
 186                 __raw_writel(0, &tx4939_ircptr->lvl[i].r);
 187         /* setup IRC interrupt mode (Low Active) */
 188         for (i = 0; i < 2; i++)
 189                 __raw_writel(0, &tx4939_ircptr->dm[i].r);
 190         for (i = 0; i < 2; i++)
 191                 __raw_writel(0, &tx4939_ircptr->dm2[i].r);
 192         /* enable interrupt control */
 193         __raw_writel(TXx9_IRCER_ICE, &tx4939_ircptr->den.r);
 194         __raw_writel(irc_elevel, &tx4939_ircptr->msk.r);
 195 
 196         irq_set_chained_handler(MIPS_CPU_IRQ_BASE + TX4939_IRC_INT,
 197                                 handle_simple_irq);
 198 
 199         /* raise priority for errors, timers, sio */
 200         tx4939_irq_set_pri(TX4939_IR_WTOERR, 7);
 201         tx4939_irq_set_pri(TX4939_IR_PCIERR, 7);
 202         tx4939_irq_set_pri(TX4939_IR_PCIPME, 7);
 203         for (i = 0; i < TX4939_NUM_IR_TMR; i++)
 204                 tx4939_irq_set_pri(TX4939_IR_TMR(i), 6);
 205         for (i = 0; i < TX4939_NUM_IR_SIO; i++)
 206                 tx4939_irq_set_pri(TX4939_IR_SIO(i), 5);
 207 }
 208 
 209 int tx4939_irq(void)
 210 {
 211         u32 csr = __raw_readl(&tx4939_ircptr->cs.r);
 212 
 213         if (likely(!(csr & TXx9_IRCSR_IF)))
 214                 return TXX9_IRQ_BASE + (csr & (TX4939_NUM_IR - 1));
 215         return -1;
 216 }

/* [<][>][^][v][top][bottom][index][help] */