summaryrefslogtreecommitdiffstats
path: root/target/linux/brcm63xx/patches-2.6.25/060-bcm963xx_rewrite_irq_handling_code.patch
diff options
context:
space:
mode:
Diffstat (limited to 'target/linux/brcm63xx/patches-2.6.25/060-bcm963xx_rewrite_irq_handling_code.patch')
-rw-r--r--target/linux/brcm63xx/patches-2.6.25/060-bcm963xx_rewrite_irq_handling_code.patch452
1 files changed, 0 insertions, 452 deletions
diff --git a/target/linux/brcm63xx/patches-2.6.25/060-bcm963xx_rewrite_irq_handling_code.patch b/target/linux/brcm63xx/patches-2.6.25/060-bcm963xx_rewrite_irq_handling_code.patch
deleted file mode 100644
index 349010486..000000000
--- a/target/linux/brcm63xx/patches-2.6.25/060-bcm963xx_rewrite_irq_handling_code.patch
+++ /dev/null
@@ -1,452 +0,0 @@
-From 9a70f2dcb24a5aab29386373c86ba035acba4891 Mon Sep 17 00:00:00 2001
-From: Axel Gembe <ago@bastart.eu.org>
-Date: Sun, 18 May 2008 12:07:21 +0200
-Subject: [PATCH] bcm963xx: rewrite irq handling code
-
-This patch adds interrupt handling as on AR7. The old code was very messy and
-didn't work too well.
-
-Signed-off-by: Axel Gembe <ago@bastart.eu.org>
----
- arch/mips/bcm963xx/irq.c | 308 ++++++++++-------------------
- drivers/serial/bcm63xx_cons.c | 13 +-
- include/asm-mips/mach-bcm963xx/bcm_intr.h | 18 +--
- 3 files changed, 119 insertions(+), 220 deletions(-)
-
---- a/arch/mips/bcm963xx/irq.c
-+++ b/arch/mips/bcm963xx/irq.c
-@@ -1,259 +1,159 @@
- /*
--<:copyright-gpl
-- Copyright 2002 Broadcom Corp. All Rights Reserved.
--
-- 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.
--:>
--*/
--/*
-- * Interrupt control functions for Broadcom 963xx MIPS boards
-+ * Copyright (C) 2006,2007 Felix Fietkau <nbd@openwrt.org>
-+ * Copyright (C) 2006,2007 Eugene Konev <ejka@openwrt.org>
-+ * Copyright (C) 2008 Axel Gembe <ago@bastart.eu.org>
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
--#include <asm/atomic.h>
--
--#include <linux/delay.h>
--#include <linux/init.h>
--#include <linux/ioport.h>
--#include <linux/irq.h>
- #include <linux/interrupt.h>
--#include <linux/kernel.h>
--#include <linux/slab.h>
--#include <linux/module.h>
-+#include <linux/io.h>
-
--#include <asm/irq.h>
-+#include <asm/irq_cpu.h>
- #include <asm/mipsregs.h>
--#include <asm/addrspace.h>
--#include <asm/signal.h>
-+
- #include <6348_map_part.h>
- #include <6348_intr.h>
- #include <bcm_map_part.h>
- #include <bcm_intr.h>
-
--static void irq_dispatch_int(void)
--{
-- unsigned int pendingIrqs;
-- static unsigned int irqBit;
-- static unsigned int isrNumber = 31;
--
-- pendingIrqs = PERF->IrqStatus & PERF->IrqMask;
-- if (!pendingIrqs) {
-- return;
-- }
-+static int bcm963xx_irq_base;
-
-- while (1) {
-- irqBit <<= 1;
-- isrNumber++;
-- if (isrNumber == 32) {
-- isrNumber = 0;
-- irqBit = 0x1;
-- }
-- if (pendingIrqs & irqBit) {
-- PERF->IrqMask &= ~irqBit; // mask
-- do_IRQ(isrNumber + INTERNAL_ISR_TABLE_OFFSET);
-- break;
-- }
-- }
-+void bcm963xx_unmask_irq(unsigned int irq)
-+{
-+ PERF->IrqMask |= (1 << (irq - bcm963xx_irq_base));
- }
-
--static void irq_dispatch_ext(uint32 irq)
-+void bcm963xx_mask_irq(unsigned int irq)
- {
-- if (!(PERF->ExtIrqCfg & (1 << (irq - INTERRUPT_ID_EXTERNAL_0 + EI_MASK_SHFT)))) {
-- printk("**** Ext IRQ mask. Should not dispatch ****\n");
-- }
-- /* disable and clear interrupt in the controller */
-- PERF->ExtIrqCfg |= (1 << (irq - INTERRUPT_ID_EXTERNAL_0 + EI_CLEAR_SHFT));
-- PERF->ExtIrqCfg &= ~(1 << (irq - INTERRUPT_ID_EXTERNAL_0 + EI_MASK_SHFT));
-- do_IRQ(irq);
-+ PERF->IrqMask &= ~(1 << (irq - bcm963xx_irq_base));
- }
-
--
--//extern void brcm_timer_interrupt(struct pt_regs *regs);
--
--asmlinkage void plat_irq_dispatch(void)
-+void bcm963xx_ack_irq(unsigned int irq)
- {
-- unsigned long cause;
--
-- cause = read_c0_status() & read_c0_cause() & ST0_IM;
-- if (cause & CAUSEF_IP7)
-- do_IRQ(7);
-- else if (cause & CAUSEF_IP2)
-- irq_dispatch_int();
-- else if (cause & CAUSEF_IP3)
-- irq_dispatch_ext(INTERRUPT_ID_EXTERNAL_0);
-- else if (cause & CAUSEF_IP4)
-- irq_dispatch_ext(INTERRUPT_ID_EXTERNAL_1);
-- else if (cause & CAUSEF_IP5)
-- irq_dispatch_ext(INTERRUPT_ID_EXTERNAL_2);
-- else if (cause & CAUSEF_IP6) {
-- irq_dispatch_ext(INTERRUPT_ID_EXTERNAL_3);
-- local_irq_disable();
-- }
-+ PERF->IrqStatus &= ~(1 << (irq - bcm963xx_irq_base));
- }
-
--
--void enable_brcm_irq(unsigned int irq)
-+void bcm963xx_unmask_ext_irq(unsigned int irq)
- {
-- unsigned long flags;
--
-- local_irq_save(flags);
-- if( irq >= INTERNAL_ISR_TABLE_OFFSET ) {
-- PERF->IrqMask |= (1 << (irq - INTERNAL_ISR_TABLE_OFFSET));
-- }
-- else if (irq >= INTERRUPT_ID_EXTERNAL_0 && irq <= INTERRUPT_ID_EXTERNAL_3) {
-- /* enable and clear interrupt in the controller */
-- PERF->ExtIrqCfg |= (1 << (irq - INTERRUPT_ID_EXTERNAL_0 + EI_CLEAR_SHFT));
- PERF->ExtIrqCfg |= (1 << (irq - INTERRUPT_ID_EXTERNAL_0 + EI_MASK_SHFT));
-- }
-- local_irq_restore(flags);
- }
-
--void disable_brcm_irq(unsigned int irq)
-+void bcm963xx_mask_ext_irq(unsigned int irq)
- {
-- unsigned long flags;
--
-- local_irq_save(flags);
-- if( irq >= INTERNAL_ISR_TABLE_OFFSET ) {
-- PERF->IrqMask &= ~(1 << (irq - INTERNAL_ISR_TABLE_OFFSET));
-- }
-- else if (irq >= INTERRUPT_ID_EXTERNAL_0 && irq <= INTERRUPT_ID_EXTERNAL_3) {
-- /* disable interrupt in the controller */
- PERF->ExtIrqCfg &= ~(1 << (irq - INTERRUPT_ID_EXTERNAL_0 + EI_MASK_SHFT));
-- }
-- local_irq_restore(flags);
- }
-
--void ack_brcm_irq(unsigned int irq)
-+void bcm963xx_ack_ext_irq(unsigned int irq)
- {
-- /* Already done in brcm_irq_dispatch */
-+ PERF->ExtIrqCfg |= (1 << (irq - INTERRUPT_ID_EXTERNAL_0 + EI_CLEAR_SHFT));
- }
-
--unsigned int startup_brcm_irq(unsigned int irq)
-+static void bcm963xx_dispatch_ext_irq(unsigned int irq)
- {
-- enable_brcm_irq(irq);
--
-- return 0; /* never anything pending */
-+ bcm963xx_ack_ext_irq(irq);
-+ bcm963xx_mask_ext_irq(irq);
-+ do_IRQ(irq);
- }
-
--unsigned int startup_brcm_none(unsigned int irq)
-+static void bcm963xx_cascade(void)
- {
-- return 0;
--}
-+ uint32_t pending, bit, irq;
-
--void end_brcm_irq(unsigned int irq)
--{
-- if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
-- enable_brcm_irq(irq);
--}
-+ if (!(pending = PERF->IrqStatus & PERF->IrqMask))
-+ return;
-
--void end_brcm_none(unsigned int irq)
--{
--}
-+ for (irq = 0, bit = 1; irq < 32; irq++, bit <<= 1) {
-+ if (pending & bit) {
-+ bcm963xx_ack_irq(irq + bcm963xx_irq_base);
-+ bcm963xx_mask_irq(irq + bcm963xx_irq_base);
-+ do_IRQ(irq + bcm963xx_irq_base);
-+ return;
-+ }
-+ }
-+
-+ spurious_interrupt();
-+}
-+
-+static struct irq_chip bcm963xx_irq_type = {
-+ .name = "bcm963xx",
-+ .unmask = bcm963xx_unmask_irq,
-+ .mask = bcm963xx_mask_irq,
-+ .ack = bcm963xx_ack_irq
-+};
-
--static struct hw_interrupt_type brcm_irq_type = {
-- .typename = "MIPS",
-- .startup = startup_brcm_irq,
-- .shutdown = disable_brcm_irq,
-- .enable = enable_brcm_irq,
-- .disable = disable_brcm_irq,
-- .ack = ack_brcm_irq,
-- .end = end_brcm_irq,
-- .set_affinity = NULL
-+static struct irq_chip bcm963xx_ext_irq_type = {
-+ .name = "bcm963xx_ext",
-+ .unmask = bcm963xx_unmask_ext_irq,
-+ .mask = bcm963xx_mask_ext_irq,
-+ .ack = bcm963xx_ack_ext_irq,
- };
-
--static struct hw_interrupt_type brcm_irq_no_end_type = {
-- .typename = "MIPS",
-- .startup = startup_brcm_none,
-- .shutdown = disable_brcm_irq,
-- .enable = enable_brcm_irq,
-- .disable = disable_brcm_irq,
-- .ack = ack_brcm_irq,
-- .end = end_brcm_none,
-- .set_affinity = NULL
-+static struct irqaction bcm963xx_cascade_action = {
-+ .handler = no_action,
-+ .name = "BCM963xx cascade interrupt"
- };
-
--void __init arch_init_irq(void)
-+static void __init bcm963xx_irq_init(int base)
- {
- int i;
-
-- clear_c0_status(ST0_BEV);
-- change_c0_status(ST0_IM, (IE_IRQ0 | IE_IRQ1 | IE_IRQ2 | IE_IRQ3 | IE_IRQ4));
-+ bcm963xx_irq_base = base;
-
-- for (i = 0; i < NR_IRQS; i++) {
-- irq_desc[i].status = IRQ_DISABLED;
-- irq_desc[i].action = 0;
-- irq_desc[i].depth = 1;
-- irq_desc[i].chip = &brcm_irq_type;
-- }
-+ /* External IRQs */
-+ set_irq_chip_and_handler(INTERRUPT_ID_EXTERNAL_0, &bcm963xx_ext_irq_type,
-+ handle_level_irq);
-+ set_irq_chip_and_handler(INTERRUPT_ID_EXTERNAL_1, &bcm963xx_ext_irq_type,
-+ handle_level_irq);
-+ set_irq_chip_and_handler(INTERRUPT_ID_EXTERNAL_2, &bcm963xx_ext_irq_type,
-+ handle_level_irq);
-+ set_irq_chip_and_handler(INTERRUPT_ID_EXTERNAL_3, &bcm963xx_ext_irq_type,
-+ handle_level_irq);
-+
-+ for (i = 0; i < 32; i++) {
-+ set_irq_chip_and_handler(base + i, &bcm963xx_irq_type,
-+ handle_level_irq);
-+ }
-+
-+ setup_irq(2, &bcm963xx_cascade_action);
-+ setup_irq(bcm963xx_irq_base, &bcm963xx_cascade_action);
-+ set_c0_status(IE_IRQ0);
- }
-
--int request_external_irq(unsigned int irq,
-- FN_HANDLER handler,
-- unsigned long irqflags,
-- const char * devname,
-- void *dev_id)
-+asmlinkage void plat_irq_dispatch(void)
- {
-- unsigned long flags;
--
-- local_irq_save(flags);
-+ unsigned int pending = read_c0_status() & read_c0_cause() & ST0_IM;
-
-- PERF->ExtIrqCfg |= (1 << (irq - INTERRUPT_ID_EXTERNAL_0 + EI_CLEAR_SHFT)); // Clear
-- PERF->ExtIrqCfg &= ~(1 << (irq - INTERRUPT_ID_EXTERNAL_0 + EI_MASK_SHFT)); // Mask
-- PERF->ExtIrqCfg &= ~(1 << (irq - INTERRUPT_ID_EXTERNAL_0 + EI_INSENS_SHFT)); // Edge insesnsitive
-- PERF->ExtIrqCfg |= (1 << (irq - INTERRUPT_ID_EXTERNAL_0 + EI_LEVEL_SHFT)); // Level triggered
-- PERF->ExtIrqCfg &= ~(1 << (irq - INTERRUPT_ID_EXTERNAL_0 + EI_SENSE_SHFT)); // Low level
--
-- local_irq_restore(flags);
--
-- return( request_irq(irq, handler, irqflags, devname, dev_id) );
-+ if (pending & STATUSF_IP7) /* cpu timer */
-+ do_IRQ(7);
-+ else if (pending & STATUSF_IP2) /* internal interrupt cascade */
-+ bcm963xx_cascade();
-+ else if (pending & STATUSF_IP3)
-+ bcm963xx_dispatch_ext_irq(INTERRUPT_ID_EXTERNAL_0);
-+ else if (pending & STATUSF_IP4)
-+ bcm963xx_dispatch_ext_irq(INTERRUPT_ID_EXTERNAL_1);
-+ else if (pending & STATUSF_IP5)
-+ bcm963xx_dispatch_ext_irq(INTERRUPT_ID_EXTERNAL_2);
-+ else if (pending & STATUSF_IP6)
-+ bcm963xx_dispatch_ext_irq(INTERRUPT_ID_EXTERNAL_3);
-+ else
-+ spurious_interrupt();
- }
-
--/* VxWorks compatibility function(s). */
--
--unsigned int BcmHalMapInterrupt(FN_HANDLER pfunc, unsigned int param,
-- unsigned int interruptId)
-+void __init arch_init_irq(void)
- {
-- int nRet = -1;
-- char *devname;
--
-- devname = kmalloc(16, GFP_KERNEL);
-- if (devname)
-- sprintf( devname, "brcm_%d", interruptId );
--
-- /* Set the IRQ description to not automatically enable the interrupt at
-- * the end of an ISR. The driver that handles the interrupt must
-- * explicitly call BcmHalInterruptEnable or enable_brcm_irq. This behavior
-- * is consistent with interrupt handling on VxWorks.
-- */
-- irq_desc[interruptId].chip = &brcm_irq_no_end_type;
--
-- if( interruptId >= INTERNAL_ISR_TABLE_OFFSET )
-- {
-- printk("BcmHalMapInterrupt : internal IRQ\n");
-- nRet = request_irq( interruptId, pfunc, IRQF_DISABLED, devname, (void *) param );
-- }
-- else if (interruptId >= INTERRUPT_ID_EXTERNAL_0 && interruptId <= INTERRUPT_ID_EXTERNAL_3)
-- {
-- printk("BcmHalMapInterrupt : external IRQ\n");
-- nRet = request_external_irq( interruptId, pfunc, IRQF_DISABLED, devname, (void *) param );
-- }
--
-- return( nRet );
-+ mips_cpu_irq_init();
-+ bcm963xx_irq_init(INTERNAL_ISR_TABLE_OFFSET);
- }
--
--
--EXPORT_SYMBOL(enable_brcm_irq);
--EXPORT_SYMBOL(disable_brcm_irq);
--EXPORT_SYMBOL(request_external_irq);
--EXPORT_SYMBOL(BcmHalMapInterrupt);
--
---- a/drivers/serial/bcm63xx_cons.c
-+++ b/drivers/serial/bcm63xx_cons.c
-@@ -267,7 +267,7 @@
- }
-
- // Clear the interrupt
-- enable_brcm_irq(INTERRUPT_ID_UART);
-+// bcm963xx_unmask_irq(INTERRUPT_ID_UART);
- #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
- return IRQ_HANDLED;
- #endif
-@@ -880,7 +880,7 @@
- info->count++;
- tty->driver_data = info;
- info->tty = tty;
-- enable_brcm_irq(INTERRUPT_ID_UART);
-+ bcm963xx_unmask_irq(INTERRUPT_ID_UART);
-
- // Start up serial port
- retval = startup(info);
-@@ -927,7 +927,7 @@
- -------------------------------------------------------------------------- */
- static int __init bcm63xx_serialinit(void)
- {
-- int i, flags;
-+ int i, flags, res;
- struct bcm_serial *info;
-
- // Print the driver version information
-@@ -981,7 +981,12 @@
- */
- if (!info->port)
- return 0;
-- BcmHalMapInterrupt(bcm_interrupt, 0, INTERRUPT_ID_UART);
-+
-+ res = request_irq(INTERRUPT_ID_UART, bcm_interrupt, 0, "bcm-uart", NULL);
-+ if (res) {
-+ spin_unlock_irqrestore(&bcm963xx_serial_lock, flags);
-+ return res;
-+ }
- }
-
- /* order matters here... the trick is that flags
---- a/include/asm-mips/mach-bcm963xx/bcm_intr.h
-+++ b/include/asm-mips/mach-bcm963xx/bcm_intr.h
-@@ -39,18 +39,12 @@
- typedef int (*FN_HANDLER) (int, void *);
-
- /* prototypes */
--extern void enable_brcm_irq(unsigned int irq);
--extern void disable_brcm_irq(unsigned int irq);
--extern int request_external_irq(unsigned int irq,
-- FN_HANDLER handler, unsigned long irqflags,
-- const char * devname, void *dev_id);
--extern unsigned int BcmHalMapInterrupt(FN_HANDLER isr, unsigned int param,
-- unsigned int interruptId);
--extern void dump_intr_regs(void);
--
--/* compatibility definitions */
--#define BcmHalInterruptEnable(irq) enable_brcm_irq( irq )
--#define BcmHalInterruptDisable(irq) disable_brcm_irq( irq )
-+extern void bcm963xx_unmask_irq(unsigned int irq);
-+extern void bcm963xx_mask_irq(unsigned int irq);
-+extern void bcm963xx_ack_irq(unsigned int irq);
-+extern void bcm963xx_unmask_ext_irq(unsigned int irq);
-+extern void bcm963xx_mask_ext_irq(unsigned int irq);
-+extern void bcm963xx_ack_ext_irq(unsigned int irq);
-
- #ifdef __cplusplus
- }