blob: e9c210419cac0c4b2566c89df0a3b436c7472462 [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
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 <asm/hardware/gic.h>
40
41
42//#pragma GCC optimize("O0")
43#define GIC_DIST_BASE (A9_PERIPHERAL_VA+0x1000)
44#define GIC_CPU_BASE (A9_PERIPHERAL_VA+0x100)
45#define A9_INT_MODE_BASE (A9_PERIPHERAL_VA+0x3050)
46
47
48#define INT_HIGHLEVEL (0x0) /* 00: high level */
49#define INT_LOWLEVEL (0x1) /* 01: low level */
50#define INT_POSEDGE (0x2) /* 10: raise edge */
51#define INT_NEGEDGE (0x3) /* 11: fall edge */
52
53
54
55extern struct gic_chip_data gic_data[MAX_GIC_NR];
56
57extern int gic_set_type(struct irq_data *d, unsigned int type);
58
59/*
60* copy from tegra, get pending intterrupt number
61*/
62unsigned int zx29_gic_pending_interrupt(void)
63{
64 unsigned int irq;
65
66 irq = ioread32(GIC_CPU_BASE + GIC_CPU_HIGHPRI);
67 irq &= 0x3ff;
68
69 return irq;
70}
71
72/*
73 *GIC only support IRQ_TYPE_LEVEL_HIGH and IRQ_TYPE_EDGE_RISING. In order to support
74 *full interrupt trigger mode(high,low,falling,rising), zx297510 add a little thing to do that.It
75 *is only for SPIs. The little thing treats all level interrupt as high level interrupt, and then
76 *sends them to GIC. Edge interrupt is treated as rising interrupt as well.
77 *external int need additional configuration in PCU
78 */
79
80static int zx297510_int_set_type(struct irq_data *d, unsigned int type)
81{
82 unsigned int data_tmp=0;
83 unsigned int srctype=0;
84 unsigned int reg_index=0,pos_index=0;
85
86 unsigned int hwirq = d->hwirq;
87
88 switch (type) {
89 case IRQ_TYPE_LEVEL_HIGH:
90 srctype = INT_HIGHLEVEL;
91 break;
92 case IRQ_TYPE_EDGE_RISING:
93 srctype = INT_POSEDGE;
94 break;
95 case IRQ_TYPE_LEVEL_LOW:
96 srctype = INT_LOWLEVEL;
97 break;
98 case IRQ_TYPE_EDGE_FALLING:
99 srctype = INT_NEGEDGE;
100 break;
101 default:
102 return -EINVAL;
103 }
104 reg_index=(hwirq-32)/16;
105 pos_index=((hwirq-32)%16)*2;
106
107
108 data_tmp=ioread32(A9_INT_MODE_BASE+reg_index*4);
109 data_tmp &= ~(3<<pos_index);
110 data_tmp |= srctype<<pos_index;
111 iowrite32(data_tmp,A9_INT_MODE_BASE+reg_index*4);
112
113 return 0;
114}
115
116
117/*
118 * set default interrupt trigger type
119 */
120static void int_set_type_default(unsigned int line)
121{
122 unsigned int int_type=0;
123 unsigned int irq=0;
124 struct gic_chip_data *gic = &gic_data[0];
125 struct irq_data *d;
126
127 if(line<GIC_PPI_START)
128 return;
129
130 irq = irq_find_mapping(gic->domain, (unsigned long)line); //get linux irq number
131 d = irq_get_irq_data(irq); //get irq_data
132
133 /*set the interrupt mode --raise edge,fall edge, high level, low level*/
134 switch ( line )
135 {
136 case TIMER0_INT:
137 case TIMER1_INT:
138 case GSM_SYS0_INT:
139 case GSM_SYS1_INT:
140 case SSC0_CONFLICT_INT:
141 case SSC1_CONFLICT_INT:
142 case TD_FRM_INT: // it is edge interrupt, maybe rising or falling???
143 case TD_LPM4_INT: // it is edge interrupt, maybe rising or falling???
144 {
145 int_type = IRQ_TYPE_EDGE_RISING;
146 break;
147 }
148 case I2C0_INT:
149 case I2C1_INT:
150 {
151 int_type = IRQ_TYPE_LEVEL_LOW;
152 break;
153 }
154 default:
155 {
156 int_type = IRQ_TYPE_LEVEL_HIGH;
157 break;
158 }
159 }
160 gic_set_type(d,int_type);
161}
162
163
164/*
165 * Initialize the interrupt controller unit.
166 */
167void __init zx297510_init_irq(void)
168{
169 unsigned int i;
170
171 /*
172 * in order to avoid config repeatedly, let bits needed by a9 in these registers default
173 * maybe some devices used by a9 should invoke functions in PCU.h to set interrupt type
174 * and clear interrupt
175 */
176
177#if 0
178 /*
179 * config int type and polarity in PCU
180 * timer2 and timer3 int is not taken care, its be config in timer driver
181 * some times external int may need different type, so zx297510_int_set_type()
182 * will config it automatically
183 */
184 iowrite32(0xfffff3f9, PCU_BASE_VA+0x60); /*int type*/
185 iowrite32(0xffffffe7,PCU_BASE_VA+0x70); /*int pol*/
186 iowrite32(0x04c3, PCU_BASE_VA+0xe4); /*int type*/
187 iowrite32(0x1ff8, PCU_BASE_VA+0xe8); /*int pol*/
188
189 /*clear fake int*/
190 iowrite32(0xffffffff, PCU_BASE_VA+0x80);
191 iowrite32(0x1fff, PCU_BASE_VA+0xec);
192#endif
193
194 gic_arch_extn.irq_set_type = zx297510_int_set_type;
195 gic_init(0, GIC_PPI_START, GIC_DIST_BASE, GIC_CPU_BASE);
196
197 /*config int type and polarity int INT_MODE_REG and GIC*/
198 for (i = GIC_PPI_START; i < NR_IRQS; i++) {
199 int_set_type_default(i);
200 }
201
202 printk(KERN_INFO "ZTE-TSP zx297510 GIC initialized\n");
203}
204
205