diff options
Diffstat (limited to 'arch/blackfin/kernel/bfin_gpio.c')
-rw-r--r-- | arch/blackfin/kernel/bfin_gpio.c | 321 |
1 files changed, 191 insertions, 130 deletions
diff --git a/arch/blackfin/kernel/bfin_gpio.c b/arch/blackfin/kernel/bfin_gpio.c index dc07ed08b37f..bcf8cf6fe412 100644 --- a/arch/blackfin/kernel/bfin_gpio.c +++ b/arch/blackfin/kernel/bfin_gpio.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * GPIO Abstraction Layer | 2 | * GPIO Abstraction Layer |
3 | * | 3 | * |
4 | * Copyright 2006-2009 Analog Devices Inc. | 4 | * Copyright 2006-2010 Analog Devices Inc. |
5 | * | 5 | * |
6 | * Licensed under the GPL-2 or later | 6 | * Licensed under the GPL-2 or later |
7 | */ | 7 | */ |
@@ -10,10 +10,12 @@ | |||
10 | #include <linux/module.h> | 10 | #include <linux/module.h> |
11 | #include <linux/err.h> | 11 | #include <linux/err.h> |
12 | #include <linux/proc_fs.h> | 12 | #include <linux/proc_fs.h> |
13 | #include <linux/seq_file.h> | ||
13 | #include <asm/blackfin.h> | 14 | #include <asm/blackfin.h> |
14 | #include <asm/gpio.h> | 15 | #include <asm/gpio.h> |
15 | #include <asm/portmux.h> | 16 | #include <asm/portmux.h> |
16 | #include <linux/irq.h> | 17 | #include <linux/irq.h> |
18 | #include <asm/irq_handler.h> | ||
17 | 19 | ||
18 | #if ANOMALY_05000311 || ANOMALY_05000323 | 20 | #if ANOMALY_05000311 || ANOMALY_05000323 |
19 | enum { | 21 | enum { |
@@ -215,82 +217,91 @@ static void port_setup(unsigned gpio, unsigned short usage) | |||
215 | } | 217 | } |
216 | 218 | ||
217 | #ifdef BF537_FAMILY | 219 | #ifdef BF537_FAMILY |
218 | static struct { | 220 | static const s8 port_mux[] = { |
219 | unsigned short res; | 221 | [GPIO_PF0] = 3, |
220 | unsigned short offset; | 222 | [GPIO_PF1] = 3, |
221 | } port_mux_lut[] = { | 223 | [GPIO_PF2] = 4, |
222 | {.res = P_PPI0_D13, .offset = 11}, | 224 | [GPIO_PF3] = 4, |
223 | {.res = P_PPI0_D14, .offset = 11}, | 225 | [GPIO_PF4] = 5, |
224 | {.res = P_PPI0_D15, .offset = 11}, | 226 | [GPIO_PF5] = 6, |
225 | {.res = P_SPORT1_TFS, .offset = 11}, | 227 | [GPIO_PF6] = 7, |
226 | {.res = P_SPORT1_TSCLK, .offset = 11}, | 228 | [GPIO_PF7] = 8, |
227 | {.res = P_SPORT1_DTPRI, .offset = 11}, | 229 | [GPIO_PF8 ... GPIO_PF15] = -1, |
228 | {.res = P_PPI0_D10, .offset = 10}, | 230 | [GPIO_PG0 ... GPIO_PG7] = -1, |
229 | {.res = P_PPI0_D11, .offset = 10}, | 231 | [GPIO_PG8] = 9, |
230 | {.res = P_PPI0_D12, .offset = 10}, | 232 | [GPIO_PG9] = 9, |
231 | {.res = P_SPORT1_RSCLK, .offset = 10}, | 233 | [GPIO_PG10] = 10, |
232 | {.res = P_SPORT1_RFS, .offset = 10}, | 234 | [GPIO_PG11] = 10, |
233 | {.res = P_SPORT1_DRPRI, .offset = 10}, | 235 | [GPIO_PG12] = 10, |
234 | {.res = P_PPI0_D8, .offset = 9}, | 236 | [GPIO_PG13] = 11, |
235 | {.res = P_PPI0_D9, .offset = 9}, | 237 | [GPIO_PG14] = 11, |
236 | {.res = P_SPORT1_DRSEC, .offset = 9}, | 238 | [GPIO_PG15] = 11, |
237 | {.res = P_SPORT1_DTSEC, .offset = 9}, | 239 | [GPIO_PH0 ... GPIO_PH15] = -1, |
238 | {.res = P_TMR2, .offset = 8}, | 240 | [PORT_PJ0 ... PORT_PJ3] = -1, |
239 | {.res = P_PPI0_FS3, .offset = 8}, | 241 | [PORT_PJ4] = 1, |
240 | {.res = P_TMR3, .offset = 7}, | 242 | [PORT_PJ5] = 1, |
241 | {.res = P_SPI0_SSEL4, .offset = 7}, | 243 | [PORT_PJ6 ... PORT_PJ9] = -1, |
242 | {.res = P_TMR4, .offset = 6}, | 244 | [PORT_PJ10] = 0, |
243 | {.res = P_SPI0_SSEL5, .offset = 6}, | 245 | [PORT_PJ11] = 0, |
244 | {.res = P_TMR5, .offset = 5}, | ||
245 | {.res = P_SPI0_SSEL6, .offset = 5}, | ||
246 | {.res = P_UART1_RX, .offset = 4}, | ||
247 | {.res = P_UART1_TX, .offset = 4}, | ||
248 | {.res = P_TMR6, .offset = 4}, | ||
249 | {.res = P_TMR7, .offset = 4}, | ||
250 | {.res = P_UART0_RX, .offset = 3}, | ||
251 | {.res = P_UART0_TX, .offset = 3}, | ||
252 | {.res = P_DMAR0, .offset = 3}, | ||
253 | {.res = P_DMAR1, .offset = 3}, | ||
254 | {.res = P_SPORT0_DTSEC, .offset = 1}, | ||
255 | {.res = P_SPORT0_DRSEC, .offset = 1}, | ||
256 | {.res = P_CAN0_RX, .offset = 1}, | ||
257 | {.res = P_CAN0_TX, .offset = 1}, | ||
258 | {.res = P_SPI0_SSEL7, .offset = 1}, | ||
259 | {.res = P_SPORT0_TFS, .offset = 0}, | ||
260 | {.res = P_SPORT0_DTPRI, .offset = 0}, | ||
261 | {.res = P_SPI0_SSEL2, .offset = 0}, | ||
262 | {.res = P_SPI0_SSEL3, .offset = 0}, | ||
263 | }; | 246 | }; |
264 | 247 | ||
265 | static void portmux_setup(unsigned short per) | 248 | static int portmux_group_check(unsigned short per) |
266 | { | 249 | { |
267 | u16 y, offset, muxreg; | 250 | u16 ident = P_IDENT(per); |
268 | u16 function = P_FUNCT2MUX(per); | 251 | u16 function = P_FUNCT2MUX(per); |
252 | s8 offset = port_mux[ident]; | ||
253 | u16 m, pmux, pfunc; | ||
269 | 254 | ||
270 | for (y = 0; y < ARRAY_SIZE(port_mux_lut); y++) { | 255 | if (offset < 0) |
271 | if (port_mux_lut[y].res == per) { | 256 | return 0; |
272 | |||
273 | /* SET PORTMUX REG */ | ||
274 | |||
275 | offset = port_mux_lut[y].offset; | ||
276 | muxreg = bfin_read_PORT_MUX(); | ||
277 | 257 | ||
278 | if (offset != 1) | 258 | pmux = bfin_read_PORT_MUX(); |
279 | muxreg &= ~(1 << offset); | 259 | for (m = 0; m < ARRAY_SIZE(port_mux); ++m) { |
280 | else | 260 | if (m == ident) |
281 | muxreg &= ~(3 << 1); | 261 | continue; |
262 | if (port_mux[m] != offset) | ||
263 | continue; | ||
264 | if (!is_reserved(peri, m, 1)) | ||
265 | continue; | ||
282 | 266 | ||
283 | muxreg |= (function << offset); | 267 | if (offset == 1) |
284 | bfin_write_PORT_MUX(muxreg); | 268 | pfunc = (pmux >> offset) & 3; |
269 | else | ||
270 | pfunc = (pmux >> offset) & 1; | ||
271 | if (pfunc != function) { | ||
272 | pr_err("pin group conflict! request pin %d func %d conflict with pin %d func %d\n", | ||
273 | ident, function, m, pfunc); | ||
274 | return -EINVAL; | ||
285 | } | 275 | } |
286 | } | 276 | } |
277 | |||
278 | return 0; | ||
279 | } | ||
280 | |||
281 | static void portmux_setup(unsigned short per) | ||
282 | { | ||
283 | u16 ident = P_IDENT(per); | ||
284 | u16 function = P_FUNCT2MUX(per); | ||
285 | s8 offset = port_mux[ident]; | ||
286 | u16 pmux; | ||
287 | |||
288 | if (offset == -1) | ||
289 | return; | ||
290 | |||
291 | pmux = bfin_read_PORT_MUX(); | ||
292 | if (offset != 1) | ||
293 | pmux &= ~(1 << offset); | ||
294 | else | ||
295 | pmux &= ~(3 << 1); | ||
296 | pmux |= (function << offset); | ||
297 | bfin_write_PORT_MUX(pmux); | ||
287 | } | 298 | } |
288 | #elif defined(CONFIG_BF54x) | 299 | #elif defined(CONFIG_BF54x) |
289 | inline void portmux_setup(unsigned short per) | 300 | inline void portmux_setup(unsigned short per) |
290 | { | 301 | { |
291 | u32 pmux; | ||
292 | u16 ident = P_IDENT(per); | 302 | u16 ident = P_IDENT(per); |
293 | u16 function = P_FUNCT2MUX(per); | 303 | u16 function = P_FUNCT2MUX(per); |
304 | u32 pmux; | ||
294 | 305 | ||
295 | pmux = gpio_array[gpio_bank(ident)]->port_mux; | 306 | pmux = gpio_array[gpio_bank(ident)]->port_mux; |
296 | 307 | ||
@@ -302,20 +313,54 @@ inline void portmux_setup(unsigned short per) | |||
302 | 313 | ||
303 | inline u16 get_portmux(unsigned short per) | 314 | inline u16 get_portmux(unsigned short per) |
304 | { | 315 | { |
305 | u32 pmux; | ||
306 | u16 ident = P_IDENT(per); | 316 | u16 ident = P_IDENT(per); |
307 | 317 | u32 pmux = gpio_array[gpio_bank(ident)]->port_mux; | |
308 | pmux = gpio_array[gpio_bank(ident)]->port_mux; | ||
309 | |||
310 | return (pmux >> (2 * gpio_sub_n(ident)) & 0x3); | 318 | return (pmux >> (2 * gpio_sub_n(ident)) & 0x3); |
311 | } | 319 | } |
320 | static int portmux_group_check(unsigned short per) | ||
321 | { | ||
322 | return 0; | ||
323 | } | ||
312 | #elif defined(CONFIG_BF52x) || defined(CONFIG_BF51x) | 324 | #elif defined(CONFIG_BF52x) || defined(CONFIG_BF51x) |
325 | static int portmux_group_check(unsigned short per) | ||
326 | { | ||
327 | u16 ident = P_IDENT(per); | ||
328 | u16 function = P_FUNCT2MUX(per); | ||
329 | u8 offset = pmux_offset[gpio_bank(ident)][gpio_sub_n(ident)]; | ||
330 | u16 pin, gpiopin, pfunc; | ||
331 | |||
332 | for (pin = 0; pin < GPIO_BANKSIZE; ++pin) { | ||
333 | if (offset != pmux_offset[gpio_bank(ident)][pin]) | ||
334 | continue; | ||
335 | |||
336 | gpiopin = gpio_bank(ident) * GPIO_BANKSIZE + pin; | ||
337 | if (gpiopin == ident) | ||
338 | continue; | ||
339 | if (!is_reserved(peri, gpiopin, 1)) | ||
340 | continue; | ||
341 | |||
342 | pfunc = *port_mux[gpio_bank(ident)]; | ||
343 | pfunc = (pfunc >> offset) & 3; | ||
344 | if (pfunc != function) { | ||
345 | pr_err("pin group conflict! request pin %d func %d conflict with pin %d func %d\n", | ||
346 | ident, function, gpiopin, pfunc); | ||
347 | return -EINVAL; | ||
348 | } | ||
349 | } | ||
350 | |||
351 | return 0; | ||
352 | } | ||
353 | |||
313 | inline void portmux_setup(unsigned short per) | 354 | inline void portmux_setup(unsigned short per) |
314 | { | 355 | { |
315 | u16 pmux, ident = P_IDENT(per), function = P_FUNCT2MUX(per); | 356 | u16 ident = P_IDENT(per); |
357 | u16 function = P_FUNCT2MUX(per); | ||
316 | u8 offset = pmux_offset[gpio_bank(ident)][gpio_sub_n(ident)]; | 358 | u8 offset = pmux_offset[gpio_bank(ident)][gpio_sub_n(ident)]; |
359 | u16 pmux; | ||
317 | 360 | ||
318 | pmux = *port_mux[gpio_bank(ident)]; | 361 | pmux = *port_mux[gpio_bank(ident)]; |
362 | if (((pmux >> offset) & 3) == function) | ||
363 | return; | ||
319 | pmux &= ~(3 << offset); | 364 | pmux &= ~(3 << offset); |
320 | pmux |= (function & 3) << offset; | 365 | pmux |= (function & 3) << offset; |
321 | *port_mux[gpio_bank(ident)] = pmux; | 366 | *port_mux[gpio_bank(ident)] = pmux; |
@@ -323,6 +368,10 @@ inline void portmux_setup(unsigned short per) | |||
323 | } | 368 | } |
324 | #else | 369 | #else |
325 | # define portmux_setup(...) do { } while (0) | 370 | # define portmux_setup(...) do { } while (0) |
371 | static int portmux_group_check(unsigned short per) | ||
372 | { | ||
373 | return 0; | ||
374 | } | ||
326 | #endif | 375 | #endif |
327 | 376 | ||
328 | #ifndef CONFIG_BF54x | 377 | #ifndef CONFIG_BF54x |
@@ -349,13 +398,13 @@ inline void portmux_setup(unsigned short per) | |||
349 | void set_gpio_ ## name(unsigned gpio, unsigned short arg) \ | 398 | void set_gpio_ ## name(unsigned gpio, unsigned short arg) \ |
350 | { \ | 399 | { \ |
351 | unsigned long flags; \ | 400 | unsigned long flags; \ |
352 | local_irq_save_hw(flags); \ | 401 | flags = hard_local_irq_save(); \ |
353 | if (arg) \ | 402 | if (arg) \ |
354 | gpio_array[gpio_bank(gpio)]->name |= gpio_bit(gpio); \ | 403 | gpio_array[gpio_bank(gpio)]->name |= gpio_bit(gpio); \ |
355 | else \ | 404 | else \ |
356 | gpio_array[gpio_bank(gpio)]->name &= ~gpio_bit(gpio); \ | 405 | gpio_array[gpio_bank(gpio)]->name &= ~gpio_bit(gpio); \ |
357 | AWA_DUMMY_READ(name); \ | 406 | AWA_DUMMY_READ(name); \ |
358 | local_irq_restore_hw(flags); \ | 407 | hard_local_irq_restore(flags); \ |
359 | } \ | 408 | } \ |
360 | EXPORT_SYMBOL(set_gpio_ ## name); | 409 | EXPORT_SYMBOL(set_gpio_ ## name); |
361 | 410 | ||
@@ -371,14 +420,14 @@ void set_gpio_ ## name(unsigned gpio, unsigned short arg) \ | |||
371 | { \ | 420 | { \ |
372 | unsigned long flags; \ | 421 | unsigned long flags; \ |
373 | if (ANOMALY_05000311 || ANOMALY_05000323) \ | 422 | if (ANOMALY_05000311 || ANOMALY_05000323) \ |
374 | local_irq_save_hw(flags); \ | 423 | flags = hard_local_irq_save(); \ |
375 | if (arg) \ | 424 | if (arg) \ |
376 | gpio_array[gpio_bank(gpio)]->name ## _set = gpio_bit(gpio); \ | 425 | gpio_array[gpio_bank(gpio)]->name ## _set = gpio_bit(gpio); \ |
377 | else \ | 426 | else \ |
378 | gpio_array[gpio_bank(gpio)]->name ## _clear = gpio_bit(gpio); \ | 427 | gpio_array[gpio_bank(gpio)]->name ## _clear = gpio_bit(gpio); \ |
379 | if (ANOMALY_05000311 || ANOMALY_05000323) { \ | 428 | if (ANOMALY_05000311 || ANOMALY_05000323) { \ |
380 | AWA_DUMMY_READ(name); \ | 429 | AWA_DUMMY_READ(name); \ |
381 | local_irq_restore_hw(flags); \ | 430 | hard_local_irq_restore(flags); \ |
382 | } \ | 431 | } \ |
383 | } \ | 432 | } \ |
384 | EXPORT_SYMBOL(set_gpio_ ## name); | 433 | EXPORT_SYMBOL(set_gpio_ ## name); |
@@ -391,11 +440,11 @@ void set_gpio_toggle(unsigned gpio) | |||
391 | { | 440 | { |
392 | unsigned long flags; | 441 | unsigned long flags; |
393 | if (ANOMALY_05000311 || ANOMALY_05000323) | 442 | if (ANOMALY_05000311 || ANOMALY_05000323) |
394 | local_irq_save_hw(flags); | 443 | flags = hard_local_irq_save(); |
395 | gpio_array[gpio_bank(gpio)]->toggle = gpio_bit(gpio); | 444 | gpio_array[gpio_bank(gpio)]->toggle = gpio_bit(gpio); |
396 | if (ANOMALY_05000311 || ANOMALY_05000323) { | 445 | if (ANOMALY_05000311 || ANOMALY_05000323) { |
397 | AWA_DUMMY_READ(toggle); | 446 | AWA_DUMMY_READ(toggle); |
398 | local_irq_restore_hw(flags); | 447 | hard_local_irq_restore(flags); |
399 | } | 448 | } |
400 | } | 449 | } |
401 | EXPORT_SYMBOL(set_gpio_toggle); | 450 | EXPORT_SYMBOL(set_gpio_toggle); |
@@ -408,11 +457,11 @@ void set_gpiop_ ## name(unsigned gpio, unsigned short arg) \ | |||
408 | { \ | 457 | { \ |
409 | unsigned long flags; \ | 458 | unsigned long flags; \ |
410 | if (ANOMALY_05000311 || ANOMALY_05000323) \ | 459 | if (ANOMALY_05000311 || ANOMALY_05000323) \ |
411 | local_irq_save_hw(flags); \ | 460 | flags = hard_local_irq_save(); \ |
412 | gpio_array[gpio_bank(gpio)]->name = arg; \ | 461 | gpio_array[gpio_bank(gpio)]->name = arg; \ |
413 | if (ANOMALY_05000311 || ANOMALY_05000323) { \ | 462 | if (ANOMALY_05000311 || ANOMALY_05000323) { \ |
414 | AWA_DUMMY_READ(name); \ | 463 | AWA_DUMMY_READ(name); \ |
415 | local_irq_restore_hw(flags); \ | 464 | hard_local_irq_restore(flags); \ |
416 | } \ | 465 | } \ |
417 | } \ | 466 | } \ |
418 | EXPORT_SYMBOL(set_gpiop_ ## name); | 467 | EXPORT_SYMBOL(set_gpiop_ ## name); |
@@ -433,11 +482,11 @@ unsigned short get_gpio_ ## name(unsigned gpio) \ | |||
433 | unsigned long flags; \ | 482 | unsigned long flags; \ |
434 | unsigned short ret; \ | 483 | unsigned short ret; \ |
435 | if (ANOMALY_05000311 || ANOMALY_05000323) \ | 484 | if (ANOMALY_05000311 || ANOMALY_05000323) \ |
436 | local_irq_save_hw(flags); \ | 485 | flags = hard_local_irq_save(); \ |
437 | ret = 0x01 & (gpio_array[gpio_bank(gpio)]->name >> gpio_sub_n(gpio)); \ | 486 | ret = 0x01 & (gpio_array[gpio_bank(gpio)]->name >> gpio_sub_n(gpio)); \ |
438 | if (ANOMALY_05000311 || ANOMALY_05000323) { \ | 487 | if (ANOMALY_05000311 || ANOMALY_05000323) { \ |
439 | AWA_DUMMY_READ(name); \ | 488 | AWA_DUMMY_READ(name); \ |
440 | local_irq_restore_hw(flags); \ | 489 | hard_local_irq_restore(flags); \ |
441 | } \ | 490 | } \ |
442 | return ret; \ | 491 | return ret; \ |
443 | } \ | 492 | } \ |
@@ -460,11 +509,11 @@ unsigned short get_gpiop_ ## name(unsigned gpio) \ | |||
460 | unsigned long flags; \ | 509 | unsigned long flags; \ |
461 | unsigned short ret; \ | 510 | unsigned short ret; \ |
462 | if (ANOMALY_05000311 || ANOMALY_05000323) \ | 511 | if (ANOMALY_05000311 || ANOMALY_05000323) \ |
463 | local_irq_save_hw(flags); \ | 512 | flags = hard_local_irq_save(); \ |
464 | ret = (gpio_array[gpio_bank(gpio)]->name); \ | 513 | ret = (gpio_array[gpio_bank(gpio)]->name); \ |
465 | if (ANOMALY_05000311 || ANOMALY_05000323) { \ | 514 | if (ANOMALY_05000311 || ANOMALY_05000323) { \ |
466 | AWA_DUMMY_READ(name); \ | 515 | AWA_DUMMY_READ(name); \ |
467 | local_irq_restore_hw(flags); \ | 516 | hard_local_irq_restore(flags); \ |
468 | } \ | 517 | } \ |
469 | return ret; \ | 518 | return ret; \ |
470 | } \ | 519 | } \ |
@@ -487,7 +536,7 @@ static const unsigned int sic_iwr_irqs[] = { | |||
487 | #if defined(BF533_FAMILY) | 536 | #if defined(BF533_FAMILY) |
488 | IRQ_PROG_INTB | 537 | IRQ_PROG_INTB |
489 | #elif defined(BF537_FAMILY) | 538 | #elif defined(BF537_FAMILY) |
490 | IRQ_PROG_INTB, IRQ_PORTG_INTB, IRQ_MAC_TX | 539 | IRQ_PF_INTB_WATCH, IRQ_PORTG_INTB, IRQ_PH_INTB_MAC_TX |
491 | #elif defined(BF538_FAMILY) | 540 | #elif defined(BF538_FAMILY) |
492 | IRQ_PORTF_INTB | 541 | IRQ_PORTF_INTB |
493 | #elif defined(CONFIG_BF52x) || defined(CONFIG_BF51x) | 542 | #elif defined(CONFIG_BF52x) || defined(CONFIG_BF51x) |
@@ -525,14 +574,14 @@ int gpio_pm_wakeup_ctrl(unsigned gpio, unsigned ctrl) | |||
525 | if (check_gpio(gpio) < 0) | 574 | if (check_gpio(gpio) < 0) |
526 | return -EINVAL; | 575 | return -EINVAL; |
527 | 576 | ||
528 | local_irq_save_hw(flags); | 577 | flags = hard_local_irq_save(); |
529 | if (ctrl) | 578 | if (ctrl) |
530 | reserve(wakeup, gpio); | 579 | reserve(wakeup, gpio); |
531 | else | 580 | else |
532 | unreserve(wakeup, gpio); | 581 | unreserve(wakeup, gpio); |
533 | 582 | ||
534 | set_gpio_maskb(gpio, ctrl); | 583 | set_gpio_maskb(gpio, ctrl); |
535 | local_irq_restore_hw(flags); | 584 | hard_local_irq_restore(flags); |
536 | 585 | ||
537 | return 0; | 586 | return 0; |
538 | } | 587 | } |
@@ -690,7 +739,7 @@ int peripheral_request(unsigned short per, const char *label) | |||
690 | 739 | ||
691 | BUG_ON(ident >= MAX_RESOURCES); | 740 | BUG_ON(ident >= MAX_RESOURCES); |
692 | 741 | ||
693 | local_irq_save_hw(flags); | 742 | flags = hard_local_irq_save(); |
694 | 743 | ||
695 | /* If a pin can be muxed as either GPIO or peripheral, make | 744 | /* If a pin can be muxed as either GPIO or peripheral, make |
696 | * sure it is not already a GPIO pin when we request it. | 745 | * sure it is not already a GPIO pin when we request it. |
@@ -701,7 +750,7 @@ int peripheral_request(unsigned short per, const char *label) | |||
701 | printk(KERN_ERR | 750 | printk(KERN_ERR |
702 | "%s: Peripheral %d is already reserved as GPIO by %s !\n", | 751 | "%s: Peripheral %d is already reserved as GPIO by %s !\n", |
703 | __func__, ident, get_label(ident)); | 752 | __func__, ident, get_label(ident)); |
704 | local_irq_restore_hw(flags); | 753 | hard_local_irq_restore(flags); |
705 | return -EBUSY; | 754 | return -EBUSY; |
706 | } | 755 | } |
707 | 756 | ||
@@ -730,18 +779,22 @@ int peripheral_request(unsigned short per, const char *label) | |||
730 | printk(KERN_ERR | 779 | printk(KERN_ERR |
731 | "%s: Peripheral %d function %d is already reserved by %s !\n", | 780 | "%s: Peripheral %d function %d is already reserved by %s !\n", |
732 | __func__, ident, P_FUNCT2MUX(per), get_label(ident)); | 781 | __func__, ident, P_FUNCT2MUX(per), get_label(ident)); |
733 | local_irq_restore_hw(flags); | 782 | hard_local_irq_restore(flags); |
734 | return -EBUSY; | 783 | return -EBUSY; |
735 | } | 784 | } |
736 | } | 785 | } |
737 | 786 | ||
787 | if (unlikely(portmux_group_check(per))) { | ||
788 | hard_local_irq_restore(flags); | ||
789 | return -EBUSY; | ||
790 | } | ||
738 | anyway: | 791 | anyway: |
739 | reserve(peri, ident); | 792 | reserve(peri, ident); |
740 | 793 | ||
741 | portmux_setup(per); | 794 | portmux_setup(per); |
742 | port_setup(ident, PERIPHERAL_USAGE); | 795 | port_setup(ident, PERIPHERAL_USAGE); |
743 | 796 | ||
744 | local_irq_restore_hw(flags); | 797 | hard_local_irq_restore(flags); |
745 | set_label(ident, label); | 798 | set_label(ident, label); |
746 | 799 | ||
747 | return 0; | 800 | return 0; |
@@ -780,10 +833,10 @@ void peripheral_free(unsigned short per) | |||
780 | if (!(per & P_DEFINED)) | 833 | if (!(per & P_DEFINED)) |
781 | return; | 834 | return; |
782 | 835 | ||
783 | local_irq_save_hw(flags); | 836 | flags = hard_local_irq_save(); |
784 | 837 | ||
785 | if (unlikely(!is_reserved(peri, ident, 0))) { | 838 | if (unlikely(!is_reserved(peri, ident, 0))) { |
786 | local_irq_restore_hw(flags); | 839 | hard_local_irq_restore(flags); |
787 | return; | 840 | return; |
788 | } | 841 | } |
789 | 842 | ||
@@ -794,7 +847,7 @@ void peripheral_free(unsigned short per) | |||
794 | 847 | ||
795 | set_label(ident, "free"); | 848 | set_label(ident, "free"); |
796 | 849 | ||
797 | local_irq_restore_hw(flags); | 850 | hard_local_irq_restore(flags); |
798 | } | 851 | } |
799 | EXPORT_SYMBOL(peripheral_free); | 852 | EXPORT_SYMBOL(peripheral_free); |
800 | 853 | ||
@@ -828,7 +881,7 @@ int bfin_gpio_request(unsigned gpio, const char *label) | |||
828 | if (check_gpio(gpio) < 0) | 881 | if (check_gpio(gpio) < 0) |
829 | return -EINVAL; | 882 | return -EINVAL; |
830 | 883 | ||
831 | local_irq_save_hw(flags); | 884 | flags = hard_local_irq_save(); |
832 | 885 | ||
833 | /* | 886 | /* |
834 | * Allow that the identical GPIO can | 887 | * Allow that the identical GPIO can |
@@ -837,7 +890,7 @@ int bfin_gpio_request(unsigned gpio, const char *label) | |||
837 | */ | 890 | */ |
838 | 891 | ||
839 | if (cmp_label(gpio, label) == 0) { | 892 | if (cmp_label(gpio, label) == 0) { |
840 | local_irq_restore_hw(flags); | 893 | hard_local_irq_restore(flags); |
841 | return 0; | 894 | return 0; |
842 | } | 895 | } |
843 | 896 | ||
@@ -846,7 +899,7 @@ int bfin_gpio_request(unsigned gpio, const char *label) | |||
846 | dump_stack(); | 899 | dump_stack(); |
847 | printk(KERN_ERR "bfin-gpio: GPIO %d is already reserved by %s !\n", | 900 | printk(KERN_ERR "bfin-gpio: GPIO %d is already reserved by %s !\n", |
848 | gpio, get_label(gpio)); | 901 | gpio, get_label(gpio)); |
849 | local_irq_restore_hw(flags); | 902 | hard_local_irq_restore(flags); |
850 | return -EBUSY; | 903 | return -EBUSY; |
851 | } | 904 | } |
852 | if (unlikely(is_reserved(peri, gpio, 1))) { | 905 | if (unlikely(is_reserved(peri, gpio, 1))) { |
@@ -855,7 +908,7 @@ int bfin_gpio_request(unsigned gpio, const char *label) | |||
855 | printk(KERN_ERR | 908 | printk(KERN_ERR |
856 | "bfin-gpio: GPIO %d is already reserved as Peripheral by %s !\n", | 909 | "bfin-gpio: GPIO %d is already reserved as Peripheral by %s !\n", |
857 | gpio, get_label(gpio)); | 910 | gpio, get_label(gpio)); |
858 | local_irq_restore_hw(flags); | 911 | hard_local_irq_restore(flags); |
859 | return -EBUSY; | 912 | return -EBUSY; |
860 | } | 913 | } |
861 | if (unlikely(is_reserved(gpio_irq, gpio, 1))) { | 914 | if (unlikely(is_reserved(gpio_irq, gpio, 1))) { |
@@ -871,7 +924,7 @@ int bfin_gpio_request(unsigned gpio, const char *label) | |||
871 | reserve(gpio, gpio); | 924 | reserve(gpio, gpio); |
872 | set_label(gpio, label); | 925 | set_label(gpio, label); |
873 | 926 | ||
874 | local_irq_restore_hw(flags); | 927 | hard_local_irq_restore(flags); |
875 | 928 | ||
876 | port_setup(gpio, GPIO_USAGE); | 929 | port_setup(gpio, GPIO_USAGE); |
877 | 930 | ||
@@ -888,13 +941,13 @@ void bfin_gpio_free(unsigned gpio) | |||
888 | 941 | ||
889 | might_sleep(); | 942 | might_sleep(); |
890 | 943 | ||
891 | local_irq_save_hw(flags); | 944 | flags = hard_local_irq_save(); |
892 | 945 | ||
893 | if (unlikely(!is_reserved(gpio, gpio, 0))) { | 946 | if (unlikely(!is_reserved(gpio, gpio, 0))) { |
894 | if (system_state == SYSTEM_BOOTING) | 947 | if (system_state == SYSTEM_BOOTING) |
895 | dump_stack(); | 948 | dump_stack(); |
896 | gpio_error(gpio); | 949 | gpio_error(gpio); |
897 | local_irq_restore_hw(flags); | 950 | hard_local_irq_restore(flags); |
898 | return; | 951 | return; |
899 | } | 952 | } |
900 | 953 | ||
@@ -902,7 +955,7 @@ void bfin_gpio_free(unsigned gpio) | |||
902 | 955 | ||
903 | set_label(gpio, "free"); | 956 | set_label(gpio, "free"); |
904 | 957 | ||
905 | local_irq_restore_hw(flags); | 958 | hard_local_irq_restore(flags); |
906 | } | 959 | } |
907 | EXPORT_SYMBOL(bfin_gpio_free); | 960 | EXPORT_SYMBOL(bfin_gpio_free); |
908 | 961 | ||
@@ -913,7 +966,7 @@ int bfin_special_gpio_request(unsigned gpio, const char *label) | |||
913 | { | 966 | { |
914 | unsigned long flags; | 967 | unsigned long flags; |
915 | 968 | ||
916 | local_irq_save_hw(flags); | 969 | flags = hard_local_irq_save(); |
917 | 970 | ||
918 | /* | 971 | /* |
919 | * Allow that the identical GPIO can | 972 | * Allow that the identical GPIO can |
@@ -922,19 +975,19 @@ int bfin_special_gpio_request(unsigned gpio, const char *label) | |||
922 | */ | 975 | */ |
923 | 976 | ||
924 | if (cmp_label(gpio, label) == 0) { | 977 | if (cmp_label(gpio, label) == 0) { |
925 | local_irq_restore_hw(flags); | 978 | hard_local_irq_restore(flags); |
926 | return 0; | 979 | return 0; |
927 | } | 980 | } |
928 | 981 | ||
929 | if (unlikely(is_reserved(special_gpio, gpio, 1))) { | 982 | if (unlikely(is_reserved(special_gpio, gpio, 1))) { |
930 | local_irq_restore_hw(flags); | 983 | hard_local_irq_restore(flags); |
931 | printk(KERN_ERR "bfin-gpio: GPIO %d is already reserved by %s !\n", | 984 | printk(KERN_ERR "bfin-gpio: GPIO %d is already reserved by %s !\n", |
932 | gpio, get_label(gpio)); | 985 | gpio, get_label(gpio)); |
933 | 986 | ||
934 | return -EBUSY; | 987 | return -EBUSY; |
935 | } | 988 | } |
936 | if (unlikely(is_reserved(peri, gpio, 1))) { | 989 | if (unlikely(is_reserved(peri, gpio, 1))) { |
937 | local_irq_restore_hw(flags); | 990 | hard_local_irq_restore(flags); |
938 | printk(KERN_ERR | 991 | printk(KERN_ERR |
939 | "bfin-gpio: GPIO %d is already reserved as Peripheral by %s !\n", | 992 | "bfin-gpio: GPIO %d is already reserved as Peripheral by %s !\n", |
940 | gpio, get_label(gpio)); | 993 | gpio, get_label(gpio)); |
@@ -946,7 +999,7 @@ int bfin_special_gpio_request(unsigned gpio, const char *label) | |||
946 | reserve(peri, gpio); | 999 | reserve(peri, gpio); |
947 | 1000 | ||
948 | set_label(gpio, label); | 1001 | set_label(gpio, label); |
949 | local_irq_restore_hw(flags); | 1002 | hard_local_irq_restore(flags); |
950 | port_setup(gpio, GPIO_USAGE); | 1003 | port_setup(gpio, GPIO_USAGE); |
951 | 1004 | ||
952 | return 0; | 1005 | return 0; |
@@ -959,18 +1012,18 @@ void bfin_special_gpio_free(unsigned gpio) | |||
959 | 1012 | ||
960 | might_sleep(); | 1013 | might_sleep(); |
961 | 1014 | ||
962 | local_irq_save_hw(flags); | 1015 | flags = hard_local_irq_save(); |
963 | 1016 | ||
964 | if (unlikely(!is_reserved(special_gpio, gpio, 0))) { | 1017 | if (unlikely(!is_reserved(special_gpio, gpio, 0))) { |
965 | gpio_error(gpio); | 1018 | gpio_error(gpio); |
966 | local_irq_restore_hw(flags); | 1019 | hard_local_irq_restore(flags); |
967 | return; | 1020 | return; |
968 | } | 1021 | } |
969 | 1022 | ||
970 | unreserve(special_gpio, gpio); | 1023 | unreserve(special_gpio, gpio); |
971 | unreserve(peri, gpio); | 1024 | unreserve(peri, gpio); |
972 | set_label(gpio, "free"); | 1025 | set_label(gpio, "free"); |
973 | local_irq_restore_hw(flags); | 1026 | hard_local_irq_restore(flags); |
974 | } | 1027 | } |
975 | EXPORT_SYMBOL(bfin_special_gpio_free); | 1028 | EXPORT_SYMBOL(bfin_special_gpio_free); |
976 | #endif | 1029 | #endif |
@@ -983,7 +1036,7 @@ int bfin_gpio_irq_request(unsigned gpio, const char *label) | |||
983 | if (check_gpio(gpio) < 0) | 1036 | if (check_gpio(gpio) < 0) |
984 | return -EINVAL; | 1037 | return -EINVAL; |
985 | 1038 | ||
986 | local_irq_save_hw(flags); | 1039 | flags = hard_local_irq_save(); |
987 | 1040 | ||
988 | if (unlikely(is_reserved(peri, gpio, 1))) { | 1041 | if (unlikely(is_reserved(peri, gpio, 1))) { |
989 | if (system_state == SYSTEM_BOOTING) | 1042 | if (system_state == SYSTEM_BOOTING) |
@@ -991,7 +1044,7 @@ int bfin_gpio_irq_request(unsigned gpio, const char *label) | |||
991 | printk(KERN_ERR | 1044 | printk(KERN_ERR |
992 | "bfin-gpio: GPIO %d is already reserved as Peripheral by %s !\n", | 1045 | "bfin-gpio: GPIO %d is already reserved as Peripheral by %s !\n", |
993 | gpio, get_label(gpio)); | 1046 | gpio, get_label(gpio)); |
994 | local_irq_restore_hw(flags); | 1047 | hard_local_irq_restore(flags); |
995 | return -EBUSY; | 1048 | return -EBUSY; |
996 | } | 1049 | } |
997 | if (unlikely(is_reserved(gpio, gpio, 1))) | 1050 | if (unlikely(is_reserved(gpio, gpio, 1))) |
@@ -1002,7 +1055,7 @@ int bfin_gpio_irq_request(unsigned gpio, const char *label) | |||
1002 | reserve(gpio_irq, gpio); | 1055 | reserve(gpio_irq, gpio); |
1003 | set_label(gpio, label); | 1056 | set_label(gpio, label); |
1004 | 1057 | ||
1005 | local_irq_restore_hw(flags); | 1058 | hard_local_irq_restore(flags); |
1006 | 1059 | ||
1007 | port_setup(gpio, GPIO_USAGE); | 1060 | port_setup(gpio, GPIO_USAGE); |
1008 | 1061 | ||
@@ -1016,13 +1069,13 @@ void bfin_gpio_irq_free(unsigned gpio) | |||
1016 | if (check_gpio(gpio) < 0) | 1069 | if (check_gpio(gpio) < 0) |
1017 | return; | 1070 | return; |
1018 | 1071 | ||
1019 | local_irq_save_hw(flags); | 1072 | flags = hard_local_irq_save(); |
1020 | 1073 | ||
1021 | if (unlikely(!is_reserved(gpio_irq, gpio, 0))) { | 1074 | if (unlikely(!is_reserved(gpio_irq, gpio, 0))) { |
1022 | if (system_state == SYSTEM_BOOTING) | 1075 | if (system_state == SYSTEM_BOOTING) |
1023 | dump_stack(); | 1076 | dump_stack(); |
1024 | gpio_error(gpio); | 1077 | gpio_error(gpio); |
1025 | local_irq_restore_hw(flags); | 1078 | hard_local_irq_restore(flags); |
1026 | return; | 1079 | return; |
1027 | } | 1080 | } |
1028 | 1081 | ||
@@ -1030,7 +1083,7 @@ void bfin_gpio_irq_free(unsigned gpio) | |||
1030 | 1083 | ||
1031 | set_label(gpio, "free"); | 1084 | set_label(gpio, "free"); |
1032 | 1085 | ||
1033 | local_irq_restore_hw(flags); | 1086 | hard_local_irq_restore(flags); |
1034 | } | 1087 | } |
1035 | 1088 | ||
1036 | static inline void __bfin_gpio_direction_input(unsigned gpio) | 1089 | static inline void __bfin_gpio_direction_input(unsigned gpio) |
@@ -1052,10 +1105,10 @@ int bfin_gpio_direction_input(unsigned gpio) | |||
1052 | return -EINVAL; | 1105 | return -EINVAL; |
1053 | } | 1106 | } |
1054 | 1107 | ||
1055 | local_irq_save_hw(flags); | 1108 | flags = hard_local_irq_save(); |
1056 | __bfin_gpio_direction_input(gpio); | 1109 | __bfin_gpio_direction_input(gpio); |
1057 | AWA_DUMMY_READ(inen); | 1110 | AWA_DUMMY_READ(inen); |
1058 | local_irq_restore_hw(flags); | 1111 | hard_local_irq_restore(flags); |
1059 | 1112 | ||
1060 | return 0; | 1113 | return 0; |
1061 | } | 1114 | } |
@@ -1070,9 +1123,9 @@ void bfin_gpio_irq_prepare(unsigned gpio) | |||
1070 | port_setup(gpio, GPIO_USAGE); | 1123 | port_setup(gpio, GPIO_USAGE); |
1071 | 1124 | ||
1072 | #ifdef CONFIG_BF54x | 1125 | #ifdef CONFIG_BF54x |
1073 | local_irq_save_hw(flags); | 1126 | flags = hard_local_irq_save(); |
1074 | __bfin_gpio_direction_input(gpio); | 1127 | __bfin_gpio_direction_input(gpio); |
1075 | local_irq_restore_hw(flags); | 1128 | hard_local_irq_restore(flags); |
1076 | #endif | 1129 | #endif |
1077 | } | 1130 | } |
1078 | 1131 | ||
@@ -1094,7 +1147,7 @@ int bfin_gpio_direction_output(unsigned gpio, int value) | |||
1094 | return -EINVAL; | 1147 | return -EINVAL; |
1095 | } | 1148 | } |
1096 | 1149 | ||
1097 | local_irq_save_hw(flags); | 1150 | flags = hard_local_irq_save(); |
1098 | 1151 | ||
1099 | gpio_array[gpio_bank(gpio)]->inen &= ~gpio_bit(gpio); | 1152 | gpio_array[gpio_bank(gpio)]->inen &= ~gpio_bit(gpio); |
1100 | gpio_set_value(gpio, value); | 1153 | gpio_set_value(gpio, value); |
@@ -1105,7 +1158,7 @@ int bfin_gpio_direction_output(unsigned gpio, int value) | |||
1105 | #endif | 1158 | #endif |
1106 | 1159 | ||
1107 | AWA_DUMMY_READ(dir); | 1160 | AWA_DUMMY_READ(dir); |
1108 | local_irq_restore_hw(flags); | 1161 | hard_local_irq_restore(flags); |
1109 | 1162 | ||
1110 | return 0; | 1163 | return 0; |
1111 | } | 1164 | } |
@@ -1120,11 +1173,11 @@ int bfin_gpio_get_value(unsigned gpio) | |||
1120 | 1173 | ||
1121 | if (unlikely(get_gpio_edge(gpio))) { | 1174 | if (unlikely(get_gpio_edge(gpio))) { |
1122 | int ret; | 1175 | int ret; |
1123 | local_irq_save_hw(flags); | 1176 | flags = hard_local_irq_save(); |
1124 | set_gpio_edge(gpio, 0); | 1177 | set_gpio_edge(gpio, 0); |
1125 | ret = get_gpio_data(gpio); | 1178 | ret = get_gpio_data(gpio); |
1126 | set_gpio_edge(gpio, 1); | 1179 | set_gpio_edge(gpio, 1); |
1127 | local_irq_restore_hw(flags); | 1180 | hard_local_irq_restore(flags); |
1128 | return ret; | 1181 | return ret; |
1129 | } else | 1182 | } else |
1130 | return get_gpio_data(gpio); | 1183 | return get_gpio_data(gpio); |
@@ -1152,35 +1205,43 @@ void bfin_reset_boot_spi_cs(unsigned short pin) | |||
1152 | } | 1205 | } |
1153 | 1206 | ||
1154 | #if defined(CONFIG_PROC_FS) | 1207 | #if defined(CONFIG_PROC_FS) |
1155 | static int gpio_proc_read(char *buf, char **start, off_t offset, | 1208 | static int gpio_proc_show(struct seq_file *m, void *v) |
1156 | int len, int *unused_i, void *unused_v) | ||
1157 | { | 1209 | { |
1158 | int c, irq, gpio, outlen = 0; | 1210 | int c, irq, gpio; |
1159 | 1211 | ||
1160 | for (c = 0; c < MAX_RESOURCES; c++) { | 1212 | for (c = 0; c < MAX_RESOURCES; c++) { |
1161 | irq = is_reserved(gpio_irq, c, 1); | 1213 | irq = is_reserved(gpio_irq, c, 1); |
1162 | gpio = is_reserved(gpio, c, 1); | 1214 | gpio = is_reserved(gpio, c, 1); |
1163 | if (!check_gpio(c) && (gpio || irq)) | 1215 | if (!check_gpio(c) && (gpio || irq)) |
1164 | len = sprintf(buf, "GPIO_%d: \t%s%s \t\tGPIO %s\n", c, | 1216 | seq_printf(m, "GPIO_%d: \t%s%s \t\tGPIO %s\n", c, |
1165 | get_label(c), (gpio && irq) ? " *" : "", | 1217 | get_label(c), (gpio && irq) ? " *" : "", |
1166 | get_gpio_dir(c) ? "OUTPUT" : "INPUT"); | 1218 | get_gpio_dir(c) ? "OUTPUT" : "INPUT"); |
1167 | else if (is_reserved(peri, c, 1)) | 1219 | else if (is_reserved(peri, c, 1)) |
1168 | len = sprintf(buf, "GPIO_%d: \t%s \t\tPeripheral\n", c, get_label(c)); | 1220 | seq_printf(m, "GPIO_%d: \t%s \t\tPeripheral\n", c, get_label(c)); |
1169 | else | 1221 | else |
1170 | continue; | 1222 | continue; |
1171 | buf += len; | ||
1172 | outlen += len; | ||
1173 | } | 1223 | } |
1174 | return outlen; | 1224 | |
1225 | return 0; | ||
1175 | } | 1226 | } |
1176 | 1227 | ||
1228 | static int gpio_proc_open(struct inode *inode, struct file *file) | ||
1229 | { | ||
1230 | return single_open(file, gpio_proc_show, NULL); | ||
1231 | } | ||
1232 | |||
1233 | static const struct file_operations gpio_proc_ops = { | ||
1234 | .open = gpio_proc_open, | ||
1235 | .read = seq_read, | ||
1236 | .llseek = seq_lseek, | ||
1237 | .release = single_release, | ||
1238 | }; | ||
1239 | |||
1177 | static __init int gpio_register_proc(void) | 1240 | static __init int gpio_register_proc(void) |
1178 | { | 1241 | { |
1179 | struct proc_dir_entry *proc_gpio; | 1242 | struct proc_dir_entry *proc_gpio; |
1180 | 1243 | ||
1181 | proc_gpio = create_proc_entry("gpio", S_IRUGO, NULL); | 1244 | proc_gpio = proc_create("gpio", S_IRUGO, NULL, &gpio_proc_ops); |
1182 | if (proc_gpio) | ||
1183 | proc_gpio->read_proc = gpio_proc_read; | ||
1184 | return proc_gpio != NULL; | 1245 | return proc_gpio != NULL; |
1185 | } | 1246 | } |
1186 | __initcall(gpio_register_proc); | 1247 | __initcall(gpio_register_proc); |