diff options
-rw-r--r-- | drivers/pinctrl/Kconfig | 4 | ||||
-rw-r--r-- | drivers/pinctrl/Makefile | 1 | ||||
-rw-r--r-- | drivers/pinctrl/pinconf-generic.c | 120 | ||||
-rw-r--r-- | drivers/pinctrl/pinconf.c | 6 | ||||
-rw-r--r-- | drivers/pinctrl/pinconf.h | 43 | ||||
-rw-r--r-- | include/linux/pinctrl/pinconf-generic.h | 114 | ||||
-rw-r--r-- | include/linux/pinctrl/pinconf.h | 5 |
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 | |||
17 | config PINCONF | 17 | config PINCONF |
18 | bool "Support pin configuration controllers" | 18 | bool "Support pin configuration controllers" |
19 | 19 | ||
20 | config GENERIC_PINCONF | ||
21 | bool | ||
22 | select PINCONF | ||
23 | |||
20 | config DEBUG_PINCTRL | 24 | config 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 | |||
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_PINCONF) += pinconf.o |
8 | obj-$(CONFIG_GENERIC_PINCONF) += pinconf-generic.o | ||
8 | obj-$(CONFIG_PINCTRL_PXA3xx) += pinctrl-pxa3xx.o | 9 | obj-$(CONFIG_PINCTRL_PXA3xx) += pinctrl-pxa3xx.o |
9 | obj-$(CONFIG_PINCTRL_MMP2) += pinctrl-mmp2.o | 10 | obj-$(CONFIG_PINCTRL_MMP2) += pinctrl-mmp2.o |
10 | obj-$(CONFIG_PINCTRL_PXA168) += pinctrl-pxa168.o | 11 | obj-$(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 | |||
28 | struct 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 | |||
36 | struct 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 | |||
50 | void 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 | |||
85 | void 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 | ||
57 | static int pin_config_get_for_pin(struct pinctrl_dev *pctldev, unsigned pin, | 57 | int 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 | ||
16 | int pinconf_check_ops(struct pinctrl_dev *pctldev); | 16 | int pinconf_check_ops(struct pinctrl_dev *pctldev); |
17 | |||
18 | int pinconf_validate_map(struct pinctrl_map const *map, int i); | 17 | int pinconf_validate_map(struct pinctrl_map const *map, int i); |
19 | |||
20 | int pinconf_map_to_setting(struct pinctrl_map const *map, | 18 | int pinconf_map_to_setting(struct pinctrl_map const *map, |
21 | struct pinctrl_setting *setting); | 19 | struct pinctrl_setting *setting); |
22 | void pinconf_free_setting(struct pinctrl_setting const *setting); | 20 | void pinconf_free_setting(struct pinctrl_setting const *setting); |
23 | int pinconf_apply_setting(struct pinctrl_setting const *setting); | 21 | int pinconf_apply_setting(struct pinctrl_setting const *setting); |
24 | |||
25 | void pinconf_show_map(struct seq_file *s, struct pinctrl_map const *map); | 22 | void pinconf_show_map(struct seq_file *s, struct pinctrl_map const *map); |
26 | void pinconf_show_setting(struct seq_file *s, | 23 | void pinconf_show_setting(struct seq_file *s, |
27 | struct pinctrl_setting const *setting); | 24 | struct pinctrl_setting const *setting); |
28 | void pinconf_init_device_debugfs(struct dentry *devroot, | 25 | void 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 | */ | ||
32 | int pin_config_get_for_pin(struct pinctrl_dev *pctldev, unsigned pin, | ||
33 | unsigned long *config); | ||
34 | int pin_config_group_get(const char *dev_name, const char *pin_group, | ||
35 | unsigned long *config); | ||
36 | |||
31 | #else | 37 | #else |
32 | 38 | ||
33 | static inline int pinconf_check_ops(struct pinctrl_dev *pctldev) | 39 | static 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 | |||
88 | void pinconf_generic_dump_pin(struct pinctrl_dev *pctldev, | ||
89 | struct seq_file *s, unsigned pin); | ||
90 | |||
91 | void pinconf_generic_dump_group(struct pinctrl_dev *pctldev, | ||
92 | struct seq_file *s, const char *gname); | ||
93 | |||
94 | #else | ||
95 | |||
96 | static inline void pinconf_generic_dump_pin(struct pinctrl_dev *pctldev, | ||
97 | struct seq_file *s, | ||
98 | unsigned pin) | ||
99 | { | ||
100 | return; | ||
101 | } | ||
102 | |||
103 | static 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 | */ | ||
69 | enum 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 | |||
96 | static inline enum pin_config_param pinconf_to_config_param(unsigned long config) | ||
97 | { | ||
98 | return (enum pin_config_param) (config & 0xffffUL); | ||
99 | } | ||
100 | |||
101 | static inline u16 pinconf_to_config_argument(unsigned long config) | ||
102 | { | ||
103 | return (enum pin_config_param) ((config >> 16) & 0xffffUL); | ||
104 | } | ||
105 | |||
106 | static 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 | */ |
35 | struct pinconf_ops { | 37 | struct 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); |