aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPeter Horton <phorton@bitbox.co.uk>2010-12-06 06:37:38 -0500
committerSascha Hauer <s.hauer@pengutronix.de>2010-12-14 03:54:37 -0500
commitcdc3f10630ecddb7870e087ff9679eef3d7b4e21 (patch)
treebcffe39f52a334e9ad8e56b15843a42e228988da
parent8be9252f7ccde4148e4b203bf64d38ae66b111e4 (diff)
mx51: support FIQ on TZIC, revised
Add support for FIQ on mx51 TZIC TZIC changes tested with FIQ audio on an mx51 board AVIC changes build with mx3_defconfig, not tested Signed-off-by: Peter Horton <phorton@bitbox.co.uk> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
-rw-r--r--arch/arm/plat-mxc/Makefile2
-rw-r--r--arch/arm/plat-mxc/avic.c32
-rw-r--r--arch/arm/plat-mxc/include/mach/entry-macro.S14
-rw-r--r--arch/arm/plat-mxc/irq-common.c60
-rw-r--r--arch/arm/plat-mxc/irq-common.h29
-rw-r--r--arch/arm/plat-mxc/tzic.c46
6 files changed, 155 insertions, 28 deletions
diff --git a/arch/arm/plat-mxc/Makefile b/arch/arm/plat-mxc/Makefile
index 989cb59e67ac..5fd20e96876c 100644
--- a/arch/arm/plat-mxc/Makefile
+++ b/arch/arm/plat-mxc/Makefile
@@ -3,7 +3,7 @@
3# 3#
4 4
5# Common support 5# Common support
6obj-y := clock.o gpio.o time.o devices.o cpu.o system.o 6obj-y := clock.o gpio.o time.o devices.o cpu.o system.o irq-common.o
7 7
8# MX51 uses the TZIC interrupt controller, older platforms use AVIC 8# MX51 uses the TZIC interrupt controller, older platforms use AVIC
9obj-$(CONFIG_MXC_TZIC) += tzic.o 9obj-$(CONFIG_MXC_TZIC) += tzic.o
diff --git a/arch/arm/plat-mxc/avic.c b/arch/arm/plat-mxc/avic.c
index 7331f2ace5fe..9a4e8a22dd0a 100644
--- a/arch/arm/plat-mxc/avic.c
+++ b/arch/arm/plat-mxc/avic.c
@@ -24,6 +24,8 @@
24#include <asm/mach/irq.h> 24#include <asm/mach/irq.h>
25#include <mach/hardware.h> 25#include <mach/hardware.h>
26 26
27#include "irq-common.h"
28
27#define AVIC_INTCNTL 0x00 /* int control reg */ 29#define AVIC_INTCNTL 0x00 /* int control reg */
28#define AVIC_NIMASK 0x04 /* int mask reg */ 30#define AVIC_NIMASK 0x04 /* int mask reg */
29#define AVIC_INTENNUM 0x08 /* int enable number reg */ 31#define AVIC_INTENNUM 0x08 /* int enable number reg */
@@ -46,9 +48,9 @@
46 48
47void __iomem *avic_base; 49void __iomem *avic_base;
48 50
49int imx_irq_set_priority(unsigned char irq, unsigned char prio)
50{
51#ifdef CONFIG_MXC_IRQ_PRIOR 51#ifdef CONFIG_MXC_IRQ_PRIOR
52static int avic_irq_set_priority(unsigned char irq, unsigned char prio)
53{
52 unsigned int temp; 54 unsigned int temp;
53 unsigned int mask = 0x0F << irq % 8 * 4; 55 unsigned int mask = 0x0F << irq % 8 * 4;
54 56
@@ -62,14 +64,11 @@ int imx_irq_set_priority(unsigned char irq, unsigned char prio)
62 __raw_writel(temp, avic_base + AVIC_NIPRIORITY(irq / 8)); 64 __raw_writel(temp, avic_base + AVIC_NIPRIORITY(irq / 8));
63 65
64 return 0; 66 return 0;
65#else
66 return -ENOSYS;
67#endif
68} 67}
69EXPORT_SYMBOL(imx_irq_set_priority); 68#endif
70 69
71#ifdef CONFIG_FIQ 70#ifdef CONFIG_FIQ
72int mxc_set_irq_fiq(unsigned int irq, unsigned int type) 71static int avic_set_irq_fiq(unsigned int irq, unsigned int type)
73{ 72{
74 unsigned int irqt; 73 unsigned int irqt;
75 74
@@ -87,7 +86,6 @@ int mxc_set_irq_fiq(unsigned int irq, unsigned int type)
87 86
88 return 0; 87 return 0;
89} 88}
90EXPORT_SYMBOL(mxc_set_irq_fiq);
91#endif /* CONFIG_FIQ */ 89#endif /* CONFIG_FIQ */
92 90
93/* Disable interrupt number "irq" in the AVIC */ 91/* Disable interrupt number "irq" in the AVIC */
@@ -102,10 +100,18 @@ static void mxc_unmask_irq(unsigned int irq)
102 __raw_writel(irq, avic_base + AVIC_INTENNUM); 100 __raw_writel(irq, avic_base + AVIC_INTENNUM);
103} 101}
104 102
105static struct irq_chip mxc_avic_chip = { 103static struct mxc_irq_chip mxc_avic_chip = {
106 .ack = mxc_mask_irq, 104 .base = {
107 .mask = mxc_mask_irq, 105 .ack = mxc_mask_irq,
108 .unmask = mxc_unmask_irq, 106 .mask = mxc_mask_irq,
107 .unmask = mxc_unmask_irq,
108 },
109#ifdef CONFIG_MXC_IRQ_PRIOR
110 .set_priority = avic_irq_set_priority,
111#endif
112#ifdef CONFIG_FIQ
113 .set_irq_fiq = avic_set_irq_fiq,
114#endif
109}; 115};
110 116
111/* 117/*
@@ -133,7 +139,7 @@ void __init mxc_init_irq(void __iomem *irqbase)
133 __raw_writel(0, avic_base + AVIC_INTTYPEH); 139 __raw_writel(0, avic_base + AVIC_INTTYPEH);
134 __raw_writel(0, avic_base + AVIC_INTTYPEL); 140 __raw_writel(0, avic_base + AVIC_INTTYPEL);
135 for (i = 0; i < MXC_INTERNAL_IRQS; i++) { 141 for (i = 0; i < MXC_INTERNAL_IRQS; i++) {
136 set_irq_chip(i, &mxc_avic_chip); 142 set_irq_chip(i, &mxc_avic_chip.base);
137 set_irq_handler(i, handle_level_irq); 143 set_irq_handler(i, handle_level_irq);
138 set_irq_flags(i, IRQF_VALID); 144 set_irq_flags(i, IRQF_VALID);
139 } 145 }
diff --git a/arch/arm/plat-mxc/include/mach/entry-macro.S b/arch/arm/plat-mxc/include/mach/entry-macro.S
index aeb08697726b..bd9bb9799141 100644
--- a/arch/arm/plat-mxc/include/mach/entry-macro.S
+++ b/arch/arm/plat-mxc/include/mach/entry-macro.S
@@ -54,15 +54,15 @@
54#elif defined CONFIG_MXC_TZIC 54#elif defined CONFIG_MXC_TZIC
55 @ Load offset & priority of the highest priority 55 @ Load offset & priority of the highest priority
56 @ interrupt pending. 56 @ interrupt pending.
57 @ 0x080 is INTSEC0 register
57 @ 0xD80 is HIPND0 register 58 @ 0xD80 is HIPND0 register
58 mov \irqnr, #0 59 mov \irqnr, #0
59 mov \irqstat, #0x0D80 601000: add \irqstat, \base, \irqnr, lsr #3
601000: 61 ldr \tmp, [\irqstat, #0xd80]
61 ldr \tmp, [\irqstat, \base] 62 ldr \irqstat, [\irqstat, #0x080]
62 cmp \tmp, #0 63 ands \tmp, \tmp, \irqstat
63 bne 1001f 64 bne 1001f
64 addeq \irqnr, \irqnr, #32 65 add \irqnr, \irqnr, #32
65 addeq \irqstat, \irqstat, #4
66 cmp \irqnr, #128 66 cmp \irqnr, #128
67 blo 1000b 67 blo 1000b
68 b 2001f 68 b 2001f
diff --git a/arch/arm/plat-mxc/irq-common.c b/arch/arm/plat-mxc/irq-common.c
new file mode 100644
index 000000000000..0c799ac27730
--- /dev/null
+++ b/arch/arm/plat-mxc/irq-common.c
@@ -0,0 +1,60 @@
1/*
2 * Copyright (C) BitBox Ltd 2010
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
16 * MA 02110-1301, USA.
17 */
18
19#include <linux/module.h>
20#include <linux/irq.h>
21
22#include "irq-common.h"
23
24int imx_irq_set_priority(unsigned char irq, unsigned char prio)
25{
26 struct mxc_irq_chip *chip;
27 struct irq_chip *base;
28 int ret;
29
30 ret = -ENOSYS;
31
32 base = get_irq_chip(irq);
33 if (base) {
34 chip = container_of(base, struct mxc_irq_chip, base);
35 if (chip->set_priority)
36 ret = chip->set_priority(irq, prio);
37 }
38
39 return ret;
40}
41EXPORT_SYMBOL(imx_irq_set_priority);
42
43int mxc_set_irq_fiq(unsigned int irq, unsigned int type)
44{
45 struct mxc_irq_chip *chip;
46 struct irq_chip *base;
47 int ret;
48
49 ret = -ENOSYS;
50
51 base = get_irq_chip(irq);
52 if (base) {
53 chip = container_of(base, struct mxc_irq_chip, base);
54 if (chip->set_irq_fiq)
55 ret = chip->set_irq_fiq(irq, type);
56 }
57
58 return ret;
59}
60EXPORT_SYMBOL(mxc_set_irq_fiq);
diff --git a/arch/arm/plat-mxc/irq-common.h b/arch/arm/plat-mxc/irq-common.h
new file mode 100644
index 000000000000..7203543fb1b3
--- /dev/null
+++ b/arch/arm/plat-mxc/irq-common.h
@@ -0,0 +1,29 @@
1/*
2 * Copyright (C) BitBox Ltd 2010
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
16 * MA 02110-1301, USA.
17 */
18
19#ifndef __PLAT_MXC_IRQ_COMMON_H__
20#define __PLAT_MXC_IRQ_COMMON_H__
21
22struct mxc_irq_chip
23{
24 struct irq_chip base;
25 int (*set_priority)(unsigned char irq, unsigned char prio);
26 int (*set_irq_fiq)(unsigned int irq, unsigned int type);
27};
28
29#endif
diff --git a/arch/arm/plat-mxc/tzic.c b/arch/arm/plat-mxc/tzic.c
index 3703ab28257f..e69ed8a8c203 100644
--- a/arch/arm/plat-mxc/tzic.c
+++ b/arch/arm/plat-mxc/tzic.c
@@ -21,6 +21,8 @@
21#include <mach/hardware.h> 21#include <mach/hardware.h>
22#include <mach/common.h> 22#include <mach/common.h>
23 23
24#include "irq-common.h"
25
24/* 26/*
25 ***************************************** 27 *****************************************
26 * TZIC Registers * 28 * TZIC Registers *
@@ -47,6 +49,25 @@
47 49
48void __iomem *tzic_base; /* Used as irq controller base in entry-macro.S */ 50void __iomem *tzic_base; /* Used as irq controller base in entry-macro.S */
49 51
52#ifdef CONFIG_FIQ
53static int tzic_set_irq_fiq(unsigned int irq, unsigned int type)
54{
55 unsigned int index, mask, value;
56
57 index = irq >> 5;
58 if (unlikely(index >= 4))
59 return -EINVAL;
60 mask = 1U << (irq & 0x1F);
61
62 value = __raw_readl(tzic_base + TZIC_INTSEC0(index)) | mask;
63 if (type)
64 value &= ~mask;
65 __raw_writel(value, tzic_base + TZIC_INTSEC0(index));
66
67 return 0;
68}
69#endif
70
50/** 71/**
51 * tzic_mask_irq() - Disable interrupt number "irq" in the TZIC 72 * tzic_mask_irq() - Disable interrupt number "irq" in the TZIC
52 * 73 *
@@ -104,12 +125,17 @@ static int tzic_set_wake_irq(unsigned int irq, unsigned int enable)
104 return 0; 125 return 0;
105} 126}
106 127
107static struct irq_chip mxc_tzic_chip = { 128static struct mxc_irq_chip mxc_tzic_chip = {
108 .name = "MXC_TZIC", 129 .base = {
109 .ack = tzic_mask_irq, 130 .name = "MXC_TZIC",
110 .mask = tzic_mask_irq, 131 .ack = tzic_mask_irq,
111 .unmask = tzic_unmask_irq, 132 .mask = tzic_mask_irq,
112 .set_wake = tzic_set_wake_irq, 133 .unmask = tzic_unmask_irq,
134 .set_wake = tzic_set_wake_irq,
135 },
136#ifdef CONFIG_FIQ
137 .set_irq_fiq = tzic_set_irq_fiq,
138#endif
113}; 139};
114 140
115/* 141/*
@@ -141,10 +167,16 @@ void __init tzic_init_irq(void __iomem *irqbase)
141 /* all IRQ no FIQ Warning :: No selection */ 167 /* all IRQ no FIQ Warning :: No selection */
142 168
143 for (i = 0; i < MXC_INTERNAL_IRQS; i++) { 169 for (i = 0; i < MXC_INTERNAL_IRQS; i++) {
144 set_irq_chip(i, &mxc_tzic_chip); 170 set_irq_chip(i, &mxc_tzic_chip.base);
145 set_irq_handler(i, handle_level_irq); 171 set_irq_handler(i, handle_level_irq);
146 set_irq_flags(i, IRQF_VALID); 172 set_irq_flags(i, IRQF_VALID);
147 } 173 }
174
175#ifdef CONFIG_FIQ
176 /* Initialize FIQ */
177 init_FIQ();
178#endif
179
148 pr_info("TrustZone Interrupt Controller (TZIC) initialized\n"); 180 pr_info("TrustZone Interrupt Controller (TZIC) initialized\n");
149} 181}
150 182