aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pinctrl
diff options
context:
space:
mode:
authorLinus Walleij <linus.walleij@linaro.org>2011-10-19 12:14:33 -0400
committerLinus Walleij <linus.walleij@linaro.org>2012-01-03 03:10:04 -0500
commitae6b4d8588f4fc95520b0e62c4b1f474c82191a9 (patch)
tree3da8e553a6374f02e89b5a6ba52b83f34c3abea2 /drivers/pinctrl
parentb4e3ac74d5cd4152f2ec6b3280b1ff3428952f7f (diff)
pinctrl: add a pin config interface
This add per-pin and per-group pin config interfaces for biasing, driving and other such electronic properties. The details of passed configurations are passed in an opaque unsigned long which may be dereferences to integer types, structs or lists on either side of the configuration interface. ChangeLog v1->v2: - Clear split of terminology: we now have pin controllers, and those may support two interfaces using vtables: pin multiplexing and pin configuration. - Break out pin configuration to its own C file, controllers may implement only config without mux, and vice versa, so keep each sub-functionality of pin controllers separate. Introduce CONFIG_PINCONF in Kconfig. - Implement some core logic around pin configuration in the pinconf.c file. - Remove UNKNOWN config states, these were just surplus baggage. - Remove FLOAT config state - HIGH_IMPEDANCE should be enough for everyone. - PIN_CONFIG_POWER_SOURCE added to handle switching the power supply for the pin logic between different sources - Explicit DISABLE config enums to turn schmitt-trigger, wakeup etc OFF. - Update documentation to reflect all the recent reasoning. ChangeLog v2->v3: - Twist API around to pass around arrays of config tuples instead of (param, value) pairs everywhere. - Explicit drive strength semantics for push/pull and similar drive modes, this shall be the number of drive stages vs nominal load impedance, which should match the actual electronics used in push/pull CMOS or TTY totempoles. - Drop load capacitance configuration - I probably don't know what I'm doing here so leave it out. - Drop PIN_CONFIG_INPUT_SCHMITT_OFF, instead the argument zero to PIN_CONFIG_INPUT_SCHMITT turns schmitt trigger off. - Drop PIN_CONFIG_NORMAL_POWER_MODE and have a well defined argument to PIN_CONFIG_LOW_POWER_MODE to get out of it instead. - Drop PIN_CONFIG_WAKEUP_ENABLE/DISABLE and just use PIN_CONFIG_WAKEUP with defined value zero to turn wakeup off. - Add PIN_CONFIG_INPUT_DEBOUNCE for configuring debounce time on input lines. - Fix a bug when we tried to configure pins for pin controllers without pinconf support. - Initialized debugfs properly so it works. - Initialize the mutex properly and lock around config tampering sections. - Check the return value from get_initial_config() properly. ChangeLog v3->v4: - Export the pin_config_get(), pin_config_set() and pin_config_group() functions. - Drop the entire concept of just getting initial config and keeping track of pin states internally, instead ask the pins what state they are in. Previous idea was plain wrong, if the device cannot keep track of its state, the driver should do it. - Drop the generic configuration layout, it seems this impose too much restriction on some pin controllers, so let them do things the way they want and split off support for generic config as an optional add-on. ChangeLog v4->v5: - Introduce two symmetric driver calls for group configuration, .pin_config_group_[get|set] and corresponding external calls. - Remove generic semantic meanings of return values from config calls, these belong in the generic config patch. Just pass the return value through instead. - Add a debugfs entry "pinconf-groups" to read status from group configuration only, also slam in a per-group debug callback in the pinconf_ops so custom drivers can display something meaningful for their pins. - Fix some dangling newline. - Drop dangling #else clause. - Update documentation to match the above. ChangeLog v5->v6: - Change to using a pin name as parameter for the [get|set]_config() functions, as suggested by Stephen Warren. This is more natural as names will be what a developer has access to in written documentation etc. ChangeLog v6->v7: - Refactor out by-pin and by-name get/set functions, only expose the by-name functions externally, expose the by-pin functions internally. - Show supported pin control functionality in the debugfs pinctrl-devices file. Acked-by: Stephen Warren <swarren@nvidia.com> Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Diffstat (limited to 'drivers/pinctrl')
-rw-r--r--drivers/pinctrl/Kconfig5
-rw-r--r--drivers/pinctrl/Makefile1
-rw-r--r--drivers/pinctrl/core.c43
-rw-r--r--drivers/pinctrl/core.h5
-rw-r--r--drivers/pinctrl/pinconf.c302
-rw-r--r--drivers/pinctrl/pinconf.h36
6 files changed, 390 insertions, 2 deletions
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
14config PINMUX 14config PINMUX
15 bool "Support pinmux controllers" 15 bool "Support pin multiplexing controllers"
16
17config PINCONF
18 bool "Support pin configuration controllers"
16 19
17config DEBUG_PINCTRL 20config 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
5obj-$(CONFIG_PINCTRL) += core.o 5obj-$(CONFIG_PINCTRL) += core.o
6obj-$(CONFIG_PINMUX) += pinmux.o 6obj-$(CONFIG_PINMUX) += pinmux.o
7obj-$(CONFIG_PINCONF) += pinconf.o
7obj-$(CONFIG_PINMUX_SIRF) += pinmux-sirf.o 8obj-$(CONFIG_PINMUX_SIRF) += pinmux-sirf.o
8obj-$(CONFIG_PINMUX_U300) += pinmux-u300.o 9obj-$(CONFIG_PINMUX_U300) += pinmux-u300.o
9obj-$(CONFIG_PINCTRL_COH901) += pinctrl-coh901.o 10obj-$(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 */
33static DEFINE_MUTEX(pinctrldev_list_mutex); 34static 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 */
109int 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
497static void pinctrl_init_debugfs(void) 528static 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
14struct 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 {
66struct pinctrl_dev *get_pinctrl_dev_from_dev(struct device *dev, 70struct pinctrl_dev *get_pinctrl_dev_from_dev(struct device *dev,
67 const char *dev_name); 71 const char *dev_name);
68struct pin_desc *pin_desc_get(struct pinctrl_dev *pctldev, unsigned int pin); 72struct pin_desc *pin_desc_get(struct pinctrl_dev *pctldev, unsigned int pin);
73int pin_get_from_name(struct pinctrl_dev *pctldev, const char *name);
69int pinctrl_get_device_gpio_range(unsigned gpio, 74int 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
26int 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 */
48int 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}
59EXPORT_SYMBOL(pin_config_get);
60
61int 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 */
91int 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}
102EXPORT_SYMBOL(pin_config_set);
103
104int 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}
123EXPORT_SYMBOL(pin_config_group_get);
124
125
126int 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}
183EXPORT_SYMBOL(pin_config_group_set);
184
185int 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
198static 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
207static 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
235static 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
245static 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
269static int pinconf_pins_open(struct inode *inode, struct file *file)
270{
271 return single_open(file, pinconf_pins_show, inode->i_private);
272}
273
274static int pinconf_groups_open(struct inode *inode, struct file *file)
275{
276 return single_open(file, pinconf_groups_show, inode->i_private);
277}
278
279static 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
286static 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
293void 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
16int pinconf_check_ops(const struct pinconf_ops *ops);
17void pinconf_init_device_debugfs(struct dentry *devroot,
18 struct pinctrl_dev *pctldev);
19int pin_config_get_for_pin(struct pinctrl_dev *pctldev, unsigned pin,
20 unsigned long *config);
21int pin_config_set_for_pin(struct pinctrl_dev *pctldev, unsigned pin,
22 unsigned long config);
23
24#else
25
26static inline int pinconf_check_ops(const struct pinconf_ops *ops)
27{
28 return 0;
29}
30
31static inline void pinconf_init_device_debugfs(struct dentry *devroot,
32 struct pinctrl_dev *pctldev)
33{
34}
35
36#endif