aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/pinctrl/Kconfig4
-rw-r--r--drivers/pinctrl/Makefile1
-rw-r--r--drivers/pinctrl/pinconf-generic.c120
-rw-r--r--drivers/pinctrl/pinconf.c6
-rw-r--r--drivers/pinctrl/pinconf.h43
-rw-r--r--include/linux/pinctrl/pinconf-generic.h114
-rw-r--r--include/linux/pinctrl/pinconf.h5
7 files changed, 289 insertions, 4 deletions
diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig
index c6d29ff61d7..07f3d8d3858 100644
--- a/drivers/pinctrl/Kconfig
+++ b/drivers/pinctrl/Kconfig
@@ -17,6 +17,10 @@ config PINMUX
17config PINCONF 17config PINCONF
18 bool "Support pin configuration controllers" 18 bool "Support pin configuration controllers"
19 19
20config GENERIC_PINCONF
21 bool
22 select PINCONF
23
20config DEBUG_PINCTRL 24config DEBUG_PINCTRL
21 bool "Debug PINCTRL calls" 25 bool "Debug PINCTRL calls"
22 depends on DEBUG_KERNEL 26 depends on DEBUG_KERNEL
diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile
index 754329b9c61..6d4150b4ece 100644
--- a/drivers/pinctrl/Makefile
+++ b/drivers/pinctrl/Makefile
@@ -5,6 +5,7 @@ ccflags-$(CONFIG_DEBUG_PINCTRL) += -DDEBUG
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_PINCONF) += pinconf.o
8obj-$(CONFIG_GENERIC_PINCONF) += pinconf-generic.o
8obj-$(CONFIG_PINCTRL_PXA3xx) += pinctrl-pxa3xx.o 9obj-$(CONFIG_PINCTRL_PXA3xx) += pinctrl-pxa3xx.o
9obj-$(CONFIG_PINCTRL_MMP2) += pinctrl-mmp2.o 10obj-$(CONFIG_PINCTRL_MMP2) += pinctrl-mmp2.o
10obj-$(CONFIG_PINCTRL_PXA168) += pinctrl-pxa168.o 11obj-$(CONFIG_PINCTRL_PXA168) += pinctrl-pxa168.o
diff --git a/drivers/pinctrl/pinconf-generic.c b/drivers/pinctrl/pinconf-generic.c
new file mode 100644
index 00000000000..33fbaeaa65d
--- /dev/null
+++ b/drivers/pinctrl/pinconf-generic.c
@@ -0,0 +1,120 @@
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>
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/pinctrl.h>
21#include <linux/pinctrl/pinconf.h>
22#include <linux/pinctrl/pinconf-generic.h>
23#include "core.h"
24#include "pinconf.h"
25
26#ifdef CONFIG_DEBUG_FS
27
28struct pin_config_item {
29 const enum pin_config_param param;
30 const char * const display;
31 const char * const format;
32};
33
34#define PCONFDUMP(a, b, c) { .param = a, .display = b, .format = c }
35
36struct pin_config_item conf_items[] = {
37 PCONFDUMP(PIN_CONFIG_BIAS_DISABLE, "input bias disabled", NULL),
38 PCONFDUMP(PIN_CONFIG_BIAS_HIGH_IMPEDANCE, "input bias high impedance", NULL),
39 PCONFDUMP(PIN_CONFIG_BIAS_PULL_UP, "input bias pull up", NULL),
40 PCONFDUMP(PIN_CONFIG_BIAS_PULL_DOWN, "input bias pull down", NULL),
41 PCONFDUMP(PIN_CONFIG_DRIVE_PUSH_PULL, "output drive push pull", NULL),
42 PCONFDUMP(PIN_CONFIG_DRIVE_OPEN_DRAIN, "output drive open drain", NULL),
43 PCONFDUMP(PIN_CONFIG_DRIVE_OPEN_SOURCE, "output drive open source", NULL),
44 PCONFDUMP(PIN_CONFIG_INPUT_SCHMITT, "input schmitt trigger", NULL),
45 PCONFDUMP(PIN_CONFIG_INPUT_DEBOUNCE, "input debounce", "time units"),
46 PCONFDUMP(PIN_CONFIG_POWER_SOURCE, "pin power source", "selector"),
47 PCONFDUMP(PIN_CONFIG_LOW_POWER_MODE, "pin low power", "mode"),
48};
49
50void pinconf_generic_dump_pin(struct pinctrl_dev *pctldev,
51 struct seq_file *s, unsigned pin)
52{
53 const struct pinconf_ops *ops = pctldev->desc->confops;
54 int i;
55
56 if (!ops->is_generic)
57 return;
58
59 for(i = 0; i < ARRAY_SIZE(conf_items); i++) {
60 unsigned long config;
61 int ret;
62
63 /* We want to check out this parameter */
64 config = pinconf_to_config_packed(conf_items[i].param, 0);
65 ret = pin_config_get_for_pin(pctldev, pin, &config);
66 /* These are legal errors */
67 if (ret == -EINVAL || ret == -ENOTSUPP)
68 continue;
69 if (ret) {
70 seq_printf(s, "ERROR READING CONFIG SETTING %d ", i);
71 continue;
72 }
73 /* Space between multiple configs */
74 seq_puts(s, " ");
75 seq_puts(s, conf_items[i].display);
76 /* Print unit if available */
77 if (conf_items[i].format &&
78 pinconf_to_config_argument(config) != 0)
79 seq_printf(s, " (%u %s)",
80 pinconf_to_config_argument(config),
81 conf_items[i].format);
82 }
83}
84
85void pinconf_generic_dump_group(struct pinctrl_dev *pctldev,
86 struct seq_file *s, const char *gname)
87{
88 const struct pinconf_ops *ops = pctldev->desc->confops;
89 int i;
90
91 if (!ops->is_generic)
92 return;
93
94 for(i = 0; i < ARRAY_SIZE(conf_items); i++) {
95 unsigned long config;
96 int ret;
97
98 /* We want to check out this parameter */
99 config = pinconf_to_config_packed(conf_items[i].param, 0);
100 ret = pin_config_group_get(dev_name(pctldev->dev), gname,
101 &config);
102 /* These are legal errors */
103 if (ret == -EINVAL || ret == -ENOTSUPP)
104 continue;
105 if (ret) {
106 seq_printf(s, "ERROR READING CONFIG SETTING %d ", i);
107 continue;
108 }
109 /* Space between multiple configs */
110 seq_puts(s, " ");
111 seq_puts(s, conf_items[i].display);
112 /* Print unit if available */
113 if (conf_items[i].format && config != 0)
114 seq_printf(s, " (%u %s)",
115 pinconf_to_config_argument(config),
116 conf_items[i].format);
117 }
118}
119
120#endif
diff --git a/drivers/pinctrl/pinconf.c b/drivers/pinctrl/pinconf.c
index b40ac1b4fb1..7321e860129 100644
--- a/drivers/pinctrl/pinconf.c
+++ b/drivers/pinctrl/pinconf.c
@@ -54,7 +54,7 @@ int pinconf_validate_map(struct pinctrl_map const *map, int i)
54 return 0; 54 return 0;
55} 55}
56 56
57static int pin_config_get_for_pin(struct pinctrl_dev *pctldev, unsigned pin, 57int pin_config_get_for_pin(struct pinctrl_dev *pctldev, unsigned pin,
58 unsigned long *config) 58 unsigned long *config)
59{ 59{
60 const struct pinconf_ops *ops = pctldev->desc->confops; 60 const struct pinconf_ops *ops = pctldev->desc->confops;
@@ -439,6 +439,8 @@ static void pinconf_dump_pin(struct pinctrl_dev *pctldev,
439{ 439{
440 const struct pinconf_ops *ops = pctldev->desc->confops; 440 const struct pinconf_ops *ops = pctldev->desc->confops;
441 441
442 /* no-op when not using generic pin config */
443 pinconf_generic_dump_pin(pctldev, s, pin);
442 if (ops && ops->pin_config_dbg_show) 444 if (ops && ops->pin_config_dbg_show)
443 ops->pin_config_dbg_show(pctldev, s, pin); 445 ops->pin_config_dbg_show(pctldev, s, pin);
444} 446}
@@ -482,6 +484,8 @@ static void pinconf_dump_group(struct pinctrl_dev *pctldev,
482{ 484{
483 const struct pinconf_ops *ops = pctldev->desc->confops; 485 const struct pinconf_ops *ops = pctldev->desc->confops;
484 486
487 /* no-op when not using generic pin config */
488 pinconf_generic_dump_group(pctldev, s, gname);
485 if (ops && ops->pin_config_group_dbg_show) 489 if (ops && ops->pin_config_group_dbg_show)
486 ops->pin_config_group_dbg_show(pctldev, s, selector); 490 ops->pin_config_group_dbg_show(pctldev, s, selector);
487} 491}
diff --git a/drivers/pinctrl/pinconf.h b/drivers/pinctrl/pinconf.h
index 0ded227661a..54510de5e8c 100644
--- a/drivers/pinctrl/pinconf.h
+++ b/drivers/pinctrl/pinconf.h
@@ -14,20 +14,26 @@
14#ifdef CONFIG_PINCONF 14#ifdef CONFIG_PINCONF
15 15
16int pinconf_check_ops(struct pinctrl_dev *pctldev); 16int pinconf_check_ops(struct pinctrl_dev *pctldev);
17
18int pinconf_validate_map(struct pinctrl_map const *map, int i); 17int pinconf_validate_map(struct pinctrl_map const *map, int i);
19
20int pinconf_map_to_setting(struct pinctrl_map const *map, 18int pinconf_map_to_setting(struct pinctrl_map const *map,
21 struct pinctrl_setting *setting); 19 struct pinctrl_setting *setting);
22void pinconf_free_setting(struct pinctrl_setting const *setting); 20void pinconf_free_setting(struct pinctrl_setting const *setting);
23int pinconf_apply_setting(struct pinctrl_setting const *setting); 21int pinconf_apply_setting(struct pinctrl_setting const *setting);
24
25void pinconf_show_map(struct seq_file *s, struct pinctrl_map const *map); 22void pinconf_show_map(struct seq_file *s, struct pinctrl_map const *map);
26void pinconf_show_setting(struct seq_file *s, 23void pinconf_show_setting(struct seq_file *s,
27 struct pinctrl_setting const *setting); 24 struct pinctrl_setting const *setting);
28void pinconf_init_device_debugfs(struct dentry *devroot, 25void pinconf_init_device_debugfs(struct dentry *devroot,
29 struct pinctrl_dev *pctldev); 26 struct pinctrl_dev *pctldev);
30 27
28/*
29 * You will only be interested in these if you're using PINCONF
30 * so don't supply any stubs for these.
31 */
32int pin_config_get_for_pin(struct pinctrl_dev *pctldev, unsigned pin,
33 unsigned long *config);
34int pin_config_group_get(const char *dev_name, const char *pin_group,
35 unsigned long *config);
36
31#else 37#else
32 38
33static inline int pinconf_check_ops(struct pinctrl_dev *pctldev) 39static inline int pinconf_check_ops(struct pinctrl_dev *pctldev)
@@ -71,3 +77,34 @@ static inline void pinconf_init_device_debugfs(struct dentry *devroot,
71} 77}
72 78
73#endif 79#endif
80
81/*
82 * The following functions are available if the driver uses the generic
83 * pin config.
84 */
85
86#ifdef CONFIG_GENERIC_PINCONF
87
88void pinconf_generic_dump_pin(struct pinctrl_dev *pctldev,
89 struct seq_file *s, unsigned pin);
90
91void pinconf_generic_dump_group(struct pinctrl_dev *pctldev,
92 struct seq_file *s, const char *gname);
93
94#else
95
96static inline void pinconf_generic_dump_pin(struct pinctrl_dev *pctldev,
97 struct seq_file *s,
98 unsigned pin)
99{
100 return;
101}
102
103static inline void pinconf_generic_dump_group(struct pinctrl_dev *pctldev,
104 struct seq_file *s,
105 const char *gname)
106{
107 return;
108}
109
110#endif
diff --git a/include/linux/pinctrl/pinconf-generic.h b/include/linux/pinctrl/pinconf-generic.h
new file mode 100644
index 00000000000..4f0abb9f1c0
--- /dev/null
+++ b/include/linux/pinctrl/pinconf-generic.h
@@ -0,0 +1,114 @@
1/*
2 * Interface the generic 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_GENERIC_H
13#define __LINUX_PINCTRL_PINCONF_GENERIC_H
14
15/*
16 * You shouldn't even be able to compile with these enums etc unless you're
17 * using generic pin config. That is why this is defined out.
18 */
19#ifdef CONFIG_GENERIC_PINCONF
20
21/**
22 * enum pin_config_param - possible pin configuration parameters
23 * @PIN_CONFIG_BIAS_DISABLE: disable any pin bias on the pin, a
24 * transition from say pull-up to pull-down implies that you disable
25 * pull-up in the process, this setting disables all biasing.
26 * @PIN_CONFIG_BIAS_HIGH_IMPEDANCE: the pin will be set to a high impedance
27 * mode, also know as "third-state" (tristate) or "high-Z" or "floating".
28 * On output pins this effectively disconnects the pin, which is useful
29 * if for example some other pin is going to drive the signal connected
30 * to it for a while. Pins used for input are usually always high
31 * impedance.
32 * @PIN_CONFIG_BIAS_PULL_UP: the pin will be pulled up (usually with high
33 * impedance to VDD). If the argument is != 0 pull-up is enabled,
34 * if it is 0, pull-up is disabled.
35 * @PIN_CONFIG_BIAS_PULL_DOWN: the pin will be pulled down (usually with high
36 * impedance to GROUND). If the argument is != 0 pull-down is enabled,
37 * if it is 0, pull-down is disabled.
38 * @PIN_CONFIG_DRIVE_PUSH_PULL: the pin will be driven actively high and
39 * low, this is the most typical case and is typically achieved with two
40 * active transistors on the output. Sending this config will enabale
41 * push-pull mode, the argument is ignored.
42 * @PIN_CONFIG_DRIVE_OPEN_DRAIN: the pin will be driven with open drain (open
43 * collector) which means it is usually wired with other output ports
44 * which are then pulled up with an external resistor. Sending this
45 * config will enabale open drain mode, the argument is ignored.
46 * @PIN_CONFIG_DRIVE_OPEN_SOURCE: the pin will be driven with open source
47 * (open emitter). Sending this config will enabale open drain mode, the
48 * argument is ignored.
49 * @PIN_CONFIG_INPUT_SCHMITT: this will configure an input pin to run in
50 * schmitt-trigger mode. If the schmitt-trigger has adjustable hysteresis,
51 * the threshold value is given on a custom format as argument when
52 * setting pins to this mode. The argument zero turns the schmitt trigger
53 * off.
54 * @PIN_CONFIG_INPUT_DEBOUNCE: this will configure the pin to debounce mode,
55 * which means it will wait for signals to settle when reading inputs. The
56 * argument gives the debounce time on a custom format. Setting the
57 * argument to zero turns debouncing off.
58 * @PIN_CONFIG_POWER_SOURCE: if the pin can select between different power
59 * supplies, the argument to this parameter (on a custom format) tells
60 * the driver which alternative power source to use.
61 * @PIN_CONFIG_LOW_POWER_MODE: this will configure the pin for low power
62 * operation, if several modes of operation are supported these can be
63 * passed in the argument on a custom form, else just use argument 1
64 * to indicate low power mode, argument 0 turns low power mode off.
65 * @PIN_CONFIG_END: this is the last enumerator for pin configurations, if
66 * you need to pass in custom configurations to the pin controller, use
67 * PIN_CONFIG_END+1 as the base offset.
68 */
69enum pin_config_param {
70 PIN_CONFIG_BIAS_DISABLE,
71 PIN_CONFIG_BIAS_HIGH_IMPEDANCE,
72 PIN_CONFIG_BIAS_PULL_UP,
73 PIN_CONFIG_BIAS_PULL_DOWN,
74 PIN_CONFIG_DRIVE_PUSH_PULL,
75 PIN_CONFIG_DRIVE_OPEN_DRAIN,
76 PIN_CONFIG_DRIVE_OPEN_SOURCE,
77 PIN_CONFIG_INPUT_SCHMITT,
78 PIN_CONFIG_INPUT_DEBOUNCE,
79 PIN_CONFIG_POWER_SOURCE,
80 PIN_CONFIG_LOW_POWER_MODE,
81 PIN_CONFIG_END = 0x7FFF,
82};
83
84/*
85 * Helpful configuration macro to be used in tables etc.
86 */
87#define PIN_CONF_PACKED(p, a) ((a << 16) | ((unsigned long) p & 0xffffUL))
88
89/*
90 * The following inlines stuffs a configuration parameter and data value
91 * into and out of an unsigned long argument, as used by the generic pin config
92 * system. We put the parameter in the lower 16 bits and the argument in the
93 * upper 16 bits.
94 */
95
96static inline enum pin_config_param pinconf_to_config_param(unsigned long config)
97{
98 return (enum pin_config_param) (config & 0xffffUL);
99}
100
101static inline u16 pinconf_to_config_argument(unsigned long config)
102{
103 return (enum pin_config_param) ((config >> 16) & 0xffffUL);
104}
105
106static inline unsigned long pinconf_to_config_packed(enum pin_config_param param,
107 u16 argument)
108{
109 return PIN_CONF_PACKED(param, argument);
110}
111
112#endif /* CONFIG_GENERIC_PINCONF */
113
114#endif /* __LINUX_PINCTRL_PINCONF_GENERIC_H */
diff --git a/include/linux/pinctrl/pinconf.h b/include/linux/pinctrl/pinconf.h
index f8cf156873d..ec431f03362 100644
--- a/include/linux/pinctrl/pinconf.h
+++ b/include/linux/pinctrl/pinconf.h
@@ -20,6 +20,8 @@ struct seq_file;
20/** 20/**
21 * struct pinconf_ops - pin config operations, to be implemented by 21 * struct pinconf_ops - pin config operations, to be implemented by
22 * pin configuration capable drivers. 22 * pin configuration capable drivers.
23 * @is_generic: for pin controllers that want to use the generic interface,
24 * this flag tells the framework that it's generic.
23 * @pin_config_get: get the config of a certain pin, if the requested config 25 * @pin_config_get: get the config of a certain pin, if the requested config
24 * is not available on this controller this should return -ENOTSUPP 26 * is not available on this controller this should return -ENOTSUPP
25 * and if it is available but disabled it should return -EINVAL 27 * and if it is available but disabled it should return -EINVAL
@@ -33,6 +35,9 @@ struct seq_file;
33 * per-device info for a certain group in debugfs 35 * per-device info for a certain group in debugfs
34 */ 36 */
35struct pinconf_ops { 37struct pinconf_ops {
38#ifdef CONFIG_GENERIC_PINCONF
39 bool is_generic;
40#endif
36 int (*pin_config_get) (struct pinctrl_dev *pctldev, 41 int (*pin_config_get) (struct pinctrl_dev *pctldev,
37 unsigned pin, 42 unsigned pin,
38 unsigned long *config); 43 unsigned long *config);