First version
[3rdparty/ote_partner/tlk.git] / platform / tegra / monitor / interrupts.c
1 /*
2  * Copyright (c) 2014, NVIDIA CORPORATION. All rights reserved
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining
5  * a copy of this software and associated documentation files
6  * (the "Software"), to deal in the Software without restriction,
7  * including without limitation the rights to use, copy, modify, merge,
8  * publish, distribute, sublicense, and/or sell copies of the Software,
9  * and to permit persons to whom the Software is furnished to do so,
10  * subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice shall be
13  * included in all copies or substantial portions of the Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
19  * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
20  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
21  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22  */
23 #include <sys/types.h>
24 #include <assert.h>
25 #include <debug.h>
26 #include <err.h>
27 #include <reg.h>
28 #include <string.h>
29 #include <kernel/thread.h>
30 #include <platform/interrupts.h>
31 #include <arch/ops.h>
32 #include <arch/arm.h>
33 #include <platform/memmap.h>
34 #include <platform/irqs.h>
35 #include <platform/platform_p.h>
36 #include <lib/monitor/monitor_vector.h>
37
38 #define GIC_DIST_CTR    0x004
39 #define GIC_CPU_ICCIAR  0x00c
40
41 #define ICTLR_CPU_IEP_VFIQ      0x08
42 #define ICTLR_CPU_IEP_FIR       0x14
43 #define ICTLR_CPU_IEP_FIR_SET   0x18
44 #define ICTLR_CPU_IEP_FIR_CLR   0x1c
45
46 #define ICTLR_CPU_IER           0x20
47 #define ICTLR_CPU_IER_SET       0x24
48 #define ICTLR_CPU_IER_CLR       0x28
49 #define ICTLR_CPU_IEP_CLASS     0x2C
50
51 #define ICTLR_COP_IER           0x30
52 #define ICTLR_COP_IER_SET       0x34
53 #define ICTLR_COP_IER_CLR       0x38
54 #define ICTLR_COP_IEP_CLASS     0x3c
55
56 static uint32_t num_ictrlrs;
57
58 static uintptr_t ictlr_reg_base[] = {
59         TEGRA_PRIMARY_ICTLR_BASE,
60         TEGRA_SECONDARY_ICTLR_BASE,
61         TEGRA_TERTIARY_ICTLR_BASE,
62         TEGRA_QUATERNARY_ICTLR_BASE,
63         TEGRA_QUINARY_ICTLR_BASE,
64 };
65
66 void platform_init_interrupts(void)
67 {
68         uint32_t i;
69
70         num_ictrlrs = *REG32(TEGRA_ARM_INT_DIST_BASE + GIC_DIST_CTR);
71         num_ictrlrs &= 0x1f;
72
73         for (i = 0; i < num_ictrlrs; i++) {
74                 uintptr_t ictrl = ictlr_reg_base[i];
75                 *REG32(ictrl + ICTLR_CPU_IER_CLR) = ~0;
76                 *REG32(ictrl + ICTLR_CPU_IEP_CLASS) = 0;
77                 *REG32(ictrl + ICTLR_CPU_IEP_FIR_CLR) = ~0;
78                 *REG32(ictrl + ICTLR_CPU_IER_SET) = ~0;
79                 *REG32(ictrl + ICTLR_COP_IER_CLR) = ~0;
80         }
81 }
82
83 void platform_config_interrupts(void)
84 {
85         int i;
86         uintptr_t eic_dist_gicd_ctlr = TEGRA_ARM_PERIF_BASE + 0x1000;
87         uintptr_t eic_dist_gicd_groupr_base = TEGRA_ARM_PERIF_BASE + 0x1080;
88         uintptr_t eic_dist_gicd_isenabler = TEGRA_ARM_PERIF_BASE + 0x1110;
89         uintptr_t eic_dist_gicd_prio_base = TEGRA_ARM_PERIF_BASE + 0x1400;
90         uintptr_t eic_dist_gicd_targetsr_base = TEGRA_ARM_PERIF_BASE + 0x1800;
91         uintptr_t eic_dist_gicd_intconfig_base = TEGRA_ARM_PERIF_BASE + 0x1C00;
92         uintptr_t eic_proc_if_gicc_ctlr = TEGRA_ARM_PERIF_BASE + 0x2000;
93         uintptr_t eic_proc_if_gicc_pmr = TEGRA_ARM_PERIF_BASE + 0x2004;
94         uint32_t val = 0, wdt_cpu = (4 * 32) + 27, wdt_cop = (4 * 32) + 28;
95
96         uintptr_t base = eic_dist_gicd_groupr_base;
97         for (i = 0; i < NR_IRQS; i += 32)
98                 *(volatile uint32_t *)(base + i * 4 / 32) = ~0;
99
100         /* enable fiqs, group 0/1, irq/fiq bypass fields */
101         val = (1 << 0 | 1 << 1 | 1 << 3 | 0xF << 4);
102         *(volatile uint32_t *)(eic_proc_if_gicc_ctlr) = val;
103
104         /* priority mask max, accept ints at all priority levels */
105         *(volatile uint32_t *)(eic_proc_if_gicc_pmr) = 0xFF;
106
107         /* enable group 0/1 in the distributor */
108         *(volatile uint32_t *)(eic_dist_gicd_ctlr) = (1 << 1) | (1 << 0);
109
110         /* enable path for the 2 WDTs in GIC: CPU = 27, COP = 28 */
111         val = *(volatile uint32_t *)(eic_dist_gicd_isenabler);
112         val |= (1 << 27) | (1 << 28);
113         *(volatile uint32_t *)(eic_dist_gicd_isenabler) = val;
114
115         /* map WDT_CPU to CPU 0 */
116         *(volatile uint32_t *)(eic_dist_gicd_targetsr_base +
117                 ((wdt_cpu / 4) * 4)) |= ~(0xFF << ((wdt_cpu % 4) * 8));
118         *(volatile uint32_t *)(eic_dist_gicd_targetsr_base +
119                 ((wdt_cpu / 4) * 4)) |= (1 << ((wdt_cpu % 4) * 8));
120
121         /* map WDT_AVP to CPUs 0-3 */
122         *(volatile uint32_t *)(eic_dist_gicd_targetsr_base +
123                 ((wdt_cop / 4) * 4)) |= ~(0xFF << ((wdt_cop % 4) * 8));
124         *(volatile uint32_t *)(eic_dist_gicd_targetsr_base +
125                 ((wdt_cop / 4) * 4)) |= (0xF << ((wdt_cop % 4) * 8));
126
127         /* configure both WDTs as level-triggered interrupts */
128         val = *(volatile uint32_t *)(eic_dist_gicd_intconfig_base +
129                 ((wdt_cpu / 16) * 4));
130         val &= ~(3 << ((wdt_cpu % 16) * 2));
131         *(volatile uint32_t *)(eic_dist_gicd_intconfig_base +
132                 ((wdt_cpu / 16) * 4)) = val;
133         val = *(volatile uint32_t *)(eic_dist_gicd_intconfig_base +
134                 ((wdt_cop / 16) * 4));
135         val &= ~(3 << ((wdt_cop % 16) * 2));
136         *(volatile uint32_t *)(eic_dist_gicd_intconfig_base +
137                 ((wdt_cop / 16) * 4)) = val;
138
139         /* configure WDT0 as IRQ (grp 1), WDT4 as FIQ (grp 0) */
140         val = *(volatile uint32_t *)(eic_dist_gicd_groupr_base +
141                 ((wdt_cpu / 32) * 4));
142         val |= (1 << (wdt_cpu % 32));
143         val &= ~(1 << (wdt_cop % 32));
144         *(volatile uint32_t *)(eic_dist_gicd_groupr_base +
145                 ((wdt_cpu / 32) * 4)) = val;
146
147         /* WDT0 is low priority */
148         val = *(volatile uint32_t *)(eic_dist_gicd_prio_base +
149                 ((wdt_cpu / 4) * 4));
150         val &= ~(0xFF << ((wdt_cop % 4) * 8));
151         *(volatile uint32_t *)(eic_dist_gicd_prio_base +
152                 ((wdt_cpu / 4) * 4)) = val;
153 }