summaryrefslogtreecommitdiff
path: root/firmware/target/arm/imx31/gigabeat-s/gpio-imx31.c
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/target/arm/imx31/gigabeat-s/gpio-imx31.c')
-rw-r--r--firmware/target/arm/imx31/gigabeat-s/gpio-imx31.c68
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
76static void gpio_call_events(enum gpio_module_number gpio) 76static 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)
104static __attribute__((interrupt("IRQ"))) void GPIO1_HANDLER(void) 113static __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)
111static __attribute__((interrupt("IRQ"))) void GPIO2_HANDLER(void) 120static __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)
118static __attribute__((interrupt("IRQ"))) void GPIO3_HANDLER(void) 127static __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
143bool gpio_enable_event(enum gpio_module_number gpio, unsigned id) 152bool 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
182void gpio_disable_event(enum gpio_module_number gpio, unsigned id) 189void 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;