1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
10 * Copyright (c) 2008 by Michael Sevakis
12 * IMX31 GPIO event manager
14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License
16 * as published by the Free Software Foundation; either version 2
17 * of the License, or (at your option) any later version.
19 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
20 * KIND, either express or implied.
22 ****************************************************************************/
25 #include "avic-imx31.h"
26 #include "gpio-imx31.h"
28 /* UIE vector found in avic-imx31.c */
29 extern void UIE_VECTOR(void);
31 /* Event lists are allocated for the specific target */
32 #if (GPIO_EVENT_MASK & USE_GPIO1_EVENTS)
33 static __attribute__((interrupt("IRQ"))) void GPIO1_HANDLER(void);
34 extern const struct gpio_event_list gpio1_event_list
;
37 #if (GPIO_EVENT_MASK & USE_GPIO2_EVENTS)
38 static __attribute__((interrupt("IRQ"))) void GPIO2_HANDLER(void);
39 extern const struct gpio_event_list gpio2_event_list
;
42 #if (GPIO_EVENT_MASK & USE_GPIO3_EVENTS)
43 static __attribute__((interrupt("IRQ"))) void GPIO3_HANDLER(void);
44 extern const struct gpio_event_list gpio3_event_list
;
47 static struct gpio_module_descriptor
49 struct gpio_map
* const base
; /* Module base address */
50 enum IMX31_INT_LIST ints
; /* AVIC int number */
51 void (*handler
)(void); /* Interrupt function */
52 const struct gpio_event_list
*list
; /* Event handler list */
53 } gpio_descs
[GPIO_NUM_GPIO
] =
55 #if (GPIO_EVENT_MASK & USE_GPIO1_EVENTS)
57 .base
= (struct gpio_map
*)GPIO1_BASE_ADDR
,
59 .handler
= GPIO1_HANDLER
,
62 #if (GPIO_EVENT_MASK & USE_GPIO2_EVENTS)
64 .base
= (struct gpio_map
*)GPIO2_BASE_ADDR
,
66 .handler
= GPIO2_HANDLER
,
69 #if (GPIO_EVENT_MASK & USE_GPIO3_EVENTS)
71 .base
= (struct gpio_map
*)GPIO3_BASE_ADDR
,
73 .handler
= GPIO3_HANDLER
,
78 static void gpio_call_events(const struct gpio_module_descriptor
* const desc
)
80 const struct gpio_event_list
* const list
= desc
->list
;
81 struct gpio_map
* const base
= desc
->base
;
82 const struct gpio_event
* event
, *event_last
;
84 /* Intersect pending and unmasked bits */
85 uint32_t pnd
= base
->isr
& base
->imr
;
88 event_last
= event
+ list
->count
;
90 /* Call each event handler in order */
91 /* .count is surely expected to be > 0 */
94 uint32_t mask
= event
->mask
;
103 break; /* Teminate early if nothing more to service */
105 while (++event
< event_last
);
109 /* One or more weren't handled */
114 #if (GPIO_EVENT_MASK & USE_GPIO1_EVENTS)
115 static __attribute__((interrupt("IRQ"))) void GPIO1_HANDLER(void)
117 gpio_call_events(&gpio_descs
[GPIO1_NUM
]);
121 #if (GPIO_EVENT_MASK & USE_GPIO2_EVENTS)
122 static __attribute__((interrupt("IRQ"))) void GPIO2_HANDLER(void)
124 gpio_call_events(&gpio_descs
[GPIO2_NUM
]);
128 #if (GPIO_EVENT_MASK & USE_GPIO3_EVENTS)
129 static __attribute__((interrupt("IRQ"))) void GPIO3_HANDLER(void)
131 gpio_call_events(&gpio_descs
[GPIO3_NUM
]);
137 /* Mask-out GPIO interrupts - enable what's wanted later */
142 /* Init the externally-defined event lists for each port */
143 #if (GPIO_EVENT_MASK & USE_GPIO1_EVENTS)
144 gpio_descs
[GPIO1_NUM
].list
= &gpio1_event_list
;
146 #if (GPIO_EVENT_MASK & USE_GPIO2_EVENTS)
147 gpio_descs
[GPIO2_NUM
].list
= &gpio2_event_list
;
149 #if (GPIO_EVENT_MASK & USE_GPIO3_EVENTS)
150 gpio_descs
[GPIO3_NUM
].list
= &gpio3_event_list
;
154 bool gpio_enable_event(enum gpio_event_ids id
)
156 const struct gpio_module_descriptor
* const desc
= &gpio_descs
[id
>> 5];
157 const struct gpio_event
* const event
= &desc
->list
->events
[id
& 31];
158 struct gpio_map
* const base
= desc
->base
;
159 volatile uint32_t *icr
;
164 int oldlevel
= disable_irq_save();
170 /* First enabled interrupt for this GPIO */
171 avic_enable_int(desc
->ints
, INT_TYPE_IRQ
, desc
->list
->ints_priority
,
175 /* Set the line sense */
176 line
= find_first_set_bit(event
->mask
);
177 icr
= &base
->icr
[line
>> 4];
178 shift
= (line
& 15) << 1;
179 mask
= GPIO_SENSE_CONFIG_MASK
<< shift
;
181 *icr
= (*icr
& ~mask
) | ((event
->sense
<< shift
) & mask
);
183 /* Unmask the line */
184 base
->imr
= imr
| event
->mask
;
186 restore_irq(oldlevel
);
191 void gpio_disable_event(enum gpio_event_ids id
)
193 const struct gpio_module_descriptor
* const desc
= &gpio_descs
[id
>> 5];
194 const struct gpio_event
* const event
= &desc
->list
->events
[id
& 31];
195 struct gpio_map
* const base
= desc
->base
;
198 int oldlevel
= disable_irq_save();
200 /* Remove bit from mask */
201 imr
= base
->imr
& ~event
->mask
;
208 /* No events remain enabled */
209 avic_disable_int(desc
->ints
);
212 restore_irq(oldlevel
);