Commit | Line | Data |
---|---|---|
394349f7 LW |
1 | /* |
2 | * Core driver for the generic pin config portions of the pin control subsystem | |
3 | * | |
4 | * Copyright (C) 2011 ST-Ericsson SA | |
5 | * Written on behalf of Linaro for ST-Ericsson | |
6 | * | |
7 | * Author: Linus Walleij <linus.walleij@linaro.org> | |
8 | * | |
9 | * License terms: GNU General Public License (GPL) version 2 | |
10 | */ | |
11 | ||
12 | #define pr_fmt(fmt) "generic pinconfig core: " fmt | |
13 | ||
14 | #include <linux/kernel.h> | |
9cfd1724 | 15 | #include <linux/module.h> |
394349f7 LW |
16 | #include <linux/init.h> |
17 | #include <linux/device.h> | |
18 | #include <linux/slab.h> | |
19 | #include <linux/debugfs.h> | |
20 | #include <linux/seq_file.h> | |
21 | #include <linux/pinctrl/pinctrl.h> | |
22 | #include <linux/pinctrl/pinconf.h> | |
23 | #include <linux/pinctrl/pinconf-generic.h> | |
24 | #include "core.h" | |
25 | #include "pinconf.h" | |
26 | ||
27 | #ifdef CONFIG_DEBUG_FS | |
28 | ||
29 | struct pin_config_item { | |
30 | const enum pin_config_param param; | |
31 | const char * const display; | |
32 | const char * const format; | |
33 | }; | |
34 | ||
35 | #define PCONFDUMP(a, b, c) { .param = a, .display = b, .format = c } | |
36 | ||
1ef465c0 | 37 | static struct pin_config_item conf_items[] = { |
394349f7 LW |
38 | PCONFDUMP(PIN_CONFIG_BIAS_DISABLE, "input bias disabled", NULL), |
39 | PCONFDUMP(PIN_CONFIG_BIAS_HIGH_IMPEDANCE, "input bias high impedance", NULL), | |
40 | PCONFDUMP(PIN_CONFIG_BIAS_PULL_UP, "input bias pull up", NULL), | |
41 | PCONFDUMP(PIN_CONFIG_BIAS_PULL_DOWN, "input bias pull down", NULL), | |
42 | PCONFDUMP(PIN_CONFIG_DRIVE_PUSH_PULL, "output drive push pull", NULL), | |
43 | PCONFDUMP(PIN_CONFIG_DRIVE_OPEN_DRAIN, "output drive open drain", NULL), | |
44 | PCONFDUMP(PIN_CONFIG_DRIVE_OPEN_SOURCE, "output drive open source", NULL), | |
ea27c396 | 45 | PCONFDUMP(PIN_CONFIG_INPUT_SCHMITT_ENABLE, "input schmitt enabled", NULL), |
394349f7 LW |
46 | PCONFDUMP(PIN_CONFIG_INPUT_SCHMITT, "input schmitt trigger", NULL), |
47 | PCONFDUMP(PIN_CONFIG_INPUT_DEBOUNCE, "input debounce", "time units"), | |
48 | PCONFDUMP(PIN_CONFIG_POWER_SOURCE, "pin power source", "selector"), | |
684697cb | 49 | PCONFDUMP(PIN_CONFIG_SLEW_RATE, "slew rate", NULL), |
394349f7 | 50 | PCONFDUMP(PIN_CONFIG_LOW_POWER_MODE, "pin low power", "mode"), |
483f33f6 | 51 | PCONFDUMP(PIN_CONFIG_OUTPUT, "pin output", "level"), |
394349f7 LW |
52 | }; |
53 | ||
54 | void pinconf_generic_dump_pin(struct pinctrl_dev *pctldev, | |
55 | struct seq_file *s, unsigned pin) | |
56 | { | |
57 | const struct pinconf_ops *ops = pctldev->desc->confops; | |
58 | int i; | |
59 | ||
60 | if (!ops->is_generic) | |
61 | return; | |
62 | ||
b6465424 | 63 | for (i = 0; i < ARRAY_SIZE(conf_items); i++) { |
394349f7 LW |
64 | unsigned long config; |
65 | int ret; | |
66 | ||
67 | /* We want to check out this parameter */ | |
68 | config = pinconf_to_config_packed(conf_items[i].param, 0); | |
69 | ret = pin_config_get_for_pin(pctldev, pin, &config); | |
70 | /* These are legal errors */ | |
71 | if (ret == -EINVAL || ret == -ENOTSUPP) | |
72 | continue; | |
73 | if (ret) { | |
74 | seq_printf(s, "ERROR READING CONFIG SETTING %d ", i); | |
75 | continue; | |
76 | } | |
77 | /* Space between multiple configs */ | |
78 | seq_puts(s, " "); | |
79 | seq_puts(s, conf_items[i].display); | |
80 | /* Print unit if available */ | |
81 | if (conf_items[i].format && | |
82 | pinconf_to_config_argument(config) != 0) | |
83 | seq_printf(s, " (%u %s)", | |
84 | pinconf_to_config_argument(config), | |
85 | conf_items[i].format); | |
86 | } | |
87 | } | |
88 | ||
89 | void pinconf_generic_dump_group(struct pinctrl_dev *pctldev, | |
90 | struct seq_file *s, const char *gname) | |
91 | { | |
92 | const struct pinconf_ops *ops = pctldev->desc->confops; | |
93 | int i; | |
94 | ||
95 | if (!ops->is_generic) | |
96 | return; | |
97 | ||
b6465424 | 98 | for (i = 0; i < ARRAY_SIZE(conf_items); i++) { |
394349f7 LW |
99 | unsigned long config; |
100 | int ret; | |
101 | ||
102 | /* We want to check out this parameter */ | |
103 | config = pinconf_to_config_packed(conf_items[i].param, 0); | |
104 | ret = pin_config_group_get(dev_name(pctldev->dev), gname, | |
105 | &config); | |
106 | /* These are legal errors */ | |
107 | if (ret == -EINVAL || ret == -ENOTSUPP) | |
108 | continue; | |
109 | if (ret) { | |
110 | seq_printf(s, "ERROR READING CONFIG SETTING %d ", i); | |
111 | continue; | |
112 | } | |
113 | /* Space between multiple configs */ | |
114 | seq_puts(s, " "); | |
115 | seq_puts(s, conf_items[i].display); | |
116 | /* Print unit if available */ | |
117 | if (conf_items[i].format && config != 0) | |
118 | seq_printf(s, " (%u %s)", | |
119 | pinconf_to_config_argument(config), | |
120 | conf_items[i].format); | |
121 | } | |
122 | } | |
123 | ||
9cfd1724 HZ |
124 | void pinconf_generic_dump_config(struct pinctrl_dev *pctldev, |
125 | struct seq_file *s, unsigned long config) | |
126 | { | |
127 | int i; | |
128 | ||
b6465424 | 129 | for (i = 0; i < ARRAY_SIZE(conf_items); i++) { |
9cfd1724 HZ |
130 | if (pinconf_to_config_param(config) != conf_items[i].param) |
131 | continue; | |
132 | seq_printf(s, "%s: 0x%x", conf_items[i].display, | |
133 | pinconf_to_config_argument(config)); | |
134 | } | |
135 | } | |
136 | EXPORT_SYMBOL_GPL(pinconf_generic_dump_config); | |
394349f7 | 137 | #endif |