blob: e7888d1bb7b4ed52b35aaf657c261ea36d795bef [file] [log] [blame]
Amol Jadidb1edb32011-07-18 14:24:46 -07001/*
2 * Copyright (c) 2008, Google Inc.
3 * All rights reserved.
4 *
Duy Truongf3ac7b32013-02-13 01:07:28 -08005 * Copyright (c) 2009-2011, The Linux Foundation. All rights reserved.
Amol Jadidb1edb32011-07-18 14:24:46 -07006 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * * Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in
14 * the documentation and/or other materials provided with the
15 * distribution.
16 * * Neither the name of Google, Inc. nor the names of its contributors
17 * may be used to endorse or promote products derived from this
18 * software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
26 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
27 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
28 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
29 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
30 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34#include <reg.h>
35#include <debug.h>
36#include <arch/arm.h>
37#include <kernel/thread.h>
38#include <platform/irqs.h>
39#include <qgic.h>
40
41static struct ihandler handler[NR_IRQS];
42
43/* Intialize distributor */
44static void qgic_dist_init(void)
45{
46 uint32_t i;
47 uint32_t num_irq = 0;
48 uint32_t cpumask = 1;
49
50 cpumask |= cpumask << 8;
51 cpumask |= cpumask << 16;
52
53 /* Disabling GIC */
54 writel(0, GIC_DIST_CTRL);
55
56 /*
57 * Find out how many interrupts are supported.
58 */
59 num_irq = readl(GIC_DIST_CTR) & 0x1f;
60 num_irq = (num_irq + 1) * 32;
61
62 /* Set each interrupt line to use N-N software model
63 * and edge sensitive, active high
64 */
Ajay Dudanib01e5062011-12-03 23:23:42 -080065 for (i = 32; i < num_irq; i += 16)
66 writel(0xffffffff, GIC_DIST_CONFIG + i * 4 / 16);
Amol Jadidb1edb32011-07-18 14:24:46 -070067
68 writel(0xffffffff, GIC_DIST_CONFIG + 4);
69
70 /* Set up interrupts for this CPU */
71 for (i = 32; i < num_irq; i += 4)
72 writel(cpumask, GIC_DIST_TARGET + i * 4 / 4);
73
Ajay Dudanib01e5062011-12-03 23:23:42 -080074 /* Set priority of all interrupts */
Amol Jadidb1edb32011-07-18 14:24:46 -070075
76 /*
77 * In bootloader we dont care about priority so
78 * setting up equal priorities for all
79 */
Ajay Dudanib01e5062011-12-03 23:23:42 -080080 for (i = 0; i < num_irq; i += 4)
81 writel(0xa0a0a0a0, GIC_DIST_PRI + i * 4 / 4);
Amol Jadidb1edb32011-07-18 14:24:46 -070082
Ajay Dudanib01e5062011-12-03 23:23:42 -080083 /* Disabling interrupts */
84 for (i = 0; i < num_irq; i += 32)
85 writel(0xffffffff, GIC_DIST_ENABLE_CLEAR + i * 4 / 32);
Amol Jadidb1edb32011-07-18 14:24:46 -070086
87 writel(0x0000ffff, GIC_DIST_ENABLE_SET);
88
Ajay Dudanib01e5062011-12-03 23:23:42 -080089 /*Enabling GIC */
Amol Jadidb1edb32011-07-18 14:24:46 -070090 writel(1, GIC_DIST_CTRL);
91}
92
93/* Intialize cpu specific controller */
94static void qgic_cpu_init(void)
95{
96 writel(0xf0, GIC_CPU_PRIMASK);
97 writel(1, GIC_CPU_CTRL);
98}
99
100/* Initialize QGIC. Called from platform specific init code */
101void qgic_init(void)
102{
103 qgic_dist_init();
104 qgic_cpu_init();
105}
106
107/* IRQ handler */
Channagoud Kadabi81ba1102011-10-01 16:37:59 +0530108enum handler_return gic_platform_irq(struct arm_iframe *frame)
Amol Jadidb1edb32011-07-18 14:24:46 -0700109{
110 uint32_t num;
111 enum handler_return ret;
112
113 num = readl(GIC_CPU_INTACK);
114 if (num > NR_IRQS)
115 return 0;
116
117 ret = handler[num].func(handler[num].arg);
118 writel(num, GIC_CPU_EOI);
119
120 return ret;
121}
122
123/* FIQ handler */
Channagoud Kadabi81ba1102011-10-01 16:37:59 +0530124void gic_platform_fiq(struct arm_iframe *frame)
Amol Jadidb1edb32011-07-18 14:24:46 -0700125{
126 PANIC_UNIMPLEMENTED;
127}
128
129/* Mask interrupt */
Channagoud Kadabi81ba1102011-10-01 16:37:59 +0530130status_t gic_mask_interrupt(unsigned int vector)
Amol Jadidb1edb32011-07-18 14:24:46 -0700131{
Ajay Dudanib01e5062011-12-03 23:23:42 -0800132 uint32_t reg = GIC_DIST_ENABLE_CLEAR + (vector / 32) * 4;
Amol Jadidb1edb32011-07-18 14:24:46 -0700133 uint32_t bit = 1 << (vector & 31);
134
135 writel(bit, reg);
136
137 return 0;
138}
139
140/* Un-mask interrupt */
Channagoud Kadabi81ba1102011-10-01 16:37:59 +0530141status_t gic_unmask_interrupt(unsigned int vector)
Amol Jadidb1edb32011-07-18 14:24:46 -0700142{
Ajay Dudanib01e5062011-12-03 23:23:42 -0800143 uint32_t reg = GIC_DIST_ENABLE_SET + (vector / 32) * 4;
Amol Jadidb1edb32011-07-18 14:24:46 -0700144 uint32_t bit = 1 << (vector & 31);
145
146 writel(bit, reg);
147
148 return 0;
149}
150
151/* Register interrupt handler */
Channagoud Kadabi81ba1102011-10-01 16:37:59 +0530152void gic_register_int_handler(unsigned int vector, int_handler func, void *arg)
Amol Jadidb1edb32011-07-18 14:24:46 -0700153{
154 ASSERT(vector < NR_IRQS);
155
156 enter_critical_section();
157 handler[vector].func = func;
158 handler[vector].arg = arg;
159 exit_critical_section();
160}