pinctrl: tegra: configure pins for gpio direction
Laxman Dewangan [Fri, 12 Sep 2014 09:42:43 +0000 (14:42 +0530)]
If pin is configured on gpio mode and set for input direction
then set e_input = 1 and if pin is set for output direction
then set tristate = 0 for that pin.

Bug 200033491

Change-Id: Ibcae17ad8bf4e45f0c74eb68d3bf975078fb67d6
Signed-off-by: Laxman Dewangan <ldewangan@nvidia.com>
Reviewed-on: http://git-master/r/416650
(cherry picked from commit 3dbac8e8382be0766e221c3f47f6254538b17030)
Reviewed-on: http://git-master/r/498327
GVS: Gerrit_Virtual_Submit
Reviewed-by: Bibek Basu <bbasu@nvidia.com>
Tested-by: Bibek Basu <bbasu@nvidia.com>
Reviewed-by: Venkat Moganty <vmoganty@nvidia.com>
Reviewed-by: Matthew Pedro <mapedro@nvidia.com>

drivers/pinctrl/pinctrl-tegra.c
drivers/pinctrl/pinctrl-tegra.h

index 528b8c5..77970f4 100644 (file)
@@ -436,12 +436,62 @@ static void tegra_pinctrl_disable(struct pinctrl_dev *pctldev,
        spin_unlock_irqrestore(&mux_lock, flags);
 }
 
+static int tegra_pinctrl_gpio_request_enable(struct pinctrl_dev *pctldev,
+                               struct pinctrl_gpio_range *range,
+                               unsigned pin)
+{
+       struct tegra_pmx *pmx = pinctrl_dev_get_drvdata(pctldev);
+
+       if (pmx->soc->gpio_request_enable)
+               return pmx->soc->gpio_request_enable(pin);
+       return 0;
+}
+
+static int tegra_pinctrl_gpio_set_direction(struct pinctrl_dev *pctldev,
+       struct pinctrl_gpio_range *range, unsigned offset, bool input)
+{
+       struct tegra_pmx *pmx = pinctrl_dev_get_drvdata(pctldev);
+       unsigned  group;
+       const unsigned *pins;
+       unsigned num_pins;
+       int ret;
+
+       for (group = 0; group < pmx->soc->ngroups; ++group) {
+               ret = tegra_pinctrl_get_group_pins(pctldev, group,
+                               &pins, &num_pins);
+               if (ret < 0 || num_pins != 1)
+                       continue;
+               if (offset ==  pins[0])
+                       break;
+       }
+
+       if (group == pmx->soc->ngroups) {
+               dev_err(pctldev->dev,
+                       "Pingroup not found for pin %u\n", offset);
+               return -EINVAL;
+       }
+
+       /*
+        * Set input = 1 for the input direction and
+        * tristate = 0 for output direction.
+        */
+       if (input)
+               ret = tegra_pinconfig_froup_set(pctldev, group,
+                                       TEGRA_PINCONF_PARAM_ENABLE_INPUT, 1);
+       else
+               ret = tegra_pinconfig_froup_set(pctldev, group,
+                                       TEGRA_PINCONF_PARAM_TRISTATE, 0);
+       return ret;
+}
+
 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,
        .enable = tegra_pinctrl_enable,
        .disable = tegra_pinctrl_disable,
+       .gpio_request_enable = tegra_pinctrl_gpio_request_enable,
+       .gpio_set_direction = tegra_pinctrl_gpio_set_direction,
 };
 
 static int tegra_pinconf_reg(struct tegra_pmx *pmx,
index 20fbb9e..c29d82a 100644 (file)
@@ -183,6 +183,7 @@ struct tegra_pinctrl_soc_data {
        unsigned nconfig_data;
        int (*suspend)(u32 *pg_data);
        void (*resume)(u32 *pg_data);
+       int (*gpio_request_enable)(unsigned pin);
 };
 
 int tegra_pinctrl_probe(struct platform_device *pdev,