diff --git a/Documentation/pinctrl.txt b/Documentation/pinctrl.txt index aa3350dd702..e454a6acdca 100644 --- a/Documentation/pinctrl.txt +++ b/Documentation/pinctrl.txt @@ -967,6 +967,18 @@ pinmux core. Pinmux requests from drivers ============================ +When a device driver is about to probe the device core will automatically +attempt to issue pinctrl_get_select_default() on these devices. +This way driver writers do not need to add any of the boilerplate code +of the type found below. However when doing fine-grained state selection +and not using the "default" state, you may have to do some device driver +handling of the pinctrl handles and states. + +So if you just want to put the pins for a certain device into the default +state and be done with it, there is nothing you need to do besides +providing the proper mapping table. The device core will take care of +the rest. + Generally it is discouraged to let individual drivers get and enable pin control. So if possible, handle the pin control in platform code or some other place where you have access to all the affected struct device * pointers. In @@ -1062,6 +1074,51 @@ registered. Thus make sure that the error path in your driver gracefully cleans up and is ready to retry the probing later in the startup process. +Drivers needing both pin control and GPIOs +========================================== + +Again, it is discouraged to let drivers lookup and select pin control states +themselves, but again sometimes this is unavoidable. + +So say that your driver is fetching its resources like this: + +#include +#include + +struct pinctrl *pinctrl; +int gpio; + +pinctrl = devm_pinctrl_get_select_default(&dev); +gpio = devm_gpio_request(&dev, 14, "foo"); + +Here we first request a certain pin state and then request GPIO 14 to be +used. If you're using the subsystems orthogonally like this, you should +nominally always get your pinctrl handle and select the desired pinctrl +state BEFORE requesting the GPIO. This is a semantic convention to avoid +situations that can be electrically unpleasant, you will certainly want to +mux in and bias pins in a certain way before the GPIO subsystems starts to +deal with them. + +The above can be hidden: using the device core, the pinctrl core may be +setting up the config and muxing for the pins right before the device is +probing, nevertheless orthogonal to the GPIO subsystem. + +But there are also situations where it makes sense for the GPIO subsystem +to communicate directly with with the pinctrl subsystem, using the latter +as a back-end. This is when the GPIO driver may call out to the functions +described in the section "Pin control interaction with the GPIO subsystem" +above. This only involves per-pin multiplexing, and will be completely +hidden behind the gpio_*() function namespace. In this case, the driver +need not interact with the pin control subsystem at all. + +If a pin control driver and a GPIO driver is dealing with the same pins +and the use cases involve multiplexing, you MUST implement the pin controller +as a back-end for the GPIO driver like this, unless your hardware design +is such that the GPIO controller can override the pin controller's +multiplexing state through hardware without the need to interact with the +pin control system. + + System pin control hogging ========================== diff --git a/drivers/base/Makefile b/drivers/base/Makefile index cb4528fdc1f..7a0d23bdbca 100644 --- a/drivers/base/Makefile +++ b/drivers/base/Makefile @@ -22,6 +22,7 @@ endif obj-$(CONFIG_SYS_HYPERVISOR) += hypervisor.o obj-$(CONFIG_REGMAP) += regmap/ obj-$(CONFIG_SOC_BUS) += soc.o +obj-$(CONFIG_PINCTRL) += pinctrl.o obj-$(CONFIG_SYNC) += sync.o obj-$(CONFIG_SW_SYNC) += sw_sync.o diff --git a/drivers/base/dd.c b/drivers/base/dd.c index 1b1cbb571d3..b3a7d6e11e7 100644 --- a/drivers/base/dd.c +++ b/drivers/base/dd.c @@ -24,6 +24,7 @@ #include #include #include +#include #include "base.h" #include "power/power.h" @@ -257,6 +258,12 @@ static int really_probe(struct device *dev, struct device_driver *drv) WARN_ON(!list_empty(&dev->devres_head)); dev->driver = drv; + + /* If using pinctrl, bind pins now before probing */ + ret = pinctrl_bind_pins(dev); + if (ret) + goto probe_failed; + if (driver_sysfs_add(dev)) { printk(KERN_ERR "%s: driver_sysfs_add(%s) failed\n", __func__, dev_name(dev)); diff --git a/drivers/base/pinctrl.c b/drivers/base/pinctrl.c new file mode 100644 index 00000000000..67a274e8672 --- /dev/null +++ b/drivers/base/pinctrl.c @@ -0,0 +1,69 @@ +/* + * Driver core interface to the pinctrl subsystem. + * + * Copyright (C) 2012 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 + */ + +#include +#include +#include +#include + +/** + * pinctrl_bind_pins() - called by the device core before probe + * @dev: the device that is just about to probe + */ +int pinctrl_bind_pins(struct device *dev) +{ + int ret; + + dev->pins = devm_kzalloc(dev, sizeof(*(dev->pins)), GFP_KERNEL); + if (!dev->pins) + return -ENOMEM; + + dev->pins->p = devm_pinctrl_get(dev); + if (IS_ERR(dev->pins->p)) { + dev_dbg(dev, "no pinctrl handle\n"); + ret = PTR_ERR(dev->pins->p); + goto cleanup_alloc; + } + + dev->pins->default_state = pinctrl_lookup_state(dev->pins->p, + PINCTRL_STATE_DEFAULT); + if (IS_ERR(dev->pins->default_state)) { + dev_dbg(dev, "no default pinctrl state\n"); + ret = 0; + goto cleanup_get; + } + + ret = pinctrl_select_state(dev->pins->p, dev->pins->default_state); + if (ret) { + dev_dbg(dev, "failed to activate default pinctrl state\n"); + goto cleanup_get; + } + + return 0; + + /* + * If no pinctrl handle or default state was found for this device, + * let's explicitly free the pin container in the device, there is + * no point in keeping it around. + */ +cleanup_get: + devm_pinctrl_put(dev->pins->p); +cleanup_alloc: + devm_kfree(dev, dev->pins); + dev->pins = NULL; + + /* Only return deferrals */ + if (ret != -EPROBE_DEFER) + ret = 0; + + return ret; +} diff --git a/drivers/pinctrl/core.c b/drivers/pinctrl/core.c index e6373f30aee..5a2fe9aae20 100644 --- a/drivers/pinctrl/core.c +++ b/drivers/pinctrl/core.c @@ -14,6 +14,7 @@ #define pr_fmt(fmt) "pinctrl core: " fmt #include +#include #include #include #include @@ -727,6 +728,8 @@ static struct pinctrl *create_pinctrl(struct device *dev) return ERR_PTR(ret); } + kref_init(&p->users); + /* Add the pinctrl handle to the global list */ list_add_tail(&p->node, &pinctrl_list); @@ -740,9 +743,17 @@ static struct pinctrl *pinctrl_get_locked(struct device *dev) if (WARN_ON(!dev)) return ERR_PTR(-EINVAL); + /* + * See if somebody else (such as the device core) has already + * obtained a handle to the pinctrl for this device. In that case, + * return another pointer to it. + */ p = find_pinctrl(dev); - if (p != NULL) - return ERR_PTR(-EBUSY); + if (p != NULL) { + dev_dbg(dev, "obtain a copy of previously claimed pinctrl\n"); + kref_get(&p->users); + return p; + } return create_pinctrl(dev); } @@ -798,13 +809,24 @@ static void pinctrl_put_locked(struct pinctrl *p, bool inlist) } /** - * pinctrl_put() - release a previously claimed pinctrl handle + * pinctrl_release() - release the pinctrl handle + * @kref: the kref in the pinctrl being released + */ +void pinctrl_release(struct kref *kref) +{ + struct pinctrl *p = container_of(kref, struct pinctrl, users); + + pinctrl_put_locked(p, true); +} + +/** + * pinctrl_put() - decrease use count on a previously claimed pinctrl handle * @p: the pinctrl handle to release */ void pinctrl_put(struct pinctrl *p) { mutex_lock(&pinctrl_mutex); - pinctrl_put_locked(p, true); + kref_put(&p->users, pinctrl_release); mutex_unlock(&pinctrl_mutex); } EXPORT_SYMBOL_GPL(pinctrl_put); diff --git a/drivers/pinctrl/core.h b/drivers/pinctrl/core.h index 232a9f6db4a..fdd350d639f 100644 --- a/drivers/pinctrl/core.h +++ b/drivers/pinctrl/core.h @@ -9,6 +9,7 @@ * License terms: GNU General Public License (GPL) version 2 */ +#include #include #include #include @@ -58,6 +59,7 @@ struct pinctrl_dev { * @state: the current state * @dt_maps: the mapping table chunks dynamically parsed from device tree for * this device, if any + * @users: reference count */ struct pinctrl { struct list_head node; @@ -65,6 +67,7 @@ struct pinctrl { struct list_head states; struct pinctrl_state *state; struct list_head dt_maps; + struct kref users; }; /** diff --git a/include/linux/device.h b/include/linux/device.h index 810337c75ca..35862c3f9ba 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -595,6 +596,8 @@ struct device_dma_parameters { * @pm_domain: Provide callbacks that are executed during system suspend, * hibernation, system resume and during runtime PM transitions * along with subsystem-level and driver-level callbacks. + * @pins: For device pin management. + * See Documentation/pinctrl.txt for details. * @numa_node: NUMA node this device is close to. * @dma_mask: Dma mask (if dma'ble device). * @coherent_dma_mask: Like dma_mask, but for alloc_coherent mapping as not all @@ -646,6 +649,10 @@ struct device { struct dev_pm_info power; struct dev_pm_domain *pm_domain; +#ifdef CONFIG_PINCTRL + struct dev_pin_info *pins; +#endif + #ifdef CONFIG_NUMA int numa_node; /* NUMA node this device is close to */ #endif diff --git a/include/linux/pinctrl/devinfo.h b/include/linux/pinctrl/devinfo.h new file mode 100644 index 00000000000..6e5f8a985ea --- /dev/null +++ b/include/linux/pinctrl/devinfo.h @@ -0,0 +1,45 @@ +/* + * Per-device information from the pin control system. + * This is the stuff that get included into the device + * core. + * + * Copyright (C) 2012 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 PINCTRL_DEVINFO_H +#define PINCTRL_DEVINFO_H + +#ifdef CONFIG_PINCTRL + +/* The device core acts as a consumer toward pinctrl */ +#include + +/** + * struct dev_pin_info - pin state container for devices + * @p: pinctrl handle for the containing device + * @default_state: the default state for the handle, if found + */ +struct dev_pin_info { + struct pinctrl *p; + struct pinctrl_state *default_state; +}; + +extern int pinctrl_bind_pins(struct device *dev); + +#else + +/* Stubs if we're not using pinctrl */ + +static inline int pinctrl_bind_pins(struct device *dev) +{ + return 0; +} + +#endif /* CONFIG_PINCTRL */ +#endif /* PINCTRL_DEVINFO_H */