diff options
| -rw-r--r-- | arch/arm/plat-mxc/Makefile | 2 | ||||
| -rw-r--r-- | arch/arm/plat-mxc/avic.c | 32 | ||||
| -rw-r--r-- | arch/arm/plat-mxc/include/mach/entry-macro.S | 14 | ||||
| -rw-r--r-- | arch/arm/plat-mxc/irq-common.c | 60 | ||||
| -rw-r--r-- | arch/arm/plat-mxc/irq-common.h | 29 | ||||
| -rw-r--r-- | arch/arm/plat-mxc/tzic.c | 46 |
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 |
| 6 | obj-y := clock.o gpio.o time.o devices.o cpu.o system.o | 6 | obj-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 |
| 9 | obj-$(CONFIG_MXC_TZIC) += tzic.o | 9 | obj-$(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 | ||
| 47 | void __iomem *avic_base; | 49 | void __iomem *avic_base; |
| 48 | 50 | ||
| 49 | int imx_irq_set_priority(unsigned char irq, unsigned char prio) | ||
| 50 | { | ||
| 51 | #ifdef CONFIG_MXC_IRQ_PRIOR | 51 | #ifdef CONFIG_MXC_IRQ_PRIOR |
| 52 | static 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 | } |
| 69 | EXPORT_SYMBOL(imx_irq_set_priority); | 68 | #endif |
| 70 | 69 | ||
| 71 | #ifdef CONFIG_FIQ | 70 | #ifdef CONFIG_FIQ |
| 72 | int mxc_set_irq_fiq(unsigned int irq, unsigned int type) | 71 | static 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 | } |
| 90 | EXPORT_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 | ||
| 105 | static struct irq_chip mxc_avic_chip = { | 103 | static 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 | 60 | 1000: add \irqstat, \base, \irqnr, lsr #3 |
| 60 | 1000: | 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 | |||
| 24 | int 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 | } | ||
| 41 | EXPORT_SYMBOL(imx_irq_set_priority); | ||
| 42 | |||
| 43 | int 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 | } | ||
| 60 | EXPORT_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 | |||
| 22 | struct 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 | ||
| 48 | void __iomem *tzic_base; /* Used as irq controller base in entry-macro.S */ | 50 | void __iomem *tzic_base; /* Used as irq controller base in entry-macro.S */ |
| 49 | 51 | ||
| 52 | #ifdef CONFIG_FIQ | ||
| 53 | static 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 | ||
| 107 | static struct irq_chip mxc_tzic_chip = { | 128 | static 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 | ||
