[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