[PATCH 3/3] Add irqs definition and handler for Mindspeed Comcerto platform

stanleymiao at gmail.com stanleymiao at gmail.com
Thu Oct 14 04:38:09 EDT 2010


From: Stanley.Miao <stanley.miao at windriver.com>

the Comcerto interrupt controller supports more than 32 peripheral interrupts,
so two interrupt status registers and associated mask registers are required.

Signed-off-by: Stanley.Miao <stanley.miao at windriver.com>
---
 arch/arm/mach-comcerto/Makefile                    |    2 +-
 arch/arm/mach-comcerto/board-c1kmfcn_evm.c         |    1 +
 arch/arm/mach-comcerto/comcerto-1000.c             |   41 ++++
 .../arm/mach-comcerto/include/mach/comcerto-1000.h |    1 +
 .../include/mach/comcerto-1000/intr.h              |   78 ++++++++
 .../include/mach/comcerto-1000/irqs.h              |  121 ++++++++++++
 arch/arm/mach-comcerto/include/mach/hardware.h     |    1 +
 arch/arm/mach-comcerto/include/mach/irq.h          |  155 +++++++++++++++
 arch/arm/mach-comcerto/include/mach/irqs.h         |   21 ++
 arch/arm/mach-comcerto/irq.c                       |  200 ++++++++++++++++++++
 10 files changed, 620 insertions(+), 1 deletions(-)
 create mode 100644 arch/arm/mach-comcerto/include/mach/comcerto-1000/intr.h
 create mode 100644 arch/arm/mach-comcerto/include/mach/comcerto-1000/irqs.h
 create mode 100644 arch/arm/mach-comcerto/include/mach/irq.h
 create mode 100644 arch/arm/mach-comcerto/include/mach/irqs.h
 create mode 100644 arch/arm/mach-comcerto/irq.c

diff --git a/arch/arm/mach-comcerto/Makefile b/arch/arm/mach-comcerto/Makefile
index c514d20..b4c369d 100644
--- a/arch/arm/mach-comcerto/Makefile
+++ b/arch/arm/mach-comcerto/Makefile
@@ -4,7 +4,7 @@
 
 # Object file lists.
 
-obj-y := time.o
+obj-y := irq.o time.o
 
 obj-$(CONFIG_ARCH_M83XXX)			+= comcerto-1000.o
 obj-$(CONFIG_EVM_C1KMFCN_EVM)			+= board-c1kmfcn_evm.o
diff --git a/arch/arm/mach-comcerto/board-c1kmfcn_evm.c b/arch/arm/mach-comcerto/board-c1kmfcn_evm.c
index 74a7da3..3dd0b6f 100644
--- a/arch/arm/mach-comcerto/board-c1kmfcn_evm.c
+++ b/arch/arm/mach-comcerto/board-c1kmfcn_evm.c
@@ -69,6 +69,7 @@ static void __init platform_map_io(void)
 
 static void __init platform_irq_init(void)
 {
+	device_irq_init();
 }
 
 static void __init platform_init(void)
