tlk: 6/19 update
[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 #if DEBUG
63 /* storage containing state at time of last interrupt */
64 static struct arm_iframe arm_iframe_last;
65 #endif
66
67 static struct int_handler_struct int_handler_table[NR_IRQS];
68 static uint32_t tegra_gic_cpu_base = TEGRA_ARM_INT_CPU_BASE;
69
70 static uint32_t ictlr_reg_base[] = {
71         TEGRA_PRIMARY_ICTLR_BASE,
72         TEGRA_SECONDARY_ICTLR_BASE,
73         TEGRA_TERTIARY_ICTLR_BASE,
74         TEGRA_QUATERNARY_ICTLR_BASE,
75         TEGRA_QUINARY_ICTLR_BASE,
76 };
77
78 #define vectorToController(vector) (((vector) - 32) / 32)
79
80 status_t mask_interrupt(unsigned int vector)
81 {
82         uint32_t base = ictlr_reg_base[vectorToController(vector)];
83         uint32_t ictlr_ier_clr = *REG32(base + ICTLR_CPU_IER_CLR);
84
85         ictlr_ier_clr |= vector;
86         *REG32(base + ICTLR_CPU_IER_CLR) = ictlr_ier_clr;
87
88         return NO_ERROR;
89 }
90
91 void platform_mask_irqs(void)
92 {
93         int i;
94
95         for (i = 0; i < NR_IRQS; i++)
96                 mask_interrupt(i);
97 }
98
99 status_t unmask_interrupt(unsigned int vector)
100 {
101         uint32_t base = ictlr_reg_base[vectorToController(vector)];
102         uint32_t ictlr_ier_set = *REG32(base + ICTLR_CPU_IER_SET);
103
104         if (vector >= NR_IRQS)
105                 return ERR_INVALID_ARGS;
106
107         ictlr_ier_set |= vector;
108         *REG32(base + ICTLR_CPU_IER_SET) = ictlr_ier_set;
109
110         return NO_ERROR;
111 }
112
113 enum handler_return platform_irq(struct arm_iframe *iframe)
114 {
115         enum handler_return ret = INT_NO_RESCHEDULE;
116         uint32_t vector;
117         struct tz_monitor_frame *smc_frame = NULL, frame;
118
119 #if DEBUG
120         /*
121          * debug aid to know where within the secure world the last interrupt
122          * occurred
123          */
124         memcpy((void *)&arm_iframe_last, iframe, sizeof(arm_iframe_last));
125 #endif
126
127         /* read GIC interrupt ack register */
128         vector = *REG32(tegra_gic_cpu_base + GIC_CPU_ICCIAR) & 0x3FF;
129
130         if (vector == 1023) {
131                 /* normal spurious intr, just return */
132                 return ret;
133         } else {
134                 /* at the moment, NS owns all interrupts */
135                 ASSERT(vector == 1022);
136         }
137
138 #if defined(WITH_MONITOR_BIN)
139         memset(&frame, 0, sizeof(struct tz_monitor_frame));
140         frame.r[0] = SMC_ERR_PREEMPT_BY_IRQ;
141
142         smc_frame = tz_switch_to_ns(SMC_TOS_COMPLETION, &frame);
143         while (smc_frame->r[0] != SMC_TOS_RESTART) {
144                 frame.r[0] = SMC_ERR_PREEMPT_BY_IRQ;
145                 smc_frame = tz_switch_to_ns(SMC_TOS_COMPLETION, &frame);
146         }
147 #else
148         smc_frame = tz_switch_to_ns(SMC_TOS_PREEMPT_BY_IRQ, NULL);
149         while (smc_frame)
150                 smc_frame = tz_switch_to_ns(SMC_TOS_PREEMPT_BY_IRQ, NULL);
151 #endif
152
153         return ret;
154 }
155
156 void platform_fiq(struct arm_iframe *frame)
157 {
158         PANIC_UNIMPLEMENTED;
159 }
160
161 void register_int_handler(unsigned int vector, int_handler handler, void *arg)
162 {
163         if (vector >= NR_IRQS)
164                 panic("register_int_handler: vector out of range %d\n", vector);
165
166         enter_critical_section();
167
168         int_handler_table[vector].arg = arg;
169         int_handler_table[vector].handler = handler;
170
171         exit_critical_section();
172 }