From f59d28dc00ae3f1a76b442dcd0a52d8708c577cc Mon Sep 17 00:00:00 2001 From: Barry Song Date: Fri, 2 Dec 2011 10:32:15 +0800 Subject: [PATCH 01/31] pinctrl/sirf: fix pin number typo for SPI1 Signed-off-by: Barry Song Signed-off-by: Linus Walleij --- drivers/pinctrl/pinmux-sirf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/pinctrl/pinmux-sirf.c b/drivers/pinctrl/pinmux-sirf.c index d76cae6209569..d848d97643788 100644 --- a/drivers/pinctrl/pinmux-sirf.c +++ b/drivers/pinctrl/pinmux-sirf.c @@ -463,7 +463,7 @@ static const struct sirfsoc_padmux spi1_padmux = { .funcval = BIT(8), }; -static const unsigned spi1_pins[] = { 33, 34, 35, 36 }; +static const unsigned spi1_pins[] = { 43, 44, 45, 46 }; static const struct sirfsoc_muxmask sdmmc1_muxmask[] = { { From 3838d3275923d0e0df706d2d32e633839166ccea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Thu, 8 Dec 2011 15:42:45 +0100 Subject: [PATCH 02/31] pinctrl: make the "Debug PINCTRL calls" entry actually do something MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit DEBUG_PINCTRL wasn't used at all and DEBUG_PINMUX doesn't exist. Signed-off-by: Uwe Kleine-König Signed-off-by: Linus Walleij --- drivers/pinctrl/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile index bdc548a6b7e9b..50a2e2f6bc270 100644 --- a/drivers/pinctrl/Makefile +++ b/drivers/pinctrl/Makefile @@ -1,6 +1,6 @@ # generic pinmux support -ccflags-$(CONFIG_DEBUG_PINMUX) += -DDEBUG +ccflags-$(CONFIG_DEBUG_PINCTRL) += -DDEBUG obj-$(CONFIG_PINCTRL) += core.o obj-$(CONFIG_PINMUX) += pinmux.o From cc96ffbb744bff2826aa9e62b14bb599b1f15fc3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Thu, 8 Dec 2011 15:52:15 +0100 Subject: [PATCH 03/31] pinctrl: remove two unused global variables MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Uwe Kleine-König Signed-off-by: Linus Walleij --- drivers/pinctrl/pinmux.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/pinctrl/pinmux.c b/drivers/pinctrl/pinmux.c index a5467f8709e9a..f2c84a90df14f 100644 --- a/drivers/pinctrl/pinmux.c +++ b/drivers/pinctrl/pinmux.c @@ -32,10 +32,6 @@ static DEFINE_MUTEX(pinmux_list_mutex); static LIST_HEAD(pinmux_list); -/* List of pinmux hogs */ -static DEFINE_MUTEX(pinmux_hoglist_mutex); -static LIST_HEAD(pinmux_hoglist); - /* Global pinmux maps, we allow one set only */ static struct pinmux_map const *pinmux_maps; static unsigned pinmux_maps_num; From 07f29ba67b7f016e8c968c8892f277bb50221ad4 Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Thu, 8 Dec 2011 15:16:19 -0700 Subject: [PATCH 04/31] MAINTAINERS: Fix pinctrl subsystem's directory Signed-off-by: Stephen Warren Signed-off-by: Linus Walleij --- MAINTAINERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index 3523ab000f1f9..6eec6ac5d1cbf 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -5128,7 +5128,7 @@ F: drivers/mtd/devices/phram.c PIN CONTROL SUBSYSTEM M: Linus Walleij S: Maintained -F: drivers/pinmux/ +F: drivers/pinctrl/ PKTCDVD DRIVER M: Peter Osterlund From b84e673f51799a2d0bad7a7c1e7a74021c4eba4b Mon Sep 17 00:00:00 2001 From: Rajendra Nayak Date: Tue, 15 Nov 2011 12:10:26 +0530 Subject: [PATCH 05/31] pinctrl: iterate over u300_pmx_mask's in u300_pmx_endisable Fix u300_pmx_endisable() to iterate over the list of 'bits' and 'mask' populated as part of u300_pmx_functions.mask[] Signed-off-by: Rajendra Nayak Signed-off-by: Linus Walleij --- drivers/pinctrl/pinmux-u300.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/pinctrl/pinmux-u300.c b/drivers/pinctrl/pinmux-u300.c index 4858a64131f8e..145a84dc16e6d 100644 --- a/drivers/pinctrl/pinmux-u300.c +++ b/drivers/pinctrl/pinmux-u300.c @@ -940,20 +940,23 @@ static void u300_pmx_endisable(struct u300_pmx *upmx, unsigned selector, { u16 regval, val, mask; int i; + const struct u300_pmx_mask *upmx_mask; + upmx_mask = u300_pmx_functions[selector].mask; for (i = 0; i < ARRAY_SIZE(u300_pmx_registers); i++) { if (enable) - val = u300_pmx_functions[selector].mask->bits; + val = upmx_mask->bits; else val = 0; - mask = u300_pmx_functions[selector].mask->mask; + mask = upmx_mask->mask; if (mask != 0) { regval = readw(upmx->virtbase + u300_pmx_registers[i]); regval &= ~mask; regval |= val; writew(regval, upmx->virtbase + u300_pmx_registers[i]); } + upmx_mask++; } } From 7afde8baa83b9ac409a6db86f27a41878aa6b33f Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Wed, 19 Oct 2011 17:07:16 +0200 Subject: [PATCH 06/31] pinctrl: move group lookup to core Now also the core needs to look up pin groups so move the lookup function there and expose it in the internal header. Acked-by: Stephen Warren Signed-off-by: Linus Walleij --- drivers/pinctrl/core.c | 31 +++++++++++++++++++++++++++++++ drivers/pinctrl/core.h | 2 ++ drivers/pinctrl/pinmux.c | 35 ++--------------------------------- 3 files changed, 35 insertions(+), 33 deletions(-) diff --git a/drivers/pinctrl/core.c b/drivers/pinctrl/core.c index eadef9e191ea5..9970590006d15 100644 --- a/drivers/pinctrl/core.c +++ b/drivers/pinctrl/core.c @@ -284,6 +284,37 @@ void pinctrl_remove_gpio_range(struct pinctrl_dev *pctldev, mutex_unlock(&pctldev->gpio_ranges_lock); } +/** + * pinctrl_get_group_selector() - returns the group selector for a group + * @pctldev: the pin controller handling the group + * @pin_group: the pin group to look up + */ +int pinctrl_get_group_selector(struct pinctrl_dev *pctldev, + const char *pin_group) +{ + const struct pinctrl_ops *pctlops = pctldev->desc->pctlops; + unsigned group_selector = 0; + + while (pctlops->list_groups(pctldev, group_selector) >= 0) { + const char *gname = pctlops->get_group_name(pctldev, + group_selector); + if (!strcmp(gname, pin_group)) { + dev_dbg(&pctldev->dev, + "found group selector %u for %s\n", + group_selector, + pin_group); + return group_selector; + } + + group_selector++; + } + + dev_err(&pctldev->dev, "does not have pin group %s\n", + pin_group); + + return -EINVAL; +} + #ifdef CONFIG_DEBUG_FS static int pinctrl_pins_show(struct seq_file *s, void *what) diff --git a/drivers/pinctrl/core.h b/drivers/pinctrl/core.h index 472fa1341cc0c..dcc6d687b6530 100644 --- a/drivers/pinctrl/core.h +++ b/drivers/pinctrl/core.h @@ -69,3 +69,5 @@ struct pin_desc *pin_desc_get(struct pinctrl_dev *pctldev, int pin); int pinctrl_get_device_gpio_range(unsigned gpio, struct pinctrl_dev **outdev, struct pinctrl_gpio_range **outrange); +int pinctrl_get_group_selector(struct pinctrl_dev *pctldev, + const char *pin_group); diff --git a/drivers/pinctrl/pinmux.c b/drivers/pinctrl/pinmux.c index f2c84a90df14f..72b760bc880a3 100644 --- a/drivers/pinctrl/pinmux.c +++ b/drivers/pinctrl/pinmux.c @@ -389,37 +389,6 @@ static void release_pins(struct pinctrl_dev *pctldev, pin_free(pctldev, pins[i], false); } -/** - * pinmux_get_group_selector() - returns the group selector for a group - * @pctldev: the pin controller handling the group - * @pin_group: the pin group to look up - */ -static int pinmux_get_group_selector(struct pinctrl_dev *pctldev, - const char *pin_group) -{ - const struct pinctrl_ops *pctlops = pctldev->desc->pctlops; - unsigned group_selector = 0; - - while (pctlops->list_groups(pctldev, group_selector) >= 0) { - const char *gname = pctlops->get_group_name(pctldev, - group_selector); - if (!strcmp(gname, pin_group)) { - dev_dbg(&pctldev->dev, - "found group selector %u for %s\n", - group_selector, - pin_group); - return group_selector; - } - - group_selector++; - } - - dev_err(&pctldev->dev, "does not have pin group %s\n", - pin_group); - - return -EINVAL; -} - /** * pinmux_check_pin_group() - check function and pin group combo * @pctldev: device to check the pin group vs function for @@ -461,7 +430,7 @@ static int pinmux_check_pin_group(struct pinctrl_dev *pctldev, return ret; if (num_groups < 1) return -EINVAL; - ret = pinmux_get_group_selector(pctldev, groups[0]); + ret = pinctrl_get_group_selector(pctldev, groups[0]); if (ret < 0) { dev_err(&pctldev->dev, "function %s wants group %s but the pin " @@ -486,7 +455,7 @@ static int pinmux_check_pin_group(struct pinctrl_dev *pctldev, "check if we have pin group %s on controller %s\n", pin_group, pinctrl_dev_get_name(pctldev)); - ret = pinmux_get_group_selector(pctldev, pin_group); + ret = pinctrl_get_group_selector(pctldev, pin_group); if (ret < 0) { dev_dbg(&pctldev->dev, "%s does not support pin group %s with function %s\n", From d2f6a1c6fb0e510a24ccac066eefbcfd0c932858 Mon Sep 17 00:00:00 2001 From: Marek Belisko Date: Wed, 26 Oct 2011 22:57:20 +0200 Subject: [PATCH 07/31] pinctrl: remove double pin validity check. Function pin_is_valid just call pin_desc_get which is in pin_request call some line below. Remove pin_is_valid() check. Acked-by: Stephen Warren Signed-off-by: Marek Belisko Signed-off-by: Linus Walleij --- drivers/pinctrl/pinmux.c | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/drivers/pinctrl/pinmux.c b/drivers/pinctrl/pinmux.c index 72b760bc880a3..17c3931d5ef0b 100644 --- a/drivers/pinctrl/pinmux.c +++ b/drivers/pinctrl/pinmux.c @@ -108,16 +108,6 @@ static int pin_request(struct pinctrl_dev *pctldev, dev_dbg(&pctldev->dev, "request pin %d for %s\n", pin, function); - if (!pin_is_valid(pctldev, pin)) { - dev_err(&pctldev->dev, "pin is invalid\n"); - return -EINVAL; - } - - if (!function) { - dev_err(&pctldev->dev, "no function name given\n"); - return -EINVAL; - } - desc = pin_desc_get(pctldev, pin); if (desc == NULL) { dev_err(&pctldev->dev, @@ -125,6 +115,11 @@ static int pin_request(struct pinctrl_dev *pctldev, goto out; } + if (!function) { + dev_err(&pctldev->dev, "no function name given\n"); + return -EINVAL; + } + spin_lock(&desc->lock); if (desc->mux_function) { spin_unlock(&desc->lock); From 3712a3c488987849613a4ad74129e67e40b12b38 Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Fri, 21 Oct 2011 12:25:53 -0600 Subject: [PATCH 08/31] pinctrl: add explicit gpio_disable_free pinmux_op Some pinctrl drivers (Tegra at least) program a pin to be a GPIO in a completely different manner than they select which function to mux out of that pin. In order to support a single "free" pinmux_op, the driver would need to maintain a per-pin state of requested-for-gpio vs. requested-for- function. However, that's a lot of work when the core already has explicit separate paths for gpio request/free and function request/free. So, add a gpio_disable_free op to struct pinmux_ops, and make pin_free() call it when appropriate. When doing this, I noticed that when calling pin_request(): !!gpio == (gpio_range != NULL) ... and so I collapsed those two parameters in both pin_request(), and when adding writing the new code in pin_free(). Also, for pin_free(): !!free_func == (gpio_range != NULL) However, I didn't want pin_free() to know about the GPIO function naming special case, so instead, I reworked pin_free() to always return the pin's previously requested function, and now pinmux_free_gpio() calls kfree(function). This is much more balanced with the allocation having been performed in pinmux_request_gpio(). Signed-off-by: Stephen Warren Signed-off-by: Linus Walleij --- drivers/pinctrl/pinmux.c | 39 ++++++++++++++++++++++------------ include/linux/pinctrl/pinmux.h | 3 +++ 2 files changed, 28 insertions(+), 14 deletions(-) diff --git a/drivers/pinctrl/pinmux.c b/drivers/pinctrl/pinmux.c index 17c3931d5ef0b..c77aee5508fbc 100644 --- a/drivers/pinctrl/pinmux.c +++ b/drivers/pinctrl/pinmux.c @@ -94,12 +94,11 @@ struct pinmux_hog { * @function: a functional name to give to this pin, passed to the driver * so it knows what function to mux in, e.g. the string "gpioNN" * means that you want to mux in the pin for use as GPIO number NN - * @gpio: if this request concerns a single GPIO pin * @gpio_range: the range matching the GPIO pin if this is a request for a * single GPIO pin */ static int pin_request(struct pinctrl_dev *pctldev, - int pin, const char *function, bool gpio, + int pin, const char *function, struct pinctrl_gpio_range *gpio_range) { struct pin_desc *desc; @@ -143,7 +142,7 @@ static int pin_request(struct pinctrl_dev *pctldev, * If there is no kind of request function for the pin we just assume * we got it by default and proceed. */ - if (gpio && ops->gpio_request_enable) + if (gpio_range && ops->gpio_request_enable) /* This requests and enables a single GPIO pin */ status = ops->gpio_request_enable(pctldev, gpio_range, pin); else if (ops->request) @@ -173,29 +172,39 @@ static int pin_request(struct pinctrl_dev *pctldev, * pin_free() - release a single muxed in pin so something else can be muxed * @pctldev: pin controller device handling this pin * @pin: the pin to free - * @free_func: whether to free the pin's assigned function name string + * @gpio_range: the range matching the GPIO pin if this is a request for a + * single GPIO pin */ -static void pin_free(struct pinctrl_dev *pctldev, int pin, int free_func) +static const char *pin_free(struct pinctrl_dev *pctldev, int pin, + struct pinctrl_gpio_range *gpio_range) { const struct pinmux_ops *ops = pctldev->desc->pmxops; struct pin_desc *desc; + const char *func; desc = pin_desc_get(pctldev, pin); if (desc == NULL) { dev_err(&pctldev->dev, "pin is not registered so it cannot be freed\n"); - return; + return NULL; } - if (ops->free) + /* + * If there is no kind of request function for the pin we just assume + * we got it by default and proceed. + */ + if (gpio_range && ops->gpio_disable_free) + ops->gpio_disable_free(pctldev, gpio_range, pin); + else if (ops->free) ops->free(pctldev, pin); spin_lock(&desc->lock); - if (free_func) - kfree(desc->mux_function); + func = desc->mux_function; desc->mux_function = NULL; spin_unlock(&desc->lock); module_put(pctldev->owner); + + return func; } /** @@ -225,7 +234,7 @@ int pinmux_request_gpio(unsigned gpio) if (!function) return -EINVAL; - ret = pin_request(pctldev, pin, function, true, range); + ret = pin_request(pctldev, pin, function, range); if (ret < 0) kfree(function); @@ -243,6 +252,7 @@ void pinmux_free_gpio(unsigned gpio) struct pinctrl_gpio_range *range; int ret; int pin; + const char *func; ret = pinctrl_get_device_gpio_range(gpio, &pctldev, &range); if (ret) @@ -251,7 +261,8 @@ void pinmux_free_gpio(unsigned gpio) /* Convert to the pin controllers number space */ pin = gpio - range->base; - pin_free(pctldev, pin, true); + func = pin_free(pctldev, pin, range); + kfree(func); } EXPORT_SYMBOL_GPL(pinmux_free_gpio); @@ -341,7 +352,7 @@ static int acquire_pins(struct pinctrl_dev *pctldev, /* Try to allocate all pins in this group, one by one */ for (i = 0; i < num_pins; i++) { - ret = pin_request(pctldev, pins[i], func, false, NULL); + ret = pin_request(pctldev, pins[i], func, NULL); if (ret) { dev_err(&pctldev->dev, "could not get pin %d for function %s " @@ -351,7 +362,7 @@ static int acquire_pins(struct pinctrl_dev *pctldev, /* On error release all taken pins */ i--; /* this pin just failed */ for (; i >= 0; i--) - pin_free(pctldev, pins[i], false); + pin_free(pctldev, pins[i], NULL); return -ENODEV; } } @@ -381,7 +392,7 @@ static void release_pins(struct pinctrl_dev *pctldev, return; } for (i = 0; i < num_pins; i++) - pin_free(pctldev, pins[i], false); + pin_free(pctldev, pins[i], NULL); } /** diff --git a/include/linux/pinctrl/pinmux.h b/include/linux/pinctrl/pinmux.h index 3c430e797efc7..350e32a98c6aa 100644 --- a/include/linux/pinctrl/pinmux.h +++ b/include/linux/pinctrl/pinmux.h @@ -73,6 +73,9 @@ struct pinmux_ops { int (*gpio_request_enable) (struct pinctrl_dev *pctldev, struct pinctrl_gpio_range *range, unsigned offset); + void (*gpio_disable_free) (struct pinctrl_dev *pctldev, + struct pinctrl_gpio_range *range, + unsigned offset); }; /* External interface to pinmux */ From 336cdba09a5df706402628fb20b7660d186aff6c Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Thu, 10 Nov 2011 09:27:41 +0100 Subject: [PATCH 09/31] pinctrl: documentation update MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Update the docs removing an obsolete __refdata tag and document the mysterious return value of pin_free(). And fixes up some various confusions in the pinctrl documentation. Reported-by: Rajendra Nayak Reported-by: Randy Dunlap Reported-by: Thomas Abraham Reported-by: Uwe Kleine-König Acked-by: Stephen Warren Signed-off-by: Linus Walleij --- Documentation/pinctrl.txt | 52 +++++++++++++++++++-------------------- drivers/pinctrl/pinmux.c | 6 ++++- 2 files changed, 31 insertions(+), 27 deletions(-) diff --git a/Documentation/pinctrl.txt b/Documentation/pinctrl.txt index b04cb7d45a163..0a8b2250062a3 100644 --- a/Documentation/pinctrl.txt +++ b/Documentation/pinctrl.txt @@ -32,7 +32,7 @@ Definition of PIN: be sparse - i.e. there may be gaps in the space with numbers where no pin exists. -When a PIN CONTROLLER is instatiated, it will register a descriptor to the +When a PIN CONTROLLER is instantiated, it will register a descriptor to the pin control framework, and this descriptor contains an array of pin descriptors describing the pins handled by this specific pin controller. @@ -61,14 +61,14 @@ this in our driver: #include -const struct pinctrl_pin_desc __refdata foo_pins[] = { - PINCTRL_PIN(0, "A1"), - PINCTRL_PIN(1, "A2"), - PINCTRL_PIN(2, "A3"), +const struct pinctrl_pin_desc foo_pins[] = { + PINCTRL_PIN(0, "A8"), + PINCTRL_PIN(1, "B8"), + PINCTRL_PIN(2, "C8"), ... - PINCTRL_PIN(61, "H6"), - PINCTRL_PIN(62, "H7"), - PINCTRL_PIN(63, "H8"), + PINCTRL_PIN(61, "F1"), + PINCTRL_PIN(62, "G1"), + PINCTRL_PIN(63, "H1"), }; static struct pinctrl_desc foo_desc = { @@ -91,8 +91,8 @@ int __init foo_probe(void) Pins usually have fancier names than this. You can find these in the dataheet for your chip. Notice that the core pinctrl.h file provides a fancy macro called PINCTRL_PIN() to create the struct entries. As you can see I enumerated -the pins from 0 in the upper left corner to 63 in the lower right corner, -this enumeration was arbitrarily chosen, in practice you need to think +the pins from 0 in the upper left corner to 63 in the lower right corner. +This enumeration was arbitrarily chosen, in practice you need to think through your numbering system so that it matches the layout of registers and such things in your driver, or the code may become complicated. You must also consider matching of offsets to the GPIO ranges that may be handled by @@ -133,8 +133,8 @@ struct foo_group { const unsigned num_pins; }; -static unsigned int spi0_pins[] = { 0, 8, 16, 24 }; -static unsigned int i2c0_pins[] = { 24, 25 }; +static const unsigned int spi0_pins[] = { 0, 8, 16, 24 }; +static const unsigned int i2c0_pins[] = { 24, 25 }; static const struct foo_group foo_groups[] = { { @@ -242,7 +242,7 @@ chip a: [32 .. 47] chip b: [48 .. 55] When GPIO-specific functions in the pin control subsystem are called, these -ranges will be used to look up the apropriate pin controller by inspecting +ranges will be used to look up the appropriate pin controller by inspecting and matching the pin to the pin ranges across all controllers. When a pin controller handling the matching range is found, GPIO-specific functions will be called on that specific pin controller. @@ -438,7 +438,7 @@ you. Define enumerators only for the pins you can control if that makes sense. Assumptions: -We assume that the number possible function maps to pin groups is limited by +We assume that the number of possible function maps to pin groups is limited by the hardware. I.e. we assume that there is no system where any function can be mapped to any pin, like in a phone exchange. So the available pins groups for a certain function will be limited to a few choices (say up to eight or so), @@ -585,7 +585,7 @@ int foo_list_funcs(struct pinctrl_dev *pctldev, unsigned selector) const char *foo_get_fname(struct pinctrl_dev *pctldev, unsigned selector) { - return myfuncs[selector].name; + return foo_functions[selector].name; } static int foo_get_groups(struct pinctrl_dev *pctldev, unsigned selector, @@ -600,16 +600,16 @@ static int foo_get_groups(struct pinctrl_dev *pctldev, unsigned selector, int foo_enable(struct pinctrl_dev *pctldev, unsigned selector, unsigned group) { - u8 regbit = (1 << group); + u8 regbit = (1 << selector + group); writeb((readb(MUX)|regbit), MUX) return 0; } -int foo_disable(struct pinctrl_dev *pctldev, unsigned selector, +void foo_disable(struct pinctrl_dev *pctldev, unsigned selector, unsigned group) { - u8 regbit = (1 << group); + u8 regbit = (1 << selector + group); writeb((readb(MUX) & ~(regbit)), MUX) return 0; @@ -683,7 +683,7 @@ spi on the second function mapping: #include -static struct pinmux_map pmx_mapping[] = { +static const struct pinmux_map pmx_mapping[] = { { .ctrl_dev_name = "pinctrl.0", .function = "spi0", @@ -714,7 +714,7 @@ for example if they are not yet instantiated or cumbersome to obtain. You register this pinmux mapping to the pinmux subsystem by simply: - ret = pinmux_register_mappings(&pmx_mapping, ARRAY_SIZE(pmx_mapping)); + ret = pinmux_register_mappings(pmx_mapping, ARRAY_SIZE(pmx_mapping)); Since the above construct is pretty common there is a helper macro to make it even more compact which assumes you want to use pinctrl.0 and position @@ -762,42 +762,42 @@ case), we define a mapping like this: .name "2bit" .ctrl_dev_name = "pinctrl.0", .function = "mmc0", - .group = "mmc0_0_grp", + .group = "mmc0_1_grp", .dev_name = "foo-mmc.0", }, { .name "4bit" .ctrl_dev_name = "pinctrl.0", .function = "mmc0", - .group = "mmc0_0_grp", + .group = "mmc0_1_grp", .dev_name = "foo-mmc.0", }, { .name "4bit" .ctrl_dev_name = "pinctrl.0", .function = "mmc0", - .group = "mmc0_1_grp", + .group = "mmc0_2_grp", .dev_name = "foo-mmc.0", }, { .name "8bit" .ctrl_dev_name = "pinctrl.0", .function = "mmc0", - .group = "mmc0_0_grp", + .group = "mmc0_1_grp", .dev_name = "foo-mmc.0", }, { .name "8bit" .ctrl_dev_name = "pinctrl.0", .function = "mmc0", - .group = "mmc0_1_grp", + .group = "mmc0_2_grp", .dev_name = "foo-mmc.0", }, { .name "8bit" .ctrl_dev_name = "pinctrl.0", .function = "mmc0", - .group = "mmc0_2_grp", + .group = "mmc0_3_grp", .dev_name = "foo-mmc.0", }, ... diff --git a/drivers/pinctrl/pinmux.c b/drivers/pinctrl/pinmux.c index c77aee5508fbc..ee3aba78c3dd6 100644 --- a/drivers/pinctrl/pinmux.c +++ b/drivers/pinctrl/pinmux.c @@ -174,6 +174,10 @@ static int pin_request(struct pinctrl_dev *pctldev, * @pin: the pin to free * @gpio_range: the range matching the GPIO pin if this is a request for a * single GPIO pin + * + * This function returns a pointer to the function name in use. This is used + * for callers that dynamically allocate a function name so it can be freed + * once the pin is free. This is done for GPIO request functions. */ static const char *pin_free(struct pinctrl_dev *pctldev, int pin, struct pinctrl_gpio_range *gpio_range) @@ -919,7 +923,7 @@ int pinmux_hog_maps(struct pinctrl_dev *pctldev) } /** - * pinmux_hog_maps() - unhog specific map entries on controller device + * pinmux_unhog_maps() - unhog specific map entries on controller device * @pctldev: the pin control device to unhog entries on */ void pinmux_unhog_maps(struct pinctrl_dev *pctldev) From 33d58949adee5086478e140751e4a7263bd7e207 Mon Sep 17 00:00:00 2001 From: Marek Belisko Date: Mon, 31 Oct 2011 21:27:52 +0100 Subject: [PATCH 10/31] pinctrl: unify pin type from signed to unsigned We want singned pins to mean "invalid" only on the outside of the subsystem. Signed-off-by: Marek Belisko Signed-off-by: Linus Walleij --- drivers/pinctrl/core.c | 2 +- drivers/pinctrl/core.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/pinctrl/core.c b/drivers/pinctrl/core.c index 9970590006d15..678216652bc0c 100644 --- a/drivers/pinctrl/core.c +++ b/drivers/pinctrl/core.c @@ -88,7 +88,7 @@ struct pinctrl_dev *get_pinctrl_dev_from_dev(struct device *dev, return found ? pctldev : NULL; } -struct pin_desc *pin_desc_get(struct pinctrl_dev *pctldev, int pin) +struct pin_desc *pin_desc_get(struct pinctrl_dev *pctldev, unsigned int pin) { struct pin_desc *pindesc; unsigned long flags; diff --git a/drivers/pinctrl/core.h b/drivers/pinctrl/core.h index dcc6d687b6530..74dee439dcf03 100644 --- a/drivers/pinctrl/core.h +++ b/drivers/pinctrl/core.h @@ -65,7 +65,7 @@ struct pin_desc { struct pinctrl_dev *get_pinctrl_dev_from_dev(struct device *dev, const char *dev_name); -struct pin_desc *pin_desc_get(struct pinctrl_dev *pctldev, int pin); +struct pin_desc *pin_desc_get(struct pinctrl_dev *pctldev, unsigned int pin); int pinctrl_get_device_gpio_range(unsigned gpio, struct pinctrl_dev **outdev, struct pinctrl_gpio_range **outrange); From 3c739ad0df5eb41cd7adad879eda6aa09879eb76 Mon Sep 17 00:00:00 2001 From: Chanho Park Date: Fri, 11 Nov 2011 18:47:58 +0900 Subject: [PATCH 11/31] pinctrl: add a pin_base for sparse gpio-ranges This patch enables mapping a base offset of gpio ranges with a pin offset even if does'nt matched. A base of pinctrl_gpio_range means a base offset of gpio. However, we cannot convert gpio to pin number for sparse gpio ranges just only using a gpio base offset. We can convert a gpio to real pin number(even if not matched) using a new pin_base which means a base pin offset of requested gpio range. Now, the pin control subsystem passes the pin base offset to the pinmux driver. For example, let's assume below two gpio ranges in the system. static struct pinctrl_gpio_range gpio_range_a = { .name = "chip a", .id = 0, .base = 32, .pin_base = 32, .npins = 16, .gc = &chip_a; }; static struct pinctrl_gpio_range gpio_range_b = { .name = "chip b", .id = 0, .base = 48, .pin_base = 64, .npins = 8, .gc = &chip_b; }; We can calucalate a exact pin ranges even if doesn't matched with gpio ranges. chip a: gpio-range : [32 .. 47] pin-range : [32 .. 47] chip b: gpio-range : [48 .. 55] pin-range : [64 .. 71] Signed-off-by: Chanho Park Signed-off-by: Kyungmin Park Signed-off-by: Linus Walleij --- Documentation/pinctrl.txt | 48 ++++++++++++++++----------------- drivers/pinctrl/pinmux-sirf.c | 6 ++++- drivers/pinctrl/pinmux-u300.c | 1 + drivers/pinctrl/pinmux.c | 4 +-- include/linux/pinctrl/pinctrl.h | 2 ++ include/linux/pinctrl/pinmux.h | 2 +- 6 files changed, 34 insertions(+), 29 deletions(-) diff --git a/Documentation/pinctrl.txt b/Documentation/pinctrl.txt index 0a8b2250062a3..43ba411d15713 100644 --- a/Documentation/pinctrl.txt +++ b/Documentation/pinctrl.txt @@ -214,19 +214,20 @@ static struct pinctrl_gpio_range gpio_range_a = { .name = "chip a", .id = 0, .base = 32, + .pin_base = 32, .npins = 16, .gc = &chip_a; }; -static struct pinctrl_gpio_range gpio_range_a = { +static struct pinctrl_gpio_range gpio_range_b = { .name = "chip b", .id = 0, .base = 48, + .pin_base = 64, .npins = 8, .gc = &chip_b; }; - { struct pinctrl_dev *pctl; ... @@ -235,11 +236,24 @@ static struct pinctrl_gpio_range gpio_range_a = { } So this complex system has one pin controller handling two different -GPIO chips. Chip a has 16 pins and chip b has 8 pins. They are mapped in -the global GPIO pin space at: +GPIO chips. "chip a" has 16 pins and "chip b" has 8 pins. The "chip a" and +"chip b" have different .pin_base, which means a start pin number of the +GPIO range. + +The GPIO range of "chip a" starts from the GPIO base of 32 and actual +pin range also starts from 32. However "chip b" has different starting +offset for the GPIO range and pin range. The GPIO range of "chip b" starts +from GPIO number 48, while the pin range of "chip b" starts from 64. -chip a: [32 .. 47] -chip b: [48 .. 55] +We can convert a gpio number to actual pin number using this "pin_base". +They are mapped in the global GPIO pin space at: + +chip a: + - GPIO range : [32 .. 47] + - pin range : [32 .. 47] +chip b: + - GPIO range : [48 .. 55] + - pin range : [64 .. 71] When GPIO-specific functions in the pin control subsystem are called, these ranges will be used to look up the appropriate pin controller by inspecting @@ -249,28 +263,12 @@ will be called on that specific pin controller. For all functionalities dealing with pin biasing, pin muxing etc, the pin controller subsystem will subtract the range's .base offset from the passed -in gpio pin number, and pass that on to the pin control driver, so the driver -will get an offset into its handled number range. Further it is also passed +in gpio number, and add the ranges's .pin_base offset to retrive a pin number. +After that, the subsystem passes it on to the pin control driver, so the driver +will get an pin number into its handled number range. Further it is also passed the range ID value, so that the pin controller knows which range it should deal with. -For example: if a user issues pinctrl_gpio_set_foo(50), the pin control -subsystem will find that the second range on this pin controller matches, -subtract the base 48 and call the -pinctrl_driver_gpio_set_foo(pinctrl, range, 2) where the latter function has -this signature: - -int pinctrl_driver_gpio_set_foo(struct pinctrl_dev *pctldev, - struct pinctrl_gpio_range *rangeid, - unsigned offset); - -Now the driver knows that we want to do some GPIO-specific operation on the -second GPIO range handled by "chip b", at offset 2 in that specific range. - -(If the GPIO subsystem is ever refactored to use a local per-GPIO controller -pin space, this mapping will need to be augmented accordingly.) - - PINMUX interfaces ================= diff --git a/drivers/pinctrl/pinmux-sirf.c b/drivers/pinctrl/pinmux-sirf.c index d848d97643788..99e688e07ea0b 100644 --- a/drivers/pinctrl/pinmux-sirf.c +++ b/drivers/pinctrl/pinmux-sirf.c @@ -1067,7 +1067,7 @@ static int sirfsoc_pinmux_request_gpio(struct pinctrl_dev *pmxdev, spmx = pinctrl_dev_get_drvdata(pmxdev); muxval = readl(spmx->gpio_virtbase + SIRFSOC_GPIO_PAD_EN(group)); - muxval = muxval | (1 << offset); + muxval = muxval | (1 << (offset - range->pin_base)); writel(muxval, spmx->gpio_virtbase + SIRFSOC_GPIO_PAD_EN(group)); return 0; @@ -1100,21 +1100,25 @@ static struct pinctrl_gpio_range sirfsoc_gpio_ranges[] = { .name = "sirfsoc-gpio*", .id = 0, .base = 0, + .pin_base = 0, .npins = 32, }, { .name = "sirfsoc-gpio*", .id = 1, .base = 32, + .pin_base = 32, .npins = 32, }, { .name = "sirfsoc-gpio*", .id = 2, .base = 64, + .pin_base = 64, .npins = 32, }, { .name = "sirfsoc-gpio*", .id = 3, .base = 96, + .pin_base = 96, .npins = 19, }, }; diff --git a/drivers/pinctrl/pinmux-u300.c b/drivers/pinctrl/pinmux-u300.c index 145a84dc16e6d..bcf61bee77638 100644 --- a/drivers/pinctrl/pinmux-u300.c +++ b/drivers/pinctrl/pinmux-u300.c @@ -1026,6 +1026,7 @@ static struct pinctrl_gpio_range u300_gpio_range = { .name = "COH901*", .id = 0, .base = 0, + .pin_base = 0, .npins = 64, }; diff --git a/drivers/pinctrl/pinmux.c b/drivers/pinctrl/pinmux.c index ee3aba78c3dd6..92aa13ee22085 100644 --- a/drivers/pinctrl/pinmux.c +++ b/drivers/pinctrl/pinmux.c @@ -229,7 +229,7 @@ int pinmux_request_gpio(unsigned gpio) return -EINVAL; /* Convert to the pin controllers number space */ - pin = gpio - range->base; + pin = gpio - range->base + range->pin_base; /* Conjure some name stating what chip and pin this is taken by */ snprintf(gpiostr, 15, "%s:%d", range->name, gpio); @@ -263,7 +263,7 @@ void pinmux_free_gpio(unsigned gpio) return; /* Convert to the pin controllers number space */ - pin = gpio - range->base; + pin = gpio - range->base + range->pin_base; func = pin_free(pctldev, pin, range); kfree(func); diff --git a/include/linux/pinctrl/pinctrl.h b/include/linux/pinctrl/pinctrl.h index 04c011038f320..f17fac4b51f18 100644 --- a/include/linux/pinctrl/pinctrl.h +++ b/include/linux/pinctrl/pinctrl.h @@ -45,6 +45,7 @@ struct pinctrl_pin_desc { * @name: a name for the chip in this range * @id: an ID number for the chip in this range * @base: base offset of the GPIO range + * @pin_base: base pin number of the GPIO range * @npins: number of pins in the GPIO range, including the base number * @gc: an optional pointer to a gpio_chip */ @@ -53,6 +54,7 @@ struct pinctrl_gpio_range { const char *name; unsigned int id; unsigned int base; + unsigned int pin_base; unsigned int npins; struct gpio_chip *gc; }; diff --git a/include/linux/pinctrl/pinmux.h b/include/linux/pinctrl/pinmux.h index 350e32a98c6aa..bb7a9792f1eaf 100644 --- a/include/linux/pinctrl/pinmux.h +++ b/include/linux/pinctrl/pinmux.h @@ -52,7 +52,7 @@ struct pinctrl_dev; * @disable: disable a certain muxing selector with a certain pin group * @gpio_request_enable: requests and enables GPIO on a certain pin. * Implement this only if you can mux every pin individually as GPIO. The - * affected GPIO range is passed along with an offset into that + * affected GPIO range is passed along with an offset(pin number) into that * specific GPIO range - function selectors and pin groups are orthogonal * to this, the core will however make sure the pins do not collide */ From 75d6642a3ee1dfe2552028997cdcc2c4207bec8f Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Wed, 16 Nov 2011 09:58:51 +0100 Subject: [PATCH 12/31] pinctrl: print pin range in GPIO range debugs Show the mapped pin range corresponding to the GPIO range in debugfs for pin controllers. Acked-by: Stephen Warren Signed-off-by: Linus Walleij --- drivers/pinctrl/core.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/pinctrl/core.c b/drivers/pinctrl/core.c index 678216652bc0c..4955a68d618fa 100644 --- a/drivers/pinctrl/core.c +++ b/drivers/pinctrl/core.c @@ -394,8 +394,11 @@ static int pinctrl_gpioranges_show(struct seq_file *s, void *what) /* Loop over the ranges */ mutex_lock(&pctldev->gpio_ranges_lock); list_for_each_entry(range, &pctldev->gpio_ranges, node) { - seq_printf(s, "%u: %s [%u - %u]\n", range->id, range->name, - range->base, (range->base + range->npins - 1)); + seq_printf(s, "%u: %s GPIOS [%u - %u] PINS [%u - %u]\n", + range->id, range->name, + range->base, (range->base + range->npins - 1), + range->pin_base, + (range->pin_base + range->npins - 1)); } mutex_unlock(&pctldev->gpio_ranges_lock); From 542e704f3ffee1dc4539c9e8191e4dc215220f5e Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Mon, 14 Nov 2011 10:06:22 +0100 Subject: [PATCH 13/31] pinctrl: GPIO direction support for muxing When requesting a single GPIO pin to be muxed in, some controllers will need to poke a different value into the control register depending on whether the pin will be used for GPIO output or GPIO input. So create pinmux counterparts to gpio_direction_[input|output] in the pinctrl framework. ChangeLog v1->v2: - This also amends the documentation to make it clear the this function and associated machinery is *ONLY* intended as a backend to gpiolib machinery, not for everyone and his dog to start playing around with pins. ChangeLog v2->v3: - Don't pass an argument to the common request function, instead provide pinmux_* counterparts to the gpio_direction_[input|output] calls, simpler and anyone can understand it. ChangeLog v3->v4: - Fix numerous spelling mistakes and dangling text in documentation. Add Ack and Rewewed-by. Cc: Igor Grinberg Acked-by: Stephen Warren Reviewed-by: Thomas Abraham Signed-off-by: Linus Walleij --- Documentation/pinctrl.txt | 32 +++++++++++++----- drivers/pinctrl/pinmux.c | 61 ++++++++++++++++++++++++++++++++++ include/linux/pinctrl/pinmux.h | 24 ++++++++++++- 3 files changed, 108 insertions(+), 9 deletions(-) diff --git a/Documentation/pinctrl.txt b/Documentation/pinctrl.txt index 43ba411d15713..3846264c5973c 100644 --- a/Documentation/pinctrl.txt +++ b/Documentation/pinctrl.txt @@ -645,6 +645,17 @@ All the above functions are mandatory to implement for a pinmux driver. Pinmux interaction with the GPIO subsystem ========================================== +The public pinmux API contains two functions named pinmux_request_gpio() +and pinmux_free_gpio(). These two functions shall *ONLY* be called from +gpiolib-based drivers as part of their gpio_request() and +gpio_free() semantics. Likewise the pinmux_gpio_direction_[input|output] +shall only be called from within respective gpio_direction_[input|output] +gpiolib implementation. + +NOTE that platforms and individual drivers shall *NOT* request GPIO pins to be +muxed in. Instead, implement a proper gpiolib driver and have that driver +request proper muxing for its pins. + The function list could become long, especially if you can convert every individual pin into a GPIO pin independent of any other pins, and then try the approach to define every pin as a function. @@ -652,19 +663,24 @@ the approach to define every pin as a function. In this case, the function array would become 64 entries for each GPIO setting and then the device functions. -For this reason there is an additional function a pinmux driver can implement -to enable only GPIO on an individual pin: .gpio_request_enable(). The same -.free() function as for other functions is assumed to be usable also for -GPIO pins. +For this reason there are two functions a pinmux driver can implement +to enable only GPIO on an individual pin: .gpio_request_enable() and +.gpio_disable_free(). This function will pass in the affected GPIO range identified by the pin controller core, so you know which GPIO pins are being affected by the request operation. -Alternatively it is fully allowed to use named functions for each GPIO -pin, the pinmux_request_gpio() will attempt to obtain the function "gpioN" -where "N" is the global GPIO pin number if no special GPIO-handler is -registered. +If your driver needs to have an indication from the framework of whether the +GPIO pin shall be used for input or output you can implement the +.gpio_set_direction() function. As described this shall be called from the +gpiolib driver and the affected GPIO range, pin offset and desired direction +will be passed along to this function. + +Alternatively to using these special functions, it is fully allowed to use +named functions for each GPIO pin, the pinmux_request_gpio() will attempt to +obtain the function "gpioN" where "N" is the global GPIO pin number if no +special GPIO-handler is registered. Pinmux board/machine configuration diff --git a/drivers/pinctrl/pinmux.c b/drivers/pinctrl/pinmux.c index 92aa13ee22085..f3e4f031fe1ce 100644 --- a/drivers/pinctrl/pinmux.c +++ b/drivers/pinctrl/pinmux.c @@ -214,6 +214,10 @@ static const char *pin_free(struct pinctrl_dev *pctldev, int pin, /** * pinmux_request_gpio() - request a single pin to be muxed in as GPIO * @gpio: the GPIO pin number from the GPIO subsystem number space + * + * This function should *ONLY* be used from gpiolib-based GPIO drivers, + * as part of their gpio_request() semantics, platforms and individual drivers + * shall *NOT* request GPIO pins to be muxed in. */ int pinmux_request_gpio(unsigned gpio) { @@ -249,6 +253,10 @@ EXPORT_SYMBOL_GPL(pinmux_request_gpio); /** * pinmux_free_gpio() - free a single pin, currently used as GPIO * @gpio: the GPIO pin number from the GPIO subsystem number space + * + * This function should *ONLY* be used from gpiolib-based GPIO drivers, + * as part of their gpio_free() semantics, platforms and individual drivers + * shall *NOT* request GPIO pins to be muxed out. */ void pinmux_free_gpio(unsigned gpio) { @@ -270,6 +278,59 @@ void pinmux_free_gpio(unsigned gpio) } EXPORT_SYMBOL_GPL(pinmux_free_gpio); +static int pinmux_gpio_direction(unsigned gpio, bool input) +{ + struct pinctrl_dev *pctldev; + struct pinctrl_gpio_range *range; + const struct pinmux_ops *ops; + int ret; + int pin; + + ret = pinctrl_get_device_gpio_range(gpio, &pctldev, &range); + if (ret) + return ret; + + ops = pctldev->desc->pmxops; + + /* Convert to the pin controllers number space */ + pin = gpio - range->base + range->pin_base; + + if (ops->gpio_set_direction) + ret = ops->gpio_set_direction(pctldev, range, pin, input); + else + ret = 0; + + return ret; +} + +/** + * pinmux_gpio_direction_input() - request a GPIO pin to go into input mode + * @gpio: the GPIO pin number from the GPIO subsystem number space + * + * This function should *ONLY* be used from gpiolib-based GPIO drivers, + * as part of their gpio_direction_input() semantics, platforms and individual + * drivers shall *NOT* touch pinmux GPIO calls. + */ +int pinmux_gpio_direction_input(unsigned gpio) +{ + return pinmux_gpio_direction(gpio, true); +} +EXPORT_SYMBOL_GPL(pinmux_gpio_direction_input); + +/** + * pinmux_gpio_direction_output() - request a GPIO pin to go into output mode + * @gpio: the GPIO pin number from the GPIO subsystem number space + * + * This function should *ONLY* be used from gpiolib-based GPIO drivers, + * as part of their gpio_direction_output() semantics, platforms and individual + * drivers shall *NOT* touch pinmux GPIO calls. + */ +int pinmux_gpio_direction_output(unsigned gpio) +{ + return pinmux_gpio_direction(gpio, false); +} +EXPORT_SYMBOL_GPL(pinmux_gpio_direction_output); + /** * pinmux_register_mappings() - register a set of pinmux mappings * @maps: the pinmux mappings table to register diff --git a/include/linux/pinctrl/pinmux.h b/include/linux/pinctrl/pinmux.h index bb7a9792f1eaf..937b3e2fa36f7 100644 --- a/include/linux/pinctrl/pinmux.h +++ b/include/linux/pinctrl/pinmux.h @@ -54,7 +54,13 @@ struct pinctrl_dev; * Implement this only if you can mux every pin individually as GPIO. The * affected GPIO range is passed along with an offset(pin number) into that * specific GPIO range - function selectors and pin groups are orthogonal - * to this, the core will however make sure the pins do not collide + * to this, the core will however make sure the pins do not collide. + * @gpio_disable_free: free up GPIO muxing on a certain pin, the reverse of + * @gpio_request_enable + * @gpio_set_direction: Since controllers may need different configurations + * depending on whether the GPIO is configured as input or output, + * a direction selector function may be implemented as a backing + * to the GPIO controllers that need pin muxing. */ struct pinmux_ops { int (*request) (struct pinctrl_dev *pctldev, unsigned offset); @@ -76,11 +82,17 @@ struct pinmux_ops { void (*gpio_disable_free) (struct pinctrl_dev *pctldev, struct pinctrl_gpio_range *range, unsigned offset); + int (*gpio_set_direction) (struct pinctrl_dev *pctldev, + struct pinctrl_gpio_range *range, + unsigned offset, + bool input); }; /* External interface to pinmux */ extern int pinmux_request_gpio(unsigned gpio); extern void pinmux_free_gpio(unsigned gpio); +extern int pinmux_gpio_direction_input(unsigned gpio); +extern int pinmux_gpio_direction_output(unsigned gpio); extern struct pinmux * __must_check pinmux_get(struct device *dev, const char *name); extern void pinmux_put(struct pinmux *pmx); extern int pinmux_enable(struct pinmux *pmx); @@ -97,6 +109,16 @@ static inline void pinmux_free_gpio(unsigned gpio) { } +static inline int pinmux_gpio_direction_input(unsigned gpio) +{ + return 0; +} + +static inline int pinmux_gpio_direction_output(unsigned gpio) +{ + return 0; +} + static inline struct pinmux * __must_check pinmux_get(struct device *dev, const char *name) { return NULL; From 97607d157c133ab18dfcd77fa836e37fa950a44a Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Tue, 29 Nov 2011 12:52:39 +0100 Subject: [PATCH 14/31] pinctrl: make a copy of pinmux map This makes a deep copy of the pinmux function map instead of keeping the copy supplied from the platform around. This makes it possible to tag the platforms map with __initdata as is also done as part of this patch. Rationale: a certain target platform (PXA) has numerous pinmux maps, many of which will be lying around unused after boot in a multi-platform binary. Instead, deep-copy the one we're going to use and tag them all __initdata so they go away after boot. ChangeLog v1->v2: - Fixup the deep copy, missed a few items on the struct, plus mark bool member non-const since we're making runtime copies if this stuff now. ChangeLog v2->v3: - Make a shallow copy (just copy the array of map structs) as Arnd noticed, string constants never get discarded by the kernel anyway, so these pointers may be safely copied over. Reviewed-by: Arnd Bergmann Signed-off-by: Linus Walleij --- Documentation/pinctrl.txt | 4 +-- arch/arm/mach-u300/core.c | 2 +- drivers/pinctrl/pinmux.c | 44 +++++++++++++++++++++++++-------- include/linux/pinctrl/machine.h | 2 +- 4 files changed, 38 insertions(+), 14 deletions(-) diff --git a/Documentation/pinctrl.txt b/Documentation/pinctrl.txt index 3846264c5973c..c8fd136eac83a 100644 --- a/Documentation/pinctrl.txt +++ b/Documentation/pinctrl.txt @@ -697,7 +697,7 @@ spi on the second function mapping: #include -static const struct pinmux_map pmx_mapping[] = { +static const struct pinmux_map __initdata pmx_mapping[] = { { .ctrl_dev_name = "pinctrl.0", .function = "spi0", @@ -734,7 +734,7 @@ Since the above construct is pretty common there is a helper macro to make it even more compact which assumes you want to use pinctrl.0 and position 0 for mapping, for example: -static struct pinmux_map pmx_mapping[] = { +static struct pinmux_map __initdata pmx_mapping[] = { PINMUX_MAP_PRIMARY("I2CMAP", "i2c0", "foo-i2c.0"), }; diff --git a/arch/arm/mach-u300/core.c b/arch/arm/mach-u300/core.c index ac0791e924bc0..839fa15c4eb61 100644 --- a/arch/arm/mach-u300/core.c +++ b/arch/arm/mach-u300/core.c @@ -1605,7 +1605,7 @@ static struct platform_device pinmux_device = { }; /* Pinmux settings */ -static struct pinmux_map u300_pinmux_map[] = { +static struct pinmux_map __initdata u300_pinmux_map[] = { /* anonymous maps for chip power and EMIFs */ PINMUX_MAP_PRIMARY_SYS_HOG("POWER", "power"), PINMUX_MAP_PRIMARY_SYS_HOG("EMIF0", "emif0"), diff --git a/drivers/pinctrl/pinmux.c b/drivers/pinctrl/pinmux.c index f3e4f031fe1ce..f6e7d583998c5 100644 --- a/drivers/pinctrl/pinmux.c +++ b/drivers/pinctrl/pinmux.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -33,7 +34,7 @@ static DEFINE_MUTEX(pinmux_list_mutex); static LIST_HEAD(pinmux_list); /* Global pinmux maps, we allow one set only */ -static struct pinmux_map const *pinmux_maps; +static struct pinmux_map *pinmux_maps; static unsigned pinmux_maps_num; /** @@ -333,7 +334,9 @@ EXPORT_SYMBOL_GPL(pinmux_gpio_direction_output); /** * pinmux_register_mappings() - register a set of pinmux mappings - * @maps: the pinmux mappings table to register + * @maps: the pinmux mappings table to register, this should be marked with + * __initdata so it can be discarded after boot, this function will + * perform a shallow copy for the mapping entries. * @num_maps: the number of maps in the mapping table * * Only call this once during initialization of your machine, the function is @@ -344,32 +347,48 @@ EXPORT_SYMBOL_GPL(pinmux_gpio_direction_output); int __init pinmux_register_mappings(struct pinmux_map const *maps, unsigned num_maps) { + int ret = 0; int i; - if (pinmux_maps != NULL) { + if (pinmux_maps_num != 0) { pr_err("pinmux mappings already registered, you can only " "register one set of maps\n"); return -EINVAL; } pr_debug("add %d pinmux maps\n", num_maps); + + /* + * Make a copy of the map array - string pointers will end up in the + * kernel const section anyway so these do not need to be deep copied. + */ + pinmux_maps = kmemdup(maps, sizeof(struct pinmux_map) * num_maps, + GFP_KERNEL); + if (!pinmux_maps) + return -ENOMEM; + for (i = 0; i < num_maps; i++) { - /* Sanity check the mapping */ + /* Sanity check the mapping while copying it */ if (!maps[i].name) { pr_err("failed to register map %d: " "no map name given\n", i); - return -EINVAL; + ret = -EINVAL; + goto err_out_free; } + if (!maps[i].ctrl_dev && !maps[i].ctrl_dev_name) { pr_err("failed to register map %s (%d): " "no pin control device given\n", maps[i].name, i); - return -EINVAL; + ret = -EINVAL; + goto err_out_free; } + if (!maps[i].function) { pr_err("failed to register map %s (%d): " "no function ID given\n", maps[i].name, i); - return -EINVAL; + ret = -EINVAL; + goto err_out_free; } if (!maps[i].dev && !maps[i].dev_name) @@ -380,12 +399,17 @@ int __init pinmux_register_mappings(struct pinmux_map const *maps, pr_debug("register map %s, function %s\n", maps[i].name, maps[i].function); - } - pinmux_maps = maps; - pinmux_maps_num = num_maps; + pinmux_maps_num++; + } return 0; + +err_out_free: + kfree(pinmux_maps); + pinmux_maps = NULL; + pinmux_maps_num = 0; + return ret; } /** diff --git a/include/linux/pinctrl/machine.h b/include/linux/pinctrl/machine.h index 88863531d862c..f5372319d9990 100644 --- a/include/linux/pinctrl/machine.h +++ b/include/linux/pinctrl/machine.h @@ -48,7 +48,7 @@ struct pinmux_map { const char *group; struct device *dev; const char *dev_name; - const bool hog_on_boot; + bool hog_on_boot; }; /* From 59b099b04981917ee7fbd88b6f50eeaffc9f33cd Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Wed, 30 Nov 2011 13:28:14 +0100 Subject: [PATCH 15/31] pinctrl: make it possible to add multiple maps Since we now anyway make a copy of the platform-supplied pinmux map, we can just as well make it possible to call the function adding maps several times, so as to simplify cases (as PXA) where several sets of disparate mappings need to be added depending on target platform. Acked-by: Haojian Zhuang Acked-by: Arnd Bergmann Signed-off-by: Linus Walleij --- drivers/pinctrl/pinmux.c | 60 +++++++++++++++++++--------------------- 1 file changed, 29 insertions(+), 31 deletions(-) diff --git a/drivers/pinctrl/pinmux.c b/drivers/pinctrl/pinmux.c index f6e7d583998c5..a11681b4bd919 100644 --- a/drivers/pinctrl/pinmux.c +++ b/drivers/pinctrl/pinmux.c @@ -33,7 +33,7 @@ static DEFINE_MUTEX(pinmux_list_mutex); static LIST_HEAD(pinmux_list); -/* Global pinmux maps, we allow one set only */ +/* Global pinmux maps */ static struct pinmux_map *pinmux_maps; static unsigned pinmux_maps_num; @@ -347,48 +347,30 @@ EXPORT_SYMBOL_GPL(pinmux_gpio_direction_output); int __init pinmux_register_mappings(struct pinmux_map const *maps, unsigned num_maps) { - int ret = 0; + void *tmp_maps; int i; - if (pinmux_maps_num != 0) { - pr_err("pinmux mappings already registered, you can only " - "register one set of maps\n"); - return -EINVAL; - } - pr_debug("add %d pinmux maps\n", num_maps); - /* - * Make a copy of the map array - string pointers will end up in the - * kernel const section anyway so these do not need to be deep copied. - */ - pinmux_maps = kmemdup(maps, sizeof(struct pinmux_map) * num_maps, - GFP_KERNEL); - if (!pinmux_maps) - return -ENOMEM; - + /* First sanity check the new mapping */ for (i = 0; i < num_maps; i++) { - /* Sanity check the mapping while copying it */ if (!maps[i].name) { pr_err("failed to register map %d: " "no map name given\n", i); - ret = -EINVAL; - goto err_out_free; + return -EINVAL; } if (!maps[i].ctrl_dev && !maps[i].ctrl_dev_name) { pr_err("failed to register map %s (%d): " "no pin control device given\n", maps[i].name, i); - ret = -EINVAL; - goto err_out_free; + return -EINVAL; } if (!maps[i].function) { pr_err("failed to register map %s (%d): " "no function ID given\n", maps[i].name, i); - ret = -EINVAL; - goto err_out_free; + return -EINVAL; } if (!maps[i].dev && !maps[i].dev_name) @@ -399,17 +381,33 @@ int __init pinmux_register_mappings(struct pinmux_map const *maps, pr_debug("register map %s, function %s\n", maps[i].name, maps[i].function); + } - pinmux_maps_num++; + /* + * Make a copy of the map array - string pointers will end up in the + * kernel const section anyway so these do not need to be deep copied. + */ + if (!pinmux_maps_num) { + /* On first call, just copy them */ + tmp_maps = kmemdup(maps, + sizeof(struct pinmux_map) * num_maps, + GFP_KERNEL); + if (!tmp_maps) + return -ENOMEM; + } else { + /* Subsequent calls, reallocate array to new size */ + size_t oldsize = sizeof(struct pinmux_map) * pinmux_maps_num; + size_t newsize = sizeof(struct pinmux_map) * num_maps; + + tmp_maps = krealloc(pinmux_maps, oldsize + newsize, GFP_KERNEL); + if (!tmp_maps) + return -ENOMEM; + memcpy((tmp_maps + oldsize), maps, newsize); } + pinmux_maps = tmp_maps; + pinmux_maps_num += num_maps; return 0; - -err_out_free: - kfree(pinmux_maps); - pinmux_maps = NULL; - pinmux_maps_num = 0; - return ret; } /** From dd68acc7cc256c928256eb5f53e163233605de5d Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Tue, 15 Nov 2011 11:18:54 +0100 Subject: [PATCH 16/31] ARM: u300: localize GPIO assignments Move the GPIO assignments for the U300 variants down to a local header file in the mach-u300 directory. There is no point in broadcasting this across the entire kernel. Signed-off-by: Linus Walleij --- arch/arm/mach-u300/include/mach/gpio-u300.h | 115 -------------------- arch/arm/mach-u300/mmc.c | 2 +- arch/arm/mach-u300/u300-gpio.h | 114 +++++++++++++++++++ 3 files changed, 115 insertions(+), 116 deletions(-) create mode 100644 arch/arm/mach-u300/u300-gpio.h diff --git a/arch/arm/mach-u300/include/mach/gpio-u300.h b/arch/arm/mach-u300/include/mach/gpio-u300.h index 0c2b2021951a8..bf4c7935aecdf 100644 --- a/arch/arm/mach-u300/include/mach/gpio-u300.h +++ b/arch/arm/mach-u300/include/mach/gpio-u300.h @@ -9,121 +9,6 @@ #ifndef __MACH_U300_GPIO_U300_H #define __MACH_U300_GPIO_U300_H -/* - * Individual pin assignments for the B26/S26. Notice that the - * actual usage of these pins depends on the PAD MUX settings, that - * is why the same number can potentially appear several times. - * In the reference design each pin is only used for one purpose. - * These were determined by inspecting the B26/S26 schematic: - * 2/1911-ROA 128 1603 - */ -#ifdef CONFIG_MACH_U300_BS2X -#define U300_GPIO_PIN_UART_RX 0 -#define U300_GPIO_PIN_UART_TX 1 -#define U300_GPIO_PIN_GPIO02 2 /* Unrouted */ -#define U300_GPIO_PIN_GPIO03 3 /* Unrouted */ -#define U300_GPIO_PIN_CAM_SLEEP 4 -#define U300_GPIO_PIN_CAM_REG_EN 5 -#define U300_GPIO_PIN_GPIO06 6 /* Unrouted */ -#define U300_GPIO_PIN_GPIO07 7 /* Unrouted */ - -#define U300_GPIO_PIN_GPIO08 8 /* Service point SP2321 */ -#define U300_GPIO_PIN_GPIO09 9 /* Service point SP2322 */ -#define U300_GPIO_PIN_PHFSENSE 10 /* Headphone jack sensing */ -#define U300_GPIO_PIN_MMC_CLKRET 11 /* Clock return from MMC/SD card */ -#define U300_GPIO_PIN_MMC_CD 12 /* MMC Card insertion detection */ -#define U300_GPIO_PIN_FLIPSENSE 13 /* Mechanical flip sensing */ -#define U300_GPIO_PIN_GPIO14 14 /* DSP JTAG Port RTCK */ -#define U300_GPIO_PIN_GPIO15 15 /* Unrouted */ - -#define U300_GPIO_PIN_GPIO16 16 /* Unrouted */ -#define U300_GPIO_PIN_GPIO17 17 /* Unrouted */ -#define U300_GPIO_PIN_GPIO18 18 /* Unrouted */ -#define U300_GPIO_PIN_GPIO19 19 /* Unrouted */ -#define U300_GPIO_PIN_GPIO20 20 /* Unrouted */ -#define U300_GPIO_PIN_GPIO21 21 /* Unrouted */ -#define U300_GPIO_PIN_GPIO22 22 /* Unrouted */ -#define U300_GPIO_PIN_GPIO23 23 /* Unrouted */ -#endif - -/* - * Individual pin assignments for the B330/S330 and B365/S365. - * Notice that the actual usage of these pins depends on the - * PAD MUX settings, that is why the same number can potentially - * appear several times. In the reference design each pin is only - * used for one purpose. These were determined by inspecting the - * S365 schematic. - */ -#if defined(CONFIG_MACH_U300_BS330) || defined(CONFIG_MACH_U300_BS365) || \ - defined(CONFIG_MACH_U300_BS335) -#define U300_GPIO_PIN_UART_RX 0 -#define U300_GPIO_PIN_UART_TX 1 -#define U300_GPIO_PIN_UART_CTS 2 -#define U300_GPIO_PIN_UART_RTS 3 -#define U300_GPIO_PIN_CAM_MAIN_STANDBY 4 /* Camera MAIN standby */ -#define U300_GPIO_PIN_GPIO05 5 /* Unrouted */ -#define U300_GPIO_PIN_MS_CD 6 /* Memory Stick Card insertion */ -#define U300_GPIO_PIN_GPIO07 7 /* Test point TP2430 */ - -#define U300_GPIO_PIN_GPIO08 8 /* Test point TP2437 */ -#define U300_GPIO_PIN_GPIO09 9 /* Test point TP2431 */ -#define U300_GPIO_PIN_GPIO10 10 /* Test point TP2432 */ -#define U300_GPIO_PIN_MMC_CLKRET 11 /* Clock return from MMC/SD card */ -#define U300_GPIO_PIN_MMC_CD 12 /* MMC Card insertion detection */ -#define U300_GPIO_PIN_CAM_SUB_STANDBY 13 /* Camera SUB standby */ -#define U300_GPIO_PIN_GPIO14 14 /* Test point TP2436 */ -#define U300_GPIO_PIN_GPIO15 15 /* Unrouted */ - -#define U300_GPIO_PIN_GPIO16 16 /* Test point TP2438 */ -#define U300_GPIO_PIN_PHFSENSE 17 /* Headphone jack sensing */ -#define U300_GPIO_PIN_GPIO18 18 /* Test point TP2439 */ -#define U300_GPIO_PIN_GPIO19 19 /* Routed somewhere */ -#define U300_GPIO_PIN_GPIO20 20 /* Unrouted */ -#define U300_GPIO_PIN_GPIO21 21 /* Unrouted */ -#define U300_GPIO_PIN_GPIO22 22 /* Unrouted */ -#define U300_GPIO_PIN_GPIO23 23 /* Unrouted */ - -#define U300_GPIO_PIN_GPIO24 24 /* Unrouted */ -#define U300_GPIO_PIN_GPIO25 25 /* Unrouted */ -#define U300_GPIO_PIN_GPIO26 26 /* Unrouted */ -#define U300_GPIO_PIN_GPIO27 27 /* Unrouted */ -#define U300_GPIO_PIN_GPIO28 28 /* Unrouted */ -#define U300_GPIO_PIN_GPIO29 29 /* Unrouted */ -#define U300_GPIO_PIN_GPIO30 30 /* Unrouted */ -#define U300_GPIO_PIN_GPIO31 31 /* Unrouted */ - -#define U300_GPIO_PIN_GPIO32 32 /* Unrouted */ -#define U300_GPIO_PIN_GPIO33 33 /* Unrouted */ -#define U300_GPIO_PIN_GPIO34 34 /* Unrouted */ -#define U300_GPIO_PIN_GPIO35 35 /* Unrouted */ -#define U300_GPIO_PIN_GPIO36 36 /* Unrouted */ -#define U300_GPIO_PIN_GPIO37 37 /* Unrouted */ -#define U300_GPIO_PIN_GPIO38 38 /* Unrouted */ -#define U300_GPIO_PIN_GPIO39 39 /* Unrouted */ - -#ifdef CONFIG_MACH_U300_BS335 - -#define U300_GPIO_PIN_GPIO40 40 /* Unrouted */ -#define U300_GPIO_PIN_GPIO41 41 /* Unrouted */ -#define U300_GPIO_PIN_GPIO42 42 /* Unrouted */ -#define U300_GPIO_PIN_GPIO43 43 /* Unrouted */ -#define U300_GPIO_PIN_GPIO44 44 /* Unrouted */ -#define U300_GPIO_PIN_GPIO45 45 /* Unrouted */ -#define U300_GPIO_PIN_GPIO46 46 /* Unrouted */ -#define U300_GPIO_PIN_GPIO47 47 /* Unrouted */ - -#define U300_GPIO_PIN_GPIO48 48 /* Unrouted */ -#define U300_GPIO_PIN_GPIO49 49 /* Unrouted */ -#define U300_GPIO_PIN_GPIO50 50 /* Unrouted */ -#define U300_GPIO_PIN_GPIO51 51 /* Unrouted */ -#define U300_GPIO_PIN_GPIO52 52 /* Unrouted */ -#define U300_GPIO_PIN_GPIO53 53 /* Unrouted */ -#define U300_GPIO_PIN_GPIO54 54 /* Unrouted */ -#define U300_GPIO_PIN_GPIO55 55 /* Unrouted */ -#endif - -#endif - /** * enum u300_gpio_variant - the type of U300 GPIO employed */ diff --git a/arch/arm/mach-u300/mmc.c b/arch/arm/mach-u300/mmc.c index 4d482aacc2720..05abd6ad9fabb 100644 --- a/arch/arm/mach-u300/mmc.c +++ b/arch/arm/mach-u300/mmc.c @@ -18,8 +18,8 @@ #include #include #include -#include +#include "u300-gpio.h" #include "mmc.h" static struct mmci_platform_data mmc0_plat_data = { diff --git a/arch/arm/mach-u300/u300-gpio.h b/arch/arm/mach-u300/u300-gpio.h new file mode 100644 index 0000000000000..847dc25300c68 --- /dev/null +++ b/arch/arm/mach-u300/u300-gpio.h @@ -0,0 +1,114 @@ +/* + * Individual pin assignments for the B26/S26. Notice that the + * actual usage of these pins depends on the PAD MUX settings, that + * is why the same number can potentially appear several times. + * In the reference design each pin is only used for one purpose. + * These were determined by inspecting the B26/S26 schematic: + * 2/1911-ROA 128 1603 + */ +#ifdef CONFIG_MACH_U300_BS2X +#define U300_GPIO_PIN_UART_RX 0 +#define U300_GPIO_PIN_UART_TX 1 +#define U300_GPIO_PIN_GPIO02 2 /* Unrouted */ +#define U300_GPIO_PIN_GPIO03 3 /* Unrouted */ +#define U300_GPIO_PIN_CAM_SLEEP 4 +#define U300_GPIO_PIN_CAM_REG_EN 5 +#define U300_GPIO_PIN_GPIO06 6 /* Unrouted */ +#define U300_GPIO_PIN_GPIO07 7 /* Unrouted */ + +#define U300_GPIO_PIN_GPIO08 8 /* Service point SP2321 */ +#define U300_GPIO_PIN_GPIO09 9 /* Service point SP2322 */ +#define U300_GPIO_PIN_PHFSENSE 10 /* Headphone jack sensing */ +#define U300_GPIO_PIN_MMC_CLKRET 11 /* Clock return from MMC/SD card */ +#define U300_GPIO_PIN_MMC_CD 12 /* MMC Card insertion detection */ +#define U300_GPIO_PIN_FLIPSENSE 13 /* Mechanical flip sensing */ +#define U300_GPIO_PIN_GPIO14 14 /* DSP JTAG Port RTCK */ +#define U300_GPIO_PIN_GPIO15 15 /* Unrouted */ + +#define U300_GPIO_PIN_GPIO16 16 /* Unrouted */ +#define U300_GPIO_PIN_GPIO17 17 /* Unrouted */ +#define U300_GPIO_PIN_GPIO18 18 /* Unrouted */ +#define U300_GPIO_PIN_GPIO19 19 /* Unrouted */ +#define U300_GPIO_PIN_GPIO20 20 /* Unrouted */ +#define U300_GPIO_PIN_GPIO21 21 /* Unrouted */ +#define U300_GPIO_PIN_GPIO22 22 /* Unrouted */ +#define U300_GPIO_PIN_GPIO23 23 /* Unrouted */ +#endif + +/* + * Individual pin assignments for the B330/S330 and B365/S365. + * Notice that the actual usage of these pins depends on the + * PAD MUX settings, that is why the same number can potentially + * appear several times. In the reference design each pin is only + * used for one purpose. These were determined by inspecting the + * S365 schematic. + */ +#if defined(CONFIG_MACH_U300_BS330) || defined(CONFIG_MACH_U300_BS365) || \ + defined(CONFIG_MACH_U300_BS335) +#define U300_GPIO_PIN_UART_RX 0 +#define U300_GPIO_PIN_UART_TX 1 +#define U300_GPIO_PIN_UART_CTS 2 +#define U300_GPIO_PIN_UART_RTS 3 +#define U300_GPIO_PIN_CAM_MAIN_STANDBY 4 /* Camera MAIN standby */ +#define U300_GPIO_PIN_GPIO05 5 /* Unrouted */ +#define U300_GPIO_PIN_MS_CD 6 /* Memory Stick Card insertion */ +#define U300_GPIO_PIN_GPIO07 7 /* Test point TP2430 */ + +#define U300_GPIO_PIN_GPIO08 8 /* Test point TP2437 */ +#define U300_GPIO_PIN_GPIO09 9 /* Test point TP2431 */ +#define U300_GPIO_PIN_GPIO10 10 /* Test point TP2432 */ +#define U300_GPIO_PIN_MMC_CLKRET 11 /* Clock return from MMC/SD card */ +#define U300_GPIO_PIN_MMC_CD 12 /* MMC Card insertion detection */ +#define U300_GPIO_PIN_CAM_SUB_STANDBY 13 /* Camera SUB standby */ +#define U300_GPIO_PIN_GPIO14 14 /* Test point TP2436 */ +#define U300_GPIO_PIN_GPIO15 15 /* Unrouted */ + +#define U300_GPIO_PIN_GPIO16 16 /* Test point TP2438 */ +#define U300_GPIO_PIN_PHFSENSE 17 /* Headphone jack sensing */ +#define U300_GPIO_PIN_GPIO18 18 /* Test point TP2439 */ +#define U300_GPIO_PIN_GPIO19 19 /* Routed somewhere */ +#define U300_GPIO_PIN_GPIO20 20 /* Unrouted */ +#define U300_GPIO_PIN_GPIO21 21 /* Unrouted */ +#define U300_GPIO_PIN_GPIO22 22 /* Unrouted */ +#define U300_GPIO_PIN_GPIO23 23 /* Unrouted */ + +#define U300_GPIO_PIN_GPIO24 24 /* Unrouted */ +#define U300_GPIO_PIN_GPIO25 25 /* Unrouted */ +#define U300_GPIO_PIN_GPIO26 26 /* Unrouted */ +#define U300_GPIO_PIN_GPIO27 27 /* Unrouted */ +#define U300_GPIO_PIN_GPIO28 28 /* Unrouted */ +#define U300_GPIO_PIN_GPIO29 29 /* Unrouted */ +#define U300_GPIO_PIN_GPIO30 30 /* Unrouted */ +#define U300_GPIO_PIN_GPIO31 31 /* Unrouted */ + +#define U300_GPIO_PIN_GPIO32 32 /* Unrouted */ +#define U300_GPIO_PIN_GPIO33 33 /* Unrouted */ +#define U300_GPIO_PIN_GPIO34 34 /* Unrouted */ +#define U300_GPIO_PIN_GPIO35 35 /* Unrouted */ +#define U300_GPIO_PIN_GPIO36 36 /* Unrouted */ +#define U300_GPIO_PIN_GPIO37 37 /* Unrouted */ +#define U300_GPIO_PIN_GPIO38 38 /* Unrouted */ +#define U300_GPIO_PIN_GPIO39 39 /* Unrouted */ + +#ifdef CONFIG_MACH_U300_BS335 + +#define U300_GPIO_PIN_GPIO40 40 /* Unrouted */ +#define U300_GPIO_PIN_GPIO41 41 /* Unrouted */ +#define U300_GPIO_PIN_GPIO42 42 /* Unrouted */ +#define U300_GPIO_PIN_GPIO43 43 /* Unrouted */ +#define U300_GPIO_PIN_GPIO44 44 /* Unrouted */ +#define U300_GPIO_PIN_GPIO45 45 /* Unrouted */ +#define U300_GPIO_PIN_GPIO46 46 /* Unrouted */ +#define U300_GPIO_PIN_GPIO47 47 /* Unrouted */ + +#define U300_GPIO_PIN_GPIO48 48 /* Unrouted */ +#define U300_GPIO_PIN_GPIO49 49 /* Unrouted */ +#define U300_GPIO_PIN_GPIO50 50 /* Unrouted */ +#define U300_GPIO_PIN_GPIO51 51 /* Unrouted */ +#define U300_GPIO_PIN_GPIO52 52 /* Unrouted */ +#define U300_GPIO_PIN_GPIO53 53 /* Unrouted */ +#define U300_GPIO_PIN_GPIO54 54 /* Unrouted */ +#define U300_GPIO_PIN_GPIO55 55 /* Unrouted */ +#endif + +#endif From ca402d37dccf2b797440c5f03bd0db16f977acc9 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Wed, 16 Nov 2011 09:22:59 +0100 Subject: [PATCH 17/31] pinctrl: move the U300 GPIO driver to pinctrl This driver will be converted to a dual GPIO + pinctrl driver since it supports biasing and driving control options. Hopefully it can serve as an example. Signed-off-by: Linus Walleij --- arch/arm/mach-u300/Kconfig | 2 +- arch/arm/mach-u300/include/mach/irqs.h | 2 +- drivers/gpio/Kconfig | 9 --------- drivers/gpio/Makefile | 1 - drivers/pinctrl/Kconfig | 9 +++++++++ drivers/pinctrl/Makefile | 1 + drivers/{gpio/gpio-u300.c => pinctrl/pinctrl-coh901.c} | 0 7 files changed, 12 insertions(+), 12 deletions(-) rename drivers/{gpio/gpio-u300.c => pinctrl/pinctrl-coh901.c} (100%) diff --git a/arch/arm/mach-u300/Kconfig b/arch/arm/mach-u300/Kconfig index 1cbcd4fc1e17f..c2d5c6c083645 100644 --- a/arch/arm/mach-u300/Kconfig +++ b/arch/arm/mach-u300/Kconfig @@ -8,7 +8,7 @@ config MACH_U300 bool "U300" select PINCTRL select PINMUX_U300 - select GPIO_U300 + select PINCTRL_COH901 comment "ST-Ericsson U300/U330/U335/U365 Feature Selections" diff --git a/arch/arm/mach-u300/include/mach/irqs.h b/arch/arm/mach-u300/include/mach/irqs.h index db3fbfa1d6e97..ee78a26707ebe 100644 --- a/arch/arm/mach-u300/include/mach/irqs.h +++ b/arch/arm/mach-u300/include/mach/irqs.h @@ -110,7 +110,7 @@ #endif /* Maximum 8*7 GPIO lines */ -#ifdef CONFIG_GPIO_U300 +#ifdef CONFIG_PINCTRL_COH901 #define IRQ_U300_GPIO_BASE (U300_VIC_IRQS_END) #define IRQ_U300_GPIO_END (IRQ_U300_GPIO_BASE + 56) #else diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 8482a23887dc4..0f82aa8fa1587 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -170,15 +170,6 @@ config GPIO_SCH The Intel Tunnel Creek processor has 5 GPIOs powered by the core power rail and 9 from suspend power supply. -config GPIO_U300 - bool "ST-Ericsson U300 COH 901 335/571 GPIO" - depends on GPIOLIB && ARCH_U300 - help - Say yes here to support GPIO interface on ST-Ericsson U300. - The names of the two IP block variants supported are - COH 901 335 and COH 901 571/3. They contain 3, 5 or 7 - ports of 8 GPIO pins each. - config GPIO_VX855 tristate "VIA VX855/VX875 GPIO" depends on PCI diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index dbcb0bcfd8dad..7f20316fb1563 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -54,7 +54,6 @@ obj-$(CONFIG_ARCH_DAVINCI_TNETV107X) += gpio-tnetv107x.o obj-$(CONFIG_GPIO_TPS65910) += gpio-tps65910.o obj-$(CONFIG_GPIO_TPS65912) += gpio-tps65912.o obj-$(CONFIG_GPIO_TWL4030) += gpio-twl4030.o -obj-$(CONFIG_MACH_U300) += gpio-u300.o obj-$(CONFIG_GPIO_UCB1400) += gpio-ucb1400.o obj-$(CONFIG_GPIO_VR41XX) += gpio-vr41xx.o obj-$(CONFIG_GPIO_VX855) += gpio-vx855.o diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig index e17e2f8001d2a..e087f0219f48c 100644 --- a/drivers/pinctrl/Kconfig +++ b/drivers/pinctrl/Kconfig @@ -30,6 +30,15 @@ config PINMUX_U300 depends on ARCH_U300 select PINMUX +config PINCTRL_COH901 + bool "ST-Ericsson U300 COH 901 335/571 GPIO" + depends on GPIOLIB && ARCH_U300 + help + Say yes here to support GPIO interface on ST-Ericsson U300. + The names of the two IP block variants supported are + COH 901 335 and COH 901 571/3. They contain 3, 5 or 7 + ports of 8 GPIO pins each. + endmenu endif diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile index 50a2e2f6bc270..5f3e4d65465a1 100644 --- a/drivers/pinctrl/Makefile +++ b/drivers/pinctrl/Makefile @@ -6,3 +6,4 @@ obj-$(CONFIG_PINCTRL) += core.o obj-$(CONFIG_PINMUX) += pinmux.o obj-$(CONFIG_PINMUX_SIRF) += pinmux-sirf.o obj-$(CONFIG_PINMUX_U300) += pinmux-u300.o +obj-$(CONFIG_PINCTRL_COH901) += pinctrl-coh901.o diff --git a/drivers/gpio/gpio-u300.c b/drivers/pinctrl/pinctrl-coh901.c similarity index 100% rename from drivers/gpio/gpio-u300.c rename to drivers/pinctrl/pinctrl-coh901.c From f812f0f53e5643c06b929ce3299cbaffb307c488 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Wed, 16 Nov 2011 10:23:05 +0100 Subject: [PATCH 18/31] pinctrl: u300-pinmux: register proper GPIO ranges This register the actual GPIO ranges used by the COH901XXX GPIO driver. Signed-off-by: Linus Walleij --- drivers/pinctrl/pinmux-u300.c | 40 +++++++++++++++++++++++++---------- 1 file changed, 29 insertions(+), 11 deletions(-) diff --git a/drivers/pinctrl/pinmux-u300.c b/drivers/pinctrl/pinmux-u300.c index bcf61bee77638..7e89b367a7e59 100644 --- a/drivers/pinctrl/pinmux-u300.c +++ b/drivers/pinctrl/pinmux-u300.c @@ -1019,15 +1019,29 @@ static struct pinmux_ops u300_pmx_ops = { }; /* - * FIXME: this will be set to sane values as this driver engulfs - * drivers/gpio/gpio-u300.c and we really know this stuff. + * GPIO ranges handled by the application-side COH901XXX GPIO controller + * Very many pins can be converted into GPIO pins, but we only list those + * that are useful in practice to cut down on tables. */ -static struct pinctrl_gpio_range u300_gpio_range = { - .name = "COH901*", - .id = 0, - .base = 0, - .pin_base = 0, - .npins = 64, +#define U300_GPIO_RANGE(a, b, c) { .name = "COH901XXX", .id = a, .base= a, \ + .pin_base = b, .npins = c } + +static struct pinctrl_gpio_range u300_gpio_ranges[] = { + U300_GPIO_RANGE(10, 426, 1), + U300_GPIO_RANGE(11, 180, 1), + U300_GPIO_RANGE(12, 165, 1), /* MS/MMC card insertion */ + U300_GPIO_RANGE(13, 179, 1), + U300_GPIO_RANGE(14, 178, 1), + U300_GPIO_RANGE(16, 194, 1), + U300_GPIO_RANGE(17, 193, 1), + U300_GPIO_RANGE(18, 192, 1), + U300_GPIO_RANGE(19, 191, 1), + U300_GPIO_RANGE(20, 186, 1), + U300_GPIO_RANGE(21, 185, 1), + U300_GPIO_RANGE(22, 184, 1), + U300_GPIO_RANGE(23, 183, 1), + U300_GPIO_RANGE(24, 182, 1), + U300_GPIO_RANGE(25, 181, 1), }; static struct pinctrl_desc u300_pmx_desc = { @@ -1042,9 +1056,10 @@ static struct pinctrl_desc u300_pmx_desc = { static int __init u300_pmx_probe(struct platform_device *pdev) { - int ret; struct u300_pmx *upmx; struct resource *res; + int ret; + int i; /* Create state holders etc for this driver */ upmx = devm_kzalloc(&pdev->dev, sizeof(*upmx), GFP_KERNEL); @@ -1081,7 +1096,8 @@ static int __init u300_pmx_probe(struct platform_device *pdev) } /* We will handle a range of GPIO pins */ - pinctrl_add_gpio_range(upmx->pctl, &u300_gpio_range); + for (i = 0; i < ARRAY_SIZE(u300_gpio_ranges); i++) + pinctrl_add_gpio_range(upmx->pctl, &u300_gpio_ranges[i]); platform_set_drvdata(pdev, upmx); @@ -1103,8 +1119,10 @@ static int __init u300_pmx_probe(struct platform_device *pdev) static int __exit u300_pmx_remove(struct platform_device *pdev) { struct u300_pmx *upmx = platform_get_drvdata(pdev); + int i; - pinctrl_remove_gpio_range(upmx->pctl, &u300_gpio_range); + for (i = 0; i < ARRAY_SIZE(u300_gpio_ranges); i++) + pinctrl_remove_gpio_range(upmx->pctl, &u300_gpio_ranges[i]); pinctrl_unregister(upmx->pctl); iounmap(upmx->virtbase); release_mem_region(upmx->phybase, upmx->physize); From b4e3ac74d5cd4152f2ec6b3280b1ff3428952f7f Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Wed, 16 Nov 2011 10:24:39 +0100 Subject: [PATCH 19/31] pinctrl/coh901: driver to request its pins This makes the COH 901 driver request muxing of its GPIO pins from the pinmux-u300 driver using the standard API calls. Signed-off-by: Linus Walleij --- drivers/pinctrl/Kconfig | 2 +- drivers/pinctrl/pinctrl-coh901.c | 21 +++++++++++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig index e087f0219f48c..e963da41e948f 100644 --- a/drivers/pinctrl/Kconfig +++ b/drivers/pinctrl/Kconfig @@ -32,7 +32,7 @@ config PINMUX_U300 config PINCTRL_COH901 bool "ST-Ericsson U300 COH 901 335/571 GPIO" - depends on GPIOLIB && ARCH_U300 + depends on GPIOLIB && ARCH_U300 && PINMUX_U300 help Say yes here to support GPIO interface on ST-Ericsson U300. The names of the two IP block variants supported are diff --git a/drivers/pinctrl/pinctrl-coh901.c b/drivers/pinctrl/pinctrl-coh901.c index 4035778852b0d..69fb7072a23ea 100644 --- a/drivers/pinctrl/pinctrl-coh901.c +++ b/drivers/pinctrl/pinctrl-coh901.c @@ -22,6 +22,7 @@ #include #include #include +#include #include /* @@ -351,6 +352,24 @@ static inline struct u300_gpio *to_u300_gpio(struct gpio_chip *chip) return container_of(chip, struct u300_gpio, chip); } +static int u300_gpio_request(struct gpio_chip *chip, unsigned offset) +{ + /* + * Map back to global GPIO space and request muxing, the direction + * parameter does not matter for this controller. + */ + int gpio = chip->base + offset; + + return pinmux_request_gpio(gpio); +} + +static void u300_gpio_free(struct gpio_chip *chip, unsigned offset) +{ + int gpio = chip->base + offset; + + pinmux_free_gpio(gpio); +} + static int u300_gpio_get(struct gpio_chip *chip, unsigned offset) { struct u300_gpio *gpio = to_u300_gpio(chip); @@ -483,6 +502,8 @@ static int u300_gpio_config(struct gpio_chip *chip, unsigned offset, static struct gpio_chip u300_gpio_chip = { .label = "u300-gpio-chip", .owner = THIS_MODULE, + .request = u300_gpio_request, + .free = u300_gpio_free, .get = u300_gpio_get, .set = u300_gpio_set, .direction_input = u300_gpio_direction_input, From ae6b4d8588f4fc95520b0e62c4b1f474c82191a9 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Wed, 19 Oct 2011 18:14:33 +0200 Subject: [PATCH 20/31] 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 Signed-off-by: Linus Walleij --- Documentation/pinctrl.txt | 96 +++++++++- drivers/pinctrl/Kconfig | 5 +- drivers/pinctrl/Makefile | 1 + drivers/pinctrl/core.c | 43 ++++- drivers/pinctrl/core.h | 5 + drivers/pinctrl/pinconf.c | 302 ++++++++++++++++++++++++++++++++ drivers/pinctrl/pinconf.h | 36 ++++ include/linux/pinctrl/pinconf.h | 96 ++++++++++ include/linux/pinctrl/pinctrl.h | 8 +- 9 files changed, 582 insertions(+), 10 deletions(-) create mode 100644 drivers/pinctrl/pinconf.c create mode 100644 drivers/pinctrl/pinconf.h create mode 100644 include/linux/pinctrl/pinconf.h diff --git a/Documentation/pinctrl.txt b/Documentation/pinctrl.txt index c8fd136eac83a..6d23fa84ee47f 100644 --- a/Documentation/pinctrl.txt +++ b/Documentation/pinctrl.txt @@ -7,12 +7,9 @@ This subsystem deals with: - Multiplexing of pins, pads, fingers (etc) see below for details -The intention is to also deal with: - -- Software-controlled biasing and driving mode specific pins, such as - pull-up/down, open drain etc, load capacitance configuration when controlled - by software, etc. - +- Configuration of pins, pads, fingers (etc), such as software-controlled + biasing and driving mode specific pins, such as pull-up/down, open drain, + load capacitance etc. Top-level interface =================== @@ -88,6 +85,11 @@ int __init foo_probe(void) pr_err("could not register foo pin driver\n"); } +To enable the pinctrl subsystem and the subgroups for PINMUX and PINCONF and +selected drivers, you need to select them from your machine's Kconfig entry, +since these are so tightly integrated with the machines they are used on. +See for example arch/arm/mach-u300/Kconfig for an example. + Pins usually have fancier names than this. You can find these in the dataheet for your chip. Notice that the core pinctrl.h file provides a fancy macro 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 and so on. +Pin configuration +================= + +Pins can sometimes be software-configured in an various ways, mostly related +to their electronic properties when used as inputs or outputs. For example you +may be able to make an output pin high impedance, or "tristate" meaning it is +effectively disconnected. You may be able to connect an input pin to VDD or GND +using a certain resistor value - pull up and pull down - so that the pin has a +stable value when nothing is driving the rail it is connected to, or when it's +unconnected. + +For example, a platform may do this: + +ret = pin_config_set(dev, "FOO_GPIO_PIN", PLATFORM_X_PULL_UP); + +To pull up a pin to VDD. The pin configuration driver implements callbacks for +changing pin configuration in the pin controller ops like this: + +#include +#include +#include "platform_x_pindefs.h" + +int foo_pin_config_get(struct pinctrl_dev *pctldev, + unsigned offset, + unsigned long *config) +{ + struct my_conftype conf; + + ... Find setting for pin @ offset ... + + *config = (unsigned long) conf; +} + +int foo_pin_config_set(struct pinctrl_dev *pctldev, + unsigned offset, + unsigned long config) +{ + struct my_conftype *conf = (struct my_conftype *) config; + + switch (conf) { + case PLATFORM_X_PULL_UP: + ... + } + } +} + +int foo_pin_config_group_get (struct pinctrl_dev *pctldev, + unsigned selector, + unsigned long *config) +{ + ... +} + +int foo_pin_config_group_set (struct pinctrl_dev *pctldev, + unsigned selector, + unsigned long config) +{ + ... +} + +static struct pinconf_ops foo_pconf_ops = { + .pin_config_get = foo_pin_config_get, + .pin_config_set = foo_pin_config_set, + .pin_config_group_get = foo_pin_config_group_get, + .pin_config_group_set = foo_pin_config_group_set, +}; + +/* Pin config operations are handled by some pin controller */ +static struct pinctrl_desc foo_desc = { + ... + .confops = &foo_pconf_ops, +}; + +Since some controllers have special logic for handling entire groups of pins +they can exploit the special whole-group pin control function. The +pin_config_group_set() callback is allowed to return the error code -EAGAIN, +for groups it does not want to handle, or if it just wants to do some +group-level handling and then fall through to iterate over all pins, in which +case each individual pin will be treated by separate pin_config_set() calls as +well. + + Interaction with the GPIO subsystem =================================== diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig index e963da41e948f..c63c721029894 100644 --- a/drivers/pinctrl/Kconfig +++ b/drivers/pinctrl/Kconfig @@ -12,7 +12,10 @@ menu "Pin controllers" depends on PINCTRL config PINMUX - bool "Support pinmux controllers" + bool "Support pin multiplexing controllers" + +config PINCONF + bool "Support pin configuration controllers" config DEBUG_PINCTRL bool "Debug PINCTRL calls" diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile index 5f3e4d65465a1..c046f78dd7f70 100644 --- a/drivers/pinctrl/Makefile +++ b/drivers/pinctrl/Makefile @@ -4,6 +4,7 @@ ccflags-$(CONFIG_DEBUG_PINCTRL) += -DDEBUG obj-$(CONFIG_PINCTRL) += core.o obj-$(CONFIG_PINMUX) += pinmux.o +obj-$(CONFIG_PINCONF) += pinconf.o obj-$(CONFIG_PINMUX_SIRF) += pinmux-sirf.o obj-$(CONFIG_PINMUX_U300) += pinmux-u300.o obj-$(CONFIG_PINCTRL_COH901) += pinctrl-coh901.o diff --git a/drivers/pinctrl/core.c b/drivers/pinctrl/core.c index 4955a68d618fa..034b1ad38b323 100644 --- a/drivers/pinctrl/core.c +++ b/drivers/pinctrl/core.c @@ -28,6 +28,7 @@ #include #include "core.h" #include "pinmux.h" +#include "pinconf.h" /* Global list of pin control devices */ static DEFINE_MUTEX(pinctrldev_list_mutex); @@ -100,6 +101,30 @@ struct pin_desc *pin_desc_get(struct pinctrl_dev *pctldev, unsigned int pin) return pindesc; } +/** + * pin_get_from_name() - look up a pin number from a name + * @pctldev: the pin control device to lookup the pin on + * @name: the name of the pin to look up + */ +int pin_get_from_name(struct pinctrl_dev *pctldev, const char *name) +{ + unsigned pin; + + /* The highest pin number need to be included in the loop, thus <= */ + for (pin = 0; pin <= pctldev->desc->maxpin; pin++) { + struct pin_desc *desc; + + desc = pin_desc_get(pctldev, pin); + /* Pin space may be sparse */ + if (desc == NULL) + continue; + if (desc->name && !strcmp(name, desc->name)) + return pin; + } + + return -EINVAL; +} + /** * pin_is_valid() - check if pin exists on controller * @pctldev: the pin control device to check the pin on @@ -160,6 +185,7 @@ static int pinctrl_register_one_pin(struct pinctrl_dev *pctldev, pindesc = kzalloc(sizeof(*pindesc), GFP_KERNEL); if (pindesc == NULL) return -ENOMEM; + spin_lock_init(&pindesc->lock); /* Set owner */ @@ -409,11 +435,15 @@ static int pinctrl_devices_show(struct seq_file *s, void *what) { struct pinctrl_dev *pctldev; - seq_puts(s, "name [pinmux]\n"); + seq_puts(s, "name [pinmux] [pinconf]\n"); mutex_lock(&pinctrldev_list_mutex); list_for_each_entry(pctldev, &pinctrldev_list, node) { seq_printf(s, "%s ", pctldev->desc->name); if (pctldev->desc->pmxops) + seq_puts(s, "yes "); + else + seq_puts(s, "no "); + if (pctldev->desc->confops) seq_puts(s, "yes"); else seq_puts(s, "no"); @@ -492,6 +522,7 @@ static void pinctrl_init_device_debugfs(struct pinctrl_dev *pctldev) debugfs_create_file("gpio-ranges", S_IFREG | S_IRUGO, device_root, pctldev, &pinctrl_gpioranges_ops); pinmux_init_device_debugfs(device_root, pctldev); + pinconf_init_device_debugfs(device_root, pctldev); } static void pinctrl_init_debugfs(void) @@ -548,6 +579,16 @@ struct pinctrl_dev *pinctrl_register(struct pinctrl_desc *pctldesc, } } + /* If we're implementing pinconfig, check the ops for sanity */ + if (pctldesc->confops) { + ret = pinconf_check_ops(pctldesc->confops); + if (ret) { + pr_err("%s pin config ops lacks necessary functions\n", + pctldesc->name); + return NULL; + } + } + pctldev = kzalloc(sizeof(struct pinctrl_dev), GFP_KERNEL); if (pctldev == NULL) return NULL; diff --git a/drivers/pinctrl/core.h b/drivers/pinctrl/core.h index 74dee439dcf03..3f5b911acf181 100644 --- a/drivers/pinctrl/core.h +++ b/drivers/pinctrl/core.h @@ -9,6 +9,10 @@ * License terms: GNU General Public License (GPL) version 2 */ +#include + +struct pinctrl_gpio_range; + /** * struct pinctrl_dev - pin control class device * @node: node to include this pin controller in the global pin controller list @@ -66,6 +70,7 @@ struct pin_desc { struct pinctrl_dev *get_pinctrl_dev_from_dev(struct device *dev, const char *dev_name); struct pin_desc *pin_desc_get(struct pinctrl_dev *pctldev, unsigned int pin); +int pin_get_from_name(struct pinctrl_dev *pctldev, const char *name); int pinctrl_get_device_gpio_range(unsigned gpio, struct pinctrl_dev **outdev, struct pinctrl_gpio_range **outrange); diff --git a/drivers/pinctrl/pinconf.c b/drivers/pinctrl/pinconf.c new file mode 100644 index 0000000000000..9195eefe258a5 --- /dev/null +++ b/drivers/pinctrl/pinconf.c @@ -0,0 +1,302 @@ +/* + * Core driver for the pin config portions of the pin control subsystem + * + * Copyright (C) 2011 ST-Ericsson SA + * Written on behalf of Linaro for ST-Ericsson + * + * Author: Linus Walleij + * + * License terms: GNU General Public License (GPL) version 2 + */ +#define pr_fmt(fmt) "pinconfig core: " fmt + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "core.h" +#include "pinconf.h" + +int pin_config_get_for_pin(struct pinctrl_dev *pctldev, unsigned pin, + unsigned long *config) +{ + const struct pinconf_ops *ops = pctldev->desc->confops; + + if (!ops || !ops->pin_config_get) { + dev_err(&pctldev->dev, "cannot get pin configuration, missing " + "pin_config_get() function in driver\n"); + return -EINVAL; + } + + return ops->pin_config_get(pctldev, pin, config); +} + +/** + * pin_config_get() - get the configuration of a single pin parameter + * @pctldev: pin controller device for this pin + * @name: name of the pin to get the config for + * @config: the config pointed to by this argument will be filled in with the + * current pin state, it can be used directly by drivers as a numeral, or + * it can be dereferenced to any struct. + */ +int pin_config_get(struct pinctrl_dev *pctldev, const char *name, + unsigned long *config) +{ + int pin; + + pin = pin_get_from_name(pctldev, name); + if (pin < 0) + return pin; + + return pin_config_get_for_pin(pctldev, pin, config); +} +EXPORT_SYMBOL(pin_config_get); + +int pin_config_set_for_pin(struct pinctrl_dev *pctldev, unsigned pin, + unsigned long config) +{ + const struct pinconf_ops *ops = pctldev->desc->confops; + int ret; + + if (!ops || !ops->pin_config_set) { + dev_err(&pctldev->dev, "cannot configure pin, missing " + "config function in driver\n"); + return -EINVAL; + } + + ret = ops->pin_config_set(pctldev, pin, config); + if (ret) { + dev_err(&pctldev->dev, + "unable to set pin configuration on pin %d\n", pin); + return ret; + } + + return 0; +} + +/** + * pin_config_set() - set the configuration of a single pin parameter + * @pctldev: pin controller device for this pin + * @name: name of the pin to set the config for + * @config: the config in this argument will contain the desired pin state, it + * can be used directly by drivers as a numeral, or it can be dereferenced + * to any struct. + */ +int pin_config_set(struct pinctrl_dev *pctldev, const char *name, + unsigned long config) +{ + int pin; + + pin = pin_get_from_name(pctldev, name); + if (pin < 0) + return pin; + + return pin_config_set_for_pin(pctldev, pin, config); +} +EXPORT_SYMBOL(pin_config_set); + +int pin_config_group_get(struct pinctrl_dev *pctldev, const char *pin_group, + unsigned long *config) +{ + const struct pinconf_ops *ops = pctldev->desc->confops; + int selector; + + if (!ops || !ops->pin_config_group_get) { + dev_err(&pctldev->dev, "cannot get configuration for pin " + "group, missing group config get function in " + "driver\n"); + return -EINVAL; + } + + selector = pinctrl_get_group_selector(pctldev, pin_group); + if (selector < 0) + return selector; + + return ops->pin_config_group_get(pctldev, selector, config); +} +EXPORT_SYMBOL(pin_config_group_get); + + +int pin_config_group_set(struct pinctrl_dev *pctldev, const char *pin_group, + unsigned long config) +{ + const struct pinctrl_ops *pctlops = pctldev->desc->pctlops; + const struct pinconf_ops *ops = pctldev->desc->confops; + int selector; + const unsigned *pins; + unsigned num_pins; + int ret; + int i; + + if (!ops || (!ops->pin_config_group_set && !ops->pin_config_set)) { + dev_err(&pctldev->dev, "cannot configure pin group, missing " + "config function in driver\n"); + return -EINVAL; + } + + selector = pinctrl_get_group_selector(pctldev, pin_group); + if (selector < 0) + return selector; + + ret = pctlops->get_group_pins(pctldev, selector, &pins, &num_pins); + if (ret) { + dev_err(&pctldev->dev, "cannot configure pin group, error " + "getting pins\n"); + return ret; + } + + /* + * If the pin controller supports handling entire groups we use that + * capability. + */ + if (ops->pin_config_group_set) { + ret = ops->pin_config_group_set(pctldev, selector, config); + /* + * If the pin controller prefer that a certain group be handled + * pin-by-pin as well, it returns -EAGAIN. + */ + if (ret != -EAGAIN) + return ret; + } + + /* + * If the controller cannot handle entire groups, we configure each pin + * individually. + */ + if (!ops->pin_config_set) + return 0; + + for (i = 0; i < num_pins; i++) { + ret = ops->pin_config_set(pctldev, pins[i], config); + if (ret < 0) + return ret; + } + + return 0; +} +EXPORT_SYMBOL(pin_config_group_set); + +int pinconf_check_ops(const struct pinconf_ops *ops) +{ + /* We must be able to read out pin status */ + if (!ops->pin_config_get && !ops->pin_config_group_get) + return -EINVAL; + /* We have to be able to config the pins in SOME way */ + if (!ops->pin_config_set && !ops->pin_config_group_set) + return -EINVAL; + return 0; +} + +#ifdef CONFIG_DEBUG_FS + +static void pinconf_dump_pin(struct pinctrl_dev *pctldev, + struct seq_file *s, int pin) +{ + const struct pinconf_ops *ops = pctldev->desc->confops; + + if (ops && ops->pin_config_dbg_show) + ops->pin_config_dbg_show(pctldev, s, pin); +} + +static int pinconf_pins_show(struct seq_file *s, void *what) +{ + struct pinctrl_dev *pctldev = s->private; + unsigned pin; + + seq_puts(s, "Pin config settings per pin\n"); + seq_puts(s, "Format: pin (name): pinmux setting array\n"); + + /* The highest pin number need to be included in the loop, thus <= */ + for (pin = 0; pin <= pctldev->desc->maxpin; pin++) { + struct pin_desc *desc; + + desc = pin_desc_get(pctldev, pin); + /* Pin space may be sparse */ + if (desc == NULL) + continue; + + seq_printf(s, "pin %d (%s):", pin, + desc->name ? desc->name : "unnamed"); + + pinconf_dump_pin(pctldev, s, pin); + + seq_printf(s, "\n"); + } + + return 0; +} + +static void pinconf_dump_group(struct pinctrl_dev *pctldev, + struct seq_file *s, unsigned selector, + const char *gname) +{ + const struct pinconf_ops *ops = pctldev->desc->confops; + + if (ops && ops->pin_config_group_dbg_show) + ops->pin_config_group_dbg_show(pctldev, s, selector); +} + +static int pinconf_groups_show(struct seq_file *s, void *what) +{ + struct pinctrl_dev *pctldev = s->private; + const struct pinctrl_ops *pctlops = pctldev->desc->pctlops; + const struct pinconf_ops *ops = pctldev->desc->confops; + unsigned selector = 0; + + if (!ops || !ops->pin_config_group_get) + return 0; + + seq_puts(s, "Pin config settings per pin group\n"); + seq_puts(s, "Format: group (name): pinmux setting array\n"); + + while (pctlops->list_groups(pctldev, selector) >= 0) { + const char *gname = pctlops->get_group_name(pctldev, selector); + + seq_printf(s, "%u (%s):", selector, gname); + pinconf_dump_group(pctldev, s, selector, gname); + selector++; + } + + return 0; +} + +static int pinconf_pins_open(struct inode *inode, struct file *file) +{ + return single_open(file, pinconf_pins_show, inode->i_private); +} + +static int pinconf_groups_open(struct inode *inode, struct file *file) +{ + return single_open(file, pinconf_groups_show, inode->i_private); +} + +static const struct file_operations pinconf_pins_ops = { + .open = pinconf_pins_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static const struct file_operations pinconf_groups_ops = { + .open = pinconf_groups_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +void pinconf_init_device_debugfs(struct dentry *devroot, + struct pinctrl_dev *pctldev) +{ + debugfs_create_file("pinconf-pins", S_IFREG | S_IRUGO, + devroot, pctldev, &pinconf_pins_ops); + debugfs_create_file("pinconf-groups", S_IFREG | S_IRUGO, + devroot, pctldev, &pinconf_groups_ops); +} + +#endif diff --git a/drivers/pinctrl/pinconf.h b/drivers/pinctrl/pinconf.h new file mode 100644 index 0000000000000..e7dc6165032a3 --- /dev/null +++ b/drivers/pinctrl/pinconf.h @@ -0,0 +1,36 @@ +/* + * Internal interface between the core pin control system and the + * pin config portions + * + * Copyright (C) 2011 ST-Ericsson SA + * Written on behalf of Linaro for ST-Ericsson + * Based on bits of regulator core, gpio core and clk core + * + * Author: Linus Walleij + * + * License terms: GNU General Public License (GPL) version 2 + */ + +#ifdef CONFIG_PINCONF + +int pinconf_check_ops(const struct pinconf_ops *ops); +void pinconf_init_device_debugfs(struct dentry *devroot, + struct pinctrl_dev *pctldev); +int pin_config_get_for_pin(struct pinctrl_dev *pctldev, unsigned pin, + unsigned long *config); +int pin_config_set_for_pin(struct pinctrl_dev *pctldev, unsigned pin, + unsigned long config); + +#else + +static inline int pinconf_check_ops(const struct pinconf_ops *ops) +{ + return 0; +} + +static inline void pinconf_init_device_debugfs(struct dentry *devroot, + struct pinctrl_dev *pctldev) +{ +} + +#endif diff --git a/include/linux/pinctrl/pinconf.h b/include/linux/pinctrl/pinconf.h new file mode 100644 index 0000000000000..d5b72e6e261d6 --- /dev/null +++ b/include/linux/pinctrl/pinconf.h @@ -0,0 +1,96 @@ +/* + * Interface the pinconfig portions of the pinctrl subsystem + * + * Copyright (C) 2011 ST-Ericsson SA + * Written on behalf of Linaro for ST-Ericsson + * This interface is used in the core to keep track of pins. + * + * Author: Linus Walleij + * + * License terms: GNU General Public License (GPL) version 2 + */ +#ifndef __LINUX_PINCTRL_PINCONF_H +#define __LINUX_PINCTRL_PINCONF_H + +#ifdef CONFIG_PINCONF + +struct pinctrl_dev; + +/** + * struct pinconf_ops - pin config operations, to be implemented by + * pin configuration capable drivers. + * @pin_config_get: get the config of a certain pin, if the requested config + * is not available on this controller this should return -ENOTSUPP + * and if it is available but disabled it should return -EINVAL + * @pin_config_get: get the config of a certain pin + * @pin_config_set: configure an individual pin + * @pin_config_group_get: get configurations for an entire pin group + * @pin_config_group_set: configure all pins in a group + * @pin_config_dbg_show: optional debugfs display hook that will provide + * per-device info for a certain pin in debugfs + * @pin_config_group_dbg_show: optional debugfs display hook that will provide + * per-device info for a certain group in debugfs + */ +struct pinconf_ops { + int (*pin_config_get) (struct pinctrl_dev *pctldev, + unsigned pin, + unsigned long *config); + int (*pin_config_set) (struct pinctrl_dev *pctldev, + unsigned pin, + unsigned long config); + int (*pin_config_group_get) (struct pinctrl_dev *pctldev, + unsigned selector, + unsigned long *config); + int (*pin_config_group_set) (struct pinctrl_dev *pctldev, + unsigned selector, + unsigned long config); + void (*pin_config_dbg_show) (struct pinctrl_dev *pctldev, + struct seq_file *s, + unsigned offset); + void (*pin_config_group_dbg_show) (struct pinctrl_dev *pctldev, + struct seq_file *s, + unsigned selector); +}; + +extern int pin_config_get(struct pinctrl_dev *pctldev, const char *name, + unsigned long *config); +extern int pin_config_set(struct pinctrl_dev *pctldev, const char *name, + unsigned long config); +extern int pin_config_group_get(struct pinctrl_dev *pctldev, + const char *pin_group, + unsigned long *config); +extern int pin_config_group_set(struct pinctrl_dev *pctldev, + const char *pin_group, + unsigned long config); + +#else + +static inline int pin_config_get(struct pinctrl_dev *pctldev, const char *name, + unsigned long *config) +{ + return 0; +} + +static inline int pin_config_set(struct pinctrl_dev *pctldev, const char *name, + unsigned long config) +{ + return 0; +} + +static inline int pin_config_group_get(struct pinctrl_dev *pctldev, + const char *pin_group, + unsigned long *config) +{ + return 0; +} + +static inline int pin_config_group_set(struct pinctrl_dev *pctldev, + const char *pin_group, + unsigned long config) +{ + return 0; +} + +#endif + +#endif /* __LINUX_PINCTRL_PINCONF_H */ diff --git a/include/linux/pinctrl/pinctrl.h b/include/linux/pinctrl/pinctrl.h index f17fac4b51f18..9809a94f151b9 100644 --- a/include/linux/pinctrl/pinctrl.h +++ b/include/linux/pinctrl/pinctrl.h @@ -21,6 +21,7 @@ struct pinctrl_dev; struct pinmux_ops; +struct pinconf_ops; struct gpio_chip; /** @@ -97,7 +98,9 @@ struct pinctrl_ops { * but may be equal to npins if you have no holes in the pin range. * @pctlops: pin control operation vtable, to support global concepts like * grouping of pins, this is optional. - * @pmxops: pinmux operation vtable, if you support pinmuxing in your driver + * @pmxops: pinmux operations vtable, if you support pinmuxing in your driver + * @confops: pin config operations vtable, if you support pin configuration in + * your driver * @owner: module providing the pin controller, used for refcounting */ struct pinctrl_desc { @@ -107,6 +110,7 @@ struct pinctrl_desc { unsigned int maxpin; struct pinctrl_ops *pctlops; struct pinmux_ops *pmxops; + struct pinconf_ops *confops; struct module *owner; }; @@ -125,7 +129,7 @@ extern void *pinctrl_dev_get_drvdata(struct pinctrl_dev *pctldev); struct pinctrl_dev; -/* Sufficiently stupid default function when pinctrl is not in use */ +/* Sufficiently stupid default functions when pinctrl is not in use */ static inline bool pin_is_valid(struct pinctrl_dev *pctldev, int pin) { return pin >= 0; From 1ddb6ff03c0cdec58c6cfdbada95acddcce4a7b7 Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Fri, 9 Dec 2011 16:59:03 -0700 Subject: [PATCH 21/31] pinctrl: implement PINMUX_MAP_SYS_HOG This is the same as PINMUX_MAP_PRIMARY_SYS_HOG, except that it allows you to specify a particular control device. Signed-off-by: Stephen Warren Signed-off-by: Linus Walleij --- include/linux/pinctrl/machine.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/include/linux/pinctrl/machine.h b/include/linux/pinctrl/machine.h index f5372319d9990..0ca32eb63b679 100644 --- a/include/linux/pinctrl/machine.h +++ b/include/linux/pinctrl/machine.h @@ -65,6 +65,14 @@ struct pinmux_map { #define PINMUX_MAP_SYS(a, b, c) \ { .name = a, .ctrl_dev_name = b, .function = c } +/* + * Convenience macro to map a system function onto a certain pinctrl device, + * to be hogged by the pinmux core until the system shuts down. + */ +#define PINMUX_MAP_SYS_HOG(a, b, c) \ + { .name = a, .ctrl_dev_name = b, .function = c, \ + .hog_on_boot = true } + /* * Convenience macro to map a function onto the primary device pinctrl device * this is especially helpful on systems that have only one pin controller From 528b78306ecf82af06c4862aa5518643fe20a440 Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Fri, 9 Dec 2011 16:59:04 -0700 Subject: [PATCH 22/31] arm/u300: don't use PINMUX_MAP_PRIMARY* The next patch will remove these macros. Signed-off-by: Stephen Warren Signed-off-by: Linus Walleij --- arch/arm/mach-u300/core.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/arch/arm/mach-u300/core.c b/arch/arm/mach-u300/core.c index 839fa15c4eb61..39e2208649887 100644 --- a/arch/arm/mach-u300/core.c +++ b/arch/arm/mach-u300/core.c @@ -1607,13 +1607,13 @@ static struct platform_device pinmux_device = { /* Pinmux settings */ static struct pinmux_map __initdata u300_pinmux_map[] = { /* anonymous maps for chip power and EMIFs */ - PINMUX_MAP_PRIMARY_SYS_HOG("POWER", "power"), - PINMUX_MAP_PRIMARY_SYS_HOG("EMIF0", "emif0"), - PINMUX_MAP_PRIMARY_SYS_HOG("EMIF1", "emif1"), + PINMUX_MAP_SYS_HOG("POWER", "pinmux-u300", "power"), + PINMUX_MAP_SYS_HOG("EMIF0", "pinmux-u300", "emif0"), + PINMUX_MAP_SYS_HOG("EMIF1", "pinmux-u300", "emif1"), /* per-device maps for MMC/SD, SPI and UART */ - PINMUX_MAP_PRIMARY("MMCSD", "mmc0", "mmci"), - PINMUX_MAP_PRIMARY("SPI", "spi0", "pl022"), - PINMUX_MAP_PRIMARY("UART0", "uart0", "uart0"), + PINMUX_MAP("MMCSD", "pinmux-u300", "mmc0", "mmci"), + PINMUX_MAP("SPI", "pinmux-u300", "spi0", "pl022"), + PINMUX_MAP("UART0", "pinmux-u300", "uart0", "uart0"), }; struct u300_mux_hog { From 51cd24ee625c348654114032499914d0311e5832 Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Fri, 9 Dec 2011 16:59:05 -0700 Subject: [PATCH 23/31] pinctrl: don't create a device for each pin controller Pin controllers should already be instantiated as a device, so there's no need for the pinctrl core to create a new struct device for each controller. This allows the controller's real name to be used in the mux mapping table, rather than e.g. "pinctrl.0", "pinctrl.1", etc. This necessitates removal of the PINMUX_MAP_PRIMARY*() macros, since their sole purpose was to hard-code the .ctrl_dev_name field to be "pinctrl.0". Signed-off-by: Stephen Warren Signed-off-by: Linus Walleij --- Documentation/pinctrl.txt | 26 +++++++++---------- drivers/pinctrl/core.c | 42 ++++++++---------------------- drivers/pinctrl/core.h | 2 +- drivers/pinctrl/pinconf.c | 12 ++++----- drivers/pinctrl/pinmux.c | 46 ++++++++++++++++----------------- include/linux/pinctrl/machine.h | 25 ------------------ 6 files changed, 54 insertions(+), 99 deletions(-) diff --git a/Documentation/pinctrl.txt b/Documentation/pinctrl.txt index 6d23fa84ee47f..f080643682913 100644 --- a/Documentation/pinctrl.txt +++ b/Documentation/pinctrl.txt @@ -783,17 +783,17 @@ spi on the second function mapping: static const struct pinmux_map __initdata pmx_mapping[] = { { - .ctrl_dev_name = "pinctrl.0", + .ctrl_dev_name = "pinctrl-foo", .function = "spi0", .dev_name = "foo-spi.0", }, { - .ctrl_dev_name = "pinctrl.0", + .ctrl_dev_name = "pinctrl-foo", .function = "i2c0", .dev_name = "foo-i2c.0", }, { - .ctrl_dev_name = "pinctrl.0", + .ctrl_dev_name = "pinctrl-foo", .function = "mmc0", .dev_name = "foo-mmc.0", }, @@ -815,7 +815,7 @@ You register this pinmux mapping to the pinmux subsystem by simply: ret = pinmux_register_mappings(pmx_mapping, ARRAY_SIZE(pmx_mapping)); Since the above construct is pretty common there is a helper macro to make -it even more compact which assumes you want to use pinctrl.0 and position +it even more compact which assumes you want to use pinctrl-foo and position 0 for mapping, for example: static struct pinmux_map __initdata pmx_mapping[] = { @@ -832,14 +832,14 @@ As it is possible to map a function to different groups of pins an optional ... { .name = "spi0-pos-A", - .ctrl_dev_name = "pinctrl.0", + .ctrl_dev_name = "pinctrl-foo", .function = "spi0", .group = "spi0_0_grp", .dev_name = "foo-spi.0", }, { .name = "spi0-pos-B", - .ctrl_dev_name = "pinctrl.0", + .ctrl_dev_name = "pinctrl-foo", .function = "spi0", .group = "spi0_1_grp", .dev_name = "foo-spi.0", @@ -858,42 +858,42 @@ case), we define a mapping like this: ... { .name "2bit" - .ctrl_dev_name = "pinctrl.0", + .ctrl_dev_name = "pinctrl-foo", .function = "mmc0", .group = "mmc0_1_grp", .dev_name = "foo-mmc.0", }, { .name "4bit" - .ctrl_dev_name = "pinctrl.0", + .ctrl_dev_name = "pinctrl-foo", .function = "mmc0", .group = "mmc0_1_grp", .dev_name = "foo-mmc.0", }, { .name "4bit" - .ctrl_dev_name = "pinctrl.0", + .ctrl_dev_name = "pinctrl-foo", .function = "mmc0", .group = "mmc0_2_grp", .dev_name = "foo-mmc.0", }, { .name "8bit" - .ctrl_dev_name = "pinctrl.0", + .ctrl_dev_name = "pinctrl-foo", .function = "mmc0", .group = "mmc0_1_grp", .dev_name = "foo-mmc.0", }, { .name "8bit" - .ctrl_dev_name = "pinctrl.0", + .ctrl_dev_name = "pinctrl-foo", .function = "mmc0", .group = "mmc0_2_grp", .dev_name = "foo-mmc.0", }, { .name "8bit" - .ctrl_dev_name = "pinctrl.0", + .ctrl_dev_name = "pinctrl-foo", .function = "mmc0", .group = "mmc0_3_grp", .dev_name = "foo-mmc.0", @@ -996,7 +996,7 @@ like this: { .name "POWERMAP" - .ctrl_dev_name = "pinctrl.0", + .ctrl_dev_name = "pinctrl-foo", .function = "power_func", .hog_on_boot = true, }, diff --git a/drivers/pinctrl/core.c b/drivers/pinctrl/core.c index 034b1ad38b323..160fb5aae591c 100644 --- a/drivers/pinctrl/core.c +++ b/drivers/pinctrl/core.c @@ -34,12 +34,6 @@ static DEFINE_MUTEX(pinctrldev_list_mutex); static LIST_HEAD(pinctrldev_list); -static void pinctrl_dev_release(struct device *dev) -{ - struct pinctrl_dev *pctldev = dev_get_drvdata(dev); - kfree(pctldev); -} - const char *pinctrl_dev_get_name(struct pinctrl_dev *pctldev) { /* We're not allowed to register devices without name */ @@ -71,14 +65,14 @@ struct pinctrl_dev *get_pinctrl_dev_from_dev(struct device *dev, mutex_lock(&pinctrldev_list_mutex); list_for_each_entry(pctldev, &pinctrldev_list, node) { - if (dev && &pctldev->dev == dev) { + if (dev && pctldev->dev == dev) { /* Matched on device pointer */ found = true; break; } if (devname && - !strcmp(dev_name(&pctldev->dev), devname)) { + !strcmp(dev_name(pctldev->dev), devname)) { /* Matched on device name */ found = true; break; @@ -325,7 +319,7 @@ int pinctrl_get_group_selector(struct pinctrl_dev *pctldev, const char *gname = pctlops->get_group_name(pctldev, group_selector); if (!strcmp(gname, pin_group)) { - dev_dbg(&pctldev->dev, + dev_dbg(pctldev->dev, "found group selector %u for %s\n", group_selector, pin_group); @@ -335,7 +329,7 @@ int pinctrl_get_group_selector(struct pinctrl_dev *pctldev, group_selector++; } - dev_err(&pctldev->dev, "does not have pin group %s\n", + dev_err(pctldev->dev, "does not have pin group %s\n", pin_group); return -EINVAL; @@ -508,11 +502,11 @@ static void pinctrl_init_device_debugfs(struct pinctrl_dev *pctldev) { static struct dentry *device_root; - device_root = debugfs_create_dir(dev_name(&pctldev->dev), + device_root = debugfs_create_dir(dev_name(pctldev->dev), debugfs_root); if (IS_ERR(device_root) || !device_root) { pr_warn("failed to create debugfs directory for %s\n", - dev_name(&pctldev->dev)); + dev_name(pctldev->dev)); return; } debugfs_create_file("pins", S_IFREG | S_IRUGO, @@ -560,7 +554,6 @@ static void pinctrl_init_debugfs(void) struct pinctrl_dev *pinctrl_register(struct pinctrl_desc *pctldesc, struct device *dev, void *driver_data) { - static atomic_t pinmux_no = ATOMIC_INIT(0); struct pinctrl_dev *pctldev; int ret; @@ -601,18 +594,7 @@ struct pinctrl_dev *pinctrl_register(struct pinctrl_desc *pctldesc, spin_lock_init(&pctldev->pin_desc_tree_lock); INIT_LIST_HEAD(&pctldev->gpio_ranges); mutex_init(&pctldev->gpio_ranges_lock); - - /* Register device */ - pctldev->dev.parent = dev; - dev_set_name(&pctldev->dev, "pinctrl.%d", - atomic_inc_return(&pinmux_no) - 1); - pctldev->dev.release = pinctrl_dev_release; - ret = device_register(&pctldev->dev); - if (ret != 0) { - pr_err("error in device registration\n"); - goto out_reg_dev_err; - } - dev_set_drvdata(&pctldev->dev, pctldev); + pctldev->dev = dev; /* Register all the pins */ pr_debug("try to register %d pins on %s...\n", @@ -622,7 +604,7 @@ struct pinctrl_dev *pinctrl_register(struct pinctrl_desc *pctldesc, pr_err("error during pin registration\n"); pinctrl_free_pindescs(pctldev, pctldesc->pins, pctldesc->npins); - goto out_reg_pins_err; + goto out_err; } pinctrl_init_device_debugfs(pctldev); @@ -632,10 +614,8 @@ struct pinctrl_dev *pinctrl_register(struct pinctrl_desc *pctldesc, pinmux_hog_maps(pctldev); return pctldev; -out_reg_pins_err: - device_del(&pctldev->dev); -out_reg_dev_err: - put_device(&pctldev->dev); +out_err: + kfree(pctldev); return NULL; } EXPORT_SYMBOL_GPL(pinctrl_register); @@ -659,7 +639,7 @@ void pinctrl_unregister(struct pinctrl_dev *pctldev) /* Destroy descriptor tree */ pinctrl_free_pindescs(pctldev, pctldev->desc->pins, pctldev->desc->npins); - device_unregister(&pctldev->dev); + kfree(pctldev); } EXPORT_SYMBOL_GPL(pinctrl_unregister); diff --git a/drivers/pinctrl/core.h b/drivers/pinctrl/core.h index 3f5b911acf181..5375582566a5f 100644 --- a/drivers/pinctrl/core.h +++ b/drivers/pinctrl/core.h @@ -38,7 +38,7 @@ struct pinctrl_dev { spinlock_t pin_desc_tree_lock; struct list_head gpio_ranges; struct mutex gpio_ranges_lock; - struct device dev; + struct device *dev; struct module *owner; void *driver_data; #ifdef CONFIG_PINMUX diff --git a/drivers/pinctrl/pinconf.c b/drivers/pinctrl/pinconf.c index 9195eefe258a5..124762b570244 100644 --- a/drivers/pinctrl/pinconf.c +++ b/drivers/pinctrl/pinconf.c @@ -29,7 +29,7 @@ int pin_config_get_for_pin(struct pinctrl_dev *pctldev, unsigned pin, const struct pinconf_ops *ops = pctldev->desc->confops; if (!ops || !ops->pin_config_get) { - dev_err(&pctldev->dev, "cannot get pin configuration, missing " + dev_err(pctldev->dev, "cannot get pin configuration, missing " "pin_config_get() function in driver\n"); return -EINVAL; } @@ -65,14 +65,14 @@ int pin_config_set_for_pin(struct pinctrl_dev *pctldev, unsigned pin, int ret; if (!ops || !ops->pin_config_set) { - dev_err(&pctldev->dev, "cannot configure pin, missing " + dev_err(pctldev->dev, "cannot configure pin, missing " "config function in driver\n"); return -EINVAL; } ret = ops->pin_config_set(pctldev, pin, config); if (ret) { - dev_err(&pctldev->dev, + dev_err(pctldev->dev, "unable to set pin configuration on pin %d\n", pin); return ret; } @@ -108,7 +108,7 @@ int pin_config_group_get(struct pinctrl_dev *pctldev, const char *pin_group, int selector; if (!ops || !ops->pin_config_group_get) { - dev_err(&pctldev->dev, "cannot get configuration for pin " + dev_err(pctldev->dev, "cannot get configuration for pin " "group, missing group config get function in " "driver\n"); return -EINVAL; @@ -135,7 +135,7 @@ int pin_config_group_set(struct pinctrl_dev *pctldev, const char *pin_group, int i; if (!ops || (!ops->pin_config_group_set && !ops->pin_config_set)) { - dev_err(&pctldev->dev, "cannot configure pin group, missing " + dev_err(pctldev->dev, "cannot configure pin group, missing " "config function in driver\n"); return -EINVAL; } @@ -146,7 +146,7 @@ int pin_config_group_set(struct pinctrl_dev *pctldev, const char *pin_group, ret = pctlops->get_group_pins(pctldev, selector, &pins, &num_pins); if (ret) { - dev_err(&pctldev->dev, "cannot configure pin group, error " + dev_err(pctldev->dev, "cannot configure pin group, error " "getting pins\n"); return ret; } diff --git a/drivers/pinctrl/pinmux.c b/drivers/pinctrl/pinmux.c index a11681b4bd919..3bcc64137ddc9 100644 --- a/drivers/pinctrl/pinmux.c +++ b/drivers/pinctrl/pinmux.c @@ -106,24 +106,24 @@ static int pin_request(struct pinctrl_dev *pctldev, const struct pinmux_ops *ops = pctldev->desc->pmxops; int status = -EINVAL; - dev_dbg(&pctldev->dev, "request pin %d for %s\n", pin, function); + dev_dbg(pctldev->dev, "request pin %d for %s\n", pin, function); desc = pin_desc_get(pctldev, pin); if (desc == NULL) { - dev_err(&pctldev->dev, + dev_err(pctldev->dev, "pin is not registered so it cannot be requested\n"); goto out; } if (!function) { - dev_err(&pctldev->dev, "no function name given\n"); + dev_err(pctldev->dev, "no function name given\n"); return -EINVAL; } spin_lock(&desc->lock); if (desc->mux_function) { spin_unlock(&desc->lock); - dev_err(&pctldev->dev, + dev_err(pctldev->dev, "pin already requested\n"); goto out; } @@ -132,7 +132,7 @@ static int pin_request(struct pinctrl_dev *pctldev, /* Let each pin increase references to this module */ if (!try_module_get(pctldev->owner)) { - dev_err(&pctldev->dev, + dev_err(pctldev->dev, "could not increase module refcount for pin %d\n", pin); status = -EINVAL; @@ -152,7 +152,7 @@ static int pin_request(struct pinctrl_dev *pctldev, status = 0; if (status) - dev_err(&pctldev->dev, "->request on device %s failed " + dev_err(pctldev->dev, "->request on device %s failed " "for pin %d\n", pctldev->desc->name, pin); out_free_pin: @@ -163,7 +163,7 @@ static int pin_request(struct pinctrl_dev *pctldev, } out: if (status) - dev_err(&pctldev->dev, "pin-%d (%s) status %d\n", + dev_err(pctldev->dev, "pin-%d (%s) status %d\n", pin, function ? : "?", status); return status; @@ -189,7 +189,7 @@ static const char *pin_free(struct pinctrl_dev *pctldev, int pin, desc = pin_desc_get(pctldev, pin); if (desc == NULL) { - dev_err(&pctldev->dev, + dev_err(pctldev->dev, "pin is not registered so it cannot be freed\n"); return NULL; } @@ -434,14 +434,14 @@ static int acquire_pins(struct pinctrl_dev *pctldev, if (ret) return ret; - dev_dbg(&pctldev->dev, "requesting the %u pins from group %u\n", + dev_dbg(pctldev->dev, "requesting the %u pins from group %u\n", num_pins, group_selector); /* Try to allocate all pins in this group, one by one */ for (i = 0; i < num_pins; i++) { ret = pin_request(pctldev, pins[i], func, NULL); if (ret) { - dev_err(&pctldev->dev, + dev_err(pctldev->dev, "could not get pin %d for function %s " "on device %s - conflicting mux mappings?\n", pins[i], func ? : "(undefined)", @@ -473,7 +473,7 @@ static void release_pins(struct pinctrl_dev *pctldev, ret = pctlops->get_group_pins(pctldev, group_selector, &pins, &num_pins); if (ret) { - dev_err(&pctldev->dev, "could not get pins to release for " + dev_err(pctldev->dev, "could not get pins to release for " "group selector %d\n", group_selector); return; @@ -525,7 +525,7 @@ static int pinmux_check_pin_group(struct pinctrl_dev *pctldev, return -EINVAL; ret = pinctrl_get_group_selector(pctldev, groups[0]); if (ret < 0) { - dev_err(&pctldev->dev, + dev_err(pctldev->dev, "function %s wants group %s but the pin " "controller does not seem to have that group\n", pmxops->get_function_name(pctldev, func_selector), @@ -534,7 +534,7 @@ static int pinmux_check_pin_group(struct pinctrl_dev *pctldev, } if (num_groups > 1) - dev_dbg(&pctldev->dev, + dev_dbg(pctldev->dev, "function %s support more than one group, " "default-selecting first group %s (%d)\n", pmxops->get_function_name(pctldev, func_selector), @@ -544,13 +544,13 @@ static int pinmux_check_pin_group(struct pinctrl_dev *pctldev, return ret; } - dev_dbg(&pctldev->dev, + dev_dbg(pctldev->dev, "check if we have pin group %s on controller %s\n", pin_group, pinctrl_dev_get_name(pctldev)); ret = pinctrl_get_group_selector(pctldev, pin_group); if (ret < 0) { - dev_dbg(&pctldev->dev, + dev_dbg(pctldev->dev, "%s does not support pin group %s with function %s\n", pinctrl_dev_get_name(pctldev), pin_group, @@ -627,7 +627,7 @@ static int pinmux_enable_muxmap(struct pinctrl_dev *pctldev, */ if (pmx->pctldev && pmx->pctldev != pctldev) { - dev_err(&pctldev->dev, + dev_err(pctldev->dev, "different pin control devices given for device %s, " "function %s\n", devname, @@ -650,7 +650,7 @@ static int pinmux_enable_muxmap(struct pinctrl_dev *pctldev, */ if (pmx->func_selector != UINT_MAX && pmx->func_selector != func_selector) { - dev_err(&pctldev->dev, + dev_err(pctldev->dev, "dual function defines in the map for device %s\n", devname); return -EINVAL; @@ -756,7 +756,7 @@ struct pinmux *pinmux_get(struct device *dev, const char *name) } pr_debug("in map, found pctldev %s to handle function %s", - dev_name(&pctldev->dev), map->function); + dev_name(pctldev->dev), map->function); /* @@ -932,7 +932,7 @@ static int pinmux_hog_map(struct pinctrl_dev *pctldev, * without any problems, so then we can hog pinmuxes for * all devices that just want a static pin mux at this point. */ - dev_err(&pctldev->dev, "map %s wants to hog a non-system " + dev_err(pctldev->dev, "map %s wants to hog a non-system " "pinmux, this is not going to work\n", map->name); return -EINVAL; } @@ -944,7 +944,7 @@ static int pinmux_hog_map(struct pinctrl_dev *pctldev, pmx = pinmux_get(NULL, map->name); if (IS_ERR(pmx)) { kfree(hog); - dev_err(&pctldev->dev, + dev_err(pctldev->dev, "could not get the %s pinmux mapping for hogging\n", map->name); return PTR_ERR(pmx); @@ -954,7 +954,7 @@ static int pinmux_hog_map(struct pinctrl_dev *pctldev, if (ret) { pinmux_put(pmx); kfree(hog); - dev_err(&pctldev->dev, + dev_err(pctldev->dev, "could not enable the %s pinmux mapping for hogging\n", map->name); return ret; @@ -963,7 +963,7 @@ static int pinmux_hog_map(struct pinctrl_dev *pctldev, hog->map = map; hog->pmx = pmx; - dev_info(&pctldev->dev, "hogged map %s, function %s\n", map->name, + dev_info(pctldev->dev, "hogged map %s, function %s\n", map->name, map->function); mutex_lock(&pctldev->pinmux_hogs_lock); list_add(&hog->node, &pctldev->pinmux_hogs); @@ -982,7 +982,7 @@ static int pinmux_hog_map(struct pinctrl_dev *pctldev, */ int pinmux_hog_maps(struct pinctrl_dev *pctldev) { - struct device *dev = &pctldev->dev; + struct device *dev = pctldev->dev; const char *devname = dev_name(dev); int ret; int i; diff --git a/include/linux/pinctrl/machine.h b/include/linux/pinctrl/machine.h index 0ca32eb63b679..ad430e05a7ba2 100644 --- a/include/linux/pinctrl/machine.h +++ b/include/linux/pinctrl/machine.h @@ -73,31 +73,6 @@ struct pinmux_map { { .name = a, .ctrl_dev_name = b, .function = c, \ .hog_on_boot = true } -/* - * Convenience macro to map a function onto the primary device pinctrl device - * this is especially helpful on systems that have only one pin controller - * or need to set up a lot of mappings on the primary controller. - */ -#define PINMUX_MAP_PRIMARY(a, b, c) \ - { .name = a, .ctrl_dev_name = "pinctrl.0", .function = b, \ - .dev_name = c } - -/* - * Convenience macro to map a system function onto the primary pinctrl device. - * System functions are not assigned to a particular device. - */ -#define PINMUX_MAP_PRIMARY_SYS(a, b) \ - { .name = a, .ctrl_dev_name = "pinctrl.0", .function = b } - -/* - * Convenience macro to map a system function onto the primary pinctrl device, - * to be hogged by the pinmux core until the system shuts down. - */ -#define PINMUX_MAP_PRIMARY_SYS_HOG(a, b) \ - { .name = a, .ctrl_dev_name = "pinctrl.0", .function = b, \ - .hog_on_boot = true } - - #ifdef CONFIG_PINMUX extern int pinmux_register_mappings(struct pinmux_map const *map, From 23750196ef472e9249958d5165b0bb292518c710 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Wed, 14 Dec 2011 09:30:08 +0100 Subject: [PATCH 24/31] pinctrl: add a group-specific hog macro To create elegant tables for pinmux hogs on the PXA MMP platform, we need this hog macro that can specify both function and group in one go. Acked-by: Stephen Warren Acked-by: Haojian Zhuang Signed-off-by: Linus Walleij --- include/linux/pinctrl/machine.h | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/include/linux/pinctrl/machine.h b/include/linux/pinctrl/machine.h index ad430e05a7ba2..d0aecb7f6fb9f 100644 --- a/include/linux/pinctrl/machine.h +++ b/include/linux/pinctrl/machine.h @@ -73,6 +73,15 @@ struct pinmux_map { { .name = a, .ctrl_dev_name = b, .function = c, \ .hog_on_boot = true } +/* + * Convenience macro to map a system function onto a certain pinctrl device + * using a specified group, to be hogged by the pinmux core until the system + * shuts down. + */ +#define PINMUX_MAP_SYS_HOG_GROUP(a, b, c, d) \ + { .name = a, .ctrl_dev_name = b, .function = c, .group = d, \ + .hog_on_boot = true } + #ifdef CONFIG_PINMUX extern int pinmux_register_mappings(struct pinmux_map const *map, From ca53c5f1ca5c936777caca46b7c716a40682ce83 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Wed, 14 Dec 2011 20:33:37 +0100 Subject: [PATCH 25/31] pinctrl: conjure names for unnamed pins If pins with blank names are registered, we assign them names on-the-fly on the form "PINn" where n is the pin number for that pin on the specific controller. Acked-by: Stephen Warren Signed-off-by: Linus Walleij --- drivers/pinctrl/core.c | 13 +++++++++++-- drivers/pinctrl/core.h | 2 ++ 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/drivers/pinctrl/core.c b/drivers/pinctrl/core.c index 160fb5aae591c..9e32ea311432a 100644 --- a/drivers/pinctrl/core.c +++ b/drivers/pinctrl/core.c @@ -158,6 +158,8 @@ static void pinctrl_free_pindescs(struct pinctrl_dev *pctldev, if (pindesc != NULL) { radix_tree_delete(&pctldev->pin_desc_tree, pins[i].number); + if (pindesc->dynamic_name) + kfree(pindesc->name); } kfree(pindesc); } @@ -186,13 +188,20 @@ static int pinctrl_register_one_pin(struct pinctrl_dev *pctldev, pindesc->pctldev = pctldev; /* Copy basic pin info */ - pindesc->name = name; + if (pindesc->name) { + pindesc->name = name; + } else { + pindesc->name = kasprintf(GFP_KERNEL, "PIN%u", number); + if (pindesc->name == NULL) + return -ENOMEM; + pindesc->dynamic_name = true; + } spin_lock(&pctldev->pin_desc_tree_lock); radix_tree_insert(&pctldev->pin_desc_tree, number, pindesc); spin_unlock(&pctldev->pin_desc_tree_lock); pr_debug("registered pin %d (%s) on %s\n", - number, name ? name : "(unnamed)", pctldev->desc->name); + number, pindesc->name, pctldev->desc->name); return 0; } diff --git a/drivers/pinctrl/core.h b/drivers/pinctrl/core.h index 5375582566a5f..177a3310547f3 100644 --- a/drivers/pinctrl/core.h +++ b/drivers/pinctrl/core.h @@ -52,6 +52,7 @@ struct pinctrl_dev { * @pctldev: corresponding pin control device * @name: a name for the pin, e.g. the name of the pin/pad/finger on a * datasheet or such + * @dynamic_name: if the name of this pin was dynamically allocated * @lock: a lock to protect the descriptor structure * @mux_requested: whether the pin is already requested by pinmux or not * @mux_function: a named muxing function for the pin that will be passed to @@ -60,6 +61,7 @@ struct pinctrl_dev { struct pin_desc { struct pinctrl_dev *pctldev; const char *name; + bool dynamic_name; spinlock_t lock; /* These fields only added when supporting pinmux drivers */ #ifdef CONFIG_PINMUX From 63fd5984a9b2214cba7dd7dd7b5a75cf40dde39f Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Thu, 15 Dec 2011 16:57:16 -0700 Subject: [PATCH 26/31] pinctrl: add "struct seq_file;" to pinconf.h This allows one to include pinconf.h without having to include other headers first. Signed-off-by: Stephen Warren Signed-off-by: Linus Walleij --- include/linux/pinctrl/pinconf.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/linux/pinctrl/pinconf.h b/include/linux/pinctrl/pinconf.h index d5b72e6e261d6..8c2c88ed46b14 100644 --- a/include/linux/pinctrl/pinconf.h +++ b/include/linux/pinctrl/pinconf.h @@ -15,6 +15,7 @@ #ifdef CONFIG_PINCONF struct pinctrl_dev; +struct seq_file; /** * struct pinconf_ops - pin config operations, to be implemented by From 43699dea1ea21a0d5786317a794cb2ba27a6f4fe Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Thu, 15 Dec 2011 16:57:17 -0700 Subject: [PATCH 27/31] pinctrl: pass name instead of device to pin_config_* Obtaining a "struct pinctrl_dev *" is difficult for code not directly related to the pinctrl subsystem. However, the device name of the pinctrl device is fairly well known. So, modify pin_config_*() to take the device name instead of the "struct pinctrl_dev *". Signed-off-by: Stephen Warren [rebased on top of refactoring code] Signed-off-by: Linus Walleij --- Documentation/pinctrl.txt | 2 +- drivers/pinctrl/pinconf.c | 41 +++++++++++++++++++++++++-------- include/linux/pinctrl/pinconf.h | 16 ++++++------- 3 files changed, 41 insertions(+), 18 deletions(-) diff --git a/Documentation/pinctrl.txt b/Documentation/pinctrl.txt index f080643682913..44321d3227e82 100644 --- a/Documentation/pinctrl.txt +++ b/Documentation/pinctrl.txt @@ -208,7 +208,7 @@ unconnected. For example, a platform may do this: -ret = pin_config_set(dev, "FOO_GPIO_PIN", PLATFORM_X_PULL_UP); +ret = pin_config_set("foo-dev", "FOO_GPIO_PIN", PLATFORM_X_PULL_UP); To pull up a pin to VDD. The pin configuration driver implements callbacks for changing pin configuration in the pin controller ops like this: diff --git a/drivers/pinctrl/pinconf.c b/drivers/pinctrl/pinconf.c index 124762b570244..57dbb4b478db3 100644 --- a/drivers/pinctrl/pinconf.c +++ b/drivers/pinctrl/pinconf.c @@ -39,17 +39,22 @@ int pin_config_get_for_pin(struct pinctrl_dev *pctldev, unsigned pin, /** * pin_config_get() - get the configuration of a single pin parameter - * @pctldev: pin controller device for this pin + * @dev_name: name of the pin controller device for this pin * @name: name of the pin to get the config for * @config: the config pointed to by this argument will be filled in with the * current pin state, it can be used directly by drivers as a numeral, or * it can be dereferenced to any struct. */ -int pin_config_get(struct pinctrl_dev *pctldev, const char *name, +int pin_config_get(const char *dev_name, const char *name, unsigned long *config) { + struct pinctrl_dev *pctldev; int pin; + pctldev = get_pinctrl_dev_from_dev(NULL, dev_name); + if (!pctldev) + return -EINVAL; + pin = pin_get_from_name(pctldev, name); if (pin < 0) return pin; @@ -82,17 +87,22 @@ int pin_config_set_for_pin(struct pinctrl_dev *pctldev, unsigned pin, /** * pin_config_set() - set the configuration of a single pin parameter - * @pctldev: pin controller device for this pin + * @dev_name: name of pin controller device for this pin * @name: name of the pin to set the config for * @config: the config in this argument will contain the desired pin state, it * can be used directly by drivers as a numeral, or it can be dereferenced * to any struct. */ -int pin_config_set(struct pinctrl_dev *pctldev, const char *name, +int pin_config_set(const char *dev_name, const char *name, unsigned long config) { + struct pinctrl_dev *pctldev; int pin; + pctldev = get_pinctrl_dev_from_dev(NULL, dev_name); + if (!pctldev) + return -EINVAL; + pin = pin_get_from_name(pctldev, name); if (pin < 0) return pin; @@ -101,12 +111,18 @@ int pin_config_set(struct pinctrl_dev *pctldev, const char *name, } EXPORT_SYMBOL(pin_config_set); -int pin_config_group_get(struct pinctrl_dev *pctldev, const char *pin_group, +int pin_config_group_get(const char *dev_name, const char *pin_group, unsigned long *config) { - const struct pinconf_ops *ops = pctldev->desc->confops; + struct pinctrl_dev *pctldev; + const struct pinconf_ops *ops; int selector; + pctldev = get_pinctrl_dev_from_dev(NULL, dev_name); + if (!pctldev) + return -EINVAL; + ops = pctldev->desc->confops; + if (!ops || !ops->pin_config_group_get) { dev_err(pctldev->dev, "cannot get configuration for pin " "group, missing group config get function in " @@ -123,17 +139,24 @@ int pin_config_group_get(struct pinctrl_dev *pctldev, const char *pin_group, EXPORT_SYMBOL(pin_config_group_get); -int pin_config_group_set(struct pinctrl_dev *pctldev, const char *pin_group, +int pin_config_group_set(const char *dev_name, const char *pin_group, unsigned long config) { - const struct pinctrl_ops *pctlops = pctldev->desc->pctlops; - const struct pinconf_ops *ops = pctldev->desc->confops; + struct pinctrl_dev *pctldev; + const struct pinconf_ops *ops; + const struct pinctrl_ops *pctlops; int selector; const unsigned *pins; unsigned num_pins; int ret; int i; + pctldev = get_pinctrl_dev_from_dev(NULL, dev_name); + if (!pctldev) + return -EINVAL; + ops = pctldev->desc->confops; + pctlops = pctldev->desc->pctlops; + if (!ops || (!ops->pin_config_group_set && !ops->pin_config_set)) { dev_err(pctldev->dev, "cannot configure pin group, missing " "config function in driver\n"); diff --git a/include/linux/pinctrl/pinconf.h b/include/linux/pinctrl/pinconf.h index 8c2c88ed46b14..477922cf043ad 100644 --- a/include/linux/pinctrl/pinconf.h +++ b/include/linux/pinctrl/pinconf.h @@ -53,39 +53,39 @@ struct pinconf_ops { unsigned selector); }; -extern int pin_config_get(struct pinctrl_dev *pctldev, const char *name, +extern int pin_config_get(const char *dev_name, const char *name, unsigned long *config); -extern int pin_config_set(struct pinctrl_dev *pctldev, const char *name, +extern int pin_config_set(const char *dev_name, const char *name, unsigned long config); -extern int pin_config_group_get(struct pinctrl_dev *pctldev, +extern int pin_config_group_get(const char *dev_name, const char *pin_group, unsigned long *config); -extern int pin_config_group_set(struct pinctrl_dev *pctldev, +extern int pin_config_group_set(const char *dev_name, const char *pin_group, unsigned long config); #else -static inline int pin_config_get(struct pinctrl_dev *pctldev, const char *name, +static inline int pin_config_get(const char *dev_name, const char *name, unsigned long *config) { return 0; } -static inline int pin_config_set(struct pinctrl_dev *pctldev, const char *name, +static inline int pin_config_set(const char *dev_name, const char *name, unsigned long config) { return 0; } -static inline int pin_config_group_get(struct pinctrl_dev *pctldev, +static inline int pin_config_group_get(const char *dev_name, const char *pin_group, unsigned long *config) { return 0; } -static inline int pin_config_group_set(struct pinctrl_dev *pctldev, +static inline int pin_config_group_set(const char *dev_name, const char *pin_group, unsigned long config) { From 3bece55aa5356af0171aaa64fd9c4f7601c47f1c Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Sun, 18 Dec 2011 23:44:26 +0100 Subject: [PATCH 28/31] pinctrl: rename U300 and SIRF pin controllers For stringent order, rename the pinmux-* pin controllers to pinctrl-* and also rename the Kconfig symbols and in-kernel users. Cc: Rongjun Ying Cc: Jean-Christophe PLAGNIOL-VILLARD Acked-by: Stephen Warren Signed-off-by: Linus Walleij --- arch/arm/mach-u300/Kconfig | 2 +- drivers/pinctrl/Kconfig | 8 ++++---- drivers/pinctrl/Makefile | 4 ++-- drivers/pinctrl/{pinmux-sirf.c => pinctrl-sirf.c} | 0 drivers/pinctrl/{pinmux-u300.c => pinctrl-u300.c} | 0 5 files changed, 7 insertions(+), 7 deletions(-) rename drivers/pinctrl/{pinmux-sirf.c => pinctrl-sirf.c} (100%) rename drivers/pinctrl/{pinmux-u300.c => pinctrl-u300.c} (100%) diff --git a/arch/arm/mach-u300/Kconfig b/arch/arm/mach-u300/Kconfig index c2d5c6c083645..54d8f34fdee5d 100644 --- a/arch/arm/mach-u300/Kconfig +++ b/arch/arm/mach-u300/Kconfig @@ -7,7 +7,7 @@ comment "ST-Ericsson Mobile Platform Products" config MACH_U300 bool "U300" select PINCTRL - select PINMUX_U300 + select PINCTRL_U300 select PINCTRL_COH901 comment "ST-Ericsson U300/U330/U335/U365 Feature Selections" diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig index c63c721029894..afaf885581251 100644 --- a/drivers/pinctrl/Kconfig +++ b/drivers/pinctrl/Kconfig @@ -23,13 +23,13 @@ config DEBUG_PINCTRL help Say Y here to add some extra checks and diagnostics to PINCTRL calls. -config PINMUX_SIRF - bool "CSR SiRFprimaII pinmux driver" +config PINCTRL_SIRF + bool "CSR SiRFprimaII pin controller driver" depends on ARCH_PRIMA2 select PINMUX -config PINMUX_U300 - bool "U300 pinmux driver" +config PINCTRL_U300 + bool "U300 pin controller driver" depends on ARCH_U300 select PINMUX diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile index c046f78dd7f70..827601cc68f6c 100644 --- a/drivers/pinctrl/Makefile +++ b/drivers/pinctrl/Makefile @@ -5,6 +5,6 @@ ccflags-$(CONFIG_DEBUG_PINCTRL) += -DDEBUG obj-$(CONFIG_PINCTRL) += core.o obj-$(CONFIG_PINMUX) += pinmux.o obj-$(CONFIG_PINCONF) += pinconf.o -obj-$(CONFIG_PINMUX_SIRF) += pinmux-sirf.o -obj-$(CONFIG_PINMUX_U300) += pinmux-u300.o +obj-$(CONFIG_PINCTRL_SIRF) += pinctrl-sirf.o +obj-$(CONFIG_PINCTRL_U300) += pinctrl-u300.o obj-$(CONFIG_PINCTRL_COH901) += pinctrl-coh901.o diff --git a/drivers/pinctrl/pinmux-sirf.c b/drivers/pinctrl/pinctrl-sirf.c similarity index 100% rename from drivers/pinctrl/pinmux-sirf.c rename to drivers/pinctrl/pinctrl-sirf.c diff --git a/drivers/pinctrl/pinmux-u300.c b/drivers/pinctrl/pinctrl-u300.c similarity index 100% rename from drivers/pinctrl/pinmux-u300.c rename to drivers/pinctrl/pinctrl-u300.c From e6337c3c96a7ee5cfd5e7afed825f894d4576f58 Mon Sep 17 00:00:00 2001 From: Dong Aisheng Date: Tue, 20 Dec 2011 17:51:59 +0800 Subject: [PATCH 29/31] pinctrl: some typo fixes Minor copyedits. Signed-off-by: Dong Aisheng Signed-off-by: Linus Walleij --- Documentation/pinctrl.txt | 10 +++++----- drivers/pinctrl/pinmux.c | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Documentation/pinctrl.txt b/Documentation/pinctrl.txt index 44321d3227e82..6727b92bc2fb9 100644 --- a/Documentation/pinctrl.txt +++ b/Documentation/pinctrl.txt @@ -217,7 +217,7 @@ changing pin configuration in the pin controller ops like this: #include #include "platform_x_pindefs.h" -int foo_pin_config_get(struct pinctrl_dev *pctldev, +static int foo_pin_config_get(struct pinctrl_dev *pctldev, unsigned offset, unsigned long *config) { @@ -228,7 +228,7 @@ int foo_pin_config_get(struct pinctrl_dev *pctldev, *config = (unsigned long) conf; } -int foo_pin_config_set(struct pinctrl_dev *pctldev, +static int foo_pin_config_set(struct pinctrl_dev *pctldev, unsigned offset, unsigned long config) { @@ -241,14 +241,14 @@ int foo_pin_config_set(struct pinctrl_dev *pctldev, } } -int foo_pin_config_group_get (struct pinctrl_dev *pctldev, +static int foo_pin_config_group_get (struct pinctrl_dev *pctldev, unsigned selector, unsigned long *config) { ... } -int foo_pin_config_group_set (struct pinctrl_dev *pctldev, +static int foo_pin_config_group_set (struct pinctrl_dev *pctldev, unsigned selector, unsigned long config) { @@ -819,7 +819,7 @@ it even more compact which assumes you want to use pinctrl-foo and position 0 for mapping, for example: static struct pinmux_map __initdata pmx_mapping[] = { - PINMUX_MAP_PRIMARY("I2CMAP", "i2c0", "foo-i2c.0"), + PINMUX_MAP("I2CMAP", "pinctrl-foo", "i2c0", "foo-i2c.0"), }; diff --git a/drivers/pinctrl/pinmux.c b/drivers/pinctrl/pinmux.c index 3bcc64137ddc9..0916222dd7d2d 100644 --- a/drivers/pinctrl/pinmux.c +++ b/drivers/pinctrl/pinmux.c @@ -342,7 +342,7 @@ EXPORT_SYMBOL_GPL(pinmux_gpio_direction_output); * Only call this once during initialization of your machine, the function is * tagged as __init and won't be callable after init has completed. The map * passed into this function will be owned by the pinmux core and cannot be - * free:d. + * freed. */ int __init pinmux_register_mappings(struct pinmux_map const *maps, unsigned num_maps) From 706e8520e8450a631ca6f798f8c811faf56f0a59 Mon Sep 17 00:00:00 2001 From: Chanho Park Date: Tue, 3 Jan 2012 16:47:50 +0900 Subject: [PATCH 30/31] pinctrl: correct a offset while enumerating pins This patch modifies a offset while enumerating pins to support a partial pin space. If we use a pin number for enumerating pins, the pin space always starts with zero base. Indeed, we always check the pin is in the pin space. An extreme example, there is only two pins. One is 0. Another is 1000. We always enumerate whole offsets until 1000. For solving this problem, we use the offset of the pin array instead of the zero-based pin number. Signed-off-by: Chanho Park Signed-off-by: Kyungmin Park [Restored sparse pin space comment] Signed-off-by: Linus Walleij --- drivers/pinctrl/core.c | 14 ++++++++------ drivers/pinctrl/pinconf.c | 9 +++++---- drivers/pinctrl/pinmux.c | 9 +++++---- 3 files changed, 18 insertions(+), 14 deletions(-) diff --git a/drivers/pinctrl/core.c b/drivers/pinctrl/core.c index 9e32ea311432a..79c56d90fcc59 100644 --- a/drivers/pinctrl/core.c +++ b/drivers/pinctrl/core.c @@ -102,12 +102,13 @@ struct pin_desc *pin_desc_get(struct pinctrl_dev *pctldev, unsigned int pin) */ int pin_get_from_name(struct pinctrl_dev *pctldev, const char *name) { - unsigned pin; + unsigned i, pin; - /* The highest pin number need to be included in the loop, thus <= */ - for (pin = 0; pin <= pctldev->desc->maxpin; pin++) { + /* The pin number can be retrived from the pin controller descriptor */ + for (i = 0; i < pctldev->desc->npins; i++) { struct pin_desc *desc; + pin = pctldev->desc->pins[i].number; desc = pin_desc_get(pctldev, pin); /* Pin space may be sparse */ if (desc == NULL) @@ -350,15 +351,16 @@ static int pinctrl_pins_show(struct seq_file *s, void *what) { struct pinctrl_dev *pctldev = s->private; const struct pinctrl_ops *ops = pctldev->desc->pctlops; - unsigned pin; + unsigned i, pin; seq_printf(s, "registered pins: %d\n", pctldev->desc->npins); seq_printf(s, "max pin number: %d\n", pctldev->desc->maxpin); - /* The highest pin number need to be included in the loop, thus <= */ - for (pin = 0; pin <= pctldev->desc->maxpin; pin++) { + /* The pin number can be retrived from the pin controller descriptor */ + for (i = 0; i < pctldev->desc->npins; i++) { struct pin_desc *desc; + pin = pctldev->desc->pins[i].number; desc = pin_desc_get(pctldev, pin); /* Pin space may be sparse */ if (desc == NULL) diff --git a/drivers/pinctrl/pinconf.c b/drivers/pinctrl/pinconf.c index 57dbb4b478db3..1259872b0a1d6 100644 --- a/drivers/pinctrl/pinconf.c +++ b/drivers/pinctrl/pinconf.c @@ -230,17 +230,18 @@ static void pinconf_dump_pin(struct pinctrl_dev *pctldev, static int pinconf_pins_show(struct seq_file *s, void *what) { struct pinctrl_dev *pctldev = s->private; - unsigned pin; + unsigned i, pin; seq_puts(s, "Pin config settings per pin\n"); seq_puts(s, "Format: pin (name): pinmux setting array\n"); - /* The highest pin number need to be included in the loop, thus <= */ - for (pin = 0; pin <= pctldev->desc->maxpin; pin++) { + /* The pin number can be retrived from the pin controller descriptor */ + for (i = 0; pin < pctldev->desc->npins; i++) { struct pin_desc *desc; + pin = pctldev->desc->pins[i].number; desc = pin_desc_get(pctldev, pin); - /* Pin space may be sparse */ + /* Skip if we cannot search the pin */ if (desc == NULL) continue; diff --git a/drivers/pinctrl/pinmux.c b/drivers/pinctrl/pinmux.c index 0916222dd7d2d..a76a348321bb4 100644 --- a/drivers/pinctrl/pinmux.c +++ b/drivers/pinctrl/pinmux.c @@ -1063,18 +1063,19 @@ static int pinmux_functions_show(struct seq_file *s, void *what) static int pinmux_pins_show(struct seq_file *s, void *what) { struct pinctrl_dev *pctldev = s->private; - unsigned pin; + unsigned i, pin; seq_puts(s, "Pinmux settings per pin\n"); seq_puts(s, "Format: pin (name): pinmuxfunction\n"); - /* The highest pin number need to be included in the loop, thus <= */ - for (pin = 0; pin <= pctldev->desc->maxpin; pin++) { + /* The pin number can be retrived from the pin controller descriptor */ + for (i = 0; i < pctldev->desc->npins; i++) { struct pin_desc *desc; + pin = pctldev->desc->pins[i].number; desc = pin_desc_get(pctldev, pin); - /* Pin space may be sparse */ + /* Skip if we cannot search the pin */ if (desc == NULL) continue; From 0d2006bbf09e817f125ba1e42b2549bc2c5d7351 Mon Sep 17 00:00:00 2001 From: Chanho Park Date: Tue, 3 Jan 2012 16:47:51 +0900 Subject: [PATCH 31/31] pinctrl: remove unnecessary max pin number This patch removes maxpin member in the pin control descriptor because we don't need this value as we enumerate a pin space using offset. Signed-off-by: Chanho Park Signed-off-by: Kyungmin Park Signed-off-by: Linus Walleij --- drivers/pinctrl/core.c | 1 - drivers/pinctrl/pinctrl-sirf.c | 1 - drivers/pinctrl/pinctrl-u300.c | 1 - include/linux/pinctrl/pinctrl.h | 5 ----- 4 files changed, 8 deletions(-) diff --git a/drivers/pinctrl/core.c b/drivers/pinctrl/core.c index 79c56d90fcc59..569bdb3ef1046 100644 --- a/drivers/pinctrl/core.c +++ b/drivers/pinctrl/core.c @@ -354,7 +354,6 @@ static int pinctrl_pins_show(struct seq_file *s, void *what) unsigned i, pin; seq_printf(s, "registered pins: %d\n", pctldev->desc->npins); - seq_printf(s, "max pin number: %d\n", pctldev->desc->maxpin); /* The pin number can be retrived from the pin controller descriptor */ for (i = 0; i < pctldev->desc->npins; i++) { diff --git a/drivers/pinctrl/pinctrl-sirf.c b/drivers/pinctrl/pinctrl-sirf.c index 99e688e07ea0b..6b3534cc051aa 100644 --- a/drivers/pinctrl/pinctrl-sirf.c +++ b/drivers/pinctrl/pinctrl-sirf.c @@ -1086,7 +1086,6 @@ static struct pinctrl_desc sirfsoc_pinmux_desc = { .name = DRIVER_NAME, .pins = sirfsoc_pads, .npins = ARRAY_SIZE(sirfsoc_pads), - .maxpin = SIRFSOC_NUM_PADS - 1, .pctlops = &sirfsoc_pctrl_ops, .pmxops = &sirfsoc_pinmux_ops, .owner = THIS_MODULE, diff --git a/drivers/pinctrl/pinctrl-u300.c b/drivers/pinctrl/pinctrl-u300.c index 7e89b367a7e59..c8d02f1c2b5e8 100644 --- a/drivers/pinctrl/pinctrl-u300.c +++ b/drivers/pinctrl/pinctrl-u300.c @@ -1048,7 +1048,6 @@ static struct pinctrl_desc u300_pmx_desc = { .name = DRIVER_NAME, .pins = u300_pads, .npins = ARRAY_SIZE(u300_pads), - .maxpin = U300_NUM_PADS-1, .pctlops = &u300_pctrl_ops, .pmxops = &u300_pmx_ops, .owner = THIS_MODULE, diff --git a/include/linux/pinctrl/pinctrl.h b/include/linux/pinctrl/pinctrl.h index 9809a94f151b9..8bd22ee7aa098 100644 --- a/include/linux/pinctrl/pinctrl.h +++ b/include/linux/pinctrl/pinctrl.h @@ -92,10 +92,6 @@ struct pinctrl_ops { * this pin controller * @npins: number of descriptors in the array, usually just ARRAY_SIZE() * of the pins field above - * @maxpin: since pin spaces may be sparse, there can he "holes" in the - * pin range, this attribute gives the maximum pin number in the - * total range. This should not be lower than npins for example, - * but may be equal to npins if you have no holes in the pin range. * @pctlops: pin control operation vtable, to support global concepts like * grouping of pins, this is optional. * @pmxops: pinmux operations vtable, if you support pinmuxing in your driver @@ -107,7 +103,6 @@ struct pinctrl_desc { const char *name; struct pinctrl_pin_desc const *pins; unsigned int npins; - unsigned int maxpin; struct pinctrl_ops *pctlops; struct pinmux_ops *pmxops; struct pinconf_ops *confops;