diff --git a/arch/arm/mach-comcerto/comcerto-1000.c b/arch/arm/mach-comcerto/comcerto-1000.c
index 09032ea..2503871 100644
--- a/arch/arm/mach-comcerto/comcerto-1000.c
+++ b/arch/arm/mach-comcerto/comcerto-1000.c
@@ -28,6 +28,8 @@
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 #include <mach/hardware.h>
+#include <mach/irq.h>
+#include <mach/irqs.h>
 
 /***********************************************************
  *   Virtual address Mapping                               *
@@ -144,3 +146,42 @@ void __init device_map_io(void)
 	iotable_init(comcerto_io_desc, ARRAY_SIZE(comcerto_io_desc));
 }
 
+/* IRQ configuration table */
+static struct comcerto_irq_desc comcerto_irq_table[] __initdata = {
+	{IRQ_EMAC0_BATCH,		handle_level_irq,			1},
+	{IRQ_EMAC1_BATCH,		handle_level_irq,			2},
+	{IRQ_ARAM,			comcerto_handle_secondary_level_irq,	3},
+	{IRQ_PCIe0_EXT,			handle_level_irq,			4},
+	{IRQ_PCIe1_EXT,			handle_level_irq,			5},
+	{IRQ_PCIe0_INT,			comcerto_handle_secondary_level_irq,	6},
+	{IRQ_PCIe1_INT,			comcerto_handle_secondary_level_irq,	7},
+	{IRQ_USB0,			comcerto_handle_secondary_level_irq,	8},
+	{STATUS_REG_1,			NULL,					9},
+	{IRQ_PTP0,			handle_level_irq,			10},
+	{IRQ_TIMER1,			comcerto_handle_secondary_level_irq,	11},
+	{IRQ_TIMER3,			comcerto_handle_secondary_level_irq,	12},
+	{IRQ_TIMER4,			comcerto_handle_secondary_level_irq,	13},
+	{IRQ_TIMER5,			comcerto_handle_secondary_level_irq,	14},
+	{IRQ_SPI,			comcerto_handle_secondary_level_irq,	15},
+	{IRQ_EMAC0,			comcerto_handle_secondary_level_irq,	16},
+	{IRQ_EMAC1,			comcerto_handle_secondary_level_irq,	17},
+	{IRQ_IPSEC_WRAP,		handle_level_irq,			18},
+	{IRQ_I2C,			comcerto_handle_secondary_level_irq,	19},
+	{IRQ_CSP_PMU,			handle_level_irq,			-1},
+	{IRQ_UART1,			comcerto_handle_secondary_level_irq,	-1},
+	{IRQ_UART0,			comcerto_handle_secondary_level_irq,	-1},
+	{IRQ_G2,			handle_level_irq,			-1},
+	{IRQ_G1,			handle_level_irq,			-1},
+	{IRQ_G0,			handle_level_irq,			-1},
+	{IRQ_FPP,			handle_level_irq,			-1},
+	{IRQ_CSPVED1RX,			handle_level_irq,			-1},
+	{IRQ_CSPVED0RX,			handle_level_irq,			-1},
+	{IRQ_SPDRV_ACP_REQ,		handle_level_irq,			-1},
+	{IRQ_SPDRV_ACP_WORK_DONE,	handle_level_irq,			-1}
+};
+
+void __init device_irq_init(void)
+{
+	comcerto_irq_init(comcerto_irq_table, ARRAY_SIZE(comcerto_irq_table));
+}
+
diff --git a/arch/arm/mach-comcerto/include/mach/comcerto-1000.h b/arch/arm/mach-comcerto/include/mach/comcerto-1000.h
index 10086c4..ac9cd21 100644
--- a/arch/arm/mach-comcerto/include/mach/comcerto-1000.h
+++ b/arch/arm/mach-comcerto/include/mach/comcerto-1000.h
@@ -90,5 +90,6 @@
 #define APB_VADDR(x)            ((x) - COMCERTO_AHB_APB_BASE + APB_VADDR_BASE)
 
 #include <mach/comcerto-1000/timer.h>
+#include <mach/comcerto-1000/intr.h>
 
 #endif
