diff options
Diffstat (limited to 'arch/mips/mti-malta/malta-int.c')
| -rw-r--r-- | arch/mips/mti-malta/malta-int.c | 453 |
1 files changed, 240 insertions, 213 deletions
diff --git a/arch/mips/mti-malta/malta-int.c b/arch/mips/mti-malta/malta-int.c index ea176113fea..ecc2785f785 100644 --- a/arch/mips/mti-malta/malta-int.c +++ b/arch/mips/mti-malta/malta-int.c @@ -1,30 +1,21 @@ /* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * * Carsten Langgaard, carstenl@mips.com * Copyright (C) 2000, 2001, 2004 MIPS Technologies, Inc. * Copyright (C) 2001 Ralf Baechle - * - * This program is free software; you can distribute it and/or modify it - * under the terms of the GNU General Public License (Version 2) as - * published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. + * Copyright (C) 2013 Imagination Technologies Ltd. * * Routines for generic manipulation of the interrupts found on the MIPS - * Malta board. - * The interrupt controller is located in the South Bridge a PIIX4 device - * with two internal 82C95 interrupt controllers. + * Malta board. The interrupt controller is located in the South Bridge + * a PIIX4 device with two internal 82C95 interrupt controllers. */ #include <linux/init.h> #include <linux/irq.h> #include <linux/sched.h> -#include <linux/slab.h> +#include <linux/smp.h> #include <linux/interrupt.h> #include <linux/io.h> #include <linux/kernel_stat.h> @@ -35,28 +26,25 @@ #include <asm/i8259.h> #include <asm/irq_cpu.h> #include <asm/irq_regs.h> +#include <asm/mips-cm.h> #include <asm/mips-boards/malta.h> #include <asm/mips-boards/maltaint.h> -#include <asm/mips-boards/piix4.h> #include <asm/gt64120.h> #include <asm/mips-boards/generic.h> #include <asm/mips-boards/msc01_pci.h> #include <asm/msc01_ic.h> #include <asm/gic.h> -#include <asm/gcmpregs.h> +#include <asm/setup.h> +#include <asm/rtlx.h> -int gcmp_present = -1; -int gic_present; static unsigned long _msc01_biu_base; -static unsigned long _gcmp_base; static unsigned int ipi_map[NR_CPUS]; -static DEFINE_SPINLOCK(mips_irq_lock); +static DEFINE_RAW_SPINLOCK(mips_irq_lock); static inline int mips_pcibios_iack(void) { int irq; - u32 dummy; /* * Determine highest priority pending interrupt by performing @@ -83,16 +71,16 @@ static inline int mips_pcibios_iack(void) BONITO_PCIMAP_CFG = 0x20000; /* Flush Bonito register block */ - dummy = BONITO_PCIMAP_CFG; - iob(); /* sync */ + (void) BONITO_PCIMAP_CFG; + iob(); /* sync */ - irq = readl((u32 *)_pcictrl_bonito_pcicfg); - iob(); /* sync */ + irq = __raw_readl((u32 *)_pcictrl_bonito_pcicfg); + iob(); /* sync */ irq &= 0xff; BONITO_PCIMAP_CFG = 0; break; default: - printk(KERN_WARNING "Unknown system controller.\n"); + pr_emerg("Unknown system controller.\n"); return -1; } return irq; @@ -102,7 +90,7 @@ static inline int get_int(void) { unsigned long flags; int irq; - spin_lock_irqsave(&mips_irq_lock, flags); + raw_spin_lock_irqsave(&mips_irq_lock, flags); irq = mips_pcibios_iack(); @@ -112,7 +100,7 @@ static inline int get_int(void) * on an SMP system, so leave it up to the generic code... */ - spin_unlock_irqrestore(&mips_irq_lock, flags); + raw_spin_unlock_irqrestore(&mips_irq_lock, flags); return irq; } @@ -128,15 +116,23 @@ static void malta_hw0_irqdispatch(void) } do_IRQ(MALTA_INT_BASE + irq); + +#ifdef CONFIG_MIPS_VPE_APSP_API_MT + if (aprp_hook) + aprp_hook(); +#endif } static void malta_ipi_irqdispatch(void) { int irq; + if (gic_compare_int()) + do_IRQ(MIPS_GIC_IRQ_BASE); + irq = gic_get_int(); if (irq < 0) - return; /* interrupt has already been cleared */ + return; /* interrupt has already been cleared */ do_IRQ(MIPS_GIC_IRQ_BASE + irq); } @@ -148,11 +144,11 @@ static void corehi_irqdispatch(void) unsigned int intrcause, datalo, datahi; struct pt_regs *regs = get_irq_regs(); - printk(KERN_EMERG "CoreHI interrupt, shouldn't happen, we die here!\n"); - printk(KERN_EMERG "epc : %08lx\nStatus: %08lx\n" - "Cause : %08lx\nbadVaddr : %08lx\n", - regs->cp0_epc, regs->cp0_status, - regs->cp0_cause, regs->cp0_badvaddr); + pr_emerg("CoreHI interrupt, shouldn't happen, we die here!\n"); + pr_emerg("epc : %08lx\nStatus: %08lx\n" + "Cause : %08lx\nbadVaddr : %08lx\n", + regs->cp0_epc, regs->cp0_status, + regs->cp0_cause, regs->cp0_badvaddr); /* Read all the registers and then print them as there is a problem with interspersed printk's upsetting the Bonito controller. @@ -170,8 +166,8 @@ static void corehi_irqdispatch(void) intrcause = GT_READ(GT_INTRCAUSE_OFS); datalo = GT_READ(GT_CPUERR_ADDRLO_OFS); datahi = GT_READ(GT_CPUERR_ADDRHI_OFS); - printk(KERN_EMERG "GT_INTRCAUSE = %08x\n", intrcause); - printk(KERN_EMERG "GT_CPUERR_ADDR = %02x%08x\n", + pr_emerg("GT_INTRCAUSE = %08x\n", intrcause); + pr_emerg("GT_CPUERR_ADDR = %02x%08x\n", datahi, datalo); break; case MIPS_REVISION_SCON_BONITO: @@ -183,14 +179,14 @@ static void corehi_irqdispatch(void) intedge = BONITO_INTEDGE; intsteer = BONITO_INTSTEER; pcicmd = BONITO_PCICMD; - printk(KERN_EMERG "BONITO_INTISR = %08x\n", intisr); - printk(KERN_EMERG "BONITO_INTEN = %08x\n", inten); - printk(KERN_EMERG "BONITO_INTPOL = %08x\n", intpol); - printk(KERN_EMERG "BONITO_INTEDGE = %08x\n", intedge); - printk(KERN_EMERG "BONITO_INTSTEER = %08x\n", intsteer); - printk(KERN_EMERG "BONITO_PCICMD = %08x\n", pcicmd); - printk(KERN_EMERG "BONITO_PCIBADADDR = %08x\n", pcibadaddr); - printk(KERN_EMERG "BONITO_PCIMSTAT = %08x\n", pcimstat); + pr_emerg("BONITO_INTISR = %08x\n", intisr); + pr_emerg("BONITO_INTEN = %08x\n", inten); + pr_emerg("BONITO_INTPOL = %08x\n", intpol); + pr_emerg("BONITO_INTEDGE = %08x\n", intedge); + pr_emerg("BONITO_INTSTEER = %08x\n", intsteer); + pr_emerg("BONITO_PCICMD = %08x\n", pcicmd); + pr_emerg("BONITO_PCIBADADDR = %08x\n", pcibadaddr); + pr_emerg("BONITO_PCIMSTAT = %08x\n", pcimstat); break; } @@ -249,20 +245,20 @@ static inline unsigned int irq_ffs(unsigned int pending) * on hardware interrupt 0 (MIPS IRQ 2)) like: * * MIPS IRQ Source - * -------- ------ - * 0 Software (ignored) - * 1 Software (ignored) - * 2 Combined hardware interrupt (hw0) - * 3 Hardware (ignored) - * 4 Hardware (ignored) - * 5 Hardware (ignored) - * 6 Hardware (ignored) - * 7 R4k timer (what we use) + * -------- ------ + * 0 Software (ignored) + * 1 Software (ignored) + * 2 Combined hardware interrupt (hw0) + * 3 Hardware (ignored) + * 4 Hardware (ignored) + * 5 Hardware (ignored) + * 6 Hardware (ignored) + * 7 R4k timer (what we use) * * We handle the IRQ according to _our_ priority which is: * - * Highest ---- R4k Timer - * Lowest ---- Combined hardware interrupt + * Highest ---- R4k Timer + * Lowest ---- Combined hardware interrupt * * then we just return, if multiple IRQs are pending then we will just take * another exception, big deal. @@ -273,24 +269,23 @@ asmlinkage void plat_irq_dispatch(void) unsigned int pending = read_c0_cause() & read_c0_status() & ST0_IM; int irq; + if (unlikely(!pending)) { + spurious_interrupt(); + return; + } + irq = irq_ffs(pending); if (irq == MIPSCPU_INT_I8259A) malta_hw0_irqdispatch(); else if (gic_present && ((1 << irq) & ipi_map[smp_processor_id()])) malta_ipi_irqdispatch(); - else if (irq >= 0) - do_IRQ(MIPS_CPU_IRQ_BASE + irq); else - spurious_interrupt(); + do_IRQ(MIPS_CPU_IRQ_BASE + irq); } #ifdef CONFIG_MIPS_MT_SMP - -#define GIC_MIPS_CPU_IPI_RESCHED_IRQ 3 -#define GIC_MIPS_CPU_IPI_CALL_IRQ 4 - #define MIPS_CPU_IPI_RESCHED_IRQ 0 /* SW int 0 for resched */ #define C_RESCHED C_SW0 #define MIPS_CPU_IPI_CALL_IRQ 1 /* SW int 1 for resched */ @@ -307,8 +302,22 @@ static void ipi_call_dispatch(void) do_IRQ(MIPS_CPU_IRQ_BASE + MIPS_CPU_IPI_CALL_IRQ); } +#endif /* CONFIG_MIPS_MT_SMP */ + +#ifdef CONFIG_MIPS_GIC_IPI + +#define GIC_MIPS_CPU_IPI_RESCHED_IRQ 3 +#define GIC_MIPS_CPU_IPI_CALL_IRQ 4 + static irqreturn_t ipi_resched_interrupt(int irq, void *dev_id) { +#ifdef CONFIG_MIPS_VPE_APSP_API_CMP + if (aprp_hook) + aprp_hook(); +#endif + + scheduler_ipi(); + return IRQ_HANDLED; } @@ -321,34 +330,51 @@ static irqreturn_t ipi_call_interrupt(int irq, void *dev_id) static struct irqaction irq_resched = { .handler = ipi_resched_interrupt, - .flags = IRQF_DISABLED|IRQF_PERCPU, + .flags = IRQF_PERCPU, .name = "IPI_resched" }; static struct irqaction irq_call = { .handler = ipi_call_interrupt, - .flags = IRQF_DISABLED|IRQF_PERCPU, + .flags = IRQF_PERCPU, .name = "IPI_call" }; -#endif /* CONFIG_MIPS_MT_SMP */ +#endif /* CONFIG_MIPS_GIC_IPI */ + +static int gic_resched_int_base; +static int gic_call_int_base; +#define GIC_RESCHED_INT(cpu) (gic_resched_int_base+(cpu)) +#define GIC_CALL_INT(cpu) (gic_call_int_base+(cpu)) + +unsigned int plat_ipi_call_int_xlate(unsigned int cpu) +{ + return GIC_CALL_INT(cpu); +} + +unsigned int plat_ipi_resched_int_xlate(unsigned int cpu) +{ + return GIC_RESCHED_INT(cpu); +} static struct irqaction i8259irq = { .handler = no_action, - .name = "XT-PIC cascade" + .name = "XT-PIC cascade", + .flags = IRQF_NO_THREAD, }; static struct irqaction corehi_irqaction = { .handler = no_action, - .name = "CoreHi" + .name = "CoreHi", + .flags = IRQF_NO_THREAD, }; -static msc_irqmap_t __initdata msc_irqmap[] = { +static msc_irqmap_t msc_irqmap[] __initdata = { {MSC01C_INT_TMR, MSC01_IRQ_EDGE, 0}, {MSC01C_INT_PCI, MSC01_IRQ_LEVEL, 0}, }; -static int __initdata msc_nr_irqs = ARRAY_SIZE(msc_irqmap); +static int msc_nr_irqs __initdata = ARRAY_SIZE(msc_irqmap); -static msc_irqmap_t __initdata msc_eicirqmap[] = { +static msc_irqmap_t msc_eicirqmap[] __initdata = { {MSC01E_INT_SW0, MSC01_IRQ_LEVEL, 0}, {MSC01E_INT_SW1, MSC01_IRQ_LEVEL, 0}, {MSC01E_INT_I8259A, MSC01_IRQ_LEVEL, 0}, @@ -361,92 +387,89 @@ static msc_irqmap_t __initdata msc_eicirqmap[] = { {MSC01E_INT_CPUCTR, MSC01_IRQ_LEVEL, 0} }; -static int __initdata msc_nr_eicirqs = ARRAY_SIZE(msc_eicirqmap); +static int msc_nr_eicirqs __initdata = ARRAY_SIZE(msc_eicirqmap); -#if defined(CONFIG_MIPS_MT_SMP) /* * This GIC specific tabular array defines the association between External * Interrupts and CPUs/Core Interrupts. The nature of the External * Interrupts is also defined here - polarity/trigger. */ -static struct gic_intr_map gic_intr_map[] = { - { GIC_EXT_INTR(0), X, X, X, X, 0 }, - { GIC_EXT_INTR(1), X, X, X, X, 0 }, - { GIC_EXT_INTR(2), X, X, X, X, 0 }, - { GIC_EXT_INTR(3), 0, GIC_CPU_INT0, GIC_POL_POS, GIC_TRIG_LEVEL, 0 }, - { GIC_EXT_INTR(4), 0, GIC_CPU_INT1, GIC_POL_POS, GIC_TRIG_LEVEL, 0 }, - { GIC_EXT_INTR(5), 0, GIC_CPU_INT2, GIC_POL_POS, GIC_TRIG_LEVEL, 0 }, - { GIC_EXT_INTR(6), 0, GIC_CPU_INT3, GIC_POL_POS, GIC_TRIG_LEVEL, 0 }, - { GIC_EXT_INTR(7), 0, GIC_CPU_INT4, GIC_POL_POS, GIC_TRIG_LEVEL, 0 }, - { GIC_EXT_INTR(8), 0, GIC_CPU_INT3, GIC_POL_POS, GIC_TRIG_LEVEL, 0 }, - { GIC_EXT_INTR(9), 0, GIC_CPU_INT3, GIC_POL_POS, GIC_TRIG_LEVEL, 0 }, - { GIC_EXT_INTR(10), X, X, X, X, 0 }, - { GIC_EXT_INTR(11), X, X, X, X, 0 }, - { GIC_EXT_INTR(12), 0, GIC_CPU_INT3, GIC_POL_POS, GIC_TRIG_LEVEL, 0 }, - { GIC_EXT_INTR(13), 0, GIC_MAP_TO_NMI_MSK, GIC_POL_POS, GIC_TRIG_LEVEL, 0 }, - { GIC_EXT_INTR(14), 0, GIC_MAP_TO_NMI_MSK, GIC_POL_POS, GIC_TRIG_LEVEL, 0 }, - { GIC_EXT_INTR(15), X, X, X, X, 0 }, - { GIC_EXT_INTR(16), 0, GIC_CPU_INT1, GIC_POL_POS, GIC_TRIG_EDGE, 1 }, - { GIC_EXT_INTR(17), 0, GIC_CPU_INT2, GIC_POL_POS, GIC_TRIG_EDGE, 1 }, - { GIC_EXT_INTR(18), 1, GIC_CPU_INT1, GIC_POL_POS, GIC_TRIG_EDGE, 1 }, - { GIC_EXT_INTR(19), 1, GIC_CPU_INT2, GIC_POL_POS, GIC_TRIG_EDGE, 1 }, - { GIC_EXT_INTR(20), 2, GIC_CPU_INT1, GIC_POL_POS, GIC_TRIG_EDGE, 1 }, - { GIC_EXT_INTR(21), 2, GIC_CPU_INT2, GIC_POL_POS, GIC_TRIG_EDGE, 1 }, - { GIC_EXT_INTR(22), 3, GIC_CPU_INT1, GIC_POL_POS, GIC_TRIG_EDGE, 1 }, - { GIC_EXT_INTR(23), 3, GIC_CPU_INT2, GIC_POL_POS, GIC_TRIG_EDGE, 1 }, + +#define GIC_CPU_NMI GIC_MAP_TO_NMI_MSK +#define X GIC_UNUSED + +static struct gic_intr_map gic_intr_map[GIC_NUM_INTRS] = { + { X, X, X, X, 0 }, + { X, X, X, X, 0 }, + { X, X, X, X, 0 }, + { 0, GIC_CPU_INT0, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT }, + { 0, GIC_CPU_INT1, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT }, + { 0, GIC_CPU_INT2, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT }, + { 0, GIC_CPU_INT3, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT }, + { 0, GIC_CPU_INT4, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT }, + { 0, GIC_CPU_INT3, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT }, + { 0, GIC_CPU_INT3, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT }, + { X, X, X, X, 0 }, + { X, X, X, X, 0 }, + { 0, GIC_CPU_INT3, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT }, + { 0, GIC_CPU_NMI, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT }, + { 0, GIC_CPU_NMI, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT }, + { X, X, X, X, 0 }, + /* The remainder of this table is initialised by fill_ipi_map */ }; -#endif +#undef X -/* - * GCMP needs to be detected before any SMP initialisation - */ -static int __init gcmp_probe(unsigned long addr, unsigned long size) +#ifdef CONFIG_MIPS_GIC_IPI +static void __init fill_ipi_map1(int baseintr, int cpu, int cpupin) { - if (gcmp_present >= 0) - return gcmp_present; - - _gcmp_base = (unsigned long) ioremap_nocache(GCMP_BASE_ADDR, GCMP_ADDRSPACE_SZ); - _msc01_biu_base = (unsigned long) ioremap_nocache(MSC01_BIU_REG_BASE, MSC01_BIU_ADDRSPACE_SZ); - gcmp_present = (GCMPGCB(GCMPB) & GCMP_GCB_GCMPB_GCMPBASE_MSK) == GCMP_BASE_ADDR; - - if (gcmp_present) - printk(KERN_DEBUG "GCMP present\n"); - return gcmp_present; + int intr = baseintr + cpu; + gic_intr_map[intr].cpunum = cpu; + gic_intr_map[intr].pin = cpupin; + gic_intr_map[intr].polarity = GIC_POL_POS; + gic_intr_map[intr].trigtype = GIC_TRIG_EDGE; + gic_intr_map[intr].flags = GIC_FLAG_IPI; + ipi_map[cpu] |= (1 << (cpupin + 2)); } -#if defined(CONFIG_MIPS_MT_SMP) static void __init fill_ipi_map(void) { - int i; + int cpu; - for (i = 0; i < ARRAY_SIZE(gic_intr_map); i++) { - if (gic_intr_map[i].ipiflag && (gic_intr_map[i].cpunum != X)) - ipi_map[gic_intr_map[i].cpunum] |= - (1 << (gic_intr_map[i].pin + 2)); + for (cpu = 0; cpu < nr_cpu_ids; cpu++) { + fill_ipi_map1(gic_resched_int_base, cpu, GIC_CPU_INT1); + fill_ipi_map1(gic_call_int_base, cpu, GIC_CPU_INT2); } } #endif -void __init arch_init_irq(void) +void __init arch_init_ipiirq(int irq, struct irqaction *action) { - int gic_present, gcmp_present; + setup_irq(irq, action); + irq_set_handler(irq, handle_percpu_irq); +} +void __init arch_init_irq(void) +{ init_i8259_irqs(); if (!cpu_has_veic) mips_cpu_irq_init(); - gcmp_present = gcmp_probe(GCMP_BASE_ADDR, GCMP_ADDRSPACE_SZ); - if (gcmp_present) { - GCMPGCB(GICBA) = GIC_BASE_ADDR | GCMP_GCB_GICBA_EN_MSK; + if (mips_cm_present()) { + write_gcr_gic_base(GIC_BASE_ADDR | CM_GCR_GIC_BASE_GICEN_MSK); gic_present = 1; } else { - _msc01_biu_base = (unsigned long) ioremap_nocache(MSC01_BIU_REG_BASE, MSC01_BIU_ADDRSPACE_SZ); - gic_present = (REG(_msc01_biu_base, MSC01_SC_CFG) & - MSC01_SC_CFG_GICPRES_MSK) >> MSC01_SC_CFG_GICPRES_SHF; + if (mips_revision_sconid == MIPS_REVISION_SCON_ROCIT) { + _msc01_biu_base = (unsigned long) + ioremap_nocache(MSC01_BIU_REG_BASE, + MSC01_BIU_ADDRSPACE_SZ); + gic_present = (REG(_msc01_biu_base, MSC01_SC_CFG) & + MSC01_SC_CFG_GICPRES_MSK) >> + MSC01_SC_CFG_GICPRES_SHF; + } } if (gic_present) - printk(KERN_DEBUG "GIC present\n"); + pr_debug("GIC present\n"); switch (mips_revision_sconid) { case MIPS_REVISION_SCON_SOCIT: @@ -481,85 +504,57 @@ void __init arch_init_irq(void) } else if (cpu_has_vint) { set_vi_handler(MIPSCPU_INT_I8259A, malta_hw0_irqdispatch); set_vi_handler(MIPSCPU_INT_COREHI, corehi_irqdispatch); -#ifdef CONFIG_MIPS_MT_SMTC - setup_irq_smtc(MIPS_CPU_IRQ_BASE+MIPSCPU_INT_I8259A, &i8259irq, - (0x100 << MIPSCPU_INT_I8259A)); - setup_irq_smtc(MIPS_CPU_IRQ_BASE+MIPSCPU_INT_COREHI, - &corehi_irqaction, (0x100 << MIPSCPU_INT_COREHI)); - /* - * Temporary hack to ensure that the subsidiary device - * interrupts coing in via the i8259A, but associated - * with low IRQ numbers, will restore the Status.IM - * value associated with the i8259A. - */ - { - int i; - - for (i = 0; i < 16; i++) - irq_hwmask[i] = (0x100 << MIPSCPU_INT_I8259A); - } -#else /* Not SMTC */ setup_irq(MIPS_CPU_IRQ_BASE+MIPSCPU_INT_I8259A, &i8259irq); setup_irq(MIPS_CPU_IRQ_BASE+MIPSCPU_INT_COREHI, &corehi_irqaction); -#endif /* CONFIG_MIPS_MT_SMTC */ } else { setup_irq(MIPS_CPU_IRQ_BASE+MIPSCPU_INT_I8259A, &i8259irq); setup_irq(MIPS_CPU_IRQ_BASE+MIPSCPU_INT_COREHI, &corehi_irqaction); } -#if defined(CONFIG_MIPS_MT_SMP) if (gic_present) { /* FIXME */ int i; - struct { - unsigned int resched; - unsigned int call; - } ipiirq[] = { - { - .resched = GIC_IPI_EXT_INTR_RESCHED_VPE0, - .call = GIC_IPI_EXT_INTR_CALLFNC_VPE0}, - { - .resched = GIC_IPI_EXT_INTR_RESCHED_VPE1, - .call = GIC_IPI_EXT_INTR_CALLFNC_VPE1 - }, { - .resched = GIC_IPI_EXT_INTR_RESCHED_VPE2, - .call = GIC_IPI_EXT_INTR_CALLFNC_VPE2 - }, { - .resched = GIC_IPI_EXT_INTR_RESCHED_VPE3, - .call = GIC_IPI_EXT_INTR_CALLFNC_VPE3 - } - }; +#if defined(CONFIG_MIPS_GIC_IPI) + gic_call_int_base = GIC_NUM_INTRS - + (NR_CPUS - nr_cpu_ids) * 2 - nr_cpu_ids; + gic_resched_int_base = gic_call_int_base - nr_cpu_ids; fill_ipi_map(); - gic_init(GIC_BASE_ADDR, GIC_ADDRSPACE_SZ, gic_intr_map, ARRAY_SIZE(gic_intr_map), MIPS_GIC_IRQ_BASE); - if (!gcmp_present) { +#endif + gic_init(GIC_BASE_ADDR, GIC_ADDRSPACE_SZ, gic_intr_map, + ARRAY_SIZE(gic_intr_map), MIPS_GIC_IRQ_BASE); + if (!mips_cm_present()) { /* Enable the GIC */ i = REG(_msc01_biu_base, MSC01_SC_CFG); REG(_msc01_biu_base, MSC01_SC_CFG) = (i | (0x1 << MSC01_SC_CFG_GICENA_SHF)); pr_debug("GIC Enabled\n"); } - +#if defined(CONFIG_MIPS_GIC_IPI) /* set up ipi interrupts */ if (cpu_has_vint) { set_vi_handler(MIPSCPU_INT_IPI0, malta_ipi_irqdispatch); set_vi_handler(MIPSCPU_INT_IPI1, malta_ipi_irqdispatch); } /* Argh.. this really needs sorting out.. */ - printk("CPU%d: status register was %08x\n", smp_processor_id(), read_c0_status()); + pr_info("CPU%d: status register was %08x\n", + smp_processor_id(), read_c0_status()); write_c0_status(read_c0_status() | STATUSF_IP3 | STATUSF_IP4); - printk("CPU%d: status register now %08x\n", smp_processor_id(), read_c0_status()); + pr_info("CPU%d: status register now %08x\n", + smp_processor_id(), read_c0_status()); write_c0_status(0x1100dc00); - printk("CPU%d: status register frc %08x\n", smp_processor_id(), read_c0_status()); - for (i = 0; i < ARRAY_SIZE(ipiirq); i++) { - setup_irq(MIPS_GIC_IRQ_BASE + ipiirq[i].resched, &irq_resched); - setup_irq(MIPS_GIC_IRQ_BASE + ipiirq[i].call, &irq_call); - - set_irq_handler(MIPS_GIC_IRQ_BASE + ipiirq[i].resched, handle_percpu_irq); - set_irq_handler(MIPS_GIC_IRQ_BASE + ipiirq[i].call, handle_percpu_irq); + pr_info("CPU%d: status register frc %08x\n", + smp_processor_id(), read_c0_status()); + for (i = 0; i < nr_cpu_ids; i++) { + arch_init_ipiirq(MIPS_GIC_IRQ_BASE + + GIC_RESCHED_INT(i), &irq_resched); + arch_init_ipiirq(MIPS_GIC_IRQ_BASE + + GIC_CALL_INT(i), &irq_call); } +#endif } else { +#if defined(CONFIG_MIPS_MT_SMP) /* set up ipi interrupts */ if (cpu_has_veic) { set_vi_handler (MSC01E_INT_SW0, ipi_resched_dispatch); @@ -568,33 +563,31 @@ void __init arch_init_irq(void) cpu_ipi_call_irq = MSC01E_INT_SW1; } else { if (cpu_has_vint) { - set_vi_handler (MIPS_CPU_IPI_RESCHED_IRQ, ipi_resched_dispatch); - set_vi_handler (MIPS_CPU_IPI_CALL_IRQ, ipi_call_dispatch); + set_vi_handler (MIPS_CPU_IPI_RESCHED_IRQ, + ipi_resched_dispatch); + set_vi_handler (MIPS_CPU_IPI_CALL_IRQ, + ipi_call_dispatch); } - cpu_ipi_resched_irq = MIPS_CPU_IRQ_BASE + MIPS_CPU_IPI_RESCHED_IRQ; - cpu_ipi_call_irq = MIPS_CPU_IRQ_BASE + MIPS_CPU_IPI_CALL_IRQ; + cpu_ipi_resched_irq = MIPS_CPU_IRQ_BASE + + MIPS_CPU_IPI_RESCHED_IRQ; + cpu_ipi_call_irq = MIPS_CPU_IRQ_BASE + + MIPS_CPU_IPI_CALL_IRQ; } - - setup_irq(cpu_ipi_resched_irq, &irq_resched); - setup_irq(cpu_ipi_call_irq, &irq_call); - - set_irq_handler(cpu_ipi_resched_irq, handle_percpu_irq); - set_irq_handler(cpu_ipi_call_irq, handle_percpu_irq); - } + arch_init_ipiirq(cpu_ipi_resched_irq, &irq_resched); + arch_init_ipiirq(cpu_ipi_call_irq, &irq_call); #endif + } } void malta_be_init(void) { - if (gcmp_present) { - /* Could change CM error mask register */ - } + /* Could change CM error mask register. */ } static char *tr[8] = { "mem", "gcr", "gic", "mmio", - "0x04", "0x05", "0x06", "0x07" + "0x04", "0x05", "0x06", "0x07" }; static char *mcmd[32] = { @@ -633,10 +626,10 @@ static char *mcmd[32] = { }; static char *core[8] = { - "Invalid/OK", "Invalid/Data", + "Invalid/OK", "Invalid/Data", "Shared/OK", "Shared/Data", "Modified/OK", "Modified/Data", - "Exclusive/OK", "Exclusive/Data" + "Exclusive/OK", "Exclusive/Data" }; static char *causes[32] = { @@ -655,27 +648,27 @@ int malta_be_handler(struct pt_regs *regs, int is_fixup) /* This duplicates the handling in do_be which seems wrong */ int retval = is_fixup ? MIPS_BE_FIXUP : MIPS_BE_FATAL; - if (gcmp_present) { - unsigned long cm_error = GCMPGCB(GCMEC); - unsigned long cm_addr = GCMPGCB(GCMEA); - unsigned long cm_other = GCMPGCB(GCMEO); + if (mips_cm_present()) { + unsigned long cm_error = read_gcr_error_cause(); + unsigned long cm_addr = read_gcr_error_addr(); + unsigned long cm_other = read_gcr_error_mult(); unsigned long cause, ocause; char buf[256]; - cause = (cm_error & GCMP_GCB_GMEC_ERROR_TYPE_MSK); + cause = cm_error & CM_GCR_ERROR_CAUSE_ERRTYPE_MSK; if (cause != 0) { - cause >>= GCMP_GCB_GMEC_ERROR_TYPE_SHF; + cause >>= CM_GCR_ERROR_CAUSE_ERRTYPE_SHF; if (cause < 16) { unsigned long cca_bits = (cm_error >> 15) & 7; unsigned long tr_bits = (cm_error >> 12) & 7; - unsigned long mcmd_bits = (cm_error >> 7) & 0x1f; + unsigned long cmd_bits = (cm_error >> 7) & 0x1f; unsigned long stag_bits = (cm_error >> 3) & 15; unsigned long sport_bits = (cm_error >> 0) & 7; snprintf(buf, sizeof(buf), "CCA=%lu TR=%s MCmd=%s STag=%lu " "SPort=%lu\n", - cca_bits, tr[tr_bits], mcmd[mcmd_bits], + cca_bits, tr[tr_bits], mcmd[cmd_bits], stag_bits, sport_bits); } else { /* glob state & sresp together */ @@ -684,7 +677,7 @@ int malta_be_handler(struct pt_regs *regs, int is_fixup) unsigned long c1_bits = (cm_error >> 12) & 7; unsigned long c0_bits = (cm_error >> 9) & 7; unsigned long sc_bit = (cm_error >> 8) & 1; - unsigned long mcmd_bits = (cm_error >> 3) & 0x1f; + unsigned long cmd_bits = (cm_error >> 3) & 0x1f; unsigned long sport_bits = (cm_error >> 0) & 7; snprintf(buf, sizeof(buf), "C3=%s C2=%s C1=%s C0=%s SC=%s " @@ -692,21 +685,55 @@ int malta_be_handler(struct pt_regs *regs, int is_fixup) core[c3_bits], core[c2_bits], core[c1_bits], core[c0_bits], sc_bit ? "True" : "False", - mcmd[mcmd_bits], sport_bits); + mcmd[cmd_bits], sport_bits); } - ocause = (cm_other & GCMP_GCB_GMEO_ERROR_2ND_MSK) >> - GCMP_GCB_GMEO_ERROR_2ND_SHF; + ocause = (cm_other & CM_GCR_ERROR_MULT_ERR2ND_MSK) >> + CM_GCR_ERROR_MULT_ERR2ND_SHF; - printk("CM_ERROR=%08lx %s <%s>\n", cm_error, + pr_err("CM_ERROR=%08lx %s <%s>\n", cm_error, causes[cause], buf); - printk("CM_ADDR =%08lx\n", cm_addr); - printk("CM_OTHER=%08lx %s\n", cm_other, causes[ocause]); + pr_err("CM_ADDR =%08lx\n", cm_addr); + pr_err("CM_OTHER=%08lx %s\n", cm_other, causes[ocause]); /* reprime cause register */ - GCMPGCB(GCMEC) = 0; + write_gcr_error_cause(0); } } return retval; } + +void gic_enable_interrupt(int irq_vec) +{ + GIC_SET_INTR_MASK(irq_vec); +} + +void gic_disable_interrupt(int irq_vec) +{ + GIC_CLR_INTR_MASK(irq_vec); +} + +void gic_irq_ack(struct irq_data *d) +{ + int irq = (d->irq - gic_irq_base); + + GIC_CLR_INTR_MASK(irq); + + if (gic_irq_flags[irq] & GIC_TRIG_EDGE) + GICWRITE(GIC_REG(SHARED, GIC_SH_WEDGE), irq); +} + +void gic_finish_irq(struct irq_data *d) +{ + /* Enable interrupts. */ + GIC_SET_INTR_MASK(d->irq - gic_irq_base); +} + +void __init gic_platform_init(int irqs, struct irq_chip *irq_controller) +{ + int i; + + for (i = gic_irq_base; i < (gic_irq_base + irqs); i++) + irq_set_chip(i, irq_controller); +} |
