From dd67b1556ebea118b40986cdb8e70874b5454442 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Sun, 14 Oct 2007 14:02:26 +0100 Subject: [PATCH 01/19] [MIPS] IP32: Fix build by conversion to irq_cpu.c. Signed-off-by: Ralf Baechle --- arch/mips/Kconfig | 1 + arch/mips/sgi-ip32/ip32-irq.c | 158 ++++++++++++++---------------- arch/mips/sgi-ip32/ip32-setup.c | 2 +- include/asm-mips/ip32/ip32_ints.h | 158 +++++++++++++++++------------- 4 files changed, 161 insertions(+), 158 deletions(-) diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index f943736541cb..f921235239f9 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -410,6 +410,7 @@ config SGI_IP32 select BOOT_ELF32 select DMA_NONCOHERENT select HW_HAS_PCI + select IRQ_CPU select R5000_CPU_SCACHE select RM7000_CPU_SCACHE select SYS_HAS_CPU_R5000 diff --git a/arch/mips/sgi-ip32/ip32-irq.c b/arch/mips/sgi-ip32/ip32-irq.c index 7f4b793c3df3..7e8094f617bf 100644 --- a/arch/mips/sgi-ip32/ip32-irq.c +++ b/arch/mips/sgi-ip32/ip32-irq.c @@ -20,6 +20,7 @@ #include #include +#include #include #include #include @@ -46,7 +47,8 @@ static void inline flush_mace_bus(void) #define DBG(x...) #endif -/* O2 irq map +/* + * O2 irq map * * IP0 -> software (ignored) * IP1 -> software (ignored) @@ -55,60 +57,60 @@ static void inline flush_mace_bus(void) * IP4 -> (irq2) X unknown * IP5 -> (irq3) X unknown * IP6 -> (irq4) X unknown - * IP7 -> (irq5) 0 CPU count/compare timer (system timer) + * IP7 -> (irq5) 7 CPU count/compare timer (system timer) * * crime: (C) * * CRIME_INT_STAT 31:0: * - * 0 -> 1 Video in 1 - * 1 -> 2 Video in 2 - * 2 -> 3 Video out - * 3 -> 4 Mace ethernet + * 0 -> 8 Video in 1 + * 1 -> 9 Video in 2 + * 2 -> 10 Video out + * 3 -> 11 Mace ethernet * 4 -> S SuperIO sub-interrupt * 5 -> M Miscellaneous sub-interrupt * 6 -> A Audio sub-interrupt - * 7 -> 8 PCI bridge errors - * 8 -> 9 PCI SCSI aic7xxx 0 - * 9 -> 10 PCI SCSI aic7xxx 1 - * 10 -> 11 PCI slot 0 - * 11 -> 12 unused (PCI slot 1) - * 12 -> 13 unused (PCI slot 2) - * 13 -> 14 unused (PCI shared 0) - * 14 -> 15 unused (PCI shared 1) - * 15 -> 16 unused (PCI shared 2) - * 16 -> 17 GBE0 (E) - * 17 -> 18 GBE1 (E) - * 18 -> 19 GBE2 (E) - * 19 -> 20 GBE3 (E) - * 20 -> 21 CPU errors - * 21 -> 22 Memory errors - * 22 -> 23 RE empty edge (E) - * 23 -> 24 RE full edge (E) - * 24 -> 25 RE idle edge (E) - * 25 -> 26 RE empty level - * 26 -> 27 RE full level - * 27 -> 28 RE idle level - * 28 -> 29 unused (software 0) (E) - * 29 -> 30 unused (software 1) (E) - * 30 -> 31 unused (software 2) - crime 1.5 CPU SysCorError (E) - * 31 -> 32 VICE + * 7 -> 15 PCI bridge errors + * 8 -> 16 PCI SCSI aic7xxx 0 + * 9 -> 17 PCI SCSI aic7xxx 1 + * 10 -> 18 PCI slot 0 + * 11 -> 19 unused (PCI slot 1) + * 12 -> 20 unused (PCI slot 2) + * 13 -> 21 unused (PCI shared 0) + * 14 -> 22 unused (PCI shared 1) + * 15 -> 23 unused (PCI shared 2) + * 16 -> 24 GBE0 (E) + * 17 -> 25 GBE1 (E) + * 18 -> 26 GBE2 (E) + * 19 -> 27 GBE3 (E) + * 20 -> 28 CPU errors + * 21 -> 29 Memory errors + * 22 -> 30 RE empty edge (E) + * 23 -> 31 RE full edge (E) + * 24 -> 32 RE idle edge (E) + * 25 -> 33 RE empty level + * 26 -> 34 RE full level + * 27 -> 35 RE idle level + * 28 -> 36 unused (software 0) (E) + * 29 -> 37 unused (software 1) (E) + * 30 -> 38 unused (software 2) - crime 1.5 CPU SysCorError (E) + * 31 -> 39 VICE * * S, M, A: Use the MACE ISA interrupt register * MACE_ISA_INT_STAT 31:0 * - * 0-7 -> 33-40 Audio - * 8 -> 41 RTC - * 9 -> 42 Keyboard + * 0-7 -> 40-47 Audio + * 8 -> 48 RTC + * 9 -> 49 Keyboard * 10 -> X Keyboard polled - * 11 -> 44 Mouse + * 11 -> 51 Mouse * 12 -> X Mouse polled - * 13-15 -> 46-48 Count/compare timers - * 16-19 -> 49-52 Parallel (16 E) - * 20-25 -> 53-58 Serial 1 (22 E) - * 26-31 -> 59-64 Serial 2 (28 E) + * 13-15 -> 53-55 Count/compare timers + * 16-19 -> 56-59 Parallel (16 E) + * 20-25 -> 60-62 Serial 1 (22 E) + * 26-31 -> 66-71 Serial 2 (28 E) * - * Note that this means IRQs 5-7, 43, and 45 do not exist. This is a + * Note that this means IRQs 12-14, 50, and 52 do not exist. This is a * different IRQ map than IRIX uses, but that's OK as Linux irq handling * is quite different anyway. */ @@ -130,36 +132,6 @@ struct irqaction cpuerr_irq = { .name = "CRIME CPU error", }; -/* - * For interrupts wired from a single device to the CPU. Only the clock - * uses this it seems, which is IRQ 0 and IP7. - */ - -static void enable_cpu_irq(unsigned int irq) -{ - set_c0_status(STATUSF_IP7); -} - -static void disable_cpu_irq(unsigned int irq) -{ - clear_c0_status(STATUSF_IP7); -} - -static void end_cpu_irq(unsigned int irq) -{ - if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) - enable_cpu_irq(irq); -} - -static struct irq_chip ip32_cpu_interrupt = { - .name = "IP32 CPU", - .ack = disable_cpu_irq, - .mask = disable_cpu_irq, - .mask_ack = disable_cpu_irq, - .unmask = enable_cpu_irq, - .end = end_cpu_irq, -}; - /* * This is for pure CRIME interrupts - ie not MACE. The advantage? * We get to split the register in half and do faster lookups. @@ -422,15 +394,23 @@ static void ip32_irq0(void) uint64_t crime_int; int irq = 0; + /* + * Sanity check interrupt numbering enum. + * MACE got 32 interrupts and there are 32 MACE ISA interrupts daisy + * chained. + */ + BUILD_BUG_ON(CRIME_VICE_IRQ - MACE_VID_IN1_IRQ != 31); + BUILD_BUG_ON(MACEISA_SERIAL2_RDMAOR_IRQ - MACEISA_AUDIO_SW_IRQ != 31); + crime_int = crime->istat & crime_mask; - irq = __ffs(crime_int); + irq = MACE_VID_IN1_IRQ + __ffs(crime_int); crime_int = 1 << irq; if (crime_int & CRIME_MACEISA_INT_MASK) { unsigned long mace_int = mace->perif.ctrl.istat; - irq = __ffs(mace_int & maceisa_mask) + 32; + irq = __ffs(mace_int & maceisa_mask) + MACEISA_AUDIO_SW_IRQ; } - irq++; + DBG("*irq %u*\n", irq); do_IRQ(irq); } @@ -457,7 +437,7 @@ static void ip32_irq4(void) static void ip32_irq5(void) { - do_IRQ(IP32_R4K_TIMER_IRQ); + do_IRQ(MIPS_CPU_IRQ_BASE + 7); } asmlinkage void plat_irq_dispatch(void) @@ -490,21 +470,25 @@ void __init arch_init_irq(void) mace->perif.ctrl.istat = 0; mace->perif.ctrl.imask = 0; - for (irq = 0; irq <= IP32_IRQ_MAX; irq++) { - struct irq_chip *controller; + mips_cpu_irq_init(); + for (irq = MIPS_CPU_IRQ_BASE + 8; irq <= IP32_IRQ_MAX; irq++) { + struct irq_chip *chip; - if (irq == IP32_R4K_TIMER_IRQ) - controller = &ip32_cpu_interrupt; - else if (irq <= MACE_PCI_BRIDGE_IRQ && irq >= MACE_VID_IN1_IRQ) - controller = &ip32_mace_interrupt; - else if (irq <= MACEPCI_SHARED2_IRQ && irq >= MACEPCI_SCSI0_IRQ) - controller = &ip32_macepci_interrupt; - else if (irq <= CRIME_VICE_IRQ && irq >= CRIME_GBE0_IRQ) - controller = &ip32_crime_interrupt; - else - controller = &ip32_maceisa_interrupt; + switch (irq) { + case MACE_VID_IN1_IRQ ... MACE_PCI_BRIDGE_IRQ: + chip = &ip32_mace_interrupt; + break; + case MACEPCI_SCSI0_IRQ ... MACEPCI_SHARED2_IRQ: + chip = &ip32_macepci_interrupt; + break; + case CRIME_GBE0_IRQ ... CRIME_VICE_IRQ: + chip = &ip32_crime_interrupt; + break; + default: + chip = &ip32_maceisa_interrupt; + } - set_irq_chip(irq, controller); + set_irq_chip(irq, chip); } setup_irq(CRIME_MEMERR_IRQ, &memerr_irq); setup_irq(CRIME_CPUERR_IRQ, &cpuerr_irq); diff --git a/arch/mips/sgi-ip32/ip32-setup.c b/arch/mips/sgi-ip32/ip32-setup.c index 4125a5ba119e..fc75bfcb0c0e 100644 --- a/arch/mips/sgi-ip32/ip32-setup.c +++ b/arch/mips/sgi-ip32/ip32-setup.c @@ -83,7 +83,7 @@ void __init plat_time_init(void) void __init plat_timer_setup(struct irqaction *irq) { irq->handler = no_action; - setup_irq(IP32_R4K_TIMER_IRQ, irq); + setup_irq(MIPS_CPU_IRQ_BASE + 7, irq); } void __init plat_mem_setup(void) diff --git a/include/asm-mips/ip32/ip32_ints.h b/include/asm-mips/ip32/ip32_ints.h index c3c280e3d591..042f821899a8 100644 --- a/include/asm-mips/ip32/ip32_ints.h +++ b/include/asm-mips/ip32/ip32_ints.h @@ -9,86 +9,104 @@ #ifndef __ASM_IP32_INTS_H #define __ASM_IP32_INTS_H +#include + /* * This list reflects the assignment of interrupt numbers to * interrupting events. Order is fairly irrelevant to handling * priority. This differs from irix. */ -/* CPU */ -#define IP32_R4K_TIMER_IRQ 0 +enum ip32_irq_no { + /* + * CPU interrupts are 0 ... 7 + */ -/* MACE */ -#define MACE_VID_IN1_IRQ 1 -#define MACE_VID_IN2_IRQ 2 -#define MACE_VID_OUT_IRQ 3 -#define MACE_ETHERNET_IRQ 4 -/* SUPERIO, MISC, and AUDIO are MACEISA */ -#define MACE_PCI_BRIDGE_IRQ 8 + /* + * MACE + */ + MACE_VID_IN1_IRQ = MIPS_CPU_IRQ_BASE + 8, + MACE_VID_IN2_IRQ, + MACE_VID_OUT_IRQ, + MACE_ETHERNET_IRQ, + /* SUPERIO, MISC, and AUDIO are MACEISA */ + __MACE_SUPERIO, + __MACE_MISC, + __MACE_AUDIO, + MACE_PCI_BRIDGE_IRQ, -/* MACEPCI */ -#define MACEPCI_SCSI0_IRQ 9 -#define MACEPCI_SCSI1_IRQ 10 -#define MACEPCI_SLOT0_IRQ 11 -#define MACEPCI_SLOT1_IRQ 12 -#define MACEPCI_SLOT2_IRQ 13 -#define MACEPCI_SHARED0_IRQ 14 -#define MACEPCI_SHARED1_IRQ 15 -#define MACEPCI_SHARED2_IRQ 16 + /* + * MACEPCI + */ + MACEPCI_SCSI0_IRQ, + MACEPCI_SCSI1_IRQ, + MACEPCI_SLOT0_IRQ, + MACEPCI_SLOT1_IRQ, + MACEPCI_SLOT2_IRQ, + MACEPCI_SHARED0_IRQ, + MACEPCI_SHARED1_IRQ, + MACEPCI_SHARED2_IRQ, -/* CRIME */ -#define CRIME_GBE0_IRQ 17 -#define CRIME_GBE1_IRQ 18 -#define CRIME_GBE2_IRQ 19 -#define CRIME_GBE3_IRQ 20 -#define CRIME_CPUERR_IRQ 21 -#define CRIME_MEMERR_IRQ 22 -#define CRIME_RE_EMPTY_E_IRQ 23 -#define CRIME_RE_FULL_E_IRQ 24 -#define CRIME_RE_IDLE_E_IRQ 25 -#define CRIME_RE_EMPTY_L_IRQ 26 -#define CRIME_RE_FULL_L_IRQ 27 -#define CRIME_RE_IDLE_L_IRQ 28 -#define CRIME_SOFT0_IRQ 29 -#define CRIME_SOFT1_IRQ 30 -#define CRIME_SOFT2_IRQ 31 -#define CRIME_SYSCORERR_IRQ CRIME_SOFT2_IRQ -#define CRIME_VICE_IRQ 32 + /* + * CRIME + */ + CRIME_GBE0_IRQ, + CRIME_GBE1_IRQ, + CRIME_GBE2_IRQ, + CRIME_GBE3_IRQ, + CRIME_CPUERR_IRQ, + CRIME_MEMERR_IRQ, + CRIME_RE_EMPTY_E_IRQ, + CRIME_RE_FULL_E_IRQ, + CRIME_RE_IDLE_E_IRQ, + CRIME_RE_EMPTY_L_IRQ, + CRIME_RE_FULL_L_IRQ, + CRIME_RE_IDLE_L_IRQ, + CRIME_SOFT0_IRQ, + CRIME_SOFT1_IRQ, + CRIME_SOFT2_IRQ, + CRIME_SYSCORERR_IRQ = CRIME_SOFT2_IRQ, + CRIME_VICE_IRQ, -/* MACEISA */ -#define MACEISA_AUDIO_SW_IRQ 33 -#define MACEISA_AUDIO_SC_IRQ 34 -#define MACEISA_AUDIO1_DMAT_IRQ 35 -#define MACEISA_AUDIO1_OF_IRQ 36 -#define MACEISA_AUDIO2_DMAT_IRQ 37 -#define MACEISA_AUDIO2_MERR_IRQ 38 -#define MACEISA_AUDIO3_DMAT_IRQ 39 -#define MACEISA_AUDIO3_MERR_IRQ 40 -#define MACEISA_RTC_IRQ 41 -#define MACEISA_KEYB_IRQ 42 -/* MACEISA_KEYB_POLL is not an IRQ */ -#define MACEISA_MOUSE_IRQ 44 -/* MACEISA_MOUSE_POLL is not an IRQ */ -#define MACEISA_TIMER0_IRQ 46 -#define MACEISA_TIMER1_IRQ 47 -#define MACEISA_TIMER2_IRQ 48 -#define MACEISA_PARALLEL_IRQ 49 -#define MACEISA_PAR_CTXA_IRQ 50 -#define MACEISA_PAR_CTXB_IRQ 51 -#define MACEISA_PAR_MERR_IRQ 52 -#define MACEISA_SERIAL1_IRQ 53 -#define MACEISA_SERIAL1_TDMAT_IRQ 54 -#define MACEISA_SERIAL1_TDMAPR_IRQ 55 -#define MACEISA_SERIAL1_TDMAME_IRQ 56 -#define MACEISA_SERIAL1_RDMAT_IRQ 57 -#define MACEISA_SERIAL1_RDMAOR_IRQ 58 -#define MACEISA_SERIAL2_IRQ 59 -#define MACEISA_SERIAL2_TDMAT_IRQ 60 -#define MACEISA_SERIAL2_TDMAPR_IRQ 61 -#define MACEISA_SERIAL2_TDMAME_IRQ 62 -#define MACEISA_SERIAL2_RDMAT_IRQ 63 -#define MACEISA_SERIAL2_RDMAOR_IRQ 64 + /* + * MACEISA + */ + MACEISA_AUDIO_SW_IRQ, + MACEISA_AUDIO_SC_IRQ, + MACEISA_AUDIO1_DMAT_IRQ, + MACEISA_AUDIO1_OF_IRQ, + MACEISA_AUDIO2_DMAT_IRQ, + MACEISA_AUDIO2_MERR_IRQ, + MACEISA_AUDIO3_DMAT_IRQ, + MACEISA_AUDIO3_MERR_IRQ, + MACEISA_RTC_IRQ, + MACEISA_KEYB_IRQ, + /* MACEISA_KEYB_POLL is not an IRQ */ + __MACEISA_KEYB_POLL, + MACEISA_MOUSE_IRQ, + /* MACEISA_MOUSE_POLL is not an IRQ */ + __MACEISA_MOUSE_POLL, + MACEISA_TIMER0_IRQ, + MACEISA_TIMER1_IRQ, + MACEISA_TIMER2_IRQ, + MACEISA_PARALLEL_IRQ, + MACEISA_PAR_CTXA_IRQ, + MACEISA_PAR_CTXB_IRQ, + MACEISA_PAR_MERR_IRQ, + MACEISA_SERIAL1_IRQ, + MACEISA_SERIAL1_TDMAT_IRQ, + MACEISA_SERIAL1_TDMAPR_IRQ, + MACEISA_SERIAL1_TDMAME_IRQ, + MACEISA_SERIAL1_RDMAT_IRQ, + MACEISA_SERIAL1_RDMAOR_IRQ, + MACEISA_SERIAL2_IRQ, + MACEISA_SERIAL2_TDMAT_IRQ, + MACEISA_SERIAL2_TDMAPR_IRQ, + MACEISA_SERIAL2_TDMAME_IRQ, + MACEISA_SERIAL2_RDMAT_IRQ, + MACEISA_SERIAL2_RDMAOR_IRQ, -#define IP32_IRQ_MAX MACEISA_SERIAL2_RDMAOR_IRQ + IP32_IRQ_MAX = MACEISA_SERIAL2_RDMAOR_IRQ +}; #endif /* __ASM_IP32_INTS_H */ From b37bac94de9ad5eb17bd9327d3ecb6f3b719dc70 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Sun, 14 Oct 2007 14:27:18 +0100 Subject: [PATCH 02/19] [MIPS] MSP71XX: Add workarounds file. Signed-off-by: Ralf Baechle --- include/asm-mips/pmc-sierra/msp71xx/war.h | 28 +++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 include/asm-mips/pmc-sierra/msp71xx/war.h diff --git a/include/asm-mips/pmc-sierra/msp71xx/war.h b/include/asm-mips/pmc-sierra/msp71xx/war.h new file mode 100644 index 000000000000..0bf48fc1892b --- /dev/null +++ b/include/asm-mips/pmc-sierra/msp71xx/war.h @@ -0,0 +1,28 @@ +/* + * 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. + * + * Copyright (C) 2002, 2004, 2007 by Ralf Baechle + */ +#ifndef __ASM_MIPS_PMC_SIERRA_WAR_H +#define __ASM_MIPS_PMC_SIERRA_WAR_H + +#define R4600_V1_INDEX_ICACHEOP_WAR 0 +#define R4600_V1_HIT_CACHEOP_WAR 0 +#define R4600_V2_HIT_CACHEOP_WAR 0 +#define R5432_CP0_INTERRUPT_WAR 0 +#define BCM1250_M3_WAR 0 +#define SIBYTE_1956_WAR 0 +#define MIPS4K_ICACHE_REFILL_WAR 0 +#define MIPS_CACHE_SYNC_WAR 0 +#define TX49XX_ICACHE_INDEX_INV_WAR 0 +#define RM9000_CDEX_SMP_WAR 0 +#define ICACHE_REFILLS_WORKAROUND_WAR 0 +#define R10000_LLSC_WAR 0 +#if defined(CONFIG_PMC_MSP7120_EVAL) || defined(CONFIG_PMC_MSP7120_GW) || \ + defined(CONFIG_PMC_MSP7120_FPGA) +#define MIPS34K_MISSED_ITLB_WAR 1 +#endif + +#endif /* __ASM_MIPS_PMC_SIERRA_WAR_H */ From f5153ee0f5b3d14213bab1d6ccf2b44bfe9e322b Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Sun, 14 Oct 2007 22:42:58 +0100 Subject: [PATCH 03/19] [MIPS] vmlinux.lds.S: Remove duplicate comment. Signed-off-by: Ralf Baechle --- arch/mips/kernel/vmlinux.lds.S | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/mips/kernel/vmlinux.lds.S b/arch/mips/kernel/vmlinux.lds.S index 84f9a4cc6f2f..03ad46e24563 100644 --- a/arch/mips/kernel/vmlinux.lds.S +++ b/arch/mips/kernel/vmlinux.lds.S @@ -21,7 +21,6 @@ SECTIONS * >= 0xa800 0000 0030 0000 otherwise */ - /* . = 0xa800000000300000; */ /* . = 0xa800000000300000; */ . = 0xffffffff80300000; #endif From 603bb99c8bca114fcd586271b19fa9fe65877b62 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Sun, 14 Oct 2007 22:49:01 +0100 Subject: [PATCH 04/19] [MIPS] vmlinux.lds.S: Fix handling of .notes in final link. Signed-off-by: Ralf Baechle --- arch/mips/kernel/vmlinux.lds.S | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/arch/mips/kernel/vmlinux.lds.S b/arch/mips/kernel/vmlinux.lds.S index 03ad46e24563..33581387d662 100644 --- a/arch/mips/kernel/vmlinux.lds.S +++ b/arch/mips/kernel/vmlinux.lds.S @@ -5,6 +5,10 @@ #define mips mips OUTPUT_ARCH(mips) ENTRY(kernel_entry) +PHDRS { + text PT_LOAD FLAGS(7); /* RWX */ + note PT_NOTE FLAGS(4); /* R__ */ +} jiffies = JIFFIES; SECTIONS @@ -33,7 +37,7 @@ SECTIONS LOCK_TEXT *(.fixup) *(.gnu.warning) - } =0 + } :text = 0 _etext = .; /* End of text section */ /* Exception table */ @@ -50,6 +54,10 @@ SECTIONS *(__dbe_table) __stop___dbe_table = .; } + + NOTES :text :note + .dummy : { *(.dummy) } :text + RODATA /* writeable */ @@ -200,7 +208,4 @@ SECTIONS *(.gptab.bss) *(.gptab.sbss) } - .note : { - *(.note) - } } From f70fd1b53c163442ba7c5d7a9279f23211a5ac6d Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Sun, 14 Oct 2007 22:50:05 +0100 Subject: [PATCH 05/19] [MIPS] vmlinux.lds.S: Handle KPROBES_TEXT. Signed-off-by: Ralf Baechle --- arch/mips/kernel/vmlinux.lds.S | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/mips/kernel/vmlinux.lds.S b/arch/mips/kernel/vmlinux.lds.S index 33581387d662..2781cff1485e 100644 --- a/arch/mips/kernel/vmlinux.lds.S +++ b/arch/mips/kernel/vmlinux.lds.S @@ -35,6 +35,7 @@ SECTIONS TEXT_TEXT SCHED_TEXT LOCK_TEXT + KPROBES_TEXT *(.fixup) *(.gnu.warning) } :text = 0 From 754d0f239ddb35682aa322b57b7fa4a8efd2fb54 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Sun, 14 Oct 2007 23:04:27 +0100 Subject: [PATCH 06/19] [MIPS] IP22: Complain if requesting the front panel irq failed. This fixes the warning: CC arch/mips/sgi-ip22/ip22-reset.o arch/mips/sgi-ip22/ip22-reset.c: In function 'reboot_setup': arch/mips/sgi-ip22/ip22-reset.c:239: warning: ignoring return value of 'request_irq', declared with attribute warn_unused_result Signed-off-by: Ralf Baechle --- arch/mips/sgi-ip22/ip22-reset.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/arch/mips/sgi-ip22/ip22-reset.c b/arch/mips/sgi-ip22/ip22-reset.c index 63afd7e44428..a435b31cf031 100644 --- a/arch/mips/sgi-ip22/ip22-reset.c +++ b/arch/mips/sgi-ip22/ip22-reset.c @@ -232,11 +232,18 @@ static struct notifier_block panic_block = { static int __init reboot_setup(void) { + int res; + _machine_restart = sgi_machine_restart; _machine_halt = sgi_machine_halt; pm_power_off = sgi_machine_power_off; - request_irq(SGI_PANEL_IRQ, panel_int, 0, "Front Panel", NULL); + res = request_irq(SGI_PANEL_IRQ, panel_int, 0, "Front Panel", NULL); + if (res) { + printk(KERN_ERR "Allocation of front panel IRQ failed\n"); + return res; + } + init_timer(&blink_timer); blink_timer.function = blink_timeout; atomic_notifier_chain_register(&panic_notifier_list, &panic_block); From eae23f2c2ac1e44f84a5f932eaad6a0dacd179d5 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Sun, 14 Oct 2007 23:27:21 +0100 Subject: [PATCH 07/19] [MIPS] IP22: Fix warning. CC arch/mips/sgi-ip22/ip22-berr.o arch/mips/sgi-ip22/ip22-berr.c: In function 'ip22_be_interrupt': arch/mips/sgi-ip22/ip22-berr.c:100: warning: passing argument 2 of 'die_if_kernel' discards qualifiers from pointer target type Signed-off-by: Ralf Baechle --- arch/mips/kernel/traps.c | 21 +++++++++++++++------ include/asm-mips/ptrace.h | 4 ++-- 2 files changed, 17 insertions(+), 8 deletions(-) diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c index 632bce1bf420..9c0c478d71ac 100644 --- a/arch/mips/kernel/traps.c +++ b/arch/mips/kernel/traps.c @@ -104,7 +104,7 @@ static int __init set_raw_show_trace(char *str) __setup("raw_show_trace", set_raw_show_trace); #endif -static void show_backtrace(struct task_struct *task, struct pt_regs *regs) +static void show_backtrace(struct task_struct *task, const struct pt_regs *regs) { unsigned long sp = regs->regs[29]; unsigned long ra = regs->regs[31]; @@ -126,7 +126,8 @@ static void show_backtrace(struct task_struct *task, struct pt_regs *regs) * This routine abuses get_user()/put_user() to reference pointers * with at least a bit of error checking ... */ -static void show_stacktrace(struct task_struct *task, struct pt_regs *regs) +static void show_stacktrace(struct task_struct *task, + const struct pt_regs *regs) { const int field = 2 * sizeof(unsigned long); long stackdata; @@ -203,7 +204,7 @@ static void show_code(unsigned int __user *pc) } } -void show_regs(struct pt_regs *regs) +static void __show_regs(const struct pt_regs *regs) { const int field = 2 * sizeof(unsigned long); unsigned int cause = regs->cp0_cause; @@ -299,9 +300,17 @@ void show_regs(struct pt_regs *regs) cpu_name_string()); } -void show_registers(struct pt_regs *regs) +/* + * FIXME: really the generic show_regs should take a const pointer argument. + */ +void show_regs(struct pt_regs *regs) { - show_regs(regs); + __show_regs((struct pt_regs *)regs); +} + +void show_registers(const struct pt_regs *regs) +{ + __show_regs(regs); print_modules(); printk("Process %s (pid: %d, threadinfo=%p, task=%p)\n", current->comm, current->pid, current_thread_info(), current); @@ -312,7 +321,7 @@ void show_registers(struct pt_regs *regs) static DEFINE_SPINLOCK(die_lock); -void __noreturn die(const char * str, struct pt_regs * regs) +void __noreturn die(const char * str, const struct pt_regs * regs) { static int die_counter; #ifdef CONFIG_MIPS_MT_SMTC diff --git a/include/asm-mips/ptrace.h b/include/asm-mips/ptrace.h index 85b44366343a..786f7e3c99bc 100644 --- a/include/asm-mips/ptrace.h +++ b/include/asm-mips/ptrace.h @@ -86,9 +86,9 @@ struct pt_regs { extern asmlinkage void do_syscall_trace(struct pt_regs *regs, int entryexit); -extern NORET_TYPE void die(const char *, struct pt_regs *) ATTRIB_NORET; +extern NORET_TYPE void die(const char *, const struct pt_regs *) ATTRIB_NORET; -static inline void die_if_kernel(const char *str, struct pt_regs *regs) +static inline void die_if_kernel(const char *str, const struct pt_regs *regs) { if (unlikely(!user_mode(regs))) die(str, regs); From 1c5dc034019d2a2c29f0c96444e02453bb495741 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Sun, 14 Oct 2007 23:27:58 +0100 Subject: [PATCH 08/19] [MIPS] IP22: Enable -Werror. Signed-off-by: Ralf Baechle --- arch/mips/sgi-ip22/Makefile | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/mips/sgi-ip22/Makefile b/arch/mips/sgi-ip22/Makefile index 1fb3e353e212..e3acb51b70b5 100644 --- a/arch/mips/sgi-ip22/Makefile +++ b/arch/mips/sgi-ip22/Makefile @@ -7,3 +7,5 @@ obj-y += ip22-mc.o ip22-hpc.o ip22-int.o ip22-berr.o \ ip22-time.o ip22-nvram.o ip22-platform.o ip22-reset.o ip22-setup.o obj-$(CONFIG_EISA) += ip22-eisa.o + +EXTRA_CFLAGS += -Werror From 951e4714295b50a8fbc2d928451c44ac56c2b575 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Sun, 14 Oct 2007 23:42:01 +0100 Subject: [PATCH 09/19] [MIPS] Lasat: Add #ifndef ... #endif include warpper to lasatint.h. Signed-off-by: Ralf Baechle --- include/asm-mips/lasat/lasatint.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/include/asm-mips/lasat/lasatint.h b/include/asm-mips/lasat/lasatint.h index 065474feeccc..1d4a52e12530 100644 --- a/include/asm-mips/lasat/lasatint.h +++ b/include/asm-mips/lasat/lasatint.h @@ -1,3 +1,6 @@ +#ifndef __ASM_LASAT_LASATINT_H +#define __ASM_LASAT_LASATINT_H + #define LASATINT_END 16 /* lasat 100 */ @@ -10,3 +13,4 @@ #define LASAT_INT_MASK_REG_200 (KSEG1ADDR(0x1104003c)) #define LASATINT_MASK_SHIFT_200 16 +#endif /* __ASM_LASAT_LASATINT_H */ From a5ccfe5c1a48bff1e47788d470ee50974f7dd33d Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Sun, 14 Oct 2007 23:49:33 +0100 Subject: [PATCH 10/19] [MIPS] Lasat: Fix build by conversion to irq_cpu.c. Signed-off-by: Ralf Baechle --- arch/mips/Kconfig | 1 + arch/mips/lasat/interrupt.c | 8 +++++--- arch/mips/pci/pci-lasat.c | 19 ++++++++++--------- include/asm-mips/lasat/lasatint.h | 5 ++++- 4 files changed, 20 insertions(+), 13 deletions(-) diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index f921235239f9..235d4514e0a9 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -133,6 +133,7 @@ config LASAT select DMA_NONCOHERENT select SYS_HAS_EARLY_PRINTK select HW_HAS_PCI + select IRQ_CPU select PCI_GT64XXX_PCI0 select MIPS_NILE4 select R5000_CPU_SCACHE diff --git a/arch/mips/lasat/interrupt.c b/arch/mips/lasat/interrupt.c index 5f35289bfff5..ba9692be3564 100644 --- a/arch/mips/lasat/interrupt.c +++ b/arch/mips/lasat/interrupt.c @@ -26,6 +26,7 @@ #include #include +#include #include #include #include @@ -88,7 +89,7 @@ asmlinkage void plat_irq_dispatch(void) int irq; if (cause & CAUSEF_IP7) { /* R4000 count / compare IRQ */ - ll_timer_interrupt(7); + do_IRQ(7); return; } @@ -96,7 +97,7 @@ asmlinkage void plat_irq_dispatch(void) /* if int_status == 0, then the interrupt has already been cleared */ if (int_status) { - irq = ls1bit32(int_status); + irq = LASATINT_BASE + ls1bit32(int_status); do_IRQ(irq); } @@ -125,6 +126,7 @@ void __init arch_init_irq(void) panic("arch_init_irq: mips_machtype incorrect"); } - for (i = 0; i <= LASATINT_END; i++) + mips_cpu_irq_init(); + for (i = LASATINT_BASE; i <= LASATINT_END; i++) set_irq_chip_and_handler(i, &lasat_irq_type, handle_level_irq); } diff --git a/arch/mips/pci/pci-lasat.c b/arch/mips/pci/pci-lasat.c index 5abd5c7119be..174f314933b5 100644 --- a/arch/mips/pci/pci-lasat.c +++ b/arch/mips/pci/pci-lasat.c @@ -10,6 +10,7 @@ #include #include #include +#include extern struct pci_ops nile4_pci_ops; extern struct pci_ops gt64xxx_pci0_ops; @@ -54,15 +55,15 @@ static int __init lasat_pci_setup(void) arch_initcall(lasat_pci_setup); -#define LASATINT_ETH1 0 -#define LASATINT_ETH0 1 -#define LASATINT_HDC 2 -#define LASATINT_COMP 3 -#define LASATINT_HDLC 4 -#define LASATINT_PCIA 5 -#define LASATINT_PCIB 6 -#define LASATINT_PCIC 7 -#define LASATINT_PCID 8 +#define LASATINT_ETH1 (LASATINT_BASE + 0) +#define LASATINT_ETH0 (LASATINT_BASE + 1) +#define LASATINT_HDC (LASATINT_BASE + 2) +#define LASATINT_COMP (LASATINT_BASE + 3) +#define LASATINT_HDLC (LASATINT_BASE + 4) +#define LASATINT_PCIA (LASATINT_BASE + 5) +#define LASATINT_PCIB (LASATINT_BASE + 6) +#define LASATINT_PCIC (LASATINT_BASE + 7) +#define LASATINT_PCID (LASATINT_BASE + 8) int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) { diff --git a/include/asm-mips/lasat/lasatint.h b/include/asm-mips/lasat/lasatint.h index 1d4a52e12530..581dc45685a2 100644 --- a/include/asm-mips/lasat/lasatint.h +++ b/include/asm-mips/lasat/lasatint.h @@ -1,7 +1,10 @@ #ifndef __ASM_LASAT_LASATINT_H #define __ASM_LASAT_LASATINT_H -#define LASATINT_END 16 +#include + +#define LASATINT_BASE MIPS_CPU_IRQ_BASE +#define LASATINT_END (LASATINT_BASE + 16) /* lasat 100 */ #define LASAT_INT_STATUS_REG_100 (KSEG1ADDR(0x1c880000)) From 41bd61a8e357f79dc65502b22d9d124a619491c0 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Mon, 15 Oct 2007 00:51:34 +0100 Subject: [PATCH 11/19] [MIPS] Alchemy: cleanup interrupt code. Signed-off-by: Ralf Baechle --- arch/mips/au1000/common/irq.c | 986 +++++++++++++++++----------------- 1 file changed, 479 insertions(+), 507 deletions(-) diff --git a/arch/mips/au1000/common/irq.c b/arch/mips/au1000/common/irq.c index a6640b998c6e..e86b4303994f 100644 --- a/arch/mips/au1000/common/irq.c +++ b/arch/mips/au1000/common/irq.c @@ -26,39 +26,18 @@ * with this program; if not, write to the Free Software Foundation, Inc., * 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include #include +#include +#include +#include +#include -#include -#include #include -#include #include #ifdef CONFIG_MIPS_PB1000 #include #endif -#undef DEBUG_IRQ -#ifdef DEBUG_IRQ -/* note: prints function name for you */ -#define DPRINTK(fmt, args...) printk("%s: " fmt, __FUNCTION__ , ## args) -#else -#define DPRINTK(fmt, args...) -#endif - #define EXT_INTC0_REQ0 2 /* IP 2 */ #define EXT_INTC0_REQ1 3 /* IP 3 */ #define EXT_INTC1_REQ0 4 /* IP 4 */ @@ -69,485 +48,10 @@ void (*board_init_irq)(void); static DEFINE_SPINLOCK(irq_lock); - -inline void local_enable_irq(unsigned int irq_nr) -{ - if (irq_nr > AU1000_LAST_INTC0_INT) { - au_writel(1<<(irq_nr-32), IC1_MASKSET); - au_writel(1<<(irq_nr-32), IC1_WAKESET); - } - else { - au_writel(1< AU1000_LAST_INTC0_INT) { - au_writel(1<<(irq_nr-32), IC1_MASKCLR); - au_writel(1<<(irq_nr-32), IC1_WAKECLR); - } - else { - au_writel(1< AU1000_LAST_INTC0_INT) { - au_writel(1<<(irq_nr-32), IC1_RISINGCLR); - au_writel(1<<(irq_nr-32), IC1_MASKCLR); - } - else { - au_writel(1< AU1000_LAST_INTC0_INT) { - au_writel(1<<(irq_nr-32), IC1_FALLINGCLR); - au_writel(1<<(irq_nr-32), IC1_MASKCLR); - } - else { - au_writel(1< AU1000_LAST_INTC0_INT) { - au_writel(1<<(irq_nr-32), IC1_FALLINGCLR); - au_writel(1<<(irq_nr-32), IC1_RISINGCLR); - au_writel(1<<(irq_nr-32), IC1_MASKCLR); - } - else { - au_writel(1<action = &action; - desc->status &= ~(IRQ_DISABLED | IRQ_AUTODETECT | IRQ_WAITING | IRQ_INPROGRESS); - - local_enable_irq(AU1000_TOY_MATCH2_INT); -} -#endif - -static void setup_local_irq(unsigned int irq_nr, int type, int int_req) -{ - if (irq_nr > AU1000_MAX_INTR) return; - /* Config2[n], Config1[n], Config0[n] */ - if (irq_nr > AU1000_LAST_INTC0_INT) { - switch (type) { - case INTC_INT_RISE_EDGE: /* 0:0:1 */ - au_writel(1<<(irq_nr-32), IC1_CFG2CLR); - au_writel(1<<(irq_nr-32), IC1_CFG1CLR); - au_writel(1<<(irq_nr-32), IC1_CFG0SET); - set_irq_chip(irq_nr, &rise_edge_irq_type); - break; - case INTC_INT_FALL_EDGE: /* 0:1:0 */ - au_writel(1<<(irq_nr-32), IC1_CFG2CLR); - au_writel(1<<(irq_nr-32), IC1_CFG1SET); - au_writel(1<<(irq_nr-32), IC1_CFG0CLR); - set_irq_chip(irq_nr, &fall_edge_irq_type); - break; - case INTC_INT_RISE_AND_FALL_EDGE: /* 0:1:1 */ - au_writel(1<<(irq_nr-32), IC1_CFG2CLR); - au_writel(1<<(irq_nr-32), IC1_CFG1SET); - au_writel(1<<(irq_nr-32), IC1_CFG0SET); - set_irq_chip(irq_nr, &either_edge_irq_type); - break; - case INTC_INT_HIGH_LEVEL: /* 1:0:1 */ - au_writel(1<<(irq_nr-32), IC1_CFG2SET); - au_writel(1<<(irq_nr-32), IC1_CFG1CLR); - au_writel(1<<(irq_nr-32), IC1_CFG0SET); - set_irq_chip(irq_nr, &level_irq_type); - break; - case INTC_INT_LOW_LEVEL: /* 1:1:0 */ - au_writel(1<<(irq_nr-32), IC1_CFG2SET); - au_writel(1<<(irq_nr-32), IC1_CFG1SET); - au_writel(1<<(irq_nr-32), IC1_CFG0CLR); - set_irq_chip(irq_nr, &level_irq_type); - break; - case INTC_INT_DISABLED: /* 0:0:0 */ - au_writel(1<<(irq_nr-32), IC1_CFG0CLR); - au_writel(1<<(irq_nr-32), IC1_CFG1CLR); - au_writel(1<<(irq_nr-32), IC1_CFG2CLR); - break; - default: /* disable the interrupt */ - printk("unexpected int type %d (irq %d)\n", type, irq_nr); - au_writel(1<<(irq_nr-32), IC1_CFG0CLR); - au_writel(1<<(irq_nr-32), IC1_CFG1CLR); - au_writel(1<<(irq_nr-32), IC1_CFG2CLR); - return; - } - if (int_req) /* assign to interrupt request 1 */ - au_writel(1<<(irq_nr-32), IC1_ASSIGNCLR); - else /* assign to interrupt request 0 */ - au_writel(1<<(irq_nr-32), IC1_ASSIGNSET); - au_writel(1<<(irq_nr-32), IC1_SRCSET); - au_writel(1<<(irq_nr-32), IC1_MASKCLR); - au_writel(1<<(irq_nr-32), IC1_WAKECLR); - } - else { - switch (type) { - case INTC_INT_RISE_EDGE: /* 0:0:1 */ - au_writel(1<im_irq, imp->im_type, imp->im_request); - imp++; - } - - /* Now set up the irq mapping for the board. - */ - imp = au1xxx_irq_map; - for (i=0; iim_irq, imp->im_type, imp->im_request); - imp++; - } - - set_c0_status(ALLINTS); - - /* Board specific IRQ initialization. - */ - if (board_init_irq) - (*board_init_irq)(); -} - - -/* - * Interrupts are nested. Even if an interrupt handler is registered - * as "fast", we might get another interrupt before we return from - * intcX_reqX_irqdispatch(). - */ - -static void intc0_req0_irqdispatch(void) -{ - int irq = 0; - static unsigned long intc0_req0 = 0; - - intc0_req0 |= au_readl(IC0_REQ0INT); - - if (!intc0_req0) - return; -#ifdef AU1000_USB_DEV_REQ_INT - /* - * Because of the tight timing of SETUP token to reply - * transactions, the USB devices-side packet complete - * interrupt needs the highest priority. - */ - if ((intc0_req0 & (1< AU1000_LAST_INTC0_INT) { + au_writel(1 << (irq_nr - 32), IC1_MASKSET); + au_writel(1 << (irq_nr - 32), IC1_WAKESET); + } else { + au_writel(1 << irq_nr, IC0_MASKSET); + au_writel(1 << irq_nr, IC0_WAKESET); + } + au_sync(); +} + + +inline void local_disable_irq(unsigned int irq_nr) +{ + if (irq_nr > AU1000_LAST_INTC0_INT) { + au_writel(1 << (irq_nr - 32), IC1_MASKCLR); + au_writel(1 << (irq_nr - 32), IC1_WAKECLR); + } else { + au_writel(1 << irq_nr, IC0_MASKCLR); + au_writel(1 << irq_nr, IC0_WAKECLR); + } + au_sync(); +} + + +static inline void mask_and_ack_rise_edge_irq(unsigned int irq_nr) +{ + if (irq_nr > AU1000_LAST_INTC0_INT) { + au_writel(1 << (irq_nr - 32), IC1_RISINGCLR); + au_writel(1 << (irq_nr - 32), IC1_MASKCLR); + } else { + au_writel(1 << irq_nr, IC0_RISINGCLR); + au_writel(1 << irq_nr, IC0_MASKCLR); + } + au_sync(); +} + + +static inline void mask_and_ack_fall_edge_irq(unsigned int irq_nr) +{ + if (irq_nr > AU1000_LAST_INTC0_INT) { + au_writel(1 << (irq_nr - 32), IC1_FALLINGCLR); + au_writel(1 << (irq_nr - 32), IC1_MASKCLR); + } else { + au_writel(1 << irq_nr, IC0_FALLINGCLR); + au_writel(1 << irq_nr, IC0_MASKCLR); + } + au_sync(); +} + + +static inline void mask_and_ack_either_edge_irq(unsigned int irq_nr) +{ + /* This may assume that we don't get interrupts from + * both edges at once, or if we do, that we don't care. + */ + if (irq_nr > AU1000_LAST_INTC0_INT) { + au_writel(1 << (irq_nr - 32), IC1_FALLINGCLR); + au_writel(1 << (irq_nr - 32), IC1_RISINGCLR); + au_writel(1 << (irq_nr - 32), IC1_MASKCLR); + } else { + au_writel(1 << irq_nr, IC0_FALLINGCLR); + au_writel(1 << irq_nr, IC0_RISINGCLR); + au_writel(1 << irq_nr, IC0_MASKCLR); + } + au_sync(); +} + + +static inline void mask_and_ack_level_irq(unsigned int irq_nr) +{ + + local_disable_irq(irq_nr); + au_sync(); +#if defined(CONFIG_MIPS_PB1000) + if (irq_nr == AU1000_GPIO_15) { + au_writel(0x8000, PB1000_MDR); /* ack int */ + au_sync(); + } +#endif + return; +} + + +static void end_irq(unsigned int irq_nr) +{ + if (!(irq_desc[irq_nr].status & (IRQ_DISABLED | IRQ_INPROGRESS))) + local_enable_irq(irq_nr); + +#if defined(CONFIG_MIPS_PB1000) + if (irq_nr == AU1000_GPIO_15) { + au_writel(0x4000, PB1000_MDR); /* enable int */ + au_sync(); + } +#endif +} + +unsigned long save_local_and_disable(int controller) +{ + int i; + unsigned long flags, mask; + + spin_lock_irqsave(&irq_lock, flags); + if (controller) { + mask = au_readl(IC1_MASKSET); + for (i = 32; i < 64; i++) + local_disable_irq(i); + } else { + mask = au_readl(IC0_MASKSET); + for (i = 0; i < 32; i++) + local_disable_irq(i); + } + spin_unlock_irqrestore(&irq_lock, flags); + + return mask; +} + +void restore_local_and_enable(int controller, unsigned long mask) +{ + int i; + unsigned long flags, new_mask; + + spin_lock_irqsave(&irq_lock, flags); + for (i = 0; i < 32; i++) { + if (mask & (1 << i)) { + if (controller) + local_enable_irq(i + 32); + else + local_enable_irq(i); + } + } + if (controller) + new_mask = au_readl(IC1_MASKSET); + else + new_mask = au_readl(IC0_MASKSET); + + spin_unlock_irqrestore(&irq_lock, flags); +} + + +static struct irq_chip rise_edge_irq_type = { + .name = "Au1000 Rise Edge", + .ack = mask_and_ack_rise_edge_irq, + .mask = local_disable_irq, + .mask_ack = mask_and_ack_rise_edge_irq, + .unmask = local_enable_irq, + .end = end_irq, +}; + +static struct irq_chip fall_edge_irq_type = { + .name = "Au1000 Fall Edge", + .ack = mask_and_ack_fall_edge_irq, + .mask = local_disable_irq, + .mask_ack = mask_and_ack_fall_edge_irq, + .unmask = local_enable_irq, + .end = end_irq, +}; + +static struct irq_chip either_edge_irq_type = { + .name = "Au1000 Rise or Fall Edge", + .ack = mask_and_ack_either_edge_irq, + .mask = local_disable_irq, + .mask_ack = mask_and_ack_either_edge_irq, + .unmask = local_enable_irq, + .end = end_irq, +}; + +static struct irq_chip level_irq_type = { + .name = "Au1000 Level", + .ack = mask_and_ack_level_irq, + .mask = local_disable_irq, + .mask_ack = mask_and_ack_level_irq, + .unmask = local_enable_irq, + .end = end_irq, +}; + +#ifdef CONFIG_PM +void startup_match20_interrupt(irq_handler_t handler) +{ + struct irq_desc *desc = &irq_desc[AU1000_TOY_MATCH2_INT]; + + static struct irqaction action; + memset(&action, 0, sizeof(struct irqaction)); + + /* + * This is a big problem.... since we didn't use request_irq + * when kernel/irq.c calls probe_irq_xxx this interrupt will + * be probed for usage. This will end up disabling the device :( + * Give it a bogus "action" pointer -- this will keep it from + * getting auto-probed! + * + * By setting the status to match that of request_irq() we + * can avoid it. --cgray + */ + action.dev_id = handler; + action.flags = IRQF_DISABLED; + cpus_clear(action.mask); + action.name = "Au1xxx TOY"; + action.handler = handler; + action.next = NULL; + + desc->action = &action; + desc->status &= ~(IRQ_DISABLED | IRQ_AUTODETECT | IRQ_WAITING | IRQ_INPROGRESS); + + local_enable_irq(AU1000_TOY_MATCH2_INT); +} +#endif + +static void setup_local_irq(unsigned int irq_nr, int type, int int_req) +{ + if (irq_nr > AU1000_MAX_INTR) return; + /* Config2[n], Config1[n], Config0[n] */ + if (irq_nr > AU1000_LAST_INTC0_INT) { + switch (type) { + case INTC_INT_RISE_EDGE: /* 0:0:1 */ + au_writel(1 << (irq_nr - 32), IC1_CFG2CLR); + au_writel(1 << (irq_nr - 32), IC1_CFG1CLR); + au_writel(1 << (irq_nr - 32), IC1_CFG0SET); + set_irq_chip(irq_nr, &rise_edge_irq_type); + break; + case INTC_INT_FALL_EDGE: /* 0:1:0 */ + au_writel(1 << (irq_nr - 32), IC1_CFG2CLR); + au_writel(1 << (irq_nr - 32), IC1_CFG1SET); + au_writel(1 << (irq_nr - 32), IC1_CFG0CLR); + set_irq_chip(irq_nr, &fall_edge_irq_type); + break; + case INTC_INT_RISE_AND_FALL_EDGE: /* 0:1:1 */ + au_writel(1 << (irq_nr - 32), IC1_CFG2CLR); + au_writel(1 << (irq_nr - 32), IC1_CFG1SET); + au_writel(1 << (irq_nr - 32), IC1_CFG0SET); + set_irq_chip(irq_nr, &either_edge_irq_type); + break; + case INTC_INT_HIGH_LEVEL: /* 1:0:1 */ + au_writel(1 << (irq_nr - 32), IC1_CFG2SET); + au_writel(1 << (irq_nr - 32), IC1_CFG1CLR); + au_writel(1 << (irq_nr - 32), IC1_CFG0SET); + set_irq_chip(irq_nr, &level_irq_type); + break; + case INTC_INT_LOW_LEVEL: /* 1:1:0 */ + au_writel(1 << (irq_nr - 32), IC1_CFG2SET); + au_writel(1 << (irq_nr - 32), IC1_CFG1SET); + au_writel(1 << (irq_nr - 32), IC1_CFG0CLR); + set_irq_chip(irq_nr, &level_irq_type); + break; + case INTC_INT_DISABLED: /* 0:0:0 */ + au_writel(1 << (irq_nr - 32), IC1_CFG0CLR); + au_writel(1 << (irq_nr - 32), IC1_CFG1CLR); + au_writel(1 << (irq_nr - 32), IC1_CFG2CLR); + break; + default: /* disable the interrupt */ + printk(KERN_WARNING "unexpected int type %d (irq %d)\n", + type, irq_nr); + au_writel(1 << (irq_nr - 32), IC1_CFG0CLR); + au_writel(1 << (irq_nr - 32), IC1_CFG1CLR); + au_writel(1 << (irq_nr - 32), IC1_CFG2CLR); + return; + } + if (int_req) /* assign to interrupt request 1 */ + au_writel(1 << (irq_nr - 32), IC1_ASSIGNCLR); + else /* assign to interrupt request 0 */ + au_writel(1 << (irq_nr - 32), IC1_ASSIGNSET); + au_writel(1 << (irq_nr - 32), IC1_SRCSET); + au_writel(1 << (irq_nr - 32), IC1_MASKCLR); + au_writel(1 << (irq_nr - 32), IC1_WAKECLR); + } else { + switch (type) { + case INTC_INT_RISE_EDGE: /* 0:0:1 */ + au_writel(1 << irq_nr, IC0_CFG2CLR); + au_writel(1 << irq_nr, IC0_CFG1CLR); + au_writel(1 << irq_nr, IC0_CFG0SET); + set_irq_chip(irq_nr, &rise_edge_irq_type); + break; + case INTC_INT_FALL_EDGE: /* 0:1:0 */ + au_writel(1 << irq_nr, IC0_CFG2CLR); + au_writel(1 << irq_nr, IC0_CFG1SET); + au_writel(1 << irq_nr, IC0_CFG0CLR); + set_irq_chip(irq_nr, &fall_edge_irq_type); + break; + case INTC_INT_RISE_AND_FALL_EDGE: /* 0:1:1 */ + au_writel(1 << irq_nr, IC0_CFG2CLR); + au_writel(1 << irq_nr, IC0_CFG1SET); + au_writel(1 << irq_nr, IC0_CFG0SET); + set_irq_chip(irq_nr, &either_edge_irq_type); + break; + case INTC_INT_HIGH_LEVEL: /* 1:0:1 */ + au_writel(1 << irq_nr, IC0_CFG2SET); + au_writel(1 << irq_nr, IC0_CFG1CLR); + au_writel(1 << irq_nr, IC0_CFG0SET); + set_irq_chip(irq_nr, &level_irq_type); + break; + case INTC_INT_LOW_LEVEL: /* 1:1:0 */ + au_writel(1 << irq_nr, IC0_CFG2SET); + au_writel(1 << irq_nr, IC0_CFG1SET); + au_writel(1 << irq_nr, IC0_CFG0CLR); + set_irq_chip(irq_nr, &level_irq_type); + break; + case INTC_INT_DISABLED: /* 0:0:0 */ + au_writel(1 << irq_nr, IC0_CFG0CLR); + au_writel(1 << irq_nr, IC0_CFG1CLR); + au_writel(1 << irq_nr, IC0_CFG2CLR); + break; + default: /* disable the interrupt */ + printk(KERN_WARNING "unexpected int type %d (irq %d)\n", + type, irq_nr); + au_writel(1 << irq_nr, IC0_CFG0CLR); + au_writel(1 << irq_nr, IC0_CFG1CLR); + au_writel(1 << irq_nr, IC0_CFG2CLR); + return; + } + if (int_req) /* assign to interrupt request 1 */ + au_writel(1 << irq_nr, IC0_ASSIGNCLR); + else /* assign to interrupt request 0 */ + au_writel(1 << irq_nr, IC0_ASSIGNSET); + au_writel(1 << irq_nr, IC0_SRCSET); + au_writel(1 << irq_nr, IC0_MASKCLR); + au_writel(1 << irq_nr, IC0_WAKECLR); + } + au_sync(); +} + +/* + * Interrupts are nested. Even if an interrupt handler is registered + * as "fast", we might get another interrupt before we return from + * intcX_reqX_irqdispatch(). + */ + +static void intc0_req0_irqdispatch(void) +{ + int irq = 0; + static unsigned long intc0_req0; + + intc0_req0 |= au_readl(IC0_REQ0INT); + + if (!intc0_req0) + return; + +#ifdef AU1000_USB_DEV_REQ_INT + /* + * Because of the tight timing of SETUP token to reply + * transactions, the USB devices-side packet complete + * interrupt needs the highest priority. + */ + if ((intc0_req0 & (1 << AU1000_USB_DEV_REQ_INT))) { + intc0_req0 &= ~(1 << AU1000_USB_DEV_REQ_INT); + do_IRQ(AU1000_USB_DEV_REQ_INT); + return; + } +#endif + irq = au_ffs(intc0_req0) - 1; + intc0_req0 &= ~(1 << irq); + do_IRQ(irq); +} + + +static void intc0_req1_irqdispatch(void) +{ + int irq = 0; + static unsigned long intc0_req1; + + intc0_req1 |= au_readl(IC0_REQ1INT); + + if (!intc0_req1) + return; + + irq = au_ffs(intc0_req1) - 1; + intc0_req1 &= ~(1 << irq); + do_IRQ(irq); +} + + +/* + * Interrupt Controller 1: + * interrupts 32 - 63 + */ +static void intc1_req0_irqdispatch(void) +{ + int irq = 0; + static unsigned long intc1_req0; + + intc1_req0 |= au_readl(IC1_REQ0INT); + + if (!intc1_req0) + return; + + irq = au_ffs(intc1_req0) - 1; + intc1_req0 &= ~(1 << irq); + irq += 32; + do_IRQ(irq); +} + + +static void intc1_req1_irqdispatch(void) +{ + int irq = 0; + static unsigned long intc1_req1; + + intc1_req1 |= au_readl(IC1_REQ1INT); + + if (!intc1_req1) + return; + + irq = au_ffs(intc1_req1) - 1; + intc1_req1 &= ~(1 << irq); + irq += 32; + do_IRQ(irq); +} + asmlinkage void plat_irq_dispatch(void) { unsigned int pending = read_c0_status() & read_c0_cause() & ST0_IM; @@ -645,3 +557,63 @@ asmlinkage void plat_irq_dispatch(void) else spurious_interrupt(); } + +void __init arch_init_irq(void) +{ + int i; + unsigned long cp0_status; + au1xxx_irq_map_t *imp; + extern au1xxx_irq_map_t au1xxx_irq_map[]; + extern au1xxx_irq_map_t au1xxx_ic0_map[]; + extern int au1xxx_nr_irqs; + extern int au1xxx_ic0_nr_irqs; + + cp0_status = read_c0_status(); + + /* Initialize interrupt controllers to a safe state. + */ + au_writel(0xffffffff, IC0_CFG0CLR); + au_writel(0xffffffff, IC0_CFG1CLR); + au_writel(0xffffffff, IC0_CFG2CLR); + au_writel(0xffffffff, IC0_MASKCLR); + au_writel(0xffffffff, IC0_ASSIGNSET); + au_writel(0xffffffff, IC0_WAKECLR); + au_writel(0xffffffff, IC0_SRCSET); + au_writel(0xffffffff, IC0_FALLINGCLR); + au_writel(0xffffffff, IC0_RISINGCLR); + au_writel(0x00000000, IC0_TESTBIT); + + au_writel(0xffffffff, IC1_CFG0CLR); + au_writel(0xffffffff, IC1_CFG1CLR); + au_writel(0xffffffff, IC1_CFG2CLR); + au_writel(0xffffffff, IC1_MASKCLR); + au_writel(0xffffffff, IC1_ASSIGNSET); + au_writel(0xffffffff, IC1_WAKECLR); + au_writel(0xffffffff, IC1_SRCSET); + au_writel(0xffffffff, IC1_FALLINGCLR); + au_writel(0xffffffff, IC1_RISINGCLR); + au_writel(0x00000000, IC1_TESTBIT); + + /* Initialize IC0, which is fixed per processor. + */ + imp = au1xxx_ic0_map; + for (i = 0; i < au1xxx_ic0_nr_irqs; i++) { + setup_local_irq(imp->im_irq, imp->im_type, imp->im_request); + imp++; + } + + /* Now set up the irq mapping for the board. + */ + imp = au1xxx_irq_map; + for (i = 0; i < au1xxx_nr_irqs; i++) { + setup_local_irq(imp->im_irq, imp->im_type, imp->im_request); + imp++; + } + + set_c0_status(ALLINTS); + + /* Board specific IRQ initialization. + */ + if (board_init_irq) + (*board_init_irq)(); +} From 56f621c7f6f735311eed3f36858b402013023c18 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Mon, 15 Oct 2007 01:00:06 +0100 Subject: [PATCH 12/19] [MIPS] Alchemy: Get rid of au_ffs(). It was plain a bad idea ... Signed-off-by: Ralf Baechle --- arch/mips/au1000/common/dbdma.c | 2 +- arch/mips/au1000/common/irq.c | 8 ++++---- arch/mips/au1000/pb1200/irqmap.c | 2 +- include/asm-mips/mach-au1x00/au1000.h | 10 ---------- 4 files changed, 6 insertions(+), 16 deletions(-) diff --git a/arch/mips/au1000/common/dbdma.c b/arch/mips/au1000/common/dbdma.c index 461cf0139737..9d6ad43fded6 100644 --- a/arch/mips/au1000/common/dbdma.c +++ b/arch/mips/au1000/common/dbdma.c @@ -859,7 +859,7 @@ dbdma_interrupt(int irq, void *dev_id) intstat = dbdma_gptr->ddma_intstat; au_sync(); - chan_index = au_ffs(intstat) - 1; + chan_index = ffs(intstat); ctp = chan_tab_ptr[chan_index]; cp = ctp->chan_ptr; diff --git a/arch/mips/au1000/common/irq.c b/arch/mips/au1000/common/irq.c index e86b4303994f..b0ae1ab0ad9e 100644 --- a/arch/mips/au1000/common/irq.c +++ b/arch/mips/au1000/common/irq.c @@ -481,7 +481,7 @@ static void intc0_req0_irqdispatch(void) return; } #endif - irq = au_ffs(intc0_req0) - 1; + irq = ffs(intc0_req0); intc0_req0 &= ~(1 << irq); do_IRQ(irq); } @@ -497,7 +497,7 @@ static void intc0_req1_irqdispatch(void) if (!intc0_req1) return; - irq = au_ffs(intc0_req1) - 1; + irq = ffs(intc0_req1); intc0_req1 &= ~(1 << irq); do_IRQ(irq); } @@ -517,7 +517,7 @@ static void intc1_req0_irqdispatch(void) if (!intc1_req0) return; - irq = au_ffs(intc1_req0) - 1; + irq = ffs(intc1_req0); intc1_req0 &= ~(1 << irq); irq += 32; do_IRQ(irq); @@ -534,7 +534,7 @@ static void intc1_req1_irqdispatch(void) if (!intc1_req1) return; - irq = au_ffs(intc1_req1) - 1; + irq = ffs(intc1_req1); intc1_req1 &= ~(1 << irq); irq += 32; do_IRQ(irq); diff --git a/arch/mips/au1000/pb1200/irqmap.c b/arch/mips/au1000/pb1200/irqmap.c index 7c708db04a88..aa85eedf7c0d 100644 --- a/arch/mips/au1000/pb1200/irqmap.c +++ b/arch/mips/au1000/pb1200/irqmap.c @@ -74,7 +74,7 @@ irqreturn_t pb1200_cascade_handler( int irq, void *dev_id) bcsr->int_status = bisr; for( ; bisr; bisr &= (bisr-1) ) { - extirq_nr = (PB1200_INT_BEGIN-1) + au_ffs(bisr); + extirq_nr = PB1200_INT_BEGIN + au_ffs(bisr); /* Ack and dispatch IRQ */ do_IRQ(extirq_nr); } diff --git a/include/asm-mips/mach-au1x00/au1000.h b/include/asm-mips/mach-au1x00/au1000.h index 10f613f23c33..6cd6e8b8cd20 100644 --- a/include/asm-mips/mach-au1x00/au1000.h +++ b/include/asm-mips/mach-au1x00/au1000.h @@ -98,16 +98,6 @@ static __inline__ int au_ffz(unsigned int x) return __ilog2(x & -x); } -/* - * ffs: find first bit set. This is defined the same way as - * the libc and compiler builtin ffs routines, therefore - * differs in spirit from the above ffz (man ffs). - */ -static __inline__ int au_ffs(int x) -{ - return __ilog2(x & -x) + 1; -} - /* arch/mips/au1000/common/clocks.c */ extern void set_au1x00_speed(unsigned int new_freq); extern unsigned int get_au1x00_speed(void); From d2126e230d3db20ee7f3ef2dc70bb241aafd4f80 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Mon, 15 Oct 2007 01:02:43 +0100 Subject: [PATCH 13/19] [MIPS] Alchemy: Get rid of au_ffz(). There were no users - and why have a private version anyway. Signed-off-by: Ralf Baechle --- include/asm-mips/mach-au1x00/au1000.h | 7 ------- 1 file changed, 7 deletions(-) diff --git a/include/asm-mips/mach-au1x00/au1000.h b/include/asm-mips/mach-au1x00/au1000.h index 6cd6e8b8cd20..630138f6f918 100644 --- a/include/asm-mips/mach-au1x00/au1000.h +++ b/include/asm-mips/mach-au1x00/au1000.h @@ -91,13 +91,6 @@ static inline u32 au_readl(unsigned long reg) } -static __inline__ int au_ffz(unsigned int x) -{ - if ((x = ~x) == 0) - return 32; - return __ilog2(x & -x); -} - /* arch/mips/au1000/common/clocks.c */ extern void set_au1x00_speed(unsigned int new_freq); extern unsigned int get_au1x00_speed(void); From 0e6799ed076fb11b3ee0a8bc19018f3410e357b2 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Mon, 15 Oct 2007 01:07:39 +0100 Subject: [PATCH 14/19] [MIPS] Alchemy: Get rid of au1xxx_irq_map_t. Signed-off-by: Ralf Baechle --- arch/mips/au1000/common/au1xxx_irqmap.c | 2 +- arch/mips/au1000/common/irq.c | 6 +++--- arch/mips/au1000/db1x00/irqmap.c | 2 +- arch/mips/au1000/mtx-1/irqmap.c | 2 +- arch/mips/au1000/pb1000/irqmap.c | 2 +- arch/mips/au1000/pb1100/irqmap.c | 2 +- arch/mips/au1000/pb1200/irqmap.c | 2 +- arch/mips/au1000/pb1500/irqmap.c | 2 +- arch/mips/au1000/pb1550/irqmap.c | 2 +- arch/mips/au1000/xxs1500/irqmap.c | 2 +- include/asm-mips/mach-au1x00/au1000.h | 6 +++--- 11 files changed, 15 insertions(+), 15 deletions(-) diff --git a/arch/mips/au1000/common/au1xxx_irqmap.c b/arch/mips/au1000/common/au1xxx_irqmap.c index 7acfe9bf5fc3..98a4e34b0248 100644 --- a/arch/mips/au1000/common/au1xxx_irqmap.c +++ b/arch/mips/au1000/common/au1xxx_irqmap.c @@ -54,7 +54,7 @@ * Careful if you change match 2 request! * The interrupt handler is called directly from the low level dispatch code. */ -au1xxx_irq_map_t __initdata au1xxx_ic0_map[] = { +struct au1xxx_irqmap __initdata au1xxx_ic0_map[] = { #if defined(CONFIG_SOC_AU1000) { AU1000_UART0_INT, INTC_INT_HIGH_LEVEL, 0}, diff --git a/arch/mips/au1000/common/irq.c b/arch/mips/au1000/common/irq.c index b0ae1ab0ad9e..c00f308fd505 100644 --- a/arch/mips/au1000/common/irq.c +++ b/arch/mips/au1000/common/irq.c @@ -562,9 +562,9 @@ void __init arch_init_irq(void) { int i; unsigned long cp0_status; - au1xxx_irq_map_t *imp; - extern au1xxx_irq_map_t au1xxx_irq_map[]; - extern au1xxx_irq_map_t au1xxx_ic0_map[]; + struct au1xxx_irqmap *imp; + extern struct au1xxx_irqmap au1xxx_irq_map[]; + extern struct au1xxx_irqmap au1xxx_ic0_map[]; extern int au1xxx_nr_irqs; extern int au1xxx_ic0_nr_irqs; diff --git a/arch/mips/au1000/db1x00/irqmap.c b/arch/mips/au1000/db1x00/irqmap.c index 3e5729145c2b..09cea03411b0 100644 --- a/arch/mips/au1000/db1x00/irqmap.c +++ b/arch/mips/au1000/db1x00/irqmap.c @@ -79,7 +79,7 @@ char irq_tab_alchemy[][5] __initdata = { #endif -au1xxx_irq_map_t __initdata au1xxx_irq_map[] = { +struct au1xxx_irqmap __initdata au1xxx_irq_map[] = { #ifndef CONFIG_MIPS_MIRAGE #ifdef CONFIG_MIPS_DB1550 diff --git a/arch/mips/au1000/mtx-1/irqmap.c b/arch/mips/au1000/mtx-1/irqmap.c index a4fa0f227e42..49c612aeddcf 100644 --- a/arch/mips/au1000/mtx-1/irqmap.c +++ b/arch/mips/au1000/mtx-1/irqmap.c @@ -58,7 +58,7 @@ char irq_tab_alchemy[][5] __initdata = { [7] = { -1, INTD, INTC, INTX, INTX}, /* IDSEL 07 - AdapterD-Slot1 (bottom) */ }; -au1xxx_irq_map_t __initdata au1xxx_irq_map[] = { +struct au1xxx_irqmap __initdata au1xxx_irq_map[] = { { AU1500_GPIO_204, INTC_INT_HIGH_LEVEL, 0}, { AU1500_GPIO_201, INTC_INT_LOW_LEVEL, 0 }, { AU1500_GPIO_202, INTC_INT_LOW_LEVEL, 0 }, diff --git a/arch/mips/au1000/pb1000/irqmap.c b/arch/mips/au1000/pb1000/irqmap.c index 156500ba467f..88e354508204 100644 --- a/arch/mips/au1000/pb1000/irqmap.c +++ b/arch/mips/au1000/pb1000/irqmap.c @@ -47,7 +47,7 @@ #include #include -au1xxx_irq_map_t __initdata au1xxx_irq_map[] = { +struct au1xxx_irqmap __initdata au1xxx_irq_map[] = { { AU1000_GPIO_15, INTC_INT_LOW_LEVEL, 0 }, }; diff --git a/arch/mips/au1000/pb1100/irqmap.c b/arch/mips/au1000/pb1100/irqmap.c index d986916221b7..880456bf8c11 100644 --- a/arch/mips/au1000/pb1100/irqmap.c +++ b/arch/mips/au1000/pb1100/irqmap.c @@ -47,7 +47,7 @@ #include #include -au1xxx_irq_map_t __initdata au1xxx_irq_map[] = { +struct au1xxx_irqmap __initdata au1xxx_irq_map[] = { { AU1000_GPIO_9, INTC_INT_LOW_LEVEL, 0 }, // PCMCIA Card Fully_Interted# { AU1000_GPIO_10, INTC_INT_LOW_LEVEL, 0 }, // PCMCIA Card STSCHG# { AU1000_GPIO_11, INTC_INT_LOW_LEVEL, 0 }, // PCMCIA Card IRQ# diff --git a/arch/mips/au1000/pb1200/irqmap.c b/arch/mips/au1000/pb1200/irqmap.c index aa85eedf7c0d..3bee274445f5 100644 --- a/arch/mips/au1000/pb1200/irqmap.c +++ b/arch/mips/au1000/pb1200/irqmap.c @@ -54,7 +54,7 @@ #define PB1200_INT_END DB1200_INT_END #endif -au1xxx_irq_map_t __initdata au1xxx_irq_map[] = { +struct au1xxx_irqmap __initdata au1xxx_irq_map[] = { { AU1000_GPIO_7, INTC_INT_LOW_LEVEL, 0 }, // This is exteranl interrupt cascade }; diff --git a/arch/mips/au1000/pb1500/irqmap.c b/arch/mips/au1000/pb1500/irqmap.c index 409d1612bb63..810f695e24bb 100644 --- a/arch/mips/au1000/pb1500/irqmap.c +++ b/arch/mips/au1000/pb1500/irqmap.c @@ -52,7 +52,7 @@ char irq_tab_alchemy[][5] __initdata = { [13] = { -1, INTA, INTB, INTC, INTD}, /* IDSEL 13 - PCI slot */ }; -au1xxx_irq_map_t __initdata au1xxx_irq_map[] = { +struct au1xxx_irqmap __initdata au1xxx_irq_map[] = { { AU1500_GPIO_204, INTC_INT_HIGH_LEVEL, 0}, { AU1500_GPIO_201, INTC_INT_LOW_LEVEL, 0 }, { AU1500_GPIO_202, INTC_INT_LOW_LEVEL, 0 }, diff --git a/arch/mips/au1000/pb1550/irqmap.c b/arch/mips/au1000/pb1550/irqmap.c index 24a9d186cf5a..56becab28e5d 100644 --- a/arch/mips/au1000/pb1550/irqmap.c +++ b/arch/mips/au1000/pb1550/irqmap.c @@ -52,7 +52,7 @@ char irq_tab_alchemy[][5] __initdata = { [13] = { -1, INTA, INTB, INTC, INTD}, /* IDSEL 13 - PCI slot 1 (right) */ }; -au1xxx_irq_map_t __initdata au1xxx_irq_map[] = { +struct au1xxx_irqmap __initdata au1xxx_irq_map[] = { { AU1000_GPIO_0, INTC_INT_LOW_LEVEL, 0 }, { AU1000_GPIO_1, INTC_INT_LOW_LEVEL, 0 }, }; diff --git a/arch/mips/au1000/xxs1500/irqmap.c b/arch/mips/au1000/xxs1500/irqmap.c index 3844c6429e27..389349295d70 100644 --- a/arch/mips/au1000/xxs1500/irqmap.c +++ b/arch/mips/au1000/xxs1500/irqmap.c @@ -47,7 +47,7 @@ #include #include -au1xxx_irq_map_t __initdata au1xxx_irq_map[] = { +struct au1xxx_irqmap __initdata au1xxx_irq_map[] = { { AU1500_GPIO_204, INTC_INT_HIGH_LEVEL, 0}, { AU1500_GPIO_201, INTC_INT_LOW_LEVEL, 0 }, { AU1500_GPIO_202, INTC_INT_LOW_LEVEL, 0 }, diff --git a/include/asm-mips/mach-au1x00/au1000.h b/include/asm-mips/mach-au1x00/au1000.h index 630138f6f918..b37baf8cf624 100644 --- a/include/asm-mips/mach-au1x00/au1000.h +++ b/include/asm-mips/mach-au1x00/au1000.h @@ -102,16 +102,16 @@ extern unsigned int get_au1x00_lcd_clock(void); /* * Every board describes its IRQ mapping with this table. */ -typedef struct au1xxx_irqmap { +struct au1xxx_irqmap { int im_irq; int im_type; int im_request; -} au1xxx_irq_map_t; +}; /* * init_IRQ looks for a table with this name. */ -extern au1xxx_irq_map_t au1xxx_irq_map[]; +extern struct au1xxx_irqmap au1xxx_irq_map[]; #endif /* !defined (_LANGUAGE_ASSEMBLY) */ From 2f7055c5932ecc02159be375ebda1eee64665d17 Mon Sep 17 00:00:00 2001 From: Thiemo Seufer Date: Sun, 14 Oct 2007 17:11:06 +0100 Subject: [PATCH 15/19] [MIPS] MIPSsim: Fix booting from NFS root MIPSsim probably doesn't have any sort of environment, but writing a zero in it kills even the compiled in command line. This prevents booting via NFS root. Signed-Off-By: Thiemo Seufer Signed-off-by: Ralf Baechle --- arch/mips/mipssim/sim_cmdline.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/arch/mips/mipssim/sim_cmdline.c b/arch/mips/mipssim/sim_cmdline.c index c63021a5dc6c..74240e1ce5a5 100644 --- a/arch/mips/mipssim/sim_cmdline.c +++ b/arch/mips/mipssim/sim_cmdline.c @@ -28,8 +28,5 @@ char * __init prom_getcmdline(void) void __init prom_init_cmdline(void) { - char *cp; - cp = arcs_cmdline; - /* Get boot line from environment? */ - *cp = '\0'; + /* XXX: Get boot line from environment? */ } From 736fad17b89e5e718908abb76ae9bce210a9d5d4 Mon Sep 17 00:00:00 2001 From: Kay Sievers Date: Mon, 15 Oct 2007 13:42:35 +0200 Subject: [PATCH 16/19] [MIPS] VPE loader: convert from struct class_ device to struct device Signed-off-by: Kay Sievers Signed-off-by: Ralf Baechle --- arch/mips/kernel/vpe.c | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/arch/mips/kernel/vpe.c b/arch/mips/kernel/vpe.c index 61b729fa0548..df8cbe4c7c0d 100644 --- a/arch/mips/kernel/vpe.c +++ b/arch/mips/kernel/vpe.c @@ -1317,7 +1317,8 @@ static void kspd_sp_exit( int sp_id) } #endif -static ssize_t store_kill(struct class_device *dev, const char *buf, size_t len) +static ssize_t store_kill(struct device *dev, struct device_attribute *attr, + const char *buf, size_t len) { struct vpe *vpe = get_vpe(tclimit); struct vpe_notifications *not; @@ -1334,14 +1335,16 @@ static ssize_t store_kill(struct class_device *dev, const char *buf, size_t len) return len; } -static ssize_t show_ntcs(struct class_device *cd, char *buf) +static ssize_t show_ntcs(struct device *cd, struct device_attribute *attr, + char *buf) { struct vpe *vpe = get_vpe(tclimit); return sprintf(buf, "%d\n", vpe->ntcs); } -static ssize_t store_ntcs(struct class_device *dev, const char *buf, size_t len) +static ssize_t store_ntcs(struct device *dev, struct device_attribute *attr, + const char *buf, size_t len) { struct vpe *vpe = get_vpe(tclimit); unsigned long new; @@ -1362,13 +1365,13 @@ static ssize_t store_ntcs(struct class_device *dev, const char *buf, size_t len) return -EINVAL;; } -static struct class_device_attribute vpe_class_attributes[] = { +static struct device_attribute vpe_class_attributes[] = { __ATTR(kill, S_IWUSR, NULL, store_kill), __ATTR(ntcs, S_IRUGO | S_IWUSR, show_ntcs, store_ntcs), {} }; -static void vpe_class_device_release(struct class_device *cd) +static void vpe_device_release(struct device *cd) { kfree(cd); } @@ -1376,11 +1379,11 @@ static void vpe_class_device_release(struct class_device *cd) struct class vpe_class = { .name = "vpe", .owner = THIS_MODULE, - .release = vpe_class_device_release, - .class_dev_attrs = vpe_class_attributes, + .dev_release = vpe_device_release, + .dev_attrs = vpe_class_attributes, }; -struct class_device vpe_device; +struct device vpe_device; static int __init vpe_module_init(void) { @@ -1423,12 +1426,12 @@ static int __init vpe_module_init(void) goto out_chrdev; } - class_device_initialize(&vpe_device); + device_initialize(&vpe_device); vpe_device.class = &vpe_class, vpe_device.parent = NULL, - strlcpy(vpe_device.class_id, "vpe1", BUS_ID_SIZE); + strlcpy(vpe_device.bus_id, "vpe1", BUS_ID_SIZE); vpe_device.devt = MKDEV(major, minor); - err = class_device_add(&vpe_device); + err = device_add(&vpe_device); if (err) { printk(KERN_ERR "Adding vpe_device failed\n"); goto out_class; @@ -1573,7 +1576,7 @@ static void __exit vpe_module_exit(void) } } - class_device_del(&vpe_device); + device_del(&vpe_device); unregister_chrdev(major, module_name); } From 985c30ef4d7c2a4f0e979a507a7e2f7f09b096c3 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Mon, 15 Oct 2007 16:30:24 +0100 Subject: [PATCH 17/19] [MIPS] Fix aliasing bug in copy_user_highpage, take 2. Turns out b868868ae0f7272228c95cc760338ffe35bb739d wasn't quite right. When called for a page that isn't marked dirty it would artificially create an alias instead of doing the obvious thing and access the page via KSEG0. The same issue also exists in copy_to_user_page and copy_from_user_page which was causing the machine to die under rare circumstances for example when running ps if the BUG_ON() assertion added by the earlier fix was getting triggered. Signed-off-by: Ralf Baechle --- arch/mips/mm/init.c | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/arch/mips/mm/init.c b/arch/mips/mm/init.c index 5240432e6d1d..110ee7656b41 100644 --- a/arch/mips/mm/init.c +++ b/arch/mips/mm/init.c @@ -211,7 +211,7 @@ void copy_user_highpage(struct page *to, struct page *from, void *vfrom, *vto; vto = kmap_atomic(to, KM_USER1); - if (cpu_has_dc_aliases && !Page_dcache_dirty(from)) { + if (cpu_has_dc_aliases && page_mapped(from)) { vfrom = kmap_coherent(from, vaddr); copy_page(vto, vfrom); kunmap_coherent(); @@ -234,12 +234,15 @@ void copy_to_user_page(struct vm_area_struct *vma, struct page *page, unsigned long vaddr, void *dst, const void *src, unsigned long len) { - if (cpu_has_dc_aliases) { + if (cpu_has_dc_aliases && page_mapped(page)) { void *vto = kmap_coherent(page, vaddr) + (vaddr & ~PAGE_MASK); memcpy(vto, src, len); kunmap_coherent(); - } else + } else { memcpy(dst, src, len); + if (cpu_has_dc_aliases) + SetPageDcacheDirty(page); + } if ((vma->vm_flags & VM_EXEC) && !cpu_has_ic_fills_f_dc) flush_cache_page(vma, vaddr, page_to_pfn(page)); } @@ -250,13 +253,15 @@ void copy_from_user_page(struct vm_area_struct *vma, struct page *page, unsigned long vaddr, void *dst, const void *src, unsigned long len) { - if (cpu_has_dc_aliases) { - void *vfrom = - kmap_coherent(page, vaddr) + (vaddr & ~PAGE_MASK); + if (cpu_has_dc_aliases && page_mapped(page)) { + void *vfrom = kmap_coherent(page, vaddr) + (vaddr & ~PAGE_MASK); memcpy(dst, vfrom, len); kunmap_coherent(); - } else + } else { memcpy(dst, src, len); + if (cpu_has_dc_aliases) + SetPageDcacheDirty(page); + } } EXPORT_SYMBOL(copy_from_user_page); From 64bfca5cd8c40fa138ad5db2513e8bcf8bd54ebd Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Mon, 15 Oct 2007 16:35:45 +0100 Subject: [PATCH 18/19] [MIPS] Cache: Provide more information on cache policy on bootup. This should help making bug reports for the gadzillion of cores with all their configuration and synthesis options more useful. Signed-off-by: Ralf Baechle --- arch/mips/mm/c-r4k.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/arch/mips/mm/c-r4k.c b/arch/mips/mm/c-r4k.c index 971f6c047b8a..d7088331fb0f 100644 --- a/arch/mips/mm/c-r4k.c +++ b/arch/mips/mm/c-r4k.c @@ -983,11 +983,15 @@ static void __init probe_pcache(void) printk("Primary instruction cache %ldkB, %s, %s, linesize %d bytes.\n", icache_size >> 10, - cpu_has_vtag_icache ? "virtually tagged" : "physically tagged", + cpu_has_vtag_icache ? "VIVT" : "VIPT", way_string[c->icache.ways], c->icache.linesz); - printk("Primary data cache %ldkB, %s, linesize %d bytes.\n", - dcache_size >> 10, way_string[c->dcache.ways], c->dcache.linesz); + printk("Primary data cache %ldkB, %s, %s, %s, linesize %d bytes\n", + dcache_size >> 10, way_string[c->dcache.ways], + (c->dcache.flags & MIPS_CACHE_PINDEX) ? "PIPT" : "VIPT", + (c->dcache.flags & MIPS_CACHE_ALIASES) ? + "cache aliases" : "no aliases", + c->dcache.linesz); } /* From 8bb00d83d8fc2de5c0614f5d55780107e0c375fe Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Tue, 16 Oct 2007 11:35:11 +0100 Subject: [PATCH 19/19] [MIPS] Increase cp0 compare clockevent min_delta_ns from 0x30 to 0x300. Extremly low values are of dubious usefulness anyway but in this case they actually were killing Qemu which simply wasn't able to complete mips_next_event() within 0x30 100MHz cycles even on fast hosts. Signed-off-by: Ralf Baechle --- arch/mips/kernel/time.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/mips/kernel/time.c b/arch/mips/kernel/time.c index 5892491b40eb..05b365167a09 100644 --- a/arch/mips/kernel/time.c +++ b/arch/mips/kernel/time.c @@ -421,7 +421,7 @@ void __cpuinit mips_clockevent_init(void) cd->mult = div_sc((unsigned long) mips_freq, NSEC_PER_SEC, 32); cd->shift = 32; cd->max_delta_ns = clockevent_delta2ns(0x7fffffff, cd); - cd->min_delta_ns = clockevent_delta2ns(0x30, cd); + cd->min_delta_ns = clockevent_delta2ns(0x300, cd); cd->rating = 300; cd->irq = irq;