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 gpio1_events
[GPIO1_NUM_EVENTS
];
37 #if (GPIO_EVENT_MASK & USE_GPIO2_EVENTS)
38 static __attribute__((interrupt("IRQ"))) void GPIO2_HANDLER(void);
39 extern const struct gpio_event gpio2_events
[GPIO2_NUM_EVENTS
];
42 #if (GPIO_EVENT_MASK & USE_GPIO3_EVENTS)
43 static __attribute__((interrupt("IRQ"))) void GPIO3_HANDLER(void);
44 extern const struct gpio_event gpio3_events
[GPIO3_NUM_EVENTS
];
47 #define DR (0x00 / sizeof (unsigned long)) /* 00h */
48 #define GDIR (0x04 / sizeof (unsigned long)) /* 04h */
49 #define PSR (0x08 / sizeof (unsigned long)) /* 08h */
50 #define ICR (0x0C / sizeof (unsigned long)) /* 0Ch ICR1,2 */
51 #define IMR (0x14 / sizeof (unsigned long)) /* 14h */
52 #define ISR (0x18 / sizeof (unsigned long))
54 static const struct gpio_module_desc
56 volatile unsigned long * const base
; /* Module base address */
57 void (* const handler
)(void); /* Interrupt function */
58 const struct gpio_event
* const events
; /* Event handler list */
59 const uint8_t ints
; /* AVIC int number */
60 const uint8_t int_priority
; /* AVIC int priority */
61 const uint8_t count
; /* Number of events */
62 } gpio_descs
[GPIO_NUM_GPIO
] =
64 #if (GPIO_EVENT_MASK & USE_GPIO1_EVENTS)
66 .base
= (unsigned long *)GPIO1_BASE_ADDR
,
68 .handler
= GPIO1_HANDLER
,
69 .events
= gpio1_events
,
70 .count
= GPIO1_NUM_EVENTS
,
71 .int_priority
= GPIO1_INT_PRIO
74 #if (GPIO_EVENT_MASK & USE_GPIO2_EVENTS)
76 .base
= (unsigned long *)GPIO2_BASE_ADDR
,
78 .handler
= GPIO2_HANDLER
,
79 .events
= gpio2_events
,
80 .count
= GPIO2_NUM_EVENTS
,
81 .int_priority
= GPIO2_INT_PRIO
84 #if (GPIO_EVENT_MASK & USE_GPIO3_EVENTS)
86 .base
= (unsigned long *)GPIO3_BASE_ADDR
,
88 .handler
= GPIO3_HANDLER
,
89 .events
= gpio3_events
,
90 .count
= GPIO3_NUM_EVENTS
,
91 .int_priority
= GPIO3_INT_PRIO
,
96 static void gpio_call_events(enum gpio_module_number gpio
)
98 const struct gpio_module_desc
* const desc
= &gpio_descs
[gpio
];
99 volatile unsigned long * const base
= desc
->base
;
100 const struct gpio_event
* event
, *event_last
;
102 event
= desc
->events
;
103 event_last
= event
+ desc
->count
;
105 /* Intersect pending and unmasked bits */
106 unsigned long pnd
= base
[ISR
] & base
[IMR
];
108 /* Call each event handler in order */
109 /* .count is surely expected to be > 0 */
112 unsigned long mask
= event
->mask
;
121 break; /* Teminate early if nothing more to service */
123 while (++event
< event_last
);
127 /* One or more weren't handled */
132 #if (GPIO_EVENT_MASK & USE_GPIO1_EVENTS)
133 static __attribute__((interrupt("IRQ"))) void GPIO1_HANDLER(void)
135 gpio_call_events(GPIO1_NUM
);
139 #if (GPIO_EVENT_MASK & USE_GPIO2_EVENTS)
140 static __attribute__((interrupt("IRQ"))) void GPIO2_HANDLER(void)
142 gpio_call_events(GPIO2_NUM
);
146 #if (GPIO_EVENT_MASK & USE_GPIO3_EVENTS)
147 static __attribute__((interrupt("IRQ"))) void GPIO3_HANDLER(void)
149 gpio_call_events(GPIO3_NUM
);
153 void INIT_ATTR
gpio_init(void)
155 /* Mask-out GPIO interrupts - enable what's wanted later */
157 for (i
= 0; i
< GPIO_NUM_GPIO
; i
++)
158 gpio_descs
[i
].base
[IMR
] = 0;
161 bool gpio_enable_event(enum gpio_event_ids id
)
163 const struct gpio_module_desc
* const desc
= &gpio_descs
[id
>> 5];
164 const struct gpio_event
* const event
= &desc
->events
[id
& 31];
165 volatile unsigned long * const base
= desc
->base
;
166 volatile unsigned long *icr
;
167 unsigned long mask
, line
;
171 int oldlevel
= disable_irq_save();
177 /* First enabled interrupt for this GPIO */
178 avic_enable_int(desc
->ints
, INT_TYPE_IRQ
, desc
->int_priority
,
182 /* Set the line sense */
183 line
= find_first_set_bit(event
->mask
);
184 icr
= &base
[ICR
+ (line
>> 4)];
185 shift
= 2*(line
& 15);
186 mask
= GPIO_SENSE_CONFIG_MASK
<< shift
;
188 *icr
= (*icr
& ~mask
) | ((event
->sense
<< shift
) & mask
);
190 /* Unmask the line */
191 base
[IMR
] = imr
| event
->mask
;
193 restore_irq(oldlevel
);
198 void gpio_disable_event(enum gpio_event_ids id
)
200 const struct gpio_module_desc
* const desc
= &gpio_descs
[id
>> 5];
201 const struct gpio_event
* const event
= &desc
->events
[id
& 31];
202 volatile unsigned long * const base
= desc
->base
;
205 int oldlevel
= disable_irq_save();
207 /* Remove bit from mask */
208 imr
= base
[IMR
] & ~event
->mask
;
215 /* No events remain enabled */
216 avic_disable_int(desc
->ints
);
219 restore_irq(oldlevel
);