aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorHerbert Valerio Riedel <hvr@gnu.org>2007-11-26 12:45:59 -0500
committerRussell King <rmk+kernel@arm.linux.org.uk>2008-01-26 09:37:31 -0500
commit7ca722533979d47563e75a40c86c405153818b83 (patch)
treef715a2f370d300587736b47d32f3fe64bdecf2ce /arch
parent4e9f9fd5148004b983b29e15de66918e71da56c0 (diff)
[ARM] 4669/1: ep93xx: simplify GPIO code and cleanups
This patch renumbers the (virtual) GPIO line numbering to have all irq-capable gpio lines <= EP93XX_GPIO_LINE_MAX_IRQ by swapping the port f range with the port c range; This simplifies code such as #define IRQ_EP93XX_GPIO(x) (64 + (((x) + (((x) >> 2) & 8)) & 0x1f)) or if (line >= 0 && line < 16) { /* Port A/B */ } else if (line >= 40 && line < 48) { /* Port F */ } considerably; in addition to the renumbering this patch also introduces macro constants EP93XX_GPIO_LINE_MAX_IRQ and EP93XX_GPIO_LINE_MAX, and replaces most magic numbers by those and invocations of gpio_to_irq()/irq_to_gpio(). Signed-off-by: Herbert Valerio Riedel <hvr@gnu.org> Acked-by: Lennert Buytenhek <buytenh@wantstofly.org> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'arch')
-rw-r--r--arch/arm/mach-ep93xx/core.c147
1 files changed, 70 insertions, 77 deletions
diff --git a/arch/arm/mach-ep93xx/core.c b/arch/arm/mach-ep93xx/core.c
index 8a7340661377..58957d7a5763 100644
--- a/arch/arm/mach-ep93xx/core.c
+++ b/arch/arm/mach-ep93xx/core.c
@@ -157,35 +157,35 @@ static unsigned char gpio_int_enabled[3];
157static unsigned char gpio_int_type1[3]; 157static unsigned char gpio_int_type1[3];
158static unsigned char gpio_int_type2[3]; 158static unsigned char gpio_int_type2[3];
159 159
160static void update_gpio_int_params(int abf) 160/* Port ordering is: A B F */
161static const u8 int_type1_register_offset[3] = { 0x90, 0xac, 0x4c };
162static const u8 int_type2_register_offset[3] = { 0x94, 0xb0, 0x50 };
163static const u8 eoi_register_offset[3] = { 0x98, 0xb4, 0x54 };
164static const u8 int_en_register_offset[3] = { 0x9c, 0xb8, 0x5c };
165
166static void update_gpio_int_params(unsigned port)
161{ 167{
162 if (abf == 0) { 168 BUG_ON(port > 2);
163 __raw_writeb(0, EP93XX_GPIO_A_INT_ENABLE);
164 __raw_writeb(gpio_int_type2[0], EP93XX_GPIO_A_INT_TYPE2);
165 __raw_writeb(gpio_int_type1[0], EP93XX_GPIO_A_INT_TYPE1);
166 __raw_writeb(gpio_int_unmasked[0] & gpio_int_enabled[0], EP93XX_GPIO_A_INT_ENABLE);
167 } else if (abf == 1) {
168 __raw_writeb(0, EP93XX_GPIO_B_INT_ENABLE);
169 __raw_writeb(gpio_int_type2[1], EP93XX_GPIO_B_INT_TYPE2);
170 __raw_writeb(gpio_int_type1[1], EP93XX_GPIO_B_INT_TYPE1);
171 __raw_writeb(gpio_int_unmasked[1] & gpio_int_enabled[1], EP93XX_GPIO_B_INT_ENABLE);
172 } else if (abf == 2) {
173 __raw_writeb(0, EP93XX_GPIO_F_INT_ENABLE);
174 __raw_writeb(gpio_int_type2[2], EP93XX_GPIO_F_INT_TYPE2);
175 __raw_writeb(gpio_int_type1[2], EP93XX_GPIO_F_INT_TYPE1);
176 __raw_writeb(gpio_int_unmasked[2] & gpio_int_enabled[2], EP93XX_GPIO_F_INT_ENABLE);
177 } else {
178 BUG();
179 }
180}
181 169
170 __raw_writeb(0, EP93XX_GPIO_REG(int_en_register_offset[port]));
171
172 __raw_writeb(gpio_int_type2[port],
173 EP93XX_GPIO_REG(int_type2_register_offset[port]));
174
175 __raw_writeb(gpio_int_type1[port],
176 EP93XX_GPIO_REG(int_type1_register_offset[port]));
177
178 __raw_writeb(gpio_int_unmasked[port] & gpio_int_enabled[port],
179 EP93XX_GPIO_REG(int_en_register_offset[port]));
180}
182 181
183static unsigned char data_register_offset[8] = { 182/* Port ordering is: A B F D E C G H */
184 0x00, 0x04, 0x08, 0x0c, 0x20, 0x30, 0x38, 0x40, 183static const u8 data_register_offset[8] = {
184 0x00, 0x04, 0x30, 0x0c, 0x20, 0x08, 0x38, 0x40,
185}; 185};
186 186
187static unsigned char data_direction_register_offset[8] = { 187static const u8 data_direction_register_offset[8] = {
188 0x10, 0x14, 0x18, 0x1c, 0x24, 0x34, 0x3c, 0x44, 188 0x10, 0x14, 0x34, 0x1c, 0x24, 0x18, 0x3c, 0x44,
189}; 189};
190 190
191static void ep93xx_gpio_set_direction(unsigned line, int direction) 191static void ep93xx_gpio_set_direction(unsigned line, int direction)
@@ -199,14 +199,10 @@ static void ep93xx_gpio_set_direction(unsigned line, int direction)
199 199
200 local_irq_save(flags); 200 local_irq_save(flags);
201 if (direction == GPIO_OUT) { 201 if (direction == GPIO_OUT) {
202 if (line >= 0 && line < 16) { 202 if (line >= 0 && line <= EP93XX_GPIO_LINE_MAX_IRQ) {
203 /* Port A/B. */ 203 /* Port A/B/F */
204 gpio_int_unmasked[line >> 3] &= ~(1 << (line & 7)); 204 gpio_int_unmasked[line >> 3] &= ~(1 << (line & 7));
205 update_gpio_int_params(line >> 3); 205 update_gpio_int_params(line >> 3);
206 } else if (line >= 40 && line < 48) {
207 /* Port F. */
208 gpio_int_unmasked[2] &= ~(1 << (line & 7));
209 update_gpio_int_params(2);
210 } 206 }
211 207
212 v = __raw_readb(data_direction_register); 208 v = __raw_readb(data_direction_register);
@@ -228,7 +224,7 @@ EXPORT_SYMBOL(gpio_line_config);
228 224
229int gpio_direction_input(unsigned gpio) 225int gpio_direction_input(unsigned gpio)
230{ 226{
231 if (gpio > EP93XX_GPIO_LINE_H(7)) 227 if (gpio > EP93XX_GPIO_LINE_MAX)
232 return -EINVAL; 228 return -EINVAL;
233 229
234 ep93xx_gpio_set_direction(gpio, GPIO_IN); 230 ep93xx_gpio_set_direction(gpio, GPIO_IN);
@@ -239,7 +235,7 @@ EXPORT_SYMBOL(gpio_direction_input);
239 235
240int gpio_direction_output(unsigned gpio, int value) 236int gpio_direction_output(unsigned gpio, int value)
241{ 237{
242 if (gpio > EP93XX_GPIO_LINE_H(7)) 238 if (gpio > EP93XX_GPIO_LINE_MAX)
243 return -EINVAL; 239 return -EINVAL;
244 240
245 gpio_set_value(gpio, value); 241 gpio_set_value(gpio, value);
@@ -290,47 +286,50 @@ static void ep93xx_gpio_ab_irq_handler(unsigned int irq, struct irq_desc *desc)
290 status = __raw_readb(EP93XX_GPIO_A_INT_STATUS); 286 status = __raw_readb(EP93XX_GPIO_A_INT_STATUS);
291 for (i = 0; i < 8; i++) { 287 for (i = 0; i < 8; i++) {
292 if (status & (1 << i)) { 288 if (status & (1 << i)) {
293 desc = irq_desc + IRQ_EP93XX_GPIO(0) + i; 289 int gpio_irq = gpio_to_irq(EP93XX_GPIO_LINE_A(0)) + i;
294 desc_handle_irq(IRQ_EP93XX_GPIO(0) + i, desc); 290 desc = irq_desc + gpio_irq;
291 desc_handle_irq(gpio_irq, desc);
295 } 292 }
296 } 293 }
297 294
298 status = __raw_readb(EP93XX_GPIO_B_INT_STATUS); 295 status = __raw_readb(EP93XX_GPIO_B_INT_STATUS);
299 for (i = 0; i < 8; i++) { 296 for (i = 0; i < 8; i++) {
300 if (status & (1 << i)) { 297 if (status & (1 << i)) {
301 desc = irq_desc + IRQ_EP93XX_GPIO(8) + i; 298 int gpio_irq = gpio_to_irq(EP93XX_GPIO_LINE_B(0)) + i;
302 desc_handle_irq(IRQ_EP93XX_GPIO(8) + i, desc); 299 desc = irq_desc + gpio_irq;
300 desc_handle_irq(gpio_irq, desc);
303 } 301 }
304 } 302 }
305} 303}
306 304
307static void ep93xx_gpio_f_irq_handler(unsigned int irq, struct irq_desc *desc) 305static void ep93xx_gpio_f_irq_handler(unsigned int irq, struct irq_desc *desc)
308{ 306{
309 int gpio_irq = IRQ_EP93XX_GPIO(16) + (((irq + 1) & 7) ^ 4); 307 /*
308 * map discontiguous hw irq range to continous sw irq range:
309 *
310 * IRQ_EP93XX_GPIO{0..7}MUX -> gpio_to_irq(EP93XX_GPIO_LINE_F({0..7})
311 */
312 int port_f_idx = ((irq + 1) & 7) ^ 4; /* {19..22,47..50} -> {0..7} */
313 int gpio_irq = gpio_to_irq(EP93XX_GPIO_LINE_F(0)) + port_f_idx;
310 314
311 desc_handle_irq(gpio_irq, irq_desc + gpio_irq); 315 desc_handle_irq(gpio_irq, irq_desc + gpio_irq);
312} 316}
313 317
314static void ep93xx_gpio_irq_mask_ack(unsigned int irq) 318static void ep93xx_gpio_irq_mask_ack(unsigned int irq)
315{ 319{
316 int line = irq - IRQ_EP93XX_GPIO(0); 320 int line = irq_to_gpio(irq);
317 int port = line >> 3; 321 int port = line >> 3;
322 int port_mask = 1 << (line & 7);
318 323
319 gpio_int_unmasked[port] &= ~(1 << (line & 7)); 324 gpio_int_unmasked[port] &= ~port_mask;
320 update_gpio_int_params(port); 325 update_gpio_int_params(port);
321 326
322 if (port == 0) { 327 __raw_writeb(port_mask, EP93XX_GPIO_REG(eoi_register_offset[port]));
323 __raw_writel(1 << (line & 7), EP93XX_GPIO_A_INT_ACK);
324 } else if (port == 1) {
325 __raw_writel(1 << (line & 7), EP93XX_GPIO_B_INT_ACK);
326 } else if (port == 2) {
327 __raw_writel(1 << (line & 7), EP93XX_GPIO_F_INT_ACK);
328 }
329} 328}
330 329
331static void ep93xx_gpio_irq_mask(unsigned int irq) 330static void ep93xx_gpio_irq_mask(unsigned int irq)
332{ 331{
333 int line = irq - IRQ_EP93XX_GPIO(0); 332 int line = irq_to_gpio(irq);
334 int port = line >> 3; 333 int port = line >> 3;
335 334
336 gpio_int_unmasked[port] &= ~(1 << (line & 7)); 335 gpio_int_unmasked[port] &= ~(1 << (line & 7));
@@ -339,7 +338,7 @@ static void ep93xx_gpio_irq_mask(unsigned int irq)
339 338
340static void ep93xx_gpio_irq_unmask(unsigned int irq) 339static void ep93xx_gpio_irq_unmask(unsigned int irq)
341{ 340{
342 int line = irq - IRQ_EP93XX_GPIO(0); 341 int line = irq_to_gpio(irq);
343 int port = line >> 3; 342 int port = line >> 3;
344 343
345 gpio_int_unmasked[port] |= 1 << (line & 7); 344 gpio_int_unmasked[port] |= 1 << (line & 7);
@@ -354,37 +353,30 @@ static void ep93xx_gpio_irq_unmask(unsigned int irq)
354 */ 353 */
355static int ep93xx_gpio_irq_type(unsigned int irq, unsigned int type) 354static int ep93xx_gpio_irq_type(unsigned int irq, unsigned int type)
356{ 355{
357 int port; 356 const int gpio = irq_to_gpio(irq);
358 int line; 357 const int port = gpio >> 3;
358 const int port_mask = 1 << (gpio & 7);
359 359
360 line = irq - IRQ_EP93XX_GPIO(0); 360 ep93xx_gpio_set_direction(gpio, GPIO_IN);
361 if (line >= 0 && line < 16) {
362 ep93xx_gpio_set_direction(line, GPIO_IN);
363 } else {
364 ep93xx_gpio_set_direction(EP93XX_GPIO_LINE_F(line-16), GPIO_IN);
365 }
366
367 port = line >> 3;
368 line &= 7;
369 361
370 if (type & IRQT_RISING) { 362 if (type & IRQT_RISING) {
371 gpio_int_enabled[port] |= 1 << line; 363 gpio_int_enabled[port] |= port_mask;
372 gpio_int_type1[port] |= 1 << line; 364 gpio_int_type1[port] |= port_mask;
373 gpio_int_type2[port] |= 1 << line; 365 gpio_int_type2[port] |= port_mask;
374 } else if (type & IRQT_FALLING) { 366 } else if (type & IRQT_FALLING) {
375 gpio_int_enabled[port] |= 1 << line; 367 gpio_int_enabled[port] |= port_mask;
376 gpio_int_type1[port] |= 1 << line; 368 gpio_int_type1[port] |= port_mask;
377 gpio_int_type2[port] &= ~(1 << line); 369 gpio_int_type2[port] &= ~port_mask;
378 } else if (type & IRQT_HIGH) { 370 } else if (type & IRQT_HIGH) {
379 gpio_int_enabled[port] |= 1 << line; 371 gpio_int_enabled[port] |= port_mask;
380 gpio_int_type1[port] &= ~(1 << line); 372 gpio_int_type1[port] &= ~port_mask;
381 gpio_int_type2[port] |= 1 << line; 373 gpio_int_type2[port] |= port_mask;
382 } else if (type & IRQT_LOW) { 374 } else if (type & IRQT_LOW) {
383 gpio_int_enabled[port] |= 1 << line; 375 gpio_int_enabled[port] |= port_mask;
384 gpio_int_type1[port] &= ~(1 << line); 376 gpio_int_type1[port] &= ~port_mask;
385 gpio_int_type2[port] &= ~(1 << line); 377 gpio_int_type2[port] &= ~port_mask;
386 } else { 378 } else {
387 gpio_int_enabled[port] &= ~(1 << line); 379 gpio_int_enabled[port] &= ~port_mask;
388 } 380 }
389 update_gpio_int_params(port); 381 update_gpio_int_params(port);
390 382
@@ -402,15 +394,16 @@ static struct irq_chip ep93xx_gpio_irq_chip = {
402 394
403void __init ep93xx_init_irq(void) 395void __init ep93xx_init_irq(void)
404{ 396{
405 int irq; 397 int gpio_irq;
406 398
407 vic_init((void *)EP93XX_VIC1_BASE, 0, EP93XX_VIC1_VALID_IRQ_MASK); 399 vic_init((void *)EP93XX_VIC1_BASE, 0, EP93XX_VIC1_VALID_IRQ_MASK);
408 vic_init((void *)EP93XX_VIC2_BASE, 32, EP93XX_VIC2_VALID_IRQ_MASK); 400 vic_init((void *)EP93XX_VIC2_BASE, 32, EP93XX_VIC2_VALID_IRQ_MASK);
409 401
410 for (irq = IRQ_EP93XX_GPIO(0); irq <= IRQ_EP93XX_GPIO(23); irq++) { 402 for (gpio_irq = gpio_to_irq(0);
411 set_irq_chip(irq, &ep93xx_gpio_irq_chip); 403 gpio_irq <= gpio_to_irq(EP93XX_GPIO_LINE_MAX_IRQ); ++gpio_irq) {
412 set_irq_handler(irq, handle_level_irq); 404 set_irq_chip(gpio_irq, &ep93xx_gpio_irq_chip);
413 set_irq_flags(irq, IRQF_VALID); 405 set_irq_handler(gpio_irq, handle_level_irq);
406 set_irq_flags(gpio_irq, IRQF_VALID);
414 } 407 }
415 408
416 set_irq_chained_handler(IRQ_EP93XX_GPIO_AB, ep93xx_gpio_ab_irq_handler); 409 set_irq_chained_handler(IRQ_EP93XX_GPIO_AB, ep93xx_gpio_ab_irq_handler);