summaryrefslogtreecommitdiff
path: root/drivers/pinctrl
diff options
context:
space:
mode:
authorLaxman Dewangan <ldewangan@nvidia.com>2013-11-07 19:18:29 +0530
committerLaxman Dewangan <ldewangan@nvidia.com>2013-11-08 02:33:55 -0800
commit3893cfbd120398a10b812824c8bebdd89e855bd7 (patch)
tree4f56e47b461a23c0fa4b050c3d4c25648a86d9f5 /drivers/pinctrl
parent6ab1530cac555c34293b4595e95796b9d2baf2b5 (diff)
pinctrl: tegra: add support for soc specific drive configuration
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
Diffstat (limited to 'drivers/pinctrl')
-rw-r--r--drivers/pinctrl/pinctrl-tegra.c82
-rw-r--r--drivers/pinctrl/pinctrl-tegra.h43
2 files changed, 115 insertions, 10 deletions
diff --git a/drivers/pinctrl/pinctrl-tegra.c b/drivers/pinctrl/pinctrl-tegra.c
index f724996fb8ef..7eecbf3de152 100644
--- a/drivers/pinctrl/pinctrl-tegra.c
+++ b/drivers/pinctrl/pinctrl-tegra.c
@@ -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) {
diff --git a/drivers/pinctrl/pinctrl-tegra.h b/drivers/pinctrl/pinctrl-tegra.h
index e2b4ef116a5a..69699f64e8ad 100644
--- a/drivers/pinctrl/pinctrl-tegra.h
+++ b/drivers/pinctrl/pinctrl-tegra.h
@@ -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