diff --git a/arch/arm/mach-comcerto/include/mach/comcerto-1000/intr.h b/arch/arm/mach-comcerto/include/mach/comcerto-1000/intr.h
new file mode 100644
index 0000000..61c2e3a
--- /dev/null
+++ b/arch/arm/mach-comcerto/include/mach/comcerto-1000/intr.h
@@ -0,0 +1,78 @@
+/*
+ *  arch/arm/mach-comcerto/include/mach/comcerto-1000/intr.h
+ *
+ *  Copyright (C) 2008 Mindspeed Technologies, 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 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 PARTINTCULAR 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
+ */
+
+#ifndef __INTR__H__
+#define __INTR__H__
+
+/*  Comcerto Interrupt Controller */
+#define COMCERTO_INTC_STATUS_REG_0			APB_VADDR((COMCERTO_APB_INTC_BASE + 0x00))
+#define COMCERTO_INTC_CLEAR_STATUS_REG_0		APB_VADDR((COMCERTO_APB_INTC_BASE + 0x00))
+#define COMCERTO_INTC_SET_STATUS_REG_0			APB_VADDR((COMCERTO_APB_INTC_BASE + 0x04))
+#define COMCERTO_INTC_ARM0_IRQMASK_0			APB_VADDR((COMCERTO_APB_INTC_BASE + 0x08))
+#define COMCERTO_INTC_ARM0_FIQMASK_0			APB_VADDR((COMCERTO_APB_INTC_BASE + 0x0C))
+#define COMCERTO_INTC_ARM1_IRQMASK_0			APB_VADDR((COMCERTO_APB_INTC_BASE + 0x10))
+#define COMCERTO_INTC_ARM1_FIQMASK_0			APB_VADDR((COMCERTO_APB_INTC_BASE + 0x14))
+#define COMCERTO_INTC_ARM1_CONTROL_REG			APB_VADDR((COMCERTO_APB_INTC_BASE + 0x18))
+#define COMCERTO_INTC_IRQ_ACK_TEST_REG			APB_VADDR((COMCERTO_APB_INTC_BASE + 0x1C))
+#define COMCERTO_INTC_STATUS_REG_1			APB_VADDR((COMCERTO_APB_INTC_BASE + 0x20))
+#define COMCERTO_INTC_CLEAR_STATUS_REG_1		APB_VADDR((COMCERTO_APB_INTC_BASE + 0x20))
+#define COMCERTO_INTC_SET_STATUS_REG_1			APB_VADDR((COMCERTO_APB_INTC_BASE + 0x24))
+#define COMCERTO_INTC_ARM0_IRQMASK_1			APB_VADDR((COMCERTO_APB_INTC_BASE + 0x28))
+#define COMCERTO_INTC_ARM0_FIQMASK_1			APB_VADDR((COMCERTO_APB_INTC_BASE + 0x2C))
+#define COMCERTO_INTC_ARM1_IRQMASK_1			APB_VADDR((COMCERTO_APB_INTC_BASE + 0x30))
+#define COMCERTO_INTC_ARM1_FIQMASK_1			APB_VADDR((COMCERTO_APB_INTC_BASE + 0x34))
+#define COMCERTO_INTC_STATUS_MASK_REG_1			APB_VADDR((COMCERTO_APB_INTC_BASE + 0x38))
+#define COMCERTO_INTC_ARM0_PRTY_0			APB_VADDR((COMCERTO_APB_INTC_BASE + 0x40))
+#define COMCERTO_INTC_ARM0_PRTY_1			APB_VADDR((COMCERTO_APB_INTC_BASE + 0x44))
+#define COMCERTO_INTC_ARM0_PRTY_2			APB_VADDR((COMCERTO_APB_INTC_BASE + 0x48))
+#define COMCERTO_INTC_ARM0_PRTY_3			APB_VADDR((COMCERTO_APB_INTC_BASE + 0x4C))
+#define COMCERTO_INTC_ARM0_PRTY_4			APB_VADDR((COMCERTO_APB_INTC_BASE + 0x50))
+#define COMCERTO_INTC_ARM0_PRTY_5			APB_VADDR((COMCERTO_APB_INTC_BASE + 0x54))
+#define COMCERTO_INTC_ARM0_PRTY_6			APB_VADDR((COMCERTO_APB_INTC_BASE + 0x58))
+#define COMCERTO_INTC_ARM0_PRTY_7			APB_VADDR((COMCERTO_APB_INTC_BASE + 0x5C))
+#define COMCERTO_INTC_ARM0_IRQ_WNR			APB_VADDR((COMCERTO_APB_INTC_BASE + 0x60))
+#define COMCERTO_INTC_ARM0_SELFCLEAR			APB_VADDR((COMCERTO_APB_INTC_BASE + 0x64))
+#define COMCERTO_INTC_FIQ_PRTY_EN			APB_VADDR((COMCERTO_APB_INTC_BASE + 0x68))
+#define COMCERTO_INTC_TDMA_STS				APB_VADDR((COMCERTO_APB_INTC_BASE + 0x70))
+#define COMCERTO_INTC_TDMA_CTRL				APB_VADDR((COMCERTO_APB_INTC_BASE + 0x74))
+#define COMCERTO_INTC_TDMA_SET				APB_VADDR((COMCERTO_APB_INTC_BASE + 0x78))
+#define COMCERTO_INTC_ARM1_PRTY_0			APB_VADDR((COMCERTO_APB_INTC_BASE + 0x80))
+#define COMCERTO_INTC_ARM1_PRTY_1			APB_VADDR((COMCERTO_APB_INTC_BASE + 0x84))
+#define COMCERTO_INTC_ARM1_PRTY_2			APB_VADDR((COMCERTO_APB_INTC_BASE + 0x88))
+#define COMCERTO_INTC_ARM1_PRTY_3			APB_VADDR((COMCERTO_APB_INTC_BASE + 0x8C))
+#define COMCERTO_INTC_ARM1_PRTY_4			APB_VADDR((COMCERTO_APB_INTC_BASE + 0x90))
+#define COMCERTO_INTC_ARM1_PRTY_5			APB_VADDR((COMCERTO_APB_INTC_BASE + 0x94))
+#define COMCERTO_INTC_ARM1_PRTY_6			APB_VADDR((COMCERTO_APB_INTC_BASE + 0x98))
+#define COMCERTO_INTC_ARM1_PRTY_7			APB_VADDR((COMCERTO_APB_INTC_BASE + 0x9C))
+#define COMCERTO_INTC_ARM1_IRQ_WNR			APB_VADDR((COMCERTO_APB_INTC_BASE + 0xA0))
+#define COMCERTO_INTC_ARM0_IRQ_WNR_VBA			APB_VADDR((COMCERTO_APB_INTC_BASE + 0xB0))
+#define COMCERTO_INTC_ARM1_IRQ_WNR_VBA			APB_VADDR((COMCERTO_APB_INTC_BASE + 0xB4))
+#define COMCERTO_INTC_ARM0_STS_VEC_ADDR(nb)		APB_VADDR((COMCERTO_APB_INTC_BASE + 0x100 + 4nb))
+#define COMCERTO_INTC_ARM1_STS_VEC_ADDR(nb)		APB_VADDR((COMCERTO_APB_INTC_BASE + 0x180 + 4nb))
+
+#define COMCERTO_INTC_CSP_IRQMASK_0     COMCERTO_INTC_ARM0_IRQMASK_0
+#define COMCERTO_INTC_CSP_IRQMASK_1     COMCERTO_INTC_ARM0_IRQMASK_1
+#define COMCERTO_INTC_CSP_FIQMASK_0     COMCERTO_INTC_ARM0_FIQMASK_0
+#define COMCERTO_INTC_CSP_FIQMASK_1     COMCERTO_INTC_ARM0_FIQMASK_1
+
+#define COMCERTO_INTC_CSP_IRQ_WNR       COMCERTO_INTC_ARM0_IRQ_WNR
+#define COMCERTO_INTC_CSP_PRTY_0        COMCERTO_INTC_ARM0_PRTY_0
+
+#endif
diff --git a/arch/arm/mach-comcerto/include/mach/comcerto-1000/irqs.h b/arch/arm/mach-comcerto/include/mach/comcerto-1000/irqs.h
new file mode 100644
index 0000000..7f59a77
--- /dev/null
+++ b/arch/arm/mach-comcerto/include/mach/comcerto-1000/irqs.h
@@ -0,0 +1,121 @@
+/*
+ *  arch/arm/mach-comcerto/include/mach/comcerto-1000/irqs.h
+ *
+ *  Copyright (C) 2008 Mindspeed Technologies, 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 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
+ */
+#ifndef __COMCERTO_IRQS_H__
+#define __COMCERTO_IRQS_H__
+
+/* INTC0 32 First IRQs*/
+#define IRQ_TIMER0			31
+#define IRQ_TIMER1			30
+#define IRQ_TIMER2			29
+#define IRQ_TIMER3			28
+#define IRQ_TIMER4			27
+#define IRQ_TIMER5			26
+/*	#define IRQ_Reserved		25*/
+#define IRQ_EMAC1_BATCH			24
+#define IRQ_EMAC0_BATCH			23
+#define IRQ_ARAM			22
+#define IRQ_I2C				21
+#define IRQ_THERMAL			20
+#define IRQ_HWFAULT			19
+#define IRQ_DDRC			18
+#define IRQ_PCIe1_INT			17
+#define IRQ_PCIe1_EXT			16
+#define IRQ_PCIe0_INT			15
+#define IRQ_PCIe0_EXT			14
+#define IRQ_MDMA1			13
+#define IRQ_MDMA0			12
+#define IRQ_SPI				11
+#define IRQ_IPSEC_CORE			10
+#define IRQ_IPSEC_WRAP			9
+#define IRQ_TDMA			8
+#define IRQ_EMAC1			7
+#define IRQ_EMAC0			6
+#define IRQ_USB0			5
+#define IRQ_TDM_TIMER			4
+#define IRQ_PTP2			3
+#define IRQ_PTP1			2
+#define IRQ_PTP0			1
+#define STATUS_REG_1			0
+
+/* INTC1 32 next IRQs*/
+/*	#define IRQ_Reserved		31*/
+/*	#define IRQ_Reserved		30*/
+/*	#define IRQ_Reserved		29*/
+#define IRQ_TDMA_TxAHBErr		(28 + 32)
+#define IRQ_TDMA_RxAHBErr		(27 + 32)
+#define IRQ_UART1			(26 + 32)
+#define IRQ_CSP_HIDRV			(25 + 32)
+#define IRQ_CSPVED1TX			(24 + 32)
+#define IRQ_CSPVED1RX			(23 + 32)
+#define IRQ_CSPVED0TX			(22 + 32)
+#define IRQ_CSPVED0RX			(21 + 32)
+#define IRQ_TOHOST			(20 + 32)
+#define IRQ_FROMHOST			(19 + 32)
+#define IRQ_MSP_PMU			(18 + 32)
+#define IRQ_CSP_PMU			(17 + 32)
+/*	#define IRQ_Reserved		16*/
+/*	#define IRQ_Reserved		15*/
+/*	#define IRQ_Reserved		14*/
+#define IRQ_SPDRV_ACP_REQ		(13 + 32)
+#define IRQ_SPDRV_ACP_WORK_DONE		(12 + 32)
+#define IRQ_VED				(11 + 32)
+#define IRQ_TDMA_IND			(10 + 32)
+#define IRQ_UART0			(9 + 32)
+#define IRQ_G7				(8 + 32)
+#define IRQ_G6				(7 + 32)
+#define IRQ_G5				(6 + 32)
+#define IRQ_G4				(5 + 32)
+#define IRQ_G3				(4 + 32)
+#define IRQ_G2				(3 + 32)
+#define IRQ_G1				(2 + 32)
+#define IRQ_G0				(1 + 32)
+#define STATUS_REG_0			(0 + 32)
+
+/* Software decoded interrupts used by PCIE */
+#define IRQ_PCIE0_MSI0			64
+#define IRQ_PCIE0_MSI1			65
+#define IRQ_PCIE0_MSI2			66
+#define IRQ_PCIE0_MSI3			67
+
+#define IRQ_PCIE0_INTA			68
+#define IRQ_PCIE0_INTB			69
+#define IRQ_PCIE0_INTC			70
+#define IRQ_PCIE0_INTD			71
+
+#define IRQ_PCIE1_MSI0			72
+#define IRQ_PCIE1_MSI1			73
+#define IRQ_PCIE1_MSI2			74
+#define IRQ_PCIE1_MSI3			75
+
+#define IRQ_PCIE1_INTA			76
+#define IRQ_PCIE1_INTB			77
+#define IRQ_PCIE1_INTC			78
+#define IRQ_PCIE1_INTD			79
+
+
+#define NR_IRQS				80
+
+#define IRQ_TIMERB		IRQ_TIMER1
+#define IRQ_FPP			IRQ_CSP_HIDRV
+
+#define FPP_IRQ_FROMHOST	IRQ_FROMHOST
+#define FPP_IRQ_TOHOST		IRQ_TOHOST
+#define FPP_IRQ_EVENT		IRQ_FPP
+#endif
diff --git a/arch/arm/mach-comcerto/include/mach/hardware.h b/arch/arm/mach-comcerto/include/mach/hardware.h
index 577289d..da023b2 100644
--- a/arch/arm/mach-comcerto/include/mach/hardware.h
+++ b/arch/arm/mach-comcerto/include/mach/hardware.h
@@ -32,6 +32,7 @@
 struct sys_timer;
 extern struct sys_timer comcerto_timer;
 extern void device_map_io(void);
