From b72c05262298cc2ac92edb657f5ea3a97ad5ea3d Mon Sep 17 00:00:00 2001 From: Chris Dearman Date: Fri, 27 Apr 2007 15:58:41 +0100 Subject: [MIPS] Malta: Fix for SOCitSC based Maltas And an attempt to tidy up the core/controller differences. Signed-off-by: Chris Dearman Signed-off-by: Ralf Baechle --- arch/mips/mips-boards/generic/init.c | 62 ++++++++++++++++++++++--------- arch/mips/mips-boards/generic/pci.c | 20 ++++------ arch/mips/mips-boards/malta/malta_int.c | 42 ++++++++------------- arch/mips/mips-boards/malta/malta_setup.c | 4 +- include/asm-mips/mips-boards/generic.h | 22 +++++++++-- include/asm-mips/mips-boards/msc01_pci.h | 1 + 6 files changed, 87 insertions(+), 64 deletions(-) diff --git a/arch/mips/mips-boards/generic/init.c b/arch/mips/mips-boards/generic/init.c index 88e9c2a7a2f..4eabc1eadd2 100644 --- a/arch/mips/mips-boards/generic/init.c +++ b/arch/mips/mips-boards/generic/init.c @@ -57,7 +57,8 @@ int *_prom_argv, *_prom_envp; int init_debug = 0; -unsigned int mips_revision_corid; +int mips_revision_corid; +int mips_revision_sconid; /* Bonito64 system controller register base. */ unsigned long _pcictrl_bonito; @@ -275,13 +276,38 @@ void __init prom_init(void) else mips_revision_corid = MIPS_REVISION_CORID_CORE_EMUL_MSC; } - switch(mips_revision_corid) { + + mips_revision_sconid = MIPS_REVISION_SCONID; + if (mips_revision_sconid == MIPS_REVISION_SCON_OTHER) { + switch (mips_revision_corid) { + case MIPS_REVISION_CORID_QED_RM5261: + case MIPS_REVISION_CORID_CORE_LV: + case MIPS_REVISION_CORID_CORE_FPGA: + case MIPS_REVISION_CORID_CORE_FPGAR2: + mips_revision_sconid = MIPS_REVISION_SCON_GT64120; + break; + case MIPS_REVISION_CORID_CORE_EMUL_BON: + case MIPS_REVISION_CORID_BONITO64: + case MIPS_REVISION_CORID_CORE_20K: + mips_revision_sconid = MIPS_REVISION_SCON_BONITO; + break; + case MIPS_REVISION_CORID_CORE_MSC: + case MIPS_REVISION_CORID_CORE_FPGA2: + case MIPS_REVISION_CORID_CORE_FPGA3: + case MIPS_REVISION_CORID_CORE_24K: + case MIPS_REVISION_CORID_CORE_EMUL_MSC: + mips_revision_sconid = MIPS_REVISION_SCON_SOCIT; + break; + default: + mips_display_message("CC Error"); + while (1); /* We die here... */ + } + } + + switch (mips_revision_sconid) { u32 start, map, mask, data; - case MIPS_REVISION_CORID_QED_RM5261: - case MIPS_REVISION_CORID_CORE_LV: - case MIPS_REVISION_CORID_CORE_FPGA: - case MIPS_REVISION_CORID_CORE_FPGAR2: + case MIPS_REVISION_SCON_GT64120: /* * Setup the North bridge to do Master byte-lane swapping * when running in bigendian. @@ -305,9 +331,7 @@ void __init prom_init(void) set_io_port_base(MALTA_GT_PORT_BASE); break; - case MIPS_REVISION_CORID_CORE_EMUL_BON: - case MIPS_REVISION_CORID_BONITO64: - case MIPS_REVISION_CORID_CORE_20K: + case MIPS_REVISION_SCON_BONITO: _pcictrl_bonito_pcicfg = (unsigned long)ioremap(BONITO_PCICFG_BASE, BONITO_PCICFG_SIZE); /* @@ -334,13 +358,10 @@ void __init prom_init(void) set_io_port_base(MALTA_BONITO_PORT_BASE); break; - case MIPS_REVISION_CORID_CORE_MSC: - case MIPS_REVISION_CORID_CORE_FPGA2: - case MIPS_REVISION_CORID_CORE_FPGA3: - case MIPS_REVISION_CORID_CORE_24K: - case MIPS_REVISION_CORID_CORE_EMUL_MSC: + case MIPS_REVISION_SCON_SOCIT: + case MIPS_REVISION_SCON_ROCIT: _pcictrl_msc = (unsigned long)ioremap(MIPS_MSC01_PCI_REG_BASE, 0x2000); - + mips_pci_controller: mb(); MSC_READ(MSC01_PCI_CFG, data); MSC_WRITE(MSC01_PCI_CFG, data & ~MSC01_PCI_CFG_EN_BIT); @@ -374,10 +395,15 @@ void __init prom_init(void) set_io_port_base(MALTA_MSC_PORT_BASE); break; + case MIPS_REVISION_SCON_SOCITSC: + case MIPS_REVISION_SCON_SOCITSCP: + _pcictrl_msc = (unsigned long)ioremap(MIPS_SOCITSC_PCI_REG_BASE, 0x2000); + goto mips_pci_controller; + default: - /* Unknown Core card */ - mips_display_message("CC Error"); - while(1); /* We die here... */ + /* Unknown system controller */ + mips_display_message("SC Error"); + while (1); /* We die here... */ } #endif board_nmi_handler_setup = mips_nmi_setup; diff --git a/arch/mips/mips-boards/generic/pci.c b/arch/mips/mips-boards/generic/pci.c index f98d60f7865..c9852206890 100644 --- a/arch/mips/mips-boards/generic/pci.c +++ b/arch/mips/mips-boards/generic/pci.c @@ -92,11 +92,8 @@ void __init mips_pcibios_init(void) struct pci_controller *controller; resource_size_t start, end, map, start1, end1, map1, map2, map3, mask; - switch (mips_revision_corid) { - case MIPS_REVISION_CORID_QED_RM5261: - case MIPS_REVISION_CORID_CORE_LV: - case MIPS_REVISION_CORID_CORE_FPGA: - case MIPS_REVISION_CORID_CORE_FPGAR2: + switch (mips_revision_sconid) { + case MIPS_REVISION_SCON_GT64120: /* * Due to a bug in the Galileo system controller, we need * to setup the PCI BAR for the Galileo internal registers. @@ -161,9 +158,7 @@ void __init mips_pcibios_init(void) controller = >64120_controller; break; - case MIPS_REVISION_CORID_BONITO64: - case MIPS_REVISION_CORID_CORE_20K: - case MIPS_REVISION_CORID_CORE_EMUL_BON: + case MIPS_REVISION_SCON_BONITO: /* Set up resource ranges from the controller's registers. */ map = BONITO_PCIMAP; map1 = (BONITO_PCIMAP & BONITO_PCIMAP_PCIMAP_LO0) >> @@ -195,11 +190,10 @@ void __init mips_pcibios_init(void) controller = &bonito64_controller; break; - case MIPS_REVISION_CORID_CORE_MSC: - case MIPS_REVISION_CORID_CORE_FPGA2: - case MIPS_REVISION_CORID_CORE_FPGA3: - case MIPS_REVISION_CORID_CORE_24K: - case MIPS_REVISION_CORID_CORE_EMUL_MSC: + case MIPS_REVISION_SCON_SOCIT: + case MIPS_REVISION_SCON_ROCIT: + case MIPS_REVISION_SCON_SOCITSC: + case MIPS_REVISION_SCON_SOCITSCP: /* Set up resource ranges from the controller's registers. */ MSC_READ(MSC01_PCI_SC2PMBASL, start); MSC_READ(MSC01_PCI_SC2PMMSKL, mask); diff --git a/arch/mips/mips-boards/malta/malta_int.c b/arch/mips/mips-boards/malta/malta_int.c index 1cd830e3d93..1668cc21d5b 100644 --- a/arch/mips/mips-boards/malta/malta_int.c +++ b/arch/mips/mips-boards/malta/malta_int.c @@ -53,25 +53,19 @@ static inline int mips_pcibios_iack(void) * Determine highest priority pending interrupt by performing * a PCI Interrupt Acknowledge cycle. */ - switch(mips_revision_corid) { - case MIPS_REVISION_CORID_CORE_MSC: - case MIPS_REVISION_CORID_CORE_FPGA2: - case MIPS_REVISION_CORID_CORE_FPGA3: - case MIPS_REVISION_CORID_CORE_24K: - case MIPS_REVISION_CORID_CORE_EMUL_MSC: + switch (mips_revision_sconid) { + case MIPS_REVISION_SCON_SOCIT: + case MIPS_REVISION_SCON_ROCIT: + case MIPS_REVISION_SCON_SOCITSC: + case MIPS_REVISION_SCON_SOCITSCP: MSC_READ(MSC01_PCI_IACK, irq); irq &= 0xff; break; - case MIPS_REVISION_CORID_QED_RM5261: - case MIPS_REVISION_CORID_CORE_LV: - case MIPS_REVISION_CORID_CORE_FPGA: - case MIPS_REVISION_CORID_CORE_FPGAR2: + case MIPS_REVISION_SCON_GT64120: irq = GT_READ(GT_PCI0_IACK_OFS); irq &= 0xff; break; - case MIPS_REVISION_CORID_BONITO64: - case MIPS_REVISION_CORID_CORE_20K: - case MIPS_REVISION_CORID_CORE_EMUL_BON: + case MIPS_REVISION_SCON_BONITO: /* The following will generate a PCI IACK cycle on the * Bonito controller. It's a little bit kludgy, but it * was the easiest way to implement it in hardware at @@ -89,7 +83,7 @@ static inline int mips_pcibios_iack(void) BONITO_PCIMAP_CFG = 0; break; default: - printk("Unknown Core card, don't know the system controller.\n"); + printk("Unknown system controller.\n"); return -1; } return irq; @@ -144,27 +138,21 @@ static void corehi_irqdispatch(void) Do it for the others too. */ - switch(mips_revision_corid) { - case MIPS_REVISION_CORID_CORE_MSC: - case MIPS_REVISION_CORID_CORE_FPGA2: - case MIPS_REVISION_CORID_CORE_FPGA3: - case MIPS_REVISION_CORID_CORE_24K: - case MIPS_REVISION_CORID_CORE_EMUL_MSC: + switch (mips_revision_sconid) { + case MIPS_REVISION_SCON_SOCIT: + case MIPS_REVISION_SCON_ROCIT: + case MIPS_REVISION_SCON_SOCITSC: + case MIPS_REVISION_SCON_SOCITSCP: ll_msc_irq(); break; - case MIPS_REVISION_CORID_QED_RM5261: - case MIPS_REVISION_CORID_CORE_LV: - case MIPS_REVISION_CORID_CORE_FPGA: - case MIPS_REVISION_CORID_CORE_FPGAR2: + case MIPS_REVISION_SCON_GT64120: intrcause = GT_READ(GT_INTRCAUSE_OFS); datalo = GT_READ(GT_CPUERR_ADDRLO_OFS); datahi = GT_READ(GT_CPUERR_ADDRHI_OFS); printk("GT_INTRCAUSE = %08x\n", intrcause); printk("GT_CPUERR_ADDR = %02x%08x\n", datahi, datalo); break; - case MIPS_REVISION_CORID_BONITO64: - case MIPS_REVISION_CORID_CORE_20K: - case MIPS_REVISION_CORID_CORE_EMUL_BON: + case MIPS_REVISION_SCON_BONITO: pcibadaddr = BONITO_PCIBADADDR; pcimstat = BONITO_PCIMSTAT; intisr = BONITO_INTISR; diff --git a/arch/mips/mips-boards/malta/malta_setup.c b/arch/mips/mips-boards/malta/malta_setup.c index c14b7bf8995..8f1b78dfd89 100644 --- a/arch/mips/mips-boards/malta/malta_setup.c +++ b/arch/mips/mips-boards/malta/malta_setup.c @@ -103,9 +103,7 @@ void __init plat_mem_setup(void) kgdb_config (); #endif - if ((mips_revision_corid == MIPS_REVISION_CORID_BONITO64) || - (mips_revision_corid == MIPS_REVISION_CORID_CORE_20K) || - (mips_revision_corid == MIPS_REVISION_CORID_CORE_EMUL_BON)) { + if (mips_revision_sconid == MIPS_REVISION_SCON_BONITO) { char *argptr; argptr = prom_getcmdline(); diff --git a/include/asm-mips/mips-boards/generic.h b/include/asm-mips/mips-boards/generic.h index b98f1658cfd..c8ebcc3e126 100644 --- a/include/asm-mips/mips-boards/generic.h +++ b/include/asm-mips/mips-boards/generic.h @@ -73,12 +73,28 @@ * CoreEMUL with Bonito System Controller is treated like a Core20K * CoreEMUL with SOC-it 101 System Controller is treated like a CoreMSC */ -#define MIPS_REVISION_CORID_CORE_EMUL_BON 0x63 -#define MIPS_REVISION_CORID_CORE_EMUL_MSC 0x65 +#define MIPS_REVISION_CORID_CORE_EMUL_BON -1 +#define MIPS_REVISION_CORID_CORE_EMUL_MSC -2 #define MIPS_REVISION_CORID (((*(volatile u32 *)ioremap(MIPS_REVISION_REG, 4)) >> 10) & 0x3f) -extern unsigned int mips_revision_corid; +extern int mips_revision_corid; + +#define MIPS_REVISION_SCON_OTHER 0 +#define MIPS_REVISION_SCON_SOCITSC 1 +#define MIPS_REVISION_SCON_SOCITSCP 2 + +/* Artificial SCON defines for MIPS_REVISION_SCON_OTHER */ +#define MIPS_REVISION_SCON_UNKNOWN -1 +#define MIPS_REVISION_SCON_GT64120 -2 +#define MIPS_REVISION_SCON_BONITO -3 +#define MIPS_REVISION_SCON_BRTL -4 +#define MIPS_REVISION_SCON_SOCIT -5 +#define MIPS_REVISION_SCON_ROCIT -6 + +#define MIPS_REVISION_SCONID (((*(volatile u32 *)ioremap(MIPS_REVISION_REG, 4)) >> 24) & 0xff) + +extern int mips_revision_sconid; #ifdef CONFIG_PCI extern void mips_pcibios_init(void); diff --git a/include/asm-mips/mips-boards/msc01_pci.h b/include/asm-mips/mips-boards/msc01_pci.h index 8eaefb837b9..e036b7dd6de 100644 --- a/include/asm-mips/mips-boards/msc01_pci.h +++ b/include/asm-mips/mips-boards/msc01_pci.h @@ -208,6 +208,7 @@ * latter, they should be moved elsewhere. */ #define MIPS_MSC01_PCI_REG_BASE 0x1bd00000 +#define MIPS_SOCITSC_PCI_REG_BASE 0x1ff10000 extern unsigned long _pcictrl_msc; -- cgit v1.2.3 From ffe9ee4709cf513fb80e9b7e04d214dd8b76a10d Mon Sep 17 00:00:00 2001 From: Chris Dearman Date: Thu, 24 May 2007 22:24:20 +0100 Subject: [MIPS] Separate performance counter interrupts Support for performance counter overflow interrupt that is on a separate interrupt from the timer. Signed-off-by: Chris Dearman Signed-off-by: Ralf Baechle --- arch/mips/kernel/smp-mt.c | 12 ++-- arch/mips/kernel/time.c | 44 +++++++++---- arch/mips/mips-boards/generic/time.c | 118 +++++++++++++++++++++++++++-------- arch/mips/oprofile/op_model_mipsxx.c | 7 ++- 4 files changed, 135 insertions(+), 46 deletions(-) diff --git a/arch/mips/kernel/smp-mt.c b/arch/mips/kernel/smp-mt.c index 64b62bdfb4f..b8fa7ddd78f 100644 --- a/arch/mips/kernel/smp-mt.c +++ b/arch/mips/kernel/smp-mt.c @@ -129,13 +129,13 @@ static irqreturn_t ipi_call_interrupt(int irq, void *dev_id) static struct irqaction irq_resched = { .handler = ipi_resched_interrupt, - .flags = IRQF_DISABLED, + .flags = IRQF_DISABLED|IRQF_PERCPU, .name = "IPI_resched" }; static struct irqaction irq_call = { .handler = ipi_call_interrupt, - .flags = IRQF_DISABLED, + .flags = IRQF_DISABLED|IRQF_PERCPU, .name = "IPI_call" }; @@ -275,10 +275,7 @@ void __init plat_prepare_cpus(unsigned int max_cpus) setup_irq(cpu_ipi_resched_irq, &irq_resched); setup_irq(cpu_ipi_call_irq, &irq_call); - /* need to mark IPI's as IRQ_PER_CPU */ - irq_desc[cpu_ipi_resched_irq].status |= IRQ_PER_CPU; set_irq_handler(cpu_ipi_resched_irq, handle_percpu_irq); - irq_desc[cpu_ipi_call_irq].status |= IRQ_PER_CPU; set_irq_handler(cpu_ipi_call_irq, handle_percpu_irq); } @@ -326,8 +323,11 @@ void prom_boot_secondary(int cpu, struct task_struct *idle) void prom_init_secondary(void) { + /* Enable per-cpu interrupts */ + + /* This is Malta specific: IPI,performance and timer inetrrupts */ write_c0_status((read_c0_status() & ~ST0_IM ) | - (STATUSF_IP0 | STATUSF_IP1 | STATUSF_IP7)); + (STATUSF_IP0 | STATUSF_IP1 | STATUSF_IP6 | STATUSF_IP7)); } void prom_smp_finish(void) diff --git a/arch/mips/kernel/time.c b/arch/mips/kernel/time.c index 751b4a18b13..7def1ff3da9 100644 --- a/arch/mips/kernel/time.c +++ b/arch/mips/kernel/time.c @@ -199,6 +199,30 @@ int (*perf_irq)(void) = null_perf_irq; EXPORT_SYMBOL(null_perf_irq); EXPORT_SYMBOL(perf_irq); +/* + * Performance counter IRQ or -1 if shared with timer + */ +int mipsxx_perfcount_irq; +EXPORT_SYMBOL(mipsxx_perfcount_irq); + +/* + * Possibly handle a performance counter interrupt. + * Return true if the timer interrupt should not be checked + */ +static inline int handle_perf_irq (int r2) +{ + /* + * The performance counter overflow interrupt may be shared with the + * timer interrupt (mipsxx_perfcount_irq < 0). If it is and a + * performance counter has overflowed (perf_irq() == IRQ_HANDLED) + * and we can't reliably determine if a counter interrupt has also + * happened (!r2) then don't check for a timer interrupt. + */ + return (mipsxx_perfcount_irq < 0) && + perf_irq() == IRQ_HANDLED && + !r2; +} + asmlinkage void ll_timer_interrupt(int irq) { int r2 = cpu_has_mips_r2; @@ -206,19 +230,13 @@ asmlinkage void ll_timer_interrupt(int irq) irq_enter(); kstat_this_cpu.irqs[irq]++; - /* - * Suckage alert: - * Before R2 of the architecture there was no way to see if a - * performance counter interrupt was pending, so we have to run the - * performance counter interrupt handler anyway. - */ - if (!r2 || (read_c0_cause() & (1 << 26))) - if (perf_irq()) - goto out; + if (handle_perf_irq(r2)) + goto out; - /* we keep interrupt disabled all the time */ - if (!r2 || (read_c0_cause() & (1 << 30))) - timer_interrupt(irq, NULL); + if (r2 && ((read_c0_cause() & (1 << 30)) == 0)) + goto out; + + timer_interrupt(irq, NULL); out: irq_exit(); @@ -258,7 +276,7 @@ unsigned int mips_hpt_frequency; static struct irqaction timer_irqaction = { .handler = timer_interrupt, - .flags = IRQF_DISABLED, + .flags = IRQF_DISABLED | IRQF_PERCPU, .name = "timer", }; diff --git a/arch/mips/mips-boards/generic/time.c b/arch/mips/mips-boards/generic/time.c index b41db9e7ab1..33432ea188f 100644 --- a/arch/mips/mips-boards/generic/time.c +++ b/arch/mips/mips-boards/generic/time.c @@ -53,9 +53,8 @@ unsigned long cpu_khz; -#define CPUCTR_IMASKBIT (0x100 << MIPSCPU_INT_CPUCTR) - static int mips_cpu_timer_irq; +extern int mipsxx_perfcount_irq; extern void smtc_timer_broadcast(int); static void mips_timer_dispatch(void) @@ -63,6 +62,11 @@ static void mips_timer_dispatch(void) do_IRQ(mips_cpu_timer_irq); } +static void mips_perf_dispatch(void) +{ + do_IRQ(mipsxx_perfcount_irq); +} + /* * Redeclare until I get around mopping the timer code insanity on MIPS. */ @@ -70,6 +74,24 @@ extern int null_perf_irq(void); extern int (*perf_irq)(void); +/* + * Possibly handle a performance counter interrupt. + * Return true if the timer interrupt should not be checked + */ +static inline int handle_perf_irq (int r2) +{ + /* + * The performance counter overflow interrupt may be shared with the + * timer interrupt (mipsxx_perfcount_irq < 0). If it is and a + * performance counter has overflowed (perf_irq() == IRQ_HANDLED) + * and we can't reliably determine if a counter interrupt has also + * happened (!r2) then don't check for a timer interrupt. + */ + return (mipsxx_perfcount_irq < 0) && + perf_irq() == IRQ_HANDLED && + !r2; +} + irqreturn_t mips_timer_interrupt(int irq, void *dev_id) { int cpu = smp_processor_id(); @@ -92,8 +114,7 @@ irqreturn_t mips_timer_interrupt(int irq, void *dev_id) * We could be here due to timer interrupt, * perf counter overflow, or both. */ - if (read_c0_cause() & (1 << 26)) - perf_irq(); + (void) handle_perf_irq(1); if (read_c0_cause() & (1 << 30)) { /* @@ -115,19 +136,19 @@ irqreturn_t mips_timer_interrupt(int irq, void *dev_id) #else /* CONFIG_MIPS_MT_SMTC */ int r2 = cpu_has_mips_r2; + if (handle_perf_irq(r2)) + goto out; + + if (r2 && ((read_c0_cause() & (1 << 30)) == 0)) + goto out; + if (cpu == 0) { /* * CPU 0 handles the global timer interrupt job and process * accounting resets count/compare registers to trigger next * timer int. */ - if (!r2 || (read_c0_cause() & (1 << 26))) - if (perf_irq()) - goto out; - - /* we keep interrupt disabled all the time */ - if (!r2 || (read_c0_cause() & (1 << 30))) - timer_interrupt(irq, NULL); + timer_interrupt(irq, NULL); } else { /* Everyone else needs to reset the timer int here as ll_local_timer_interrupt doesn't */ @@ -225,35 +246,82 @@ void __init mips_time_init(void) mips_scroll_message(); } -void __init plat_timer_setup(struct irqaction *irq) +irqreturn_t mips_perf_interrupt(int irq, void *dev_id) { + return perf_irq(); +} + +static struct irqaction perf_irqaction = { + .handler = mips_perf_interrupt, + .flags = IRQF_DISABLED | IRQF_PERCPU, + .name = "performance", +}; + +void __init plat_perf_setup(struct irqaction *irq) +{ + int hwint = 0; + mipsxx_perfcount_irq = -1; + #ifdef MSC01E_INT_BASE if (cpu_has_veic) { - set_vi_handler (MSC01E_INT_CPUCTR, mips_timer_dispatch); - mips_cpu_timer_irq = MSC01E_INT_BASE + MSC01E_INT_CPUCTR; + set_vi_handler (MSC01E_INT_PERFCTR, mips_perf_dispatch); + mipsxx_perfcount_irq = MSC01E_INT_BASE + MSC01E_INT_PERFCTR; } else #endif - { - if (cpu_has_vint) - set_vi_handler (MIPSCPU_INT_CPUCTR, mips_timer_dispatch); - mips_cpu_timer_irq = MIPSCPU_INT_BASE + MIPSCPU_INT_CPUCTR; + if (cpu_has_mips_r2) { + /* + * Read IntCtl.IPPCI to determine the performance + * counter interrupt + */ + hwint = (read_c0_intctl () >> 26) & 7; + if (hwint != MIPSCPU_INT_CPUCTR) { + if (cpu_has_vint) + set_vi_handler (hwint, mips_perf_dispatch); + mipsxx_perfcount_irq = MIPSCPU_INT_BASE + hwint; + } + } + if (mipsxx_perfcount_irq >= 0) { +#ifdef CONFIG_MIPS_MT_SMTC + setup_irq_smtc(mipsxx_perfcount_irq, irq, 0x100 << hwint); +#else + setup_irq(mipsxx_perfcount_irq, irq); +#endif /* CONFIG_MIPS_MT_SMTC */ +#ifdef CONFIG_SMP + set_irq_handler(mipsxx_perfcount_irq, handle_percpu_irq); +#endif } +} +void __init plat_timer_setup(struct irqaction *irq) +{ + int hwint = 0; + if (cpu_has_veic) { + set_vi_handler (MSC01E_INT_CPUCTR, mips_timer_dispatch); + mips_cpu_timer_irq = MSC01E_INT_BASE + MSC01E_INT_CPUCTR; + } + else { + if (cpu_has_mips_r2) + /* + * Read IntCtl.IPTI to determine the timer interrupt + */ + hwint = (read_c0_intctl () >> 29) & 7; + else + hwint = MIPSCPU_INT_CPUCTR; + if (cpu_has_vint) + set_vi_handler (hwint, mips_timer_dispatch); + mips_cpu_timer_irq = MIPSCPU_INT_BASE + hwint; + } /* we are using the cpu counter for timer interrupts */ irq->handler = mips_timer_interrupt; /* we use our own handler */ #ifdef CONFIG_MIPS_MT_SMTC - setup_irq_smtc(mips_cpu_timer_irq, irq, CPUCTR_IMASKBIT); + setup_irq_smtc(mips_cpu_timer_irq, irq, 0x100 << hwint); #else setup_irq(mips_cpu_timer_irq, irq); #endif /* CONFIG_MIPS_MT_SMTC */ - #ifdef CONFIG_SMP - /* irq_desc(riptor) is a global resource, when the interrupt overlaps - on seperate cpu's the first one tries to handle the second interrupt. - The effect is that the int remains disabled on the second cpu. - Mark the interrupt with IRQ_PER_CPU to avoid any confusion */ - irq_desc[mips_cpu_timer_irq].status |= IRQ_PER_CPU; set_irq_handler(mips_cpu_timer_irq, handle_percpu_irq); #endif + + plat_perf_setup(&perf_irqaction); } diff --git a/arch/mips/oprofile/op_model_mipsxx.c b/arch/mips/oprofile/op_model_mipsxx.c index 4f94fa261aa..1ea5c9c1010 100644 --- a/arch/mips/oprofile/op_model_mipsxx.c +++ b/arch/mips/oprofile/op_model_mipsxx.c @@ -177,7 +177,10 @@ static int mipsxx_perfcount_handler(void) unsigned int counters = op_model_mipsxx_ops.num_counters; unsigned int control; unsigned int counter; - int handled = 0; + int handled = IRQ_NONE; + + if (cpu_has_mips_r2 && !(read_c0_cause() & (1 << 26))) + return handled; switch (counters) { #define HANDLE_COUNTER(n) \ @@ -188,7 +191,7 @@ static int mipsxx_perfcount_handler(void) (counter & M_COUNTER_OVERFLOW)) { \ oprofile_add_sample(get_irq_regs(), n); \ w_c0_perfcntr ## n(reg.counter[n]); \ - handled = 1; \ + handled = IRQ_HANDLED; \ } HANDLE_COUNTER(3) HANDLE_COUNTER(2) -- cgit v1.2.3 From 7b4f4ec21038ac13c63d130357d1c3015ec3f3e8 Mon Sep 17 00:00:00 2001 From: Chris Dearman Date: Thu, 24 May 2007 22:46:25 +0100 Subject: [MIPS] Fix builds where MSC01E_xxx is undefined. Signed-off-by: Chris Dearman Signed-off-by: Ralf Baechle --- arch/mips/mips-boards/generic/time.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/arch/mips/mips-boards/generic/time.c b/arch/mips/mips-boards/generic/time.c index 33432ea188f..8f1000f51b3 100644 --- a/arch/mips/mips-boards/generic/time.c +++ b/arch/mips/mips-boards/generic/time.c @@ -295,11 +295,14 @@ void __init plat_perf_setup(struct irqaction *irq) void __init plat_timer_setup(struct irqaction *irq) { int hwint = 0; +#ifdef MSC01E_INT_BASE if (cpu_has_veic) { set_vi_handler (MSC01E_INT_CPUCTR, mips_timer_dispatch); mips_cpu_timer_irq = MSC01E_INT_BASE + MSC01E_INT_CPUCTR; } - else { + else +#endif + { if (cpu_has_mips_r2) /* * Read IntCtl.IPTI to determine the timer interrupt -- cgit v1.2.3