summaryrefslogtreecommitdiff
path: root/drivers/pinctrl/pinctrl-tegra.c
diff options
context:
space:
mode:
authorStephen Warren <swarren@nvidia.com>2014-03-07 19:22:16 (GMT)
committerLinus Walleij <linus.walleij@linaro.org>2014-03-12 14:23:41 (GMT)
commitce4362546612c00a059c255f5c55373d6ee1022a (patch)
tree88d22d243ae5e6b467caaeb7ab07af6f20f57632 /drivers/pinctrl/pinctrl-tegra.c
parentedfab368c8087ae574d6fa49fdc85068a116b79b (diff)
downloadlinux-ce4362546612c00a059c255f5c55373d6ee1022a.tar.xz
pinctrl: tegra: dynamically calculate function list of groups
The per-SoC data structures for Tegra pinctrl stored some information in a redundant way. Specifically, the list of groups that each function could be muxed onto was stored once explicitly, and also as part of the definition of each group. Eliminate this redundancy, and calculate each function's list of valid groups at pinctrl probe time. This removes thousands of lines of code from the pinctrl driver and ~16K from the vmlinux binary size, and adds only about 500uS to the boot process (on Tegra30; newer SoCs will likely be faster still). Signed-off-by: Stephen Warren <swarren@nvidia.com> Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Diffstat (limited to 'drivers/pinctrl/pinctrl-tegra.c')
-rw-r--r--drivers/pinctrl/pinctrl-tegra.c38
1 files changed, 38 insertions, 0 deletions
diff --git a/drivers/pinctrl/pinctrl-tegra.c b/drivers/pinctrl/pinctrl-tegra.c
index e767355..6545809 100644
--- a/drivers/pinctrl/pinctrl-tegra.c
+++ b/drivers/pinctrl/pinctrl-tegra.c
@@ -39,6 +39,7 @@ struct tegra_pmx {
struct pinctrl_dev *pctl;
const struct tegra_pinctrl_soc_data *soc;
+ const char **group_pins;
int nbanks;
void __iomem **regs;
@@ -620,6 +621,8 @@ int tegra_pinctrl_probe(struct platform_device *pdev,
struct tegra_pmx *pmx;
struct resource *res;
int i;
+ const char **group_pins;
+ int fn, gn, gfn;
pmx = devm_kzalloc(&pdev->dev, sizeof(*pmx), GFP_KERNEL);
if (!pmx) {
@@ -629,6 +632,41 @@ int tegra_pinctrl_probe(struct platform_device *pdev,
pmx->dev = &pdev->dev;
pmx->soc = soc_data;
+ /*
+ * Each mux group will appear in 4 functions' list of groups.
+ * This over-allocates slightly, since not all groups are mux groups.
+ */
+ pmx->group_pins = devm_kzalloc(&pdev->dev,
+ soc_data->ngroups * 4 * sizeof(*pmx->group_pins),
+ GFP_KERNEL);
+ if (!pmx->group_pins)
+ return -ENOMEM;
+
+ group_pins = pmx->group_pins;
+ for (fn = 0; fn < soc_data->nfunctions; fn++) {
+ struct tegra_function *func = &soc_data->functions[fn];
+
+ func->groups = group_pins;
+
+ for (gn = 0; gn < soc_data->ngroups; gn++) {
+ const struct tegra_pingroup *g = &soc_data->groups[gn];
+
+ if (g->mux_reg == -1)
+ continue;
+
+ for (gfn = 0; gfn < 4; gfn++)
+ if (g->funcs[gfn] == fn)
+ break;
+ if (gfn == 4)
+ continue;
+
+ BUG_ON(group_pins - pmx->group_pins >=
+ soc_data->ngroups * 4);
+ *group_pins++ = g->name;
+ func->ngroups++;
+ }
+ }
+
tegra_pinctrl_gpio_range.npins = pmx->soc->ngpios;
tegra_pinctrl_desc.name = dev_name(&pdev->dev);
tegra_pinctrl_desc.pins = pmx->soc->pins;