Changeset 8743


Ignore:
Timestamp:
2007-09-11T15:07:52+02:00 (10 years ago)
Author:
ejka
Message:

AR7: IRQ handlng cleanup

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/target/linux/ar7/files/arch/mips/ar7/irq.c

    r7487 r8743  
    11/* 
    22 * $Id$ 
    3  *  
     3 * 
    44 * Copyright (C) 2006, 2007 OpenWrt.org 
    5  *  
     5 * 
    66 * This program is free software; you can redistribute it and/or modify 
    77 * it under the terms of the GNU General Public License as published by 
    88 * the Free Software Foundation; either version 2 of the License, or 
    99 * (at your option) any later version. 
    10  *  
     10 * 
    1111 * This program is distributed in the hope that it will be useful, 
    1212 * but WITHOUT ANY WARRANTY; without even the implied warranty of 
    1313 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
    1414 * GNU General Public License for more details. 
    15  *  
     15 * 
    1616 * You should have received a copy of the GNU General Public License 
    1717 * along with this program; if not, write to the Free Software 
     
    1919 */ 
    2020 
    21 #include <linux/init.h> 
    2221#include <linux/interrupt.h> 
    23 #include <linux/ioport.h> 
     22#include <linux/io.h> 
    2423 
    25 #include <asm/irq.h> 
    2624#include <asm/irq_cpu.h> 
    2725#include <asm/mipsregs.h> 
     
    4644#define TM_OFFSET(irq)  (REG_OFFSET(irq, 6))    /* 0x60 */ 
    4745 
    48 #define REG(addr) (*(volatile u32 *)(KSEG1ADDR(AR7_REGS_IRQ) + addr)) 
     46#define REG(addr) ((u32 *)(KSEG1ADDR(AR7_REGS_IRQ) + addr)) 
    4947 
    5048#define CHNL_OFFSET(chnl) (CHNLS_OFFSET + (chnl * 4)) 
     
    5250static void ar7_unmask_irq(unsigned int irq_nr); 
    5351static void ar7_mask_irq(unsigned int irq_nr); 
    54 static void ar7_unmask_secondary_irq(unsigned int irq_nr); 
    55 static void ar7_mask_secondary_irq(unsigned int irq_nr); 
    56 static irqreturn_t ar7_cascade(int interrupt, void *dev); 
    57 static irqreturn_t ar7_secondary_cascade(int interrupt, void *dev); 
     52static void ar7_ack_irq(unsigned int irq_nr); 
     53static void ar7_unmask_sec_irq(unsigned int irq_nr); 
     54static void ar7_mask_sec_irq(unsigned int irq_nr); 
     55static void ar7_ack_sec_irq(unsigned int irq_nr); 
     56static void ar7_cascade(void); 
    5857static void ar7_irq_init(int base); 
    5958static int ar7_irq_base; 
    6059 
    6160static struct irq_chip ar7_irq_type = { 
    62         .typename = "AR7", 
    6361        .name = "AR7", 
    6462        .unmask = ar7_unmask_irq, 
    6563        .mask = ar7_mask_irq, 
     64        .ack = ar7_ack_irq 
    6665}; 
    6766 
    68 static struct irq_chip ar7_secondary_irq_type = { 
     67static struct irq_chip ar7_sec_irq_type = { 
    6968        .name = "AR7", 
    70         .unmask = ar7_unmask_secondary_irq, 
    71         .mask = ar7_mask_secondary_irq, 
     69        .unmask = ar7_unmask_sec_irq, 
     70        .mask = ar7_mask_sec_irq, 
     71        .ack = ar7_ack_sec_irq, 
    7272}; 
    7373 
    7474static struct irqaction ar7_cascade_action = { 
    75         .handler = ar7_cascade,  
     75        .handler = no_action, 
    7676        .name = "AR7 cascade interrupt" 
    7777}; 
    7878 
    79 static struct irqaction ar7_secondary_cascade_action = { 
    80         .handler = ar7_secondary_cascade,  
     79static struct irqaction ar7_sec_cascade_action = { 
     80        .handler = no_action, 
    8181        .name = "AR7 secondary cascade interrupt" 
    8282}; 
     
    8484static void ar7_unmask_irq(unsigned int irq) 
    8585{ 
    86         unsigned long flags; 
    87         local_irq_save(flags); 
    88         /* enable the interrupt channel  bit */ 
    89         REG(ESR_OFFSET(irq)) = 1 << ((irq - ar7_irq_base) % 32); 
    90         local_irq_restore(flags); 
     86        writel(1 << ((irq - ar7_irq_base) % 32), 
     87               REG(ESR_OFFSET(irq - ar7_irq_base))); 
    9188} 
    9289 
    9390static void ar7_mask_irq(unsigned int irq) 
    9491{ 
    95         unsigned long flags; 
    96         local_irq_save(flags); 
    97         /* disable the interrupt channel bit */ 
    98         REG(ECR_OFFSET(irq)) = 1 << ((irq - ar7_irq_base) % 32); 
    99         local_irq_restore(flags); 
     92        writel(1 << ((irq - ar7_irq_base) % 32), 
     93               REG(ECR_OFFSET(irq - ar7_irq_base))); 
    10094} 
    10195 
    102 static void ar7_unmask_secondary_irq(unsigned int irq) 
     96static void ar7_ack_irq(unsigned int irq) 
    10397{ 
    104         unsigned long flags; 
    105         local_irq_save(flags); 
    106         /* enable the interrupt channel  bit */ 
    107         REG(SEC_ESR_OFFSET) = 1 << (irq - ar7_irq_base - 40); 
    108         local_irq_restore(flags); 
     98        writel(1 << ((irq - ar7_irq_base) % 32), 
     99               REG(CR_OFFSET(irq - ar7_irq_base))); 
    109100} 
    110101 
    111 static void ar7_mask_secondary_irq(unsigned int irq) 
     102static void ar7_unmask_sec_irq(unsigned int irq) 
    112103{ 
    113         unsigned long flags; 
    114         local_irq_save(flags); 
    115         /* disable the interrupt channel bit */ 
    116         REG(SEC_ECR_OFFSET) = 1 << (irq - ar7_irq_base - 40); 
    117         local_irq_restore(flags); 
     104        writel(1 << (irq - ar7_irq_base - 40), REG(SEC_ESR_OFFSET)); 
     105} 
     106 
     107static void ar7_mask_sec_irq(unsigned int irq) 
     108{ 
     109        writel(1 << (irq - ar7_irq_base - 40), REG(SEC_ECR_OFFSET)); 
     110} 
     111 
     112static void ar7_ack_sec_irq(unsigned int irq) 
     113{ 
     114        writel(1 << (irq - ar7_irq_base - 40), REG(SEC_CR_OFFSET)); 
    118115} 
    119116 
     
    126123{ 
    127124        int i; 
    128         /*   
    129            Disable interrupts and clear pending 
    130         */ 
    131         REG(ECR_OFFSET(0)) = 0xffffffff; 
    132         REG(ECR_OFFSET(32)) = 0xff; 
    133         REG(SEC_ECR_OFFSET) = 0xffffffff; 
    134         REG(CR_OFFSET(0)) = 0xffffffff; 
    135         REG(CR_OFFSET(32)) = 0xff; 
    136         REG(SEC_CR_OFFSET) = 0xffffffff; 
     125        /* 
     126         * Disable interrupts and clear pending 
     127         */ 
     128        writel(0xffffffff, REG(ECR_OFFSET(0))); 
     129        writel(0xff, REG(ECR_OFFSET(32))); 
     130        writel(0xffffffff, REG(SEC_ECR_OFFSET)); 
     131        writel(0xffffffff, REG(CR_OFFSET(0))); 
     132        writel(0xff, REG(CR_OFFSET(32))); 
     133        writel(0xffffffff, REG(SEC_CR_OFFSET)); 
    137134 
    138135        ar7_irq_base = base; 
    139136 
    140         for(i = 0; i < 40; i++) { 
    141                 REG(CHNL_OFFSET(i)) = i; 
     137        for (i = 0; i < 40; i++) { 
     138                writel(i, REG(CHNL_OFFSET(i))); 
    142139                /* Primary IRQ's */ 
    143                 irq_desc[i + base].status = IRQ_DISABLED; 
    144                 irq_desc[i + base].action = NULL; 
    145                 irq_desc[i + base].depth = 1; 
    146                 irq_desc[i + base].chip = &ar7_irq_type; 
     140                set_irq_chip_and_handler(base + i, &ar7_irq_type, 
     141                                         handle_level_irq); 
    147142                /* Secondary IRQ's */ 
    148                 if (i < 32) { 
    149                         irq_desc[i + base + 40].status = IRQ_DISABLED; 
    150                         irq_desc[i + base + 40].action = NULL; 
    151                         irq_desc[i + base + 40].depth = 1; 
    152                         irq_desc[i + base + 40].chip = &ar7_secondary_irq_type; 
    153                 } 
     143                if (i < 32) 
     144                        set_irq_chip_and_handler(base + i + 40, 
     145                                                 &ar7_sec_irq_type, 
     146                                                 handle_level_irq); 
    154147        } 
    155148 
    156149        setup_irq(2, &ar7_cascade_action); 
    157         setup_irq(ar7_irq_base, &ar7_secondary_cascade_action); 
     150        setup_irq(ar7_irq_base, &ar7_sec_cascade_action); 
    158151        set_c0_status(IE_IRQ0); 
    159152} 
    160153 
    161 static irqreturn_t ar7_cascade(int interrupt, void *dev) 
     154static void ar7_cascade(void) 
    162155{ 
    163         int irq; 
     156        u32 status; 
     157        int i, irq; 
    164158 
    165         irq = (REG(PIR_OFFSET) & 0x3F); 
    166         REG(CR_OFFSET(irq)) = 1 << (irq % 32); 
    167  
    168         do_IRQ(irq + ar7_irq_base); 
    169  
    170         return IRQ_HANDLED; 
    171 } 
    172  
    173 static irqreturn_t ar7_secondary_cascade(int interrupt, void *dev) 
    174 { 
    175         int irq = 0, i; 
    176         unsigned long status; 
    177  
    178         status = REG(SEC_SR_OFFSET); 
    179         if (unlikely(!status)) { 
    180                 spurious_interrupt(); 
    181                 return IRQ_NONE; 
     159        /* Primary IRQ's */ 
     160        irq = readl(REG(PIR_OFFSET)) & 0x3f; 
     161        if (irq) { 
     162                do_IRQ(ar7_irq_base + irq); 
     163                return; 
    182164        } 
    183165 
    184         for (i = 0; i < 32; i++) 
    185                 if (status & (i << 1)) { 
    186                         irq = i + 40; 
    187                         REG(SEC_CR_OFFSET) = 1 << i; 
    188                         break; 
     166        /* Secondary IRQ's are cascaded through primary '0' */ 
     167        writel(1, REG(CR_OFFSET(irq))); 
     168        status = readl(REG(SEC_SR_OFFSET)); 
     169        for (i = 0; i < 32; i++) { 
     170                if (status & 1) { 
     171                        do_IRQ(ar7_irq_base + i + 40); 
     172                        return; 
    189173                } 
     174                status >>= 1; 
     175        } 
    190176 
    191         do_IRQ(irq + ar7_irq_base); 
    192  
    193         return IRQ_HANDLED; 
     177        spurious_interrupt(); 
    194178} 
    195179 
    196180asmlinkage void plat_irq_dispatch(void) 
    197181{ 
    198         unsigned int pending = read_c0_status() & read_c0_cause(); 
     182        unsigned int pending = read_c0_status() & read_c0_cause() & ST0_IM; 
    199183        if (pending & STATUSF_IP7)              /* cpu timer */ 
    200184                do_IRQ(7); 
    201185        else if (pending & STATUSF_IP2)         /* int0 hardware line */ 
    202                 do_IRQ(2); 
    203         else  
     186                ar7_cascade(); 
     187        else 
    204188                spurious_interrupt(); 
    205189} 
Note: See TracChangeset for help on using the changeset viewer.