diff options
Diffstat (limited to 'firmware/target/arm/imx31/gigabeat-s/gpio-imx31.c')
-rw-r--r-- | firmware/target/arm/imx31/gigabeat-s/gpio-imx31.c | 68 |
1 files changed, 36 insertions, 32 deletions
diff --git a/firmware/target/arm/imx31/gigabeat-s/gpio-imx31.c b/firmware/target/arm/imx31/gigabeat-s/gpio-imx31.c index 0b76b84d36..2a83b5ca73 100644 --- a/firmware/target/arm/imx31/gigabeat-s/gpio-imx31.c +++ b/firmware/target/arm/imx31/gigabeat-s/gpio-imx31.c | |||
@@ -73,29 +73,38 @@ static struct gpio_module_descriptor | |||
73 | #endif | 73 | #endif |
74 | }; | 74 | }; |
75 | 75 | ||
76 | static void gpio_call_events(enum gpio_module_number gpio) | 76 | static void gpio_call_events(const struct gpio_module_descriptor * const desc) |
77 | { | 77 | { |
78 | const struct gpio_module_descriptor * const desc = &gpio_descs[gpio]; | ||
79 | const struct gpio_event_list * const list = desc->list; | 78 | const struct gpio_event_list * const list = desc->list; |
80 | struct gpio_map * const base = desc->base; | 79 | struct gpio_map * const base = desc->base; |
81 | unsigned i; | 80 | const struct gpio_event * event, *event_last; |
82 | 81 | ||
83 | /* Intersect pending and unmasked bits */ | 82 | /* Intersect pending and unmasked bits */ |
84 | uint32_t pending = base->isr & base->imr; | 83 | uint32_t pnd = base->isr & base->imr; |
84 | |||
85 | event = list->events; | ||
86 | event_last = event + list->count; | ||
85 | 87 | ||
86 | /* Call each event handler in order */ | 88 | /* Call each event handler in order */ |
87 | for (i = 0; i < list->count; i++) | 89 | /* .count is surely expected to be > 0 */ |
90 | do | ||
88 | { | 91 | { |
89 | const struct gpio_event * const event = &list->events[i]; | 92 | uint32_t mask = event->mask; |
90 | uint32_t bit = 1ul << event->line; | 93 | |
94 | if (pnd & mask) | ||
95 | { | ||
96 | event->callback(); | ||
97 | pnd &= ~mask; | ||
98 | } | ||
91 | 99 | ||
92 | if ((pending & bit) && event->callback()) | 100 | if (pnd == 0) |
93 | pending &= ~bit; | 101 | break; /* Teminate early if nothing more to service */ |
94 | } | 102 | } |
103 | while (++event < event_last); | ||
95 | 104 | ||
96 | if (pending != 0) | 105 | if (pnd != 0) |
97 | { | 106 | { |
98 | /* Wasn't handled */ | 107 | /* One or more weren't handled */ |
99 | UIE_VECTOR(); | 108 | UIE_VECTOR(); |
100 | } | 109 | } |
101 | } | 110 | } |
@@ -103,21 +112,21 @@ static void gpio_call_events(enum gpio_module_number gpio) | |||
103 | #if (GPIO_EVENT_MASK & USE_GPIO1_EVENTS) | 112 | #if (GPIO_EVENT_MASK & USE_GPIO1_EVENTS) |
104 | static __attribute__((interrupt("IRQ"))) void GPIO1_HANDLER(void) | 113 | static __attribute__((interrupt("IRQ"))) void GPIO1_HANDLER(void) |
105 | { | 114 | { |
106 | gpio_call_events(GPIO1_NUM); | 115 | gpio_call_events(&gpio_descs[GPIO1_NUM]); |
107 | } | 116 | } |
108 | #endif | 117 | #endif |
109 | 118 | ||
110 | #if (GPIO_EVENT_MASK & USE_GPIO2_EVENTS) | 119 | #if (GPIO_EVENT_MASK & USE_GPIO2_EVENTS) |
111 | static __attribute__((interrupt("IRQ"))) void GPIO2_HANDLER(void) | 120 | static __attribute__((interrupt("IRQ"))) void GPIO2_HANDLER(void) |
112 | { | 121 | { |
113 | gpio_call_events(GPIO2_NUM); | 122 | gpio_call_events(&gpio_descs[GPIO2_NUM]); |
114 | } | 123 | } |
115 | #endif | 124 | #endif |
116 | 125 | ||
117 | #if (GPIO_EVENT_MASK & USE_GPIO3_EVENTS) | 126 | #if (GPIO_EVENT_MASK & USE_GPIO3_EVENTS) |
118 | static __attribute__((interrupt("IRQ"))) void GPIO3_HANDLER(void) | 127 | static __attribute__((interrupt("IRQ"))) void GPIO3_HANDLER(void) |
119 | { | 128 | { |
120 | gpio_call_events(GPIO3_NUM); | 129 | gpio_call_events(&gpio_descs[GPIO3_NUM]); |
121 | } | 130 | } |
122 | #endif | 131 | #endif |
123 | 132 | ||
@@ -140,19 +149,16 @@ void gpio_init(void) | |||
140 | #endif | 149 | #endif |
141 | } | 150 | } |
142 | 151 | ||
143 | bool gpio_enable_event(enum gpio_module_number gpio, unsigned id) | 152 | bool gpio_enable_event(enum gpio_event_ids id) |
144 | { | 153 | { |
145 | const struct gpio_module_descriptor * const desc = &gpio_descs[gpio]; | 154 | const struct gpio_module_descriptor * const desc = &gpio_descs[id >> 5]; |
146 | const struct gpio_event * const event = &desc->list->events[id]; | 155 | const struct gpio_event * const event = &desc->list->events[id & 31]; |
147 | struct gpio_map * const base = desc->base; | 156 | struct gpio_map * const base = desc->base; |
148 | volatile uint32_t *icr; | 157 | volatile uint32_t *icr; |
149 | uint32_t mask; | 158 | uint32_t mask, line; |
150 | uint32_t imr; | 159 | uint32_t imr; |
151 | int shift; | 160 | int shift; |
152 | 161 | ||
153 | if (id >= desc->list->count) | ||
154 | return false; | ||
155 | |||
156 | int oldlevel = disable_irq_save(); | 162 | int oldlevel = disable_irq_save(); |
157 | 163 | ||
158 | imr = base->imr; | 164 | imr = base->imr; |
@@ -160,39 +166,37 @@ bool gpio_enable_event(enum gpio_module_number gpio, unsigned id) | |||
160 | if (imr == 0) | 166 | if (imr == 0) |
161 | { | 167 | { |
162 | /* First enabled interrupt for this GPIO */ | 168 | /* First enabled interrupt for this GPIO */ |
163 | avic_enable_int(desc->ints, IRQ, desc->list->priority, | 169 | avic_enable_int(desc->ints, IRQ, desc->list->ints_priority, |
164 | desc->handler); | 170 | desc->handler); |
165 | } | 171 | } |
166 | 172 | ||
167 | /* Set the line sense */ | 173 | /* Set the line sense */ |
168 | icr = &base->icr[event->line >> 4]; | 174 | line = find_first_set_bit(event->mask); |
169 | shift = (event->line & 15) << 1; | 175 | icr = &base->icr[line >> 4]; |
176 | shift = (line & 15) << 1; | ||
170 | mask = GPIO_SENSE_CONFIG_MASK << shift; | 177 | mask = GPIO_SENSE_CONFIG_MASK << shift; |
171 | 178 | ||
172 | *icr = (*icr & ~mask) | ((event->sense << shift) & mask); | 179 | *icr = (*icr & ~mask) | ((event->sense << shift) & mask); |
173 | 180 | ||
174 | /* Unmask the line */ | 181 | /* Unmask the line */ |
175 | base->imr = imr | (1ul << event->line); | 182 | base->imr = imr | event->mask; |
176 | 183 | ||
177 | restore_irq(oldlevel); | 184 | restore_irq(oldlevel); |
178 | 185 | ||
179 | return true; | 186 | return true; |
180 | } | 187 | } |
181 | 188 | ||
182 | void gpio_disable_event(enum gpio_module_number gpio, unsigned id) | 189 | void gpio_disable_event(enum gpio_event_ids id) |
183 | { | 190 | { |
184 | const struct gpio_module_descriptor * const desc = &gpio_descs[gpio]; | 191 | const struct gpio_module_descriptor * const desc = &gpio_descs[id >> 5]; |
185 | const struct gpio_event * const event = &desc->list->events[id]; | 192 | const struct gpio_event * const event = &desc->list->events[id & 31]; |
186 | struct gpio_map * const base = desc->base; | 193 | struct gpio_map * const base = desc->base; |
187 | uint32_t imr; | 194 | uint32_t imr; |
188 | 195 | ||
189 | if (id >= desc->list->count) | ||
190 | return; | ||
191 | |||
192 | int oldlevel = disable_irq_save(); | 196 | int oldlevel = disable_irq_save(); |
193 | 197 | ||
194 | /* Remove bit from mask */ | 198 | /* Remove bit from mask */ |
195 | imr = base->imr & ~(1ul << event->line); | 199 | imr = base->imr & ~event->mask; |
196 | 200 | ||
197 | /* Mask the line */ | 201 | /* Mask the line */ |
198 | base->imr = imr; | 202 | base->imr = imr; |