diff options
author | Laxman Dewangan <ldewangan@nvidia.com> | 2013-11-07 19:18:29 +0530 |
---|---|---|
committer | Laxman Dewangan <ldewangan@nvidia.com> | 2013-11-08 02:33:55 -0800 |
commit | 3893cfbd120398a10b812824c8bebdd89e855bd7 (patch) | |
tree | 4f56e47b461a23c0fa4b050c3d4c25648a86d9f5 /drivers/pinctrl | |
parent | 6ab1530cac555c34293b4595e95796b9d2baf2b5 (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.c | 82 | ||||
-rw-r--r-- | drivers/pinctrl/pinctrl-tegra.h | 43 |
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 |