diff options
-rw-r--r-- | Documentation/pinctrl.txt | 96 | ||||
-rw-r--r-- | drivers/pinctrl/Kconfig | 5 | ||||
-rw-r--r-- | drivers/pinctrl/Makefile | 1 | ||||
-rw-r--r-- | drivers/pinctrl/core.c | 43 | ||||
-rw-r--r-- | drivers/pinctrl/core.h | 5 | ||||
-rw-r--r-- | drivers/pinctrl/pinconf.c | 302 | ||||
-rw-r--r-- | drivers/pinctrl/pinconf.h | 36 | ||||
-rw-r--r-- | include/linux/pinctrl/pinconf.h | 96 | ||||
-rw-r--r-- | include/linux/pinctrl/pinctrl.h | 8 |
9 files changed, 582 insertions, 10 deletions
diff --git a/Documentation/pinctrl.txt b/Documentation/pinctrl.txt index c8fd136eac83..6d23fa84ee47 100644 --- a/Documentation/pinctrl.txt +++ b/Documentation/pinctrl.txt | |||
@@ -7,12 +7,9 @@ This subsystem deals with: | |||
7 | 7 | ||
8 | - Multiplexing of pins, pads, fingers (etc) see below for details | 8 | - Multiplexing of pins, pads, fingers (etc) see below for details |
9 | 9 | ||
10 | The intention is to also deal with: | 10 | - Configuration of pins, pads, fingers (etc), such as software-controlled |
11 | 11 | biasing and driving mode specific pins, such as pull-up/down, open drain, | |
12 | - Software-controlled biasing and driving mode specific pins, such as | 12 | load capacitance etc. |
13 | pull-up/down, open drain etc, load capacitance configuration when controlled | ||
14 | by software, etc. | ||
15 | |||
16 | 13 | ||
17 | Top-level interface | 14 | Top-level interface |
18 | =================== | 15 | =================== |
@@ -88,6 +85,11 @@ int __init foo_probe(void) | |||
88 | pr_err("could not register foo pin driver\n"); | 85 | pr_err("could not register foo pin driver\n"); |
89 | } | 86 | } |
90 | 87 | ||
88 | To enable the pinctrl subsystem and the subgroups for PINMUX and PINCONF and | ||
89 | selected drivers, you need to select them from your machine's Kconfig entry, | ||
90 | since these are so tightly integrated with the machines they are used on. | ||
91 | See for example arch/arm/mach-u300/Kconfig for an example. | ||
92 | |||
91 | Pins usually have fancier names than this. You can find these in the dataheet | 93 | Pins usually have fancier names than this. You can find these in the dataheet |
92 | for your chip. Notice that the core pinctrl.h file provides a fancy macro | 94 | for your chip. Notice that the core pinctrl.h file provides a fancy macro |
93 | called PINCTRL_PIN() to create the struct entries. As you can see I enumerated | 95 | called PINCTRL_PIN() to create the struct entries. As you can see I enumerated |
@@ -193,6 +195,88 @@ structure, for example specific register ranges associated with each group | |||
193 | and so on. | 195 | and so on. |
194 | 196 | ||
195 | 197 | ||
198 | Pin configuration | ||
199 | ================= | ||
200 | |||
201 | Pins can sometimes be software-configured in an various ways, mostly related | ||
202 | to their electronic properties when used as inputs or outputs. For example you | ||
203 | may be able to make an output pin high impedance, or "tristate" meaning it is | ||
204 | effectively disconnected. You may be able to connect an input pin to VDD or GND | ||
205 | using a certain resistor value - pull up and pull down - so that the pin has a | ||
206 | stable value when nothing is driving the rail it is connected to, or when it's | ||
207 | unconnected. | ||
208 | |||
209 | For example, a platform may do this: | ||
210 | |||
211 | ret = pin_config_set(dev, "FOO_GPIO_PIN", PLATFORM_X_PULL_UP); | ||
212 | |||
213 | To pull up a pin to VDD. The pin configuration driver implements callbacks for | ||
214 | changing pin configuration in the pin controller ops like this: | ||
215 | |||
216 | #include <linux/pinctrl/pinctrl.h> | ||
217 | #include <linux/pinctrl/pinconf.h> | ||
218 | #include "platform_x_pindefs.h" | ||
219 | |||
220 | int foo_pin_config_get(struct pinctrl_dev *pctldev, | ||
221 | unsigned offset, | ||
222 | unsigned long *config) | ||
223 | { | ||
224 | struct my_conftype conf; | ||
225 | |||
226 | ... Find setting for pin @ offset ... | ||
227 | |||
228 | *config = (unsigned long) conf; | ||
229 | } | ||
230 | |||
231 | int foo_pin_config_set(struct pinctrl_dev *pctldev, | ||
232 | unsigned offset, | ||
233 | unsigned long config) | ||
234 | { | ||
235 | struct my_conftype *conf = (struct my_conftype *) config; | ||
236 | |||
237 | switch (conf) { | ||
238 | case PLATFORM_X_PULL_UP: | ||
239 | ... | ||
240 | } | ||
241 | } | ||
242 | } | ||
243 | |||
244 | int foo_pin_config_group_get (struct pinctrl_dev *pctldev, | ||
245 | unsigned selector, | ||
246 | unsigned long *config) | ||
247 | { | ||
248 | ... | ||
249 | } | ||
250 | |||
251 | int foo_pin_config_group_set (struct pinctrl_dev *pctldev, | ||
252 | unsigned selector, | ||
253 | unsigned long config) | ||
254 | { | ||
255 | ... | ||
256 | } | ||
257 | |||
258 | static struct pinconf_ops foo_pconf_ops = { | ||
259 | .pin_config_get = foo_pin_config_get, | ||
260 | .pin_config_set = foo_pin_config_set, | ||
261 | .pin_config_group_get = foo_pin_config_group_get, | ||
262 | .pin_config_group_set = foo_pin_config_group_set, | ||
263 | }; | ||
264 | |||
265 | /* Pin config operations are handled by some pin controller */ | ||
266 | static struct pinctrl_desc foo_desc = { | ||
267 | ... | ||
268 | .confops = &foo_pconf_ops, | ||
269 | }; | ||
270 | |||
271 | Since some controllers have special logic for handling entire groups of pins | ||
272 | they can exploit the special whole-group pin control function. The | ||
273 | pin_config_group_set() callback is allowed to return the error code -EAGAIN, | ||
274 | for groups it does not want to handle, or if it just wants to do some | ||
275 | group-level handling and then fall through to iterate over all pins, in which | ||
276 | case each individual pin will be treated by separate pin_config_set() calls as | ||
277 | well. | ||
278 | |||
279 | |||
196 | Interaction with the GPIO subsystem | 280 | Interaction with the GPIO subsystem |
197 | =================================== | 281 | =================================== |
198 | 282 | ||
diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig index e963da41e948..c63c72102989 100644 --- a/drivers/pinctrl/Kconfig +++ b/drivers/pinctrl/Kconfig | |||
@@ -12,7 +12,10 @@ menu "Pin controllers" | |||
12 | depends on PINCTRL | 12 | depends on PINCTRL |
13 | 13 | ||
14 | config PINMUX | 14 | config PINMUX |
15 | bool "Support pinmux controllers" | 15 | bool "Support pin multiplexing controllers" |
16 | |||
17 | config PINCONF | ||
18 | bool "Support pin configuration controllers" | ||
16 | 19 | ||
17 | config DEBUG_PINCTRL | 20 | config DEBUG_PINCTRL |
18 | bool "Debug PINCTRL calls" | 21 | bool "Debug PINCTRL calls" |
diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile index 5f3e4d65465a..c046f78dd7f7 100644 --- a/drivers/pinctrl/Makefile +++ b/drivers/pinctrl/Makefile | |||
@@ -4,6 +4,7 @@ ccflags-$(CONFIG_DEBUG_PINCTRL) += -DDEBUG | |||
4 | 4 | ||
5 | obj-$(CONFIG_PINCTRL) += core.o | 5 | obj-$(CONFIG_PINCTRL) += core.o |
6 | obj-$(CONFIG_PINMUX) += pinmux.o | 6 | obj-$(CONFIG_PINMUX) += pinmux.o |
7 | obj-$(CONFIG_PINCONF) += pinconf.o | ||
7 | obj-$(CONFIG_PINMUX_SIRF) += pinmux-sirf.o | 8 | obj-$(CONFIG_PINMUX_SIRF) += pinmux-sirf.o |
8 | obj-$(CONFIG_PINMUX_U300) += pinmux-u300.o | 9 | obj-$(CONFIG_PINMUX_U300) += pinmux-u300.o |
9 | obj-$(CONFIG_PINCTRL_COH901) += pinctrl-coh901.o | 10 | obj-$(CONFIG_PINCTRL_COH901) += pinctrl-coh901.o |
diff --git a/drivers/pinctrl/core.c b/drivers/pinctrl/core.c index 4955a68d618f..034b1ad38b32 100644 --- a/drivers/pinctrl/core.c +++ b/drivers/pinctrl/core.c | |||
@@ -28,6 +28,7 @@ | |||
28 | #include <linux/pinctrl/machine.h> | 28 | #include <linux/pinctrl/machine.h> |
29 | #include "core.h" | 29 | #include "core.h" |
30 | #include "pinmux.h" | 30 | #include "pinmux.h" |
31 | #include "pinconf.h" | ||
31 | 32 | ||
32 | /* Global list of pin control devices */ | 33 | /* Global list of pin control devices */ |
33 | static DEFINE_MUTEX(pinctrldev_list_mutex); | 34 | static DEFINE_MUTEX(pinctrldev_list_mutex); |
@@ -101,6 +102,30 @@ struct pin_desc *pin_desc_get(struct pinctrl_dev *pctldev, unsigned int pin) | |||
101 | } | 102 | } |
102 | 103 | ||
103 | /** | 104 | /** |
105 | * pin_get_from_name() - look up a pin number from a name | ||
106 | * @pctldev: the pin control device to lookup the pin on | ||
107 | * @name: the name of the pin to look up | ||
108 | */ | ||
109 | int pin_get_from_name(struct pinctrl_dev *pctldev, const char *name) | ||
110 | { | ||
111 | unsigned pin; | ||
112 | |||
113 | /* The highest pin number need to be included in the loop, thus <= */ | ||
114 | for (pin = 0; pin <= pctldev->desc->maxpin; pin++) { | ||
115 | struct pin_desc *desc; | ||
116 | |||
117 | desc = pin_desc_get(pctldev, pin); | ||
118 | /* Pin space may be sparse */ | ||
119 | if (desc == NULL) | ||
120 | continue; | ||
121 | if (desc->name && !strcmp(name, desc->name)) | ||
122 | return pin; | ||
123 | } | ||
124 | |||
125 | return -EINVAL; | ||
126 | } | ||
127 | |||
128 | /** | ||
104 | * pin_is_valid() - check if pin exists on controller | 129 | * pin_is_valid() - check if pin exists on controller |
105 | * @pctldev: the pin control device to check the pin on | 130 | * @pctldev: the pin control device to check the pin on |
106 | * @pin: pin to check, use the local pin controller index number | 131 | * @pin: pin to check, use the local pin controller index number |
@@ -160,6 +185,7 @@ static int pinctrl_register_one_pin(struct pinctrl_dev *pctldev, | |||
160 | pindesc = kzalloc(sizeof(*pindesc), GFP_KERNEL); | 185 | pindesc = kzalloc(sizeof(*pindesc), GFP_KERNEL); |
161 | if (pindesc == NULL) | 186 | if (pindesc == NULL) |
162 | return -ENOMEM; | 187 | return -ENOMEM; |
188 | |||
163 | spin_lock_init(&pindesc->lock); | 189 | spin_lock_init(&pindesc->lock); |
164 | 190 | ||
165 | /* Set owner */ | 191 | /* Set owner */ |
@@ -409,11 +435,15 @@ static int pinctrl_devices_show(struct seq_file *s, void *what) | |||
409 | { | 435 | { |
410 | struct pinctrl_dev *pctldev; | 436 | struct pinctrl_dev *pctldev; |
411 | 437 | ||
412 | seq_puts(s, "name [pinmux]\n"); | 438 | seq_puts(s, "name [pinmux] [pinconf]\n"); |
413 | mutex_lock(&pinctrldev_list_mutex); | 439 | mutex_lock(&pinctrldev_list_mutex); |
414 | list_for_each_entry(pctldev, &pinctrldev_list, node) { | 440 | list_for_each_entry(pctldev, &pinctrldev_list, node) { |
415 | seq_printf(s, "%s ", pctldev->desc->name); | 441 | seq_printf(s, "%s ", pctldev->desc->name); |
416 | if (pctldev->desc->pmxops) | 442 | if (pctldev->desc->pmxops) |
443 | seq_puts(s, "yes "); | ||
444 | else | ||
445 | seq_puts(s, "no "); | ||
446 | if (pctldev->desc->confops) | ||
417 | seq_puts(s, "yes"); | 447 | seq_puts(s, "yes"); |
418 | else | 448 | else |
419 | seq_puts(s, "no"); | 449 | seq_puts(s, "no"); |
@@ -492,6 +522,7 @@ static void pinctrl_init_device_debugfs(struct pinctrl_dev *pctldev) | |||
492 | debugfs_create_file("gpio-ranges", S_IFREG | S_IRUGO, | 522 | debugfs_create_file("gpio-ranges", S_IFREG | S_IRUGO, |
493 | device_root, pctldev, &pinctrl_gpioranges_ops); | 523 | device_root, pctldev, &pinctrl_gpioranges_ops); |
494 | pinmux_init_device_debugfs(device_root, pctldev); | 524 | pinmux_init_device_debugfs(device_root, pctldev); |
525 | pinconf_init_device_debugfs(device_root, pctldev); | ||
495 | } | 526 | } |
496 | 527 | ||
497 | static void pinctrl_init_debugfs(void) | 528 | static void pinctrl_init_debugfs(void) |
@@ -548,6 +579,16 @@ struct pinctrl_dev *pinctrl_register(struct pinctrl_desc *pctldesc, | |||
548 | } | 579 | } |
549 | } | 580 | } |
550 | 581 | ||
582 | /* If we're implementing pinconfig, check the ops for sanity */ | ||
583 | if (pctldesc->confops) { | ||
584 | ret = pinconf_check_ops(pctldesc->confops); | ||
585 | if (ret) { | ||
586 | pr_err("%s pin config ops lacks necessary functions\n", | ||
587 | pctldesc->name); | ||
588 | return NULL; | ||
589 | } | ||
590 | } | ||
591 | |||
551 | pctldev = kzalloc(sizeof(struct pinctrl_dev), GFP_KERNEL); | 592 | pctldev = kzalloc(sizeof(struct pinctrl_dev), GFP_KERNEL); |
552 | if (pctldev == NULL) | 593 | if (pctldev == NULL) |
553 | return NULL; | 594 | return NULL; |
diff --git a/drivers/pinctrl/core.h b/drivers/pinctrl/core.h index 74dee439dcf0..3f5b911acf18 100644 --- a/drivers/pinctrl/core.h +++ b/drivers/pinctrl/core.h | |||
@@ -9,6 +9,10 @@ | |||
9 | * License terms: GNU General Public License (GPL) version 2 | 9 | * License terms: GNU General Public License (GPL) version 2 |
10 | */ | 10 | */ |
11 | 11 | ||
12 | #include <linux/pinctrl/pinconf.h> | ||
13 | |||
14 | struct pinctrl_gpio_range; | ||
15 | |||
12 | /** | 16 | /** |
13 | * struct pinctrl_dev - pin control class device | 17 | * struct pinctrl_dev - pin control class device |
14 | * @node: node to include this pin controller in the global pin controller list | 18 | * @node: node to include this pin controller in the global pin controller list |
@@ -66,6 +70,7 @@ struct pin_desc { | |||
66 | struct pinctrl_dev *get_pinctrl_dev_from_dev(struct device *dev, | 70 | struct pinctrl_dev *get_pinctrl_dev_from_dev(struct device *dev, |
67 | const char *dev_name); | 71 | const char *dev_name); |
68 | struct pin_desc *pin_desc_get(struct pinctrl_dev *pctldev, unsigned int pin); | 72 | struct pin_desc *pin_desc_get(struct pinctrl_dev *pctldev, unsigned int pin); |
73 | int pin_get_from_name(struct pinctrl_dev *pctldev, const char *name); | ||
69 | int pinctrl_get_device_gpio_range(unsigned gpio, | 74 | int pinctrl_get_device_gpio_range(unsigned gpio, |
70 | struct pinctrl_dev **outdev, | 75 | struct pinctrl_dev **outdev, |
71 | struct pinctrl_gpio_range **outrange); | 76 | struct pinctrl_gpio_range **outrange); |
diff --git a/drivers/pinctrl/pinconf.c b/drivers/pinctrl/pinconf.c new file mode 100644 index 000000000000..9195eefe258a --- /dev/null +++ b/drivers/pinctrl/pinconf.c | |||
@@ -0,0 +1,302 @@ | |||
1 | /* | ||
2 | * Core driver for the 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 | #define pr_fmt(fmt) "pinconfig core: " fmt | ||
12 | |||
13 | #include <linux/kernel.h> | ||
14 | #include <linux/module.h> | ||
15 | #include <linux/init.h> | ||
16 | #include <linux/device.h> | ||
17 | #include <linux/slab.h> | ||
18 | #include <linux/debugfs.h> | ||
19 | #include <linux/seq_file.h> | ||
20 | #include <linux/pinctrl/machine.h> | ||
21 | #include <linux/pinctrl/pinctrl.h> | ||
22 | #include <linux/pinctrl/pinconf.h> | ||
23 | #include "core.h" | ||
24 | #include "pinconf.h" | ||
25 | |||
26 | int pin_config_get_for_pin(struct pinctrl_dev *pctldev, unsigned pin, | ||
27 | unsigned long *config) | ||
28 | { | ||
29 | const struct pinconf_ops *ops = pctldev->desc->confops; | ||
30 | |||
31 | if (!ops || !ops->pin_config_get) { | ||
32 | dev_err(&pctldev->dev, "cannot get pin configuration, missing " | ||
33 | "pin_config_get() function in driver\n"); | ||
34 | return -EINVAL; | ||
35 | } | ||
36 | |||
37 | return ops->pin_config_get(pctldev, pin, config); | ||
38 | } | ||
39 | |||
40 | /** | ||
41 | * pin_config_get() - get the configuration of a single pin parameter | ||
42 | * @pctldev: pin controller device for this pin | ||
43 | * @name: name of the pin to get the config for | ||
44 | * @config: the config pointed to by this argument will be filled in with the | ||
45 | * current pin state, it can be used directly by drivers as a numeral, or | ||
46 | * it can be dereferenced to any struct. | ||
47 | */ | ||
48 | int pin_config_get(struct pinctrl_dev *pctldev, const char *name, | ||
49 | unsigned long *config) | ||
50 | { | ||
51 | int pin; | ||
52 | |||
53 | pin = pin_get_from_name(pctldev, name); | ||
54 | if (pin < 0) | ||
55 | return pin; | ||
56 | |||
57 | return pin_config_get_for_pin(pctldev, pin, config); | ||
58 | } | ||
59 | EXPORT_SYMBOL(pin_config_get); | ||
60 | |||
61 | int pin_config_set_for_pin(struct pinctrl_dev *pctldev, unsigned pin, | ||
62 | unsigned long config) | ||
63 | { | ||
64 | const struct pinconf_ops *ops = pctldev->desc->confops; | ||
65 | int ret; | ||
66 | |||
67 | if (!ops || !ops->pin_config_set) { | ||
68 | dev_err(&pctldev->dev, "cannot configure pin, missing " | ||
69 | "config function in driver\n"); | ||
70 | return -EINVAL; | ||
71 | } | ||
72 | |||
73 | ret = ops->pin_config_set(pctldev, pin, config); | ||
74 | if (ret) { | ||
75 | dev_err(&pctldev->dev, | ||
76 | "unable to set pin configuration on pin %d\n", pin); | ||
77 | return ret; | ||
78 | } | ||
79 | |||
80 | return 0; | ||
81 | } | ||
82 | |||
83 | /** | ||
84 | * pin_config_set() - set the configuration of a single pin parameter | ||
85 | * @pctldev: pin controller device for this pin | ||
86 | * @name: name of the pin to set the config for | ||
87 | * @config: the config in this argument will contain the desired pin state, it | ||
88 | * can be used directly by drivers as a numeral, or it can be dereferenced | ||
89 | * to any struct. | ||
90 | */ | ||
91 | int pin_config_set(struct pinctrl_dev *pctldev, const char *name, | ||
92 | unsigned long config) | ||
93 | { | ||
94 | int pin; | ||
95 | |||
96 | pin = pin_get_from_name(pctldev, name); | ||
97 | if (pin < 0) | ||
98 | return pin; | ||
99 | |||
100 | return pin_config_set_for_pin(pctldev, pin, config); | ||
101 | } | ||
102 | EXPORT_SYMBOL(pin_config_set); | ||
103 | |||
104 | int pin_config_group_get(struct pinctrl_dev *pctldev, const char *pin_group, | ||
105 | unsigned long *config) | ||
106 | { | ||
107 | const struct pinconf_ops *ops = pctldev->desc->confops; | ||
108 | int selector; | ||
109 | |||
110 | if (!ops || !ops->pin_config_group_get) { | ||
111 | dev_err(&pctldev->dev, "cannot get configuration for pin " | ||
112 | "group, missing group config get function in " | ||
113 | "driver\n"); | ||
114 | return -EINVAL; | ||
115 | } | ||
116 | |||
117 | selector = pinctrl_get_group_selector(pctldev, pin_group); | ||
118 | if (selector < 0) | ||
119 | return selector; | ||
120 | |||
121 | return ops->pin_config_group_get(pctldev, selector, config); | ||
122 | } | ||
123 | EXPORT_SYMBOL(pin_config_group_get); | ||
124 | |||
125 | |||
126 | int pin_config_group_set(struct pinctrl_dev *pctldev, const char *pin_group, | ||
127 | unsigned long config) | ||
128 | { | ||
129 | const struct pinctrl_ops *pctlops = pctldev->desc->pctlops; | ||
130 | const struct pinconf_ops *ops = pctldev->desc->confops; | ||
131 | int selector; | ||
132 | const unsigned *pins; | ||
133 | unsigned num_pins; | ||
134 | int ret; | ||
135 | int i; | ||
136 | |||
137 | if (!ops || (!ops->pin_config_group_set && !ops->pin_config_set)) { | ||
138 | dev_err(&pctldev->dev, "cannot configure pin group, missing " | ||
139 | "config function in driver\n"); | ||
140 | return -EINVAL; | ||
141 | } | ||
142 | |||
143 | selector = pinctrl_get_group_selector(pctldev, pin_group); | ||
144 | if (selector < 0) | ||
145 | return selector; | ||
146 | |||
147 | ret = pctlops->get_group_pins(pctldev, selector, &pins, &num_pins); | ||
148 | if (ret) { | ||
149 | dev_err(&pctldev->dev, "cannot configure pin group, error " | ||
150 | "getting pins\n"); | ||
151 | return ret; | ||
152 | } | ||
153 | |||
154 | /* | ||
155 | * If the pin controller supports handling entire groups we use that | ||
156 | * capability. | ||
157 | */ | ||
158 | if (ops->pin_config_group_set) { | ||
159 | ret = ops->pin_config_group_set(pctldev, selector, config); | ||
160 | /* | ||
161 | * If the pin controller prefer that a certain group be handled | ||
162 | * pin-by-pin as well, it returns -EAGAIN. | ||
163 | */ | ||
164 | if (ret != -EAGAIN) | ||
165 | return ret; | ||
166 | } | ||
167 | |||
168 | /* | ||
169 | * If the controller cannot handle entire groups, we configure each pin | ||
170 | * individually. | ||
171 | */ | ||
172 | if (!ops->pin_config_set) | ||
173 | return 0; | ||
174 | |||
175 | for (i = 0; i < num_pins; i++) { | ||
176 | ret = ops->pin_config_set(pctldev, pins[i], config); | ||
177 | if (ret < 0) | ||
178 | return ret; | ||
179 | } | ||
180 | |||
181 | return 0; | ||
182 | } | ||
183 | EXPORT_SYMBOL(pin_config_group_set); | ||
184 | |||
185 | int pinconf_check_ops(const struct pinconf_ops *ops) | ||
186 | { | ||
187 | /* We must be able to read out pin status */ | ||
188 | if (!ops->pin_config_get && !ops->pin_config_group_get) | ||
189 | return -EINVAL; | ||
190 | /* We have to be able to config the pins in SOME way */ | ||
191 | if (!ops->pin_config_set && !ops->pin_config_group_set) | ||
192 | return -EINVAL; | ||
193 | return 0; | ||
194 | } | ||
195 | |||
196 | #ifdef CONFIG_DEBUG_FS | ||
197 | |||
198 | static void pinconf_dump_pin(struct pinctrl_dev *pctldev, | ||
199 | struct seq_file *s, int pin) | ||
200 | { | ||
201 | const struct pinconf_ops *ops = pctldev->desc->confops; | ||
202 | |||
203 | if (ops && ops->pin_config_dbg_show) | ||
204 | ops->pin_config_dbg_show(pctldev, s, pin); | ||
205 | } | ||
206 | |||
207 | static int pinconf_pins_show(struct seq_file *s, void *what) | ||
208 | { | ||
209 | struct pinctrl_dev *pctldev = s->private; | ||
210 | unsigned pin; | ||
211 | |||
212 | seq_puts(s, "Pin config settings per pin\n"); | ||
213 | seq_puts(s, "Format: pin (name): pinmux setting array\n"); | ||
214 | |||
215 | /* The highest pin number need to be included in the loop, thus <= */ | ||
216 | for (pin = 0; pin <= pctldev->desc->maxpin; pin++) { | ||
217 | struct pin_desc *desc; | ||
218 | |||
219 | desc = pin_desc_get(pctldev, pin); | ||
220 | /* Pin space may be sparse */ | ||
221 | if (desc == NULL) | ||
222 | continue; | ||
223 | |||
224 | seq_printf(s, "pin %d (%s):", pin, | ||
225 | desc->name ? desc->name : "unnamed"); | ||
226 | |||
227 | pinconf_dump_pin(pctldev, s, pin); | ||
228 | |||
229 | seq_printf(s, "\n"); | ||
230 | } | ||
231 | |||
232 | return 0; | ||
233 | } | ||
234 | |||
235 | static void pinconf_dump_group(struct pinctrl_dev *pctldev, | ||
236 | struct seq_file *s, unsigned selector, | ||
237 | const char *gname) | ||
238 | { | ||
239 | const struct pinconf_ops *ops = pctldev->desc->confops; | ||
240 | |||
241 | if (ops && ops->pin_config_group_dbg_show) | ||
242 | ops->pin_config_group_dbg_show(pctldev, s, selector); | ||
243 | } | ||
244 | |||
245 | static int pinconf_groups_show(struct seq_file *s, void *what) | ||
246 | { | ||
247 | struct pinctrl_dev *pctldev = s->private; | ||
248 | const struct pinctrl_ops *pctlops = pctldev->desc->pctlops; | ||
249 | const struct pinconf_ops *ops = pctldev->desc->confops; | ||
250 | unsigned selector = 0; | ||
251 | |||
252 | if (!ops || !ops->pin_config_group_get) | ||
253 | return 0; | ||
254 | |||
255 | seq_puts(s, "Pin config settings per pin group\n"); | ||
256 | seq_puts(s, "Format: group (name): pinmux setting array\n"); | ||
257 | |||
258 | while (pctlops->list_groups(pctldev, selector) >= 0) { | ||
259 | const char *gname = pctlops->get_group_name(pctldev, selector); | ||
260 | |||
261 | seq_printf(s, "%u (%s):", selector, gname); | ||
262 | pinconf_dump_group(pctldev, s, selector, gname); | ||
263 | selector++; | ||
264 | } | ||
265 | |||
266 | return 0; | ||
267 | } | ||
268 | |||
269 | static int pinconf_pins_open(struct inode *inode, struct file *file) | ||
270 | { | ||
271 | return single_open(file, pinconf_pins_show, inode->i_private); | ||
272 | } | ||
273 | |||
274 | static int pinconf_groups_open(struct inode *inode, struct file *file) | ||
275 | { | ||
276 | return single_open(file, pinconf_groups_show, inode->i_private); | ||
277 | } | ||
278 | |||
279 | static const struct file_operations pinconf_pins_ops = { | ||
280 | .open = pinconf_pins_open, | ||
281 | .read = seq_read, | ||
282 | .llseek = seq_lseek, | ||
283 | .release = single_release, | ||
284 | }; | ||
285 | |||
286 | static const struct file_operations pinconf_groups_ops = { | ||
287 | .open = pinconf_groups_open, | ||
288 | .read = seq_read, | ||
289 | .llseek = seq_lseek, | ||
290 | .release = single_release, | ||
291 | }; | ||
292 | |||
293 | void pinconf_init_device_debugfs(struct dentry *devroot, | ||
294 | struct pinctrl_dev *pctldev) | ||
295 | { | ||
296 | debugfs_create_file("pinconf-pins", S_IFREG | S_IRUGO, | ||
297 | devroot, pctldev, &pinconf_pins_ops); | ||
298 | debugfs_create_file("pinconf-groups", S_IFREG | S_IRUGO, | ||
299 | devroot, pctldev, &pinconf_groups_ops); | ||
300 | } | ||
301 | |||
302 | #endif | ||
diff --git a/drivers/pinctrl/pinconf.h b/drivers/pinctrl/pinconf.h new file mode 100644 index 000000000000..e7dc6165032a --- /dev/null +++ b/drivers/pinctrl/pinconf.h | |||
@@ -0,0 +1,36 @@ | |||
1 | /* | ||
2 | * Internal interface between the core pin control system and the | ||
3 | * pin config portions | ||
4 | * | ||
5 | * Copyright (C) 2011 ST-Ericsson SA | ||
6 | * Written on behalf of Linaro for ST-Ericsson | ||
7 | * Based on bits of regulator core, gpio core and clk core | ||
8 | * | ||
9 | * Author: Linus Walleij <linus.walleij@linaro.org> | ||
10 | * | ||
11 | * License terms: GNU General Public License (GPL) version 2 | ||
12 | */ | ||
13 | |||
14 | #ifdef CONFIG_PINCONF | ||
15 | |||
16 | int pinconf_check_ops(const struct pinconf_ops *ops); | ||
17 | void pinconf_init_device_debugfs(struct dentry *devroot, | ||
18 | struct pinctrl_dev *pctldev); | ||
19 | int pin_config_get_for_pin(struct pinctrl_dev *pctldev, unsigned pin, | ||
20 | unsigned long *config); | ||
21 | int pin_config_set_for_pin(struct pinctrl_dev *pctldev, unsigned pin, | ||
22 | unsigned long config); | ||
23 | |||
24 | #else | ||
25 | |||
26 | static inline int pinconf_check_ops(const struct pinconf_ops *ops) | ||
27 | { | ||
28 | return 0; | ||
29 | } | ||
30 | |||
31 | static inline void pinconf_init_device_debugfs(struct dentry *devroot, | ||
32 | struct pinctrl_dev *pctldev) | ||
33 | { | ||
34 | } | ||
35 | |||
36 | #endif | ||
diff --git a/include/linux/pinctrl/pinconf.h b/include/linux/pinctrl/pinconf.h new file mode 100644 index 000000000000..d5b72e6e261d --- /dev/null +++ b/include/linux/pinctrl/pinconf.h | |||
@@ -0,0 +1,96 @@ | |||
1 | /* | ||
2 | * Interface the pinconfig portions of the pinctrl subsystem | ||
3 | * | ||
4 | * Copyright (C) 2011 ST-Ericsson SA | ||
5 | * Written on behalf of Linaro for ST-Ericsson | ||
6 | * This interface is used in the core to keep track of pins. | ||
7 | * | ||
8 | * Author: Linus Walleij <linus.walleij@linaro.org> | ||
9 | * | ||
10 | * License terms: GNU General Public License (GPL) version 2 | ||
11 | */ | ||
12 | #ifndef __LINUX_PINCTRL_PINCONF_H | ||
13 | #define __LINUX_PINCTRL_PINCONF_H | ||
14 | |||
15 | #ifdef CONFIG_PINCONF | ||
16 | |||
17 | struct pinctrl_dev; | ||
18 | |||
19 | /** | ||
20 | * struct pinconf_ops - pin config operations, to be implemented by | ||
21 | * pin configuration capable drivers. | ||
22 | * @pin_config_get: get the config of a certain pin, if the requested config | ||
23 | * is not available on this controller this should return -ENOTSUPP | ||
24 | * and if it is available but disabled it should return -EINVAL | ||
25 | * @pin_config_get: get the config of a certain pin | ||
26 | * @pin_config_set: configure an individual pin | ||
27 | * @pin_config_group_get: get configurations for an entire pin group | ||
28 | * @pin_config_group_set: configure all pins in a group | ||
29 | * @pin_config_dbg_show: optional debugfs display hook that will provide | ||
30 | * per-device info for a certain pin in debugfs | ||
31 | * @pin_config_group_dbg_show: optional debugfs display hook that will provide | ||
32 | * per-device info for a certain group in debugfs | ||
33 | */ | ||
34 | struct pinconf_ops { | ||
35 | int (*pin_config_get) (struct pinctrl_dev *pctldev, | ||
36 | unsigned pin, | ||
37 | unsigned long *config); | ||
38 | int (*pin_config_set) (struct pinctrl_dev *pctldev, | ||
39 | unsigned pin, | ||
40 | unsigned long config); | ||
41 | int (*pin_config_group_get) (struct pinctrl_dev *pctldev, | ||
42 | unsigned selector, | ||
43 | unsigned long *config); | ||
44 | int (*pin_config_group_set) (struct pinctrl_dev *pctldev, | ||
45 | unsigned selector, | ||
46 | unsigned long config); | ||
47 | void (*pin_config_dbg_show) (struct pinctrl_dev *pctldev, | ||
48 | struct seq_file *s, | ||
49 | unsigned offset); | ||
50 | void (*pin_config_group_dbg_show) (struct pinctrl_dev *pctldev, | ||
51 | struct seq_file *s, | ||
52 | unsigned selector); | ||
53 | }; | ||
54 | |||
55 | extern int pin_config_get(struct pinctrl_dev *pctldev, const char *name, | ||
56 | unsigned long *config); | ||
57 | extern int pin_config_set(struct pinctrl_dev *pctldev, const char *name, | ||
58 | unsigned long config); | ||
59 | extern int pin_config_group_get(struct pinctrl_dev *pctldev, | ||
60 | const char *pin_group, | ||
61 | unsigned long *config); | ||
62 | extern int pin_config_group_set(struct pinctrl_dev *pctldev, | ||
63 | const char *pin_group, | ||
64 | unsigned long config); | ||
65 | |||
66 | #else | ||
67 | |||
68 | static inline int pin_config_get(struct pinctrl_dev *pctldev, const char *name, | ||
69 | unsigned long *config) | ||
70 | { | ||
71 | return 0; | ||
72 | } | ||
73 | |||
74 | static inline int pin_config_set(struct pinctrl_dev *pctldev, const char *name, | ||
75 | unsigned long config) | ||
76 | { | ||
77 | return 0; | ||
78 | } | ||
79 | |||
80 | static inline int pin_config_group_get(struct pinctrl_dev *pctldev, | ||
81 | const char *pin_group, | ||
82 | unsigned long *config) | ||
83 | { | ||
84 | return 0; | ||
85 | } | ||
86 | |||
87 | static inline int pin_config_group_set(struct pinctrl_dev *pctldev, | ||
88 | const char *pin_group, | ||
89 | unsigned long config) | ||
90 | { | ||
91 | return 0; | ||
92 | } | ||
93 | |||
94 | #endif | ||
95 | |||
96 | #endif /* __LINUX_PINCTRL_PINCONF_H */ | ||
diff --git a/include/linux/pinctrl/pinctrl.h b/include/linux/pinctrl/pinctrl.h index f17fac4b51f1..9809a94f151b 100644 --- a/include/linux/pinctrl/pinctrl.h +++ b/include/linux/pinctrl/pinctrl.h | |||
@@ -21,6 +21,7 @@ | |||
21 | 21 | ||
22 | struct pinctrl_dev; | 22 | struct pinctrl_dev; |
23 | struct pinmux_ops; | 23 | struct pinmux_ops; |
24 | struct pinconf_ops; | ||
24 | struct gpio_chip; | 25 | struct gpio_chip; |
25 | 26 | ||
26 | /** | 27 | /** |
@@ -97,7 +98,9 @@ struct pinctrl_ops { | |||
97 | * but may be equal to npins if you have no holes in the pin range. | 98 | * but may be equal to npins if you have no holes in the pin range. |
98 | * @pctlops: pin control operation vtable, to support global concepts like | 99 | * @pctlops: pin control operation vtable, to support global concepts like |
99 | * grouping of pins, this is optional. | 100 | * grouping of pins, this is optional. |
100 | * @pmxops: pinmux operation vtable, if you support pinmuxing in your driver | 101 | * @pmxops: pinmux operations vtable, if you support pinmuxing in your driver |
102 | * @confops: pin config operations vtable, if you support pin configuration in | ||
103 | * your driver | ||
101 | * @owner: module providing the pin controller, used for refcounting | 104 | * @owner: module providing the pin controller, used for refcounting |
102 | */ | 105 | */ |
103 | struct pinctrl_desc { | 106 | struct pinctrl_desc { |
@@ -107,6 +110,7 @@ struct pinctrl_desc { | |||
107 | unsigned int maxpin; | 110 | unsigned int maxpin; |
108 | struct pinctrl_ops *pctlops; | 111 | struct pinctrl_ops *pctlops; |
109 | struct pinmux_ops *pmxops; | 112 | struct pinmux_ops *pmxops; |
113 | struct pinconf_ops *confops; | ||
110 | struct module *owner; | 114 | struct module *owner; |
111 | }; | 115 | }; |
112 | 116 | ||
@@ -125,7 +129,7 @@ extern void *pinctrl_dev_get_drvdata(struct pinctrl_dev *pctldev); | |||
125 | 129 | ||
126 | struct pinctrl_dev; | 130 | struct pinctrl_dev; |
127 | 131 | ||
128 | /* Sufficiently stupid default function when pinctrl is not in use */ | 132 | /* Sufficiently stupid default functions when pinctrl is not in use */ |
129 | static inline bool pin_is_valid(struct pinctrl_dev *pctldev, int pin) | 133 | static inline bool pin_is_valid(struct pinctrl_dev *pctldev, int pin) |
130 | { | 134 | { |
131 | return pin >= 0; | 135 | return pin >= 0; |