aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pinctrl
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
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')
-rw-r--r--drivers/pinctrl/pinctrl-sunxi.c134
-rw-r--r--drivers/pinctrl/pinctrl-sunxi.h25
2 files changed, 156 insertions, 3 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 = {
diff --git a/drivers/pinctrl/pinctrl-sunxi.h b/drivers/pinctrl/pinctrl-sunxi.h
index 0dc3b9d5321b..1ee35c03eef1 100644
--- a/drivers/pinctrl/pinctrl-sunxi.h
+++ b/drivers/pinctrl/pinctrl-sunxi.h
@@ -254,8 +254,11 @@
254#define SUNXI_PINCTRL_PIN_PG30 PINCTRL_PIN(PG_BASE + 30, "PG30") 254#define SUNXI_PINCTRL_PIN_PG30 PINCTRL_PIN(PG_BASE + 30, "PG30")
255#define SUNXI_PINCTRL_PIN_PG31 PINCTRL_PIN(PG_BASE + 31, "PG31") 255#define SUNXI_PINCTRL_PIN_PG31 PINCTRL_PIN(PG_BASE + 31, "PG31")
256 256
257#define SUNXI_PIN_NAME_MAX_LEN 5
258
257#define BANK_MEM_SIZE 0x24 259#define BANK_MEM_SIZE 0x24
258#define MUX_REGS_OFFSET 0x0 260#define MUX_REGS_OFFSET 0x0
261#define DATA_REGS_OFFSET 0x10
259#define DLEVEL_REGS_OFFSET 0x14 262#define DLEVEL_REGS_OFFSET 0x14
260#define PULL_REGS_OFFSET 0x1c 263#define PULL_REGS_OFFSET 0x1c
261 264
@@ -263,6 +266,9 @@
263#define MUX_PINS_PER_REG 8 266#define MUX_PINS_PER_REG 8
264#define MUX_PINS_BITS 4 267#define MUX_PINS_BITS 4
265#define MUX_PINS_MASK 0x0f 268#define MUX_PINS_MASK 0x0f
269#define DATA_PINS_PER_REG 32
270#define DATA_PINS_BITS 1
271#define DATA_PINS_MASK 0x01
266#define DLEVEL_PINS_PER_REG 16 272#define DLEVEL_PINS_PER_REG 16
267#define DLEVEL_PINS_BITS 2 273#define DLEVEL_PINS_BITS 2
268#define DLEVEL_PINS_MASK 0x03 274#define DLEVEL_PINS_MASK 0x03
@@ -283,6 +289,8 @@ struct sunxi_desc_pin {
283struct sunxi_pinctrl_desc { 289struct sunxi_pinctrl_desc {
284 const struct sunxi_desc_pin *pins; 290 const struct sunxi_desc_pin *pins;
285 int npins; 291 int npins;
292 struct pinctrl_gpio_range *ranges;
293 int nranges;
286}; 294};
287 295
288struct sunxi_pinctrl_function { 296struct sunxi_pinctrl_function {
@@ -299,6 +307,7 @@ struct sunxi_pinctrl_group {
299 307
300struct sunxi_pinctrl { 308struct sunxi_pinctrl {
301 void __iomem *membase; 309 void __iomem *membase;
310 struct gpio_chip *chip;
302 struct sunxi_pinctrl_desc *desc; 311 struct sunxi_pinctrl_desc *desc;
303 struct device *dev; 312 struct device *dev;
304 struct sunxi_pinctrl_function *functions; 313 struct sunxi_pinctrl_function *functions;
@@ -321,7 +330,6 @@ struct sunxi_pinctrl {
321 .muxval = _val, \ 330 .muxval = _val, \
322 } 331 }
323 332
324
325/* 333/*
326 * The sunXi PIO registers are organized as is: 334 * The sunXi PIO registers are organized as is:
327 * 0x00 - 0x0c Muxing values. 335 * 0x00 - 0x0c Muxing values.
@@ -354,6 +362,21 @@ static inline u32 sunxi_mux_offset(u16 pin)
354 return pin_num * MUX_PINS_BITS; 362 return pin_num * MUX_PINS_BITS;
355} 363}
356 364
365static inline u32 sunxi_data_reg(u16 pin)
366{
367 u8 bank = pin / PINS_PER_BANK;
368 u32 offset = bank * BANK_MEM_SIZE;
369 offset += DATA_REGS_OFFSET;
370 offset += pin % PINS_PER_BANK / DATA_PINS_PER_REG * 0x04;
371 return round_down(offset, 4);
372}
373
374static inline u32 sunxi_data_offset(u16 pin)
375{
376 u32 pin_num = pin % DATA_PINS_PER_REG;
377 return pin_num * DATA_PINS_BITS;
378}
379
357static inline u32 sunxi_dlevel_reg(u16 pin) 380static inline u32 sunxi_dlevel_reg(u16 pin)
358{ 381{
359 u8 bank = pin / PINS_PER_BANK; 382 u8 bank = pin / PINS_PER_BANK;