diff options
Diffstat (limited to 'arch/mips')
25 files changed, 490 insertions, 497 deletions
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index f943736..235d451 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 @@ -410,6 +411,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/au1000/common/au1xxx_irqmap.c b/arch/mips/au1000/common/au1xxx_irqmap.c index 7acfe9b..98a4e34 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/dbdma.c b/arch/mips/au1000/common/dbdma.c index 461cf01..9d6ad43 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 a6640b9..c00f308 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 <linux/errno.h> +#include <linux/bitops.h> #include <linux/init.h> -#include <linux/irq.h> -#include <linux/kernel_stat.h> -#include <linux/module.h> -#include <linux/signal.h> -#include <linux/sched.h> -#include <linux/types.h> +#include <linux/io.h> #include <linux/interrupt.h> -#include <linux/ioport.h> -#include <linux/timex.h> -#include <linux/slab.h> -#include <linux/random.h> -#include <linux/delay.h> -#include <linux/bitops.h> +#include <linux/irq.h> -#include <asm/bootinfo.h> -#include <asm/io.h> #include <asm/mipsregs.h> -#include <asm/system.h> #include <asm/mach-au1x00/au1000.h> #ifdef CONFIG_MIPS_PB1000 #include <asm/mach-pb1x00/pb1000.h> #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,16 +48,98 @@ void (*board_init_irq)(void); static DEFINE_SPINLOCK(irq_lock); +#ifdef CONFIG_PM + +/* + * Save/restore the interrupt controller state. + * Called from the save/restore core registers as part of the + * au_sleep function in power.c.....maybe I should just pm_register() + * them instead? + */ +static unsigned int sleep_intctl_config0[2]; +static unsigned int sleep_intctl_config1[2]; +static unsigned int sleep_intctl_config2[2]; +static unsigned int sleep_intctl_src[2]; +static unsigned int sleep_intctl_assign[2]; +static unsigned int sleep_intctl_wake[2]; +static unsigned int sleep_intctl_mask[2]; + +void save_au1xxx_intctl(void) +{ + sleep_intctl_config0[0] = au_readl(IC0_CFG0RD); + sleep_intctl_config1[0] = au_readl(IC0_CFG1RD); + sleep_intctl_config2[0] = au_readl(IC0_CFG2RD); + sleep_intctl_src[0] = au_readl(IC0_SRCRD); + sleep_intctl_assign[0] = au_readl(IC0_ASSIGNRD); + sleep_intctl_wake[0] = au_readl(IC0_WAKERD); + sleep_intctl_mask[0] = au_readl(IC0_MASKRD); + + sleep_intctl_config0[1] = au_readl(IC1_CFG0RD); + sleep_intctl_config1[1] = au_readl(IC1_CFG1RD); + sleep_intctl_config2[1] = au_readl(IC1_CFG2RD); + sleep_intctl_src[1] = au_readl(IC1_SRCRD); + sleep_intctl_assign[1] = au_readl(IC1_ASSIGNRD); + sleep_intctl_wake[1] = au_readl(IC1_WAKERD); + sleep_intctl_mask[1] = au_readl(IC1_MASKRD); +} + +/* + * For most restore operations, we clear the entire register and + * then set the bits we found during the save. + */ +void restore_au1xxx_intctl(void) +{ + au_writel(0xffffffff, IC0_MASKCLR); au_sync(); + + au_writel(0xffffffff, IC0_CFG0CLR); au_sync(); + au_writel(sleep_intctl_config0[0], IC0_CFG0SET); au_sync(); + au_writel(0xffffffff, IC0_CFG1CLR); au_sync(); + au_writel(sleep_intctl_config1[0], IC0_CFG1SET); au_sync(); + au_writel(0xffffffff, IC0_CFG2CLR); au_sync(); + au_writel(sleep_intctl_config2[0], IC0_CFG2SET); au_sync(); + au_writel(0xffffffff, IC0_SRCCLR); au_sync(); + au_writel(sleep_intctl_src[0], IC0_SRCSET); au_sync(); + au_writel(0xffffffff, IC0_ASSIGNCLR); au_sync(); + au_writel(sleep_intctl_assign[0], IC0_ASSIGNSET); au_sync(); + au_writel(0xffffffff, IC0_WAKECLR); au_sync(); + au_writel(sleep_intctl_wake[0], IC0_WAKESET); au_sync(); + au_writel(0xffffffff, IC0_RISINGCLR); au_sync(); + au_writel(0xffffffff, IC0_FALLINGCLR); au_sync(); + au_writel(0x00000000, IC0_TESTBIT); au_sync(); + + au_writel(0xffffffff, IC1_MASKCLR); au_sync(); + + au_writel(0xffffffff, IC1_CFG0CLR); au_sync(); + au_writel(sleep_intctl_config0[1], IC1_CFG0SET); au_sync(); + au_writel(0xffffffff, IC1_CFG1CLR); au_sync(); + au_writel(sleep_intctl_config1[1], IC1_CFG1SET); au_sync(); + au_writel(0xffffffff, IC1_CFG2CLR); au_sync(); + au_writel(sleep_intctl_config2[1], IC1_CFG2SET); au_sync(); + au_writel(0xffffffff, IC1_SRCCLR); au_sync(); + au_writel(sleep_intctl_src[1], IC1_SRCSET); au_sync(); + au_writel(0xffffffff, IC1_ASSIGNCLR); au_sync(); + au_writel(sleep_intctl_assign[1], IC1_ASSIGNSET); au_sync(); + au_writel(0xffffffff, IC1_WAKECLR); au_sync(); + au_writel(sleep_intctl_wake[1], IC1_WAKESET); au_sync(); + au_writel(0xffffffff, IC1_RISINGCLR); au_sync(); + au_writel(0xffffffff, IC1_FALLINGCLR); au_sync(); + au_writel(0x00000000, IC1_TESTBIT); au_sync(); + + au_writel(sleep_intctl_mask[1], IC1_MASKSET); au_sync(); + + au_writel(sleep_intctl_mask[0], IC0_MASKSET); au_sync(); +} +#endif /* CONFIG_PM */ + 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<<irq_nr, IC0_MASKSET); - au_writel(1<<irq_nr, IC0_WAKESET); + 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(); } @@ -87,12 +148,11 @@ inline void local_enable_irq(unsigned int irq_nr) 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_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(); } @@ -101,12 +161,11 @@ inline void local_disable_irq(unsigned int irq_nr) 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_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(); } @@ -115,12 +174,11 @@ static inline void mask_and_ack_rise_edge_irq(unsigned int irq_nr) 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_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(); } @@ -132,14 +190,13 @@ static inline void mask_and_ack_either_edge_irq(unsigned int irq_nr) * 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_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(); } @@ -162,9 +219,9 @@ static inline void mask_and_ack_level_irq(unsigned int irq_nr) static void end_irq(unsigned int irq_nr) { - if (!(irq_desc[irq_nr].status & (IRQ_DISABLED|IRQ_INPROGRESS))) { + 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 */ @@ -181,15 +238,12 @@ unsigned long save_local_and_disable(int controller) spin_lock_irqsave(&irq_lock, flags); if (controller) { mask = au_readl(IC1_MASKSET); - for (i=32; i<64; i++) { + for (i = 32; i < 64; i++) local_disable_irq(i); - } - } - else { + } else { mask = au_readl(IC0_MASKSET); - for (i=0; i<32; i++) { + for (i = 0; i < 32; i++) local_disable_irq(i); - } } spin_unlock_irqrestore(&irq_lock, flags); @@ -202,10 +256,10 @@ void restore_local_and_enable(int controller, unsigned long mask) unsigned long flags, new_mask; spin_lock_irqsave(&irq_lock, flags); - for (i=0; i<32; i++) { - if (mask & (1<<i)) { + for (i = 0; i < 32; i++) { + if (mask & (1 << i)) { if (controller) - local_enable_irq(i+32); + local_enable_irq(i + 32); else local_enable_irq(i); } @@ -220,39 +274,39 @@ void restore_local_and_enable(int controller, unsigned long mask) 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, + .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, + .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, + .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, + .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 @@ -263,7 +317,8 @@ void startup_match20_interrupt(irq_handler_t handler) static struct irqaction action; memset(&action, 0, sizeof(struct irqaction)); - /* This is a big problem.... since we didn't use request_irq + /* + * 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 @@ -292,173 +347,112 @@ static void setup_local_irq(unsigned int irq_nr, int type, int int_req) /* 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; + 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); + 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 { + 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("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; + 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); + 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_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(); } - -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)(); -} - - /* * Interrupts are nested. Even if an interrupt handler is registered * as "fast", we might get another interrupt before we return from @@ -468,26 +462,27 @@ void __init arch_init_irq(void) static void intc0_req0_irqdispatch(void) { int irq = 0; - static unsigned long intc0_req0 = 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); + 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); + irq = ffs(intc0_req0); + intc0_req0 &= ~(1 << irq); do_IRQ(irq); } @@ -495,15 +490,15 @@ static void intc0_req0_irqdispatch(void) static void intc0_req1_irqdispatch(void) { int irq = 0; - static unsigned long intc0_req1 = 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); + irq = ffs(intc0_req1); + intc0_req1 &= ~(1 << irq); do_IRQ(irq); } @@ -515,15 +510,15 @@ static void intc0_req1_irqdispatch(void) static void intc1_req0_irqdispatch(void) { int irq = 0; - static unsigned long intc1_req0 = 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 = ffs(intc1_req0); + intc1_req0 &= ~(1 << irq); irq += 32; do_IRQ(irq); } @@ -532,102 +527,19 @@ static void intc1_req0_irqdispatch(void) static void intc1_req1_irqdispatch(void) { int irq = 0; - static unsigned long intc1_req1 = 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 = ffs(intc1_req1); + intc1_req1 &= ~(1 << irq); irq += 32; do_IRQ(irq); } -#ifdef CONFIG_PM - -/* Save/restore the interrupt controller state. - * Called from the save/restore core registers as part of the - * au_sleep function in power.c.....maybe I should just pm_register() - * them instead? - */ -static unsigned int sleep_intctl_config0[2]; -static unsigned int sleep_intctl_config1[2]; -static unsigned int sleep_intctl_config2[2]; -static unsigned int sleep_intctl_src[2]; -static unsigned int sleep_intctl_assign[2]; -static unsigned int sleep_intctl_wake[2]; -static unsigned int sleep_intctl_mask[2]; - -void -save_au1xxx_intctl(void) -{ - sleep_intctl_config0[0] = au_readl(IC0_CFG0RD); - sleep_intctl_config1[0] = au_readl(IC0_CFG1RD); - sleep_intctl_config2[0] = au_readl(IC0_CFG2RD); - sleep_intctl_src[0] = au_readl(IC0_SRCRD); - sleep_intctl_assign[0] = au_readl(IC0_ASSIGNRD); - sleep_intctl_wake[0] = au_readl(IC0_WAKERD); - sleep_intctl_mask[0] = au_readl(IC0_MASKRD); - - sleep_intctl_config0[1] = au_readl(IC1_CFG0RD); - sleep_intctl_config1[1] = au_readl(IC1_CFG1RD); - sleep_intctl_config2[1] = au_readl(IC1_CFG2RD); - sleep_intctl_src[1] = au_readl(IC1_SRCRD); - sleep_intctl_assign[1] = au_readl(IC1_ASSIGNRD); - sleep_intctl_wake[1] = au_readl(IC1_WAKERD); - sleep_intctl_mask[1] = au_readl(IC1_MASKRD); -} - -/* For most restore operations, we clear the entire register and - * then set the bits we found during the save. - */ -void -restore_au1xxx_intctl(void) -{ - au_writel(0xffffffff, IC0_MASKCLR); au_sync(); - - au_writel(0xffffffff, IC0_CFG0CLR); au_sync(); - au_writel(sleep_intctl_config0[0], IC0_CFG0SET); au_sync(); - au_writel(0xffffffff, IC0_CFG1CLR); au_sync(); - au_writel(sleep_intctl_config1[0], IC0_CFG1SET); au_sync(); - au_writel(0xffffffff, IC0_CFG2CLR); au_sync(); - au_writel(sleep_intctl_config2[0], IC0_CFG2SET); au_sync(); - au_writel(0xffffffff, IC0_SRCCLR); au_sync(); - au_writel(sleep_intctl_src[0], IC0_SRCSET); au_sync(); - au_writel(0xffffffff, IC0_ASSIGNCLR); au_sync(); - au_writel(sleep_intctl_assign[0], IC0_ASSIGNSET); au_sync(); - au_writel(0xffffffff, IC0_WAKECLR); au_sync(); - au_writel(sleep_intctl_wake[0], IC0_WAKESET); au_sync(); - au_writel(0xffffffff, IC0_RISINGCLR); au_sync(); - au_writel(0xffffffff, IC0_FALLINGCLR); au_sync(); - au_writel(0x00000000, IC0_TESTBIT); au_sync(); - - au_writel(0xffffffff, IC1_MASKCLR); au_sync(); - - au_writel(0xffffffff, IC1_CFG0CLR); au_sync(); - au_writel(sleep_intctl_config0[1], IC1_CFG0SET); au_sync(); - au_writel(0xffffffff, IC1_CFG1CLR); au_sync(); - au_writel(sleep_intctl_config1[1], IC1_CFG1SET); au_sync(); - au_writel(0xffffffff, IC1_CFG2CLR); au_sync(); - au_writel(sleep_intctl_config2[1], IC1_CFG2SET); au_sync(); - au_writel(0xffffffff, IC1_SRCCLR); au_sync(); - au_writel(sleep_intctl_src[1], IC1_SRCSET); au_sync(); - au_writel(0xffffffff, IC1_ASSIGNCLR); au_sync(); - au_writel(sleep_intctl_assign[1], IC1_ASSIGNSET); au_sync(); - au_writel(0xffffffff, IC1_WAKECLR); au_sync(); - au_writel(sleep_intctl_wake[1], IC1_WAKESET); au_sync(); - au_writel(0xffffffff, IC1_RISINGCLR); au_sync(); - au_writel(0xffffffff, IC1_FALLINGCLR); au_sync(); - au_writel(0x00000000, IC1_TESTBIT); au_sync(); - - au_writel(sleep_intctl_mask[1], IC1_MASKSET); au_sync(); - - au_writel(sleep_intctl_mask[0], IC0_MASKSET); au_sync(); -} -#endif /* CONFIG_PM */ - 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; + 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; + + 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)(); +} diff --git a/arch/mips/au1000/db1x00/irqmap.c b/arch/mips/au1000/db1x00/irqmap.c index 3e57291..09cea03 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 a4fa0f2..49c612a 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 156500b..88e3545 100644 --- a/arch/mips/au1000/pb1000/irqmap.c +++ b/arch/mips/au1000/pb1000/irqmap.c @@ -47,7 +47,7 @@ #include <asm/system.h> #include <asm/mach-au1x00/au1000.h> -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 d986916..880456b 100644 --- a/arch/mips/au1000/pb1100/irqmap.c +++ b/arch/mips/au1000/pb1100/irqmap.c @@ -47,7 +47,7 @@ #include <asm/system.h> #include <asm/mach-au1x00/au1000.h> -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 7c708db..3bee274 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 }; @@ -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/arch/mips/au1000/pb1500/irqmap.c b/arch/mips/au1000/pb1500/irqmap.c index 409d161..810f695 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 24a9d18..56becab 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 3844c64..3893492 100644 --- a/arch/mips/au1000/xxs1500/irqmap.c +++ b/arch/mips/au1000/xxs1500/irqmap.c @@ -47,7 +47,7 @@ #include <asm/system.h> #include <asm/au1000.h> -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/kernel/time.c b/arch/mips/kernel/time.c index 5892491..05b3651 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; diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c index 632bce1..9c0c478 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((struct pt_regs *)regs); +} + +void show_registers(const struct pt_regs *regs) { - show_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/arch/mips/kernel/vmlinux.lds.S b/arch/mips/kernel/vmlinux.lds.S index 84f9a4c..2781cff 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 @@ -22,7 +26,6 @@ SECTIONS */ /* . = 0xa800000000300000; */ - /* . = 0xa800000000300000; */ . = 0xffffffff80300000; #endif . = LOADADDR; @@ -32,9 +35,10 @@ SECTIONS TEXT_TEXT SCHED_TEXT LOCK_TEXT + KPROBES_TEXT *(.fixup) *(.gnu.warning) - } =0 + } :text = 0 _etext = .; /* End of text section */ /* Exception table */ @@ -51,6 +55,10 @@ SECTIONS *(__dbe_table) __stop___dbe_table = .; } + + NOTES :text :note + .dummy : { *(.dummy) } :text + RODATA /* writeable */ @@ -201,7 +209,4 @@ SECTIONS *(.gptab.bss) *(.gptab.sbss) } - .note : { - *(.note) - } } diff --git a/arch/mips/kernel/vpe.c b/arch/mips/kernel/vpe.c index 61b729f..df8cbe4 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 @@ out_einval: 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); } diff --git a/arch/mips/lasat/interrupt.c b/arch/mips/lasat/interrupt.c index 5f35289..ba9692b 100644 --- a/arch/mips/lasat/interrupt.c +++ b/arch/mips/lasat/interrupt.c @@ -26,6 +26,7 @@ #include <linux/kernel_stat.h> #include <asm/bootinfo.h> +#include <asm/irq_cpu.h> #include <asm/lasat/lasatint.h> #include <asm/time.h> #include <asm/gdb-stub.h> @@ -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/mipssim/sim_cmdline.c b/arch/mips/mipssim/sim_cmdline.c index c63021a..74240e1 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? */ } diff --git a/arch/mips/mm/c-r4k.c b/arch/mips/mm/c-r4k.c index 971f6c0..d708833 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); } /* diff --git a/arch/mips/mm/init.c b/arch/mips/mm/init.c index 5240432..110ee76 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); diff --git a/arch/mips/pci/pci-lasat.c b/arch/mips/pci/pci-lasat.c index 5abd5c7..174f314 100644 --- a/arch/mips/pci/pci-lasat.c +++ b/arch/mips/pci/pci-lasat.c @@ -10,6 +10,7 @@ #include <linux/pci.h> #include <linux/types.h> #include <asm/bootinfo.h> +#include <asm/lasat/lasatint.h> 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/arch/mips/sgi-ip22/Makefile b/arch/mips/sgi-ip22/Makefile index 1fb3e35..e3acb51 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 diff --git a/arch/mips/sgi-ip22/ip22-reset.c b/arch/mips/sgi-ip22/ip22-reset.c index 63afd7e..a435b31 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); diff --git a/arch/mips/sgi-ip32/ip32-irq.c b/arch/mips/sgi-ip32/ip32-irq.c index 7f4b793..7e8094f 100644 --- a/arch/mips/sgi-ip32/ip32-irq.c +++ b/arch/mips/sgi-ip32/ip32-irq.c @@ -20,6 +20,7 @@ #include <linux/random.h> #include <linux/sched.h> +#include <asm/irq_cpu.h> #include <asm/mipsregs.h> #include <asm/signal.h> #include <asm/system.h> @@ -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. */ @@ -131,36 +133,6 @@ struct irqaction cpuerr_irq = { }; /* - * 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; - - 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; - - set_irq_chip(irq, controller); + mips_cpu_irq_init(); + for (irq = MIPS_CPU_IRQ_BASE + 8; irq <= IP32_IRQ_MAX; irq++) { + struct irq_chip *chip; + + 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, 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 4125a5b..fc75bfc 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) |