aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/cris/arch-v10/drivers/gpio.c80
1 files changed, 48 insertions, 32 deletions
diff --git a/arch/cris/arch-v10/drivers/gpio.c b/arch/cris/arch-v10/drivers/gpio.c
index 080927ffe63b..a07b6d25b0c7 100644
--- a/arch/cris/arch-v10/drivers/gpio.c
+++ b/arch/cris/arch-v10/drivers/gpio.c
@@ -16,7 +16,6 @@
16#include <linux/errno.h> 16#include <linux/errno.h>
17#include <linux/kernel.h> 17#include <linux/kernel.h>
18#include <linux/fs.h> 18#include <linux/fs.h>
19#include <linux/smp_lock.h>
20#include <linux/string.h> 19#include <linux/string.h>
21#include <linux/poll.h> 20#include <linux/poll.h>
22#include <linux/init.h> 21#include <linux/init.h>
@@ -46,7 +45,7 @@ static char gpio_name[] = "etrax gpio";
46static wait_queue_head_t *gpio_wq; 45static wait_queue_head_t *gpio_wq;
47#endif 46#endif
48 47
49static int gpio_ioctl(struct file *file, unsigned int cmd, unsigned long arg); 48static long gpio_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
50static ssize_t gpio_write(struct file *file, const char __user *buf, 49static ssize_t gpio_write(struct file *file, const char __user *buf,
51 size_t count, loff_t *off); 50 size_t count, loff_t *off);
52static int gpio_open(struct inode *inode, struct file *filp); 51static int gpio_open(struct inode *inode, struct file *filp);
@@ -323,7 +322,6 @@ gpio_open(struct inode *inode, struct file *filp)
323 if (!priv) 322 if (!priv)
324 return -ENOMEM; 323 return -ENOMEM;
325 324
326 lock_kernel();
327 priv->minor = p; 325 priv->minor = p;
328 326
329 /* initialize the io/alarm struct */ 327 /* initialize the io/alarm struct */
@@ -358,7 +356,6 @@ gpio_open(struct inode *inode, struct file *filp)
358 alarmlist = priv; 356 alarmlist = priv;
359 spin_unlock_irqrestore(&gpio_lock, flags); 357 spin_unlock_irqrestore(&gpio_lock, flags);
360 358
361 unlock_kernel();
362 return 0; 359 return 0;
363} 360}
364 361
@@ -503,8 +500,7 @@ unsigned long inline setget_output(struct gpio_private *priv, unsigned long arg)
503static int 500static int
504gpio_leds_ioctl(unsigned int cmd, unsigned long arg); 501gpio_leds_ioctl(unsigned int cmd, unsigned long arg);
505 502
506static int 503static long gpio_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
507gpio_ioctl_unlocked(struct file *file, unsigned int cmd, unsigned long arg)
508{ 504{
509 unsigned long flags; 505 unsigned long flags;
510 unsigned long val; 506 unsigned long val;
@@ -514,54 +510,65 @@ gpio_ioctl_unlocked(struct file *file, unsigned int cmd, unsigned long arg)
514 if (_IOC_TYPE(cmd) != ETRAXGPIO_IOCTYPE) 510 if (_IOC_TYPE(cmd) != ETRAXGPIO_IOCTYPE)
515 return -EINVAL; 511 return -EINVAL;
516 512
517 spin_lock_irqsave(&gpio_lock, flags);
518
519 switch (_IOC_NR(cmd)) { 513 switch (_IOC_NR(cmd)) {
520 case IO_READBITS: /* Use IO_READ_INBITS and IO_READ_OUTBITS instead */ 514 case IO_READBITS: /* Use IO_READ_INBITS and IO_READ_OUTBITS instead */
521 // read the port 515 // read the port
516 spin_lock_irqsave(&gpio_lock, flags);
522 if (USE_PORTS(priv)) { 517 if (USE_PORTS(priv)) {
523 ret = *priv->port; 518 ret = *priv->port;
524 } else if (priv->minor == GPIO_MINOR_G) { 519 } else if (priv->minor == GPIO_MINOR_G) {
525 ret = (*R_PORT_G_DATA) & 0x7FFFFFFF; 520 ret = (*R_PORT_G_DATA) & 0x7FFFFFFF;
526 } 521 }
522 spin_unlock_irqrestore(&gpio_lock, flags);
523
527 break; 524 break;
528 case IO_SETBITS: 525 case IO_SETBITS:
529 // set changeable bits with a 1 in arg 526 // set changeable bits with a 1 in arg
527 spin_lock_irqsave(&gpio_lock, flags);
528
530 if (USE_PORTS(priv)) { 529 if (USE_PORTS(priv)) {
531 *priv->port = *priv->shadow |= 530 *priv->port = *priv->shadow |=
532 ((unsigned char)arg & priv->changeable_bits); 531 ((unsigned char)arg & priv->changeable_bits);
533 } else if (priv->minor == GPIO_MINOR_G) { 532 } else if (priv->minor == GPIO_MINOR_G) {
534 *R_PORT_G_DATA = port_g_data_shadow |= (arg & dir_g_out_bits); 533 *R_PORT_G_DATA = port_g_data_shadow |= (arg & dir_g_out_bits);
535 } 534 }
535 spin_unlock_irqrestore(&gpio_lock, flags);
536
536 break; 537 break;
537 case IO_CLRBITS: 538 case IO_CLRBITS:
538 // clear changeable bits with a 1 in arg 539 // clear changeable bits with a 1 in arg
540 spin_lock_irqsave(&gpio_lock, flags);
539 if (USE_PORTS(priv)) { 541 if (USE_PORTS(priv)) {
540 *priv->port = *priv->shadow &= 542 *priv->port = *priv->shadow &=
541 ~((unsigned char)arg & priv->changeable_bits); 543 ~((unsigned char)arg & priv->changeable_bits);
542 } else if (priv->minor == GPIO_MINOR_G) { 544 } else if (priv->minor == GPIO_MINOR_G) {
543 *R_PORT_G_DATA = port_g_data_shadow &= ~((unsigned long)arg & dir_g_out_bits); 545 *R_PORT_G_DATA = port_g_data_shadow &= ~((unsigned long)arg & dir_g_out_bits);
544 } 546 }
547 spin_unlock_irqrestore(&gpio_lock, flags);
545 break; 548 break;
546 case IO_HIGHALARM: 549 case IO_HIGHALARM:
547 // set alarm when bits with 1 in arg go high 550 // set alarm when bits with 1 in arg go high
551 spin_lock_irqsave(&gpio_lock, flags);
548 priv->highalarm |= arg; 552 priv->highalarm |= arg;
549 gpio_some_alarms = 1; 553 gpio_some_alarms = 1;
554 spin_unlock_irqrestore(&gpio_lock, flags);
550 break; 555 break;
551 case IO_LOWALARM: 556 case IO_LOWALARM:
552 // set alarm when bits with 1 in arg go low 557 // set alarm when bits with 1 in arg go low
558 spin_lock_irqsave(&gpio_lock, flags);
553 priv->lowalarm |= arg; 559 priv->lowalarm |= arg;
554 gpio_some_alarms = 1; 560 gpio_some_alarms = 1;
561 spin_unlock_irqrestore(&gpio_lock, flags);
555 break; 562 break;
556 case IO_CLRALARM: 563 case IO_CLRALARM:
557 // clear alarm for bits with 1 in arg 564 /* clear alarm for bits with 1 in arg */
565 spin_lock_irqsave(&gpio_lock, flags);
558 priv->highalarm &= ~arg; 566 priv->highalarm &= ~arg;
559 priv->lowalarm &= ~arg; 567 priv->lowalarm &= ~arg;
560 { 568 {
561 /* Must update gpio_some_alarms */ 569 /* Must update gpio_some_alarms */
562 struct gpio_private *p = alarmlist; 570 struct gpio_private *p = alarmlist;
563 int some_alarms; 571 int some_alarms;
564 spin_lock_irq(&gpio_lock);
565 p = alarmlist; 572 p = alarmlist;
566 some_alarms = 0; 573 some_alarms = 0;
567 while (p) { 574 while (p) {
@@ -572,11 +579,12 @@ gpio_ioctl_unlocked(struct file *file, unsigned int cmd, unsigned long arg)
572 p = p->next; 579 p = p->next;
573 } 580 }
574 gpio_some_alarms = some_alarms; 581 gpio_some_alarms = some_alarms;
575 spin_unlock_irq(&gpio_lock);
576 } 582 }
583 spin_unlock_irqrestore(&gpio_lock, flags);
577 break; 584 break;
578 case IO_READDIR: /* Use IO_SETGET_INPUT/OUTPUT instead! */ 585 case IO_READDIR: /* Use IO_SETGET_INPUT/OUTPUT instead! */
579 /* Read direction 0=input 1=output */ 586 /* Read direction 0=input 1=output */
587 spin_lock_irqsave(&gpio_lock, flags);
580 if (USE_PORTS(priv)) { 588 if (USE_PORTS(priv)) {
581 ret = *priv->dir_shadow; 589 ret = *priv->dir_shadow;
582 } else if (priv->minor == GPIO_MINOR_G) { 590 } else if (priv->minor == GPIO_MINOR_G) {
@@ -585,30 +593,40 @@ gpio_ioctl_unlocked(struct file *file, unsigned int cmd, unsigned long arg)
585 */ 593 */
586 ret = (dir_g_shadow | dir_g_out_bits) & 0x7FFFFFFF; 594 ret = (dir_g_shadow | dir_g_out_bits) & 0x7FFFFFFF;
587 } 595 }
596 spin_unlock_irqrestore(&gpio_lock, flags);
588 break; 597 break;
589 case IO_SETINPUT: /* Use IO_SETGET_INPUT instead! */ 598 case IO_SETINPUT: /* Use IO_SETGET_INPUT instead! */
590 /* Set direction 0=unchanged 1=input, 599 /* Set direction 0=unchanged 1=input,
591 * return mask with 1=input 600 * return mask with 1=input
592 */ 601 */
602 spin_lock_irqsave(&gpio_lock, flags);
593 ret = setget_input(priv, arg) & 0x7FFFFFFF; 603 ret = setget_input(priv, arg) & 0x7FFFFFFF;
604 spin_unlock_irqrestore(&gpio_lock, flags);
594 break; 605 break;
595 case IO_SETOUTPUT: /* Use IO_SETGET_OUTPUT instead! */ 606 case IO_SETOUTPUT: /* Use IO_SETGET_OUTPUT instead! */
596 /* Set direction 0=unchanged 1=output, 607 /* Set direction 0=unchanged 1=output,
597 * return mask with 1=output 608 * return mask with 1=output
598 */ 609 */
610 spin_lock_irqsave(&gpio_lock, flags);
599 ret = setget_output(priv, arg) & 0x7FFFFFFF; 611 ret = setget_output(priv, arg) & 0x7FFFFFFF;
612 spin_unlock_irqrestore(&gpio_lock, flags);
600 break; 613 break;
601 case IO_SHUTDOWN: 614 case IO_SHUTDOWN:
615 spin_lock_irqsave(&gpio_lock, flags);
602 SOFT_SHUTDOWN(); 616 SOFT_SHUTDOWN();
617 spin_unlock_irqrestore(&gpio_lock, flags);
603 break; 618 break;
604 case IO_GET_PWR_BT: 619 case IO_GET_PWR_BT:
620 spin_lock_irqsave(&gpio_lock, flags);
605#if defined (CONFIG_ETRAX_SOFT_SHUTDOWN) 621#if defined (CONFIG_ETRAX_SOFT_SHUTDOWN)
606 ret = (*R_PORT_G_DATA & ( 1 << CONFIG_ETRAX_POWERBUTTON_BIT)); 622 ret = (*R_PORT_G_DATA & ( 1 << CONFIG_ETRAX_POWERBUTTON_BIT));
607#else 623#else
608 ret = 0; 624 ret = 0;
609#endif 625#endif
626 spin_unlock_irqrestore(&gpio_lock, flags);
610 break; 627 break;
611 case IO_CFG_WRITE_MODE: 628 case IO_CFG_WRITE_MODE:
629 spin_lock_irqsave(&gpio_lock, flags);
612 priv->clk_mask = arg & 0xFF; 630 priv->clk_mask = arg & 0xFF;
613 priv->data_mask = (arg >> 8) & 0xFF; 631 priv->data_mask = (arg >> 8) & 0xFF;
614 priv->write_msb = (arg >> 16) & 0x01; 632 priv->write_msb = (arg >> 16) & 0x01;
@@ -624,28 +642,33 @@ gpio_ioctl_unlocked(struct file *file, unsigned int cmd, unsigned long arg)
624 priv->data_mask = 0; 642 priv->data_mask = 0;
625 ret = -EPERM; 643 ret = -EPERM;
626 } 644 }
645 spin_unlock_irqrestore(&gpio_lock, flags);
627 break; 646 break;
628 case IO_READ_INBITS: 647 case IO_READ_INBITS:
629 /* *arg is result of reading the input pins */ 648 /* *arg is result of reading the input pins */
649 spin_lock_irqsave(&gpio_lock, flags);
630 if (USE_PORTS(priv)) { 650 if (USE_PORTS(priv)) {
631 val = *priv->port; 651 val = *priv->port;
632 } else if (priv->minor == GPIO_MINOR_G) { 652 } else if (priv->minor == GPIO_MINOR_G) {
633 val = *R_PORT_G_DATA; 653 val = *R_PORT_G_DATA;
634 } 654 }
655 spin_unlock_irqrestore(&gpio_lock, flags);
635 if (copy_to_user((void __user *)arg, &val, sizeof(val))) 656 if (copy_to_user((void __user *)arg, &val, sizeof(val)))
636 ret = -EFAULT; 657 ret = -EFAULT;
637 break; 658 break;
638 case IO_READ_OUTBITS: 659 case IO_READ_OUTBITS:
639 /* *arg is result of reading the output shadow */ 660 /* *arg is result of reading the output shadow */
661 spin_lock_irqsave(&gpio_lock, flags);
640 if (USE_PORTS(priv)) { 662 if (USE_PORTS(priv)) {
641 val = *priv->shadow; 663 val = *priv->shadow;
642 } else if (priv->minor == GPIO_MINOR_G) { 664 } else if (priv->minor == GPIO_MINOR_G) {
643 val = port_g_data_shadow; 665 val = port_g_data_shadow;
644 } 666 }
667 spin_unlock_irqrestore(&gpio_lock, flags);
645 if (copy_to_user((void __user *)arg, &val, sizeof(val))) 668 if (copy_to_user((void __user *)arg, &val, sizeof(val)))
646 ret = -EFAULT; 669 ret = -EFAULT;
647 break; 670 break;
648 case IO_SETGET_INPUT: 671 case IO_SETGET_INPUT:
649 /* bits set in *arg is set to input, 672 /* bits set in *arg is set to input,
650 * *arg updated with current input pins. 673 * *arg updated with current input pins.
651 */ 674 */
@@ -654,7 +677,9 @@ gpio_ioctl_unlocked(struct file *file, unsigned int cmd, unsigned long arg)
654 ret = -EFAULT; 677 ret = -EFAULT;
655 break; 678 break;
656 } 679 }
680 spin_lock_irqsave(&gpio_lock, flags);
657 val = setget_input(priv, val); 681 val = setget_input(priv, val);
682 spin_unlock_irqrestore(&gpio_lock, flags);
658 if (copy_to_user((void __user *)arg, &val, sizeof(val))) 683 if (copy_to_user((void __user *)arg, &val, sizeof(val)))
659 ret = -EFAULT; 684 ret = -EFAULT;
660 break; 685 break;
@@ -666,34 +691,25 @@ gpio_ioctl_unlocked(struct file *file, unsigned int cmd, unsigned long arg)
666 ret = -EFAULT; 691 ret = -EFAULT;
667 break; 692 break;
668 } 693 }
694 spin_lock_irqsave(&gpio_lock, flags);
669 val = setget_output(priv, val); 695 val = setget_output(priv, val);
696 spin_unlock_irqrestore(&gpio_lock, flags);
670 if (copy_to_user((void __user *)arg, &val, sizeof(val))) 697 if (copy_to_user((void __user *)arg, &val, sizeof(val)))
671 ret = -EFAULT; 698 ret = -EFAULT;
672 break; 699 break;
673 default: 700 default:
701 spin_lock_irqsave(&gpio_lock, flags);
674 if (priv->minor == GPIO_MINOR_LEDS) 702 if (priv->minor == GPIO_MINOR_LEDS)
675 ret = gpio_leds_ioctl(cmd, arg); 703 ret = gpio_leds_ioctl(cmd, arg);
676 else 704 else
677 ret = -EINVAL; 705 ret = -EINVAL;
706 spin_unlock_irqrestore(&gpio_lock, flags);
678 } /* switch */ 707 } /* switch */
679 708
680 spin_unlock_irqrestore(&gpio_lock, flags);
681 return ret; 709 return ret;
682} 710}
683 711
684static int 712static int
685gpio_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
686{
687 long ret;
688
689 lock_kernel();
690 ret = gpio_ioctl_unlocked(file, cmd, arg);
691 unlock_kernel();
692
693 return ret;
694}
695
696static int
697gpio_leds_ioctl(unsigned int cmd, unsigned long arg) 713gpio_leds_ioctl(unsigned int cmd, unsigned long arg)
698{ 714{
699 unsigned char green; 715 unsigned char green;