blob: 935afd030c11ea095af2cf16d7da9b914c3039e6 [file] [log] [blame]
yuezonghe824eb0c2024-06-27 02:32:26 -07001/*
2 * linux/arch/arm/mach-zx297510/irq.c
3 *
4 * Copyright (C) 2013 ZTE-TSP
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 */
16
17#include <linux/init.h>
18#include <linux/module.h>
19#include <linux/mm.h>
20#include <linux/types.h>
21#include <linux/irq.h>
22#include <linux/interrupt.h>
23
24#include <mach/iomap.h>
25#include <mach/irqs.h>
26#include <mach/debug.h>
27#include <mach/pcu.h>
28
29#include <asm/irq.h>
30#include <asm/setup.h>
31#include <asm/io.h>
32#include <asm/system.h>
33#include <asm/cp15.h>
34
35
36#include <asm/mach/arch.h>
37#include <asm/mach/irq.h>
38#include <asm/mach/map.h>
39#include <mach/board.h>
40
41#if NEW_LINUX_FRAME
42#include <linux/irqchip/arm-gic.h>
43#else
44#include <asm/hardware/gic.h>
45#endif
46#include <linux/irqdomain.h>
47
48#define A9_INT_MODE_BASE (A9_CRM_BASE + 0x50)
49
50
51#define INT_HIGHLEVEL (0x0) /* 00: high level */
52#define INT_LOWLEVEL (0x1) /* 01: low level */
53#define INT_POSEDGE (0x2) /* 10: raise edge */
54#define INT_NEGEDGE (0x3) /* 11: fall edge */
55
56extern int gic_set_type(struct irq_data *d, unsigned int type);
57extern unsigned int gic_get_irq_nr(irq_hw_number_t hwirq);
58
59static int init_irq_flag = 0;
60
61
62/*
63 * GIC only support IRQ_TYPE_LEVEL_HIGH and IRQ_TYPE_EDGE_RISING. In order to support
64 * full interrupt trigger mode(high,low,falling,rising), zx29 treats all level interrupt
65 * as high level interrupt and Edge interrupt is treated as rising interrupt . It is only
66 * for SPIs. External int need additional configuration in PCU
67 */
68
69static int zx29_int_set_type(struct irq_data *d, unsigned int type)
70{
71 unsigned int data_tmp=0;
72 unsigned int srctype=0;
73 unsigned int reg_index=0,pos_index=0;
74
75 unsigned int hwirq = d->hwirq;
76
77 switch (type) {
78 case IRQ_TYPE_LEVEL_HIGH:
79 srctype = INT_HIGHLEVEL;
80 break;
81 case IRQ_TYPE_EDGE_RISING:
82 srctype = INT_POSEDGE;
83 break;
84 case IRQ_TYPE_LEVEL_LOW:
85 srctype = INT_LOWLEVEL;
86 break;
87 case IRQ_TYPE_EDGE_FALLING:
88 srctype = INT_NEGEDGE;
89 break;
90 default:
91 return -EINVAL;
92 }
93 reg_index=(hwirq-32)/16;
94 pos_index=((hwirq-32)%16)*2;
95
96 data_tmp=ioread32(A9_INT_MODE_BASE+reg_index*4);
97 data_tmp &= ~(3<<pos_index);
98 data_tmp |= srctype<<pos_index;
99 iowrite32(data_tmp,A9_INT_MODE_BASE+reg_index*4);
100
101 return 0;
102}
103
104/*
105 * Enable/disable power management wakeup mode, which is
106 * disabled by default. Enables and disables must match,
107 * just as they match for non-wakeup mode support.
108 *
109 * Wakeup mode lets this IRQ wake the system from sleep
110 * states like "suspend to RAM".
111 */
112static int zx29_int_set_wake(struct irq_data *d, unsigned int on)
113{
114 return pcu_set_irq_wake(d->hwirq, on);
115}
116
117bool irq_type_valid(unsigned int int_type)
118{
119 return ((int_type==IRQ_TYPE_LEVEL_HIGH) || (int_type==IRQ_TYPE_LEVEL_LOW) || \
120 (int_type==IRQ_TYPE_EDGE_RISING) || (int_type==IRQ_TYPE_EDGE_FALLING));
121}
122
123
124/*
125 * set default interrupt trigger type
126 */
127static void int_set_type_default(unsigned int line)
128{
129 unsigned int int_type=0;
130 unsigned int irq=0;
131 struct irq_data *d;
132
133 if(line<GIC_PPI_START)
134 return;
135
136 irq = gic_get_irq_nr((unsigned long)line);
137 d = irq_get_irq_data(irq);
138
139 /*set the interrupt mode --raise edge,fall edge, high level, low level*/
140 switch ( line )
141 {
142 case WDT_INT:
143 case AP_TIMER0_INT:
144 case GSM_SYS0_INT:
145 case GSM_SYS1_INT:
146 case AP_TIMER4_INT:
147 {
148 int_type = IRQ_TYPE_EDGE_RISING;
149 break;
150 }
151 default:
152 {
153 int_type = IRQ_TYPE_LEVEL_HIGH;
154 break;
155 }
156 }
157 gic_set_type(d,int_type);
158}
159
160
161/*
162 * Initialize the interrupt controller unit.
163 */
164void __init zx29_init_irq(void)
165{
166 unsigned int i;
167
168 gic_arch_extn.irq_set_type = zx29_int_set_type;
169 gic_arch_extn.irq_set_wake = zx29_int_set_wake;
170
171 gic_init(0, GIC_PPI_START, GIC_DIST_BASE, GIC_CPU_BASE);
172
173 for (i = GIC_PPI_START; i < NR_IRQS; i++) {
174 int_set_type_default(i);
175 }
176
177 init_irq_flag = 1;
178
179 pr_info("[GIC]ZTE-TSP zx297520v2 GIC initialized.\n");
180}
181
182
183int get_init_irq_flag(void)
184{
185 return init_irq_flag;
186}
187
188
189/* --------------------------------------------------------------------
190 * extint_8in1
191 * -------------------------------------------------------------------- */
192static void ext8in1_irq_lock(struct irq_data *data)
193{
194}
195static void ext8in1_irq_sync_unlock(struct irq_data *data)
196{
197}
198static void ext8in1_irq_mask(struct irq_data *data)
199{
200}
201
202static void ext8in1_irq_unmask(struct irq_data *data)
203{
204}
205static struct irq_chip ext8in1_irq_chip =
206{
207 .name = "ext8in1",
208 .irq_bus_lock = ext8in1_irq_lock,
209 .irq_bus_sync_unlock = ext8in1_irq_sync_unlock,
210 .irq_mask = ext8in1_irq_mask,
211 .irq_unmask = ext8in1_irq_unmask,
212 .irq_set_wake = zx29_int_set_wake,
213
214};
215static irqreturn_t ext8in1_irq_thread(int irq, void *irq_data)
216{
217 u32 line;
218 u32 nextLine;
219
220 line = pcu_get_8in1_int_source();
221
222 while (1)
223 {
224 pcu_clr_irq_pending(line + EX8IN1_INT_BASE);
225 handle_nested_irq(line + EX8IN1_INT_BASE);
226
227 nextLine = pcu_get_8in1_int_source();
228
229 /*
230 * no new interrupt
231 * here is not absolutely right. the same interrupt maybe come again
232 * during ex8in1Isr() execution, or there is really no interrupt comes.
233 * in both situation, we can get same line number. we do nothing to the
234 * case. if there is really a new interrupt, it will trigger a new
235 * arm interrupt.
236 */
237 if (line == nextLine)
238 break;
239 else
240 line = nextLine;
241 }
242
243// enable_irq(irq);
244
245 return IRQ_HANDLED;
246}
247
248static irqreturn_t ext8in1_irq(int irq, void *dev_id)
249{
250// disable_irq_nosync(irq);
251
252 return IRQ_WAKE_THREAD;
253}
254
255static int __init zx29_ext_int_init(void)
256{
257 int ret;
258 int cur_irq;
259
260 for (cur_irq = EX8IN1_INT_BASE; cur_irq <= EX8IN1_INT_END; cur_irq++)
261 {
262 irq_set_chip_and_handler(cur_irq, &ext8in1_irq_chip, handle_simple_irq);
263 irq_set_nested_thread(cur_irq, 1);
264 set_irq_flags(cur_irq, IRQF_VALID);
265 }
266
267 ret = request_threaded_irq(EX8IN1_INT, ext8in1_irq, ext8in1_irq_thread, IRQF_ONESHOT,
268 "ext8in1", NULL);
269 if(ret<0)
270 {
271 pr_info("[GIC]ZTE-TSP zx297520v2 EXTINT_8IN1 initialized failed.\n");
272 }
273
274 return ret;
275}
276subsys_initcall(zx29_ext_int_init);
277