diff options
author | Olof Johansson <olof@lixom.net> | 2012-05-10 02:43:04 -0400 |
---|---|---|
committer | Olof Johansson <olof@lixom.net> | 2012-05-10 02:43:04 -0400 |
commit | 7488185d0777ef84be7b365b08037fc7213010f6 (patch) | |
tree | c23a3db331693f783228c2f5afb38fed26ac1205 /drivers/pinctrl | |
parent | b664ae6ff92f7ba5c597d4f1b74d478d712c01c4 (diff) | |
parent | aef7704c6cc36db9618603b22194def441d30432 (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.c | 236 | ||||
-rw-r--r-- | drivers/pinctrl/pinctrl-tegra.h | 23 | ||||
-rw-r--r-- | drivers/pinctrl/pinctrl-tegra20.c | 40 | ||||
-rw-r--r-- | drivers/pinctrl/pinctrl-tegra30.c | 40 |
4 files changed, 213 insertions, 126 deletions
diff --git a/drivers/pinctrl/pinctrl-tegra.c b/drivers/pinctrl/pinctrl-tegra.c index 2c98fba01ca..b6934867d8d 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 | |||
38 | struct tegra_pmx { | 38 | struct 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 | ||
86 | static void tegra_pinctrl_pin_dbg_show(struct pinctrl_dev *pctldev, | 87 | static 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 | ||
93 | static int reserve_map(struct pinctrl_map **map, unsigned *reserved_maps, | 95 | static 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 | ||
130 | static int add_map_configs(struct pinctrl_map **map, unsigned *reserved_maps, | 135 | static 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 | ||
153 | static int add_config(unsigned long **configs, unsigned *num_configs, | 161 | static 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 | ||
204 | int tegra_pinctrl_dt_subnode_to_map(struct device_node *np, | 214 | int 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 = { | |||
385 | static int tegra_pinconf_reg(struct tegra_pmx *pmx, | 410 | static 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, | |||
484 | static int tegra_pinconf_get(struct pinctrl_dev *pctldev, | 511 | static 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 | ||
490 | static int tegra_pinconf_set(struct pinctrl_dev *pctldev, | 518 | static 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, ®, &bit, &width); | 539 | ret = tegra_pinconf_reg(pmx, g, param, true, &bank, ®, &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, ®, &bit, &width); | 567 | ret = tegra_pinconf_reg(pmx, g, param, true, &bank, ®, &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 | ||
566 | static void tegra_pinconf_dbg_show(struct pinctrl_dev *pctldev, | 604 | static 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 | ||
609 | static 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 | |||
571 | static void tegra_pinconf_group_dbg_show(struct pinctrl_dev *pctldev, | 618 | static 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, ®, &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 | |||
645 | static 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 | ||
576 | struct pinconf_ops tegra_pinconf_ops = { | 665 | struct 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 | ||
585 | static struct pinctrl_gpio_range tegra_pinctrl_gpio_range = { | 677 | static 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 | ||
591 | static struct pinctrl_desc tegra_pinctrl_desc = { | 683 | static 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 | ||
599 | static struct of_device_id tegra_pinctrl_of_match[] __devinitdata = { | 690 | int __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 | |||
615 | static 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 | } |
761 | EXPORT_SYMBOL_GPL(tegra_pinctrl_probe); | ||
700 | 762 | ||
701 | static int __devexit tegra_pinctrl_remove(struct platform_device *pdev) | 763 | int __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 | 772 | EXPORT_SYMBOL_GPL(tegra_pinctrl_remove); | |
711 | static 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 | |||
721 | static int __init tegra_pinctrl_init(void) | ||
722 | { | ||
723 | return platform_driver_register(&tegra_pinctrl_driver); | ||
724 | } | ||
725 | arch_initcall(tegra_pinctrl_init); | ||
726 | |||
727 | static void __exit tegra_pinctrl_exit(void) | ||
728 | { | ||
729 | platform_driver_unregister(&tegra_pinctrl_driver); | ||
730 | } | ||
731 | module_exit(tegra_pinctrl_exit); | ||
732 | |||
733 | MODULE_AUTHOR("Stephen Warren <swarren@nvidia.com>"); | ||
734 | MODULE_DESCRIPTION("NVIDIA Tegra pinctrl driver"); | ||
735 | MODULE_LICENSE("GPL v2"); | ||
736 | MODULE_DEVICE_TABLE(of, tegra_pinctrl_of_match); | ||
diff --git a/drivers/pinctrl/pinctrl-tegra.h b/drivers/pinctrl/pinctrl-tegra.h index 782c795326e..705c007a38c 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 | /** | 142 | int 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 | 144 | int tegra_pinctrl_remove(struct platform_device *pdev); |
145 | * details of the SoC. | ||
146 | */ | ||
147 | typedef 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 | */ | ||
155 | void 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 | */ | ||
161 | void 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 f69ff96aa29..a74f9a56853 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 | ||
2857 | void __devinit tegra20_pinctrl_init(const struct tegra_pinctrl_soc_data **soc) | 2859 | static 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 | |||
2864 | static struct of_device_id tegra20_pinctrl_of_match[] __devinitdata = { | ||
2865 | { .compatible = "nvidia,tegra20-pinmux", }, | ||
2866 | { }, | ||
2867 | }; | ||
2868 | |||
2869 | static 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 | |||
2879 | static int __init tegra20_pinctrl_init(void) | ||
2880 | { | ||
2881 | return platform_driver_register(&tegra20_pinctrl_driver); | ||
2882 | } | ||
2883 | arch_initcall(tegra20_pinctrl_init); | ||
2884 | |||
2885 | static void __exit tegra20_pinctrl_exit(void) | ||
2886 | { | ||
2887 | platform_driver_unregister(&tegra20_pinctrl_driver); | ||
2888 | } | ||
2889 | module_exit(tegra20_pinctrl_exit); | ||
2890 | |||
2891 | MODULE_AUTHOR("Stephen Warren <swarren@nvidia.com>"); | ||
2892 | MODULE_DESCRIPTION("NVIDIA Tegra20 pinctrl driver"); | ||
2893 | MODULE_LICENSE("GPL v2"); | ||
2894 | MODULE_DEVICE_TABLE(of, tegra20_pinctrl_of_match); | ||
diff --git a/drivers/pinctrl/pinctrl-tegra30.c b/drivers/pinctrl/pinctrl-tegra30.c index 4d7571d4a43..0386fdf0da1 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 | ||
3723 | void __devinit tegra30_pinctrl_init(const struct tegra_pinctrl_soc_data **soc) | 3725 | static 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 | |||
3730 | static struct of_device_id tegra30_pinctrl_of_match[] __devinitdata = { | ||
3731 | { .compatible = "nvidia,tegra30-pinmux", }, | ||
3732 | { }, | ||
3733 | }; | ||
3734 | |||
3735 | static 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 | |||
3745 | static int __init tegra30_pinctrl_init(void) | ||
3746 | { | ||
3747 | return platform_driver_register(&tegra30_pinctrl_driver); | ||
3748 | } | ||
3749 | arch_initcall(tegra30_pinctrl_init); | ||
3750 | |||
3751 | static void __exit tegra30_pinctrl_exit(void) | ||
3752 | { | ||
3753 | platform_driver_unregister(&tegra30_pinctrl_driver); | ||
3754 | } | ||
3755 | module_exit(tegra30_pinctrl_exit); | ||
3756 | |||
3757 | MODULE_AUTHOR("Stephen Warren <swarren@nvidia.com>"); | ||
3758 | MODULE_DESCRIPTION("NVIDIA Tegra30 pinctrl driver"); | ||
3759 | MODULE_LICENSE("GPL v2"); | ||
3760 | MODULE_DEVICE_TABLE(of, tegra30_pinctrl_of_match); | ||