2 * This file is subject to the terms and conditions of the GNU General Public
3 * License. See the file "COPYING" in the main directory of this archive
6 * Copyright (C) 2003 Atheros Communications, Inc., All Rights Reserved.
7 * Copyright (C) 2006 FON Technology, SL.
8 * Copyright (C) 2006 Imre Kaloz <kaloz@openwrt.org>
9 * Copyright (C) 2007 Othello <bach_ag@hotmail.com>
13 * Support for AR531X GPIO -- General Purpose Input/Output Pins
16 #include <linux/autoconf.h>
17 #include <linux/init.h>
18 #include <linux/interrupt.h>
19 #include <linux/types.h>
20 #include <linux/module.h>
21 #include <linux/delay.h>
22 #include <linux/platform_device.h>
23 #include <linux/irq.h>
25 #include <asm/addrspace.h>
27 #include <asm/irq_cpu.h>
31 GPIO Interrupt Support
32 Make use of request_irq() and the function gpio_to_irq() to trap gpio events
35 /* Global variables */
36 static u32 ar531x_gpio_intr_Mask
= 0;
38 AR5312: I don't have any devices with this chip. Assumed to be similar to AR5215
39 will someone who has one try the code and remove this message if it works?
42 #ifdef CONFIG_ATHEROS_AR5315
44 AR5315: Up to 2 GPIO pins may be monitored simultaneously
45 specifying more pins if you already have 2 will not have any effect
46 however, the excess gpio irqs will also be triggered if a valid gpio being monitored triggers
47 only high, low or edge triggered interrupt supported
49 static unsigned int ar5315_gpio_set_type_gpio
= 0;
50 static unsigned int ar5315_gpio_set_type_lvl
= IRQF_TRIGGER_RISING
| IRQF_TRIGGER_FALLING
;
53 #ifdef CONFIG_ATHEROS_AR5312
54 /* Enable the specified AR5312_GPIO_IRQ interrupt */
55 static void ar5312_gpio_intr_enable(unsigned int irq
) {
60 gpio
= irq
- (AR531X_GPIO_IRQ(0));
61 if (gpio
>= AR531X_NUM_GPIO
)
63 ar531x_gpio_intr_Mask
|= (1<<gpio
);
65 reg
= sysRegRead(AR531X_GPIO_CR
);
66 reg
&= ~(AR531X_GPIO_CR_M(gpio
) | AR531X_GPIO_CR_UART(gpio
) | AR531X_GPIO_CR_INT(gpio
));
67 reg
|= AR531X_GPIO_CR_I(gpio
);
68 reg
|= AR531X_GPIO_CR_INT(gpio
);
70 sysRegWrite(AR531X_GPIO_CR
, reg
);
71 (void)sysRegRead(AR531X_GPIO_CR
); /* flush to hardware */
73 imr
= sysRegRead(AR531X_IMR
);
74 imr
|= AR531X_ISR_GPIO
;
75 sysRegWrite(AR531X_IMR
, imr
);
76 imr
= sysRegRead(AR531X_IMR
); /* flush write buffer */
79 /* Disable the specified AR5312_GPIO_IRQ interrupt */
80 static void ar5312_gpio_intr_disable(unsigned int irq
) {
83 gpio
= irq
- (AR531X_GPIO_IRQ(0));
84 if (gpio
>= AR531X_NUM_GPIO
)
87 reg
= sysRegRead(AR531X_GPIO_CR
);
88 reg
&= ~(AR531X_GPIO_CR_M(gpio
) | AR531X_GPIO_CR_UART(gpio
) | AR531X_GPIO_CR_INT(gpio
));
89 reg
|= AR531X_GPIO_CR_I(gpio
);
90 /* No GPIO_CR_INT bit */
92 sysRegWrite(AR531X_GPIO_CR
, reg
);
93 (void)sysRegRead(AR531X_GPIO_CR
); /* flush to hardware */
95 /* Disable Interrupt if no gpio needs triggering */
96 if (ar531x_gpio_intr_Mask
!= 0) {
99 imr
= sysRegRead(AR531X_IMR
);
100 imr
&= ~AR531X_ISR_GPIO
;
101 sysRegWrite(AR531X_IMR
, imr
);
102 imr
= sysRegRead(AR531X_IMR
); /* flush write buffer */
105 ar531x_gpio_intr_Mask
&= ~(1<<gpio
);
108 /* Turn on the specified AR5312_GPIO_IRQ interrupt */
109 static unsigned int ar5312_gpio_intr_startup(unsigned int irq
) {
110 ar5312_gpio_intr_enable(irq
);
114 static void ar5312_gpio_intr_end(unsigned int irq
) {
115 if (!(irq_desc
[irq
].status
& (IRQ_DISABLED
| IRQ_INPROGRESS
)))
116 ar5312_gpio_intr_enable(irq
);
119 asmlinkage
void ar5312_gpio_irq_dispatch(void) {
122 gpioIntPending
= sysRegRead(AR531X_GPIO_DI
) & ar531x_gpio_intr_Mask
;
123 sysRegWrite(AR531X_ISR
, sysRegRead(AR531X_IMR
) | ~AR531X_ISR_GPIO
);
124 for (i
=0; i
<AR531X_GPIO_IRQ_COUNT
; i
++) {
125 if (gpioIntPending
& (1 << i
))
126 do_IRQ(AR531X_GPIO_IRQ(i
));
129 #endif /* #ifdef CONFIG_ATHEROS_AR5312 */
131 #ifdef CONFIG_ATHEROS_AR5315
132 /* Enable the specified AR5315_GPIO_IRQ interrupt */
133 static void ar5315_gpio_intr_enable(unsigned int irq
) {
139 gpio
= irq
- (AR531X_GPIO_IRQ(0));
140 if (gpio
>= AR5315_NUM_GPIO
)
142 ar531x_gpio_intr_Mask
|= (1<<gpio
);
144 reg
= sysRegRead(AR5315_GPIO_CR
);
145 reg
&= ~(AR5315_GPIO_CR_M(gpio
));
146 reg
|= AR5315_GPIO_CR_I(gpio
);
147 sysRegWrite(AR5315_GPIO_CR
, reg
);
148 (void)sysRegRead(AR5315_GPIO_CR
); /* flush write to hardware */
150 /* Locate a free register slot to enable gpio intr
151 will fail silently if no more slots are available
153 reg
= sysRegRead(AR5315_GPIO_INT
);
154 for (i
=0 ; i
<=AR5315_GPIO_INT_MAX_Y
; i
++) {
155 /* Free slot means trigger level = 0 */
156 if ( AR5315_GPIO_INT_LVL_OFF
==
157 (reg
& AR5315_GPIO_INT_LVL_M
) ) {
159 unsigned int def_lvl
= AR5315_GPIO_INT_LVL_EDGE
;
160 if (ar5315_gpio_set_type_gpio
== gpio
)
161 def_lvl
= ar5315_gpio_set_type_lvl
;
163 /* Set the gpio level trigger mode */
164 /* reg &= ~(AR5315_GPIO_INT_LVL_M(i)); */
165 reg
|= AR5315_GPIO_INT_LVL(def_lvl
);
167 /* Enable the gpio pin */
168 reg
&= ~(AR5315_GPIO_INT_M
);
169 reg
|= AR5315_GPIO_INT_S(i
);
171 sysRegWrite(AR5315_GPIO_INT
, reg
);
172 (void)sysRegRead(AR5315_GPIO_INT
); /* flush write to hardware */
174 /* break out of for loop */
176 } /* end if trigger level for slot i is 0 */
177 } /* end for each slot */
179 imr
= sysRegRead(AR5315_IMR
);
180 imr
|= AR5315_ISR_GPIO
;
181 sysRegWrite(AR5315_IMR
, imr
);
182 imr
= sysRegRead(AR5315_IMR
); /* flush write buffer */
186 /* Disable the specified AR5315_GPIO_IRQ interrupt */
187 static void ar5315_gpio_intr_disable(unsigned int irq
) {
192 gpio
= irq
- (AR531X_GPIO_IRQ(0));
193 if (gpio
>= AR5315_NUM_GPIO
)
196 reg
= sysRegRead(AR5315_GPIO_CR
);
197 reg
&= ~(AR5315_GPIO_CR_M(gpio
));
198 reg
|= AR5315_GPIO_CR_I(gpio
);
199 sysRegWrite(AR5315_GPIO_CR
, reg
);
200 (void)sysRegRead(AR5315_GPIO_CR
); /* flush write to hardware */
202 /* Locate a the correct register slot to disable gpio intr */
203 reg
= sysRegRead(AR5315_GPIO_INT
);
204 for (i
=0 ; i
<=AR5315_GPIO_INT_MAX_Y
; i
++) {
205 /* If this correct */
206 if ( AR5315_GPIO_INT_S(i
) ==
207 (reg
& AR5315_GPIO_INT_M
) ) {
208 /* Clear the gpio level trigger mode */
209 reg
&= ~(AR5315_GPIO_INT_LVL_M
);
211 sysRegWrite(AR5315_GPIO_INT
, reg
);
212 (void)sysRegRead(AR5315_GPIO_INT
); /* flush write to hardware */
214 } /* end if trigger level for slot i is 0 */
215 } /* end for each slot */
217 /* Disable interrupt only if no gpio needs triggering */
218 if (ar531x_gpio_intr_Mask
!= 0) {
221 imr
= sysRegRead(AR5315_IMR
);
222 imr
&= ~AR5315_ISR_GPIO
;
223 sysRegWrite(AR5315_IMR
, imr
);
224 imr
= sysRegRead(AR5315_IMR
); /* flush write buffer */
227 ar531x_gpio_intr_Mask
&= ~(1<<gpio
);
230 /* Turn on the specified AR5315_GPIO_IRQ interrupt */
231 static unsigned int ar5315_gpio_intr_startup(unsigned int irq
) {
232 ar5315_gpio_intr_enable(irq
);
236 static void ar5315_gpio_intr_end(unsigned int irq
) {
237 if (!(irq_desc
[irq
].status
& (IRQ_DISABLED
| IRQ_INPROGRESS
)))
238 ar5315_gpio_intr_enable(irq
);
241 static int ar5315_gpio_intr_set_type(unsigned int irq
, unsigned int flow_type
) {
242 ar5315_gpio_set_type_gpio
= irq
- (AR531X_GPIO_IRQ(0));
243 if (ar5315_gpio_set_type_gpio
> AR5315_NUM_GPIO
)
245 switch (flow_type
& IRQF_TRIGGER_MASK
) {
246 case IRQF_TRIGGER_RISING
:
247 case IRQF_TRIGGER_FALLING
:
248 printk(KERN_WARNING
"AR5315 GPIO %u falling back to edge triggered\n", ar5315_gpio_set_type_gpio
);
249 case IRQF_TRIGGER_RISING
| IRQF_TRIGGER_FALLING
:
250 ar5315_gpio_set_type_lvl
= AR5315_GPIO_INT_LVL_EDGE
;
252 case IRQF_TRIGGER_LOW
:
253 ar5315_gpio_set_type_lvl
= AR5315_GPIO_INT_LVL_LOW
;
255 case IRQF_TRIGGER_HIGH
:
256 ar5315_gpio_set_type_lvl
= AR5315_GPIO_INT_LVL_HIGH
;
264 asmlinkage
void ar5315_gpio_irq_dispatch(void){
267 gpioIntPending
= sysRegRead(AR5315_GPIO_DI
) & ar531x_gpio_intr_Mask
;
268 sysRegWrite(AR5315_ISR
, sysRegRead(AR5315_IMR
) | ~AR5315_ISR_GPIO
);
269 for (i
=0; i
<AR531X_GPIO_IRQ_COUNT
; i
++) {
270 if (gpioIntPending
& (1 << i
))
271 do_IRQ(AR531X_GPIO_IRQ(i
));
274 #endif /* #ifdef CONFIG_ATHEROS_AR5315 */
277 static struct irq_chip ar531x_gpio_intr_controller
= {
278 .typename
= "AR531X GPIO",
283 spurious_gpio_handler(int cpl
, void *dev_id
)
286 DO_AR5312(gpioDataIn
= sysRegRead(AR531X_GPIO_DI
);)
287 DO_AR5315(gpioDataIn
= sysRegRead(AR5315_GPIO_DI
);)
289 printk("spurious_gpio_handler: 0x%08x dev=%p DI=0x%08x gpioIntMask=0x%08x\n",
290 cpl
, dev_id
, gpioDataIn
, ar531x_gpio_intr_Mask
);
295 static struct irqaction spurious_gpio
= {
296 .handler
= spurious_gpio_handler
,
297 .name
= "spurious_gpio",
300 /* Initialize AR531X GPIO interrupts */
301 static int __init
ar531x_gpio_init(void)
306 ar531x_gpio_intr_controller
.startup
= ar5312_gpio_intr_startup
; \
307 ar531x_gpio_intr_controller
.shutdown
= ar5312_gpio_intr_disable
; \
308 ar531x_gpio_intr_controller
.enable
= ar5312_gpio_intr_enable
; \
309 ar531x_gpio_intr_controller
.disable
= ar5312_gpio_intr_disable
; \
310 ar531x_gpio_intr_controller
.ack
= ar5312_gpio_intr_disable
; \
311 ar531x_gpio_intr_controller
.end
= ar5312_gpio_intr_end
; \
315 ar531x_gpio_intr_controller
.startup
= ar5315_gpio_intr_startup
; \
316 ar531x_gpio_intr_controller
.shutdown
= ar5315_gpio_intr_disable
; \
317 ar531x_gpio_intr_controller
.enable
= ar5315_gpio_intr_enable
; \
318 ar531x_gpio_intr_controller
.disable
= ar5315_gpio_intr_disable
; \
319 ar531x_gpio_intr_controller
.ack
= ar5315_gpio_intr_disable
; \
320 ar531x_gpio_intr_controller
.end
= ar5315_gpio_intr_end
; \
321 ar531x_gpio_intr_controller
.set_type
= ar5315_gpio_intr_set_type
; \
324 for (i
= AR531X_GPIO_IRQ_BASE
;
325 i
< AR531X_GPIO_IRQ_BASE
+ AR531X_GPIO_IRQ_COUNT
;
327 irq_desc
[i
].status
= IRQ_DISABLED
;
328 irq_desc
[i
].action
= NULL
;
329 irq_desc
[i
].depth
= 1;
330 irq_desc
[i
].chip
= &ar531x_gpio_intr_controller
;
333 setup_irq(AR531X_GPIO_IRQ_NONE
, &spurious_gpio
);
338 subsys_initcall(ar531x_gpio_init
);