First version
[3rdparty/ote_partner/tlk.git] / platform / tegra / common / interrupts.c
1 /*
2  * Copyright (c) 2008 Travis Geiselbrecht
3  * Copyright (c) 2012-2014, NVIDIA CORPORATION. All rights reserved
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining
6  * a copy of this software and associated documentation files
7  * (the "Software"), to deal in the Software without restriction,
8  * including without limitation the rights to use, copy, modify, merge,
9  * publish, distribute, sublicense, and/or sell copies of the Software,
10  * and to permit persons to whom the Software is furnished to do so,
11  * subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be
14  * included in all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
20  * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
21  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
22  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23  */
24 #include <sys/types.h>
25 #include <assert.h>
26 #include <debug.h>
27 #include <err.h>
28 #include <reg.h>
29 #include <string.h>
30 #include <kernel/thread.h>
31 #include <platform/interrupts.h>
32 #include <arch/ops.h>
33 #include <arch/arm.h>
34 #include <platform/memmap.h>
35 #include <platform/irqs.h>
36 #include <platform/platform_p.h>
37 #include <lib/monitor/monitor_vector.h>
38
39 #define GIC_DIST_CTR    0x004
40 #define GIC_CPU_ICCIAR  0x00c
41
42 #define ICTLR_CPU_IEP_VFIQ      0x08
43 #define ICTLR_CPU_IEP_FIR       0x14
44 #define ICTLR_CPU_IEP_FIR_SET   0x18
45 #define ICTLR_CPU_IEP_FIR_CLR   0x1c
46
47 #define ICTLR_CPU_IER           0x20
48 #define ICTLR_CPU_IER_SET       0x24
49 #define ICTLR_CPU_IER_CLR       0x28
50 #define ICTLR_CPU_IEP_CLASS     0x2C
51
52 #define ICTLR_COP_IER           0x30
53 #define ICTLR_COP_IER_SET       0x34
54 #define ICTLR_COP_IER_CLR       0x38
55 #define ICTLR_COP_IEP_CLASS     0x3c
56
57 struct int_handler_struct {
58         int_handler handler;
59         void *arg;
60 };
61
62 /* location in NS to have IRQ serviced */
63 unsigned long _jump_to_ns_irq_addr = 0;
64
65 /* storage containing state at time of last interrupt */
66 static struct arm_iframe arm_iframe_last;
67
68 static struct int_handler_struct int_handler_table[NR_IRQS];
69 static uint32_t tegra_gic_cpu_base = TEGRA_ARM_INT_CPU_BASE;
70
71 static uint32_t ictlr_reg_base[] = {
72         TEGRA_PRIMARY_ICTLR_BASE,
73         TEGRA_SECONDARY_ICTLR_BASE,
74         TEGRA_TERTIARY_ICTLR_BASE,
75         TEGRA_QUATERNARY_ICTLR_BASE,
76         TEGRA_QUINARY_ICTLR_BASE,
77 };
78
79 #define vectorToController(vector) (((vector) - 32) / 32)
80
81 static bool platform_ns_handler_set;
82
83 bool platform_intr_ready(void)
84 {
85         /* return if normal world handler is setup */
86         return platform_ns_handler_set;
87 }
88
89 inline void platform_set_intr_ready_state(bool ready, struct tz_monitor_frame *frame)
90 {
91         /* update state of normal world handler */
92         platform_ns_handler_set = ready;
93 #if NOT_YET
94         /* enable intrs, if not in a critical section (and enabled in NS world) */
95         if (ready) {
96                 if (!in_critical_section() && !(frame->spsr & 0x80)) {
97                         arch_enable_ints();
98                 }
99         }
100 #endif
101 }
102
103 status_t mask_interrupt(unsigned int vector)
104 {
105         uint32_t base = ictlr_reg_base[vectorToController(vector)];
106         uint32_t ictlr_ier_clr = *REG32(base + ICTLR_CPU_IER_CLR);
107
108         ictlr_ier_clr |= vector;
109         *REG32(base + ICTLR_CPU_IER_CLR) = ictlr_ier_clr;
110
111         return NO_ERROR;
112 }
113
114 void platform_mask_irqs(void)
115 {
116         int i;
117
118         for (i = 0; i < NR_IRQS; i++)
119                 mask_interrupt(i);
120 }
121
122 status_t unmask_interrupt(unsigned int vector)
123 {
124         uint32_t base = ictlr_reg_base[vectorToController(vector)];
125         uint32_t ictlr_ier_set = *REG32(base + ICTLR_CPU_IER_SET);
126
127         if (vector >= NR_IRQS)
128                 return ERR_INVALID_ARGS;
129
130         ictlr_ier_set |= vector;
131         *REG32(base + ICTLR_CPU_IER_SET) = ictlr_ier_set;
132
133         return NO_ERROR;
134 }
135
136 enum handler_return platform_irq(struct arm_iframe *iframe)
137 {
138         enum handler_return ret = INT_NO_RESCHEDULE;
139         struct tz_monitor_frame tzframe;
140         uint32_t vector;
141
142         /* save interrupt state */
143         memcpy((void *)&arm_iframe_last, iframe, sizeof(arm_iframe_last));
144
145         /* read GIC interrupt ack register */
146         vector = *REG32(tegra_gic_cpu_base + GIC_CPU_ICCIAR) & 0x3FF;
147
148         if (vector == 1023) {
149                 /* normal spurious intr, just return */
150                 return ret;
151         } else {
152                 /* at the moment, NS owns all interrupts */
153                 ASSERT(vector == 1022);
154         }
155
156         /* create a frame to use to return to the NS world */
157         memset(&tzframe, 0, sizeof(tzframe));
158
159         ASSERT(_jump_to_ns_irq_addr);
160         tzframe.pc = _jump_to_ns_irq_addr;
161         tzframe.spsr = MODE_SVC;
162
163         /* service in the NS world */
164         platform_handle_tz_smc(SMC_TOS_PREEMPT_BY_IRQ, &tzframe);
165         return ret;
166 }
167
168 void platform_fiq(struct arm_iframe *frame)
169 {
170         PANIC_UNIMPLEMENTED;
171 }
172
173 void register_int_handler(unsigned int vector, int_handler handler, void *arg)
174 {
175         if (vector >= NR_IRQS)
176                 panic("register_int_handler: vector out of range %d\n", vector);
177
178         enter_critical_section();
179
180         int_handler_table[vector].arg = arg;
181         int_handler_table[vector].handler = handler;
182
183         exit_critical_section();
184 }