pinctrl: tegra: add support for soc specific drive configuration
Laxman Dewangan [Thu, 7 Nov 2013 13:48:29 +0000 (18:48 +0530)]
Every soc have their default driver configuration based on
characterization recommendation.

Add support to configure the drive group during pincontrol
driver initialisation.

Change-Id: I9af34c65feb77a5bb8af15a08dffe246e8c8eb9d
Signed-off-by: Laxman Dewangan <ldewangan@nvidia.com>
Reviewed-on: http://git-master/r/327754

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

index f724996..7eecbf3 100644 (file)
@@ -781,6 +781,75 @@ static struct syscore_ops pinctrl_syscore_ops = {
 
 #endif
 
+static int tegra_pinctrl_get_group(struct tegra_pmx *pmx, const char *name)
+{
+       int i;
+
+       for (i = 0; i< pmx->soc->ngroups; ++i) {
+               if (!strcmp(pmx->soc->groups[i].name, name))
+                       return i;
+       }
+       return -EINVAL;
+}
+
+int tegra_pinctrl_set_config(struct pinctrl_dev *pctldev,
+       int pg, int param, int val)
+{
+       unsigned long config;
+
+       config = TEGRA_PINCONF_PACK(param, val);
+       return tegra_pinconf_group_set(pmx->pctl, pg, config);
+}
+
+static void tegra_pinctrl_default_soc_init(struct tegra_pmx *pmx)
+{
+       struct tegra_pinctrl_group_config_data *cdata;
+       int group;
+       int i;
+
+       for (i = 0; i < pmx->soc->nconfig_data; ++i) {
+               cdata = &pmx->soc->config_data[i];
+               group = tegra_pinctrl_get_group(pmx, cdata->name);
+               if (group < 0) {
+                       dev_warn(pmx->dev, "Group name %s not found\n",
+                               cdata->name);
+                       continue;
+               }
+
+               tegra_pinctrl_set_config(pmx->pctl, group,
+                               TEGRA_PINCONF_PARAM_HIGH_SPEED_MODE,
+                               cdata->high_speed_mode);
+
+               tegra_pinctrl_set_config(pmx->pctl, group,
+                               TEGRA_PINCONF_PARAM_SCHMITT,
+                               cdata->schmitt);
+
+               tegra_pinctrl_set_config(pmx->pctl, group,
+                               TEGRA_PINCONF_PARAM_LOW_POWER_MODE,
+                               cdata->low_power_mode);
+
+               tegra_pinctrl_set_config(pmx->pctl, group,
+                               TEGRA_PINCONF_PARAM_DRIVE_DOWN_STRENGTH,
+                               cdata->pull_down_strength);
+
+               tegra_pinctrl_set_config(pmx->pctl, group,
+                               TEGRA_PINCONF_PARAM_DRIVE_UP_STRENGTH,
+                               cdata->pull_up_strength);
+
+               tegra_pinctrl_set_config(pmx->pctl, group,
+                               TEGRA_PINCONF_PARAM_SLEW_RATE_FALLING,
+                               cdata->slew_rate_falling);
+
+               tegra_pinctrl_set_config(pmx->pctl, group,
+                               TEGRA_PINCONF_PARAM_SLEW_RATE_RISING,
+                               cdata->slew_rate_rising);
+
+               tegra_pinctrl_set_config(pmx->pctl, group,
+                               TEGRA_PINCONF_PARAM_DRIVE_TYPE,
+                               cdata->drive_type);
+       }
+}
+
 int tegra_pinctrl_probe(struct platform_device *pdev,
                        const struct tegra_pinctrl_soc_data *soc_data)
 {
@@ -800,7 +869,7 @@ int tegra_pinctrl_probe(struct platform_device *pdev,
        for (i = 0; i < pmx->soc->ngroups; ++i) {
                if (pmx->soc->groups[i].drv_reg < 0)
                        continue;
-               pmx->drive_group_start_index =i;
+               pmx->drive_group_start_index = i;
                break;
        }
 
@@ -877,6 +946,8 @@ int tegra_pinctrl_probe(struct platform_device *pdev,
 
        platform_set_drvdata(pdev, pmx);
 
+       tegra_pinctrl_default_soc_init(pmx);
+
 #ifdef CONFIG_PM_SLEEP
        register_syscore_ops(&pinctrl_syscore_ops);
 #endif
@@ -1220,15 +1291,6 @@ int tegra_pinctrl_get_func(int pg)
        return g->funcs_non_dt[mux];
 }
 
-int tegra_pinctrl_set_config(struct pinctrl_dev *pctldev,
-       int pg, int param, int val)
-{
-       unsigned long config;
-
-       config = TEGRA_PINCONF_PACK(param, val);
-       return tegra_pinconf_group_set(pmx->pctl, pg, config);
-}
-
 int tegra_pinctrl_set_tristate(int pg, int tristate)
 {
        if (!pmx) {
index e2b4ef1..69699f6 100644 (file)
@@ -133,6 +133,29 @@ struct tegra_pingroup {
        const char *dev_id;
 };
 
+/* struct tegra_pinctrl_driver_config_data: Drive pingroup default data.
+ * @name: Name of the group;
+ * @high_speed_mode: Enable high speed mode
+ * @schmitt: Enable schimit.
+ * @low_power_mode: Low power mode value.
+ * @pull_down_strength: Pull down strength.
+ * @pull_up_strength: Pull up strength.
+ * @slew_rate_rising: Rising slew rate.
+ * @slew_rate_falling: Falling slew rate.
+ * @drive_type: Drive type.
+ */
+struct tegra_pinctrl_group_config_data {
+       const char *name;
+       int high_speed_mode;
+       int schmitt;
+       int low_power_mode;
+       int pull_down_strength;
+       int pull_up_strength;
+       int slew_rate_rising;
+       int slew_rate_falling;
+       int drive_type;
+};
+
 /**
  * struct tegra_pinctrl_soc_data - Tegra pin controller driver configuration
  * @ngpios:    The number of GPIO pins the pin controller HW affects.
@@ -145,6 +168,8 @@ struct tegra_pingroup {
  * @nfunctions:        The numbmer of entries in @functions.
  * @groups:    An array describing all pin groups the pin SoC supports.
  * @ngroups:   The numbmer of entries in @groups.
+ * @config_data: List of configuration data which is SoC specific.
+ * @nconfig_data: Number of config data.
  */
 struct tegra_pinctrl_soc_data {
        unsigned ngpios;
@@ -154,6 +179,8 @@ struct tegra_pinctrl_soc_data {
        unsigned nfunctions;
        const struct tegra_pingroup *groups;
        unsigned ngroups;
+       struct tegra_pinctrl_group_config_data *config_data;
+       unsigned nconfig_data;
        int (*suspend)(u32 *pg_data);
        void (*resume)(u32 *pg_data);
 };
@@ -165,4 +192,20 @@ int tegra_pinctrl_remove(struct platform_device *pdev);
 u32 tegra_pinctrl_readl(u32 bank, u32 reg);
 void tegra_pinctrl_writel(u32 val, u32 bank, u32 reg);
 
+/* Some macro for usage */
+#define TEGRA_PINCTRL_SET_DRIVE(_name, _hsm, _schmitt, _drive,         \
+       _pulldn_drive, _pullup_drive, _pulldn_slew, _pullup_slew,       \
+       _drive_type)                                                    \
+       {                                                               \
+               .name = _name,                                          \
+               .high_speed_mode = _hsm,                                \
+               .schmitt = _schmitt,                                    \
+               .low_power_mode = _drive,                               \
+               .pull_down_strength = _pulldn_drive,                    \
+               .pull_up_strength = _pullup_drive,                      \
+               .slew_rate_rising = _pullup_slew,                       \
+               .slew_rate_falling = _pulldn_slew,                      \
+               .drive_type = _drive_type,                              \
+       }
+
 #endif