diff options
author | Jonathan Herman <hermanjl@cs.unc.edu> | 2013-01-22 10:38:37 -0500 |
---|---|---|
committer | Jonathan Herman <hermanjl@cs.unc.edu> | 2013-01-22 10:38:37 -0500 |
commit | fcc9d2e5a6c89d22b8b773a64fb4ad21ac318446 (patch) | |
tree | a57612d1888735a2ec7972891b68c1ac5ec8faea /arch/arm/plat-mxc/tzic.c | |
parent | 8dea78da5cee153b8af9c07a2745f6c55057fe12 (diff) |
Diffstat (limited to 'arch/arm/plat-mxc/tzic.c')
-rw-r--r-- | arch/arm/plat-mxc/tzic.c | 160 |
1 files changed, 160 insertions, 0 deletions
diff --git a/arch/arm/plat-mxc/tzic.c b/arch/arm/plat-mxc/tzic.c new file mode 100644 index 00000000000..f257fccdc39 --- /dev/null +++ b/arch/arm/plat-mxc/tzic.c | |||
@@ -0,0 +1,160 @@ | |||
1 | /* | ||
2 | * Copyright (C)2004-2010 Freescale Semiconductor, Inc. All Rights Reserved. | ||
3 | * | ||
4 | * The code contained herein is licensed under the GNU General Public | ||
5 | * License. You may obtain a copy of the GNU General Public License | ||
6 | * Version 2 or later at the following locations: | ||
7 | * | ||
8 | * http://www.opensource.org/licenses/gpl-license.html | ||
9 | * http://www.gnu.org/copyleft/gpl.html | ||
10 | */ | ||
11 | |||
12 | #include <linux/module.h> | ||
13 | #include <linux/moduleparam.h> | ||
14 | #include <linux/init.h> | ||
15 | #include <linux/device.h> | ||
16 | #include <linux/errno.h> | ||
17 | #include <linux/io.h> | ||
18 | |||
19 | #include <asm/mach/irq.h> | ||
20 | |||
21 | #include <mach/hardware.h> | ||
22 | #include <mach/common.h> | ||
23 | |||
24 | #include "irq-common.h" | ||
25 | |||
26 | /* | ||
27 | ***************************************** | ||
28 | * TZIC Registers * | ||
29 | ***************************************** | ||
30 | */ | ||
31 | |||
32 | #define TZIC_INTCNTL 0x0000 /* Control register */ | ||
33 | #define TZIC_INTTYPE 0x0004 /* Controller Type register */ | ||
34 | #define TZIC_IMPID 0x0008 /* Distributor Implementer Identification */ | ||
35 | #define TZIC_PRIOMASK 0x000C /* Priority Mask Reg */ | ||
36 | #define TZIC_SYNCCTRL 0x0010 /* Synchronizer Control register */ | ||
37 | #define TZIC_DSMINT 0x0014 /* DSM interrupt Holdoffregister */ | ||
38 | #define TZIC_INTSEC0(i) (0x0080 + ((i) << 2)) /* Interrupt Security Reg 0 */ | ||
39 | #define TZIC_ENSET0(i) (0x0100 + ((i) << 2)) /* Enable Set Reg 0 */ | ||
40 | #define TZIC_ENCLEAR0(i) (0x0180 + ((i) << 2)) /* Enable Clear Reg 0 */ | ||
41 | #define TZIC_SRCSET0 0x0200 /* Source Set Register 0 */ | ||
42 | #define TZIC_SRCCLAR0 0x0280 /* Source Clear Register 0 */ | ||
43 | #define TZIC_PRIORITY0 0x0400 /* Priority Register 0 */ | ||
44 | #define TZIC_PND0 0x0D00 /* Pending Register 0 */ | ||
45 | #define TZIC_HIPND0 0x0D80 /* High Priority Pending Register */ | ||
46 | #define TZIC_WAKEUP0(i) (0x0E00 + ((i) << 2)) /* Wakeup Config Register */ | ||
47 | #define TZIC_SWINT 0x0F00 /* Software Interrupt Rigger Register */ | ||
48 | #define TZIC_ID0 0x0FD0 /* Indentification Register 0 */ | ||
49 | |||
50 | void __iomem *tzic_base; /* Used as irq controller base in entry-macro.S */ | ||
51 | |||
52 | #define TZIC_NUM_IRQS 128 | ||
53 | |||
54 | #ifdef CONFIG_FIQ | ||
55 | static int tzic_set_irq_fiq(unsigned int irq, unsigned int type) | ||
56 | { | ||
57 | unsigned int index, mask, value; | ||
58 | |||
59 | index = irq >> 5; | ||
60 | if (unlikely(index >= 4)) | ||
61 | return -EINVAL; | ||
62 | mask = 1U << (irq & 0x1F); | ||
63 | |||
64 | value = __raw_readl(tzic_base + TZIC_INTSEC0(index)) | mask; | ||
65 | if (type) | ||
66 | value &= ~mask; | ||
67 | __raw_writel(value, tzic_base + TZIC_INTSEC0(index)); | ||
68 | |||
69 | return 0; | ||
70 | } | ||
71 | #else | ||
72 | #define tzic_set_irq_fiq NULL | ||
73 | #endif | ||
74 | |||
75 | static unsigned int *wakeup_intr[4]; | ||
76 | |||
77 | static __init void tzic_init_gc(unsigned int irq_start) | ||
78 | { | ||
79 | struct irq_chip_generic *gc; | ||
80 | struct irq_chip_type *ct; | ||
81 | int idx = irq_start >> 5; | ||
82 | |||
83 | gc = irq_alloc_generic_chip("tzic", 1, irq_start, tzic_base, | ||
84 | handle_level_irq); | ||
85 | gc->private = tzic_set_irq_fiq; | ||
86 | gc->wake_enabled = IRQ_MSK(32); | ||
87 | wakeup_intr[idx] = &gc->wake_active; | ||
88 | |||
89 | ct = gc->chip_types; | ||
90 | ct->chip.irq_mask = irq_gc_mask_disable_reg; | ||
91 | ct->chip.irq_unmask = irq_gc_unmask_enable_reg; | ||
92 | ct->chip.irq_set_wake = irq_gc_set_wake; | ||
93 | ct->regs.disable = TZIC_ENCLEAR0(idx); | ||
94 | ct->regs.enable = TZIC_ENSET0(idx); | ||
95 | |||
96 | irq_setup_generic_chip(gc, IRQ_MSK(32), 0, IRQ_NOREQUEST, 0); | ||
97 | } | ||
98 | |||
99 | /* | ||
100 | * This function initializes the TZIC hardware and disables all the | ||
101 | * interrupts. It registers the interrupt enable and disable functions | ||
102 | * to the kernel for each interrupt source. | ||
103 | */ | ||
104 | void __init tzic_init_irq(void __iomem *irqbase) | ||
105 | { | ||
106 | int i; | ||
107 | |||
108 | tzic_base = irqbase; | ||
109 | /* put the TZIC into the reset value with | ||
110 | * all interrupts disabled | ||
111 | */ | ||
112 | i = __raw_readl(tzic_base + TZIC_INTCNTL); | ||
113 | |||
114 | __raw_writel(0x80010001, tzic_base + TZIC_INTCNTL); | ||
115 | __raw_writel(0x1f, tzic_base + TZIC_PRIOMASK); | ||
116 | __raw_writel(0x02, tzic_base + TZIC_SYNCCTRL); | ||
117 | |||
118 | for (i = 0; i < 4; i++) | ||
119 | __raw_writel(0xFFFFFFFF, tzic_base + TZIC_INTSEC0(i)); | ||
120 | |||
121 | /* disable all interrupts */ | ||
122 | for (i = 0; i < 4; i++) | ||
123 | __raw_writel(0xFFFFFFFF, tzic_base + TZIC_ENCLEAR0(i)); | ||
124 | |||
125 | /* all IRQ no FIQ Warning :: No selection */ | ||
126 | |||
127 | for (i = 0; i < TZIC_NUM_IRQS; i += 32) | ||
128 | tzic_init_gc(i); | ||
129 | |||
130 | #ifdef CONFIG_FIQ | ||
131 | /* Initialize FIQ */ | ||
132 | init_FIQ(); | ||
133 | #endif | ||
134 | |||
135 | pr_info("TrustZone Interrupt Controller (TZIC) initialized\n"); | ||
136 | } | ||
137 | |||
138 | /** | ||
139 | * tzic_enable_wake() - enable wakeup interrupt | ||
140 | * | ||
141 | * @param is_idle 1 if called in idle loop (ENSET0 register); | ||
142 | * 0 to be used when called from low power entry | ||
143 | * @return 0 if successful; non-zero otherwise | ||
144 | */ | ||
145 | int tzic_enable_wake(int is_idle) | ||
146 | { | ||
147 | unsigned int i, v; | ||
148 | |||
149 | __raw_writel(1, tzic_base + TZIC_DSMINT); | ||
150 | if (unlikely(__raw_readl(tzic_base + TZIC_DSMINT) == 0)) | ||
151 | return -EAGAIN; | ||
152 | |||
153 | for (i = 0; i < 4; i++) { | ||
154 | v = is_idle ? __raw_readl(tzic_base + TZIC_ENSET0(i)) : | ||
155 | *wakeup_intr[i]; | ||
156 | __raw_writel(v, tzic_base + TZIC_WAKEUP0(i)); | ||
157 | } | ||
158 | |||
159 | return 0; | ||
160 | } | ||