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