aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pinctrl/pinctrl-samsung.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/pinctrl/pinctrl-samsung.c')
-rw-r--r--drivers/pinctrl/pinctrl-samsung.c207
1 files changed, 149 insertions, 58 deletions
diff --git a/drivers/pinctrl/pinctrl-samsung.c b/drivers/pinctrl/pinctrl-samsung.c
index 861cd5f04d5e..3b52c17c4fd2 100644
--- a/drivers/pinctrl/pinctrl-samsung.c
+++ b/drivers/pinctrl/pinctrl-samsung.c
@@ -26,6 +26,7 @@
26#include <linux/slab.h> 26#include <linux/slab.h>
27#include <linux/err.h> 27#include <linux/err.h>
28#include <linux/gpio.h> 28#include <linux/gpio.h>
29#include <linux/irqdomain.h>
29 30
30#include "core.h" 31#include "core.h"
31#include "pinctrl-samsung.h" 32#include "pinctrl-samsung.h"
@@ -46,6 +47,13 @@ struct pin_config {
46 { "samsung,pin-pud-pdn", PINCFG_TYPE_PUD_PDN }, 47 { "samsung,pin-pud-pdn", PINCFG_TYPE_PUD_PDN },
47}; 48};
48 49
50static unsigned int pin_base = 0;
51
52static inline struct samsung_pin_bank *gc_to_pin_bank(struct gpio_chip *gc)
53{
54 return container_of(gc, struct samsung_pin_bank, gpio_chip);
55}
56
49/* check if the selector is a valid pin group selector */ 57/* check if the selector is a valid pin group selector */
50static int samsung_get_group_count(struct pinctrl_dev *pctldev) 58static int samsung_get_group_count(struct pinctrl_dev *pctldev)
51{ 59{
@@ -250,14 +258,12 @@ static int samsung_pinmux_get_groups(struct pinctrl_dev *pctldev,
250 * given a pin number that is local to a pin controller, find out the pin bank 258 * given a pin number that is local to a pin controller, find out the pin bank
251 * and the register base of the pin bank. 259 * and the register base of the pin bank.
252 */ 260 */
253static void pin_to_reg_bank(struct gpio_chip *gc, unsigned pin, 261static void pin_to_reg_bank(struct samsung_pinctrl_drv_data *drvdata,
254 void __iomem **reg, u32 *offset, 262 unsigned pin, void __iomem **reg, u32 *offset,
255 struct samsung_pin_bank **bank) 263 struct samsung_pin_bank **bank)
256{ 264{
257 struct samsung_pinctrl_drv_data *drvdata;
258 struct samsung_pin_bank *b; 265 struct samsung_pin_bank *b;
259 266
260 drvdata = dev_get_drvdata(gc->dev);
261 b = drvdata->ctrl->pin_banks; 267 b = drvdata->ctrl->pin_banks;
262 268
263 while ((pin >= b->pin_base) && 269 while ((pin >= b->pin_base) &&
@@ -292,7 +298,7 @@ static void samsung_pinmux_setup(struct pinctrl_dev *pctldev, unsigned selector,
292 * pin function number in the config register. 298 * pin function number in the config register.
293 */ 299 */
294 for (cnt = 0; cnt < drvdata->pin_groups[group].num_pins; cnt++) { 300 for (cnt = 0; cnt < drvdata->pin_groups[group].num_pins; cnt++) {
295 pin_to_reg_bank(drvdata->gc, pins[cnt] - drvdata->ctrl->base, 301 pin_to_reg_bank(drvdata, pins[cnt] - drvdata->ctrl->base,
296 &reg, &pin_offset, &bank); 302 &reg, &pin_offset, &bank);
297 mask = (1 << bank->func_width) - 1; 303 mask = (1 << bank->func_width) - 1;
298 shift = pin_offset * bank->func_width; 304 shift = pin_offset * bank->func_width;
@@ -329,10 +335,16 @@ static int samsung_pinmux_gpio_set_direction(struct pinctrl_dev *pctldev,
329 struct pinctrl_gpio_range *range, unsigned offset, bool input) 335 struct pinctrl_gpio_range *range, unsigned offset, bool input)
330{ 336{
331 struct samsung_pin_bank *bank; 337 struct samsung_pin_bank *bank;
338 struct samsung_pinctrl_drv_data *drvdata;
332 void __iomem *reg; 339 void __iomem *reg;
333 u32 data, pin_offset, mask, shift; 340 u32 data, pin_offset, mask, shift;
334 341
335 pin_to_reg_bank(range->gc, offset, &reg, &pin_offset, &bank); 342 bank = gc_to_pin_bank(range->gc);
343 drvdata = pinctrl_dev_get_drvdata(pctldev);
344
345 pin_offset = offset - bank->pin_base;
346 reg = drvdata->virt_base + bank->pctl_offset;
347
336 mask = (1 << bank->func_width) - 1; 348 mask = (1 << bank->func_width) - 1;
337 shift = pin_offset * bank->func_width; 349 shift = pin_offset * bank->func_width;
338 350
@@ -366,7 +378,7 @@ static int samsung_pinconf_rw(struct pinctrl_dev *pctldev, unsigned int pin,
366 u32 cfg_value, cfg_reg; 378 u32 cfg_value, cfg_reg;
367 379
368 drvdata = pinctrl_dev_get_drvdata(pctldev); 380 drvdata = pinctrl_dev_get_drvdata(pctldev);
369 pin_to_reg_bank(drvdata->gc, pin - drvdata->ctrl->base, &reg_base, 381 pin_to_reg_bank(drvdata, pin - drvdata->ctrl->base, &reg_base,
370 &pin_offset, &bank); 382 &pin_offset, &bank);
371 383
372 switch (cfg_type) { 384 switch (cfg_type) {
@@ -391,6 +403,9 @@ static int samsung_pinconf_rw(struct pinctrl_dev *pctldev, unsigned int pin,
391 return -EINVAL; 403 return -EINVAL;
392 } 404 }
393 405
406 if (!width)
407 return -EINVAL;
408
394 mask = (1 << width) - 1; 409 mask = (1 << width) - 1;
395 shift = pin_offset * width; 410 shift = pin_offset * width;
396 data = readl(reg_base + cfg_reg); 411 data = readl(reg_base + cfg_reg);
@@ -463,14 +478,16 @@ static struct pinconf_ops samsung_pinconf_ops = {
463/* gpiolib gpio_set callback function */ 478/* gpiolib gpio_set callback function */
464static void samsung_gpio_set(struct gpio_chip *gc, unsigned offset, int value) 479static void samsung_gpio_set(struct gpio_chip *gc, unsigned offset, int value)
465{ 480{
481 struct samsung_pin_bank *bank = gc_to_pin_bank(gc);
466 void __iomem *reg; 482 void __iomem *reg;
467 u32 pin_offset, data; 483 u32 data;
484
485 reg = bank->drvdata->virt_base + bank->pctl_offset;
468 486
469 pin_to_reg_bank(gc, offset, &reg, &pin_offset, NULL);
470 data = readl(reg + DAT_REG); 487 data = readl(reg + DAT_REG);
471 data &= ~(1 << pin_offset); 488 data &= ~(1 << offset);
472 if (value) 489 if (value)
473 data |= 1 << pin_offset; 490 data |= 1 << offset;
474 writel(data, reg + DAT_REG); 491 writel(data, reg + DAT_REG);
475} 492}
476 493
@@ -478,11 +495,13 @@ static void samsung_gpio_set(struct gpio_chip *gc, unsigned offset, int value)
478static int samsung_gpio_get(struct gpio_chip *gc, unsigned offset) 495static int samsung_gpio_get(struct gpio_chip *gc, unsigned offset)
479{ 496{
480 void __iomem *reg; 497 void __iomem *reg;
481 u32 pin_offset, data; 498 u32 data;
499 struct samsung_pin_bank *bank = gc_to_pin_bank(gc);
500
501 reg = bank->drvdata->virt_base + bank->pctl_offset;
482 502
483 pin_to_reg_bank(gc, offset, &reg, &pin_offset, NULL);
484 data = readl(reg + DAT_REG); 503 data = readl(reg + DAT_REG);
485 data >>= pin_offset; 504 data >>= offset;
486 data &= 1; 505 data &= 1;
487 return data; 506 return data;
488} 507}
@@ -510,6 +529,23 @@ static int samsung_gpio_direction_output(struct gpio_chip *gc, unsigned offset,
510} 529}
511 530
512/* 531/*
532 * gpiolib gpio_to_irq callback function. Creates a mapping between a GPIO pin
533 * and a virtual IRQ, if not already present.
534 */
535static int samsung_gpio_to_irq(struct gpio_chip *gc, unsigned offset)
536{
537 struct samsung_pin_bank *bank = gc_to_pin_bank(gc);
538 unsigned int virq;
539
540 if (!bank->irq_domain)
541 return -ENXIO;
542
543 virq = irq_create_mapping(bank->irq_domain, offset);
544
545 return (virq) ? : -ENXIO;
546}
547
548/*
513 * Parse the pin names listed in the 'samsung,pins' property and convert it 549 * Parse the pin names listed in the 'samsung,pins' property and convert it
514 * into a list of gpio numbers are create a pin group from it. 550 * into a list of gpio numbers are create a pin group from it.
515 */ 551 */
@@ -524,7 +560,7 @@ static int __devinit samsung_pinctrl_parse_dt_pins(struct platform_device *pdev,
524 const char *pin_name; 560 const char *pin_name;
525 561
526 *npins = of_property_count_strings(cfg_np, "samsung,pins"); 562 *npins = of_property_count_strings(cfg_np, "samsung,pins");
527 if (*npins < 0) { 563 if (IS_ERR_VALUE(*npins)) {
528 dev_err(dev, "invalid pin list in %s node", cfg_np->name); 564 dev_err(dev, "invalid pin list in %s node", cfg_np->name);
529 return -EINVAL; 565 return -EINVAL;
530 } 566 }
@@ -597,7 +633,7 @@ static int __devinit samsung_pinctrl_parse_dt(struct platform_device *pdev,
597 */ 633 */
598 for_each_child_of_node(dev_np, cfg_np) { 634 for_each_child_of_node(dev_np, cfg_np) {
599 u32 function; 635 u32 function;
600 if (of_find_property(cfg_np, "interrupt-controller", NULL)) 636 if (!of_find_property(cfg_np, "samsung,pins", NULL))
601 continue; 637 continue;
602 638
603 ret = samsung_pinctrl_parse_dt_pins(pdev, cfg_np, 639 ret = samsung_pinctrl_parse_dt_pins(pdev, cfg_np,
@@ -712,12 +748,16 @@ static int __devinit samsung_pinctrl_register(struct platform_device *pdev,
712 return -EINVAL; 748 return -EINVAL;
713 } 749 }
714 750
715 drvdata->grange.name = "samsung-pctrl-gpio-range"; 751 for (bank = 0; bank < drvdata->ctrl->nr_banks; ++bank) {
716 drvdata->grange.id = 0; 752 pin_bank = &drvdata->ctrl->pin_banks[bank];
717 drvdata->grange.base = drvdata->ctrl->base; 753 pin_bank->grange.name = pin_bank->name;
718 drvdata->grange.npins = drvdata->ctrl->nr_pins; 754 pin_bank->grange.id = bank;
719 drvdata->grange.gc = drvdata->gc; 755 pin_bank->grange.pin_base = pin_bank->pin_base;
720 pinctrl_add_gpio_range(drvdata->pctl_dev, &drvdata->grange); 756 pin_bank->grange.base = pin_bank->gpio_chip.base;
757 pin_bank->grange.npins = pin_bank->gpio_chip.ngpio;
758 pin_bank->grange.gc = &pin_bank->gpio_chip;
759 pinctrl_add_gpio_range(drvdata->pctl_dev, &pin_bank->grange);
760 }
721 761
722 ret = samsung_pinctrl_parse_dt(pdev, drvdata); 762 ret = samsung_pinctrl_parse_dt(pdev, drvdata);
723 if (ret) { 763 if (ret) {
@@ -728,68 +768,117 @@ static int __devinit samsung_pinctrl_register(struct platform_device *pdev,
728 return 0; 768 return 0;
729} 769}
730 770
771static const struct gpio_chip samsung_gpiolib_chip = {
772 .set = samsung_gpio_set,
773 .get = samsung_gpio_get,
774 .direction_input = samsung_gpio_direction_input,
775 .direction_output = samsung_gpio_direction_output,
776 .to_irq = samsung_gpio_to_irq,
777 .owner = THIS_MODULE,
778};
779
731/* register the gpiolib interface with the gpiolib subsystem */ 780/* register the gpiolib interface with the gpiolib subsystem */
732static int __devinit samsung_gpiolib_register(struct platform_device *pdev, 781static int __devinit samsung_gpiolib_register(struct platform_device *pdev,
733 struct samsung_pinctrl_drv_data *drvdata) 782 struct samsung_pinctrl_drv_data *drvdata)
734{ 783{
784 struct samsung_pin_ctrl *ctrl = drvdata->ctrl;
785 struct samsung_pin_bank *bank = ctrl->pin_banks;
735 struct gpio_chip *gc; 786 struct gpio_chip *gc;
736 int ret; 787 int ret;
737 788 int i;
738 gc = devm_kzalloc(&pdev->dev, sizeof(*gc), GFP_KERNEL); 789
739 if (!gc) { 790 for (i = 0; i < ctrl->nr_banks; ++i, ++bank) {
740 dev_err(&pdev->dev, "mem alloc for gpio_chip failed\n"); 791 bank->gpio_chip = samsung_gpiolib_chip;
741 return -ENOMEM; 792
742 } 793 gc = &bank->gpio_chip;
743 794 gc->base = ctrl->base + bank->pin_base;
744 drvdata->gc = gc; 795 gc->ngpio = bank->nr_pins;
745 gc->base = drvdata->ctrl->base; 796 gc->dev = &pdev->dev;
746 gc->ngpio = drvdata->ctrl->nr_pins; 797 gc->of_node = bank->of_node;
747 gc->dev = &pdev->dev; 798 gc->label = bank->name;
748 gc->set = samsung_gpio_set; 799
749 gc->get = samsung_gpio_get; 800 ret = gpiochip_add(gc);
750 gc->direction_input = samsung_gpio_direction_input; 801 if (ret) {
751 gc->direction_output = samsung_gpio_direction_output; 802 dev_err(&pdev->dev, "failed to register gpio_chip %s, error code: %d\n",
752 gc->label = drvdata->ctrl->label; 803 gc->label, ret);
753 gc->owner = THIS_MODULE; 804 goto fail;
754 ret = gpiochip_add(gc); 805 }
755 if (ret) {
756 dev_err(&pdev->dev, "failed to register gpio_chip %s, error "
757 "code: %d\n", gc->label, ret);
758 return ret;
759 } 806 }
760 807
761 return 0; 808 return 0;
809
810fail:
811 for (--i, --bank; i >= 0; --i, --bank)
812 if (gpiochip_remove(&bank->gpio_chip))
813 dev_err(&pdev->dev, "gpio chip %s remove failed\n",
814 bank->gpio_chip.label);
815 return ret;
762} 816}
763 817
764/* unregister the gpiolib interface with the gpiolib subsystem */ 818/* unregister the gpiolib interface with the gpiolib subsystem */
765static int __devinit samsung_gpiolib_unregister(struct platform_device *pdev, 819static int __devinit samsung_gpiolib_unregister(struct platform_device *pdev,
766 struct samsung_pinctrl_drv_data *drvdata) 820 struct samsung_pinctrl_drv_data *drvdata)
767{ 821{
768 int ret = gpiochip_remove(drvdata->gc); 822 struct samsung_pin_ctrl *ctrl = drvdata->ctrl;
769 if (ret) { 823 struct samsung_pin_bank *bank = ctrl->pin_banks;
824 int ret = 0;
825 int i;
826
827 for (i = 0; !ret && i < ctrl->nr_banks; ++i, ++bank)
828 ret = gpiochip_remove(&bank->gpio_chip);
829
830 if (ret)
770 dev_err(&pdev->dev, "gpio chip remove failed\n"); 831 dev_err(&pdev->dev, "gpio chip remove failed\n");
771 return ret; 832
772 } 833 return ret;
773 return 0;
774} 834}
775 835
776static const struct of_device_id samsung_pinctrl_dt_match[]; 836static const struct of_device_id samsung_pinctrl_dt_match[];
777 837
778/* retrieve the soc specific data */ 838/* retrieve the soc specific data */
779static struct samsung_pin_ctrl *samsung_pinctrl_get_soc_data( 839static struct samsung_pin_ctrl *samsung_pinctrl_get_soc_data(
840 struct samsung_pinctrl_drv_data *d,
780 struct platform_device *pdev) 841 struct platform_device *pdev)
781{ 842{
782 int id; 843 int id;
783 const struct of_device_id *match; 844 const struct of_device_id *match;
784 const struct device_node *node = pdev->dev.of_node; 845 struct device_node *node = pdev->dev.of_node;
846 struct device_node *np;
847 struct samsung_pin_ctrl *ctrl;
848 struct samsung_pin_bank *bank;
849 int i;
785 850
786 id = of_alias_get_id(pdev->dev.of_node, "pinctrl"); 851 id = of_alias_get_id(node, "pinctrl");
787 if (id < 0) { 852 if (id < 0) {
788 dev_err(&pdev->dev, "failed to get alias id\n"); 853 dev_err(&pdev->dev, "failed to get alias id\n");
789 return NULL; 854 return NULL;
790 } 855 }
791 match = of_match_node(samsung_pinctrl_dt_match, node); 856 match = of_match_node(samsung_pinctrl_dt_match, node);
792 return (struct samsung_pin_ctrl *)match->data + id; 857 ctrl = (struct samsung_pin_ctrl *)match->data + id;
858
859 bank = ctrl->pin_banks;
860 for (i = 0; i < ctrl->nr_banks; ++i, ++bank) {
861 bank->drvdata = d;
862 bank->pin_base = ctrl->nr_pins;
863 ctrl->nr_pins += bank->nr_pins;
864 }
865
866 for_each_child_of_node(node, np) {
867 if (!of_find_property(np, "gpio-controller", NULL))
868 continue;
869 bank = ctrl->pin_banks;
870 for (i = 0; i < ctrl->nr_banks; ++i, ++bank) {
871 if (!strcmp(bank->name, np->name)) {
872 bank->of_node = np;
873 break;
874 }
875 }
876 }
877
878 ctrl->base = pin_base;
879 pin_base += ctrl->nr_pins;
880
881 return ctrl;
793} 882}
794 883
795static int __devinit samsung_pinctrl_probe(struct platform_device *pdev) 884static int __devinit samsung_pinctrl_probe(struct platform_device *pdev)
@@ -805,18 +894,18 @@ static int __devinit samsung_pinctrl_probe(struct platform_device *pdev)
805 return -ENODEV; 894 return -ENODEV;
806 } 895 }
807 896
808 ctrl = samsung_pinctrl_get_soc_data(pdev);
809 if (!ctrl) {
810 dev_err(&pdev->dev, "driver data not available\n");
811 return -EINVAL;
812 }
813
814 drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL); 897 drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL);
815 if (!drvdata) { 898 if (!drvdata) {
816 dev_err(dev, "failed to allocate memory for driver's " 899 dev_err(dev, "failed to allocate memory for driver's "
817 "private data\n"); 900 "private data\n");
818 return -ENOMEM; 901 return -ENOMEM;
819 } 902 }
903
904 ctrl = samsung_pinctrl_get_soc_data(drvdata, pdev);
905 if (!ctrl) {
906 dev_err(&pdev->dev, "driver data not available\n");
907 return -EINVAL;
908 }
820 drvdata->ctrl = ctrl; 909 drvdata->ctrl = ctrl;
821 drvdata->dev = dev; 910 drvdata->dev = dev;
822 911
@@ -858,6 +947,8 @@ static int __devinit samsung_pinctrl_probe(struct platform_device *pdev)
858static const struct of_device_id samsung_pinctrl_dt_match[] = { 947static const struct of_device_id samsung_pinctrl_dt_match[] = {
859 { .compatible = "samsung,pinctrl-exynos4210", 948 { .compatible = "samsung,pinctrl-exynos4210",
860 .data = (void *)exynos4210_pin_ctrl }, 949 .data = (void *)exynos4210_pin_ctrl },
950 { .compatible = "samsung,pinctrl-exynos4x12",
951 .data = (void *)exynos4x12_pin_ctrl },
861 {}, 952 {},
862}; 953};
863MODULE_DEVICE_TABLE(of, samsung_pinctrl_dt_match); 954MODULE_DEVICE_TABLE(of, samsung_pinctrl_dt_match);