aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pinctrl/pinctrl-sunxi.c
diff options
context:
space:
mode:
authorMaxime Ripard <maxime.ripard@free-electrons.com>2013-01-28 15:33:12 -0500
committerLinus Walleij <linus.walleij@linaro.org>2013-01-29 17:37:16 -0500
commit08e9e614ca4bec167f4b432328912b51a555f339 (patch)
tree6c7820882046c25d43e7af8aa6857f9030789557 /drivers/pinctrl/pinctrl-sunxi.c
parentc54729eeb05d65a77975ca042cc334b32baa86f4 (diff)
ARM: sunxi: gpio: Add Allwinner SoCs GPIO drivers
The IP responsible for the muxing on the Allwinner SoCs are also handling the GPIOs on the system. This patch adds the needed driver that relies on the pinctrl driver for most of its operations. The number of pins available for GPIOs operations are already declared in the pinctrl driver, we only need to probe a generic driver to handle the banks available for each SoC. This driver has been tested on a A13-Olinuxino. Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com> Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Diffstat (limited to 'drivers/pinctrl/pinctrl-sunxi.c')
-rw-r--r--drivers/pinctrl/pinctrl-sunxi.c134
1 files changed, 132 insertions, 2 deletions
diff --git a/drivers/pinctrl/pinctrl-sunxi.c b/drivers/pinctrl/pinctrl-sunxi.c
index 6f02e3422af9..fb000b00c6d3 100644
--- a/drivers/pinctrl/pinctrl-sunxi.c
+++ b/drivers/pinctrl/pinctrl-sunxi.c
@@ -11,6 +11,7 @@
11 */ 11 */
12 12
13#include <linux/io.h> 13#include <linux/io.h>
14#include <linux/gpio.h>
14#include <linux/module.h> 15#include <linux/module.h>
15#include <linux/of.h> 16#include <linux/of.h>
16#include <linux/of_address.h> 17#include <linux/of_address.h>
@@ -609,11 +610,53 @@ static int sunxi_pmx_enable(struct pinctrl_dev *pctldev,
609 return 0; 610 return 0;
610} 611}
611 612
613static int
614sunxi_pmx_gpio_set_direction(struct pinctrl_dev *pctldev,
615 struct pinctrl_gpio_range *range,
616 unsigned offset,
617 bool input)
618{
619 struct sunxi_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
620 struct sunxi_desc_function *desc;
621 char pin_name[SUNXI_PIN_NAME_MAX_LEN];
622 const char *func;
623 u8 bank, pin;
624 int ret;
625
626 bank = (offset) / PINS_PER_BANK;
627 pin = (offset) % PINS_PER_BANK;
628
629 ret = sprintf(pin_name, "P%c%d", 'A' + bank, pin);
630 if (!ret)
631 goto error;
632
633 if (input)
634 func = "gpio_in";
635 else
636 func = "gpio_out";
637
638 desc = sunxi_pinctrl_desc_find_function_by_name(pctl,
639 pin_name,
640 func);
641 if (!desc) {
642 ret = -EINVAL;
643 goto error;
644 }
645
646 sunxi_pmx_set(pctldev, offset, desc->muxval);
647
648 ret = 0;
649
650error:
651 return ret;
652}
653
612static struct pinmux_ops sunxi_pmx_ops = { 654static struct pinmux_ops sunxi_pmx_ops = {
613 .get_functions_count = sunxi_pmx_get_funcs_cnt, 655 .get_functions_count = sunxi_pmx_get_funcs_cnt,
614 .get_function_name = sunxi_pmx_get_func_name, 656 .get_function_name = sunxi_pmx_get_func_name,
615 .get_function_groups = sunxi_pmx_get_func_groups, 657 .get_function_groups = sunxi_pmx_get_func_groups,
616 .enable = sunxi_pmx_enable, 658 .enable = sunxi_pmx_enable,
659 .gpio_set_direction = sunxi_pmx_gpio_set_direction,
617}; 660};
618 661
619static struct pinctrl_desc sunxi_pctrl_desc = { 662static struct pinctrl_desc sunxi_pctrl_desc = {
@@ -622,6 +665,60 @@ static struct pinctrl_desc sunxi_pctrl_desc = {
622 .pmxops = &sunxi_pmx_ops, 665 .pmxops = &sunxi_pmx_ops,
623}; 666};
624 667
668static int sunxi_pinctrl_gpio_request(struct gpio_chip *chip, unsigned offset)
669{
670 return pinctrl_request_gpio(chip->base + offset);
671}
672
673static void sunxi_pinctrl_gpio_free(struct gpio_chip *chip, unsigned offset)
674{
675 pinctrl_free_gpio(chip->base + offset);
676}
677
678static int sunxi_pinctrl_gpio_direction_input(struct gpio_chip *chip,
679 unsigned offset)
680{
681 return pinctrl_gpio_direction_input(chip->base + offset);
682}
683
684static int sunxi_pinctrl_gpio_get(struct gpio_chip *chip, unsigned offset)
685{
686 struct sunxi_pinctrl *pctl = dev_get_drvdata(chip->dev);
687
688 u32 reg = sunxi_data_reg(offset);
689 u8 index = sunxi_data_offset(offset);
690 u32 val = (readl(pctl->membase + reg) >> index) & DATA_PINS_MASK;
691
692 return val;
693}
694
695static int sunxi_pinctrl_gpio_direction_output(struct gpio_chip *chip,
696 unsigned offset, int value)
697{
698 return pinctrl_gpio_direction_output(chip->base + offset);
699}
700
701static void sunxi_pinctrl_gpio_set(struct gpio_chip *chip,
702 unsigned offset, int value)
703{
704 struct sunxi_pinctrl *pctl = dev_get_drvdata(chip->dev);
705 u32 reg = sunxi_data_reg(offset);
706 u8 index = sunxi_data_offset(offset);
707
708 writel((value & DATA_PINS_MASK) << index, pctl->membase + reg);
709}
710
711static struct gpio_chip sunxi_pinctrl_gpio_chip = {
712 .owner = THIS_MODULE,
713 .request = sunxi_pinctrl_gpio_request,
714 .free = sunxi_pinctrl_gpio_free,
715 .direction_input = sunxi_pinctrl_gpio_direction_input,
716 .direction_output = sunxi_pinctrl_gpio_direction_output,
717 .get = sunxi_pinctrl_gpio_get,
718 .set = sunxi_pinctrl_gpio_set,
719 .can_sleep = 0,
720};
721
625static struct of_device_id sunxi_pinctrl_match[] = { 722static struct of_device_id sunxi_pinctrl_match[] = {
626 { .compatible = "allwinner,sun5i-a13-pinctrl", .data = (void *)&sun5i_a13_pinctrl_data }, 723 { .compatible = "allwinner,sun5i-a13-pinctrl", .data = (void *)&sun5i_a13_pinctrl_data },
627 {} 724 {}
@@ -737,7 +834,7 @@ static int sunxi_pinctrl_probe(struct platform_device *pdev)
737 const struct of_device_id *device; 834 const struct of_device_id *device;
738 struct pinctrl_pin_desc *pins; 835 struct pinctrl_pin_desc *pins;
739 struct sunxi_pinctrl *pctl; 836 struct sunxi_pinctrl *pctl;
740 int i, ret; 837 int i, ret, last_pin;
741 838
742 pctl = devm_kzalloc(&pdev->dev, sizeof(*pctl), GFP_KERNEL); 839 pctl = devm_kzalloc(&pdev->dev, sizeof(*pctl), GFP_KERNEL);
743 if (!pctl) 840 if (!pctl)
@@ -781,9 +878,42 @@ static int sunxi_pinctrl_probe(struct platform_device *pdev)
781 return -EINVAL; 878 return -EINVAL;
782 } 879 }
783 880
784 dev_info(&pdev->dev, "initialized sunXi pin control driver\n"); 881 pctl->chip = devm_kzalloc(&pdev->dev, sizeof(*pctl->chip), GFP_KERNEL);
882 if (!pctl->chip) {
883 ret = -ENOMEM;
884 goto pinctrl_error;
885 }
886
887 last_pin = pctl->desc->pins[pctl->desc->npins - 1].pin.number;
888 pctl->chip = &sunxi_pinctrl_gpio_chip;
889 pctl->chip->ngpio = round_up(last_pin, PINS_PER_BANK);
890 pctl->chip->label = dev_name(&pdev->dev);
891 pctl->chip->dev = &pdev->dev;
892 pctl->chip->base = 0;
893
894 ret = gpiochip_add(pctl->chip);
895 if (ret)
896 goto pinctrl_error;
897
898 for (i = 0; i < pctl->desc->npins; i++) {
899 const struct sunxi_desc_pin *pin = pctl->desc->pins + i;
900
901 ret = gpiochip_add_pin_range(pctl->chip, dev_name(&pdev->dev),
902 pin->pin.number,
903 pin->pin.number, 1);
904 if (ret)
905 goto gpiochip_error;
906 }
907
908 dev_info(&pdev->dev, "initialized sunXi PIO driver\n");
785 909
786 return 0; 910 return 0;
911
912gpiochip_error:
913 ret = gpiochip_remove(pctl->chip);
914pinctrl_error:
915 pinctrl_unregister(pctl->pctl_dev);
916 return ret;
787} 917}
788 918
789static struct platform_driver sunxi_pinctrl_driver = { 919static struct platform_driver sunxi_pinctrl_driver = {