]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blame - drivers/pinctrl/pinctrl-tegra.c
dt: Document Tegra20/30 pinctrl binding
[mirror_ubuntu-artful-kernel.git] / drivers / pinctrl / pinctrl-tegra.c
CommitLineData
971dac71
SW
1/*
2 * Driver for the NVIDIA Tegra pinmux
3 *
4 * Copyright (c) 2011, NVIDIA CORPORATION. All rights reserved.
5 *
6 * Derived from code:
7 * Copyright (C) 2010 Google, Inc.
8 * Copyright (C) 2010 NVIDIA Corporation
9 * Copyright (C) 2009-2011 ST-Ericsson AB
10 *
11 * This program is free software; you can redistribute it and/or modify it
12 * under the terms and conditions of the GNU General Public License,
13 * version 2, as published by the Free Software Foundation.
14 *
15 * This program is distributed in the hope it will be useful, but WITHOUT
16 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
17 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
18 * more details.
19 */
20
21#include <linux/err.h>
22#include <linux/init.h>
23#include <linux/io.h>
24#include <linux/module.h>
25#include <linux/of_device.h>
26#include <linux/pinctrl/pinctrl.h>
27#include <linux/pinctrl/pinmux.h>
28#include <linux/pinctrl/pinconf.h>
29
30#include <mach/pinconf-tegra.h>
31
32#include "pinctrl-tegra.h"
33
34#define DRIVER_NAME "tegra-pinmux-disabled"
35
36struct tegra_pmx {
37 struct device *dev;
38 struct pinctrl_dev *pctl;
39
40 const struct tegra_pinctrl_soc_data *soc;
41
42 int nbanks;
43 void __iomem **regs;
44};
45
46static inline u32 pmx_readl(struct tegra_pmx *pmx, u32 bank, u32 reg)
47{
48 return readl(pmx->regs[bank] + reg);
49}
50
51static inline void pmx_writel(struct tegra_pmx *pmx, u32 val, u32 bank, u32 reg)
52{
53 writel(val, pmx->regs[bank] + reg);
54}
55
d1e90e9e 56static int tegra_pinctrl_get_groups_count(struct pinctrl_dev *pctldev)
971dac71
SW
57{
58 struct tegra_pmx *pmx = pinctrl_dev_get_drvdata(pctldev);
59
d1e90e9e 60 return pmx->soc->ngroups;
971dac71
SW
61}
62
63static const char *tegra_pinctrl_get_group_name(struct pinctrl_dev *pctldev,
64 unsigned group)
65{
66 struct tegra_pmx *pmx = pinctrl_dev_get_drvdata(pctldev);
67
971dac71
SW
68 return pmx->soc->groups[group].name;
69}
70
71static int tegra_pinctrl_get_group_pins(struct pinctrl_dev *pctldev,
72 unsigned group,
73 const unsigned **pins,
74 unsigned *num_pins)
75{
76 struct tegra_pmx *pmx = pinctrl_dev_get_drvdata(pctldev);
77
971dac71
SW
78 *pins = pmx->soc->groups[group].pins;
79 *num_pins = pmx->soc->groups[group].npins;
80
81 return 0;
82}
83
84static void tegra_pinctrl_pin_dbg_show(struct pinctrl_dev *pctldev,
85 struct seq_file *s,
86 unsigned offset)
87{
88 seq_printf(s, " " DRIVER_NAME);
89}
90
91static struct pinctrl_ops tegra_pinctrl_ops = {
d1e90e9e 92 .get_groups_count = tegra_pinctrl_get_groups_count,
971dac71
SW
93 .get_group_name = tegra_pinctrl_get_group_name,
94 .get_group_pins = tegra_pinctrl_get_group_pins,
95 .pin_dbg_show = tegra_pinctrl_pin_dbg_show,
96};
97
d1e90e9e 98static int tegra_pinctrl_get_funcs_count(struct pinctrl_dev *pctldev)
971dac71
SW
99{
100 struct tegra_pmx *pmx = pinctrl_dev_get_drvdata(pctldev);
101
d1e90e9e 102 return pmx->soc->nfunctions;
971dac71
SW
103}
104
105static const char *tegra_pinctrl_get_func_name(struct pinctrl_dev *pctldev,
106 unsigned function)
107{
108 struct tegra_pmx *pmx = pinctrl_dev_get_drvdata(pctldev);
109
971dac71
SW
110 return pmx->soc->functions[function].name;
111}
112
113static int tegra_pinctrl_get_func_groups(struct pinctrl_dev *pctldev,
114 unsigned function,
115 const char * const **groups,
116 unsigned * const num_groups)
117{
118 struct tegra_pmx *pmx = pinctrl_dev_get_drvdata(pctldev);
119
971dac71
SW
120 *groups = pmx->soc->functions[function].groups;
121 *num_groups = pmx->soc->functions[function].ngroups;
122
123 return 0;
124}
125
126static int tegra_pinctrl_enable(struct pinctrl_dev *pctldev, unsigned function,
127 unsigned group)
128{
129 struct tegra_pmx *pmx = pinctrl_dev_get_drvdata(pctldev);
130 const struct tegra_pingroup *g;
131 int i;
132 u32 val;
133
971dac71
SW
134 g = &pmx->soc->groups[group];
135
136 if (g->mux_reg < 0)
137 return -EINVAL;
138
139 for (i = 0; i < ARRAY_SIZE(g->funcs); i++) {
140 if (g->funcs[i] == function)
141 break;
142 }
143 if (i == ARRAY_SIZE(g->funcs))
144 return -EINVAL;
145
146 val = pmx_readl(pmx, g->mux_bank, g->mux_reg);
147 val &= ~(0x3 << g->mux_bit);
148 val |= i << g->mux_bit;
149 pmx_writel(pmx, val, g->mux_bank, g->mux_reg);
150
151 return 0;
152}
153
154static void tegra_pinctrl_disable(struct pinctrl_dev *pctldev,
155 unsigned function, unsigned group)
156{
157 struct tegra_pmx *pmx = pinctrl_dev_get_drvdata(pctldev);
158 const struct tegra_pingroup *g;
159 u32 val;
160
971dac71
SW
161 g = &pmx->soc->groups[group];
162
163 if (g->mux_reg < 0)
164 return;
165
166 val = pmx_readl(pmx, g->mux_bank, g->mux_reg);
167 val &= ~(0x3 << g->mux_bit);
168 val |= g->func_safe << g->mux_bit;
169 pmx_writel(pmx, val, g->mux_bank, g->mux_reg);
170}
171
172static struct pinmux_ops tegra_pinmux_ops = {
d1e90e9e 173 .get_functions_count = tegra_pinctrl_get_funcs_count,
971dac71
SW
174 .get_function_name = tegra_pinctrl_get_func_name,
175 .get_function_groups = tegra_pinctrl_get_func_groups,
176 .enable = tegra_pinctrl_enable,
177 .disable = tegra_pinctrl_disable,
178};
179
180static int tegra_pinconf_reg(struct tegra_pmx *pmx,
181 const struct tegra_pingroup *g,
182 enum tegra_pinconf_param param,
183 s8 *bank, s16 *reg, s8 *bit, s8 *width)
184{
185 switch (param) {
186 case TEGRA_PINCONF_PARAM_PULL:
187 *bank = g->pupd_bank;
188 *reg = g->pupd_reg;
189 *bit = g->pupd_bit;
190 *width = 2;
191 break;
192 case TEGRA_PINCONF_PARAM_TRISTATE:
193 *bank = g->tri_bank;
194 *reg = g->tri_reg;
195 *bit = g->tri_bit;
196 *width = 1;
197 break;
198 case TEGRA_PINCONF_PARAM_ENABLE_INPUT:
199 *bank = g->einput_bank;
200 *reg = g->einput_reg;
201 *bit = g->einput_bit;
202 *width = 1;
203 break;
204 case TEGRA_PINCONF_PARAM_OPEN_DRAIN:
205 *bank = g->odrain_bank;
206 *reg = g->odrain_reg;
207 *bit = g->odrain_bit;
208 *width = 1;
209 break;
210 case TEGRA_PINCONF_PARAM_LOCK:
211 *bank = g->lock_bank;
212 *reg = g->lock_reg;
213 *bit = g->lock_bit;
214 *width = 1;
215 break;
216 case TEGRA_PINCONF_PARAM_IORESET:
217 *bank = g->ioreset_bank;
218 *reg = g->ioreset_reg;
219 *bit = g->ioreset_bit;
220 *width = 1;
221 break;
222 case TEGRA_PINCONF_PARAM_HIGH_SPEED_MODE:
223 *bank = g->drv_bank;
224 *reg = g->drv_reg;
225 *bit = g->hsm_bit;
226 *width = 1;
227 break;
228 case TEGRA_PINCONF_PARAM_SCHMITT:
229 *bank = g->drv_bank;
230 *reg = g->drv_reg;
231 *bit = g->schmitt_bit;
232 *width = 1;
233 break;
234 case TEGRA_PINCONF_PARAM_LOW_POWER_MODE:
235 *bank = g->drv_bank;
236 *reg = g->drv_reg;
237 *bit = g->lpmd_bit;
238 *width = 1;
239 break;
240 case TEGRA_PINCONF_PARAM_DRIVE_DOWN_STRENGTH:
241 *bank = g->drv_bank;
242 *reg = g->drv_reg;
243 *bit = g->drvdn_bit;
244 *width = g->drvdn_width;
245 break;
246 case TEGRA_PINCONF_PARAM_DRIVE_UP_STRENGTH:
247 *bank = g->drv_bank;
248 *reg = g->drv_reg;
249 *bit = g->drvup_bit;
250 *width = g->drvup_width;
251 break;
252 case TEGRA_PINCONF_PARAM_SLEW_RATE_FALLING:
253 *bank = g->drv_bank;
254 *reg = g->drv_reg;
255 *bit = g->slwf_bit;
256 *width = g->slwf_width;
257 break;
258 case TEGRA_PINCONF_PARAM_SLEW_RATE_RISING:
259 *bank = g->drv_bank;
260 *reg = g->drv_reg;
261 *bit = g->slwr_bit;
262 *width = g->slwr_width;
263 break;
264 default:
265 dev_err(pmx->dev, "Invalid config param %04x\n", param);
266 return -ENOTSUPP;
267 }
268
269 if (*reg < 0) {
270 dev_err(pmx->dev,
271 "Config param %04x not supported on group %s\n",
272 param, g->name);
273 return -ENOTSUPP;
274 }
275
276 return 0;
277}
278
279static int tegra_pinconf_get(struct pinctrl_dev *pctldev,
280 unsigned pin, unsigned long *config)
281{
282 return -ENOTSUPP;
283}
284
285static int tegra_pinconf_set(struct pinctrl_dev *pctldev,
286 unsigned pin, unsigned long config)
287{
288 return -ENOTSUPP;
289}
290
291static int tegra_pinconf_group_get(struct pinctrl_dev *pctldev,
292 unsigned group, unsigned long *config)
293{
294 struct tegra_pmx *pmx = pinctrl_dev_get_drvdata(pctldev);
295 enum tegra_pinconf_param param = TEGRA_PINCONF_UNPACK_PARAM(*config);
296 u16 arg;
297 const struct tegra_pingroup *g;
298 int ret;
299 s8 bank, bit, width;
300 s16 reg;
301 u32 val, mask;
302
971dac71
SW
303 g = &pmx->soc->groups[group];
304
305 ret = tegra_pinconf_reg(pmx, g, param, &bank, &reg, &bit, &width);
306 if (ret < 0)
307 return ret;
308
309 val = pmx_readl(pmx, bank, reg);
310 mask = (1 << width) - 1;
311 arg = (val >> bit) & mask;
312
313 *config = TEGRA_PINCONF_PACK(param, arg);
314
315 return 0;
316}
317
318static int tegra_pinconf_group_set(struct pinctrl_dev *pctldev,
319 unsigned group, unsigned long config)
320{
321 struct tegra_pmx *pmx = pinctrl_dev_get_drvdata(pctldev);
322 enum tegra_pinconf_param param = TEGRA_PINCONF_UNPACK_PARAM(config);
323 u16 arg = TEGRA_PINCONF_UNPACK_ARG(config);
324 const struct tegra_pingroup *g;
325 int ret;
326 s8 bank, bit, width;
327 s16 reg;
328 u32 val, mask;
329
971dac71
SW
330 g = &pmx->soc->groups[group];
331
332 ret = tegra_pinconf_reg(pmx, g, param, &bank, &reg, &bit, &width);
333 if (ret < 0)
334 return ret;
335
336 val = pmx_readl(pmx, bank, reg);
337
338 /* LOCK can't be cleared */
339 if (param == TEGRA_PINCONF_PARAM_LOCK) {
340 if ((val & BIT(bit)) && !arg)
341 return -EINVAL;
342 }
343
344 /* Special-case Boolean values; allow any non-zero as true */
345 if (width == 1)
346 arg = !!arg;
347
348 /* Range-check user-supplied value */
349 mask = (1 << width) - 1;
350 if (arg & ~mask)
351 return -EINVAL;
352
353 /* Update register */
354 val &= ~(mask << bit);
355 val |= arg << bit;
356 pmx_writel(pmx, val, bank, reg);
357
358 return 0;
359}
360
361static void tegra_pinconf_dbg_show(struct pinctrl_dev *pctldev,
362 struct seq_file *s, unsigned offset)
363{
364}
365
366static void tegra_pinconf_group_dbg_show(struct pinctrl_dev *pctldev,
367 struct seq_file *s, unsigned selector)
368{
369}
370
371struct pinconf_ops tegra_pinconf_ops = {
372 .pin_config_get = tegra_pinconf_get,
373 .pin_config_set = tegra_pinconf_set,
374 .pin_config_group_get = tegra_pinconf_group_get,
375 .pin_config_group_set = tegra_pinconf_group_set,
376 .pin_config_dbg_show = tegra_pinconf_dbg_show,
377 .pin_config_group_dbg_show = tegra_pinconf_group_dbg_show,
378};
379
380static struct pinctrl_gpio_range tegra_pinctrl_gpio_range = {
381 .name = "Tegra GPIOs",
382 .id = 0,
383 .base = 0,
384};
385
386static struct pinctrl_desc tegra_pinctrl_desc = {
387 .name = DRIVER_NAME,
388 .pctlops = &tegra_pinctrl_ops,
389 .pmxops = &tegra_pinmux_ops,
390 .confops = &tegra_pinconf_ops,
391 .owner = THIS_MODULE,
392};
393
394static struct of_device_id tegra_pinctrl_of_match[] __devinitdata = {
395#ifdef CONFIG_PINCTRL_TEGRA20
396 {
397 .compatible = "nvidia,tegra20-pinmux-disabled",
398 .data = tegra20_pinctrl_init,
399 },
400#endif
401#ifdef CONFIG_PINCTRL_TEGRA30
402 {
403 .compatible = "nvidia,tegra30-pinmux-disabled",
404 .data = tegra30_pinctrl_init,
405 },
406#endif
407 {},
408};
409
410static int __devinit tegra_pinctrl_probe(struct platform_device *pdev)
411{
412 const struct of_device_id *match;
413 tegra_pinctrl_soc_initf initf = NULL;
414 struct tegra_pmx *pmx;
415 struct resource *res;
416 int i;
417
418 match = of_match_device(tegra_pinctrl_of_match, &pdev->dev);
419 if (match)
420 initf = (tegra_pinctrl_soc_initf)match->data;
421#ifdef CONFIG_PINCTRL_TEGRA20
422 if (!initf)
423 initf = tegra20_pinctrl_init;
424#endif
425 if (!initf) {
426 dev_err(&pdev->dev,
427 "Could not determine SoC-specific init func\n");
428 return -EINVAL;
429 }
430
431 pmx = devm_kzalloc(&pdev->dev, sizeof(*pmx), GFP_KERNEL);
432 if (!pmx) {
433 dev_err(&pdev->dev, "Can't alloc tegra_pmx\n");
434 return -ENOMEM;
435 }
436 pmx->dev = &pdev->dev;
437
438 (*initf)(&pmx->soc);
439
440 tegra_pinctrl_gpio_range.npins = pmx->soc->ngpios;
441 tegra_pinctrl_desc.pins = pmx->soc->pins;
442 tegra_pinctrl_desc.npins = pmx->soc->npins;
443
444 for (i = 0; ; i++) {
445 res = platform_get_resource(pdev, IORESOURCE_MEM, i);
446 if (!res)
447 break;
448 }
449 pmx->nbanks = i;
450
451 pmx->regs = devm_kzalloc(&pdev->dev, pmx->nbanks * sizeof(*pmx->regs),
452 GFP_KERNEL);
453 if (!pmx->regs) {
454 dev_err(&pdev->dev, "Can't alloc regs pointer\n");
455 return -ENODEV;
456 }
457
458 for (i = 0; i < pmx->nbanks; i++) {
459 res = platform_get_resource(pdev, IORESOURCE_MEM, i);
460 if (!res) {
461 dev_err(&pdev->dev, "Missing MEM resource\n");
462 return -ENODEV;
463 }
464
465 if (!devm_request_mem_region(&pdev->dev, res->start,
466 resource_size(res),
467 dev_name(&pdev->dev))) {
468 dev_err(&pdev->dev,
469 "Couldn't request MEM resource %d\n", i);
470 return -ENODEV;
471 }
472
473 pmx->regs[i] = devm_ioremap(&pdev->dev, res->start,
474 resource_size(res));
475 if (!pmx->regs[i]) {
476 dev_err(&pdev->dev, "Couldn't ioremap regs %d\n", i);
477 return -ENODEV;
478 }
479 }
480
481 pmx->pctl = pinctrl_register(&tegra_pinctrl_desc, &pdev->dev, pmx);
482 if (IS_ERR(pmx->pctl)) {
483 dev_err(&pdev->dev, "Couldn't register pinctrl driver\n");
484 return PTR_ERR(pmx->pctl);
485 }
486
487 pinctrl_add_gpio_range(pmx->pctl, &tegra_pinctrl_gpio_range);
488
489 platform_set_drvdata(pdev, pmx);
490
491 dev_dbg(&pdev->dev, "Probed Tegra pinctrl driver\n");
492
493 return 0;
494}
495
496static int __devexit tegra_pinctrl_remove(struct platform_device *pdev)
497{
498 struct tegra_pmx *pmx = platform_get_drvdata(pdev);
499
500 pinctrl_remove_gpio_range(pmx->pctl, &tegra_pinctrl_gpio_range);
501 pinctrl_unregister(pmx->pctl);
502
503 return 0;
504}
505
506static struct platform_driver tegra_pinctrl_driver = {
507 .driver = {
508 .name = DRIVER_NAME,
509 .owner = THIS_MODULE,
510 .of_match_table = tegra_pinctrl_of_match,
511 },
512 .probe = tegra_pinctrl_probe,
513 .remove = __devexit_p(tegra_pinctrl_remove),
514};
515
516static int __init tegra_pinctrl_init(void)
517{
518 return platform_driver_register(&tegra_pinctrl_driver);
519}
520arch_initcall(tegra_pinctrl_init);
521
522static void __exit tegra_pinctrl_exit(void)
523{
524 platform_driver_unregister(&tegra_pinctrl_driver);
525}
526module_exit(tegra_pinctrl_exit);
527
528MODULE_AUTHOR("Stephen Warren <swarren@nvidia.com>");
529MODULE_DESCRIPTION("NVIDIA Tegra pinctrl driver");
530MODULE_LICENSE("GPL v2");
531MODULE_DEVICE_TABLE(of, tegra_pinctrl_of_match);