diff options
-rw-r--r-- | drivers/pinctrl/pinctrl-sunxi.c | 134 | ||||
-rw-r--r-- | drivers/pinctrl/pinctrl-sunxi.h | 25 |
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 | ||
613 | static int | ||
614 | sunxi_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 | |||
650 | error: | ||
651 | return ret; | ||
652 | } | ||
653 | |||
612 | static struct pinmux_ops sunxi_pmx_ops = { | 654 | static 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 | ||
619 | static struct pinctrl_desc sunxi_pctrl_desc = { | 662 | static 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 | ||
668 | static int sunxi_pinctrl_gpio_request(struct gpio_chip *chip, unsigned offset) | ||
669 | { | ||
670 | return pinctrl_request_gpio(chip->base + offset); | ||
671 | } | ||
672 | |||
673 | static void sunxi_pinctrl_gpio_free(struct gpio_chip *chip, unsigned offset) | ||
674 | { | ||
675 | pinctrl_free_gpio(chip->base + offset); | ||
676 | } | ||
677 | |||
678 | static 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 | |||
684 | static 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 | |||
695 | static 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 | |||
701 | static 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 | |||
711 | static 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 | |||
625 | static struct of_device_id sunxi_pinctrl_match[] = { | 722 | static 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 | |||
912 | gpiochip_error: | ||
913 | ret = gpiochip_remove(pctl->chip); | ||
914 | pinctrl_error: | ||
915 | pinctrl_unregister(pctl->pctl_dev); | ||
916 | return ret; | ||
787 | } | 917 | } |
788 | 918 | ||
789 | static struct platform_driver sunxi_pinctrl_driver = { | 919 | static 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 { | |||
283 | struct sunxi_pinctrl_desc { | 289 | struct 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 | ||
288 | struct sunxi_pinctrl_function { | 296 | struct sunxi_pinctrl_function { |
@@ -299,6 +307,7 @@ struct sunxi_pinctrl_group { | |||
299 | 307 | ||
300 | struct sunxi_pinctrl { | 308 | struct 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 | ||
365 | static 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 | |||
374 | static 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 | |||
357 | static inline u32 sunxi_dlevel_reg(u16 pin) | 380 | static inline u32 sunxi_dlevel_reg(u16 pin) |
358 | { | 381 | { |
359 | u8 bank = pin / PINS_PER_BANK; | 382 | u8 bank = pin / PINS_PER_BANK; |