aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorCharles Keepax <ckeepax@opensource.wolfsonmicro.com>2017-03-22 13:15:34 -0400
committerKrzysztof Kozlowski <krzk@kernel.org>2017-03-23 15:13:19 -0400
commit1abd18d1a51a95bf90c10459f1ed5c692660408e (patch)
tree46db95b97313cf1d3b347e3822959bb712eba7de
parente1d7eb0c8fc9c33ef60ac31172fb0fbb78c24271 (diff)
pinctrl: samsung: Register pinctrl before GPIO
If we request a GPIO hog, then gpiochip_add_data will attempt to request some of its own GPIOs. The driver also uses gpiochip_generic_request which means that for any GPIO request to succeed the pinctrl needs to be registered. Currently however the driver registers the GPIO and then the pinctrl meaning all GPIO hog requests will fail, which then in turn causes the whole driver to fail probe. Fix this up by ensuring we register the pinctrl first. This does require us to manually set the GPIO base for the pinctrl. Fortunately the driver already assigns a fixed GPIO base, in samsung_gpiolib_register, and uses the same calculation it does for the pin_base. Meaning the two will always be the same and allowing us to reuse the pinbase and avoid the issue. Although currently there are no users of GPIO hogs in mainline there are plenty of Samsung based boards that are widely used for development purposes of other hardware. Indeed we hit this issue whilst attaching some additional hardware to an Arndale system. Signed-off-by: Charles Keepax <ckeepax@opensource.wolfsonmicro.com> Signed-off-by: Krzysztof Kozlowski <krzk@kernel.org>
-rw-r--r--drivers/pinctrl/samsung/pinctrl-samsung.c36
1 files changed, 18 insertions, 18 deletions
diff --git a/drivers/pinctrl/samsung/pinctrl-samsung.c b/drivers/pinctrl/samsung/pinctrl-samsung.c
index f9ddba7decc1..5d5337072350 100644
--- a/drivers/pinctrl/samsung/pinctrl-samsung.c
+++ b/drivers/pinctrl/samsung/pinctrl-samsung.c
@@ -884,7 +884,7 @@ static int samsung_pinctrl_register(struct platform_device *pdev,
884 pin_bank->grange.id = bank; 884 pin_bank->grange.id = bank;
885 pin_bank->grange.pin_base = drvdata->pin_base 885 pin_bank->grange.pin_base = drvdata->pin_base
886 + pin_bank->pin_base; 886 + pin_bank->pin_base;
887 pin_bank->grange.base = pin_bank->gpio_chip.base; 887 pin_bank->grange.base = pin_bank->grange.pin_base;
888 pin_bank->grange.npins = pin_bank->gpio_chip.ngpio; 888 pin_bank->grange.npins = pin_bank->gpio_chip.ngpio;
889 pin_bank->grange.gc = &pin_bank->gpio_chip; 889 pin_bank->grange.gc = &pin_bank->gpio_chip;
890 pinctrl_add_gpio_range(drvdata->pctl_dev, &pin_bank->grange); 890 pinctrl_add_gpio_range(drvdata->pctl_dev, &pin_bank->grange);
@@ -893,6 +893,19 @@ static int samsung_pinctrl_register(struct platform_device *pdev,
893 return 0; 893 return 0;
894} 894}
895 895
896/* unregister the pinctrl interface with the pinctrl subsystem */
897static int samsung_pinctrl_unregister(struct platform_device *pdev,
898 struct samsung_pinctrl_drv_data *drvdata)
899{
900 struct samsung_pin_bank *bank = drvdata->pin_banks;
901 int i;
902
903 for (i = 0; i < drvdata->nr_banks; ++i, ++bank)
904 pinctrl_remove_gpio_range(drvdata->pctl_dev, &bank->grange);
905
906 return 0;
907}
908
896static const struct gpio_chip samsung_gpiolib_chip = { 909static const struct gpio_chip samsung_gpiolib_chip = {
897 .request = gpiochip_generic_request, 910 .request = gpiochip_generic_request,
898 .free = gpiochip_generic_free, 911 .free = gpiochip_generic_free,
@@ -917,7 +930,7 @@ static int samsung_gpiolib_register(struct platform_device *pdev,
917 bank->gpio_chip = samsung_gpiolib_chip; 930 bank->gpio_chip = samsung_gpiolib_chip;
918 931
919 gc = &bank->gpio_chip; 932 gc = &bank->gpio_chip;
920 gc->base = drvdata->pin_base + bank->pin_base; 933 gc->base = bank->grange.base;
921 gc->ngpio = bank->nr_pins; 934 gc->ngpio = bank->nr_pins;
922 gc->parent = &pdev->dev; 935 gc->parent = &pdev->dev;
923 gc->of_node = bank->of_node; 936 gc->of_node = bank->of_node;
@@ -939,19 +952,6 @@ fail:
939 return ret; 952 return ret;
940} 953}
941 954
942/* unregister the gpiolib interface with the gpiolib subsystem */
943static int samsung_gpiolib_unregister(struct platform_device *pdev,
944 struct samsung_pinctrl_drv_data *drvdata)
945{
946 struct samsung_pin_bank *bank = drvdata->pin_banks;
947 int i;
948
949 for (i = 0; i < drvdata->nr_banks; ++i, ++bank)
950 gpiochip_remove(&bank->gpio_chip);
951
952 return 0;
953}
954
955/* retrieve the soc specific data */ 955/* retrieve the soc specific data */
956static const struct samsung_pin_ctrl * 956static const struct samsung_pin_ctrl *
957samsung_pinctrl_get_soc_data(struct samsung_pinctrl_drv_data *d, 957samsung_pinctrl_get_soc_data(struct samsung_pinctrl_drv_data *d,
@@ -1062,13 +1062,13 @@ static int samsung_pinctrl_probe(struct platform_device *pdev)
1062 return PTR_ERR(drvdata->retention_ctrl); 1062 return PTR_ERR(drvdata->retention_ctrl);
1063 } 1063 }
1064 1064
1065 ret = samsung_gpiolib_register(pdev, drvdata); 1065 ret = samsung_pinctrl_register(pdev, drvdata);
1066 if (ret) 1066 if (ret)
1067 return ret; 1067 return ret;
1068 1068
1069 ret = samsung_pinctrl_register(pdev, drvdata); 1069 ret = samsung_gpiolib_register(pdev, drvdata);
1070 if (ret) { 1070 if (ret) {
1071 samsung_gpiolib_unregister(pdev, drvdata); 1071 samsung_pinctrl_unregister(pdev, drvdata);
1072 return ret; 1072 return ret;
1073 } 1073 }
1074 1074