From 6e01e0c7a0bebd8626e651181d3592cea8d456c4 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Thu, 19 Mar 2020 13:27:34 +0100 Subject: pinctrl: tegra: Pass struct tegra_pmx for pin range check Pass the struct tegra_pmx when checking for the pin range in device tree. This makes the call site a bit easier to read and will help keep that readability in a subsequent patch. Signed-off-by: Thierry Reding Link: https://lore.kernel.org/r/20200319122737.3063291-7-thierry.reding@gmail.com Tested-by: Vidya Sagar Signed-off-by: Linus Walleij --- drivers/pinctrl/tegra/pinctrl-tegra.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/pinctrl/tegra/pinctrl-tegra.c') diff --git a/drivers/pinctrl/tegra/pinctrl-tegra.c b/drivers/pinctrl/tegra/pinctrl-tegra.c index cefbbb8d1a68..c8246cc2c4fd 100644 --- a/drivers/pinctrl/tegra/pinctrl-tegra.c +++ b/drivers/pinctrl/tegra/pinctrl-tegra.c @@ -689,12 +689,12 @@ const struct dev_pm_ops tegra_pinctrl_pm = { .resume = &tegra_pinctrl_resume }; -static bool gpio_node_has_range(const char *compatible) +static bool tegra_pinctrl_gpio_node_has_range(struct tegra_pmx *pmx) { struct device_node *np; bool has_prop = false; - np = of_find_compatible_node(NULL, NULL, compatible); + np = of_find_compatible_node(NULL, NULL, pmx->soc->gpio_compatible); if (!np) return has_prop; @@ -794,7 +794,7 @@ int tegra_pinctrl_probe(struct platform_device *pdev, tegra_pinctrl_clear_parked_bits(pmx); - if (!gpio_node_has_range(pmx->soc->gpio_compatible)) + if (!tegra_pinctrl_gpio_node_has_range(pmx)) pinctrl_add_gpio_range(pmx->pctl, &tegra_pinctrl_gpio_range); platform_set_drvdata(pdev, pmx); -- cgit From f67499f8ea7c15818d3375d718bd6cde4ae3d4f5 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Thu, 19 Mar 2020 13:27:35 +0100 Subject: pinctrl: tegra: Do not add default pin range on Tegra194 On Tegra194, almost all of the pin control programming happens in early boot firmware, so there is no use in having a pin range defined for all the pins. Signed-off-by: Thierry Reding Link: https://lore.kernel.org/r/20200319122737.3063291-8-thierry.reding@gmail.com Tested-by: Vidya Sagar Signed-off-by: Linus Walleij --- drivers/pinctrl/tegra/pinctrl-tegra.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/pinctrl/tegra/pinctrl-tegra.c') diff --git a/drivers/pinctrl/tegra/pinctrl-tegra.c b/drivers/pinctrl/tegra/pinctrl-tegra.c index c8246cc2c4fd..65511bf27d34 100644 --- a/drivers/pinctrl/tegra/pinctrl-tegra.c +++ b/drivers/pinctrl/tegra/pinctrl-tegra.c @@ -794,7 +794,7 @@ int tegra_pinctrl_probe(struct platform_device *pdev, tegra_pinctrl_clear_parked_bits(pmx); - if (!tegra_pinctrl_gpio_node_has_range(pmx)) + if (pmx->soc->ngpios > 0 && !tegra_pinctrl_gpio_node_has_range(pmx)) pinctrl_add_gpio_range(pmx->pctl, &tegra_pinctrl_gpio_range); platform_set_drvdata(pdev, pmx); -- cgit From 368b62f2fd077d4c7db09461e8e24f07491a513d Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Thu, 19 Mar 2020 13:27:37 +0100 Subject: pinctrl: tegra: Add SFIO/GPIO programming on Tegra194 Prior to Tegra186, the selection of SFIO vs. GPIO modes was done as part of the GPIO controller's register programming. Starting with Tegra186, a pin is configured as GPIO or SFIO with a bit in a configuration register of the pin controller. Signed-off-by: Thierry Reding Link: https://lore.kernel.org/r/20200319122737.3063291-10-thierry.reding@gmail.com Tested-by: Vidya Sagar Signed-off-by: Linus Walleij --- drivers/pinctrl/tegra/pinctrl-tegra.c | 46 +++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) (limited to 'drivers/pinctrl/tegra/pinctrl-tegra.c') diff --git a/drivers/pinctrl/tegra/pinctrl-tegra.c b/drivers/pinctrl/tegra/pinctrl-tegra.c index 65511bf27d34..21661f6490d6 100644 --- a/drivers/pinctrl/tegra/pinctrl-tegra.c +++ b/drivers/pinctrl/tegra/pinctrl-tegra.c @@ -275,11 +275,57 @@ static int tegra_pinctrl_set_mux(struct pinctrl_dev *pctldev, return 0; } +static int tegra_pinctrl_gpio_request_enable(struct pinctrl_dev *pctldev, + struct pinctrl_gpio_range *range, + unsigned int offset) +{ + struct tegra_pmx *pmx = pinctrl_dev_get_drvdata(pctldev); + const struct tegra_pingroup *group; + u32 value; + + if (!pmx->soc->sfsel_in_mux) + return 0; + + group = &pmx->soc->groups[offset]; + + if (group->mux_reg < 0 || group->sfsel_bit < 0) + return -EINVAL; + + value = pmx_readl(pmx, group->mux_bank, group->mux_reg); + value &= ~BIT(group->sfsel_bit); + pmx_writel(pmx, value, group->mux_bank, group->mux_reg); + + return 0; +} + +static void tegra_pinctrl_gpio_disable_free(struct pinctrl_dev *pctldev, + struct pinctrl_gpio_range *range, + unsigned int offset) +{ + struct tegra_pmx *pmx = pinctrl_dev_get_drvdata(pctldev); + const struct tegra_pingroup *group; + u32 value; + + if (!pmx->soc->sfsel_in_mux) + return; + + group = &pmx->soc->groups[offset]; + + if (group->mux_reg < 0 || group->sfsel_bit < 0) + return; + + value = pmx_readl(pmx, group->mux_bank, group->mux_reg); + value |= BIT(group->sfsel_bit); + pmx_writel(pmx, value, group->mux_bank, group->mux_reg); +} + static const struct pinmux_ops tegra_pinmux_ops = { .get_functions_count = tegra_pinctrl_get_funcs_count, .get_function_name = tegra_pinctrl_get_func_name, .get_function_groups = tegra_pinctrl_get_func_groups, .set_mux = tegra_pinctrl_set_mux, + .gpio_request_enable = tegra_pinctrl_gpio_request_enable, + .gpio_disable_free = tegra_pinctrl_gpio_disable_free, }; static int tegra_pinconf_reg(struct tegra_pmx *pmx, -- cgit