aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pinctrl
diff options
context:
space:
mode:
authorOlof Johansson <olof@lixom.net>2012-05-10 02:43:04 -0400
committerOlof Johansson <olof@lixom.net>2012-05-10 02:43:04 -0400
commit7488185d0777ef84be7b365b08037fc7213010f6 (patch)
treec23a3db331693f783228c2f5afb38fed26ac1205 /drivers/pinctrl
parentb664ae6ff92f7ba5c597d4f1b74d478d712c01c4 (diff)
parentaef7704c6cc36db9618603b22194def441d30432 (diff)
Merge branch 'for-3.5/gpio-pinmux' of git://git.kernel.org/pub/scm/linux/kernel/git/swarren/linux-tegra into next/pinctrl
By Stephen Warren via Stephen Warren * 'for-3.5/gpio-pinmux' of git://git.kernel.org/pub/scm/linux/kernel/git/swarren/linux-tegra: pinctrl: tegra: error reporting cleanup pinctrl: tegra: debugfs enhancements pinctrl: tegra: refactor probe handling ARM: dt: tegra20: add pinmux to device tree ARM: dt: tegra cardhu: add pinmux to device tree ARM: tegra: Remove pre-pinctrl pinmux driver ARM: tegra: Switch to new pinctrl driver gpio: tegra: Hide tegra_gpio_enable/disable() ARM: tegra: seaboard: Don't gpio_request() ISL29018_IRQ gpio: tegra: configure pins during irq_set_type ARM: tegra: Remove VBUS_GPIO handling from board files usb: ehci-tegra: Add vbus_gpio to platform data
Diffstat (limited to 'drivers/pinctrl')
-rw-r--r--drivers/pinctrl/pinctrl-tegra.c236
-rw-r--r--drivers/pinctrl/pinctrl-tegra.h23
-rw-r--r--drivers/pinctrl/pinctrl-tegra20.c40
-rw-r--r--drivers/pinctrl/pinctrl-tegra30.c40
4 files changed, 213 insertions, 126 deletions
diff --git a/drivers/pinctrl/pinctrl-tegra.c b/drivers/pinctrl/pinctrl-tegra.c
index 2c98fba01ca5..b6934867d8d3 100644
--- a/drivers/pinctrl/pinctrl-tegra.c
+++ b/drivers/pinctrl/pinctrl-tegra.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * Driver for the NVIDIA Tegra pinmux 2 * Driver for the NVIDIA Tegra pinmux
3 * 3 *
4 * Copyright (c) 2011, NVIDIA CORPORATION. All rights reserved. 4 * Copyright (c) 2011-2012, NVIDIA CORPORATION. All rights reserved.
5 * 5 *
6 * Derived from code: 6 * Derived from code:
7 * Copyright (C) 2010 Google, Inc. 7 * Copyright (C) 2010 Google, Inc.
@@ -22,7 +22,8 @@
22#include <linux/init.h> 22#include <linux/init.h>
23#include <linux/io.h> 23#include <linux/io.h>
24#include <linux/module.h> 24#include <linux/module.h>
25#include <linux/of_device.h> 25#include <linux/of.h>
26#include <linux/platform_device.h>
26#include <linux/pinctrl/machine.h> 27#include <linux/pinctrl/machine.h>
27#include <linux/pinctrl/pinctrl.h> 28#include <linux/pinctrl/pinctrl.h>
28#include <linux/pinctrl/pinmux.h> 29#include <linux/pinctrl/pinmux.h>
@@ -31,10 +32,9 @@
31 32
32#include <mach/pinconf-tegra.h> 33#include <mach/pinconf-tegra.h>
33 34
35#include "core.h"
34#include "pinctrl-tegra.h" 36#include "pinctrl-tegra.h"
35 37
36#define DRIVER_NAME "tegra-pinmux-disabled"
37
38struct tegra_pmx { 38struct tegra_pmx {
39 struct device *dev; 39 struct device *dev;
40 struct pinctrl_dev *pctl; 40 struct pinctrl_dev *pctl;
@@ -83,15 +83,18 @@ static int tegra_pinctrl_get_group_pins(struct pinctrl_dev *pctldev,
83 return 0; 83 return 0;
84} 84}
85 85
86#ifdef CONFIG_DEBUG_FS
86static void tegra_pinctrl_pin_dbg_show(struct pinctrl_dev *pctldev, 87static void tegra_pinctrl_pin_dbg_show(struct pinctrl_dev *pctldev,
87 struct seq_file *s, 88 struct seq_file *s,
88 unsigned offset) 89 unsigned offset)
89{ 90{
90 seq_printf(s, " " DRIVER_NAME); 91 seq_printf(s, " %s", dev_name(pctldev->dev));
91} 92}
93#endif
92 94
93static int reserve_map(struct pinctrl_map **map, unsigned *reserved_maps, 95static int reserve_map(struct device *dev, struct pinctrl_map **map,
94 unsigned *num_maps, unsigned reserve) 96 unsigned *reserved_maps, unsigned *num_maps,
97 unsigned reserve)
95{ 98{
96 unsigned old_num = *reserved_maps; 99 unsigned old_num = *reserved_maps;
97 unsigned new_num = *num_maps + reserve; 100 unsigned new_num = *num_maps + reserve;
@@ -101,8 +104,10 @@ static int reserve_map(struct pinctrl_map **map, unsigned *reserved_maps,
101 return 0; 104 return 0;
102 105
103 new_map = krealloc(*map, sizeof(*new_map) * new_num, GFP_KERNEL); 106 new_map = krealloc(*map, sizeof(*new_map) * new_num, GFP_KERNEL);
104 if (!new_map) 107 if (!new_map) {
108 dev_err(dev, "krealloc(map) failed\n");
105 return -ENOMEM; 109 return -ENOMEM;
110 }
106 111
107 memset(new_map + old_num, 0, (new_num - old_num) * sizeof(*new_map)); 112 memset(new_map + old_num, 0, (new_num - old_num) * sizeof(*new_map));
108 113
@@ -116,7 +121,7 @@ static int add_map_mux(struct pinctrl_map **map, unsigned *reserved_maps,
116 unsigned *num_maps, const char *group, 121 unsigned *num_maps, const char *group,
117 const char *function) 122 const char *function)
118{ 123{
119 if (*num_maps == *reserved_maps) 124 if (WARN_ON(*num_maps == *reserved_maps))
120 return -ENOSPC; 125 return -ENOSPC;
121 126
122 (*map)[*num_maps].type = PIN_MAP_TYPE_MUX_GROUP; 127 (*map)[*num_maps].type = PIN_MAP_TYPE_MUX_GROUP;
@@ -127,19 +132,22 @@ static int add_map_mux(struct pinctrl_map **map, unsigned *reserved_maps,
127 return 0; 132 return 0;
128} 133}
129 134
130static int add_map_configs(struct pinctrl_map **map, unsigned *reserved_maps, 135static int add_map_configs(struct device *dev, struct pinctrl_map **map,
131 unsigned *num_maps, const char *group, 136 unsigned *reserved_maps, unsigned *num_maps,
132 unsigned long *configs, unsigned num_configs) 137 const char *group, unsigned long *configs,
138 unsigned num_configs)
133{ 139{
134 unsigned long *dup_configs; 140 unsigned long *dup_configs;
135 141
136 if (*num_maps == *reserved_maps) 142 if (WARN_ON(*num_maps == *reserved_maps))
137 return -ENOSPC; 143 return -ENOSPC;
138 144
139 dup_configs = kmemdup(configs, num_configs * sizeof(*dup_configs), 145 dup_configs = kmemdup(configs, num_configs * sizeof(*dup_configs),
140 GFP_KERNEL); 146 GFP_KERNEL);
141 if (!dup_configs) 147 if (!dup_configs) {
148 dev_err(dev, "kmemdup(configs) failed\n");
142 return -ENOMEM; 149 return -ENOMEM;
150 }
143 151
144 (*map)[*num_maps].type = PIN_MAP_TYPE_CONFIGS_GROUP; 152 (*map)[*num_maps].type = PIN_MAP_TYPE_CONFIGS_GROUP;
145 (*map)[*num_maps].data.configs.group_or_pin = group; 153 (*map)[*num_maps].data.configs.group_or_pin = group;
@@ -150,8 +158,8 @@ static int add_map_configs(struct pinctrl_map **map, unsigned *reserved_maps,
150 return 0; 158 return 0;
151} 159}
152 160
153static int add_config(unsigned long **configs, unsigned *num_configs, 161static int add_config(struct device *dev, unsigned long **configs,
154 unsigned long config) 162 unsigned *num_configs, unsigned long config)
155{ 163{
156 unsigned old_num = *num_configs; 164 unsigned old_num = *num_configs;
157 unsigned new_num = old_num + 1; 165 unsigned new_num = old_num + 1;
@@ -159,8 +167,10 @@ static int add_config(unsigned long **configs, unsigned *num_configs,
159 167
160 new_configs = krealloc(*configs, sizeof(*new_configs) * new_num, 168 new_configs = krealloc(*configs, sizeof(*new_configs) * new_num,
161 GFP_KERNEL); 169 GFP_KERNEL);
162 if (!new_configs) 170 if (!new_configs) {
171 dev_err(dev, "krealloc(configs) failed\n");
163 return -ENOMEM; 172 return -ENOMEM;
173 }
164 174
165 new_configs[old_num] = config; 175 new_configs[old_num] = config;
166 176
@@ -201,7 +211,8 @@ static const struct cfg_param {
201 {"nvidia,slew-rate-rising", TEGRA_PINCONF_PARAM_SLEW_RATE_RISING}, 211 {"nvidia,slew-rate-rising", TEGRA_PINCONF_PARAM_SLEW_RATE_RISING},
202}; 212};
203 213
204int tegra_pinctrl_dt_subnode_to_map(struct device_node *np, 214int tegra_pinctrl_dt_subnode_to_map(struct device *dev,
215 struct device_node *np,
205 struct pinctrl_map **map, 216 struct pinctrl_map **map,
206 unsigned *reserved_maps, 217 unsigned *reserved_maps,
207 unsigned *num_maps) 218 unsigned *num_maps)
@@ -217,16 +228,25 @@ int tegra_pinctrl_dt_subnode_to_map(struct device_node *np,
217 const char *group; 228 const char *group;
218 229
219 ret = of_property_read_string(np, "nvidia,function", &function); 230 ret = of_property_read_string(np, "nvidia,function", &function);
220 if (ret < 0) 231 if (ret < 0) {
232 /* EINVAL=missing, which is fine since it's optional */
233 if (ret != -EINVAL)
234 dev_err(dev,
235 "could not parse property nvidia,function\n");
221 function = NULL; 236 function = NULL;
237 }
222 238
223 for (i = 0; i < ARRAY_SIZE(cfg_params); i++) { 239 for (i = 0; i < ARRAY_SIZE(cfg_params); i++) {
224 ret = of_property_read_u32(np, cfg_params[i].property, &val); 240 ret = of_property_read_u32(np, cfg_params[i].property, &val);
225 if (!ret) { 241 if (!ret) {
226 config = TEGRA_PINCONF_PACK(cfg_params[i].param, val); 242 config = TEGRA_PINCONF_PACK(cfg_params[i].param, val);
227 ret = add_config(&configs, &num_configs, config); 243 ret = add_config(dev, &configs, &num_configs, config);
228 if (ret < 0) 244 if (ret < 0)
229 goto exit; 245 goto exit;
246 /* EINVAL=missing, which is fine since it's optional */
247 } else if (ret != -EINVAL) {
248 dev_err(dev, "could not parse property %s\n",
249 cfg_params[i].property);
230 } 250 }
231 } 251 }
232 252
@@ -236,11 +256,13 @@ int tegra_pinctrl_dt_subnode_to_map(struct device_node *np,
236 if (num_configs) 256 if (num_configs)
237 reserve++; 257 reserve++;
238 ret = of_property_count_strings(np, "nvidia,pins"); 258 ret = of_property_count_strings(np, "nvidia,pins");
239 if (ret < 0) 259 if (ret < 0) {
260 dev_err(dev, "could not parse property nvidia,pins\n");
240 goto exit; 261 goto exit;
262 }
241 reserve *= ret; 263 reserve *= ret;
242 264
243 ret = reserve_map(map, reserved_maps, num_maps, reserve); 265 ret = reserve_map(dev, map, reserved_maps, num_maps, reserve);
244 if (ret < 0) 266 if (ret < 0)
245 goto exit; 267 goto exit;
246 268
@@ -253,8 +275,9 @@ int tegra_pinctrl_dt_subnode_to_map(struct device_node *np,
253 } 275 }
254 276
255 if (num_configs) { 277 if (num_configs) {
256 ret = add_map_configs(map, reserved_maps, num_maps, 278 ret = add_map_configs(dev, map, reserved_maps,
257 group, configs, num_configs); 279 num_maps, group, configs,
280 num_configs);
258 if (ret < 0) 281 if (ret < 0)
259 goto exit; 282 goto exit;
260 } 283 }
@@ -280,8 +303,8 @@ int tegra_pinctrl_dt_node_to_map(struct pinctrl_dev *pctldev,
280 *num_maps = 0; 303 *num_maps = 0;
281 304
282 for_each_child_of_node(np_config, np) { 305 for_each_child_of_node(np_config, np) {
283 ret = tegra_pinctrl_dt_subnode_to_map(np, map, &reserved_maps, 306 ret = tegra_pinctrl_dt_subnode_to_map(pctldev->dev, np, map,
284 num_maps); 307 &reserved_maps, num_maps);
285 if (ret < 0) { 308 if (ret < 0) {
286 tegra_pinctrl_dt_free_map(pctldev, *map, *num_maps); 309 tegra_pinctrl_dt_free_map(pctldev, *map, *num_maps);
287 return ret; 310 return ret;
@@ -295,7 +318,9 @@ static struct pinctrl_ops tegra_pinctrl_ops = {
295 .get_groups_count = tegra_pinctrl_get_groups_count, 318 .get_groups_count = tegra_pinctrl_get_groups_count,
296 .get_group_name = tegra_pinctrl_get_group_name, 319 .get_group_name = tegra_pinctrl_get_group_name,
297 .get_group_pins = tegra_pinctrl_get_group_pins, 320 .get_group_pins = tegra_pinctrl_get_group_pins,
321#ifdef CONFIG_DEBUG_FS
298 .pin_dbg_show = tegra_pinctrl_pin_dbg_show, 322 .pin_dbg_show = tegra_pinctrl_pin_dbg_show,
323#endif
299 .dt_node_to_map = tegra_pinctrl_dt_node_to_map, 324 .dt_node_to_map = tegra_pinctrl_dt_node_to_map,
300 .dt_free_map = tegra_pinctrl_dt_free_map, 325 .dt_free_map = tegra_pinctrl_dt_free_map,
301}; 326};
@@ -338,14 +363,14 @@ static int tegra_pinctrl_enable(struct pinctrl_dev *pctldev, unsigned function,
338 363
339 g = &pmx->soc->groups[group]; 364 g = &pmx->soc->groups[group];
340 365
341 if (g->mux_reg < 0) 366 if (WARN_ON(g->mux_reg < 0))
342 return -EINVAL; 367 return -EINVAL;
343 368
344 for (i = 0; i < ARRAY_SIZE(g->funcs); i++) { 369 for (i = 0; i < ARRAY_SIZE(g->funcs); i++) {
345 if (g->funcs[i] == function) 370 if (g->funcs[i] == function)
346 break; 371 break;
347 } 372 }
348 if (i == ARRAY_SIZE(g->funcs)) 373 if (WARN_ON(i == ARRAY_SIZE(g->funcs)))
349 return -EINVAL; 374 return -EINVAL;
350 375
351 val = pmx_readl(pmx, g->mux_bank, g->mux_reg); 376 val = pmx_readl(pmx, g->mux_bank, g->mux_reg);
@@ -365,7 +390,7 @@ static void tegra_pinctrl_disable(struct pinctrl_dev *pctldev,
365 390
366 g = &pmx->soc->groups[group]; 391 g = &pmx->soc->groups[group];
367 392
368 if (g->mux_reg < 0) 393 if (WARN_ON(g->mux_reg < 0))
369 return; 394 return;
370 395
371 val = pmx_readl(pmx, g->mux_bank, g->mux_reg); 396 val = pmx_readl(pmx, g->mux_bank, g->mux_reg);
@@ -385,6 +410,7 @@ static struct pinmux_ops tegra_pinmux_ops = {
385static int tegra_pinconf_reg(struct tegra_pmx *pmx, 410static int tegra_pinconf_reg(struct tegra_pmx *pmx,
386 const struct tegra_pingroup *g, 411 const struct tegra_pingroup *g,
387 enum tegra_pinconf_param param, 412 enum tegra_pinconf_param param,
413 bool report_err,
388 s8 *bank, s16 *reg, s8 *bit, s8 *width) 414 s8 *bank, s16 *reg, s8 *bit, s8 *width)
389{ 415{
390 switch (param) { 416 switch (param) {
@@ -472,9 +498,10 @@ static int tegra_pinconf_reg(struct tegra_pmx *pmx,
472 } 498 }
473 499
474 if (*reg < 0) { 500 if (*reg < 0) {
475 dev_err(pmx->dev, 501 if (report_err)
476 "Config param %04x not supported on group %s\n", 502 dev_err(pmx->dev,
477 param, g->name); 503 "Config param %04x not supported on group %s\n",
504 param, g->name);
478 return -ENOTSUPP; 505 return -ENOTSUPP;
479 } 506 }
480 507
@@ -484,12 +511,14 @@ static int tegra_pinconf_reg(struct tegra_pmx *pmx,
484static int tegra_pinconf_get(struct pinctrl_dev *pctldev, 511static int tegra_pinconf_get(struct pinctrl_dev *pctldev,
485 unsigned pin, unsigned long *config) 512 unsigned pin, unsigned long *config)
486{ 513{
514 dev_err(pctldev->dev, "pin_config_get op not supported\n");
487 return -ENOTSUPP; 515 return -ENOTSUPP;
488} 516}
489 517
490static int tegra_pinconf_set(struct pinctrl_dev *pctldev, 518static int tegra_pinconf_set(struct pinctrl_dev *pctldev,
491 unsigned pin, unsigned long config) 519 unsigned pin, unsigned long config)
492{ 520{
521 dev_err(pctldev->dev, "pin_config_set op not supported\n");
493 return -ENOTSUPP; 522 return -ENOTSUPP;
494} 523}
495 524
@@ -507,7 +536,8 @@ static int tegra_pinconf_group_get(struct pinctrl_dev *pctldev,
507 536
508 g = &pmx->soc->groups[group]; 537 g = &pmx->soc->groups[group];
509 538
510 ret = tegra_pinconf_reg(pmx, g, param, &bank, &reg, &bit, &width); 539 ret = tegra_pinconf_reg(pmx, g, param, true, &bank, &reg, &bit,
540 &width);
511 if (ret < 0) 541 if (ret < 0)
512 return ret; 542 return ret;
513 543
@@ -534,7 +564,8 @@ static int tegra_pinconf_group_set(struct pinctrl_dev *pctldev,
534 564
535 g = &pmx->soc->groups[group]; 565 g = &pmx->soc->groups[group];
536 566
537 ret = tegra_pinconf_reg(pmx, g, param, &bank, &reg, &bit, &width); 567 ret = tegra_pinconf_reg(pmx, g, param, true, &bank, &reg, &bit,
568 &width);
538 if (ret < 0) 569 if (ret < 0)
539 return ret; 570 return ret;
540 571
@@ -542,8 +573,10 @@ static int tegra_pinconf_group_set(struct pinctrl_dev *pctldev,
542 573
543 /* LOCK can't be cleared */ 574 /* LOCK can't be cleared */
544 if (param == TEGRA_PINCONF_PARAM_LOCK) { 575 if (param == TEGRA_PINCONF_PARAM_LOCK) {
545 if ((val & BIT(bit)) && !arg) 576 if ((val & BIT(bit)) && !arg) {
577 dev_err(pctldev->dev, "LOCK bit cannot be cleared\n");
546 return -EINVAL; 578 return -EINVAL;
579 }
547 } 580 }
548 581
549 /* Special-case Boolean values; allow any non-zero as true */ 582 /* Special-case Boolean values; allow any non-zero as true */
@@ -552,8 +585,12 @@ static int tegra_pinconf_group_set(struct pinctrl_dev *pctldev,
552 585
553 /* Range-check user-supplied value */ 586 /* Range-check user-supplied value */
554 mask = (1 << width) - 1; 587 mask = (1 << width) - 1;
555 if (arg & ~mask) 588 if (arg & ~mask) {
589 dev_err(pctldev->dev,
590 "config %lx: %x too big for %d bit register\n",
591 config, arg, width);
556 return -EINVAL; 592 return -EINVAL;
593 }
557 594
558 /* Update register */ 595 /* Update register */
559 val &= ~(mask << bit); 596 val &= ~(mask << bit);
@@ -563,23 +600,78 @@ static int tegra_pinconf_group_set(struct pinctrl_dev *pctldev,
563 return 0; 600 return 0;
564} 601}
565 602
603#ifdef CONFIG_DEBUG_FS
566static void tegra_pinconf_dbg_show(struct pinctrl_dev *pctldev, 604static void tegra_pinconf_dbg_show(struct pinctrl_dev *pctldev,
567 struct seq_file *s, unsigned offset) 605 struct seq_file *s, unsigned offset)
568{ 606{
569} 607}
570 608
609static const char *strip_prefix(const char *s)
610{
611 const char *comma = strchr(s, ',');
612 if (!comma)
613 return s;
614
615 return comma + 1;
616}
617
571static void tegra_pinconf_group_dbg_show(struct pinctrl_dev *pctldev, 618static void tegra_pinconf_group_dbg_show(struct pinctrl_dev *pctldev,
572 struct seq_file *s, unsigned selector) 619 struct seq_file *s, unsigned group)
620{
621 struct tegra_pmx *pmx = pinctrl_dev_get_drvdata(pctldev);
622 const struct tegra_pingroup *g;
623 int i, ret;
624 s8 bank, bit, width;
625 s16 reg;
626 u32 val;
627
628 g = &pmx->soc->groups[group];
629
630 for (i = 0; i < ARRAY_SIZE(cfg_params); i++) {
631 ret = tegra_pinconf_reg(pmx, g, cfg_params[i].param, false,
632 &bank, &reg, &bit, &width);
633 if (ret < 0)
634 continue;
635
636 val = pmx_readl(pmx, bank, reg);
637 val >>= bit;
638 val &= (1 << width) - 1;
639
640 seq_printf(s, "\n\t%s=%u",
641 strip_prefix(cfg_params[i].property), val);
642 }
643}
644
645static void tegra_pinconf_config_dbg_show(struct pinctrl_dev *pctldev,
646 struct seq_file *s,
647 unsigned long config)
573{ 648{
649 enum tegra_pinconf_param param = TEGRA_PINCONF_UNPACK_PARAM(config);
650 u16 arg = TEGRA_PINCONF_UNPACK_ARG(config);
651 const char *pname = "unknown";
652 int i;
653
654 for (i = 0; i < ARRAY_SIZE(cfg_params); i++) {
655 if (cfg_params[i].param == param) {
656 pname = cfg_params[i].property;
657 break;
658 }
659 }
660
661 seq_printf(s, "%s=%d", strip_prefix(pname), arg);
574} 662}
663#endif
575 664
576struct pinconf_ops tegra_pinconf_ops = { 665struct pinconf_ops tegra_pinconf_ops = {
577 .pin_config_get = tegra_pinconf_get, 666 .pin_config_get = tegra_pinconf_get,
578 .pin_config_set = tegra_pinconf_set, 667 .pin_config_set = tegra_pinconf_set,
579 .pin_config_group_get = tegra_pinconf_group_get, 668 .pin_config_group_get = tegra_pinconf_group_get,
580 .pin_config_group_set = tegra_pinconf_group_set, 669 .pin_config_group_set = tegra_pinconf_group_set,
670#ifdef CONFIG_DEBUG_FS
581 .pin_config_dbg_show = tegra_pinconf_dbg_show, 671 .pin_config_dbg_show = tegra_pinconf_dbg_show,
582 .pin_config_group_dbg_show = tegra_pinconf_group_dbg_show, 672 .pin_config_group_dbg_show = tegra_pinconf_group_dbg_show,
673 .pin_config_config_dbg_show = tegra_pinconf_config_dbg_show,
674#endif
583}; 675};
584 676
585static struct pinctrl_gpio_range tegra_pinctrl_gpio_range = { 677static struct pinctrl_gpio_range tegra_pinctrl_gpio_range = {
@@ -589,60 +681,29 @@ static struct pinctrl_gpio_range tegra_pinctrl_gpio_range = {
589}; 681};
590 682
591static struct pinctrl_desc tegra_pinctrl_desc = { 683static struct pinctrl_desc tegra_pinctrl_desc = {
592 .name = DRIVER_NAME,
593 .pctlops = &tegra_pinctrl_ops, 684 .pctlops = &tegra_pinctrl_ops,
594 .pmxops = &tegra_pinmux_ops, 685 .pmxops = &tegra_pinmux_ops,
595 .confops = &tegra_pinconf_ops, 686 .confops = &tegra_pinconf_ops,
596 .owner = THIS_MODULE, 687 .owner = THIS_MODULE,
597}; 688};
598 689
599static struct of_device_id tegra_pinctrl_of_match[] __devinitdata = { 690int __devinit tegra_pinctrl_probe(struct platform_device *pdev,
600#ifdef CONFIG_PINCTRL_TEGRA20 691 const struct tegra_pinctrl_soc_data *soc_data)
601 {
602 .compatible = "nvidia,tegra20-pinmux-disabled",
603 .data = tegra20_pinctrl_init,
604 },
605#endif
606#ifdef CONFIG_PINCTRL_TEGRA30
607 {
608 .compatible = "nvidia,tegra30-pinmux-disabled",
609 .data = tegra30_pinctrl_init,
610 },
611#endif
612 {},
613};
614
615static int __devinit tegra_pinctrl_probe(struct platform_device *pdev)
616{ 692{
617 const struct of_device_id *match;
618 tegra_pinctrl_soc_initf initf = NULL;
619 struct tegra_pmx *pmx; 693 struct tegra_pmx *pmx;
620 struct resource *res; 694 struct resource *res;
621 int i; 695 int i;
622 696
623 match = of_match_device(tegra_pinctrl_of_match, &pdev->dev);
624 if (match)
625 initf = (tegra_pinctrl_soc_initf)match->data;
626#ifdef CONFIG_PINCTRL_TEGRA20
627 if (!initf)
628 initf = tegra20_pinctrl_init;
629#endif
630 if (!initf) {
631 dev_err(&pdev->dev,
632 "Could not determine SoC-specific init func\n");
633 return -EINVAL;
634 }
635
636 pmx = devm_kzalloc(&pdev->dev, sizeof(*pmx), GFP_KERNEL); 697 pmx = devm_kzalloc(&pdev->dev, sizeof(*pmx), GFP_KERNEL);
637 if (!pmx) { 698 if (!pmx) {
638 dev_err(&pdev->dev, "Can't alloc tegra_pmx\n"); 699 dev_err(&pdev->dev, "Can't alloc tegra_pmx\n");
639 return -ENOMEM; 700 return -ENOMEM;
640 } 701 }
641 pmx->dev = &pdev->dev; 702 pmx->dev = &pdev->dev;
642 703 pmx->soc = soc_data;
643 (*initf)(&pmx->soc);
644 704
645 tegra_pinctrl_gpio_range.npins = pmx->soc->ngpios; 705 tegra_pinctrl_gpio_range.npins = pmx->soc->ngpios;
706 tegra_pinctrl_desc.name = dev_name(&pdev->dev);
646 tegra_pinctrl_desc.pins = pmx->soc->pins; 707 tegra_pinctrl_desc.pins = pmx->soc->pins;
647 tegra_pinctrl_desc.npins = pmx->soc->npins; 708 tegra_pinctrl_desc.npins = pmx->soc->npins;
648 709
@@ -697,8 +758,9 @@ static int __devinit tegra_pinctrl_probe(struct platform_device *pdev)
697 758
698 return 0; 759 return 0;
699} 760}
761EXPORT_SYMBOL_GPL(tegra_pinctrl_probe);
700 762
701static int __devexit tegra_pinctrl_remove(struct platform_device *pdev) 763int __devexit tegra_pinctrl_remove(struct platform_device *pdev)
702{ 764{
703 struct tegra_pmx *pmx = platform_get_drvdata(pdev); 765 struct tegra_pmx *pmx = platform_get_drvdata(pdev);
704 766
@@ -707,30 +769,4 @@ static int __devexit tegra_pinctrl_remove(struct platform_device *pdev)
707 769
708 return 0; 770 return 0;
709} 771}
710 772EXPORT_SYMBOL_GPL(tegra_pinctrl_remove);
711static struct platform_driver tegra_pinctrl_driver = {
712 .driver = {
713 .name = DRIVER_NAME,
714 .owner = THIS_MODULE,
715 .of_match_table = tegra_pinctrl_of_match,
716 },
717 .probe = tegra_pinctrl_probe,
718 .remove = __devexit_p(tegra_pinctrl_remove),
719};
720
721static int __init tegra_pinctrl_init(void)
722{
723 return platform_driver_register(&tegra_pinctrl_driver);
724}
725arch_initcall(tegra_pinctrl_init);
726
727static void __exit tegra_pinctrl_exit(void)
728{
729 platform_driver_unregister(&tegra_pinctrl_driver);
730}
731module_exit(tegra_pinctrl_exit);
732
733MODULE_AUTHOR("Stephen Warren <swarren@nvidia.com>");
734MODULE_DESCRIPTION("NVIDIA Tegra pinctrl driver");
735MODULE_LICENSE("GPL v2");
736MODULE_DEVICE_TABLE(of, tegra_pinctrl_of_match);
diff --git a/drivers/pinctrl/pinctrl-tegra.h b/drivers/pinctrl/pinctrl-tegra.h
index 782c795326ef..705c007a38cc 100644
--- a/drivers/pinctrl/pinctrl-tegra.h
+++ b/drivers/pinctrl/pinctrl-tegra.h
@@ -139,25 +139,8 @@ struct tegra_pinctrl_soc_data {
139 unsigned ngroups; 139 unsigned ngroups;
140}; 140};
141 141
142/** 142int tegra_pinctrl_probe(struct platform_device *pdev,
143 * tegra_pinctrl_soc_initf() - Retrieve pin controller details for a SoC. 143 const struct tegra_pinctrl_soc_data *soc_data);
144 * @soc_data: This pointer must be updated to point at a struct containing 144int tegra_pinctrl_remove(struct platform_device *pdev);
145 * details of the SoC.
146 */
147typedef void (*tegra_pinctrl_soc_initf)(
148 const struct tegra_pinctrl_soc_data **soc_data);
149
150/**
151 * tegra20_pinctrl_init() - Retrieve pin controller details for Tegra20
152 * @soc_data: This pointer will be updated to point at a struct containing
153 * details of Tegra20's pin controller.
154 */
155void tegra20_pinctrl_init(const struct tegra_pinctrl_soc_data **soc_data);
156/**
157 * tegra30_pinctrl_init() - Retrieve pin controller details for Tegra20
158 * @soc_data: This pointer will be updated to point at a struct containing
159 * details of Tegra30's pin controller.
160 */
161void tegra30_pinctrl_init(const struct tegra_pinctrl_soc_data **soc_data);
162 145
163#endif 146#endif
diff --git a/drivers/pinctrl/pinctrl-tegra20.c b/drivers/pinctrl/pinctrl-tegra20.c
index f69ff96aa292..a74f9a568536 100644
--- a/drivers/pinctrl/pinctrl-tegra20.c
+++ b/drivers/pinctrl/pinctrl-tegra20.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * Pinctrl data for the NVIDIA Tegra20 pinmux 2 * Pinctrl data for the NVIDIA Tegra20 pinmux
3 * 3 *
4 * Copyright (c) 2011, NVIDIA CORPORATION. All rights reserved. 4 * Copyright (c) 2011-2012, NVIDIA CORPORATION. All rights reserved.
5 * 5 *
6 * Derived from code: 6 * Derived from code:
7 * Copyright (C) 2010 Google, Inc. 7 * Copyright (C) 2010 Google, Inc.
@@ -17,6 +17,8 @@
17 * more details. 17 * more details.
18 */ 18 */
19 19
20#include <linux/module.h>
21#include <linux/of.h>
20#include <linux/platform_device.h> 22#include <linux/platform_device.h>
21#include <linux/pinctrl/pinctrl.h> 23#include <linux/pinctrl/pinctrl.h>
22#include <linux/pinctrl/pinmux.h> 24#include <linux/pinctrl/pinmux.h>
@@ -2854,7 +2856,39 @@ static const struct tegra_pinctrl_soc_data tegra20_pinctrl = {
2854 .ngroups = ARRAY_SIZE(tegra20_groups), 2856 .ngroups = ARRAY_SIZE(tegra20_groups),
2855}; 2857};
2856 2858
2857void __devinit tegra20_pinctrl_init(const struct tegra_pinctrl_soc_data **soc) 2859static int __devinit tegra20_pinctrl_probe(struct platform_device *pdev)
2858{ 2860{
2859 *soc = &tegra20_pinctrl; 2861 return tegra_pinctrl_probe(pdev, &tegra20_pinctrl);
2860} 2862}
2863
2864static struct of_device_id tegra20_pinctrl_of_match[] __devinitdata = {
2865 { .compatible = "nvidia,tegra20-pinmux", },
2866 { },
2867};
2868
2869static struct platform_driver tegra20_pinctrl_driver = {
2870 .driver = {
2871 .name = "tegra20-pinctrl",
2872 .owner = THIS_MODULE,
2873 .of_match_table = tegra20_pinctrl_of_match,
2874 },
2875 .probe = tegra20_pinctrl_probe,
2876 .remove = __devexit_p(tegra_pinctrl_remove),
2877};
2878
2879static int __init tegra20_pinctrl_init(void)
2880{
2881 return platform_driver_register(&tegra20_pinctrl_driver);
2882}
2883arch_initcall(tegra20_pinctrl_init);
2884
2885static void __exit tegra20_pinctrl_exit(void)
2886{
2887 platform_driver_unregister(&tegra20_pinctrl_driver);
2888}
2889module_exit(tegra20_pinctrl_exit);
2890
2891MODULE_AUTHOR("Stephen Warren <swarren@nvidia.com>");
2892MODULE_DESCRIPTION("NVIDIA Tegra20 pinctrl driver");
2893MODULE_LICENSE("GPL v2");
2894MODULE_DEVICE_TABLE(of, tegra20_pinctrl_of_match);
diff --git a/drivers/pinctrl/pinctrl-tegra30.c b/drivers/pinctrl/pinctrl-tegra30.c
index 4d7571d4a431..0386fdf0da16 100644
--- a/drivers/pinctrl/pinctrl-tegra30.c
+++ b/drivers/pinctrl/pinctrl-tegra30.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * Pinctrl data for the NVIDIA Tegra30 pinmux 2 * Pinctrl data for the NVIDIA Tegra30 pinmux
3 * 3 *
4 * Copyright (c) 2011, NVIDIA CORPORATION. All rights reserved. 4 * Copyright (c) 2011-2012, NVIDIA CORPORATION. All rights reserved.
5 * 5 *
6 * This program is free software; you can redistribute it and/or modify it 6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms and conditions of the GNU General Public License, 7 * under the terms and conditions of the GNU General Public License,
@@ -13,6 +13,8 @@
13 * more details. 13 * more details.
14 */ 14 */
15 15
16#include <linux/module.h>
17#include <linux/of.h>
16#include <linux/platform_device.h> 18#include <linux/platform_device.h>
17#include <linux/pinctrl/pinctrl.h> 19#include <linux/pinctrl/pinctrl.h>
18#include <linux/pinctrl/pinmux.h> 20#include <linux/pinctrl/pinmux.h>
@@ -3720,7 +3722,39 @@ static const struct tegra_pinctrl_soc_data tegra30_pinctrl = {
3720 .ngroups = ARRAY_SIZE(tegra30_groups), 3722 .ngroups = ARRAY_SIZE(tegra30_groups),
3721}; 3723};
3722 3724
3723void __devinit tegra30_pinctrl_init(const struct tegra_pinctrl_soc_data **soc) 3725static int __devinit tegra30_pinctrl_probe(struct platform_device *pdev)
3724{ 3726{
3725 *soc = &tegra30_pinctrl; 3727 return tegra_pinctrl_probe(pdev, &tegra30_pinctrl);
3726} 3728}
3729
3730static struct of_device_id tegra30_pinctrl_of_match[] __devinitdata = {
3731 { .compatible = "nvidia,tegra30-pinmux", },
3732 { },
3733};
3734
3735static struct platform_driver tegra30_pinctrl_driver = {
3736 .driver = {
3737 .name = "tegra30-pinctrl",
3738 .owner = THIS_MODULE,
3739 .of_match_table = tegra30_pinctrl_of_match,
3740 },
3741 .probe = tegra30_pinctrl_probe,
3742 .remove = __devexit_p(tegra_pinctrl_remove),
3743};
3744
3745static int __init tegra30_pinctrl_init(void)
3746{
3747 return platform_driver_register(&tegra30_pinctrl_driver);
3748}
3749arch_initcall(tegra30_pinctrl_init);
3750
3751static void __exit tegra30_pinctrl_exit(void)
3752{
3753 platform_driver_unregister(&tegra30_pinctrl_driver);
3754}
3755module_exit(tegra30_pinctrl_exit);
3756
3757MODULE_AUTHOR("Stephen Warren <swarren@nvidia.com>");
3758MODULE_DESCRIPTION("NVIDIA Tegra30 pinctrl driver");
3759MODULE_LICENSE("GPL v2");
3760MODULE_DEVICE_TABLE(of, tegra30_pinctrl_of_match);