root/arch/mips/mti-malta/malta-int.c

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

DEFINITIONS

This source file includes following definitions.
  1. mips_pcibios_iack
  2. corehi_irqdispatch
  3. corehi_handler
  4. arch_init_irq

   1 /*
   2  * This file is subject to the terms and conditions of the GNU General Public
   3  * License.  See the file "COPYING" in the main directory of this archive
   4  * for more details.
   5  *
   6  * Carsten Langgaard, carstenl@mips.com
   7  * Copyright (C) 2000, 2001, 2004 MIPS Technologies, Inc.
   8  * Copyright (C) 2001 Ralf Baechle
   9  * Copyright (C) 2013 Imagination Technologies Ltd.
  10  *
  11  * Routines for generic manipulation of the interrupts found on the MIPS
  12  * Malta board. The interrupt controller is located in the South Bridge
  13  * a PIIX4 device with two internal 82C95 interrupt controllers.
  14  */
  15 #include <linux/init.h>
  16 #include <linux/irq.h>
  17 #include <linux/irqchip.h>
  18 #include <linux/sched.h>
  19 #include <linux/smp.h>
  20 #include <linux/interrupt.h>
  21 #include <linux/io.h>
  22 #include <linux/of_irq.h>
  23 #include <linux/kernel_stat.h>
  24 #include <linux/kernel.h>
  25 #include <linux/random.h>
  26 
  27 #include <asm/traps.h>
  28 #include <asm/i8259.h>
  29 #include <asm/irq_cpu.h>
  30 #include <asm/irq_regs.h>
  31 #include <asm/mips-boards/malta.h>
  32 #include <asm/mips-boards/maltaint.h>
  33 #include <asm/mips-cps.h>
  34 #include <asm/gt64120.h>
  35 #include <asm/mips-boards/generic.h>
  36 #include <asm/mips-boards/msc01_pci.h>
  37 #include <asm/msc01_ic.h>
  38 #include <asm/setup.h>
  39 #include <asm/rtlx.h>
  40 
  41 static inline int mips_pcibios_iack(void)
  42 {
  43         int irq;
  44 
  45         /*
  46          * Determine highest priority pending interrupt by performing
  47          * a PCI Interrupt Acknowledge cycle.
  48          */
  49         switch (mips_revision_sconid) {
  50         case MIPS_REVISION_SCON_SOCIT:
  51         case MIPS_REVISION_SCON_ROCIT:
  52         case MIPS_REVISION_SCON_SOCITSC:
  53         case MIPS_REVISION_SCON_SOCITSCP:
  54                 MSC_READ(MSC01_PCI_IACK, irq);
  55                 irq &= 0xff;
  56                 break;
  57         case MIPS_REVISION_SCON_GT64120:
  58                 irq = GT_READ(GT_PCI0_IACK_OFS);
  59                 irq &= 0xff;
  60                 break;
  61         case MIPS_REVISION_SCON_BONITO:
  62                 /* The following will generate a PCI IACK cycle on the
  63                  * Bonito controller. It's a little bit kludgy, but it
  64                  * was the easiest way to implement it in hardware at
  65                  * the given time.
  66                  */
  67                 BONITO_PCIMAP_CFG = 0x20000;
  68 
  69                 /* Flush Bonito register block */
  70                 (void) BONITO_PCIMAP_CFG;
  71                 iob();    /* sync */
  72 
  73                 irq = __raw_readl((u32 *)_pcictrl_bonito_pcicfg);
  74                 iob();    /* sync */
  75                 irq &= 0xff;
  76                 BONITO_PCIMAP_CFG = 0;
  77                 break;
  78         default:
  79                 pr_emerg("Unknown system controller.\n");
  80                 return -1;
  81         }
  82         return irq;
  83 }
  84 
  85 static void corehi_irqdispatch(void)
  86 {
  87         unsigned int intedge, intsteer, pcicmd, pcibadaddr;
  88         unsigned int pcimstat, intisr, inten, intpol;
  89         unsigned int intrcause, datalo, datahi;
  90         struct pt_regs *regs = get_irq_regs();
  91 
  92         pr_emerg("CoreHI interrupt, shouldn't happen, we die here!\n");
  93         pr_emerg("epc    : %08lx\nStatus: %08lx\n"
  94                  "Cause : %08lx\nbadVaddr : %08lx\n",
  95                  regs->cp0_epc, regs->cp0_status,
  96                  regs->cp0_cause, regs->cp0_badvaddr);
  97 
  98         /* Read all the registers and then print them as there is a
  99            problem with interspersed printk's upsetting the Bonito controller.
 100            Do it for the others too.
 101         */
 102 
 103         switch (mips_revision_sconid) {
 104         case MIPS_REVISION_SCON_SOCIT:
 105         case MIPS_REVISION_SCON_ROCIT:
 106         case MIPS_REVISION_SCON_SOCITSC:
 107         case MIPS_REVISION_SCON_SOCITSCP:
 108                 ll_msc_irq();
 109                 break;
 110         case MIPS_REVISION_SCON_GT64120:
 111                 intrcause = GT_READ(GT_INTRCAUSE_OFS);
 112                 datalo = GT_READ(GT_CPUERR_ADDRLO_OFS);
 113                 datahi = GT_READ(GT_CPUERR_ADDRHI_OFS);
 114                 pr_emerg("GT_INTRCAUSE = %08x\n", intrcause);
 115                 pr_emerg("GT_CPUERR_ADDR = %02x%08x\n",
 116                                 datahi, datalo);
 117                 break;
 118         case MIPS_REVISION_SCON_BONITO:
 119                 pcibadaddr = BONITO_PCIBADADDR;
 120                 pcimstat = BONITO_PCIMSTAT;
 121                 intisr = BONITO_INTISR;
 122                 inten = BONITO_INTEN;
 123                 intpol = BONITO_INTPOL;
 124                 intedge = BONITO_INTEDGE;
 125                 intsteer = BONITO_INTSTEER;
 126                 pcicmd = BONITO_PCICMD;
 127                 pr_emerg("BONITO_INTISR = %08x\n", intisr);
 128                 pr_emerg("BONITO_INTEN = %08x\n", inten);
 129                 pr_emerg("BONITO_INTPOL = %08x\n", intpol);
 130                 pr_emerg("BONITO_INTEDGE = %08x\n", intedge);
 131                 pr_emerg("BONITO_INTSTEER = %08x\n", intsteer);
 132                 pr_emerg("BONITO_PCICMD = %08x\n", pcicmd);
 133                 pr_emerg("BONITO_PCIBADADDR = %08x\n", pcibadaddr);
 134                 pr_emerg("BONITO_PCIMSTAT = %08x\n", pcimstat);
 135                 break;
 136         }
 137 
 138         die("CoreHi interrupt", regs);
 139 }
 140 
 141 static irqreturn_t corehi_handler(int irq, void *dev_id)
 142 {
 143         corehi_irqdispatch();
 144         return IRQ_HANDLED;
 145 }
 146 
 147 static struct irqaction corehi_irqaction = {
 148         .handler = corehi_handler,
 149         .name = "CoreHi",
 150         .flags = IRQF_NO_THREAD,
 151 };
 152 
 153 static msc_irqmap_t msc_irqmap[] __initdata = {
 154         {MSC01C_INT_TMR,                MSC01_IRQ_EDGE, 0},
 155         {MSC01C_INT_PCI,                MSC01_IRQ_LEVEL, 0},
 156 };
 157 static int msc_nr_irqs __initdata = ARRAY_SIZE(msc_irqmap);
 158 
 159 static msc_irqmap_t msc_eicirqmap[] __initdata = {
 160         {MSC01E_INT_SW0,                MSC01_IRQ_LEVEL, 0},
 161         {MSC01E_INT_SW1,                MSC01_IRQ_LEVEL, 0},
 162         {MSC01E_INT_I8259A,             MSC01_IRQ_LEVEL, 0},
 163         {MSC01E_INT_SMI,                MSC01_IRQ_LEVEL, 0},
 164         {MSC01E_INT_COREHI,             MSC01_IRQ_LEVEL, 0},
 165         {MSC01E_INT_CORELO,             MSC01_IRQ_LEVEL, 0},
 166         {MSC01E_INT_TMR,                MSC01_IRQ_EDGE, 0},
 167         {MSC01E_INT_PCI,                MSC01_IRQ_LEVEL, 0},
 168         {MSC01E_INT_PERFCTR,            MSC01_IRQ_LEVEL, 0},
 169         {MSC01E_INT_CPUCTR,             MSC01_IRQ_LEVEL, 0}
 170 };
 171 
 172 static int msc_nr_eicirqs __initdata = ARRAY_SIZE(msc_eicirqmap);
 173 
 174 void __init arch_init_irq(void)
 175 {
 176         int corehi_irq;
 177 
 178         /*
 179          * Preallocate the i8259's expected virq's here. Since irqchip_init()
 180          * will probe the irqchips in hierarchial order, i8259 is probed last.
 181          * If anything allocates a virq before the i8259 is probed, it will
 182          * be given one of the i8259's expected range and consequently setup
 183          * of the i8259 will fail.
 184          */
 185         WARN(irq_alloc_descs(I8259A_IRQ_BASE, I8259A_IRQ_BASE,
 186                             16, numa_node_id()) < 0,
 187                 "Cannot reserve i8259 virqs at IRQ%d\n", I8259A_IRQ_BASE);
 188 
 189         i8259_set_poll(mips_pcibios_iack);
 190         irqchip_init();
 191 
 192         switch (mips_revision_sconid) {
 193         case MIPS_REVISION_SCON_SOCIT:
 194         case MIPS_REVISION_SCON_ROCIT:
 195                 if (cpu_has_veic)
 196                         init_msc_irqs(MIPS_MSC01_IC_REG_BASE,
 197                                         MSC01E_INT_BASE, msc_eicirqmap,
 198                                         msc_nr_eicirqs);
 199                 else
 200                         init_msc_irqs(MIPS_MSC01_IC_REG_BASE,
 201                                         MSC01C_INT_BASE, msc_irqmap,
 202                                         msc_nr_irqs);
 203                 break;
 204 
 205         case MIPS_REVISION_SCON_SOCITSC:
 206         case MIPS_REVISION_SCON_SOCITSCP:
 207                 if (cpu_has_veic)
 208                         init_msc_irqs(MIPS_SOCITSC_IC_REG_BASE,
 209                                         MSC01E_INT_BASE, msc_eicirqmap,
 210                                         msc_nr_eicirqs);
 211                 else
 212                         init_msc_irqs(MIPS_SOCITSC_IC_REG_BASE,
 213                                         MSC01C_INT_BASE, msc_irqmap,
 214                                         msc_nr_irqs);
 215         }
 216 
 217         if (mips_gic_present()) {
 218                 corehi_irq = MIPS_CPU_IRQ_BASE + MIPSCPU_INT_COREHI;
 219         } else if (cpu_has_veic) {
 220                 set_vi_handler(MSC01E_INT_COREHI, corehi_irqdispatch);
 221                 corehi_irq = MSC01E_INT_BASE + MSC01E_INT_COREHI;
 222         } else {
 223                 corehi_irq = MIPS_CPU_IRQ_BASE + MIPSCPU_INT_COREHI;
 224         }
 225 
 226         setup_irq(corehi_irq, &corehi_irqaction);
 227 }

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