aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pinctrl/sunxi/pinctrl-sunxi.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/pinctrl/sunxi/pinctrl-sunxi.c')
-rw-r--r--drivers/pinctrl/sunxi/pinctrl-sunxi.c187
1 files changed, 138 insertions, 49 deletions
diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.c b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
index 5f38c7f67834..3df66e366c87 100644
--- a/drivers/pinctrl/sunxi/pinctrl-sunxi.c
+++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
@@ -31,6 +31,9 @@
31#include "../core.h" 31#include "../core.h"
32#include "pinctrl-sunxi.h" 32#include "pinctrl-sunxi.h"
33 33
34static struct irq_chip sunxi_pinctrl_edge_irq_chip;
35static struct irq_chip sunxi_pinctrl_level_irq_chip;
36
34static struct sunxi_pinctrl_group * 37static struct sunxi_pinctrl_group *
35sunxi_pinctrl_find_group_by_name(struct sunxi_pinctrl *pctl, const char *group) 38sunxi_pinctrl_find_group_by_name(struct sunxi_pinctrl *pctl, const char *group)
36{ 39{
@@ -508,7 +511,7 @@ static int sunxi_pinctrl_gpio_of_xlate(struct gpio_chip *gc,
508 base = PINS_PER_BANK * gpiospec->args[0]; 511 base = PINS_PER_BANK * gpiospec->args[0];
509 pin = base + gpiospec->args[1]; 512 pin = base + gpiospec->args[1];
510 513
511 if (pin > (gc->base + gc->ngpio)) 514 if (pin > gc->ngpio)
512 return -EINVAL; 515 return -EINVAL;
513 516
514 if (flags) 517 if (flags)
@@ -521,25 +524,61 @@ static int sunxi_pinctrl_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
521{ 524{
522 struct sunxi_pinctrl *pctl = dev_get_drvdata(chip->dev); 525 struct sunxi_pinctrl *pctl = dev_get_drvdata(chip->dev);
523 struct sunxi_desc_function *desc; 526 struct sunxi_desc_function *desc;
527 unsigned pinnum = pctl->desc->pin_base + offset;
528 unsigned irqnum;
524 529
525 if (offset >= chip->ngpio) 530 if (offset >= chip->ngpio)
526 return -ENXIO; 531 return -ENXIO;
527 532
528 desc = sunxi_pinctrl_desc_find_function_by_pin(pctl, offset, "irq"); 533 desc = sunxi_pinctrl_desc_find_function_by_pin(pctl, pinnum, "irq");
529 if (!desc) 534 if (!desc)
530 return -EINVAL; 535 return -EINVAL;
531 536
537 irqnum = desc->irqbank * IRQ_PER_BANK + desc->irqnum;
538
532 dev_dbg(chip->dev, "%s: request IRQ for GPIO %d, return %d\n", 539 dev_dbg(chip->dev, "%s: request IRQ for GPIO %d, return %d\n",
533 chip->label, offset + chip->base, desc->irqnum); 540 chip->label, offset + chip->base, irqnum);
534 541
535 return irq_find_mapping(pctl->domain, desc->irqnum); 542 return irq_find_mapping(pctl->domain, irqnum);
536} 543}
537 544
545static int sunxi_pinctrl_irq_request_resources(struct irq_data *d)
546{
547 struct sunxi_pinctrl *pctl = irq_data_get_irq_chip_data(d);
548 struct sunxi_desc_function *func;
549 int ret;
550
551 func = sunxi_pinctrl_desc_find_function_by_pin(pctl,
552 pctl->irq_array[d->hwirq], "irq");
553 if (!func)
554 return -EINVAL;
555
556 ret = gpio_lock_as_irq(pctl->chip,
557 pctl->irq_array[d->hwirq] - pctl->desc->pin_base);
558 if (ret) {
559 dev_err(pctl->dev, "unable to lock HW IRQ %lu for IRQ\n",
560 irqd_to_hwirq(d));
561 return ret;
562 }
563
564 /* Change muxing to INT mode */
565 sunxi_pmx_set(pctl->pctl_dev, pctl->irq_array[d->hwirq], func->muxval);
538 566
539static int sunxi_pinctrl_irq_set_type(struct irq_data *d, 567 return 0;
540 unsigned int type) 568}
569
570static void sunxi_pinctrl_irq_release_resources(struct irq_data *d)
571{
572 struct sunxi_pinctrl *pctl = irq_data_get_irq_chip_data(d);
573
574 gpio_unlock_as_irq(pctl->chip,
575 pctl->irq_array[d->hwirq] - pctl->desc->pin_base);
576}
577
578static int sunxi_pinctrl_irq_set_type(struct irq_data *d, unsigned int type)
541{ 579{
542 struct sunxi_pinctrl *pctl = irq_data_get_irq_chip_data(d); 580 struct sunxi_pinctrl *pctl = irq_data_get_irq_chip_data(d);
581 struct irq_desc *desc = container_of(d, struct irq_desc, irq_data);
543 u32 reg = sunxi_irq_cfg_reg(d->hwirq); 582 u32 reg = sunxi_irq_cfg_reg(d->hwirq);
544 u8 index = sunxi_irq_cfg_offset(d->hwirq); 583 u8 index = sunxi_irq_cfg_offset(d->hwirq);
545 unsigned long flags; 584 unsigned long flags;
@@ -566,6 +605,14 @@ static int sunxi_pinctrl_irq_set_type(struct irq_data *d,
566 return -EINVAL; 605 return -EINVAL;
567 } 606 }
568 607
608 if (type & IRQ_TYPE_LEVEL_MASK) {
609 d->chip = &sunxi_pinctrl_level_irq_chip;
610 desc->handle_irq = handle_fasteoi_irq;
611 } else {
612 d->chip = &sunxi_pinctrl_edge_irq_chip;
613 desc->handle_irq = handle_edge_irq;
614 }
615
569 spin_lock_irqsave(&pctl->lock, flags); 616 spin_lock_irqsave(&pctl->lock, flags);
570 617
571 regval = readl(pctl->membase + reg); 618 regval = readl(pctl->membase + reg);
@@ -577,26 +624,14 @@ static int sunxi_pinctrl_irq_set_type(struct irq_data *d,
577 return 0; 624 return 0;
578} 625}
579 626
580static void sunxi_pinctrl_irq_mask_ack(struct irq_data *d) 627static void sunxi_pinctrl_irq_ack(struct irq_data *d)
581{ 628{
582 struct sunxi_pinctrl *pctl = irq_data_get_irq_chip_data(d); 629 struct sunxi_pinctrl *pctl = irq_data_get_irq_chip_data(d);
583 u32 ctrl_reg = sunxi_irq_ctrl_reg(d->hwirq);
584 u8 ctrl_idx = sunxi_irq_ctrl_offset(d->hwirq);
585 u32 status_reg = sunxi_irq_status_reg(d->hwirq); 630 u32 status_reg = sunxi_irq_status_reg(d->hwirq);
586 u8 status_idx = sunxi_irq_status_offset(d->hwirq); 631 u8 status_idx = sunxi_irq_status_offset(d->hwirq);
587 unsigned long flags;
588 u32 val;
589
590 spin_lock_irqsave(&pctl->lock, flags);
591
592 /* Mask the IRQ */
593 val = readl(pctl->membase + ctrl_reg);
594 writel(val & ~(1 << ctrl_idx), pctl->membase + ctrl_reg);
595 632
596 /* Clear the IRQ */ 633 /* Clear the IRQ */
597 writel(1 << status_idx, pctl->membase + status_reg); 634 writel(1 << status_idx, pctl->membase + status_reg);
598
599 spin_unlock_irqrestore(&pctl->lock, flags);
600} 635}
601 636
602static void sunxi_pinctrl_irq_mask(struct irq_data *d) 637static void sunxi_pinctrl_irq_mask(struct irq_data *d)
@@ -619,19 +654,11 @@ static void sunxi_pinctrl_irq_mask(struct irq_data *d)
619static void sunxi_pinctrl_irq_unmask(struct irq_data *d) 654static void sunxi_pinctrl_irq_unmask(struct irq_data *d)
620{ 655{
621 struct sunxi_pinctrl *pctl = irq_data_get_irq_chip_data(d); 656 struct sunxi_pinctrl *pctl = irq_data_get_irq_chip_data(d);
622 struct sunxi_desc_function *func;
623 u32 reg = sunxi_irq_ctrl_reg(d->hwirq); 657 u32 reg = sunxi_irq_ctrl_reg(d->hwirq);
624 u8 idx = sunxi_irq_ctrl_offset(d->hwirq); 658 u8 idx = sunxi_irq_ctrl_offset(d->hwirq);
625 unsigned long flags; 659 unsigned long flags;
626 u32 val; 660 u32 val;
627 661
628 func = sunxi_pinctrl_desc_find_function_by_pin(pctl,
629 pctl->irq_array[d->hwirq],
630 "irq");
631
632 /* Change muxing to INT mode */
633 sunxi_pmx_set(pctl->pctl_dev, pctl->irq_array[d->hwirq], func->muxval);
634
635 spin_lock_irqsave(&pctl->lock, flags); 662 spin_lock_irqsave(&pctl->lock, flags);
636 663
637 /* Unmask the IRQ */ 664 /* Unmask the IRQ */
@@ -641,28 +668,60 @@ static void sunxi_pinctrl_irq_unmask(struct irq_data *d)
641 spin_unlock_irqrestore(&pctl->lock, flags); 668 spin_unlock_irqrestore(&pctl->lock, flags);
642} 669}
643 670
644static struct irq_chip sunxi_pinctrl_irq_chip = { 671static void sunxi_pinctrl_irq_ack_unmask(struct irq_data *d)
672{
673 sunxi_pinctrl_irq_ack(d);
674 sunxi_pinctrl_irq_unmask(d);
675}
676
677static struct irq_chip sunxi_pinctrl_edge_irq_chip = {
678 .irq_ack = sunxi_pinctrl_irq_ack,
679 .irq_mask = sunxi_pinctrl_irq_mask,
680 .irq_unmask = sunxi_pinctrl_irq_unmask,
681 .irq_request_resources = sunxi_pinctrl_irq_request_resources,
682 .irq_release_resources = sunxi_pinctrl_irq_release_resources,
683 .irq_set_type = sunxi_pinctrl_irq_set_type,
684 .flags = IRQCHIP_SKIP_SET_WAKE,
685};
686
687static struct irq_chip sunxi_pinctrl_level_irq_chip = {
688 .irq_eoi = sunxi_pinctrl_irq_ack,
645 .irq_mask = sunxi_pinctrl_irq_mask, 689 .irq_mask = sunxi_pinctrl_irq_mask,
646 .irq_mask_ack = sunxi_pinctrl_irq_mask_ack,
647 .irq_unmask = sunxi_pinctrl_irq_unmask, 690 .irq_unmask = sunxi_pinctrl_irq_unmask,
691 /* Define irq_enable / disable to avoid spurious irqs for drivers
692 * using these to suppress irqs while they clear the irq source */
693 .irq_enable = sunxi_pinctrl_irq_ack_unmask,
694 .irq_disable = sunxi_pinctrl_irq_mask,
695 .irq_request_resources = sunxi_pinctrl_irq_request_resources,
696 .irq_release_resources = sunxi_pinctrl_irq_release_resources,
648 .irq_set_type = sunxi_pinctrl_irq_set_type, 697 .irq_set_type = sunxi_pinctrl_irq_set_type,
698 .flags = IRQCHIP_SKIP_SET_WAKE | IRQCHIP_EOI_THREADED |
699 IRQCHIP_EOI_IF_HANDLED,
649}; 700};
650 701
651static void sunxi_pinctrl_irq_handler(unsigned irq, struct irq_desc *desc) 702static void sunxi_pinctrl_irq_handler(unsigned irq, struct irq_desc *desc)
652{ 703{
653 struct irq_chip *chip = irq_get_chip(irq); 704 struct irq_chip *chip = irq_get_chip(irq);
654 struct sunxi_pinctrl *pctl = irq_get_handler_data(irq); 705 struct sunxi_pinctrl *pctl = irq_get_handler_data(irq);
655 const unsigned long reg = readl(pctl->membase + IRQ_STATUS_REG); 706 unsigned long bank, reg, val;
707
708 for (bank = 0; bank < pctl->desc->irq_banks; bank++)
709 if (irq == pctl->irq[bank])
710 break;
711
712 if (bank == pctl->desc->irq_banks)
713 return;
656 714
657 /* Clear all interrupts */ 715 reg = sunxi_irq_status_reg_from_bank(bank);
658 writel(reg, pctl->membase + IRQ_STATUS_REG); 716 val = readl(pctl->membase + reg);
659 717
660 if (reg) { 718 if (val) {
661 int irqoffset; 719 int irqoffset;
662 720
663 chained_irq_enter(chip, desc); 721 chained_irq_enter(chip, desc);
664 for_each_set_bit(irqoffset, &reg, SUNXI_IRQ_NUMBER) { 722 for_each_set_bit(irqoffset, &val, IRQ_PER_BANK) {
665 int pin_irq = irq_find_mapping(pctl->domain, irqoffset); 723 int pin_irq = irq_find_mapping(pctl->domain,
724 bank * IRQ_PER_BANK + irqoffset);
666 generic_handle_irq(pin_irq); 725 generic_handle_irq(pin_irq);
667 } 726 }
668 chained_irq_exit(chip, desc); 727 chained_irq_exit(chip, desc);
@@ -730,8 +789,11 @@ static int sunxi_pinctrl_build_state(struct platform_device *pdev)
730 789
731 while (func->name) { 790 while (func->name) {
732 /* Create interrupt mapping while we're at it */ 791 /* Create interrupt mapping while we're at it */
733 if (!strcmp(func->name, "irq")) 792 if (!strcmp(func->name, "irq")) {
734 pctl->irq_array[func->irqnum] = pin->pin.number; 793 int irqnum = func->irqnum + func->irqbank * IRQ_PER_BANK;
794 pctl->irq_array[irqnum] = pin->pin.number;
795 }
796
735 sunxi_pinctrl_add_function(pctl, func->name); 797 sunxi_pinctrl_add_function(pctl, func->name);
736 func++; 798 func++;
737 } 799 }
@@ -801,6 +863,13 @@ int sunxi_pinctrl_init(struct platform_device *pdev,
801 pctl->dev = &pdev->dev; 863 pctl->dev = &pdev->dev;
802 pctl->desc = desc; 864 pctl->desc = desc;
803 865
866 pctl->irq_array = devm_kcalloc(&pdev->dev,
867 IRQ_PER_BANK * pctl->desc->irq_banks,
868 sizeof(*pctl->irq_array),
869 GFP_KERNEL);
870 if (!pctl->irq_array)
871 return -ENOMEM;
872
804 ret = sunxi_pinctrl_build_state(pdev); 873 ret = sunxi_pinctrl_build_state(pdev);
805 if (ret) { 874 if (ret) {
806 dev_err(&pdev->dev, "dt probe failed: %d\n", ret); 875 dev_err(&pdev->dev, "dt probe failed: %d\n", ret);
@@ -869,7 +938,7 @@ int sunxi_pinctrl_init(struct platform_device *pdev,
869 const struct sunxi_desc_pin *pin = pctl->desc->pins + i; 938 const struct sunxi_desc_pin *pin = pctl->desc->pins + i;
870 939
871 ret = gpiochip_add_pin_range(pctl->chip, dev_name(&pdev->dev), 940 ret = gpiochip_add_pin_range(pctl->chip, dev_name(&pdev->dev),
872 pin->pin.number, 941 pin->pin.number - pctl->desc->pin_base,
873 pin->pin.number, 1); 942 pin->pin.number, 1);
874 if (ret) 943 if (ret)
875 goto gpiochip_error; 944 goto gpiochip_error;
@@ -885,30 +954,51 @@ int sunxi_pinctrl_init(struct platform_device *pdev,
885 if (ret) 954 if (ret)
886 goto gpiochip_error; 955 goto gpiochip_error;
887 956
888 pctl->irq = irq_of_parse_and_map(node, 0); 957 pctl->irq = devm_kcalloc(&pdev->dev,
958 pctl->desc->irq_banks,
959 sizeof(*pctl->irq),
960 GFP_KERNEL);
889 if (!pctl->irq) { 961 if (!pctl->irq) {
890 ret = -EINVAL; 962 ret = -ENOMEM;
891 goto clk_error; 963 goto clk_error;
892 } 964 }
893 965
894 pctl->domain = irq_domain_add_linear(node, SUNXI_IRQ_NUMBER, 966 for (i = 0; i < pctl->desc->irq_banks; i++) {
895 &irq_domain_simple_ops, NULL); 967 pctl->irq[i] = platform_get_irq(pdev, i);
968 if (pctl->irq[i] < 0) {
969 ret = pctl->irq[i];
970 goto clk_error;
971 }
972 }
973
974 pctl->domain = irq_domain_add_linear(node,
975 pctl->desc->irq_banks * IRQ_PER_BANK,
976 &irq_domain_simple_ops,
977 NULL);
896 if (!pctl->domain) { 978 if (!pctl->domain) {
897 dev_err(&pdev->dev, "Couldn't register IRQ domain\n"); 979 dev_err(&pdev->dev, "Couldn't register IRQ domain\n");
898 ret = -ENOMEM; 980 ret = -ENOMEM;
899 goto clk_error; 981 goto clk_error;
900 } 982 }
901 983
902 for (i = 0; i < SUNXI_IRQ_NUMBER; i++) { 984 for (i = 0; i < (pctl->desc->irq_banks * IRQ_PER_BANK); i++) {
903 int irqno = irq_create_mapping(pctl->domain, i); 985 int irqno = irq_create_mapping(pctl->domain, i);
904 986
905 irq_set_chip_and_handler(irqno, &sunxi_pinctrl_irq_chip, 987 irq_set_chip_and_handler(irqno, &sunxi_pinctrl_edge_irq_chip,
906 handle_simple_irq); 988 handle_edge_irq);
907 irq_set_chip_data(irqno, pctl); 989 irq_set_chip_data(irqno, pctl);
908 }; 990 };
909 991
910 irq_set_chained_handler(pctl->irq, sunxi_pinctrl_irq_handler); 992 for (i = 0; i < pctl->desc->irq_banks; i++) {
911 irq_set_handler_data(pctl->irq, pctl); 993 /* Mask and clear all IRQs before registering a handler */
994 writel(0, pctl->membase + sunxi_irq_ctrl_reg_from_bank(i));
995 writel(0xffffffff,
996 pctl->membase + sunxi_irq_status_reg_from_bank(i));
997
998 irq_set_chained_handler(pctl->irq[i],
999 sunxi_pinctrl_irq_handler);
1000 irq_set_handler_data(pctl->irq[i], pctl);
1001 }
912 1002
913 dev_info(&pdev->dev, "initialized sunXi PIO driver\n"); 1003 dev_info(&pdev->dev, "initialized sunXi PIO driver\n");
914 1004
@@ -917,8 +1007,7 @@ int sunxi_pinctrl_init(struct platform_device *pdev,
917clk_error: 1007clk_error:
918 clk_disable_unprepare(clk); 1008 clk_disable_unprepare(clk);
919gpiochip_error: 1009gpiochip_error:
920 if (gpiochip_remove(pctl->chip)) 1010 gpiochip_remove(pctl->chip);
921 dev_err(&pdev->dev, "failed to remove gpio chip\n");
922pinctrl_error: 1011pinctrl_error:
923 pinctrl_unregister(pctl->pctl_dev); 1012 pinctrl_unregister(pctl->pctl_dev);
924 return ret; 1013 return ret;