+extern void device_irq_init(void);
 #endif
 
 #endif
diff --git a/arch/arm/mach-comcerto/include/mach/irq.h b/arch/arm/mach-comcerto/include/mach/irq.h
new file mode 100644
index 0000000..b5b8a54
--- /dev/null
+++ b/arch/arm/mach-comcerto/include/mach/irq.h
@@ -0,0 +1,155 @@
+/*
+ *  arch/arm/mach-comcerto/include/mach/irq.h
+ *
+ *  Copyright (C) 2004,2008 Mindspeed Technologies, 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 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
+ */
+#ifndef __ASM_ARCH_IRQ_H
+#define __ASM_ARCH_IRQ_H
+
+#include <linux/irq.h>
+#include <asm/io.h>
+
+extern spinlock_t comcerto_irq_lock;
+extern int noirqdebug;
+
+struct comcerto_irq_desc {
+	char num;
+	irq_flow_handler_t handler;
+	unsigned int prio;
+};
+
+void comcerto_handle_secondary_level_irq(unsigned int irq, struct irq_desc *);
+void __init comcerto_irq_init(struct comcerto_irq_desc *irq_table, int size);
+
+/* For all devices with priority support we provide a call to change STATUS1
+ * priority from the EVM-specific code. Priority value should be in [0..31]
+ * range.
+ */
+void __init comcerto_irq_status1_priority_set(unsigned char priority);
+
+static inline u32 comcerto_irq_to_mask(unsigned int irq)
+{
+	return 1 << ((irq) & 0x1f);
+}
+
+static inline void comcerto_irq_mask_0(unsigned int irq)
+{
+	unsigned long flags;
+	unsigned long mask;
+
+	spin_lock_irqsave(&comcerto_irq_lock, flags);
+	mask = __raw_readl(COMCERTO_INTC_CSP_IRQMASK_0);
+	mask &= ~comcerto_irq_to_mask(irq);
+	__raw_writel(mask, COMCERTO_INTC_CSP_IRQMASK_0);
+	spin_unlock_irqrestore(&comcerto_irq_lock, flags);
+}
+
+static inline void comcerto_irq_mask_1(unsigned int irq)
+{
+	unsigned long flags;
+	unsigned long mask;
+
+	spin_lock_irqsave(&comcerto_irq_lock, flags);
+	mask = __raw_readl(COMCERTO_INTC_CSP_IRQMASK_1);
+	mask &= ~comcerto_irq_to_mask(irq);
+	__raw_writel(mask, COMCERTO_INTC_CSP_IRQMASK_1);
+	spin_unlock_irqrestore(&comcerto_irq_lock, flags);
+}
+
+static inline void comcerto_irq_mask(unsigned int irq)
+{
+	if (irq < 32)
+		comcerto_irq_mask_0(irq);
+	else
+		comcerto_irq_mask_1(irq);
+}
+
+static inline void comcerto_irq_ack_0(unsigned int irq)
+{
+	__raw_writel(comcerto_irq_to_mask(irq), COMCERTO_INTC_STATUS_REG_0);
+}
+
+static inline void comcerto_irq_ack_1(unsigned int irq)
+{
+	__raw_writel(comcerto_irq_to_mask(irq), COMCERTO_INTC_STATUS_REG_1);
+}
+
+static inline void comcerto_irq_ack(unsigned int irq)
+{
+	if (irq < 32)
+		comcerto_irq_ack_0(irq);
+	else
+		comcerto_irq_ack_1(irq);
+}
+
+static inline void comcerto_irq_unmask_0(unsigned int irq)
+{
+	unsigned long flags;
+	unsigned long mask;
+
+	spin_lock_irqsave(&comcerto_irq_lock, flags);
+	mask = __raw_readl(COMCERTO_INTC_CSP_IRQMASK_0);
+	mask |= comcerto_irq_to_mask(irq);
+	__raw_writel(mask, COMCERTO_INTC_CSP_IRQMASK_0);
+	spin_unlock_irqrestore(&comcerto_irq_lock, flags);
+}
+
+static inline void comcerto_irq_unmask_1(unsigned int irq)
+{
+	unsigned long flags;
+	unsigned long mask;
+
+	spin_lock_irqsave(&comcerto_irq_lock, flags);
+	mask = __raw_readl(COMCERTO_INTC_CSP_IRQMASK_1);
+	mask |= comcerto_irq_to_mask(irq);
+	__raw_writel(mask, COMCERTO_INTC_CSP_IRQMASK_1);
+	spin_unlock_irqrestore(&comcerto_irq_lock, flags);
+}
+
+static inline void comcerto_irq_unmask(unsigned int irq)
+{
+	if (irq < 32)
+		comcerto_irq_unmask_0(irq);
+	else
+		comcerto_irq_unmask_1(irq);
+}
+
+static inline void comcerto_softirq_set(unsigned int irq)
+{
+	void *reg;
+
+	if (irq < 32)
+		reg = (void *)COMCERTO_INTC_SET_STATUS_REG_0;
+	else
+		reg = (void *)COMCERTO_INTC_SET_STATUS_REG_1;
+
+	__raw_writel(comcerto_irq_to_mask(irq), reg);
+}
+
+static inline int comcerto_softirq_check(unsigned int irq)
+{
+	void *reg;
+
+	if (irq < 32)
+		reg = (void *)COMCERTO_INTC_STATUS_REG_0;
+	else
+		reg = (void *)COMCERTO_INTC_STATUS_REG_1;
+
+	return __raw_readl(reg) & comcerto_irq_to_mask(irq) ? 1 : 0;
+}
+
+#endif /* __ASM_ARCH_IRQ_H */
diff --git a/arch/arm/mach-comcerto/include/mach/irqs.h b/arch/arm/mach-comcerto/include/mach/irqs.h
new file mode 100644
index 0000000..409281b
--- /dev/null
+++ b/arch/arm/mach-comcerto/include/mach/irqs.h
@@ -0,0 +1,21 @@
+/*
+ *  arch/arm/mach-comcerto/include/mach/irqs.h
+ *
+ *  Copyright (C) 2004,2005 Mindspeed Technologies, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#ifndef __ASM_ARCH_IRQS_H
+#define __ASM_ARCH_IRQS_H
+
+#if defined(CONFIG_ARCH_M83XXX)
+	#include <mach/comcerto-1000/irqs.h>
+#else
+	#error "Unsupported CPU"
+#endif
+
+#endif  /* __ASM_ARCH_IRQS_H */
diff --git a/arch/arm/mach-comcerto/irq.c b/arch/arm/mach-comcerto/irq.c
new file mode 100644
index 0000000..4288ba1
--- /dev/null
+++ b/arch/arm/mach-comcerto/irq.c
@@ -0,0 +1,200 @@
+/*
+ *  linux/arch/arm/mach-comcerto/irq.c
+ *
+ *  Copyright (C) 2004-2008 Mindspeed Technologies, Inc.
+ *  Copyright (c) 2010 Wind River Systems, 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 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/ptrace.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+#include <linux/kernel_stat.h>
+
+#include <asm/irq.h>
+#include <linux/io.h>
+#include <asm/mach/irq.h>
+#include <mach/hardware.h>
+
+#include <mach/irq.h>
+#include <mach/irqs.h>
+
+spinlock_t comcerto_irq_lock;
+
+static void comcerto_irq_mask_ack_0(unsigned int irq)
+{
+	comcerto_irq_mask_0(irq);
+	comcerto_irq_ack_0(irq);
+}
+
+static void comcerto_irq_mask_ack_1(unsigned int irq)
+{
+	comcerto_irq_mask_1(irq);
+	comcerto_irq_ack_1(irq);
+}
+
+static int comcerto_set_irq_type_0(unsigned int irq, unsigned int type)
+{
+	return 0;
+}
+
+static int comcerto_set_irq_type_1(unsigned int irq, unsigned int type)
+{
+	return 0;
+}
+
+static struct irq_chip comcerto_irq_chip_0 = {
+	.name		= "Comcerto INTC0",
+	.disable	= comcerto_irq_mask_0,
+	.ack		= comcerto_irq_ack_0,
+	.mask		= comcerto_irq_mask_0,
+	.unmask		= comcerto_irq_unmask_0,
+	.set_type	= comcerto_set_irq_type_0,
+	.mask_ack	= comcerto_irq_mask_ack_0,
+};
+
+static struct irq_chip comcerto_irq_chip_1 = {
+	.name		= "Comcerto INTC1",
+	.disable	= comcerto_irq_mask_1,
+	.ack		= comcerto_irq_ack_1,
+	.mask		= comcerto_irq_mask_1,
+	.unmask		= comcerto_irq_unmask_1,
+	.set_type	= comcerto_set_irq_type_1,
+	.mask_ack	= comcerto_irq_mask_ack_1,
+};
+
+void comcerto_handle_secondary_level_irq(unsigned int irq,
+						struct irq_desc *desc)
+{
+	struct irqaction *action;
+	irqreturn_t action_ret;
+
+	raw_spin_lock(&desc->lock);
+	desc->chip->mask(irq);
+
+	if (unlikely(desc->status & IRQ_INPROGRESS))
+		goto out_unlock;
+	desc->status &= ~(IRQ_REPLAY | IRQ_WAITING);
+	kstat_incr_irqs_this_cpu(irq, desc);
+	/*
+	 * If its disabled or no action available
+	 * keep it masked and get out of here
+	 */
+	action = desc->action;
+	if (unlikely(!action || (desc->status & IRQ_DISABLED))) {
+		desc->status |= IRQ_PENDING;
+		goto out_unlock;
+	}
+
+	desc->status |= IRQ_INPROGRESS;
+	desc->status &= ~IRQ_PENDING;
+	raw_spin_unlock(&desc->lock);
+
+	action_ret = handle_IRQ_event(irq, action);
+	if (!noirqdebug)
+		note_interrupt(irq, desc, action_ret);
+
+	raw_spin_lock(&desc->lock);
+	desc->status &= ~IRQ_INPROGRESS;
+
+	desc->chip->ack(irq);
+
+	if (unlikely(desc->status & IRQ_ONESHOT))
+		desc->status |= IRQ_MASKED;
+	else if (!(desc->status & IRQ_DISABLED) && desc->chip->unmask)
+		desc->chip->unmask(irq);
+out_unlock:
+	raw_spin_unlock(&desc->lock);
+}
+
+static u8 comcerto_status0_priorities[32] __initdata = {0, };
+
+static __init void comcerto_irq_priority_set(unsigned int irq, unsigned int prio)
+{
+	unsigned int prio_reg, prio_shift, prio_mask, tmp;
+
+	/* we store +1 priority to reserve zero for non-used slots */
+	comcerto_status0_priorities[irq] = prio + 1;
+	prio_reg = COMCERTO_INTC_CSP_PRTY_0 + 4 * (prio / 4);
+	prio_shift = ((prio % 4) << 3);
+	prio_mask = 0x1f << prio_shift;
+	tmp = __raw_readl(prio_reg) & ~prio_mask;
+	tmp |= irq << prio_shift;
+	__raw_writel(tmp, prio_reg);
+}
+
+void __init comcerto_irq_status1_priority_set(unsigned char priority)
+{
+	int i;
+	unsigned long flags;
+
+	if ((priority & ~31) != 0)
+		BUG();
+
+	priority++;	/*  */
+
+	spin_lock_irqsave(&comcerto_irq_lock, flags);
+
+	/* look at all interrupts except STATUS1 and
+	 * fix all priorities >= specified */
+	for (i = 1; i < 32; i++)
+		if (comcerto_status0_priorities[i] >= priority \
+				&& comcerto_status0_priorities[i] > 0)
+			comcerto_status0_priorities[i]++;
+
+	comcerto_status0_priorities[0] = priority;
+
+	/* program all non-zero priorities,
+	 * don't forget to decrement priority value taken from array */
+	for (i = 0; i < 32; i++)
+		if (comcerto_status0_priorities[i] > 0)
+			comcerto_irq_priority_set(i, comcerto_status0_priorities[i] - 1);
+
+	spin_unlock_irqrestore(&comcerto_irq_lock, flags);
+}
+
+void __init comcerto_irq_init(struct comcerto_irq_desc *irq_table, int size)
+{
+	unsigned int irq;
+	int i;
+
+	spin_lock_init(&comcerto_irq_lock);
+
+	/* mask all interrupts */
+	__raw_writel(0, COMCERTO_INTC_CSP_IRQMASK_0);
+	__raw_writel(0, COMCERTO_INTC_CSP_IRQMASK_1);
+
+	for (i = 0; i < size; i++) {
+		irq = irq_table[i].num;
+
+		/* setup interrupt handler and priority */
+		if (irq < 32) {
+			/* All STATUS0 interrupts must be setup from
+			 * the single table declared in comcerto-xxx.c
+			 * file. Use description index as a priority.
+			 */
+			comcerto_irq_priority_set(irq, irq_table[i].prio);
+			set_irq_chip(irq, &comcerto_irq_chip_0);
+		} else
+			set_irq_chip(irq, &comcerto_irq_chip_1);
+
+		if (irq_table[i].handler != NULL) {
+			set_irq_handler(irq, irq_table[i].handler);
+			set_irq_flags(irq, IRQF_VALID);
+		}
+	}
+}
-- 
1.5.4.3




More information about the linux-arm-kernel mailing list