From 3712a3c488987849613a4ad74129e67e40b12b38 Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Fri, 21 Oct 2011 12:25:53 -0600 Subject: 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 --- include/linux/pinctrl/pinmux.h | 3 +++ 1 file changed, 3 insertions(+) (limited to 'include') diff --git a/include/linux/pinctrl/pinmux.h b/include/linux/pinctrl/pinmux.h index 3c430e797efc..350e32a98c6a 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 */ -- cgit v1.2.3 From 3c739ad0df5eb41cd7adad879eda6aa09879eb76 Mon Sep 17 00:00:00 2001 From: Chanho Park Date: Fri, 11 Nov 2011 18:47:58 +0900 Subject: 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(-) (limited to 'include') diff --git a/Documentation/pinctrl.txt b/Documentation/pinctrl.txt index 0a8b2250062a..43ba411d1571 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 d848d9764378..99e688e07ea0 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 145a84dc16e6..bcf61bee7763 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 ee3aba78c3dd..92aa13ee2208 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 04c011038f32..f17fac4b51f1 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 350e32a98c6a..bb7a9792f1ea 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 */ -- cgit v1.2.3 From 542e704f3ffee1dc4539c9e8191e4dc215220f5e Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Mon, 14 Nov 2011 10:06:22 +0100 Subject: 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(-) (limited to 'include') diff --git a/Documentation/pinctrl.txt b/Documentation/pinctrl.txt index 43ba411d1571..3846264c5973 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 92aa13ee2208..f3e4f031fe1c 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 bb7a9792f1ea..937b3e2fa36f 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; -- cgit v1.2.3 From 97607d157c133ab18dfcd77fa836e37fa950a44a Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Tue, 29 Nov 2011 12:52:39 +0100 Subject: 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(-) (limited to 'include') diff --git a/Documentation/pinctrl.txt b/Documentation/pinctrl.txt index 3846264c5973..c8fd136eac83 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 ac0791e924bc..839fa15c4eb6 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 f3e4f031fe1c..f6e7d583998c 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 88863531d862..f5372319d999 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; }; /* -- cgit v1.2.3 From ae6b4d8588f4fc95520b0e62c4b1f474c82191a9 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Wed, 19 Oct 2011 18:14:33 +0200 Subject: 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 (limited to 'include') diff --git a/Documentation/pinctrl.txt b/Documentation/pinctrl.txt index c8fd136eac83..6d23fa84ee47 100644 --- a/Documentation/pinctrl.txt +++ b/Documentation/pinctrl.txt @@ -7,12 +7,9 @@ This subsystem deals with: - 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 e963da41e948..c63c72102989 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 5f3e4d65465a..c046f78dd7f7 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 4955a68d618f..034b1ad38b32 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 74dee439dcf0..3f5b911acf18 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 000000000000..9195eefe258a --- /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 000000000000..e7dc6165032a --- /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 000000000000..d5b72e6e261d --- /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 f17fac4b51f1..9809a94f151b 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; -- cgit v1.2.3 From 1ddb6ff03c0cdec58c6cfdbada95acddcce4a7b7 Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Fri, 9 Dec 2011 16:59:03 -0700 Subject: 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(+) (limited to 'include') diff --git a/include/linux/pinctrl/machine.h b/include/linux/pinctrl/machine.h index f5372319d999..0ca32eb63b67 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 -- cgit v1.2.3 From 51cd24ee625c348654114032499914d0311e5832 Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Fri, 9 Dec 2011 16:59:05 -0700 Subject: 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(-) (limited to 'include') diff --git a/Documentation/pinctrl.txt b/Documentation/pinctrl.txt index 6d23fa84ee47..f08064368291 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 034b1ad38b32..160fb5aae591 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 3f5b911acf18..5375582566a5 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 9195eefe258a..124762b57024 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 a11681b4bd91..3bcc64137ddc 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 @@ out_free_pin: } 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 0ca32eb63b67..ad430e05a7ba 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, -- cgit v1.2.3 From 23750196ef472e9249958d5165b0bb292518c710 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Wed, 14 Dec 2011 09:30:08 +0100 Subject: 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(+) (limited to 'include') diff --git a/include/linux/pinctrl/machine.h b/include/linux/pinctrl/machine.h index ad430e05a7ba..d0aecb7f6fb9 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, -- cgit v1.2.3 From 63fd5984a9b2214cba7dd7dd7b5a75cf40dde39f Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Thu, 15 Dec 2011 16:57:16 -0700 Subject: 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(+) (limited to 'include') diff --git a/include/linux/pinctrl/pinconf.h b/include/linux/pinctrl/pinconf.h index d5b72e6e261d..8c2c88ed46b1 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 -- cgit v1.2.3 From 43699dea1ea21a0d5786317a794cb2ba27a6f4fe Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Thu, 15 Dec 2011 16:57:17 -0700 Subject: 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(-) (limited to 'include') diff --git a/Documentation/pinctrl.txt b/Documentation/pinctrl.txt index f08064368291..44321d3227e8 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 124762b57024..57dbb4b478db 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 8c2c88ed46b1..477922cf043a 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) { -- cgit v1.2.3 From 0d2006bbf09e817f125ba1e42b2549bc2c5d7351 Mon Sep 17 00:00:00 2001 From: Chanho Park Date: Tue, 3 Jan 2012 16:47:51 +0900 Subject: 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(-) (limited to 'include') diff --git a/drivers/pinctrl/core.c b/drivers/pinctrl/core.c index 79c56d90fcc5..569bdb3ef104 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 99e688e07ea0..6b3534cc051a 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 7e89b367a7e5..c8d02f1c2b5e 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 9809a94f151b..8bd22ee7aa09 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; -- cgit v1.2.3