aboutsummaryrefslogtreecommitdiff
path: root/arch/mips/vr41xx/common
diff options
context:
space:
mode:
Diffstat (limited to 'arch/mips/vr41xx/common')
-rw-r--r--arch/mips/vr41xx/common/Makefile5
-rw-r--r--arch/mips/vr41xx/common/bcu.c26
-rw-r--r--arch/mips/vr41xx/common/cmu.c42
-rw-r--r--arch/mips/vr41xx/common/giu.c123
-rw-r--r--arch/mips/vr41xx/common/icu.c562
-rw-r--r--arch/mips/vr41xx/common/init.c30
-rw-r--r--arch/mips/vr41xx/common/int-handler.S114
-rw-r--r--arch/mips/vr41xx/common/irq.c124
-rw-r--r--arch/mips/vr41xx/common/pmu.c43
-rw-r--r--arch/mips/vr41xx/common/rtc.c118
-rw-r--r--arch/mips/vr41xx/common/siu.c155
-rw-r--r--arch/mips/vr41xx/common/type.c24
-rw-r--r--arch/mips/vr41xx/common/vrc4173.c581
13 files changed, 885 insertions, 1062 deletions
diff --git a/arch/mips/vr41xx/common/Makefile b/arch/mips/vr41xx/common/Makefile
index fa98ef3855b..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 pmu.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 cdfa4273a1c..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 <yuasa@hh.iij4u.or.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 <yuasa@hh.iij4u.or.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 fcd3cb8cdd9..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 <yuasa@hh.iij4u.or.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 <yuasa@hh.iij4u.or.jp>
+ * Yoichi Yuasa <yuasa@linux-mips.org>
* - Added support for NEC VR4133.
*/
#include <linux/init.h>
@@ -69,7 +69,7 @@
static void __iomem *cmu_base;
static uint16_t cmuclkmsk, cmuclkmsk2;
-static spinlock_t cmu_lock;
+static DEFINE_SPINLOCK(cmu_lock);
#define cmu_read(offset) readw(cmu_base + (offset))
#define cmu_write(offset, value) writew((value), cmu_base + (offset))
@@ -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 c842661144c..41e873bc847 100644
--- a/arch/mips/vr41xx/common/icu.c
+++ b/arch/mips/vr41xx/common/icu.c
@@ -2,9 +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-2004 Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
- * Copyright (C) 2005 Ralf Baechle (ralf@linux-mips.org)
+ * 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
@@ -22,16 +21,16 @@
*/
/*
* 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 <yuasa@hh.iij4u.or.jp>
+ * Yoichi Yuasa <yuasa@linux-mips.org>
* - Coped with INTASSIGN of NEC VR4133.
*/
#include <linux/errno.h>
#include <linux/init.h>
-#include <linux/interrupt.h>
+#include <linux/ioport.h>
#include <linux/irq.h>
#include <linux/module.h>
#include <linux/smp.h>
@@ -39,34 +38,25 @@
#include <asm/cpu.h>
#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/irq_cpu.h>
+#include <asm/vr41xx/irq.h>
#include <asm/vr41xx/vr41xx.h>
-extern asmlinkage void vr41xx_handle_interrupt(void);
-
-extern void init_vr41xx_giuint_irq(void);
-extern void giuint_irq_dispatch(struct pt_regs *regs);
-
-static uint32_t icu1_base;
-static uint32_t icu2_base;
-
-static struct irqaction icu_cascade = {
- .handler = no_action,
- .mask = CPU_MASK_NONE,
- .name = "cascade",
-};
+static void __iomem *icu1_base;
+static void __iomem *icu2_base;
static unsigned char sysint1_assign[16] = {
0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
static unsigned char sysint2_assign[16] = {
- 2, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
+ 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
-#define SYSINT1REG_TYPE1 KSEG1ADDR(0x0b000080)
-#define SYSINT2REG_TYPE1 KSEG1ADDR(0x0b000200)
+#define ICU1_TYPE1_BASE 0x0b000080UL
+#define ICU2_TYPE1_BASE 0x0b000200UL
-#define SYSINT1REG_TYPE2 KSEG1ADDR(0x0f000080)
-#define SYSINT2REG_TYPE2 KSEG1ADDR(0x0f0000a0)
+#define ICU1_TYPE2_BASE 0x0f000080UL
+#define ICU2_TYPE2_BASE 0x0f0000a0UL
+
+#define ICU1_SIZE 0x20
+#define ICU2_SIZE 0x1c
#define SYSINT1REG 0x00
#define PIUINTREG 0x02
@@ -78,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
@@ -106,71 +97,71 @@ static unsigned char sysint2_assign[16] = {
#define SYSINT1_IRQ_TO_PIN(x) ((x) - SYSINT1_IRQ_BASE) /* Pin 0-15 */
#define SYSINT2_IRQ_TO_PIN(x) ((x) - SYSINT2_IRQ_BASE) /* Pin 0-15 */
-#define read_icu1(offset) readw(icu1_base + (offset))
-#define write_icu1(val, offset) writew((val), icu1_base + (offset))
+#define INT_TO_IRQ(x) ((x) + 2) /* Int0-4 -> IRQ2-6 */
+
+#define icu1_read(offset) readw(icu1_base + (offset))
+#define icu1_write(offset, value) writew((value), icu1_base + (offset))
-#define read_icu2(offset) readw(icu2_base + (offset))
-#define write_icu2(val, offset) writew((val), icu2_base + (offset))
+#define icu2_read(offset) readw(icu2_base + (offset))
+#define icu2_write(offset, value) writew((value), icu2_base + (offset))
#define INTASSIGN_MAX 4
#define INTASSIGN_MASK 0x0007
-static inline uint16_t set_icu1(uint8_t offset, uint16_t set)
+static inline uint16_t icu1_set(uint8_t offset, uint16_t set)
{
- uint16_t res;
+ uint16_t data;
- res = read_icu1(offset);
- res |= set;
- write_icu1(res, offset);
+ data = icu1_read(offset);
+ data |= set;
+ icu1_write(offset, data);
- return res;
+ return data;
}
-static inline uint16_t clear_icu1(uint8_t offset, uint16_t clear)
+static inline uint16_t icu1_clear(uint8_t offset, uint16_t clear)
{
- uint16_t res;
+ uint16_t data;
- res = read_icu1(offset);
- res &= ~clear;
- write_icu1(res, offset);
+ data = icu1_read(offset);
+ data &= ~clear;
+ icu1_write(offset, data);
- return res;
+ return data;
}
-static inline uint16_t set_icu2(uint8_t offset, uint16_t set)
+static inline uint16_t icu2_set(uint8_t offset, uint16_t set)
{
- uint16_t res;
+ uint16_t data;
- res = read_icu2(offset);
- res |= set;
- write_icu2(res, offset);
+ data = icu2_read(offset);
+ data |= set;
+ icu2_write(offset, data);
- return res;
+ return data;
}
-static inline uint16_t clear_icu2(uint8_t offset, uint16_t clear)
+static inline uint16_t icu2_clear(uint8_t offset, uint16_t clear)
{
- uint16_t res;
+ uint16_t data;
- res = read_icu2(offset);
- res &= ~clear;
- write_icu2(res, offset);
+ data = icu2_read(offset);
+ data &= ~clear;
+ icu2_write(offset, data);
- return res;
+ return data;
}
-/*=======================================================================*/
-
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);
- set_icu1(MPIUINTREG, mask);
- spin_unlock_irqrestore(&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);
+ raw_spin_unlock_irqrestore(&desc->lock, flags);
}
}
@@ -178,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);
- clear_icu1(MPIUINTREG, mask);
- spin_unlock_irqrestore(&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);
+ raw_spin_unlock_irqrestore(&desc->lock, flags);
}
}
@@ -193,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);
- set_icu1(MAIUINTREG, mask);
- spin_unlock_irqrestore(&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);
+ raw_spin_unlock_irqrestore(&desc->lock, flags);
}
}
@@ -208,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);
- clear_icu1(MAIUINTREG, mask);
- spin_unlock_irqrestore(&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);
+ raw_spin_unlock_irqrestore(&desc->lock, flags);
}
}
@@ -223,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);
- set_icu1(MKIUINTREG, mask);
- spin_unlock_irqrestore(&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);
+ raw_spin_unlock_irqrestore(&desc->lock, flags);
}
}
@@ -238,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);
- clear_icu1(MKIUINTREG, mask);
- spin_unlock_irqrestore(&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);
+ 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);
- set_icu1(MDSIUINTREG, mask);
- spin_unlock_irqrestore(&desc->lock, flags);
+ raw_spin_lock_irqsave(&desc->lock, flags);
+ icu1_set(MDSIUINTREG, mask);
+ 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);
- clear_icu1(MDSIUINTREG, mask);
- spin_unlock_irqrestore(&desc->lock, flags);
+ raw_spin_lock_irqsave(&desc->lock, flags);
+ icu1_clear(MDSIUINTREG, mask);
+ 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);
- set_icu2(MFIRINTREG, mask);
- spin_unlock_irqrestore(&desc->lock, flags);
+ raw_spin_lock_irqsave(&desc->lock, flags);
+ icu2_set(MFIRINTREG, mask);
+ 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);
- clear_icu2(MFIRINTREG, mask);
- spin_unlock_irqrestore(&desc->lock, flags);
+ raw_spin_lock_irqsave(&desc->lock, flags);
+ icu2_clear(MFIRINTREG, mask);
+ 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);
- write_icu2(PCIINT0, MPCIINTREG);
- spin_unlock_irqrestore(&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);
+ raw_spin_unlock_irqrestore(&desc->lock, flags);
}
}
@@ -317,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);
- write_icu2(0, MPCIINTREG);
- spin_unlock_irqrestore(&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);
+ raw_spin_unlock_irqrestore(&desc->lock, flags);
}
}
@@ -333,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);
- write_icu2(SCUINT0, MSCUINTREG);
- spin_unlock_irqrestore(&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);
+ raw_spin_unlock_irqrestore(&desc->lock, flags);
}
}
@@ -349,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);
- write_icu2(0, MSCUINTREG);
- spin_unlock_irqrestore(&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);
+ raw_spin_unlock_irqrestore(&desc->lock, flags);
}
}
@@ -365,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);
- set_icu2(MCSIINTREG, mask);
- spin_unlock_irqrestore(&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);
+ raw_spin_unlock_irqrestore(&desc->lock, flags);
}
}
@@ -381,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);
- clear_icu2(MCSIINTREG, mask);
- spin_unlock_irqrestore(&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);
+ raw_spin_unlock_irqrestore(&desc->lock, flags);
}
}
@@ -397,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);
- write_icu2(BCUINTR, MBCUINTREG);
- spin_unlock_irqrestore(&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);
+ raw_spin_unlock_irqrestore(&desc->lock, flags);
}
}
@@ -413,110 +428,64 @@ 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);
- write_icu2(0, MBCUINTREG);
- spin_unlock_irqrestore(&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);
+ raw_spin_unlock_irqrestore(&desc->lock, flags);
}
}
EXPORT_SYMBOL(vr41xx_disable_bcuint);
-/*=======================================================================*/
-
-static unsigned int startup_sysint1_irq(unsigned int irq)
-{
- set_icu1(MSYSINT1REG, (uint16_t)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)
{
- clear_icu1(MSYSINT1REG, (uint16_t)1 << SYSINT1_IRQ_TO_PIN(irq));
+ icu1_clear(MSYSINT1REG, 1 << SYSINT1_IRQ_TO_PIN(d->irq));
}
-static void enable_sysint1_irq(unsigned int irq)
-{
- set_icu1(MSYSINT1REG, (uint16_t)1 << SYSINT1_IRQ_TO_PIN(irq));
-}
-
-#define disable_sysint1_irq shutdown_sysint1_irq
-#define ack_sysint1_irq shutdown_sysint1_irq
-
-static void end_sysint1_irq(unsigned int irq)
+static void enable_sysint1_irq(struct irq_data *d)
{
- if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
- set_icu1(MSYSINT1REG, (uint16_t)1 << SYSINT1_IRQ_TO_PIN(irq));
+ icu1_set(MSYSINT1REG, 1 << SYSINT1_IRQ_TO_PIN(d->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)
-{
- set_icu2(MSYSINT2REG, (uint16_t)1 << SYSINT2_IRQ_TO_PIN(irq));
-
- return 0; /* never anything pending */
-}
-
-static void shutdown_sysint2_irq(unsigned int irq)
-{
- clear_icu2(MSYSINT2REG, (uint16_t)1 << SYSINT2_IRQ_TO_PIN(irq));
-}
-
-static void enable_sysint2_irq(unsigned int irq)
+static void disable_sysint2_irq(struct irq_data *d)
{
- set_icu2(MSYSINT2REG, (uint16_t)1 << SYSINT2_IRQ_TO_PIN(irq));
+ icu2_clear(MSYSINT2REG, 1 << SYSINT2_IRQ_TO_PIN(d->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)))
- set_icu2(MSYSINT2REG, (uint16_t)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 = read_icu1(INTASSIGN0);
- intassign1 = read_icu1(INTASSIGN1);
+ intassign0 = icu1_read(INTASSIGN0);
+ intassign1 = icu1_read(INTASSIGN1);
switch (pin) {
case 0:
@@ -552,30 +521,31 @@ 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;
}
sysint1_assign[pin] = assign;
- write_icu1(intassign0, INTASSIGN0);
- write_icu1(intassign1, INTASSIGN1);
+ 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 = read_icu1(INTASSIGN2);
- intassign3 = read_icu1(INTASSIGN3);
+ intassign2 = icu1_read(INTASSIGN2);
+ intassign3 = icu1_read(INTASSIGN3);
switch (pin) {
case 0:
@@ -619,14 +589,15 @@ 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;
}
sysint2_assign[pin] = assign;
- write_icu1(intassign2, INTASSIGN2);
- write_icu1(intassign3, INTASSIGN3);
+ icu1_write(INTASSIGN2, intassign2);
+ icu1_write(INTASSIGN3, intassign3);
- spin_unlock_irq(&desc->lock);
+ raw_spin_unlock_irq(&desc->lock);
return 0;
}
@@ -635,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)
@@ -651,107 +622,108 @@ int vr41xx_set_intassign(unsigned int irq, unsigned char intassign)
EXPORT_SYMBOL(vr41xx_set_intassign);
-/*=======================================================================*/
-
-asmlinkage void irq_dispatch(unsigned char intnum, struct pt_regs *regs)
+static int icu_get_irq(unsigned int irq)
{
uint16_t pend1, pend2;
uint16_t mask1, mask2;
int i;
- pend1 = read_icu1(SYSINT1REG);
- mask1 = read_icu1(MSYSINT1REG);
+ pend1 = icu1_read(SYSINT1REG);
+ mask1 = icu1_read(MSYSINT1REG);
- pend2 = read_icu2(SYSINT2REG);
- mask2 = read_icu2(MSYSINT2REG);
+ pend2 = icu2_read(SYSINT2REG);
+ mask2 = icu2_read(MSYSINT2REG);
mask1 &= pend1;
mask2 &= pend2;
if (mask1) {
for (i = 0; i < 16; i++) {
- if (intnum == sysint1_assign[i] &&
- (mask1 & ((uint16_t)1 << i))) {
- if (i == 8)
- giuint_irq_dispatch(regs);
- else
- do_IRQ(SYSINT1_IRQ(i), regs);
- return;
- }
+ if (irq == INT_TO_IRQ(sysint1_assign[i]) && (mask1 & (1 << i)))
+ return SYSINT1_IRQ(i);
}
}
if (mask2) {
for (i = 0; i < 16; i++) {
- if (intnum == sysint2_assign[i] &&
- (mask2 & ((uint16_t)1 << i))) {
- do_IRQ(SYSINT2_IRQ(i), regs);
- return;
- }
+ if (irq == INT_TO_IRQ(sysint2_assign[i]) && (mask2 & (1 << i)))
+ return SYSINT2_IRQ(i);
}
}
printk(KERN_ERR "spurious ICU interrupt: %04x,%04x\n", pend1, pend2);
atomic_inc(&irq_err_count);
-}
-/*=======================================================================*/
+ return -1;
+}
static int __init vr41xx_icu_init(void)
{
- switch (current_cpu_data.cputype) {
+ unsigned long icu1_start, icu2_start;
+ int i;
+
+ switch (current_cpu_type()) {
case CPU_VR4111:
case CPU_VR4121:
- icu1_base = SYSINT1REG_TYPE1;
- icu2_base = SYSINT2REG_TYPE1;
+ icu1_start = ICU1_TYPE1_BASE;
+ icu2_start = ICU2_TYPE1_BASE;
break;
case CPU_VR4122:
case CPU_VR4131:
case CPU_VR4133:
- icu1_base = SYSINT1REG_TYPE2;
- icu2_base = SYSINT2REG_TYPE2;
+ icu1_start = ICU1_TYPE2_BASE;
+ icu2_start = ICU2_TYPE2_BASE;
break;
default:
printk(KERN_ERR "ICU: Unexpected CPU of NEC VR4100 series\n");
- return -EINVAL;
+ return -ENODEV;
}
- write_icu1(0, MSYSINT1REG);
- write_icu1(0xffff, MGIUINTLREG);
+ if (request_mem_region(icu1_start, ICU1_SIZE, "ICU") == NULL)
+ return -EBUSY;
- write_icu2(0, MSYSINT2REG);
- write_icu2(0xffff, MGIUINTHREG);
+ if (request_mem_region(icu2_start, ICU2_SIZE, "ICU") == NULL) {
+ release_mem_region(icu1_start, ICU1_SIZE);
+ return -EBUSY;
+ }
- return 0;
-}
+ icu1_base = ioremap(icu1_start, ICU1_SIZE);
+ if (icu1_base == NULL) {
+ release_mem_region(icu1_start, ICU1_SIZE);
+ release_mem_region(icu2_start, ICU2_SIZE);
+ return -ENOMEM;
+ }
-early_initcall(vr41xx_icu_init);
+ icu2_base = ioremap(icu2_start, ICU2_SIZE);
+ if (icu2_base == NULL) {
+ iounmap(icu1_base);
+ release_mem_region(icu1_start, ICU1_SIZE);
+ release_mem_region(icu2_start, ICU2_SIZE);
+ return -ENOMEM;
+ }
-/*=======================================================================*/
+ icu1_write(MSYSINT1REG, 0);
+ icu1_write(MGIUINTLREG, 0xffff);
-static inline void init_vr41xx_icu_irq(void)
-{
- int i;
+ icu2_write(MSYSINT2REG, 0);
+ 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);
- setup_irq(INT0_CASCADE_IRQ, &icu_cascade);
- setup_irq(INT1_CASCADE_IRQ, &icu_cascade);
- setup_irq(INT2_CASCADE_IRQ, &icu_cascade);
- setup_irq(INT3_CASCADE_IRQ, &icu_cascade);
- setup_irq(INT4_CASCADE_IRQ, &icu_cascade);
-}
+ cascade_irq(INT0_IRQ, icu_get_irq);
+ cascade_irq(INT1_IRQ, icu_get_irq);
+ cascade_irq(INT2_IRQ, icu_get_irq);
+ cascade_irq(INT3_IRQ, icu_get_irq);
+ cascade_irq(INT4_IRQ, icu_get_irq);
-void __init arch_init_irq(void)
-{
- mips_cpu_irq_init(MIPS_CPU_IRQ_BASE);
- init_vr41xx_icu_irq();
- init_vr41xx_giuint_irq();
-
- set_except_vector(0, vr41xx_handle_interrupt);
+ return 0;
}
+
+core_initcall(vr41xx_icu_init);
diff --git a/arch/mips/vr41xx/common/init.c b/arch/mips/vr41xx/common/init.c
index e03be896cbc..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 <yuasa@hh.iij4u.or.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,15 +50,11 @@ static void __init setup_timer_frequency(void)
mips_hpt_frequency = tclock / 4;
}
-static void __init setup_timer_irq(struct irqaction *irq)
+void __init plat_mem_setup(void)
{
- setup_irq(TIMER_IRQ, irq);
-}
+ iomem_resource_init();
-static void __init timer_init(void)
-{
- board_time_init = setup_timer_frequency;
- board_timer_setup = setup_timer_irq;
+ vr41xx_siu_setup();
}
void __init prom_init(void)
@@ -67,19 +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);
}
-
- vr41xx_calculate_clock_frequency();
-
- timer_init();
-
- iomem_resource_init();
}
-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 38ff89b505f..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 <yuasa@hh.iij4u.or.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, 1
-
- andi t1, t0, CAUSEF_IP4 # check for Int2
- bnez t1, handle_int
- li a0, 2
-
- andi t1, t0, CAUSEF_IP5 # check for Int3
- bnez t1, handle_int
- li a0, 3
-
- andi t1, t0, CAUSEF_IP6 # check for Int4
- bnez t1, handle_int
- li a0, 4
-
-1:
- andi t1, t0, CAUSEF_IP2 # check for Int0
- bnez t1, handle_int
- li a0, 0
-
- 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
new file mode 100644
index 00000000000..ae0e4ee6c61
--- /dev/null
+++ b/arch/mips/vr41xx/common/irq.c
@@ -0,0 +1,124 @@
+/*
+ * Interrupt handing routines for NEC VR4100 series.
+ *
+ * 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
+ * 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/interrupt.h>
+#include <linux/module.h>
+#include <linux/irq.h>
+
+#include <asm/irq_cpu.h>
+#include <asm/vr41xx/irq.h>
+
+typedef struct irq_cascade {
+ 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,
+ .name = "cascade",
+ .flags = IRQF_NO_THREAD,
+};
+
+int cascade_irq(unsigned int irq, int (*get_irq)(unsigned int))
+{
+ int retval = 0;
+
+ if (irq >= NR_IRQS)
+ return -EINVAL;
+
+ if (irq_cascade[irq].get_irq != NULL)
+ free_irq(irq, NULL);
+
+ irq_cascade[irq].get_irq = get_irq;
+
+ if (get_irq != NULL) {
+ retval = setup_irq(irq, &cascade_irqaction);
+ if (retval < 0)
+ irq_cascade[irq].get_irq = NULL;
+ }
+
+ return retval;
+}
+
+EXPORT_SYMBOL_GPL(cascade_irq);
+
+static void irq_dispatch(unsigned int irq)
+{
+ irq_cascade_t *cascade;
+
+ if (irq >= NR_IRQS) {
+ atomic_inc(&irq_err_count);
+ return;
+ }
+
+ cascade = irq_cascade + irq;
+ if (cascade->get_irq != NULL) {
+ 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);
+ if (!irqd_irq_disabled(idata) && chip->irq_unmask)
+ chip->irq_unmask(idata);
+ } else
+ do_IRQ(irq);
+}
+
+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();
+}
diff --git a/arch/mips/vr41xx/common/pmu.c b/arch/mips/vr41xx/common/pmu.c
index 53166f3598b..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 <yuasa@hh.iij4u.or.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
new file mode 100644
index 00000000000..45836a92b7a
--- /dev/null
+++ b/arch/mips/vr41xx/common/type.c
@@ -0,0 +1,24 @@
+/*
+ * type.c, System type for NEC VR4100 series.
+ *
+ * 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
+ * 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
+ */
+
+const char *get_system_type(void)
+{
+ return "NEC VR4100 series";
+}
diff --git a/arch/mips/vr41xx/common/vrc4173.c b/arch/mips/vr41xx/common/vrc4173.c
deleted file mode 100644
index 5475dd72e26..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 <yuasa@hh.iij4u.or.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 spinlock_t vrc4173_cmu_lock;
-static spinlock_t 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_module_init(&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);