1 /* mbed Microcontroller Library
2 * Copyright (c) 2006-2013 ARM Limited
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
18 #include "gpio_irq_api.h"
19 #include "intc_iodefine.h"
22 #include "gpio_addrdefine.h"
26 static void gpio_irq0(void);
27 static void gpio_irq1(void);
28 static void gpio_irq2(void);
29 static void gpio_irq3(void);
30 static void gpio_irq4(void);
31 static void gpio_irq5(void);
32 static void gpio_irq6(void);
33 static void gpio_irq7(void);
35 static gpio_irq_t
*channel_obj
[CHANNEL_NUM
] = {NULL
};
36 static gpio_irq_handler irq_handler
;
37 static const int nIRQn_h
= 32;
38 extern PinName gpio_multi_guard
;
48 static const IRQHandler irq_tbl
[CHANNEL_NUM
] = {
59 static const PinMap PinMap_IRQ
[] = {
60 {P1_0
, IRQ0
, 4}, {P1_1
, IRQ1
, 4}, {P1_2
, IRQ2
, 4},
61 {P1_3
, IRQ3
, 4}, {P1_4
, IRQ4
, 4}, {P1_5
, IRQ5
, 4},
62 {P1_6
, IRQ6
, 4}, {P1_7
, IRQ7
, 4}, {P1_8
, IRQ2
, 3},
63 {P1_9
, IRQ3
, 3}, {P1_10
, IRQ4
, 3}, {P1_11
, IRQ5
, 3}, // 11
64 {P2_0
, IRQ5
, 6}, {P2_12
, IRQ6
, 6}, {P2_13
, IRQ7
, 8},
65 {P2_14
, IRQ0
, 8}, {P2_15
, IRQ1
, 8}, // 16
66 {P3_0
, IRQ2
, 3}, {P3_1
, IRQ6
, 3}, {P3_3
, IRQ4
, 3},
67 {P3_9
, IRQ6
, 8}, // 20
68 {P4_8
, IRQ0
, 8}, {P4_9
, IRQ1
, 8}, {P4_10
, IRQ2
, 8},
69 {P4_11
, IRQ3
, 8}, {P4_12
, IRQ4
, 8}, {P4_13
, IRQ5
, 8},
70 {P4_14
, IRQ6
, 8}, {P4_15
, IRQ7
, 8}, // 28
71 {P5_6
, IRQ6
, 6}, {P5_8
, IRQ0
, 2}, {P5_9
, IRQ2
, 4}, // 31
72 {P6_0
, IRQ5
, 6}, {P6_1
, IRQ4
, 4}, {P6_2
, IRQ7
, 4},
73 {P6_3
, IRQ2
, 4}, {P6_4
, IRQ3
, 4}, {P6_8
, IRQ0
, 8},
74 {P6_9
, IRQ1
, 8}, {P6_10
, IRQ2
, 8}, {P6_11
, IRQ3
, 8},
75 {P6_12
, IRQ4
, 8}, {P6_13
, IRQ5
, 8}, {P6_14
, IRQ6
, 8},
76 {P6_15
, IRQ7
, 8}, // 44
77 {P7_8
, IRQ1
, 8}, {P7_9
, IRQ0
, 8}, {P7_10
, IRQ2
, 8},
78 {P7_11
, IRQ3
, 8}, {P7_12
, IRQ4
, 8}, {P7_13
, IRQ5
, 8},
79 {P7_14
, IRQ6
, 8}, // 51
80 {P8_2
, IRQ0
, 5}, {P8_3
, IRQ1
, 6}, {P8_7
, IRQ5
, 4},
81 {P9_1
, IRQ0
, 4}, // 55
82 {P11_12
,IRQ3
, 3}, {P11_15
,IRQ1
, 3}, // 57
87 static void handle_interrupt_in(int irq_num
) {
91 gpio_irq_event irq_event
;
94 if (irqs
& (1 << irq_num
)) {
95 obj
= channel_obj
[irq_num
];
97 edge_req
= ((INTCICR1
>> (obj
->ch
* 2)) & 3);
100 } else if (edge_req
== 2) {
101 irq_event
= IRQ_RISE
;
103 uint32_t mask
= (1 << (obj
->pin
& 0x0F));
104 __I
uint32_t *reg_in
= (volatile uint32_t *) PPR((int)PINGROUP(obj
->pin
));
106 if ((*reg_in
& mask
) == 0) {
107 irq_event
= IRQ_FALL
;
109 irq_event
= IRQ_RISE
;
112 irq_handler(obj
->port
, irq_event
);
114 INTCIRQRR
&= ~(1 << irq_num
);
118 static void gpio_irq0(void) {
119 handle_interrupt_in(0);
122 static void gpio_irq1(void) {
123 handle_interrupt_in(1);
126 static void gpio_irq2(void) {
127 handle_interrupt_in(2);
130 static void gpio_irq3(void) {
131 handle_interrupt_in(3);
134 static void gpio_irq4(void) {
135 handle_interrupt_in(4);
138 static void gpio_irq5(void) {
139 handle_interrupt_in(5);
142 static void gpio_irq6(void) {
143 handle_interrupt_in(6);
146 static void gpio_irq7(void) {
147 handle_interrupt_in(7);
150 int gpio_irq_init(gpio_irq_t
*obj
, PinName pin
, gpio_irq_handler handler
, uint32_t id
) {
152 if (pin
== NC
) return -1;
154 obj
->ch
= pinmap_peripheral(pin
, PinMap_IRQ
);
155 obj
->pin
= (int)pin
;
156 obj
->port
= (int)id
;
159 channel_obj
[obj
->ch
] = obj
;
160 irq_handler
= handler
;
162 pinmap_pinout(pin
, PinMap_IRQ
);
163 gpio_multi_guard
= pin
; /* Set multi guard */
166 InterruptHandlerRegister((IRQn_Type
)(nIRQn_h
+obj
->ch
), (void (*)(uint32_t))irq_tbl
[obj
->ch
]);
167 INTCICR1
&= ~(0x3 << shift
);
168 INTCICR1
|= (0x3 << shift
);
169 GIC_SetPriority((IRQn_Type
)(nIRQn_h
+obj
->ch
), 5);
170 GIC_EnableIRQ((IRQn_Type
)(nIRQn_h
+obj
->ch
));
177 void gpio_irq_free(gpio_irq_t
*obj
) {
178 channel_obj
[obj
->ch
] = NULL
;
181 void gpio_irq_set(gpio_irq_t
*obj
, gpio_irq_event event
, uint32_t enable
) {
182 int shift
= obj
->ch
*2;
183 uint16_t val
= event
== IRQ_RISE
? 2 :
184 event
== IRQ_FALL
? 1 : 0;
185 uint16_t work_icr_val
;
187 /* check edge interrupt setting */
188 work_icr_val
= INTCICR1
;
190 /* Set interrupt serect */
191 work_icr_val
|= (val
<< shift
);
193 /* Clear interrupt serect */
194 work_icr_val
&= ~(val
<< shift
);
197 if ((work_icr_val
& (3 << shift
)) == 0) {
198 /* No edge interrupt setting */
199 GIC_DisableIRQ((IRQn_Type
)(nIRQn_h
+obj
->ch
));
200 /* Clear Interrupt flags */
201 INTCIRQRR
&= ~(1 << obj
->ch
);
202 INTCICR1
= work_icr_val
;
203 } else if (obj
->int_enable
== 1) {
204 INTCICR1
= work_icr_val
;
205 GIC_EnableIRQ((IRQn_Type
)(nIRQn_h
+ obj
->ch
));
207 INTCICR1
= work_icr_val
;
211 void gpio_irq_enable(gpio_irq_t
*obj
) {
212 int shift
= obj
->ch
*2;
213 uint16_t work_icr_val
= INTCICR1
;
215 /* check edge interrupt setting */
216 if ((work_icr_val
& (3 << shift
)) != 0) {
217 GIC_EnableIRQ((IRQn_Type
)(nIRQn_h
+ obj
->ch
));
222 void gpio_irq_disable(gpio_irq_t
*obj
) {
223 GIC_DisableIRQ((IRQn_Type
)(nIRQn_h
+ obj
->ch
));