[PATCHv2 04/11] mxc: changes to common plat-mxc code to add support for i.MX5
Sascha Hauer
s.hauer at pengutronix.de
Wed Feb 3 04:49:59 EST 2010
On Tue, Feb 02, 2010 at 10:43:33PM -0800, Eric Miao wrote:
>
> Mmm.... this should be something that we really need to get rid of, it just
> makes a single kernel for both TZIC and AVIC together impossible, if that's
> so designed by HW, I'm thinking about keeping this into plat-mxc/ is a good
> way to go ...
>
> Sascha, you have any better idea? Provided the other file debug-macro.S in
> the same directory already seems to break the support for multiple arches?
>
I have the following patch which I'm not sure I like better. It can
support both irq controller types and does not add overhead if only one
of them is compiled in. It might need some refactoring to fit into Amits
patch stack.
Sascha
commit c30ed01dcd257bba813b27a423bc54d5f32fc878
Author: Sascha Hauer <s.hauer at pengutronix.de>
Date: Tue Nov 17 16:23:24 2009 +0100
MXC tzic support
Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
diff --git a/arch/arm/plat-mxc/Kconfig b/arch/arm/plat-mxc/Kconfig
index ebe4b8c..377f792 100644
--- a/arch/arm/plat-mxc/Kconfig
+++ b/arch/arm/plat-mxc/Kconfig
@@ -84,4 +84,7 @@ config ARCH_MXC_IOMUX_V3
config ARCH_MXC_AVIC
bool
+config ARCH_MXC_TZIC
+ bool
+
endif
diff --git a/arch/arm/plat-mxc/Makefile b/arch/arm/plat-mxc/Makefile
index 325d9da..37ce6ec 100644
--- a/arch/arm/plat-mxc/Makefile
+++ b/arch/arm/plat-mxc/Makefile
@@ -9,4 +9,5 @@ obj-$(CONFIG_ARCH_MX1) += iomux-mx1-mx2.o dma-mx1-mx2.o
obj-$(CONFIG_ARCH_MX2) += iomux-mx1-mx2.o dma-mx1-mx2.o
obj-$(CONFIG_ARCH_MXC_IOMUX_V3) += iomux-v3.o
obj-$(CONFIG_MXC_PWM) += pwm.o
+obj-$(CONFIG_ARCH_MXC_TZIC) += tzic.o
obj-$(CONFIG_ARCH_MXC_AVIC) += irq.o
diff --git a/arch/arm/plat-mxc/cpu.c b/arch/arm/plat-mxc/cpu.c
index b073b7d..d46325e 100644
--- a/arch/arm/plat-mxc/cpu.c
+++ b/arch/arm/plat-mxc/cpu.c
@@ -11,4 +11,5 @@ void mxc_set_cpu_type(unsigned int type)
}
void __iomem *mxc_irq_base;
+int mxc_irq_controller_type;
diff --git a/arch/arm/plat-mxc/include/mach/common.h b/arch/arm/plat-mxc/include/mach/common.h
index 286cb9b..d395763 100644
--- a/arch/arm/plat-mxc/include/mach/common.h
+++ b/arch/arm/plat-mxc/include/mach/common.h
@@ -44,5 +44,5 @@ extern void mxc_arch_reset_init(void __iomem *);
extern void mxc91231_power_off(void);
extern void mxc91231_arch_reset(int, const char *);
extern void mxc91231_prepare_idle(void);
-
+extern void tzic_init_irq(void __iomem *);
#endif
diff --git a/arch/arm/plat-mxc/include/mach/entry-macro.S b/arch/arm/plat-mxc/include/mach/entry-macro.S
index 55375df..049f740 100644
--- a/arch/arm/plat-mxc/include/mach/entry-macro.S
+++ b/arch/arm/plat-mxc/include/mach/entry-macro.S
@@ -13,6 +13,9 @@
#define AVIC_NIMASK 0x04
+#define TZIC_HIPND0 0xd80
+
+
@ this macro disables fast irq (not implemented)
.macro disable_fiq
.endm
@@ -28,10 +31,35 @@
.macro arch_ret_to_user, tmp1, tmp2
.endm
- @ this macro checks which interrupt occured
- @ and returns its number in irqnr
- @ and returns if an interrupt occured in irqstat
- .macro get_irqnr_and_base, irqnr, irqstat, base, tmp
+ .macro tzic_get_irqnr_and_base, irqnr, irqstat, base, tmp
+
+ @ Load offset & priority of the highest priority
+ @ interrupt pending.
+ ldr \irqnr, =0
+ ldr \irqstat, =TZIC_HIPND0
+1000:
+ ldr \tmp, [\base, \irqstat]
+ cmp \tmp, #0
+ bne 1001f
+ addeq \irqnr, \irqnr, #32
+ addeq \irqstat, \irqstat, #4
+ cmp \irqnr, #128
+ blo 1000b
+ b 2001f
+1001: ldr \irqstat, =1
+1002: tst \tmp, \irqstat
+ bne 2002f
+ movs \irqstat, \irqstat, lsl #1
+ addne \irqnr, \irqnr, #1
+ bne 1002b
+2001:
+ ldr \irqnr, =0
+2002:
+ movs \irqnr, \irqnr
+ .endm
+
+ .macro avic_get_irqnr_and_base, irqnr, irqstat, base, tmp
+
@ Load offset & priority of the highest priority
@ interrupt pending from AVIC_NIVECSR
ldr \irqstat, [\base, #0x40]
@@ -47,6 +75,28 @@
#endif
.endm
+ .macro get_irqnr_and_base, irqnr, irqstat, base, tmp
+#if defined CONFIG_ARCH_MXC_TZIC && defined CONFIG_ARCH_MXC_AVIC
+ ldr \tmp, =mxc_irq_controller_type
+ ldr \tmp, [\tmp]
+ cmp \tmp, #MXC_IRQ_TYPE_AVIC
+ beq 3001f
+
+ tzic_get_irqnr_and_base \irqnr, \irqstat, \base, \tmp
+ b 3002f
+3001:
+ avic_get_irqnr_and_base \irqnr, \irqstat, \base, \tmp
+3002:
+
+#elif defined CONFIG_ARCH_MXC_TZIC
+ tzic_get_irqnr_and_base \irqnr, \irqstat, \base, \tmp
+#elif defined CONFIG_ARCH_MXC_AVIC
+ avic_get_irqnr_and_base \irqnr, \irqstat, \base, \tmp
+#else
+#error no tzic and no avic?
+#endif
+ .endm
+
@ irq priority table (not used)
.macro irq_prio_table
.endm
diff --git a/arch/arm/plat-mxc/include/mach/mxc.h b/arch/arm/plat-mxc/include/mach/mxc.h
index b64a269..6cf0f98 100644
--- a/arch/arm/plat-mxc/include/mach/mxc.h
+++ b/arch/arm/plat-mxc/include/mach/mxc.h
@@ -129,8 +129,12 @@ extern unsigned int __mxc_cpu_type;
#define cpu_is_mx3() (cpu_is_mx31() || cpu_is_mx35() || cpu_is_mxc91231())
#define cpu_is_mx2() (cpu_is_mx21() || cpu_is_mx27())
+#define MXC_IRQ_TYPE_AVIC 1
+#define MXC_IRQ_TYPE_TZIC 2
+
#ifndef __ASSEMBLY__
extern void __iomem *mxc_irq_base;
+extern int mxc_irq_controller_type;
#endif
#endif /* __ASM_ARCH_MXC_H__ */
diff --git a/arch/arm/plat-mxc/irq.c b/arch/arm/plat-mxc/irq.c
index 4855a65..3e7ac84 100644
--- a/arch/arm/plat-mxc/irq.c
+++ b/arch/arm/plat-mxc/irq.c
@@ -116,6 +116,7 @@ void __init mxc_init_irq(void __iomem *irqbase)
int i;
mxc_irq_base = irqbase;
+ mxc_irq_controller_type = MXC_IRQ_TYPE_AVIC;
/* put the AVIC into the reset value with
* all interrupts disabled
diff --git a/arch/arm/plat-mxc/tzic.c b/arch/arm/plat-mxc/tzic.c
new file mode 100644
index 0000000..2d14af4
--- /dev/null
+++ b/arch/arm/plat-mxc/tzic.c
@@ -0,0 +1,104 @@
+/*
+ * Copyright 2004-2008 Freescale Semiconductor, Inc. All Rights Reserved.
+ */
+
+/*
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/errno.h>
+#include <linux/io.h>
+#include <asm/irq.h>
+#include <asm/mach/irq.h>
+#include <mach/common.h>
+#include <mach/hardware.h>
+
+extern void __iomem *mxc_irq_base;
+extern int mxc_irq_controller_type;
+
+#define TZIC_INTCNTL 0x0000 /* control register */
+#define TZIC_INTTYPE 0x0004 /* Controller type register */
+#define TZIC_IMPID 0x0008 /* Distributor Implementer Identification Register */
+#define TZIC_PRIOMASK 0x000c /* Priority Mask Reg */
+#define TZIC_SYNCCTRL 0x0010 /* Synchronizer Control register */
+#define TZIC_DSMINT 0x0014 /* DSM interrupt Holdoffregister */
+#define TZIC_INTSEC0 0x0080 /* interrupt security register 0 */
+#define TZIC_ENSET0 0x0100 /* Enable Set Register 0 */
+#define TZIC_ENCLEAR0 0x0180 /* Enable Clear Register 0 */
+#define TZIC_SRCSET0 0x0200 /* Source Set Register 0 */
+#define TZIC_SRCCLAR0 0x0280 /* Source Clear Register 0 */
+#define TZIC_PRIORITY0 0x0400 /* Priority Register 0 */
+#define TZIC_PND0 0x0d00 /* Pending Register 0 */
+#define TZIC_HIPND0 0x0d80 /* High Priority Pending Register */
+#define TZIC_WAKEUP0 0x0e00 /* Wakeup Config Register */
+#define TZIC_SWINT 0x0f00 /* Software Interrupt Rigger Register */
+#define TZIC_ID0 0x0fd0 /* Indentification Register 0 */
+
+static void mxc_mask_irq(unsigned int irq)
+{
+ int index, off;
+
+ index = irq >> 5;
+ off = irq & 0x1F;
+ __raw_writel(1 << off, mxc_irq_base + TZIC_ENCLEAR0 + (index << 2));
+}
+
+static void mxc_unmask_irq(unsigned int irq)
+{
+ int index, off;
+
+ index = irq >> 5;
+ off = irq & 0x1F;
+ __raw_writel(1 << off, mxc_irq_base + TZIC_ENSET0 + (index << 2));
+}
+
+static struct irq_chip mxc_tzic_chip = {
+ .name = "MXC_TZIC",
+ .ack = mxc_mask_irq,
+ .mask = mxc_mask_irq,
+ .unmask = mxc_unmask_irq,
+};
+
+void __init tzic_init_irq(void __iomem *base)
+{
+ int i;
+
+ mxc_irq_base = base;
+ mxc_irq_controller_type = MXC_IRQ_TYPE_TZIC;
+
+ /* put the TZIC into the reset value with
+ * all interrupts disabled
+ */
+ __raw_readl(mxc_irq_base + TZIC_INTCNTL);
+
+ __raw_writel(0x80010001, mxc_irq_base + TZIC_INTCNTL);
+ __raw_readl(mxc_irq_base + TZIC_INTCNTL);
+ __raw_writel(0x1f, mxc_irq_base + TZIC_PRIOMASK);
+ __raw_readl(mxc_irq_base + TZIC_PRIOMASK);
+ __raw_writel(0x02, mxc_irq_base + TZIC_SYNCCTRL);
+ __raw_readl(mxc_irq_base + TZIC_SYNCCTRL);
+
+ for (i = 0; i < 4; i++)
+ __raw_writel(0xffffffff, mxc_irq_base + TZIC_INTSEC0 + i * 4);
+
+ /* disable all interrupts */
+ for (i = 0; i < 4; i++)
+ __raw_writel(0xffffffff, mxc_irq_base + TZIC_ENCLEAR0 + i * 4);
+
+ for (i = 0; i < 128; i++) {
+ set_irq_chip(i, &mxc_tzic_chip);
+ set_irq_handler(i, handle_level_irq);
+ set_irq_flags(i, IRQF_VALID);
+ }
+
+ printk(KERN_INFO "MXC IRQ initialized\n");
+}
--
Pengutronix e.K. | |
Industrial Linux Solutions | http://www.pengutronix.de/ |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
More information about the linux-arm-kernel
mailing list