diff options
Diffstat (limited to 'arch/mips/vr41xx/common')
| -rw-r--r-- | arch/mips/vr41xx/common/Makefile | 5 | ||||
| -rw-r--r-- | arch/mips/vr41xx/common/bcu.c | 26 | ||||
| -rw-r--r-- | arch/mips/vr41xx/common/cmu.c | 40 | ||||
| -rw-r--r-- | arch/mips/vr41xx/common/giu.c | 123 | ||||
| -rw-r--r-- | arch/mips/vr41xx/common/icu.c | 320 | ||||
| -rw-r--r-- | arch/mips/vr41xx/common/init.c | 32 | ||||
| -rw-r--r-- | arch/mips/vr41xx/common/int-handler.S | 114 | ||||
| -rw-r--r-- | arch/mips/vr41xx/common/irq.c | 70 | ||||
| -rw-r--r-- | arch/mips/vr41xx/common/pmu.c | 43 | ||||
| -rw-r--r-- | arch/mips/vr41xx/common/rtc.c | 118 | ||||
| -rw-r--r-- | arch/mips/vr41xx/common/siu.c | 155 | ||||
| -rw-r--r-- | arch/mips/vr41xx/common/type.c | 2 | ||||
| -rw-r--r-- | arch/mips/vr41xx/common/vrc4173.c | 581 |
13 files changed, 675 insertions, 954 deletions
diff --git a/arch/mips/vr41xx/common/Makefile b/arch/mips/vr41xx/common/Makefile index 9096302a7ec..d0d84ec8d63 100644 --- a/arch/mips/vr41xx/common/Makefile +++ b/arch/mips/vr41xx/common/Makefile @@ -2,7 +2,4 @@ # Makefile for common code of the NEC VR4100 series. # -obj-y += bcu.o cmu.o icu.o init.o int-handler.o irq.o pmu.o type.o -obj-$(CONFIG_VRC4173) += vrc4173.o - -EXTRA_AFLAGS := $(CFLAGS) +obj-y += bcu.o cmu.o giu.o icu.o init.o irq.o pmu.o rtc.o siu.o type.o diff --git a/arch/mips/vr41xx/common/bcu.c b/arch/mips/vr41xx/common/bcu.c index de0c1b35f11..ff7d1c66cf8 100644 --- a/arch/mips/vr41xx/common/bcu.c +++ b/arch/mips/vr41xx/common/bcu.c @@ -1,9 +1,9 @@ /* * bcu.c, Bus Control Unit routines for the NEC VR4100 series. * - * Copyright (C) 2002 MontaVista Software Inc. - * Author: Yoichi Yuasa <yyuasa@mvista.com, or source@mvista.com> - * Copyright (C) 2003-2005 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> + * Copyright (C) 2002 MontaVista Software Inc. + * Author: Yoichi Yuasa <source@mvista.com> + * Copyright (C) 2003-2005 Yoichi Yuasa <yuasa@linux-mips.org> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -21,11 +21,11 @@ */ /* * Changes: - * MontaVista Software Inc. <yyuasa@mvista.com> or <source@mvista.com> + * MontaVista Software Inc. <source@mvista.com> * - New creation, NEC VR4122 and VR4131 are supported. * - Added support for NEC VR4111 and VR4121. * - * Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> + * Yoichi Yuasa <yuasa@linux-mips.org> * - Added support for NEC VR4133. */ #include <linux/kernel.h> @@ -70,7 +70,7 @@ EXPORT_SYMBOL_GPL(vr41xx_get_tclock_frequency); static inline uint16_t read_clkspeed(void) { - switch (current_cpu_data.cputype) { + switch (current_cpu_type()) { case CPU_VR4111: case CPU_VR4121: return readw(CLKSPEEDREG_TYPE1); case CPU_VR4122: @@ -88,7 +88,7 @@ static inline unsigned long calculate_pclock(uint16_t clkspeed) { unsigned long pclock = 0; - switch (current_cpu_data.cputype) { + switch (current_cpu_type()) { case CPU_VR4111: case CPU_VR4121: pclock = 18432000 * 64; @@ -138,7 +138,7 @@ static inline unsigned long calculate_vtclock(uint16_t clkspeed, unsigned long p { unsigned long vtclock = 0; - switch (current_cpu_data.cputype) { + switch (current_cpu_type()) { case CPU_VR4111: /* The NEC VR4111 doesn't have the VTClock. */ break; @@ -176,18 +176,18 @@ static inline unsigned long calculate_vtclock(uint16_t clkspeed, unsigned long p } static inline unsigned long calculate_tclock(uint16_t clkspeed, unsigned long pclock, - unsigned long vtclock) + unsigned long vtclock) { unsigned long tclock = 0; - switch (current_cpu_data.cputype) { + switch (current_cpu_type()) { case CPU_VR4111: if (!(clkspeed & DIV2B)) - tclock = pclock / 2; + tclock = pclock / 2; else if (!(clkspeed & DIV3B)) - tclock = pclock / 3; + tclock = pclock / 3; else if (!(clkspeed & DIV4B)) - tclock = pclock / 4; + tclock = pclock / 4; break; case CPU_VR4121: tclock = pclock / DIVT(clkspeed); diff --git a/arch/mips/vr41xx/common/cmu.c b/arch/mips/vr41xx/common/cmu.c index 657c5133c93..05302bfdd11 100644 --- a/arch/mips/vr41xx/common/cmu.c +++ b/arch/mips/vr41xx/common/cmu.c @@ -2,8 +2,8 @@ * cmu.c, Clock Mask Unit routines for the NEC VR4100 series. * * Copyright (C) 2001-2002 MontaVista Software Inc. - * Author: Yoichi Yuasa <yyuasa@mvista.com or source@mvista.com> - * Copuright (C) 2003-2005 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> + * Author: Yoichi Yuasa <source@mvista.com> + * Copuright (C) 2003-2005 Yoichi Yuasa <yuasa@linux-mips.org> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -21,11 +21,11 @@ */ /* * Changes: - * MontaVista Software Inc. <yyuasa@mvista.com> or <source@mvista.com> + * MontaVista Software Inc. <source@mvista.com> * - New creation, NEC VR4122 and VR4131 are supported. * - Added support for NEC VR4111 and VR4121. * - * Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> + * Yoichi Yuasa <yuasa@linux-mips.org> * - Added support for NEC VR4133. */ #include <linux/init.h> @@ -95,8 +95,8 @@ void vr41xx_supply_clock(vr41xx_clock_t clock) cmuclkmsk |= MSKFIR | MSKFFIR; break; case DSIU_CLOCK: - if (current_cpu_data.cputype == CPU_VR4111 || - current_cpu_data.cputype == CPU_VR4121) + if (current_cpu_type() == CPU_VR4111 || + current_cpu_type() == CPU_VR4121) cmuclkmsk |= MSKDSIU; else cmuclkmsk |= MSKSIU | MSKDSIU; @@ -146,8 +146,8 @@ void vr41xx_mask_clock(vr41xx_clock_t clock) cmuclkmsk &= ~MSKPIU; break; case SIU_CLOCK: - if (current_cpu_data.cputype == CPU_VR4111 || - current_cpu_data.cputype == CPU_VR4121) { + if (current_cpu_type() == CPU_VR4111 || + current_cpu_type() == CPU_VR4121) { cmuclkmsk &= ~(MSKSIU | MSKSSIU); } else { if (cmuclkmsk & MSKDSIU) @@ -166,8 +166,8 @@ void vr41xx_mask_clock(vr41xx_clock_t clock) cmuclkmsk &= ~(MSKFIR | MSKFFIR); break; case DSIU_CLOCK: - if (current_cpu_data.cputype == CPU_VR4111 || - current_cpu_data.cputype == CPU_VR4121) { + if (current_cpu_type() == CPU_VR4111 || + current_cpu_type() == CPU_VR4121) { cmuclkmsk &= ~MSKDSIU; } else { if (cmuclkmsk & MSKSSIU) @@ -216,25 +216,25 @@ static int __init vr41xx_cmu_init(void) { unsigned long start, size; - switch (current_cpu_data.cputype) { - case CPU_VR4111: - case CPU_VR4121: + switch (current_cpu_type()) { + case CPU_VR4111: + case CPU_VR4121: start = CMU_TYPE1_BASE; size = CMU_TYPE1_SIZE; - break; - case CPU_VR4122: - case CPU_VR4131: + break; + case CPU_VR4122: + case CPU_VR4131: start = CMU_TYPE2_BASE; size = CMU_TYPE2_SIZE; break; - case CPU_VR4133: + case CPU_VR4133: start = CMU_TYPE3_BASE; size = CMU_TYPE3_SIZE; - break; + break; default: panic("Unexpected CPU of NEC VR4100 series"); break; - } + } if (request_mem_region(start, size, "CMU") == NULL) return -EBUSY; @@ -246,7 +246,7 @@ static int __init vr41xx_cmu_init(void) } cmuclkmsk = cmu_read(CMUCLKMSK); - if (current_cpu_data.cputype == CPU_VR4133) + if (current_cpu_type() == CPU_VR4133) cmuclkmsk2 = cmu_read(CMUCLKMSK2); spin_lock_init(&cmu_lock); diff --git a/arch/mips/vr41xx/common/giu.c b/arch/mips/vr41xx/common/giu.c new file mode 100644 index 00000000000..32cc8d66b34 --- /dev/null +++ b/arch/mips/vr41xx/common/giu.c @@ -0,0 +1,123 @@ +/* + * NEC VR4100 series GIU platform device. + * + * Copyright (C) 2007 Yoichi Yuasa <yuasa@linux-mips.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include <linux/errno.h> +#include <linux/init.h> +#include <linux/smp.h> +#include <linux/ioport.h> +#include <linux/platform_device.h> + +#include <asm/cpu.h> +#include <asm/vr41xx/giu.h> +#include <asm/vr41xx/irq.h> + +static struct resource giu_50pins_pullupdown_resource[] __initdata = { + { + .start = 0x0b000100, + .end = 0x0b00011f, + .flags = IORESOURCE_MEM, + }, + { + .start = 0x0b0002e0, + .end = 0x0b0002e3, + .flags = IORESOURCE_MEM, + }, + { + .start = GIUINT_IRQ, + .end = GIUINT_IRQ, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct resource giu_36pins_resource[] __initdata = { + { + .start = 0x0f000140, + .end = 0x0f00015f, + .flags = IORESOURCE_MEM, + }, + { + .start = GIUINT_IRQ, + .end = GIUINT_IRQ, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct resource giu_48pins_resource[] __initdata = { + { + .start = 0x0f000140, + .end = 0x0f000167, + .flags = IORESOURCE_MEM, + }, + { + .start = GIUINT_IRQ, + .end = GIUINT_IRQ, + .flags = IORESOURCE_IRQ, + }, +}; + +static int __init vr41xx_giu_add(void) +{ + struct platform_device *pdev; + struct resource *res; + unsigned int num; + int retval; + + pdev = platform_device_alloc("GIU", -1); + if (!pdev) + return -ENOMEM; + + switch (current_cpu_type()) { + case CPU_VR4111: + case CPU_VR4121: + pdev->id = GPIO_50PINS_PULLUPDOWN; + res = giu_50pins_pullupdown_resource; + num = ARRAY_SIZE(giu_50pins_pullupdown_resource); + break; + case CPU_VR4122: + case CPU_VR4131: + pdev->id = GPIO_36PINS; + res = giu_36pins_resource; + num = ARRAY_SIZE(giu_36pins_resource); + break; + case CPU_VR4133: + pdev->id = GPIO_48PINS_EDGE_SELECT; + res = giu_48pins_resource; + num = ARRAY_SIZE(giu_48pins_resource); + break; + default: + retval = -ENODEV; + goto err_free_device; + } + + retval = platform_device_add_resources(pdev, res, num); + if (retval) + goto err_free_device; + + retval = platform_device_add(pdev); + if (retval) + goto err_free_device; + + return 0; + +err_free_device: + platform_device_put(pdev); + + return retval; +} +device_initcall(vr41xx_giu_add); diff --git a/arch/mips/vr41xx/common/icu.c b/arch/mips/vr41xx/common/icu.c index 07ae19cf0c2..41e873bc847 100644 --- a/arch/mips/vr41xx/common/icu.c +++ b/arch/mips/vr41xx/common/icu.c @@ -2,8 +2,8 @@ * icu.c, Interrupt Control Unit routines for the NEC VR4100 series. * * Copyright (C) 2001-2002 MontaVista Software Inc. - * Author: Yoichi Yuasa <yyuasa@mvista.com or source@mvista.com> - * Copyright (C) 2003-2005 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> + * Author: Yoichi Yuasa <source@mvista.com> + * Copyright (C) 2003-2006 Yoichi Yuasa <yuasa@linux-mips.org> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -21,11 +21,11 @@ */ /* * Changes: - * MontaVista Software Inc. <yyuasa@mvista.com> or <source@mvista.com> + * MontaVista Software Inc. <source@mvista.com> * - New creation, NEC VR4122 and VR4131 are supported. * - Added support for NEC VR4111 and VR4121. * - * Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> + * Yoichi Yuasa <yuasa@linux-mips.org> * - Coped with INTASSIGN of NEC VR4133. */ #include <linux/errno.h> @@ -38,6 +38,7 @@ #include <asm/cpu.h> #include <asm/io.h> +#include <asm/vr41xx/irq.h> #include <asm/vr41xx/vr41xx.h> static void __iomem *icu1_base; @@ -48,11 +49,11 @@ static unsigned char sysint1_assign[16] = { static unsigned char sysint2_assign[16] = { 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; -#define ICU1_TYPE1_BASE 0x0b000080UL -#define ICU2_TYPE1_BASE 0x0b000200UL +#define ICU1_TYPE1_BASE 0x0b000080UL +#define ICU2_TYPE1_BASE 0x0b000200UL -#define ICU1_TYPE2_BASE 0x0f000080UL -#define ICU2_TYPE2_BASE 0x0f0000a0UL +#define ICU1_TYPE2_BASE 0x0f000080UL +#define ICU2_TYPE2_BASE 0x0f0000a0UL #define ICU1_SIZE 0x20 #define ICU2_SIZE 0x1c @@ -67,6 +68,7 @@ static unsigned char sysint2_assign[16] = { #define MPIUINTREG 0x0e #define MAIUINTREG 0x10 #define MKIUINTREG 0x12 +#define MMACINTREG 0x12 #define MGIUINTLREG 0x14 #define MDSIUINTREG 0x16 #define NMIREG 0x18 @@ -152,14 +154,14 @@ static inline uint16_t icu2_clear(uint8_t offset, uint16_t clear) void vr41xx_enable_piuint(uint16_t mask) { - irq_desc_t *desc = irq_desc + PIU_IRQ; + struct irq_desc *desc = irq_to_desc(PIU_IRQ); unsigned long flags; - if (current_cpu_data.cputype == CPU_VR4111 || - current_cpu_data.cputype == CPU_VR4121) { - spin_lock_irqsave(&desc->lock, flags); + if (current_cpu_type() == CPU_VR4111 || + current_cpu_type() == CPU_VR4121) { + raw_spin_lock_irqsave(&desc->lock, flags); icu1_set(MPIUINTREG, mask); - spin_unlock_irqrestore(&desc->lock, flags); + raw_spin_unlock_irqrestore(&desc->lock, flags); } } @@ -167,14 +169,14 @@ EXPORT_SYMBOL(vr41xx_enable_piuint); void vr41xx_disable_piuint(uint16_t mask) { - irq_desc_t *desc = irq_desc + PIU_IRQ; + struct irq_desc *desc = irq_to_desc(PIU_IRQ); unsigned long flags; - if (current_cpu_data.cputype == CPU_VR4111 || - current_cpu_data.cputype == CPU_VR4121) { - spin_lock_irqsave(&desc->lock, flags); + if (current_cpu_type() == CPU_VR4111 || + current_cpu_type() == CPU_VR4121) { + raw_spin_lock_irqsave(&desc->lock, flags); icu1_clear(MPIUINTREG, mask); - spin_unlock_irqrestore(&desc->lock, flags); + raw_spin_unlock_irqrestore(&desc->lock, flags); } } @@ -182,14 +184,14 @@ EXPORT_SYMBOL(vr41xx_disable_piuint); void vr41xx_enable_aiuint(uint16_t mask) { - irq_desc_t *desc = irq_desc + AIU_IRQ; + struct irq_desc *desc = irq_to_desc(AIU_IRQ); unsigned long flags; - if (current_cpu_data.cputype == CPU_VR4111 || - current_cpu_data.cputype == CPU_VR4121) { - spin_lock_irqsave(&desc->lock, flags); + if (current_cpu_type() == CPU_VR4111 || + current_cpu_type() == CPU_VR4121) { + raw_spin_lock_irqsave(&desc->lock, flags); icu1_set(MAIUINTREG, mask); - spin_unlock_irqrestore(&desc->lock, flags); + raw_spin_unlock_irqrestore(&desc->lock, flags); } } @@ -197,14 +199,14 @@ EXPORT_SYMBOL(vr41xx_enable_aiuint); void vr41xx_disable_aiuint(uint16_t mask) { - irq_desc_t *desc = irq_desc + AIU_IRQ; + struct irq_desc *desc = irq_to_desc(AIU_IRQ); unsigned long flags; - if (current_cpu_data.cputype == CPU_VR4111 || - current_cpu_data.cputype == CPU_VR4121) { - spin_lock_irqsave(&desc->lock, flags); + if (current_cpu_type() == CPU_VR4111 || + current_cpu_type() == CPU_VR4121) { + raw_spin_lock_irqsave(&desc->lock, flags); icu1_clear(MAIUINTREG, mask); - spin_unlock_irqrestore(&desc->lock, flags); + raw_spin_unlock_irqrestore(&desc->lock, flags); } } @@ -212,14 +214,14 @@ EXPORT_SYMBOL(vr41xx_disable_aiuint); void vr41xx_enable_kiuint(uint16_t mask) { - irq_desc_t *desc = irq_desc + KIU_IRQ; + struct irq_desc *desc = irq_to_desc(KIU_IRQ); unsigned long flags; - if (current_cpu_data.cputype == CPU_VR4111 || - current_cpu_data.cputype == CPU_VR4121) { - spin_lock_irqsave(&desc->lock, flags); + if (current_cpu_type() == CPU_VR4111 || + current_cpu_type() == CPU_VR4121) { + raw_spin_lock_irqsave(&desc->lock, flags); icu1_set(MKIUINTREG, mask); - spin_unlock_irqrestore(&desc->lock, flags); + raw_spin_unlock_irqrestore(&desc->lock, flags); } } @@ -227,78 +229,102 @@ EXPORT_SYMBOL(vr41xx_enable_kiuint); void vr41xx_disable_kiuint(uint16_t mask) { - irq_desc_t *desc = irq_desc + KIU_IRQ; + struct irq_desc *desc = irq_to_desc(KIU_IRQ); unsigned long flags; - if (current_cpu_data.cputype == CPU_VR4111 || - current_cpu_data.cputype == CPU_VR4121) { - spin_lock_irqsave(&desc->lock, flags); + if (current_cpu_type() == CPU_VR4111 || + current_cpu_type() == CPU_VR4121) { + raw_spin_lock_irqsave(&desc->lock, flags); icu1_clear(MKIUINTREG, mask); - spin_unlock_irqrestore(&desc->lock, flags); + raw_spin_unlock_irqrestore(&desc->lock, flags); } } EXPORT_SYMBOL(vr41xx_disable_kiuint); +void vr41xx_enable_macint(uint16_t mask) +{ + struct irq_desc *desc = irq_to_desc(ETHERNET_IRQ); + unsigned long flags; + + raw_spin_lock_irqsave(&desc->lock, flags); + icu1_set(MMACINTREG, mask); + raw_spin_unlock_irqrestore(&desc->lock, flags); +} + +EXPORT_SYMBOL(vr41xx_enable_macint); + +void vr41xx_disable_macint(uint16_t mask) +{ + struct irq_desc *desc = irq_to_desc(ETHERNET_IRQ); + unsigned long flags; + + raw_spin_lock_irqsave(&desc->lock, flags); + icu1_clear(MMACINTREG, mask); + raw_spin_unlock_irqrestore(&desc->lock, flags); +} + +EXPORT_SYMBOL(vr41xx_disable_macint); + void vr41xx_enable_dsiuint(uint16_t mask) { - irq_desc_t *desc = irq_desc + DSIU_IRQ; + struct irq_desc *desc = irq_to_desc(DSIU_IRQ); unsigned long flags; - spin_lock_irqsave(&desc->lock, flags); + raw_spin_lock_irqsave(&desc->lock, flags); icu1_set(MDSIUINTREG, mask); - spin_unlock_irqrestore(&desc->lock, flags); + raw_spin_unlock_irqrestore(&desc->lock, flags); } EXPORT_SYMBOL(vr41xx_enable_dsiuint); void vr41xx_disable_dsiuint(uint16_t mask) { - irq_desc_t *desc = irq_desc + DSIU_IRQ; + struct irq_desc *desc = irq_to_desc(DSIU_IRQ); unsigned long flags; - spin_lock_irqsave(&desc->lock, flags); + raw_spin_lock_irqsave(&desc->lock, flags); icu1_clear(MDSIUINTREG, mask); - spin_unlock_irqrestore(&desc->lock, flags); + raw_spin_unlock_irqrestore(&desc->lock, flags); } EXPORT_SYMBOL(vr41xx_disable_dsiuint); void vr41xx_enable_firint(uint16_t mask) { - irq_desc_t *desc = irq_desc + FIR_IRQ; + struct irq_desc *desc = irq_to_desc(FIR_IRQ); unsigned long flags; - spin_lock_irqsave(&desc->lock, flags); + raw_spin_lock_irqsave(&desc->lock, flags); icu2_set(MFIRINTREG, mask); - spin_unlock_irqrestore(&desc->lock, flags); + raw_spin_unlock_irqrestore(&desc->lock, flags); } EXPORT_SYMBOL(vr41xx_enable_firint); void vr41xx_disable_firint(uint16_t mask) { - irq_desc_t *desc = irq_desc + FIR_IRQ; + struct irq_desc *desc = irq_to_desc(FIR_IRQ); unsigned long flags; - spin_lock_irqsave(&desc->lock, flags); + raw_spin_lock_irqsave(&desc->lock, flags); icu2_clear(MFIRINTREG, mask); - spin_unlock_irqrestore(&desc->lock, flags); + raw_spin_unlock_irqrestore(&desc->lock, flags); } EXPORT_SYMBOL(vr41xx_disable_firint); void vr41xx_enable_pciint(void) { - irq_desc_t *desc = irq_desc + PCI_IRQ; + struct irq_desc *desc = irq_to_desc(PCI_IRQ); unsigned long flags; - if (current_cpu_data.cputype == CPU_VR4122 || - current_cpu_data.cputype == CPU_VR4131 || - current_cpu_data.cputype == CPU_VR4133) { - spin_lock_irqsave(&desc->lock, flags); + if (current_cpu_type() == CPU_VR4122 || + current_cpu_type() == CPU_VR4131 || + current_cpu_type() == CPU_VR4133) { + raw_spin_lock_irqsave(&desc->lock, flags); icu2_write(MPCIINTREG, PCIINT0); - spin_unlock_irqrestore(&desc->lock, flags); + raw_spin_unlock_irqrestore(&desc->lock, flags); } } @@ -306,15 +332,15 @@ EXPORT_SYMBOL(vr41xx_enable_pciint); void vr41xx_disable_pciint(void) { - irq_desc_t *desc = irq_desc + PCI_IRQ; + struct irq_desc *desc = irq_to_desc(PCI_IRQ); unsigned long flags; - if (current_cpu_data.cputype == CPU_VR4122 || - current_cpu_data.cputype == CPU_VR4131 || - current_cpu_data.cputype == CPU_VR4133) { - spin_lock_irqsave(&desc->lock, flags); + if (current_cpu_type() == CPU_VR4122 || + current_cpu_type() == CPU_VR4131 || + current_cpu_type() == CPU_VR4133) { + raw_spin_lock_irqsave(&desc->lock, flags); icu2_write(MPCIINTREG, 0); - spin_unlock_irqrestore(&desc->lock, flags); + raw_spin_unlock_irqrestore(&desc->lock, flags); } } @@ -322,15 +348,15 @@ EXPORT_SYMBOL(vr41xx_disable_pciint); void vr41xx_enable_scuint(void) { - irq_desc_t *desc = irq_desc + SCU_IRQ; + struct irq_desc *desc = irq_to_desc(SCU_IRQ); unsigned long flags; - if (current_cpu_data.cputype == CPU_VR4122 || - current_cpu_data.cputype == CPU_VR4131 || - current_cpu_data.cputype == CPU_VR4133) { - spin_lock_irqsave(&desc->lock, flags); + if (current_cpu_type() == CPU_VR4122 || + current_cpu_type() == CPU_VR4131 || + current_cpu_type() == CPU_VR4133) { + raw_spin_lock_irqsave(&desc->lock, flags); icu2_write(MSCUINTREG, SCUINT0); - spin_unlock_irqrestore(&desc->lock, flags); + raw_spin_unlock_irqrestore(&desc->lock, flags); } } @@ -338,15 +364,15 @@ EXPORT_SYMBOL(vr41xx_enable_scuint); void vr41xx_disable_scuint(void) { - irq_desc_t *desc = irq_desc + SCU_IRQ; + struct irq_desc *desc = irq_to_desc(SCU_IRQ); unsigned long flags; - if (current_cpu_data.cputype == CPU_VR4122 || - current_cpu_data.cputype == CPU_VR4131 || - current_cpu_data.cputype == CPU_VR4133) { - spin_lock_irqsave(&desc->lock, flags); + if (current_cpu_type() == CPU_VR4122 || + current_cpu_type() == CPU_VR4131 || + current_cpu_type() == CPU_VR4133) { + raw_spin_lock_irqsave(&desc->lock, flags); icu2_write(MSCUINTREG, 0); - spin_unlock_irqrestore(&desc->lock, flags); + raw_spin_unlock_irqrestore(&desc->lock, flags); } } @@ -354,15 +380,15 @@ EXPORT_SYMBOL(vr41xx_disable_scuint); void vr41xx_enable_csiint(uint16_t mask) { - irq_desc_t *desc = irq_desc + CSI_IRQ; + struct irq_desc *desc = irq_to_desc(CSI_IRQ); unsigned long flags; - if (current_cpu_data.cputype == CPU_VR4122 || - current_cpu_data.cputype == CPU_VR4131 || - current_cpu_data.cputype == CPU_VR4133) { - spin_lock_irqsave(&desc->lock, flags); + if (current_cpu_type() == CPU_VR4122 || + current_cpu_type() == CPU_VR4131 || + current_cpu_type() == CPU_VR4133) { + raw_spin_lock_irqsave(&desc->lock, flags); icu2_set(MCSIINTREG, mask); - spin_unlock_irqrestore(&desc->lock, flags); + raw_spin_unlock_irqrestore(&desc->lock, flags); } } @@ -370,15 +396,15 @@ EXPORT_SYMBOL(vr41xx_enable_csiint); void vr41xx_disable_csiint(uint16_t mask) { - irq_desc_t *desc = irq_desc + CSI_IRQ; + struct irq_desc *desc = irq_to_desc(CSI_IRQ); unsigned long flags; - if (current_cpu_data.cputype == CPU_VR4122 || - current_cpu_data.cputype == CPU_VR4131 || - current_cpu_data.cputype == CPU_VR4133) { - spin_lock_irqsave(&desc->lock, flags); + if (current_cpu_type() == CPU_VR4122 || + current_cpu_type() == CPU_VR4131 || + current_cpu_type() == CPU_VR4133) { + raw_spin_lock_irqsave(&desc->lock, flags); icu2_clear(MCSIINTREG, mask); - spin_unlock_irqrestore(&desc->lock, flags); + raw_spin_unlock_irqrestore(&desc->lock, flags); } } @@ -386,15 +412,15 @@ EXPORT_SYMBOL(vr41xx_disable_csiint); void vr41xx_enable_bcuint(void) { - irq_desc_t *desc = irq_desc + BCU_IRQ; + struct irq_desc *desc = irq_to_desc(BCU_IRQ); unsigned long flags; - if (current_cpu_data.cputype == CPU_VR4122 || - current_cpu_data.cputype == CPU_VR4131 || - current_cpu_data.cputype == CPU_VR4133) { - spin_lock_irqsave(&desc->lock, flags); + if (current_cpu_type() == CPU_VR4122 || + current_cpu_type() == CPU_VR4131 || + current_cpu_type() == CPU_VR4133) { + raw_spin_lock_irqsave(&desc->lock, flags); icu2_write(MBCUINTREG, BCUINTR); - spin_unlock_irqrestore(&desc->lock, flags); + raw_spin_unlock_irqrestore(&desc->lock, flags); } } @@ -402,101 +428,61 @@ EXPORT_SYMBOL(vr41xx_enable_bcuint); void vr41xx_disable_bcuint(void) { - irq_desc_t *desc = irq_desc + BCU_IRQ; + struct irq_desc *desc = irq_to_desc(BCU_IRQ); unsigned long flags; - if (current_cpu_data.cputype == CPU_VR4122 || - current_cpu_data.cputype == CPU_VR4131 || - current_cpu_data.cputype == CPU_VR4133) { - spin_lock_irqsave(&desc->lock, flags); + if (current_cpu_type() == CPU_VR4122 || + current_cpu_type() == CPU_VR4131 || + current_cpu_type() == CPU_VR4133) { + raw_spin_lock_irqsave(&desc->lock, flags); icu2_write(MBCUINTREG, 0); - spin_unlock_irqrestore(&desc->lock, flags); + raw_spin_unlock_irqrestore(&desc->lock, flags); } } EXPORT_SYMBOL(vr41xx_disable_bcuint); -static unsigned int startup_sysint1_irq(unsigned int irq) -{ - icu1_set(MSYSINT1REG, 1 << SYSINT1_IRQ_TO_PIN(irq)); - - return 0; /* never anything pending */ -} - -static void shutdown_sysint1_irq(unsigned int irq) +static void disable_sysint1_irq(struct irq_data *d) { - icu1_clear(MSYSINT1REG, 1 << SYSINT1_IRQ_TO_PIN(irq)); + icu1_clear(MSYSINT1REG, 1 << SYSINT1_IRQ_TO_PIN(d->irq)); } -static void enable_sysint1_irq(unsigned int irq) +static void enable_sysint1_irq(struct irq_data *d) { - icu1_set(MSYSINT1REG, 1 << SYSINT1_IRQ_TO_PIN(irq)); + icu1_set(MSYSINT1REG, 1 << SYSINT1_IRQ_TO_PIN(d->irq)); } -#define disable_sysint1_irq shutdown_sysint1_irq -#define ack_sysint1_irq shutdown_sysint1_irq - -static void end_sysint1_irq(unsigned int irq) -{ - if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) - icu1_set(MSYSINT1REG, 1 << SYSINT1_IRQ_TO_PIN(irq)); -} - -static struct hw_interrupt_type sysint1_irq_type = { - .typename = "SYSINT1", - .startup = startup_sysint1_irq, - .shutdown = shutdown_sysint1_irq, - .enable = enable_sysint1_irq, - .disable = disable_sysint1_irq, - .ack = ack_sysint1_irq, - .end = end_sysint1_irq, +static struct irq_chip sysint1_irq_type = { + .name = "SYSINT1", + .irq_mask = disable_sysint1_irq, + .irq_unmask = enable_sysint1_irq, }; -static unsigned int startup_sysint2_irq(unsigned int irq) -{ - icu2_set(MSYSINT2REG, 1 << SYSINT2_IRQ_TO_PIN(irq)); - - return 0; /* never anything pending */ -} - -static void shutdown_sysint2_irq(unsigned int irq) +static void disable_sysint2_irq(struct irq_data *d) { - icu2_clear(MSYSINT2REG, 1 << SYSINT2_IRQ_TO_PIN(irq)); + icu2_clear(MSYSINT2REG, 1 << SYSINT2_IRQ_TO_PIN(d->irq)); } -static void enable_sysint2_irq(unsigned int irq) -{ - icu2_set(MSYSINT2REG, 1 << SYSINT2_IRQ_TO_PIN(irq)); -} - -#define disable_sysint2_irq shutdown_sysint2_irq -#define ack_sysint2_irq shutdown_sysint2_irq - -static void end_sysint2_irq(unsigned int irq) +static void enable_sysint2_irq(struct irq_data *d) { - if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) - icu2_set(MSYSINT2REG, 1 << SYSINT2_IRQ_TO_PIN(irq)); + icu2_set(MSYSINT2REG, 1 << SYSINT2_IRQ_TO_PIN(d->irq)); } -static struct hw_interrupt_type sysint2_irq_type = { - .typename = "SYSINT2", - .startup = startup_sysint2_irq, - .shutdown = shutdown_sysint2_irq, - .enable = enable_sysint2_irq, - .disable = disable_sysint2_irq, - .ack = ack_sysint2_irq, - .end = end_sysint2_irq, +static struct irq_chip sysint2_irq_type = { + .name = "SYSINT2", + .irq_mask = disable_sysint2_irq, + .irq_unmask = enable_sysint2_irq, }; static inline int set_sysint1_assign(unsigned int irq, unsigned char assign) { - irq_desc_t *desc = irq_desc + irq; + struct irq_desc *desc = irq_to_desc(irq); uint16_t intassign0, intassign1; unsigned int pin; pin = SYSINT1_IRQ_TO_PIN(irq); - spin_lock_irq(&desc->lock); + raw_spin_lock_irq(&desc->lock); intassign0 = icu1_read(INTASSIGN0); intassign1 = icu1_read(INTASSIGN1); @@ -535,6 +521,7 @@ static inline int set_sysint1_assign(unsigned int irq, unsigned char assign) intassign1 |= (uint16_t)assign << 9; break; default: + raw_spin_unlock_irq(&desc->lock); return -EINVAL; } @@ -542,20 +529,20 @@ static inline int set_sysint1_assign(unsigned int irq, unsigned char assign) icu1_write(INTASSIGN0, intassign0); icu1_write(INTASSIGN1, intassign1); - spin_unlock_irq(&desc->lock); + raw_spin_unlock_irq(&desc->lock); return 0; } static inline int set_sysint2_assign(unsigned int irq, unsigned char assign) { - irq_desc_t *desc = irq_desc + irq; + struct irq_desc *desc = irq_to_desc(irq); uint16_t intassign2, intassign3; unsigned int pin; pin = SYSINT2_IRQ_TO_PIN(irq); - spin_lock_irq(&desc->lock); + raw_spin_lock_irq(&desc->lock); intassign2 = icu1_read(INTASSIGN2); intassign3 = icu1_read(INTASSIGN3); @@ -602,6 +589,7 @@ static inline int set_sysint2_assign(unsigned int irq, unsigned char assign) intassign3 |= (uint16_t)assign << 12; break; default: + raw_spin_unlock_irq(&desc->lock); return -EINVAL; } @@ -609,7 +597,7 @@ static inline int set_sysint2_assign(unsigned int irq, unsigned char assign) icu1_write(INTASSIGN2, intassign2); icu1_write(INTASSIGN3, intassign3); - spin_unlock_irq(&desc->lock); + raw_spin_unlock_irq(&desc->lock); return 0; } @@ -618,7 +606,7 @@ int vr41xx_set_intassign(unsigned int irq, unsigned char intassign) { int retval = -EINVAL; - if (current_cpu_data.cputype != CPU_VR4133) + if (current_cpu_type() != CPU_VR4133) return -EINVAL; if (intassign > INTASSIGN_MAX) @@ -634,7 +622,7 @@ int vr41xx_set_intassign(unsigned int irq, unsigned char intassign) EXPORT_SYMBOL(vr41xx_set_intassign); -static int icu_get_irq(unsigned int irq, struct pt_regs *regs) +static int icu_get_irq(unsigned int irq) { uint16_t pend1, pend2; uint16_t mask1, mask2; @@ -675,7 +663,7 @@ static int __init vr41xx_icu_init(void) unsigned long icu1_start, icu2_start; int i; - switch (current_cpu_data.cputype) { + switch (current_cpu_type()) { case CPU_VR4111: case CPU_VR4121: icu1_start = ICU1_TYPE1_BASE; @@ -722,10 +710,12 @@ static int __init vr41xx_icu_init(void) icu2_write(MGIUINTHREG, 0xffff); for (i = SYSINT1_IRQ_BASE; i <= SYSINT1_IRQ_LAST; i++) - irq_desc[i].handler = &sysint1_irq_type; + irq_set_chip_and_handler(i, &sysint1_irq_type, + handle_level_irq); for (i = SYSINT2_IRQ_BASE; i <= SYSINT2_IRQ_LAST; i++) - irq_desc[i].handler = &sysint2_irq_type; + irq_set_chip_and_handler(i, &sysint2_irq_type, + handle_level_irq); cascade_irq(INT0_IRQ, icu_get_irq); cascade_irq(INT1_IRQ, icu_get_irq); diff --git a/arch/mips/vr41xx/common/init.c b/arch/mips/vr41xx/common/init.c index 707bd0933ee..23916321cc1 100644 --- a/arch/mips/vr41xx/common/init.c +++ b/arch/mips/vr41xx/common/init.c @@ -1,7 +1,7 @@ /* * init.c, Common initialization routines for NEC VR4100 series. * - * Copyright (C) 2003-2005 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> + * Copyright (C) 2003-2009 Yoichi Yuasa <yuasa@linux-mips.org> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -24,6 +24,7 @@ #include <asm/bootinfo.h> #include <asm/time.h> +#include <asm/vr41xx/irq.h> #include <asm/vr41xx/vr41xx.h> #define IO_MEM_RESOURCE_START 0UL @@ -35,10 +36,12 @@ static void __init iomem_resource_init(void) iomem_resource.end = IO_MEM_RESOURCE_END; } -static void __init setup_timer_frequency(void) +void __init plat_time_init(void) { unsigned long tclock; + vr41xx_calculate_clock_frequency(); + tclock = vr41xx_get_tclock_frequency(); if (current_cpu_data.processor_id == PRID_VR4131_REV2_0 || current_cpu_data.processor_id == PRID_VR4131_REV2_1) @@ -47,23 +50,11 @@ static void __init setup_timer_frequency(void) mips_hpt_frequency = tclock / 4; } -static void __init setup_timer_irq(struct irqaction *irq) -{ - setup_irq(TIMER_IRQ, irq); -} - -static void __init timer_init(void) +void __init plat_mem_setup(void) { - board_time_init = setup_timer_frequency; - board_timer_setup = setup_timer_irq; -} - -void __init plat_setup(void) -{ - vr41xx_calculate_clock_frequency(); - - timer_init(); iomem_resource_init(); + + vr41xx_siu_setup(); } void __init prom_init(void) @@ -75,13 +66,12 @@ void __init prom_init(void) argv = (char **)fw_arg1; for (i = 1; i < argc; i++) { - strcat(arcs_cmdline, argv[i]); + strlcat(arcs_cmdline, argv[i], COMMAND_LINE_SIZE); if (i < (argc - 1)) - strcat(arcs_cmdline, " "); + strlcat(arcs_cmdline, " ", COMMAND_LINE_SIZE); } } -unsigned long __init prom_free_prom_memory (void) +void __init prom_free_prom_memory(void) { - return 0UL; } diff --git a/arch/mips/vr41xx/common/int-handler.S b/arch/mips/vr41xx/common/int-handler.S deleted file mode 100644 index 2b6043f16d0..00000000000 --- a/arch/mips/vr41xx/common/int-handler.S +++ /dev/null @@ -1,114 +0,0 @@ -/* - * FILE NAME - * arch/mips/vr41xx/common/int-handler.S - * - * BRIEF MODULE DESCRIPTION - * Interrupt dispatcher for the NEC VR4100 series. - * - * Author: Yoichi Yuasa - * yyuasa@mvista.com or source@mvista.com - * - * Copyright 2001 MontaVista Software Inc. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS - * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE - * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 675 Mass Ave, Cambridge, MA 02139, USA. - */ -/* - * Changes: - * MontaVista Software Inc. <yyuasa@mvista.com> or <source@mvista.com> - * - New creation, NEC VR4100 series are supported. - * - * Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> - * - Coped with INTASSIGN of NEC VR4133. - */ -#include <asm/asm.h> -#include <asm/regdef.h> -#include <asm/mipsregs.h> -#include <asm/stackframe.h> - - .text - .set noreorder - - .align 5 - NESTED(vr41xx_handle_interrupt, PT_SIZE, ra) - .set noat - SAVE_ALL - CLI - .set at - .set noreorder - - /* - * Get the pending interrupts - */ - mfc0 t0, CP0_CAUSE - mfc0 t1, CP0_STATUS - andi t0, 0xff00 - and t0, t0, t1 - - andi t1, t0, CAUSEF_IP7 # MIPS timer interrupt - bnez t1, handle_irq - li a0, 7 - - andi t1, t0, 0x7800 # check for Int1-4 - beqz t1, 1f - - andi t1, t0, CAUSEF_IP3 # check for Int1 - bnez t1, handle_int - li a0, 3 - - andi t1, t0, CAUSEF_IP4 # check for Int2 - bnez t1, handle_int - li a0, 4 - - andi t1, t0, CAUSEF_IP5 # check for Int3 - bnez t1, handle_int - li a0, 5 - - andi t1, t0, CAUSEF_IP6 # check for Int4 - bnez t1, handle_int - li a0, 6 - -1: - andi t1, t0, CAUSEF_IP2 # check for Int0 - bnez t1, handle_int - li a0, 2 - - andi t1, t0, CAUSEF_IP0 # check for IP0 - bnez t1, handle_irq - li a0, 0 - - andi t1, t0, CAUSEF_IP1 # check for IP1 - bnez t1, handle_irq - li a0, 1 - - j spurious_interrupt - nop - -handle_int: - jal irq_dispatch - move a1, sp - j ret_from_irq - nop - -handle_irq: - jal do_IRQ - move a1, sp - j ret_from_irq - END(vr41xx_handle_interrupt) diff --git a/arch/mips/vr41xx/common/irq.c b/arch/mips/vr41xx/common/irq.c index 61aa264275f..ae0e4ee6c61 100644 --- a/arch/mips/vr41xx/common/irq.c +++ b/arch/mips/vr41xx/common/irq.c @@ -1,7 +1,7 @@ /* * Interrupt handing routines for NEC VR4100 series. * - * Copyright (C) 2005 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> + * Copyright (C) 2005-2007 Yoichi Yuasa <yuasa@linux-mips.org> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -19,24 +19,24 @@ */ #include <linux/interrupt.h> #include <linux/module.h> +#include <linux/irq.h> #include <asm/irq_cpu.h> -#include <asm/system.h> -#include <asm/vr41xx/vr41xx.h> +#include <asm/vr41xx/irq.h> typedef struct irq_cascade { - int (*get_irq)(unsigned int, struct pt_regs *); + int (*get_irq)(unsigned int); } irq_cascade_t; static irq_cascade_t irq_cascade[NR_IRQS] __cacheline_aligned; static struct irqaction cascade_irqaction = { .handler = no_action, - .mask = CPU_MASK_NONE, .name = "cascade", + .flags = IRQF_NO_THREAD, }; -int cascade_irq(unsigned int irq, int (*get_irq)(unsigned int, struct pt_regs *)) +int cascade_irq(unsigned int irq, int (*get_irq)(unsigned int)) { int retval = 0; @@ -59,10 +59,9 @@ int cascade_irq(unsigned int irq, int (*get_irq)(unsigned int, struct pt_regs *) EXPORT_SYMBOL_GPL(cascade_irq); -asmlinkage void irq_dispatch(unsigned int irq, struct pt_regs *regs) +static void irq_dispatch(unsigned int irq) { irq_cascade_t *cascade; - irq_desc_t *desc; if (irq >= NR_IRQS) { atomic_inc(&irq_err_count); @@ -71,24 +70,55 @@ asmlinkage void irq_dispatch(unsigned int irq, struct pt_regs *regs) cascade = irq_cascade + irq; if (cascade->get_irq != NULL) { - unsigned int source_irq = irq; - desc = irq_desc + source_irq; - desc->handler->ack(source_irq); - irq = cascade->get_irq(irq, regs); - if (irq < 0) + struct irq_desc *desc = irq_to_desc(irq); + struct irq_data *idata = irq_desc_get_irq_data(desc); + struct irq_chip *chip = irq_desc_get_chip(desc); + int ret; + + if (chip->irq_mask_ack) + chip->irq_mask_ack(idata); + else { + chip->irq_mask(idata); + chip->irq_ack(idata); + } + ret = cascade->get_irq(irq); + irq = ret; + if (ret < 0) atomic_inc(&irq_err_count); else - irq_dispatch(irq, regs); - desc->handler->end(source_irq); + irq_dispatch(irq); + if (!irqd_irq_disabled(idata) && chip->irq_unmask) + chip->irq_unmask(idata); } else - do_IRQ(irq, regs); + do_IRQ(irq); } -extern asmlinkage void vr41xx_handle_interrupt(void); +asmlinkage void plat_irq_dispatch(void) +{ + unsigned int pending = read_c0_cause() & read_c0_status() & ST0_IM; + + if (pending & CAUSEF_IP7) + do_IRQ(TIMER_IRQ); + else if (pending & 0x7800) { + if (pending & CAUSEF_IP3) + irq_dispatch(INT1_IRQ); + else if (pending & CAUSEF_IP4) + irq_dispatch(INT2_IRQ); + else if (pending & CAUSEF_IP5) + irq_dispatch(INT3_IRQ); + else if (pending & CAUSEF_IP6) + irq_dispatch(INT4_IRQ); + } else if (pending & CAUSEF_IP2) + irq_dispatch(INT0_IRQ); + else if (pending & CAUSEF_IP0) + do_IRQ(MIPS_SOFTINT0_IRQ); + else if (pending & CAUSEF_IP1) + do_IRQ(MIPS_SOFTINT1_IRQ); + else + spurious_interrupt(); +} void __init arch_init_irq(void) { - mips_cpu_irq_init(MIPS_CPU_IRQ_BASE); - - set_except_vector(0, vr41xx_handle_interrupt); + mips_cpu_irq_init(); } diff --git a/arch/mips/vr41xx/common/pmu.c b/arch/mips/vr41xx/common/pmu.c index 02bf4f7d06b..d7f755833c3 100644 --- a/arch/mips/vr41xx/common/pmu.c +++ b/arch/mips/vr41xx/common/pmu.c @@ -1,7 +1,7 @@ /* * pmu.c, Power Management Unit routines for NEC VR4100 series. * - * Copyright (C) 2003-2005 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> + * Copyright (C) 2003-2007 Yoichi Yuasa <yuasa@linux-mips.org> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -21,13 +21,16 @@ #include <linux/init.h> #include <linux/ioport.h> #include <linux/kernel.h> -#include <linux/smp.h> +#include <linux/pm.h> +#include <linux/sched.h> #include <linux/types.h> +#include <asm/cacheflush.h> #include <asm/cpu.h> +#include <asm/idle.h> #include <asm/io.h> +#include <asm/processor.h> #include <asm/reboot.h> -#include <asm/system.h> #define PMU_TYPE1_BASE 0x0b0000a0UL #define PMU_TYPE1_SIZE 0x0eUL @@ -43,11 +46,23 @@ static void __iomem *pmu_base; #define pmu_read(offset) readw(pmu_base + (offset)) #define pmu_write(offset, value) writew((value), pmu_base + (offset)) +static void vr41xx_cpu_wait(void) +{ + local_irq_disable(); + if (!need_resched()) + /* + * "standby" sets IE bit of the CP0_STATUS to 1. + */ + __asm__("standby;\n"); + else + local_irq_enable(); +} + static inline void software_reset(void) { uint16_t pmucnt2; - switch (current_cpu_data.cputype) { + switch (current_cpu_type()) { case CPU_VR4122: case CPU_VR4131: case CPU_VR4133: @@ -56,6 +71,11 @@ static inline void software_reset(void) pmu_write(PMUCNT2REG, pmucnt2); break; default: + set_c0_status(ST0_BEV | ST0_ERL); + change_c0_config(CONF_CM_CMASK, CONF_CM_UNCACHED); + flush_cache_all(); + write_c0_wired(0); + __asm__("jr %0"::"r"(0xbfc00000)); break; } } @@ -64,7 +84,6 @@ static void vr41xx_restart(char *command) { local_irq_disable(); software_reset(); - printk(KERN_NOTICE "\nYou can reset your system\n"); while (1) ; } @@ -72,21 +91,14 @@ static void vr41xx_halt(void) { local_irq_disable(); printk(KERN_NOTICE "\nYou can turn off the power supply\n"); - while (1) ; -} - -static void vr41xx_power_off(void) -{ - local_irq_disable(); - printk(KERN_NOTICE "\nYou can turn off the power supply\n"); - while (1) ; + __asm__("hibernate;\n"); } static int __init vr41xx_pmu_init(void) { unsigned long start, size; - switch (current_cpu_data.cputype) { + switch (current_cpu_type()) { case CPU_VR4111: case CPU_VR4121: start = PMU_TYPE1_BASE; @@ -112,9 +124,10 @@ static int __init vr41xx_pmu_init(void) return -EBUSY; } + cpu_wait = vr41xx_cpu_wait; _machine_restart = vr41xx_restart; _machine_halt = vr41xx_halt; - _machine_power_off = vr41xx_power_off; + pm_power_off = vr41xx_halt; return 0; } diff --git a/arch/mips/vr41xx/common/rtc.c b/arch/mips/vr41xx/common/rtc.c new file mode 100644 index 00000000000..c1e3d200920 --- /dev/null +++ b/arch/mips/vr41xx/common/rtc.c @@ -0,0 +1,118 @@ +/* + * NEC VR4100 series RTC platform device. + * + * Copyright (C) 2007 Yoichi Yuasa <yuasa@linux-mips.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include <linux/errno.h> +#include <linux/init.h> +#include <linux/smp.h> +#include <linux/ioport.h> +#include <linux/platform_device.h> + +#include <asm/cpu.h> +#include <asm/vr41xx/irq.h> + +static struct resource rtc_type1_resource[] __initdata = { + { + .start = 0x0b0000c0, + .end = 0x0b0000df, + .flags = IORESOURCE_MEM, + }, + { + .start = 0x0b0001c0, + .end = 0x0b0001df, + .flags = IORESOURCE_MEM, + }, + { + .start = ELAPSEDTIME_IRQ, + .end = ELAPSEDTIME_IRQ, + .flags = IORESOURCE_IRQ, + }, + { + .start = RTCLONG1_IRQ, + .end = RTCLONG1_IRQ, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct resource rtc_type2_resource[] __initdata = { + { + .start = 0x0f000100, + .end = 0x0f00011f, + .flags = IORESOURCE_MEM, + }, + { + .start = 0x0f000120, + .end = 0x0f00013f, + .flags = IORESOURCE_MEM, + }, + { + .start = ELAPSEDTIME_IRQ, + .end = ELAPSEDTIME_IRQ, + .flags = IORESOURCE_IRQ, + }, + { + .start = RTCLONG1_IRQ, + .end = RTCLONG1_IRQ, + .flags = IORESOURCE_IRQ, + }, +}; + +static int __init vr41xx_rtc_add(void) +{ + struct platform_device *pdev; + struct resource *res; + unsigned int num; + int retval; + + pdev = platform_device_alloc("RTC", -1); + if (!pdev) + return -ENOMEM; + + switch (current_cpu_type()) { + case CPU_VR4111: + case CPU_VR4121: + res = rtc_type1_resource; + num = ARRAY_SIZE(rtc_type1_resource); + break; + case CPU_VR4122: + case CPU_VR4131: + case CPU_VR4133: + res = rtc_type2_resource; + num = ARRAY_SIZE(rtc_type2_resource); + break; + default: + retval = -ENODEV; + goto err_free_device; + } + + retval = platform_device_add_resources(pdev, res, num); + if (retval) + goto err_free_device; + + retval = platform_device_add(pdev); + if (retval) + goto err_free_device; + + return 0; + +err_free_device: + platform_device_put(pdev); + + return retval; +} +device_initcall(vr41xx_rtc_add); diff --git a/arch/mips/vr41xx/common/siu.c b/arch/mips/vr41xx/common/siu.c new file mode 100644 index 00000000000..bbd45d2559d --- /dev/null +++ b/arch/mips/vr41xx/common/siu.c @@ -0,0 +1,155 @@ +/* + * NEC VR4100 series SIU platform device. + * + * Copyright (C) 2007-2008 Yoichi Yuasa <yuasa@linux-mips.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include <linux/errno.h> +#include <linux/init.h> +#include <linux/ioport.h> +#include <linux/platform_device.h> +#include <linux/serial_core.h> +#include <linux/irq.h> + +#include <asm/cpu.h> +#include <asm/vr41xx/siu.h> + +static unsigned int siu_type1_ports[SIU_PORTS_MAX] __initdata = { + PORT_VR41XX_SIU, + PORT_UNKNOWN, +}; + +static struct resource siu_type1_resource[] __initdata = { + { + .start = 0x0c000000, + .end = 0x0c00000a, + .flags = IORESOURCE_MEM, + }, + { + .start = SIU_IRQ, + .end = SIU_IRQ, + .flags = IORESOURCE_IRQ, + }, +}; + +static unsigned int siu_type2_ports[SIU_PORTS_MAX] __initdata = { + PORT_VR41XX_SIU, + PORT_VR41XX_DSIU, +}; + +static struct resource siu_type2_resource[] __initdata = { + { + .start = 0x0f000800, + .end = 0x0f00080a, + .flags = IORESOURCE_MEM, + }, + { + .start = 0x0f000820, + .end = 0x0f000829, + .flags = IORESOURCE_MEM, + }, + { + .start = SIU_IRQ, + .end = SIU_IRQ, + .flags = IORESOURCE_IRQ, + }, + { + .start = DSIU_IRQ, + .end = DSIU_IRQ, + .flags = IORESOURCE_IRQ, + }, +}; + +static int __init vr41xx_siu_add(void) +{ + struct platform_device *pdev; + struct resource *res; + unsigned int num; + int retval; + + pdev = platform_device_alloc("SIU", -1); + if (!pdev) + return -ENOMEM; + + switch (current_cpu_type()) { + case CPU_VR4111: + case CPU_VR4121: + pdev->dev.platform_data = siu_type1_ports; + res = siu_type1_resource; + num = ARRAY_SIZE(siu_type1_resource); + break; + case CPU_VR4122: + case CPU_VR4131: + case CPU_VR4133: + pdev->dev.platform_data = siu_type2_ports; + res = siu_type2_resource; + num = ARRAY_SIZE(siu_type2_resource); + break; + default: + retval = -ENODEV; + goto err_free_device; + } + + retval = platform_device_add_resources(pdev, res, num); + if (retval) + goto err_free_device; + + retval = platform_device_add(pdev); + if (retval) + goto err_free_device; + + return 0; + +err_free_device: + platform_device_put(pdev); + + return retval; +} +device_initcall(vr41xx_siu_add); + +void __init vr41xx_siu_setup(void) +{ + struct uart_port port; + struct resource *res; + unsigned int *type; + int i; + + switch (current_cpu_type()) { + case CPU_VR4111: + case CPU_VR4121: + type = siu_type1_ports; + res = siu_type1_resource; + break; + case CPU_VR4122: + case CPU_VR4131: + case CPU_VR4133: + type = siu_type2_ports; + res = siu_type2_resource; + break; + default: + return; + } + + for (i = 0; i < SIU_PORTS_MAX; i++) { + port.line = i; + port.type = type[i]; + if (port.type == PORT_UNKNOWN) + break; + port.mapbase = res[i].start; + port.membase = (unsigned char __iomem *)KSEG1ADDR(res[i].start); + vr41xx_siu_early_setup(&port); + } +} diff --git a/arch/mips/vr41xx/common/type.c b/arch/mips/vr41xx/common/type.c index e0c1ac5e988..45836a92b7a 100644 --- a/arch/mips/vr41xx/common/type.c +++ b/arch/mips/vr41xx/common/type.c @@ -1,7 +1,7 @@ /* * type.c, System type for NEC VR4100 series. * - * Copyright (C) 2005 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> + * Copyright (C) 2005 Yoichi Yuasa <yuasa@linux-mips.org> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/arch/mips/vr41xx/common/vrc4173.c b/arch/mips/vr41xx/common/vrc4173.c deleted file mode 100644 index 3e31f8193d2..00000000000 --- a/arch/mips/vr41xx/common/vrc4173.c +++ /dev/null @@ -1,581 +0,0 @@ -/* - * vrc4173.c, NEC VRC4173 base driver for NEC VR4122/VR4131. - * - * Copyright (C) 2001-2003 MontaVista Software Inc. - * Author: Yoichi Yuasa <yyuasa@mvista.com, or source@mvista.com> - * Copyright (C) 2004 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> - * Copyright (C) 2005 Ralf Baechle (ralf@linux-mips.org) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -#include <linux/init.h> -#include <linux/module.h> -#include <linux/interrupt.h> -#include <linux/irq.h> -#include <linux/pci.h> -#include <linux/spinlock.h> -#include <linux/types.h> - -#include <asm/vr41xx/vr41xx.h> -#include <asm/vr41xx/vrc4173.h> - -MODULE_DESCRIPTION("NEC VRC4173 base driver for NEC VR4122/4131"); -MODULE_AUTHOR("Yoichi Yuasa <yyuasa@mvista.com>"); -MODULE_LICENSE("GPL"); - -#define VRC4173_CMUCLKMSK 0x040 - #define MSKPIU 0x0001 - #define MSKKIU 0x0002 - #define MSKAIU 0x0004 - #define MSKPS2CH1 0x0008 - #define MSKPS2CH2 0x0010 - #define MSKUSB 0x0020 - #define MSKCARD1 0x0040 - #define MSKCARD2 0x0080 - #define MSKAC97 0x0100 - #define MSK48MUSB 0x0400 - #define MSK48MPIN 0x0800 - #define MSK48MOSC 0x1000 -#define VRC4173_CMUSRST 0x042 - #define USBRST 0x0001 - #define CARD1RST 0x0002 - #define CARD2RST 0x0004 - #define AC97RST 0x0008 - -#define VRC4173_SYSINT1REG 0x060 -#define VRC4173_MSYSINT1REG 0x06c -#define VRC4173_MPIUINTREG 0x06e -#define VRC4173_MAIUINTREG 0x070 -#define VRC4173_MKIUINTREG 0x072 - -#define VRC4173_SELECTREG 0x09e - #define SEL3 0x0008 - #define SEL2 0x0004 - #define SEL1 0x0002 - #define SEL0 0x0001 - -static struct pci_device_id vrc4173_id_table[] __devinitdata = { - { .vendor = PCI_VENDOR_ID_NEC, - .device = PCI_DEVICE_ID_NEC_VRC4173, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, }, - { .vendor = 0, }, -}; - -unsigned long vrc4173_io_offset = 0; - -EXPORT_SYMBOL(vrc4173_io_offset); - -static int vrc4173_initialized; -static uint16_t vrc4173_cmuclkmsk; -static uint16_t vrc4173_selectreg; -static DEFINE_SPINLOCK(vrc4173_cmu_lock); -static DEFINE_SPINLOCK(vrc4173_giu_lock); - -static inline void set_cmusrst(uint16_t val) -{ - uint16_t cmusrst; - - cmusrst = vrc4173_inw(VRC4173_CMUSRST); - cmusrst |= val; - vrc4173_outw(cmusrst, VRC4173_CMUSRST); -} - -static inline void clear_cmusrst(uint16_t val) -{ - uint16_t cmusrst; - - cmusrst = vrc4173_inw(VRC4173_CMUSRST); - cmusrst &= ~val; - vrc4173_outw(cmusrst, VRC4173_CMUSRST); -} - -void vrc4173_supply_clock(vrc4173_clock_t clock) -{ - if (vrc4173_initialized) { - spin_lock_irq(&vrc4173_cmu_lock); - - switch (clock) { - case VRC4173_PIU_CLOCK: - vrc4173_cmuclkmsk |= MSKPIU; - break; - case VRC4173_KIU_CLOCK: - vrc4173_cmuclkmsk |= MSKKIU; - break; - case VRC4173_AIU_CLOCK: - vrc4173_cmuclkmsk |= MSKAIU; - break; - case VRC4173_PS2_CH1_CLOCK: - vrc4173_cmuclkmsk |= MSKPS2CH1; - break; - case VRC4173_PS2_CH2_CLOCK: - vrc4173_cmuclkmsk |= MSKPS2CH2; - break; - case VRC4173_USBU_PCI_CLOCK: - set_cmusrst(USBRST); - vrc4173_cmuclkmsk |= MSKUSB; - break; - case VRC4173_CARDU1_PCI_CLOCK: - set_cmusrst(CARD1RST); - vrc4173_cmuclkmsk |= MSKCARD1; - break; - case VRC4173_CARDU2_PCI_CLOCK: - set_cmusrst(CARD2RST); - vrc4173_cmuclkmsk |= MSKCARD2; - break; - case VRC4173_AC97U_PCI_CLOCK: - set_cmusrst(AC97RST); - vrc4173_cmuclkmsk |= MSKAC97; - break; - case VRC4173_USBU_48MHz_CLOCK: - set_cmusrst(USBRST); - vrc4173_cmuclkmsk |= MSK48MUSB; - break; - case VRC4173_EXT_48MHz_CLOCK: - if (vrc4173_cmuclkmsk & MSK48MOSC) - vrc4173_cmuclkmsk |= MSK48MPIN; - else - printk(KERN_WARNING - "vrc4173_supply_clock: " - "Please supply VRC4173_48MHz_CLOCK first " - "rather than VRC4173_EXT_48MHz_CLOCK.\n"); - break; - case VRC4173_48MHz_CLOCK: - vrc4173_cmuclkmsk |= MSK48MOSC; - break; - default: - printk(KERN_WARNING - "vrc4173_supply_clock: Invalid CLOCK value %u\n", clock); - break; - } - - vrc4173_outw(vrc4173_cmuclkmsk, VRC4173_CMUCLKMSK); - - switch (clock) { - case VRC4173_USBU_PCI_CLOCK: - case VRC4173_USBU_48MHz_CLOCK: - clear_cmusrst(USBRST); - break; - case VRC4173_CARDU1_PCI_CLOCK: - clear_cmusrst(CARD1RST); - break; - case VRC4173_CARDU2_PCI_CLOCK: - clear_cmusrst(CARD2RST); - break; - case VRC4173_AC97U_PCI_CLOCK: - clear_cmusrst(AC97RST); - break; - default: - break; - } - - spin_unlock_irq(&vrc4173_cmu_lock); - } -} - -EXPORT_SYMBOL(vrc4173_supply_clock); - -void vrc4173_mask_clock(vrc4173_clock_t clock) -{ - if (vrc4173_initialized) { - spin_lock_irq(&vrc4173_cmu_lock); - - switch (clock) { - case VRC4173_PIU_CLOCK: - vrc4173_cmuclkmsk &= ~MSKPIU; - break; - case VRC4173_KIU_CLOCK: - vrc4173_cmuclkmsk &= ~MSKKIU; - break; - case VRC4173_AIU_CLOCK: - vrc4173_cmuclkmsk &= ~MSKAIU; - break; - case VRC4173_PS2_CH1_CLOCK: - vrc4173_cmuclkmsk &= ~MSKPS2CH1; - break; - case VRC4173_PS2_CH2_CLOCK: - vrc4173_cmuclkmsk &= ~MSKPS2CH2; - break; - case VRC4173_USBU_PCI_CLOCK: - set_cmusrst(USBRST); - vrc4173_cmuclkmsk &= ~MSKUSB; - break; - case VRC4173_CARDU1_PCI_CLOCK: - set_cmusrst(CARD1RST); - vrc4173_cmuclkmsk &= ~MSKCARD1; - break; - case VRC4173_CARDU2_PCI_CLOCK: - set_cmusrst(CARD2RST); - vrc4173_cmuclkmsk &= ~MSKCARD2; - break; - case VRC4173_AC97U_PCI_CLOCK: - set_cmusrst(AC97RST); - vrc4173_cmuclkmsk &= ~MSKAC97; - break; - case VRC4173_USBU_48MHz_CLOCK: - set_cmusrst(USBRST); - vrc4173_cmuclkmsk &= ~MSK48MUSB; - break; - case VRC4173_EXT_48MHz_CLOCK: - vrc4173_cmuclkmsk &= ~MSK48MPIN; - break; - case VRC4173_48MHz_CLOCK: - vrc4173_cmuclkmsk &= ~MSK48MOSC; - break; - default: - printk(KERN_WARNING "vrc4173_mask_clock: Invalid CLOCK value %u\n", clock); - break; - } - - vrc4173_outw(vrc4173_cmuclkmsk, VRC4173_CMUCLKMSK); - - switch (clock) { - case VRC4173_USBU_PCI_CLOCK: - case VRC4173_USBU_48MHz_CLOCK: - clear_cmusrst(USBRST); - break; - case VRC4173_CARDU1_PCI_CLOCK: - clear_cmusrst(CARD1RST); - break; - case VRC4173_CARDU2_PCI_CLOCK: - clear_cmusrst(CARD2RST); - break; - case VRC4173_AC97U_PCI_CLOCK: - clear_cmusrst(AC97RST); - break; - default: - break; - } - - spin_unlock_irq(&vrc4173_cmu_lock); - } -} - -EXPORT_SYMBOL(vrc4173_mask_clock); - -static inline void vrc4173_cmu_init(void) -{ - vrc4173_cmuclkmsk = vrc4173_inw(VRC4173_CMUCLKMSK); - - spin_lock_init(&vrc4173_cmu_lock); -} - -void vrc4173_select_function(vrc4173_function_t function) -{ - if (vrc4173_initialized) { - spin_lock_irq(&vrc4173_giu_lock); - - switch(function) { - case PS2_CHANNEL1: - vrc4173_selectreg |= SEL2; - break; - case PS2_CHANNEL2: - vrc4173_selectreg |= SEL1; - break; - case TOUCHPANEL: - vrc4173_selectreg &= SEL2 | SEL1 | SEL0; - break; - case KEYBOARD_8SCANLINES: - vrc4173_selectreg &= SEL3 | SEL2 | SEL1; - break; - case KEYBOARD_10SCANLINES: - vrc4173_selectreg &= SEL3 | SEL2; - break; - case KEYBOARD_12SCANLINES: - vrc4173_selectreg &= SEL3; - break; - case GPIO_0_15PINS: - vrc4173_selectreg |= SEL0; - break; - case GPIO_16_20PINS: - vrc4173_selectreg |= SEL3; - break; - } - - vrc4173_outw(vrc4173_selectreg, VRC4173_SELECTREG); - - spin_unlock_irq(&vrc4173_giu_lock); - } -} - -EXPORT_SYMBOL(vrc4173_select_function); - -static inline void vrc4173_giu_init(void) -{ - vrc4173_selectreg = vrc4173_inw(VRC4173_SELECTREG); - - spin_lock_init(&vrc4173_giu_lock); -} - -void vrc4173_enable_piuint(uint16_t mask) -{ - irq_desc_t *desc = irq_desc + VRC4173_PIU_IRQ; - unsigned long flags; - uint16_t val; - - spin_lock_irqsave(&desc->lock, flags); - val = vrc4173_inw(VRC4173_MPIUINTREG); - val |= mask; - vrc4173_outw(val, VRC4173_MPIUINTREG); - spin_unlock_irqrestore(&desc->lock, flags); -} - -EXPORT_SYMBOL(vrc4173_enable_piuint); - -void vrc4173_disable_piuint(uint16_t mask) -{ - irq_desc_t *desc = irq_desc + VRC4173_PIU_IRQ; - unsigned long flags; - uint16_t val; - - spin_lock_irqsave(&desc->lock, flags); - val = vrc4173_inw(VRC4173_MPIUINTREG); - val &= ~mask; - vrc4173_outw(val, VRC4173_MPIUINTREG); - spin_unlock_irqrestore(&desc->lock, flags); -} - -EXPORT_SYMBOL(vrc4173_disable_piuint); - -void vrc4173_enable_aiuint(uint16_t mask) -{ - irq_desc_t *desc = irq_desc + VRC4173_AIU_IRQ; - unsigned long flags; - uint16_t val; - - spin_lock_irqsave(&desc->lock, flags); - val = vrc4173_inw(VRC4173_MAIUINTREG); - val |= mask; - vrc4173_outw(val, VRC4173_MAIUINTREG); - spin_unlock_irqrestore(&desc->lock, flags); -} - -EXPORT_SYMBOL(vrc4173_enable_aiuint); - -void vrc4173_disable_aiuint(uint16_t mask) -{ - irq_desc_t *desc = irq_desc + VRC4173_AIU_IRQ; - unsigned long flags; - uint16_t val; - - spin_lock_irqsave(&desc->lock, flags); - val = vrc4173_inw(VRC4173_MAIUINTREG); - val &= ~mask; - vrc4173_outw(val, VRC4173_MAIUINTREG); - spin_unlock_irqrestore(&desc->lock, flags); -} - -EXPORT_SYMBOL(vrc4173_disable_aiuint); - -void vrc4173_enable_kiuint(uint16_t mask) -{ - irq_desc_t *desc = irq_desc + VRC4173_KIU_IRQ; - unsigned long flags; - uint16_t val; - - spin_lock_irqsave(&desc->lock, flags); - val = vrc4173_inw(VRC4173_MKIUINTREG); - val |= mask; - vrc4173_outw(val, VRC4173_MKIUINTREG); - spin_unlock_irqrestore(&desc->lock, flags); -} - -EXPORT_SYMBOL(vrc4173_enable_kiuint); - -void vrc4173_disable_kiuint(uint16_t mask) -{ - irq_desc_t *desc = irq_desc + VRC4173_KIU_IRQ; - unsigned long flags; - uint16_t val; - - spin_lock_irqsave(&desc->lock, flags); - val = vrc4173_inw(VRC4173_MKIUINTREG); - val &= ~mask; - vrc4173_outw(val, VRC4173_MKIUINTREG); - spin_unlock_irqrestore(&desc->lock, flags); -} - -EXPORT_SYMBOL(vrc4173_disable_kiuint); - -static void enable_vrc4173_irq(unsigned int irq) -{ - uint16_t val; - - val = vrc4173_inw(VRC4173_MSYSINT1REG); - val |= (uint16_t)1 << (irq - VRC4173_IRQ_BASE); - vrc4173_outw(val, VRC4173_MSYSINT1REG); -} - -static void disable_vrc4173_irq(unsigned int irq) -{ - uint16_t val; - - val = vrc4173_inw(VRC4173_MSYSINT1REG); - val &= ~((uint16_t)1 << (irq - VRC4173_IRQ_BASE)); - vrc4173_outw(val, VRC4173_MSYSINT1REG); -} - -static unsigned int startup_vrc4173_irq(unsigned int irq) -{ - enable_vrc4173_irq(irq); - return 0; /* never anything pending */ -} - -#define shutdown_vrc4173_irq disable_vrc4173_irq -#define ack_vrc4173_irq disable_vrc4173_irq - -static void end_vrc4173_irq(unsigned int irq) -{ - if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) - enable_vrc4173_irq(irq); -} - -static struct hw_interrupt_type vrc4173_irq_type = { - .typename = "VRC4173", - .startup = startup_vrc4173_irq, - .shutdown = shutdown_vrc4173_irq, - .enable = enable_vrc4173_irq, - .disable = disable_vrc4173_irq, - .ack = ack_vrc4173_irq, - .end = end_vrc4173_irq, -}; - -static int vrc4173_get_irq_number(int irq) -{ - uint16_t status, mask; - int i; - - status = vrc4173_inw(VRC4173_SYSINT1REG); - mask = vrc4173_inw(VRC4173_MSYSINT1REG); - - status &= mask; - if (status) { - for (i = 0; i < 16; i++) - if (status & (0x0001 << i)) - return VRC4173_IRQ(i); - } - - return -EINVAL; -} - -static inline int vrc4173_icu_init(int cascade_irq) -{ - int i; - - if (cascade_irq < GIU_IRQ(0) || cascade_irq > GIU_IRQ(15)) - return -EINVAL; - - vrc4173_outw(0, VRC4173_MSYSINT1REG); - - vr41xx_set_irq_trigger(GIU_IRQ_TO_PIN(cascade_irq), TRIGGER_LEVEL, SIGNAL_THROUGH); - vr41xx_set_irq_level(GIU_IRQ_TO_PIN(cascade_irq), LEVEL_LOW); - - for (i = VRC4173_IRQ_BASE; i <= VRC4173_IRQ_LAST; i++) - irq_desc[i].handler = &vrc4173_irq_type; - - return 0; -} - -static int __devinit vrc4173_probe(struct pci_dev *dev, - const struct pci_device_id *id) -{ - unsigned long start, flags; - int err; - - err = pci_enable_device(dev); - if (err < 0) { - printk(KERN_ERR "vrc4173: Failed to enable PCI device, aborting\n"); - return err; - } - - pci_set_master(dev); - - start = pci_resource_start(dev, 0); - if (start == 0) { - printk(KERN_ERR "vrc4173:No such PCI I/O resource, aborting\n"); - return -ENXIO; - } - - flags = pci_resource_flags(dev, 0); - if ((flags & IORESOURCE_IO) == 0) { - printk(KERN_ERR "vrc4173: No such PCI I/O resource, aborting\n"); - return -ENXIO; - } - - err = pci_request_regions(dev, "NEC VRC4173"); - if (err < 0) { - printk(KERN_ERR "vrc4173: PCI resources are busy, aborting\n"); - return err; - } - - set_vrc4173_io_offset(start); - - vrc4173_cmu_init(); - vrc4173_giu_init(); - - err = vrc4173_icu_init(dev->irq); - if (err < 0) { - printk(KERN_ERR "vrc4173: Invalid IRQ %d, aborting\n", dev->irq); - return err; - } - - err = vr41xx_cascade_irq(dev->irq, vrc4173_get_irq_number); - if (err < 0) { - printk(KERN_ERR "vrc4173: IRQ resource %d is busy, aborting\n", dev->irq); - return err; - } - - printk(KERN_INFO - "NEC VRC4173 at 0x%#08lx, IRQ is cascaded to %d\n", start, dev->irq); - - return 0; -} - -static void vrc4173_remove(struct pci_dev *dev) -{ - free_irq(dev->irq, NULL); - - pci_release_regions(dev); -} - -static struct pci_driver vrc4173_driver = { - .name = "NEC VRC4173", - .probe = vrc4173_probe, - .remove = vrc4173_remove, - .id_table = vrc4173_id_table, -}; - -static int __devinit vrc4173_init(void) -{ - int err; - - err = pci_register_driver(&vrc4173_driver); - if (err < 0) - return err; - - vrc4173_initialized = 1; - - return 0; -} - -static void __devexit vrc4173_exit(void) -{ - vrc4173_initialized = 0; - - pci_unregister_driver(&vrc4173_driver); -} - -module_init(vrc4173_init); -module_exit(vrc4173_exit); |
